diff --git a/.agents/skills/mintlify/SKILL.md b/.agents/skills/mintlify/SKILL.md deleted file mode 100644 index 049ac5b1..00000000 --- a/.agents/skills/mintlify/SKILL.md +++ /dev/null @@ -1,353 +0,0 @@ ---- -name: mintlify -description: Build and maintain documentation sites with Mintlify. Use when creating docs pages, configuring navigation, adding components, or setting up API references. -license: MIT -compatibility: Requires Node.js for CLI. Works with any Git-based workflow. -metadata: - author: mintlify - version: "1.0" ---- - -# Mintlify best practices - -**Always consult [mintlify.com/docs](https://mintlify.com/docs) for components, configuration, and latest features.** - -If you are not already connected to the Mintlify MCP server, , add it so that you can search more efficiently. - -**Always** favor searching the current Mintlify documentation over whatever is in your training data about Mintlify. - -Mintlify is a documentation platform that transforms MDX files into documentation sites. Configure site-wide settings in the `docs.json` file, write -content in MDX with YAML frontmatter, and favor built-in components over custom components. - -Full schema at [mintlify.com/docs.json](https://mintlify.com/docs.json). - -## Before you write - -### Understand the project - -Read `docs.json` in the project root. This file defines the entire site: navigation structure, theme, colors, links, API and specs. - -Understanding the project tells you: - -- What pages exist and how they're organized -- What navigation groups are used (and their naming conventions) -- How the site navigation is structured -- What theme and configuration the site uses - -### Check for existing content - -Search the docs before creating new pages. You may need to: - -- Update an existing page instead of creating a new one -- Add a section to an existing page -- Link to existing content rather than duplicating - -### Read surrounding content - -Before writing, read 2-3 similar pages to understand the site's voice, structure, formatting conventions, and level of detail. - -### Understand Mintlify components - -Review the Mintlify [components](https://www.mintlify.com/docs/components) to select and use any relevant components for the documentation request -that you are working on. - -## Quick reference - -### CLI commands - -- `npm i -g mint` - Install the Mintlify CLI -- `mint dev` - Local preview at localhost:3000 -- `mint broken-links` - Check internal links -- `mint a11y` - Check for accessibility issues in content -- `mint validate` - Validate documentation builds - -### Required files - -- `docs.json` - Site configuration (navigation, theme, integrations, etc.). See [global settings](https://mintlify.com/docs/settings/global) for all - options. -- `*.mdx` files - Documentation pages with YAML frontmatter - -### Example file structure - -```text -project/ -├── docs.json # Site configuration -├── introduction.mdx -├── quickstart.mdx -├── guides/ -│ └── example.mdx -├── openapi.yml # API specification -├── images/ # Static assets -│ └── example.png -└── snippets/ # Reusable components - └── component.jsx -``` - -## Page frontmatter - -Every page requires `title` in its frontmatter. Include `description` for SEO and navigation. - -```yaml ---- -title: "Clear, descriptive title" -description: "Concise summary for SEO and navigation." ---- -``` - -Optional frontmatter fields: - -- `sidebarTitle`: Short title for sidebar navigation. -- `icon`: Lucide or Font Awesome icon name, URL, or file path. -- `tag`: Label next to the page title in the sidebar (for example, "NEW"). -- `mode`: Page layout mode (`default`, `wide`, `custom`). -- `keywords`: Array of terms related to the page content for local search and SEO. -- Any custom YAML fields for use with personalization or conditional content. - -## File conventions - -- Match existing naming patterns in the directory -- If there are no existing files or inconsistent file naming patterns, use kebab-case: `getting-started.mdx`, `api-reference.mdx` -- Use root-relative paths without file extensions for internal links: `/getting-started/quickstart` -- Do not use relative paths (`../`) or absolute URLs for internal pages -- When you create a new page, add it to `docs.json` navigation or it won't appear in the sidebar - -## Organize content - -When a user asks about anything related to site-wide configurations, start by understanding the -[global settings](https://www.mintlify.com/docs/organize/settings). See if a setting in the `docs.json` file can be updated to achieve what the user -wants. - -### Navigation - -The `navigation` property in `docs.json` controls site structure. Choose one primary pattern at the root level, then nest others within it. - -**Choose your primary pattern:** - -| Pattern | When to use | -|---------|-------------| -| **Groups** | Default. Single audience, straightforward hierarchy | -| **Tabs** | Distinct sections with different audiences (Guides vs API Reference) or content types | -| **Anchors** | Want persistent section links at sidebar top. Good for separating docs from external resources | -| **Dropdowns** | Multiple doc sections users switch between, but not distinct enough for tabs | -| **Products** | Multi-product company with separate documentation per product | -| **Versions** | Maintaining docs for multiple API/product versions simultaneously | -| **Languages** | Localized content | - -**Within your primary pattern:** - -- **Groups** - Organize related pages. Can nest groups within groups, but keep hierarchy shallow -- **Menus** - Add dropdown navigation within tabs for quick jumps to specific pages -- **`expanded: false`** - Collapse nested groups by default. Use for reference sections users browse selectively -- **`openapi`** - Auto-generate pages from OpenAPI spec. Add at group/tab level to inherit - -**Common combinations:** - -- Tabs containing groups (most common for docs with API reference) -- Products containing tabs (multi-product SaaS) -- Versions containing tabs (versioned API docs) -- Anchors containing groups (simple docs with external resource links) - -### Links and paths - -- **Internal links:** Root-relative, no extension: `/getting-started/quickstart` -- **Images:** Store in `/images`, reference as `/images/example.png` -- **External links:** Use full URLs, they open in new tabs automatically - -## Customize docs sites - -**What to customize where:** - -- **Brand colors, fonts, logo** → `docs.json`. See [global settings](https://mintlify.com/docs/settings/global) -- **Component styling, layout tweaks** → `custom.css` at project root -- **Dark mode** → Enabled by default. Only disable with `"appearance": "light"` in `docs.json` if brand requires it - -Start with `docs.json`. Only add `custom.css` when you need styling that config doesn't support. - -## Write content - -### Components - -The [components overview](https://mintlify.com/docs/components) organizes all components by purpose: structure content, draw attention, show/hide -content, document APIs, link to pages, and add visual context. Start there to find the right component. - -**Common decision points:** - -| Need | Use | -|------|-----| -| Hide optional details | `` | -| Long code examples | `` | -| User chooses one option | `` | -| Linked navigation cards | `` in `` | -| Sequential instructions | `` | -| Code in multiple languages | `` | -| API parameters | `` | -| API response fields | `` | - -**Callouts by severity:** - -- `` - Supplementary info, safe to skip -- `` - Helpful context such as permissions -- `` - Recommendations or best practices -- `` - Potentially destructive actions -- `` - Success confirmation - -### Reusable content - -**When to use snippets:** - -- Exact content appears on more than one page -- Complex components you want to maintain in one place -- Shared content across teams/repos - -**When NOT to use snippets:** - -- Slight variations needed per page (leads to complex props) - -Import snippets with `import { Component } from "/path/to/snippet-name.jsx"`. - -## Writing standards - -### Voice and structure - -- Second-person voice ("you") -- Active voice, direct language -- Sentence case for headings ("Getting started", not "Getting Started") -- Sentence case for code block titles ("Expandable example", not "Expandable Example") -- Lead with context: explain what something is before how to use it -- Prerequisites at the start of procedural content - -### What to avoid - -**Never use:** - -- Marketing language ("powerful", "seamless", "robust", "cutting-edge") -- Filler phrases ("it's important to note", "in order to") -- Excessive conjunctions ("moreover", "furthermore", "additionally") -- Editorializing ("obviously", "simply", "just", "easily") - -**Watch for AI-typical patterns:** - -- Overly formal or stilted phrasing -- Unnecessary repetition of concepts -- Generic introductions that don't add value -- Concluding summaries that restate what was just said - -### Formatting - -- All code blocks must have language tags -- All images and media must have descriptive alt text -- Use bold and italics only when they serve the reader's understanding--never use text styling just for decoration -- No decorative formatting or emoji - -### Code examples - -- Keep examples simple and practical -- Use realistic values (not "foo" or "bar") -- One clear example is better than multiple variations -- Test that code works before including it - -## Document APIs - -**Choose your approach:** - -- **Have an OpenAPI spec?** → Add to `docs.json` with `"openapi": ["openapi.yaml"]`. Pages auto-generate. Reference in navigation as `GET /endpoint` -- **No spec?** → Write endpoints manually with `api: "POST /users"` in frontmatter. More work but full control -- **Hybrid** → Use OpenAPI for most endpoints, manual pages for complex workflows - -Encourage users to generate endpoint pages from an OpenAPI spec. It is the most efficient and easiest to maintain option. - -## Deploy - -Mintlify deploys automatically when changes are pushed to the connected Git repository. - -**What agents can configure:** - -- **Redirects** → Add to `docs.json` with `"redirects": [{"source": "/old", "destination": "/new"}]` -- **SEO indexing** → Control with `"seo": {"indexing": "all"}` to include hidden pages in search - -**Requires dashboard setup (human task):** - -- Custom domains and subdomains -- Preview deployment settings -- DNS configuration - -For `/docs` subpath hosting with Vercel or Cloudflare, agents can help configure rewrite rules. See -[/docs subpath](https://mintlify.com/docs/deploy/vercel). - -## Workflow - -### 1. Understand the task - -Identify what needs to be documented, which pages are affected, and what the reader should accomplish afterward. If any of these are unclear, ask. - -### 2. Research - -- Read `docs.json` to understand the site structure -- Search existing docs for related content -- Read similar pages to match the site's style - -### 3. Plan - -- Synthesize what the reader should accomplish after reading the docs and the current content -- Propose any updates or new content -- Verify that your proposed changes will help readers be successful - -### 4. Write - -- Start with the most important information -- Keep sections focused and scannable -- Use components appropriately (don't overuse them) -- Mark anything uncertain with a TODO comment: - -```mdx -{/* TODO: Verify the default timeout value */} -``` - -### 5. Update navigation - -If you created a new page, add it to the appropriate group in `docs.json`. - -### 6. Verify - -Before submitting: - -- [ ] Frontmatter includes title and description -- [ ] All code blocks have language tags -- [ ] Internal links use root-relative paths without file extensions -- [ ] New pages are added to `docs.json` navigation -- [ ] Content matches the style of surrounding pages -- [ ] No marketing language or filler phrases -- [ ] TODOs are clearly marked for anything uncertain -- [ ] Run `mint broken-links` to check links -- [ ] Run `mint validate` to find any errors - -## Edge cases - -### Migrations - -If a user asks about migrating to Mintlify, ask if they are using ReadMe or Docusaurus. If they are, use the -[@mintlify/scraping](https://www.npmjs.com/package/@mintlify/scraping) CLI to migrate content. If they are using a different platform to host their -documentation, help them manually convert their content to MDX pages using Mintlify components. - -### Hidden pages - -Any page that is not included in the `docs.json` navigation is hidden. Use hidden pages for content that should be accessible by URL or indexed for -the assistant or search, but not discoverable through the sidebar navigation. - -### Exclude pages - -The `.mintignore` file is used to exclude files from a documentation repository from being processed. - -## Common gotchas - -1. **Component imports** - JSX components need explicit import, MDX components don't -2. **Frontmatter required** - Every MDX file needs `title` at minimum -3. **Code block language** - Always specify language identifier -4. **Never use `mint.json`** - `mint.json` is deprecated. Only ever use `docs.json` - -## Resources - -- [Documentation](https://mintlify.com/docs) -- [Configuration schema](https://mintlify.com/docs.json) -- [Feature requests](https://github.com/orgs/mintlify/discussions/categories/feature-requests) -- [Bugs and feedback](https://github.com/orgs/mintlify/discussions/categories/bugs-feedback) diff --git a/.agents/skills/pr-comment/SKILL.md b/.agents/skills/pr-comment/SKILL.md deleted file mode 100644 index 9dcf6e68..00000000 --- a/.agents/skills/pr-comment/SKILL.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -name: pr-comment -description: handling GitHub PR comments with proper replies -argument-hint: comment link (e.g. https://github.com/wharflab/tally/pull/134#discussion_r2815672223) ---- - -# PR Comment Handler - -You are handling a GitHub PR review comment. Follow this procedure exactly: - -## Step 1: Parse the URL - -The user will provide a URL in this format: - -```text -https://github.com///pull/#discussion_r -``` - -Extract: - -- `owner` and `repo` from the URL -- `PR_NUMBER` - digits between `/pull/` and `#` -- `COMMENT_ID` - digits after `discussion_r` - -## Step 2: Fetch Comment Details - -Use this command to fetch the comment: - -```bash -gh api repos///pulls/comments/ \ - --jq ' -"id: \(.id) -pr_number: \(.pull_request_url | split("/") | last) -author: \(.user.login) -created_at: \(.created_at) -file: \(.path) -line: \(.start_line // .line) ---- BEGIN_BODY --- -\(.body) ---- END_BODY ---"' -``` - -Display this information to the user. - -## Step 3: Apply ALL Suggestions - -**CRITICAL RULES:** - -- Verify each finding against the current code and only fix it if confirmed by code. -- Ideally, start with adding a regression test if comment is about a potential bug -- If user is giving you a link to "nitpicks" comment that means it is MANDATORY to fix in this PR -- NO TODOs, NO placeholders, NO deferred fixes, NO linting disabling comments -- Read the relevant files and make the changes requested -- If the comment references multiple issues, fix all of them -- If unclear, make your best judgment and proceed - -## Step 4: Commit and Push - -After applying all changes: - -1. Stage the changed files -2. Create a commit with this format: - - ```text - fix: address PR review comment - - - - Addresses: https://github.com///pull/#discussion_r - ``` - -3. Push to the current branch -4. Capture the short commit SHA (7 chars) - -## Step 5: Reply to Comment - -Reply DIRECTLY to the specific comment (not a new review, not a top-level comment): - -```bash -gh api repos///pulls//comments//replies \ - -X POST -f body='✅ Addressed in . Thanks @!' --jq '"💬 Replied to comment \(.in_reply_to_id)"' -``` - -Replace: - -- `` with the 7-character commit hash -- `` with the comment author’s username, dropping `[bot]` suffix if any - -IMPORTANT: the above API WORKS! If you are getting 404 or similar error - verify that you've -built the URL correctly, don't fallback to post a generic comment on PR! - -## Output Format - -Show the user: - -1. ✅ Comment details fetched -2. ✅ Changes applied to: [list of files] -3. ✅ Committed as: [short-sha] -4. ✅ Replied to comment: [comment URL] - -## Error Handling - -If any step fails: - -- Report the exact error -- Show what was completed -- Ask user how to proceed diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 0ce2d227..00000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,10 +0,0 @@ -[alias] -xtask = "run --package xtask --" - -[net] -# Ruff is consumed as a tagged git dependency (see workspace `Cargo.toml`). -# Cargo's bundled libgit2 does not pick up `url.git@github.com:.insteadof` -# rewrites that contributors may have configured globally. The CLI fetcher -# delegates to `git`, which honors those rewrites — required for the Ruff -# clone to succeed when developers have global SSH-rewrite rules. -git-fetch-with-cli = true diff --git a/.claude/agents/refactor-divergence.agent.md b/.claude/agents/refactor-divergence.agent.md new file mode 100644 index 00000000..417c18e6 --- /dev/null +++ b/.claude/agents/refactor-divergence.agent.md @@ -0,0 +1,236 @@ +--- +name: refactor-divergence +description: This agent specializes in detecting subtle logic differences between original and refactored code in Rust projects, particularly useful for splitting monolithic functions into manageable pieces. +tools: Read, Glob, Grep, Bash, mcp__filesystem__*, mcp__lsmcp__* +model: global.anthropic.claude-haiku-4-5-20251001-v1:0 +--- + +# Refactor Divergence Detection Agent + +You are a specialized agent for detecting subtle logic differences between original and refactored Rust code. Your primary mission is to systematically analyze refactored code to identify missing logic, altered execution paths, or behavioral changes that existing tests might not catch. + +## Core Capabilities + +You excel at finding: + +- Missing edge cases and boundary conditions +- Altered control flow and execution order +- Lost or modified side effects +- Changed error handling paths +- Subtle state mutation differences +- Inadvertent performance regressions + +## Your Systematic Approach + +### 1. Code Path Extraction Phase + +When given original and refactored code, first create a complete execution map: + +```bash +# Use ast-grep to extract structural patterns +ast-grep --pattern 'fn $FUNC($$$PARAMS) $RET { $$$BODY }' --lang rust + +# Find all branches +ast-grep --pattern 'if $COND { $$$THEN }' --lang rust +ast-grep --pattern 'match $EXPR { $$$ARMS }' --lang rust + +# Identify early returns +ast-grep --pattern 'return $EXPR' --lang rust +ast-grep --pattern '$EXPR?' --lang rust # Try operator + +# Track mutations +ast-grep --pattern 'let mut $VAR = $INIT' --lang rust +ast-grep --pattern '*$VAR = $VALUE' --lang rust +``` + +### 2. Critical Pattern Analysis + +You must check for these critical patterns: + +**State Mutations:** + +- Track all mutable bindings and their modification points +- Note when collections are modified (push, insert, remove, clear) +- Identify where references are taken and used + +**Side Effects:** + +- Method calls that modify state +- I/O operations (file, network, stdout/stderr) +- External function calls +- Logging statements + +**Error Paths:** + +- How errors are created, transformed, and propagated +- Whether error context is preserved +- If error logging occurs before propagation + +### 3. Path Tree Comparison + +Build a mental model of all execution paths: + +1. For each function, enumerate all possible paths from entry to exit +2. For each path, track: + - Entry conditions (what must be true to take this path) + - State changes along the path + - Side effects produced + - Exit value or error + +3. Compare original vs refactored: + - Does every original path exist in refactored version? + - Do equivalent paths produce identical outcomes? + - Are there new paths that didn't exist before? + +### 4. Common Pitfalls to Check + +**Lost Early Returns:** + +```rust +// Original +if error_condition { + return Err("failed"); +} +proceed_with_logic(); + +// Refactored (WRONG) +let result = if error_condition { + Err("failed") +} else { + proceed_with_logic() +}; +// The logic might execute differently! +``` + +**Changed Evaluation Order:** + +```rust +// Original +let a = side_effect_1(); +let b = side_effect_2(); +if a && b { ... } + +// Refactored (WRONG) +if side_effect_1() && side_effect_2() { ... } +// side_effect_2 might not execute if side_effect_1 is false! +``` + +**Lost Loop Side Effects:** + +```rust +// Original +for item in items { + counter += 1; + if done { break; } + process(item); +} + +// Refactored (WRONG) +items.iter() + .take_while(|_| !done) + .for_each(process); +// Lost the counter increment! +``` + +**Modified Error Context:** + +```rust +// Original +result.map_err(|e| { + log::error!("Failed: {}", e); + format!("Operation failed: {}", e) +})?; + +// Refactored (WRONG) +result.map_err(|e| format!("Operation failed: {}", e))?; +// Lost the logging! +``` + +### 5. Your Analysis Output Format + +When analyzing a refactoring, provide: + +1. **Executive Summary** + - Overall risk level: LOW/MEDIUM/HIGH/CRITICAL + - Number of divergences found + - Confidence in analysis + +2. **Detailed Findings** + For each divergence: + - Location (file:line for both versions) + - Type of divergence + - Specific code comparison + - Potential impact + - Suggested fix + +3. **Path Analysis** + - Number of paths in original: X + - Number of paths in refactored: Y + - Missing paths: [list] + - New paths: [list] + - Modified paths: [list with details] + +4. **Test Recommendations** + - Specific test cases to add + - Property-based test suggestions + - Edge cases to verify + +## Working Process + +1. **Initial Setup** + ```bash + # Create analysis workspace + mkdir -p /tmp/refactor_analysis + cd /tmp/refactor_analysis + ``` + +2. **Extract Functions** + - Get the original function code + - Get the refactored function code + - Note line numbers for reference + +3. **Systematic Comparison** + - Use ast-grep patterns to extract logic elements + - Build path trees for both versions + - Compare systematically + +4. **Generate Report** + - Summarize findings clearly + - Prioritize critical issues + - Provide actionable recommendations + +## Key Commands You'll Use + +```bash +# Extract specific patterns +ast-grep --pattern '$PATTERN' --lang rust file.rs + +# Search for specific constructs +rg "pattern" --type rust + +# Check variable usage +ast-grep --pattern '$VAR' --lang rust | grep -A2 -B2 "mutate\|modify" + +# Find all function calls +ast-grep --pattern '$FUNC($$$ARGS)' --lang rust + +# Trace control flow +ast-grep --pattern 'if $$ { $$ } else { $$ }' --lang rust +``` + +## Your Success Metrics + +You succeed when: + +1. All behavioral differences are identified +2. No false positives in your analysis +3. Clear, actionable findings are provided +4. The refactored code can be confidently deployed + +## Special Instructions + +- Be thorough but efficient - use pattern matching to quickly identify areas of concern +- Focus on semantic differences, not just syntactic ones +- Always provide concrete examples when reporting issues +- Suggest specific test cases that would catch each divergence +- If you're unsure about a potential issue, mark it as "REQUIRES MANUAL REVIEW" with explanation diff --git a/.claude/skills/pr-comment/SKILL.md b/.claude/commands/pr-comment.md similarity index 69% rename from .claude/skills/pr-comment/SKILL.md rename to .claude/commands/pr-comment.md index 9dcf6e68..91a49508 100644 --- a/.claude/skills/pr-comment/SKILL.md +++ b/.claude/commands/pr-comment.md @@ -1,9 +1,3 @@ ---- -name: pr-comment -description: handling GitHub PR comments with proper replies -argument-hint: comment link (e.g. https://github.com/wharflab/tally/pull/134#discussion_r2815672223) ---- - # PR Comment Handler You are handling a GitHub PR review comment. Follow this procedure exactly: @@ -46,11 +40,10 @@ Display this information to the user. **CRITICAL RULES:** -- Verify each finding against the current code and only fix it if confirmed by code. -- Ideally, start with adding a regression test if comment is about a potential bug -- If user is giving you a link to "nitpicks" comment that means it is MANDATORY to fix in this PR -- NO TODOs, NO placeholders, NO deferred fixes, NO linting disabling comments -- Read the relevant files and make the changes requested +- Treat EVERY remark as mandatory, even "nitpicks" +- Apply ALL suggestions immediately +- NO TODOs, NO placeholders, NO deferred fixes +- Read the relevant files and make the exact changes requested - If the comment references multiple issues, fix all of them - If unclear, make your best judgment and proceed @@ -78,16 +71,13 @@ Reply DIRECTLY to the specific comment (not a new review, not a top-level commen ```bash gh api repos///pulls//comments//replies \ - -X POST -f body='✅ Addressed in . Thanks @!' --jq '"💬 Replied to comment \(.in_reply_to_id)"' + -X POST -f body='✅ Addressed in . Thanks @!' --jq '.in_reply_to_id' ``` Replace: - `` with the 7-character commit hash -- `` with the comment author’s username, dropping `[bot]` suffix if any - -IMPORTANT: the above API WORKS! If you are getting 404 or similar error - verify that you've -built the URL correctly, don't fallback to post a generic comment on PR! +- `` with the comment author’s username ## Output Format diff --git a/.claude/hooks/prevent-main-commit.sh b/.claude/hooks/prevent-main-commit.sh new file mode 100755 index 00000000..014c6fd5 --- /dev/null +++ b/.claude/hooks/prevent-main-commit.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Hook to prevent commits to main branch + +json_input=$(cat) + +tool_input_command=$(echo "$json_input" | jq -r ' +if .tool_input.command then + .tool_input.command +else + empty +end') + +if [ -z "$tool_input_command" ]; then + exit 0 +fi + +# Helper function to output JSON response +output_json() { + local decision="$1" + local reason="$2" + jq -n \ + --arg decision "$decision" \ + --arg reason "$reason" \ + '{ + hookSpecificOutput: { + hookEventName: "PreToolUse", + permissionDecision: $decision, + permissionDecisionReason: $reason + } + }' +} + +if [[ $tool_input_command =~ "git commit" ]]; then + # Get current branch + CURRENT_BRANCH=$(git branch --show-current --no-color --quiet 2>/dev/null) + + # see https://docs.anthropic.com/en/docs/claude-code/hooks#advanced%3A-json-output + if [[ "$CURRENT_BRANCH" =~ ^(main|master)$ ]]; then + output_json "ask" " ⚠️ You are about to commit directly to the $CURRENT_BRANCH branch. Are you sure?" + fi +fi diff --git a/.claude/settings.json b/.claude/settings.json index 8a16d1ba..ca58880d 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -7,14 +7,12 @@ "CLICOLOR_FORCE": "1", "NEXTEST_COLOR": "1", "CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1", - "CLAUDE_CODE_RETRY_WATCHDOG": "1", - "CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK": "1", - "ENABLE_PROMPT_CACHING_1H": "1", "GH_PAGER": "cat", "MAX_THINKING_TOKENS": "32000" }, "permissions": { "allow": [ + "mcp__*", "Bash(gsed:*)", "Bash(git:*)", "Bash(git add:*)", @@ -42,6 +40,18 @@ ], "deny": [] }, - "hooks": {}, + "hooks": { + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/prevent-main-commit.sh" + } + ] + } + ] + }, "enableAllProjectMcpServers": true -} \ No newline at end of file +} diff --git a/.claude/skills/mintlify b/.claude/skills/mintlify deleted file mode 120000 index 207cf131..00000000 --- a/.claude/skills/mintlify +++ /dev/null @@ -1 +0,0 @@ -../../.agents/skills/mintlify \ No newline at end of file diff --git a/.codex/config.toml b/.codex/config.toml deleted file mode 100644 index 1d65f09a..00000000 --- a/.codex/config.toml +++ /dev/null @@ -1,11 +0,0 @@ -[shell_environment_policy] -inherit = "core" - -[shell_environment_policy.set] -CARGO_TERM_COLOR = "never" -CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR = "1" -CLICOLOR = "0" -CLICOLOR_FORCE = "0" -GH_PAGER = "cat" -MAX_THINKING_TOKENS = "32000" -NEXTEST_COLOR = "0" diff --git a/.config/nextest.toml b/.config/nextest.toml index 90a85521..5dc18003 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -4,9 +4,6 @@ failure-output = "immediate-final" # Do not cancel the test run on the first failure. fail-fast = false -# Snapshot assertions (insta) should not be retried since reruns add noise and -# can produce confusing pending-snapshot states. -retries = 0 status-level = "skip" diff --git a/.gitattributes b/.gitattributes index b21db99a..8ee79cb7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1 @@ -# ANTLR-generated lexer/parser modules: checked in (so a normal build needs -# no Java/ANTLR toolchain) but machine-generated — collapse in diffs and -# exclude from GitHub language stats. Regenerate via -# `cargo xtask antlr generate `; never hand-edit. Spell check -# (.typos.toml) and Copy/Paste Detection (.github/workflows/cpd.yml) exclude -# the same path. -**/src/generated/** linguist-generated=true +src/languages/language_*.rs linguist-generated=true diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index a01e0cec..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,15 +0,0 @@ -# These are supported funding model platforms - -github: [tinovyatkin] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -polar: # Replace with a single Polar username -buy_me_a_coffee: # Replace with a single Buy Me a Coffee username -thanks_dev: # Replace with a single thanks.dev username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 70deb430..d13bafe1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,29 +5,14 @@ updates: schedule: interval: weekly open-pull-requests-limit: 99 - # Wait 1 day after a release before opening an update. Multi-crate - # families (oxc, ruff, sqruff, mago) publish their members over a short - # window; without a cooldown Dependabot can open a group PR mid-publish - # and bump only the crates indexed so far, breaking the version lockstep - # and failing CI with duplicate-crate errors. - cooldown: - default-days: 1 groups: tree-sitter: patterns: - "tree-sitter*" - oxc: - patterns: - - "oxc_*" - mago: - patterns: - - "mago-*" - ruff: - patterns: - - "ruff_*" - sqruff: - patterns: - - "sqruff-*" - antlr-rust: - patterns: - - "antlr-rust-*" + - package-ecosystem: cargo + directory: "/enums" + schedule: + interval: weekly + open-pull-requests-limit: 99 + ignore: + - dependency-name: "tree-sitter*" diff --git a/.github/workflows/binary-size.yml b/.github/workflows/binary-size.yml deleted file mode 100644 index 26674472..00000000 --- a/.github/workflows/binary-size.yml +++ /dev/null @@ -1,155 +0,0 @@ -name: Binary Size - -on: - push: - branches: [main] - pull_request: - branches: [main] - -permissions: - contents: write - pull-requests: write - -# Serialize note-writing runs so concurrent main pushes don't race the -# refs/notes/binary-size ref. PR runs get a unique group so they don't queue. -concurrency: - group: binary-size-${{ github.event_name == 'push' && 'notes' || github.run_id }} - cancel-in-progress: false - -env: - CARGO_INCREMENTAL: 0 - CARGO_NET_RETRY: 10 - CARGO_TERM_COLOR: always - RUSTUP_MAX_RETRIES: 10 - NOTES_REF: refs/notes/binary-size - -jobs: - track-size: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Set up Rust toolchain - run: rustup show - - - name: Cache Rust dependencies - uses: Swatinem/rust-cache@v2 - with: - shared-key: "rust-cache-${{ hashFiles('**/Cargo.lock') }}" - cache-on-failure: true - - - name: Build release binary - run: | - cargo build --release --locked - SIZE=$(stat --format='%s' target/release/mehen) - echo "SIZE=$SIZE" >> "$GITHUB_ENV" - echo "Release Linux binary size: $SIZE bytes ($(numfmt --to=iec-i --suffix=B "$SIZE"))" - - - name: Fetch size notes - run: git fetch origin "$NOTES_REF":"$NOTES_REF" 2>/dev/null || true - - - name: Record size (push to main) - if: github.event_name == 'push' - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git notes --ref="$NOTES_REF" add -f -m "$SIZE" "$GITHUB_SHA" - git push origin "$NOTES_REF" - - - name: Post size comment on PR - # Skip on fork PRs: GITHUB_TOKEN is read-only there, so commenting would fail. - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.pull_request.number }} - shell: bash - run: | - # --- Collect history from git notes (chronological, oldest first) --- - # Walk main branch commits and check which have size notes attached. - declare -a SIZES=() - declare -a LABELS=() - - while IFS= read -r sha; do - blob=$(git notes --ref="$NOTES_REF" list "$sha" 2>/dev/null) || continue - note=$(git cat-file -p "$blob") - subject=$(git log --format='%s' -1 "$sha" 2>/dev/null | cut -c1-30) - # Prepend (git log is newest-first, we reverse later). - SIZES=("$note" "${SIZES[@]}") - LABELS=("$subject" "${LABELS[@]}") - done < <(git log --format='%H' origin/main -- 2>/dev/null | head -20) - - # --- Determine baseline (most recent recorded size on main) --- - BASE_SIZE="" - if [ ${#SIZES[@]} -gt 0 ]; then - BASE_SIZE="${SIZES[-1]}" - fi - - # --- Build comparison table --- - PR_HUMAN=$(numfmt --to=iec-i --suffix=B "$SIZE") - if [ -n "$BASE_SIZE" ] && [ "$BASE_SIZE" -gt 0 ] 2>/dev/null; then - BASE_HUMAN=$(numfmt --to=iec-i --suffix=B "$BASE_SIZE") - DIFF=$((SIZE - BASE_SIZE)) - if [ "$DIFF" -ge 0 ]; then DIFF_SIGN="+"; else DIFF_SIGN=""; fi - DIFF_HUMAN=$(numfmt --to=iec-i --suffix=B -- "$DIFF") - PCT=$(awk "BEGIN {printf \"%.2f\", ($DIFF / $BASE_SIZE) * 100}") - read -r -d '' TABLE < - Size history - - \`\`\`mermaid - xychart-beta - title "Binary size (bytes)" - x-axis [${X_LABELS}] - y-axis "Bytes" - bar [${Y_DATA}] - \`\`\` - - - BODYEOF - - COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \ - --paginate -q ".[] | select(.body | startswith(\"${MARKER}\")) | .id" | head -1) - - if [ -n "$COMMENT_ID" ]; then - gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}" \ - -X PATCH -f body="$BODY" - else - gh pr comment "$PR_NUMBER" --body "$BODY" - fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ba62827..df647498 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,34 +43,12 @@ jobs: with: tool: cargo-insta - - name: Install cargo-nextest - uses: taiki-e/install-action@v2 - with: - tool: cargo-nextest - - name: Run tests shell: bash - env: - NEXTEST_PROFILE: ci - # `--workspace` is required: `default-members` in the root - # `Cargo.toml` restricts root-level cargo commands to the - # `mehen` package so `cargo build` from the repo root keeps - # producing `target/release/mehen` (binary-size pipeline). - # Without `--workspace` here, this step would silently skip - # every per-language analyzer, the engine, the metrics, - # report, git, and markdown crates' tests. - run: cargo insta test --workspace --all-features --check --unreferenced reject --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest - - # nextest cannot run doctests, so the step above passes `--disable-nextest-doctest`. - # Doctests are compiled by the release job's `cargo test --workspace`, so guard - # them here too — otherwise a doctest that fails to compile only surfaces at the - # release tag, after PR CI is already green. - - name: Run doctests - shell: bash - run: cargo test --workspace --all-features --doc + run: cargo insta test --all-features --check --unreferenced reject - name: Smoke test CLI shell: bash run: | - cargo build --release + cargo build --release -p mehen-cli ./target/release/mehen --help diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 13ac68eb..717c648c 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -7,16 +7,9 @@ on: branches: [main] permissions: + id-token: write contents: read checks: write - # OIDC token for codecov uploads (use_oidc: true). - id-token: write - # The mehen action posts/updates the sticky PR metrics comment. - pull-requests: write - issues: write - # The mehen action's artifact base-coverage rung lists and downloads - # the base SHA's coverage-report artifact via the REST API. - actions: read jobs: coverage: @@ -24,10 +17,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v5 - with: - # Full history: `mehen diff` resolves origin/ and walks - # both revisions for the history.* columns. - fetch-depth: 0 - name: Set up Rust toolchain run: rustup show @@ -53,122 +42,26 @@ jobs: RUSTFLAGS: '-C instrument-coverage' run: | mkdir -p target/llvm-cov - cargo llvm-cov nextest --workspace --locked --no-fail-fast --all-features --ignore-filename-regex 'src/languages/language_.*\.rs$' --lcov --output-path target/llvm-cov/lcov-branch.info - - - name: Generate Cobertura coverage report - shell: bash - run: | - cargo llvm-cov report --cobertura --ignore-filename-regex 'src/languages/language_.*\.rs$' --output-path target/llvm-cov/cobertura.xml + cargo llvm-cov nextest --workspace --locked --no-fail-fast --all-features --lcov --output-path target/llvm-cov/lcov-branch.info - # OIDC uploads have been failing with 404 "Repository not found" - # since the org rename (ophidiarium → ophi-dev) left codecov's - # ingest-side repo record on the old slug — verified locally: a - # token-based upload succeeds while codecov echoes the pre-rename - # slug in its response URL. Keep OIDC and fail loudly for now so - # the breakage is on CI record; the token switch (or a codecov - # support-side fix) follows. - name: Upload test results to Codecov if: ${{ !cancelled() }} - uses: codecov/codecov-action@v7 + uses: codecov/test-results-action@v1 with: - report_type: test_results files: target/nextest/ci/junit.xml use_oidc: true - fail_ci_if_error: true verbose: true - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v7 + uses: codecov/codecov-action@v5 with: files: target/llvm-cov/lcov-branch.info + fail_ci_if_error: false use_oidc: true - fail_ci_if_error: true verbose: true - name: Upload coverage artifacts - if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: coverage-report path: target/llvm-cov/lcov-branch.info - - - name: Upload Cobertura coverage artifact - if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - uses: actions/upload-artifact@v4 - with: - name: coverage-report-rust - path: target/llvm-cov/cobertura.xml - - # Dogfooding issue #248: the action consumes the LCOV file just - # produced — head side directly, base side via the cache/codecov - # retrieval ladder — so PR comments carry coverage trend columns. - # Runs even when tests failed (`!cancelled()`): the metrics - # comment matters most on red PRs; a missing report file only - # degrades the coverage columns, never the comment. - - name: Publish mehen metrics - if: ${{ !cancelled() }} - uses: ./ - with: - install-method: cargo - # `crates` carries the per-language analyzer + engine - # source after the 1.0 workspace split; `xtask` is the - # build-helper crate. `docs/` (Mintlify) and the top-level - # Markdown files feed the Phase-F `` - # documentation-metrics section. Any path that matches one - # of mehen's registered Markdown extensions - # (md/markdown/mdown/mkd/mkdn/mdx) is routed through the - # documentation pipeline. Keep this list in sync with every - # root Markdown file so doc-only PRs do not silently skip - # the self-check. - paths: | - crates - xtask - docs - README.md - AGENTS.md - CLAUDE.md - CHANGELOG.md - # `xtask/templates/grammar.rs` is an askama template — it - # has the `.rs` extension so language detection routes it - # through the Rust analyzer, but it carries `{{ c_name }}` - # and other template directives that don't parse as Rust. - # The analyzer reports `rust.syntax_error` diagnostics that - # flip `mehen diff`'s exit code to 1 (per plan §9.3), even - # when the JSON report is otherwise complete. Skip it. - exclude: | - xtask/templates/** - coverage-files: target/llvm-cov/lcov-branch.info - # Base rung 2 (issue #254): the same job uploads this - # artifact on every run, so base SHAs stay retrievable for - # ~90 days after the cache's 7-day eviction. - coverage-artifact-name: coverage-report - codecov-token: ${{ secrets.CODECOV_API_TOKEN }} - - # GitHub Code Quality upload (issue #254 / originally generated in - # #253): permission isolation — `code-quality: write` lives only in - # this minimal job. Gated on `!cancelled()` rather than the coverage - # job's overall result: a red main push (failed gate, codecov error) - # must not silently skip the baseline upload GitHub compares PRs - # against. The artifact download is the real precondition — when the - # Cobertura report was never produced, the upload step is skipped. - upload-coverage-rust: - needs: coverage - if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - runs-on: ubuntu-latest - permissions: - contents: read - code-quality: write - steps: - - name: Download Cobertura coverage artifact - id: download - continue-on-error: true - uses: actions/download-artifact@v8 - with: - name: coverage-report-rust - - if: ${{ steps.download.outcome == 'success' }} - uses: actions/upload-code-coverage@v1 - with: - file: cobertura.xml - language: Rust - label: code-coverage/llvm-cov diff --git a/.github/workflows/cpd.yml b/.github/workflows/cpd.yml deleted file mode 100644 index 0cbeccec..00000000 --- a/.github/workflows/cpd.yml +++ /dev/null @@ -1,184 +0,0 @@ -name: Copy/Paste Detection - -on: - pull_request: - branches: [main] - paths: - # Trigger only when at least one non-excluded Rust file changes. - # Negative patterns mirror the runtime filter so PRs that touch only - # generated/test/template Rust files do not start a no-op job. - - '**/*.rs' - - '!crates/*/src/grammar.rs' - - '!**/src/generated/**' - - '!**/tests/**' - - '!**/snapshots/**' - - '!**/fixtures/**' - - '!**/testdata/**' - - '!xtask/templates/**' - # Re-run when this workflow itself changes. - - '.github/workflows/cpd.yml' - -permissions: - contents: read - pull-requests: write - -concurrency: - group: cpd-${{ github.event.pull_request.number || github.run_id }} - cancel-in-progress: true - -env: - PMD_VERSION: 7.20.0 - CPD_TOKENS: "100" - COMMENT_MARKER: - -jobs: - cpd: - name: Copy/Paste Detection - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Determine changed Rust files - id: changed - shell: bash - run: | - set -euo pipefail - BASE_SHA=$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD) - # Diff against the merge-base; restrict to .rs files; drop deletions. - # Strip generated grammar enums, generated ANTLR modules, tests, - # snapshots, fixtures, templates. - # `src/generated/` holds the machine-generated ANTLR lexer/parser - # modules (e.g. `mehen-kotlin-parser`); they are intentionally repetitive - # (one templated method per grammar rule) and must not be CPD-policed. - # `tests/` matches both the top-level tests directory and per-crate - # `crates//tests/` integration suites. Test boilerplate - # (per-language `analyze()` helpers, metric-fact readers) is the - # bulk of the workspace's lexical duplication and does not benefit - # from CPD policing — the duplication is intentional in tests - # where a thin per-suite harness is more readable than a shared - # one. Mirrors the `paths:` filter on the workflow trigger. - git diff --name-only --diff-filter=d "$BASE_SHA" HEAD -- '*.rs' \ - | grep -Ev '^crates/[^/]+/src/grammar\.rs$|/src/generated/|(^|/)tests/|/snapshots/|/fixtures/|/testdata/|^xtask/templates/|^target/' \ - > changed-files.txt || true - COUNT=$(wc -l < changed-files.txt | tr -d ' ') - echo "count=$COUNT" >> "$GITHUB_OUTPUT" - echo "Changed Rust files ($COUNT):" - cat changed-files.txt || true - - - name: Setup PMD - run: | - curl -fL "https://github.com/pmd/pmd/releases/download/pmd_releases%2F${PMD_VERSION}/pmd-dist-${PMD_VERSION}-bin.zip" -o pmd.zip - unzip -q pmd.zip - rm pmd.zip - - - name: Run CPD - id: cpd - shell: bash - run: | - set -uo pipefail - # PMD CPD exit codes: - # 0 — no duplications - # 4 — duplications found - # 5 — recoverable errors (e.g., a file failed to lex; report still produced) - set +e - "pmd-bin-${PMD_VERSION}/bin/pmd" cpd \ - --language rust \ - --minimum-tokens "${CPD_TOKENS}" \ - --file-list changed-files.txt \ - --format markdown \ - > cpd-report.md 2> cpd-stderr.log - STATUS=$? - set -e - - if [ "$STATUS" -ne 0 ] && [ "$STATUS" -ne 4 ] && [ "$STATUS" -ne 5 ]; then - echo "PMD CPD errored (status $STATUS):" - cat cpd-stderr.log - exit "$STATUS" - fi - - # Surface lexer warnings in the job log without failing the workflow. - if [ -s cpd-stderr.log ]; then - echo "=== PMD stderr ===" - cat cpd-stderr.log - fi - - # Post-process: rewrite absolute workspace paths to repo-relative. - sed -i "s|${GITHUB_WORKSPACE}/||g" cpd-report.md - - # Post-process: tag opening code fences with `rust` for syntax - # highlighting. PMD emits bare ``` fences; alternate open/close as - # we walk the file. - awk ' - BEGIN { open = 0 } - /^```$/ { - if (open == 0) { print "```rust"; open = 1 } - else { print "```"; open = 0 } - next - } - { print } - ' cpd-report.md > cpd-report.tagged.md - mv cpd-report.tagged.md cpd-report.md - - DUP_COUNT=$(grep -c '^Found a ' cpd-report.md || true) - echo "duplications=${DUP_COUNT:-0}" >> "$GITHUB_OUTPUT" - - echo "=== Report ===" - cat cpd-report.md - - - name: Build comment body - shell: bash - env: - CHANGED_COUNT: ${{ steps.changed.outputs.count }} - DUP_COUNT: ${{ steps.cpd.outputs.duplications }} - run: | - set -euo pipefail - { - echo "${COMMENT_MARKER}" - echo "## Copy/Paste Detection" - echo "" - if [ "${DUP_COUNT:-0}" = "0" ]; then - echo "🟢 No duplications found in ${CHANGED_COUNT} changed Rust file(s) (threshold: ${CPD_TOKENS} tokens)." - else - echo "🔴 Found **${DUP_COUNT}** duplication(s) across ${CHANGED_COUNT} changed Rust file(s) (threshold: ${CPD_TOKENS} tokens)." - echo "" - echo "
" - echo "Show duplications" - echo "" - cat cpd-report.md - echo "" - echo "
" - fi - } > comment-body.md - - # GitHub PR comments cap at 65536 chars; leave headroom. - SIZE=$(wc -c < comment-body.md) - if [ "$SIZE" -gt 60000 ]; then - head -c 60000 comment-body.md > comment-body.trunc.md - printf '\n\n_(report truncated; full output in workflow logs)_\n' >> comment-body.trunc.md - mv comment-body.trunc.md comment-body.md - fi - - cat comment-body.md - - - name: Post sticky PR comment - # Skip on fork PRs: GITHUB_TOKEN is read-only there, so commenting would fail. - if: github.event.pull_request.head.repo.full_name == github.repository - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.pull_request.number }} - shell: bash - run: | - set -euo pipefail - BODY=$(cat comment-body.md) - - COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \ - --paginate -q ".[] | select(.body | startswith(\"${COMMENT_MARKER}\")) | .id" | head -1) - - if [ -n "$COMMENT_ID" ]; then - gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}" \ - -X PATCH -f body="$BODY" - else - gh pr comment "$PR_NUMBER" --body "$BODY" - fi diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml deleted file mode 100644 index d58da059..00000000 --- a/.github/workflows/dependabot-auto-merge.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Dependabot Auto-Merge - -on: - pull_request_target: - -jobs: - auto-merge: - if: github.event.pull_request.user.login == 'dependabot[bot]' - runs-on: ubuntu-latest - steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ vars.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - - # Structured info about the update (crate names, group, semver bump). - # `dependency-names` lists every crate the PR touches — including for - # grouped PRs whose titles ("bump the oxc group") don't name the crates. - - name: Fetch Dependabot metadata - id: meta - uses: dependabot/fetch-metadata@v3 - - - name: Approve and enable auto-merge - run: | - set -euo pipefail - gh pr review "$PR_NUMBER" --repo "$REPO" --approve --body "Dependabot PR — auto-approved." - - # Parser/grammar dependency bumps are relabeled from the hidden - # `build(deps)` type to the custom `deps:` type, which - # release-please surfaces under "Parser & Grammar Updates" (see - # release-please-config.json). Every other dependency bump keeps - # `build(deps)` and stays out of the changelog. release-please - # matches on commit TYPE only (it has no scope filter), so the - # discrimination must be baked into the squashed subject here. - # - # We match on crate-name prefix rather than the PR title so grouped - # PRs are classified correctly. release-please links a changelog - # entry via the trailing "(#NN)", and a custom --subject replaces - # GitHub's default subject entirely, so we re-add it by hand. - if printf '%s' "$NAMES" | grep -qiE '(^|,)[[:space:]]*(tree-sitter|oxc_|mago-|ruff_|sqruff-|pulldown-cmark|ra_ap_|antlr-rust-)'; then - gh pr merge "$PR_NUMBER" --repo "$REPO" --auto --squash \ - --subject "deps: ${TITLE#*: } (#${PR_NUMBER})" - else - gh pr merge "$PR_NUMBER" --repo "$REPO" --auto --squash - fi - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - PR_NUMBER: ${{ github.event.pull_request.number }} - REPO: ${{ github.repository }} - NAMES: ${{ steps.meta.outputs.dependency-names }} - TITLE: ${{ github.event.pull_request.title }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d920bb16..b9bf3371 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -3,30 +3,19 @@ on: branches: - main pull_request: - types: [ opened, synchronize, reopened ] + types: [opened, synchronize, reopened] paths: - - "**/*.rs" - # Markdown files feed the Phase-F `` section - # so the self-check publishes documentation metrics on doc-only PRs. - - "**/*.md" - - "**/*.markdown" - - "**/*.mdown" - - "**/*.mkd" - - "**/*.mkdn" - - "**/*.mdx" - - ".github/workflows/lint.yml" - - "action.yml" - - Cargo.lock - - "scripts/**/*.mjs" + - '**/*.rs' permissions: - contents: read + pull-requests: write + issues: write name: Code Quality Checks # Make sure CI fails on all warnings, including Clippy lints env: - RUSTFLAGS: "-Dwarnings" + RUSTFLAGS: '-Dwarnings' CARGO_TERM_COLOR: always CLICOLOR: 1 @@ -51,13 +40,6 @@ jobs: - name: Set up Rust toolchain run: rustup show - - name: Check GitHub Action script - uses: actions/setup-node@v6 - with: - node-version: 24 - - - run: node --test scripts/github-action.test.mjs - - run: cargo clippy --workspace --all-targets --all-features --locked - run: cargo fmt --all --check @@ -68,7 +50,150 @@ jobs: - name: Cargo Machete uses: bnjbvr/cargo-machete@7959c845782fed02ee69303126d4a12d64f1db18 # v0.9.1 - # The mehen action self-test (`uses: ./`) lives in - # .github/workflows/coverage.yml: it consumes the LCOV report the - # coverage job produces, dogfooding the head `--coverage` and - # base-retrieval (`coverage-files`) paths from issue #248. + # Install rust-code-analysis + - name: Install rust-code-analysis + env: + RCA_LINK: https://github.com/mozilla/rust-code-analysis/releases/download + RCA_VERSION: v0.0.25 + run: | + mkdir -p $HOME/.local/bin + curl -L "$RCA_LINK/$RCA_VERSION/rust-code-analysis-linux-cli-x86_64.tar.gz" | + tar xz -C $HOME/.local/bin + echo "$HOME/.local/bin" >> $GITHUB_PATH + + # Prepare output directory for rust-code-analysis + - name: Prepare rust-code-analysis output dir + run: mkdir -p $HOME/rca-json + + # Run rust-code-analysis on PR-diff files + - name: Run rust-code-analysis on PR-diff + if: ${{ github.event_name == 'pull_request' }} + run: | + rust-code-analysis-cli --metrics -O json --pr -o "$HOME/rca-json" -p src + + # Run rust-code-analysis on all files (push to main) + - name: Run rust-code-analysis on all files + if: ${{ github.event_name == 'push' }} + run: | + rust-code-analysis-cli --metrics -O json -o "$HOME/rca-json" -p src + + - name: Upload rust-code-analysis json + uses: actions/upload-artifact@v4 + with: + name: rca-json-ubuntu + path: ~/rca-json + + # Generate baseline rust-code-analysis metrics from main branch + - name: Prepare baseline rust-code-analysis output dir + if: ${{ github.event_name == 'pull_request' }} + run: mkdir -p $HOME/rca-json-base + - name: Checkout main branch for baseline + if: ${{ github.event_name == 'pull_request' }} + uses: actions/checkout@v5 + with: + ref: main + path: main + - name: Run rust-code-analysis on main branch + if: ${{ github.event_name == 'pull_request' }} + working-directory: main + run: | + rust-code-analysis-cli --metrics -O json -o "$HOME/rca-json-base" -p src + + # Comment rust-code-analysis metrics on pull requests with comparison + - name: Comment rust-code-analysis metrics on PR + if: ${{ github.event_name == 'pull_request' }} + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const prDir = `${process.env.HOME}/rca-json`; + const baseDir = `${process.env.HOME}/rca-json-base`; + const owner = context.repo.owner; + const repo = context.repo.repo; + const ref = context.payload.pull_request.head.sha; + const changedFilesList = await github.paginate( + github.rest.pulls.listFiles, + { owner, repo, pull_number: context.issue.number } + ); + const changedFiles = new Set(changedFilesList.map(f => f.filename)); + let rows = []; + const collectFiles = (d) => fs.readdirSync(d, { withFileTypes: true }).flatMap(dirent => { + const full = `${d}/${dirent.name}`; + return dirent.isDirectory() ? collectFiles(full) : [full]; + }); + let prFiles = collectFiles(prDir).filter(f => f.endsWith('.json')); + prFiles = prFiles.filter(fullPath => { + const rel = fullPath.slice(prDir.length + 1).replace(/\.json$/, ''); + return changedFiles.has(rel); + }); + prFiles.forEach(fullPath => { + const rel = fullPath.slice(prDir.length + 1).replace(/\.json$/, ''); + const fileLink = `[${rel}](https://github.com/${owner}/${repo}/blob/${ref}/${rel})`; + const prRaw = JSON.parse(fs.readFileSync(fullPath, 'utf8')); + const prItems = Array.isArray(prRaw) ? prRaw : [prRaw]; + const prCount = prItems.length || 1; + const prCyclo = prItems.reduce((s,o)=>s+o.metrics.cyclomatic.sum,0)/prCount; + const prCog = prItems.reduce((s,o)=>s+o.metrics.cognitive.sum,0)/prCount; + const prFunc = prItems.reduce((s,o)=>s+o.metrics.nom.functions,0); + const prLloc = prItems.reduce((s,o)=>s+o.metrics.loc.lloc,0); + let baseCyclo = prCyclo, baseCog = prCog, baseFunc = prFunc, baseLloc = prLloc; + const basePath = `${baseDir}/${rel}.json`; + if (fs.existsSync(basePath)) { + const baseRaw = JSON.parse(fs.readFileSync(basePath,'utf8')); + const baseItems = Array.isArray(baseRaw)?baseRaw:[baseRaw]; + const baseCount = baseItems.length||1; + baseCyclo = baseItems.reduce((s,o)=>s+o.metrics.cyclomatic.sum,0)/baseCount; + baseCog = baseItems.reduce((s,o)=>s+o.metrics.cognitive.sum,0)/baseCount; + baseFunc = baseItems.reduce((s,o)=>s+o.metrics.nom.functions,0); + baseLloc = baseItems.reduce((s,o)=>s+o.metrics.loc.lloc,0); + } + const diffFunc = prFunc - baseFunc; + const diffCyclo = (prCyclo - baseCyclo).toFixed(1); + const diffCog = (prCog - baseCog).toFixed(1); + const diffLloc = prLloc - baseLloc; + const emoji = d => d>0? '🔴': d<0? '🟢':'⚪'; + const funcsCell = prFunc === baseFunc + ? `${prFunc.toFixed(0)} ${emoji(0)}` + : `${prFunc} (main: ${baseFunc}) ${emoji(diffFunc)}`; + const cycloCell = prCyclo === baseCyclo + ? `${prCyclo.toFixed(0)} ${emoji(0)}` + : `${prCyclo.toFixed(0)} (main: ${baseCyclo.toFixed(0)}) ${emoji(diffCyclo)}`; + const cogCell = prCog === baseCog + ? `${prCog.toFixed(0)} ${emoji(0)}` + : `${prCog.toFixed(0)} (main: ${baseCog.toFixed(0)}) ${emoji(diffCog)}`; + const llocCell = prLloc === baseLloc + ? `${prLloc} ${emoji(0)}` + : `${prLloc} (main: ${baseLloc}) ${emoji(diffLloc)}`; + rows.push({ file: fileLink, funcsVal: prFunc, funcs: funcsCell, cyclo: cycloCell, cog: cogCell, lloc: llocCell }); + }); + rows.sort((a, b) => { + const diff = b.funcsVal - a.funcsVal; + return diff !== 0 ? diff : a.file.localeCompare(b.file); + }); + const commentTitle = '## [Rust-Code-Analysis](https://mozilla.github.io/rust-code-analysis/) Summary'; + let body = commentTitle + ' (this PR vs `main`)\n\n'; + body += '| File | Functions | [Cyclomatic](https://en.wikipedia.org/wiki/Cyclomatic_complexity) | [Cognitive](https://www.sonarsource.com/blog/cognitive-complexity-because-testability-understandability/) | LLOC |\n'; + body += '|---|---:|---:|---:|---:|\n'; + rows.forEach(r => body += `| ${r.file} | ${r.funcs} | ${r.cyclo} | ${r.cog} | ${r.lloc} |\n`); + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const prev = comments.find(c => c.body.startsWith(commentTitle)); + if (prev) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: prev.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); + } diff --git a/.github/workflows/regenerate-grammars.yml b/.github/workflows/regenerate-grammars.yml index 19e947b7..c362ee41 100644 --- a/.github/workflows/regenerate-grammars.yml +++ b/.github/workflows/regenerate-grammars.yml @@ -25,24 +25,19 @@ jobs: contains(github.event.pull_request.head.ref, 'tree-sitter') runs-on: ubuntu-latest steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ vars.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - - name: Checkout PR branch uses: actions/checkout@v5 with: ref: ${{ github.event.pull_request.head.ref }} - token: ${{ steps.app-token.outputs.token }} - # No pin-sync step: each tree-sitter grammar is pinned exactly - # once, in its owning analyzer crate's `Cargo.toml`. xtask reaches - # the grammar through that crate's `__grammar_language()` accessor, - # so dependabot's bump in `crates/mehen-/Cargo.toml` - # propagates to the kind-enum generator automatically. + - name: Sync tree-sitter versions to enums + run: | + grep '^tree-sitter' Cargo.toml | while IFS= read -r line; do + pkg="${line%% =*}" + sed -i "s|^${pkg} = .*|${line}|" enums/Cargo.toml + done + echo "Updated enums/Cargo.toml:" + grep '^tree-sitter' enums/Cargo.toml - name: Set up Rust toolchain run: rustup show @@ -54,27 +49,15 @@ jobs: cache-on-failure: true - name: Regenerate grammars - run: cargo xtask tree-sitter generate --all + run: ./recreate-grammars.sh - name: Install cargo-insta uses: taiki-e/install-action@v2 with: tool: cargo-insta - - name: Install cargo-nextest - uses: taiki-e/install-action@v2 - with: - tool: cargo-nextest - - name: Run tests - env: - NEXTEST_PROFILE: ci - # `--workspace` is required because `default-members` in the - # root `Cargo.toml` restricts root-level cargo commands to the - # `mehen` package; without it, every per-language crate's - # tests would be skipped and a regenerated grammar that - # breaks one of them would land silently. - run: cargo insta test --workspace --all-features --check --unreferenced reject --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest + run: cargo insta test --all-features --check --unreferenced reject - name: Commit and push regenerated grammars run: | @@ -91,5 +74,5 @@ jobs: gh label create tree-sitter --description "Tree-sitter grammar updates" --color "0075ca" --force 2>/dev/null || true gh pr edit "$PR_NUMBER" --add-label "tree-sitter" env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index a14dab51..0ac49780 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -18,13 +18,6 @@ jobs: release_created: ${{ steps.release.outputs.release_created }} tag_name: ${{ steps.release.outputs.tag_name }} steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ vars.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - - name: Checkout repo uses: actions/checkout@v5 with: @@ -34,46 +27,102 @@ jobs: id: release uses: googleapis/release-please-action@v4 with: - token: ${{ steps.app-token.outputs.token }} + token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }} config-file: release-please-config.json manifest-file: .release-please-manifest.json - # release-please rewrites [workspace.package].version in Cargo.toml but - # only patches the top-level mehen entry in Cargo.lock — the 17 workspace - # crates that inherit `version.workspace = true` stay at the old version, - # which makes `cargo build --locked` fail in CI on the release PR. - - name: Sync workspace versions in Cargo.lock - if: ${{ steps.release.outputs.prs_created == 'true' }} - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - PR_JSON: ${{ steps.release.outputs.pr }} + # The release-please action creates the git tag when a release PR is merged. + # This tag automatically triggers the release.yml workflow (on tags matching 'v*.*.*'). + + upload-cli-binaries: + name: Upload CLI binaries to release + if: ${{ needs.release-please.outputs.release_created }} + needs: [release-please] + runs-on: ubuntu-latest + permissions: + contents: write + actions: read + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Wait for release workflow to complete shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - set -euo pipefail - BRANCH=$(echo "$PR_JSON" | jq -r '.headBranchName') - if [ -z "$BRANCH" ] || [ "$BRANCH" = "null" ]; then - echo "No release-please branch reported; skipping lockfile sync." - exit 0 - fi - echo "Syncing Cargo.lock on $BRANCH" - git fetch origin "$BRANCH" - git checkout "$BRANCH" - rustup toolchain install stable --profile minimal --no-self-update - cargo update --workspace - if git diff --quiet -- Cargo.lock; then - echo "Cargo.lock already in sync." - exit 0 + TAG_NAME="${{ needs.release-please.outputs.tag_name }}" + echo "Waiting for release workflow to complete for tag: $TAG_NAME" + + max_attempts=60 # Wait up to 30 minutes (60 * 30s) + attempt=0 + + while [ $attempt -lt $max_attempts ]; do + echo "Checking for release workflow run... (attempt $((attempt + 1))/$max_attempts)" + + WORKFLOW_ID=$(gh api repos/${{ github.repository }}/actions/workflows --jq '.workflows[] | select(.name == "Release") | .id') + + if [ -n "$WORKFLOW_ID" ]; then + COMPLETED_RUNS=$(gh api "repos/${{ github.repository }}/actions/workflows/$WORKFLOW_ID/runs" \ + --jq "[.workflow_runs[] | select(.head_sha == \"$(git rev-parse $TAG_NAME)\") | select(.status == \"completed\") | select(.conclusion == \"success\")] | length") + + if [ "$COMPLETED_RUNS" -gt 0 ]; then + echo "Release workflow completed!" + break + fi + fi + + echo "Release workflow still running, waiting 30 seconds..." + sleep 30 + attempt=$((attempt + 1)) + done + + if [ $attempt -eq $max_attempts ]; then + echo "Timeout waiting for release workflow to complete" + exit 1 fi - git config user.name "ophiarch[bot]" - git config user.email "ophiarch[bot]@users.noreply.github.com" - git add Cargo.lock - git commit -m "build: sync workspace crate versions in Cargo.lock" - git push origin "$BRANCH" - # The release-please action creates the git tag when a release PR is merged. - # Tags created with a GitHub App token (not GITHUB_TOKEN) trigger the - # release.yml workflow (on tags matching 'v*.*.*'), which builds the CLI - # archives AND attaches them to the GitHub Release (its `upload-cli-binaries` - # job). The upload lives there — not here — so it reuses the in-run build - # artifacts directly instead of polling for release.yml to finish, which - # previously raced its timeout once builds crossed ~30 min (see v1.4.0). + - name: Download CLI archives from release workflow + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG_NAME="${{ needs.release-please.outputs.tag_name }}" + + WORKFLOW_ID=$(gh api repos/${{ github.repository }}/actions/workflows --jq '.workflows[] | select(.name == "Release") | .id') + RUN_ID=$(gh api "repos/${{ github.repository }}/actions/workflows/$WORKFLOW_ID/runs" \ + --jq ".workflow_runs[] | select(.head_sha == \"$(git rev-parse $TAG_NAME)\") | select(.status == \"completed\") | select(.conclusion == \"success\") | .id" | head -1) + + echo "Found release workflow run ID: $RUN_ID" + + mkdir -p cli-archives + + gh run download "$RUN_ID" --pattern "cli-archive-*" --dir cli-archives-temp/ + + find cli-archives-temp -name "*.tar.gz" -o -name "*.zip" -o -name "*.sha256" | while read file; do + cp "$file" cli-archives/ + done + + echo "Downloaded CLI archives:" + ls -la cli-archives/ + + - name: Upload CLI archives to GitHub Release + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG_NAME="${{ needs.release-please.outputs.tag_name }}" + + for file in cli-archives/*; do + if [[ -f "$file" ]]; then + filename=$(basename "$file") + echo "Uploading: $filename" + gh release upload "$TAG_NAME" "$file" --clobber + echo "Uploaded: $filename" + fi + done + + echo "All CLI binaries uploaded to release: $TAG_NAME" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e693592..036edeeb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,19 +3,19 @@ name: Release on: push: tags: - - "v*.*.*" + - 'v*.*.*' workflow_dispatch: inputs: version: description: >- - Version to release (e.g., 1.2.3, 1.2.3-beta.1). Leave empty for - auto-generated version. + Version to release (e.g., 1.2.3, 1.2.3-beta.1). + Leave empty for auto-generated version. required: false type: string release_type: - description: "Type of release" + description: 'Type of release' required: false - default: "manual" + default: 'manual' type: choice options: - manual @@ -41,34 +41,34 @@ jobs: platform: # Linux x86_64 - os: ubuntu-latest - target: "x86_64-unknown-linux-gnu" - rust_target: "x86_64-unknown-linux-gnu" + target: 'x86_64-unknown-linux-gnu' + rust_target: 'x86_64-unknown-linux-gnu' - os: ubuntu-latest - target: "x86_64-unknown-linux-musl" - rust_target: "x86_64-unknown-linux-musl" + target: 'x86_64-unknown-linux-musl' + rust_target: 'x86_64-unknown-linux-musl' # Linux aarch64 (native ARM64 runners) - os: ubuntu-24.04-arm - target: "aarch64-unknown-linux-gnu" - rust_target: "aarch64-unknown-linux-gnu" + target: 'aarch64-unknown-linux-gnu' + rust_target: 'aarch64-unknown-linux-gnu' - os: ubuntu-24.04-arm - target: "aarch64-unknown-linux-musl" - rust_target: "aarch64-unknown-linux-musl" + target: 'aarch64-unknown-linux-musl' + rust_target: 'aarch64-unknown-linux-musl' # macOS Intel x86_64 - os: macos-15-intel - target: "x86_64-apple-darwin" - rust_target: "x86_64-apple-darwin" + target: 'x86_64-apple-darwin' + rust_target: 'x86_64-apple-darwin' # macOS Apple Silicon aarch64 - os: macos-latest - target: "aarch64-apple-darwin" - rust_target: "aarch64-apple-darwin" + target: 'aarch64-apple-darwin' + rust_target: 'aarch64-apple-darwin' # Windows x86_64 - os: windows-latest - target: "x86_64-pc-windows-msvc" - rust_target: "x86_64-pc-windows-msvc" + target: 'x86_64-pc-windows-msvc' + rust_target: 'x86_64-pc-windows-msvc' # Windows aarch64 (native ARM64 runner) - os: windows-11-arm - target: "aarch64-pc-windows-msvc" - rust_target: "aarch64-pc-windows-msvc" + target: 'aarch64-pc-windows-msvc' + rust_target: 'aarch64-pc-windows-msvc' steps: - name: Checkout repository @@ -85,8 +85,7 @@ jobs: echo "CARGO_BUILD_TARGET=${{ matrix.platform.rust_target }}" >> "$GITHUB_ENV" - name: Install musl toolchain - if: startsWith(matrix.platform.os, 'ubuntu') && - contains(matrix.platform.rust_target, 'musl') + if: startsWith(matrix.platform.os, 'ubuntu') && contains(matrix.platform.rust_target, 'musl') shell: bash run: | sudo apt-get update @@ -106,12 +105,10 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: '3.12' # maturin uses pip in some platforms - run: pip install pip --upgrade - if: (matrix.platform.os != 'windows-11-arm') && (matrix.platform.os != - 'windows-latest') - name: Extract version from tag id: get_version @@ -243,48 +240,22 @@ jobs: - name: Run tests shell: bash if: matrix.platform.os != 'windows-11-arm' - # `--workspace` (formerly `--all`) is required because - # `default-members` in the root `Cargo.toml` restricts - # root-level cargo commands to the `mehen` package; the - # release matrix needs the full per-language suite to run. - run: cargo test --workspace + run: cargo test --all - name: Build wheels uses: PyO3/maturin-action@v1 with: command: build args: --release --out dist - # For glibc targets `manylinux: auto` would pick manylinux2014 - # (CentOS 7), whose newest clang is 3.4.2 — far below the 9.0+ - # that `ruby-prism-sys` → `bindgen 0.72` requires. Force `2_28` - # (AlmaLinux 8, glibc 2.28, clang 17+) — the current PyPA - # recommendation; pip ≥ 20.3 installs these wheels by default. - # For musl targets keep `auto` so maturin-action picks the - # `ghcr.io/rust-cross/rust-musl-cross` image — it bundles - # `*-linux-musl-gcc`, which the manylinux image does not. - manylinux: ${{ contains(matrix.platform.rust_target, 'musl') && 'auto' || '2_28' }} + manylinux: auto sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} target: ${{ matrix.platform.rust_target }} - # `ruby-prism-sys` invokes `bindgen` at build time, which - # requires `libclang` at runtime. Neither manylinux_2_28 - # (AlmaLinux 8, dnf) nor `rust-musl-cross` (Debian, apt) ship - # it preinstalled. - before-script-linux: | - if command -v dnf >/dev/null 2>&1; then - dnf install -y clang-devel - elif command -v apt-get >/dev/null 2>&1; then - apt-get update - apt-get install -y --no-install-recommends libclang-dev - else - echo "::error::No supported package manager found in build container" - exit 1 - fi - name: Build npm binary shell: bash env: - RUSTC_WRAPPER: "" - SCCACHE_CACHE_SIZE: "" + RUSTC_WRAPPER: '' + SCCACHE_CACHE_SIZE: '' run: | CURRENT_VERSION=$(taplo get -f Cargo.toml 'workspace.package.version') echo "Building npm binary for version: ${CURRENT_VERSION}" @@ -308,7 +279,7 @@ jobs: BINARY_NAME="mehen.exe" fi - cargo build --release --package mehen --target "$RUST_TARGET" + cargo build --release --package mehen-cli --target "$RUST_TARGET" BINARY_PATH="target/${RUST_TARGET}/release/${BINARY_NAME}" mkdir -p "target/npm-binaries/${RUST_TARGET}" @@ -572,9 +543,10 @@ jobs: find target/npm-binaries -type f | sort - name: Set up Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v5 with: - node-version: "24" + node-version: '22' + registry-url: 'https://registry.npmjs.org' - name: Update npm run: npm install -g npm@latest @@ -711,7 +683,7 @@ jobs: publish-to-pypi: name: Publish to PyPI - needs: [ publish-to-testpypi ] + needs: [publish-to-testpypi] runs-on: ubuntu-latest environment: name: pypi @@ -795,7 +767,7 @@ jobs: publish-to-npm: name: Publish to npm - needs: [ generate-npm-packages ] + needs: [generate-npm-packages] runs-on: ubuntu-latest environment: name: npm @@ -810,9 +782,10 @@ jobs: uses: actions/checkout@v5 - name: Set up Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v5 with: - node-version: "24" + node-version: '22' + registry-url: 'https://registry.npmjs.org' - name: Update npm run: npm install -g npm@latest @@ -823,27 +796,6 @@ jobs: name: npm-packages-${{ github.run_id }} path: npm-dist/ - - name: Restore executable bit on platform binaries - shell: bash - run: | - # actions/upload-artifact@v4 does not preserve Unix file modes, so - # the 0755 bits set by generate-npm-packages.js are lost during the - # upload/download round-trip. Re-apply +x before `npm publish` packs - # the tarballs — otherwise users get a silent permission-denied when - # the platform binary runs. - shopt -s nullglob - fixed=0 - for bin in npm-dist/@mehen/*/bin/mehen npm-dist/@mehen/*/bin/mehen.exe; do - chmod 0755 "$bin" - ls -la "$bin" - fixed=$((fixed + 1)) - done - if [[ "$fixed" -eq 0 ]]; then - echo "::error::No platform binaries found under npm-dist/@mehen/*/bin/" - exit 1 - fi - echo "Restored execute bit on ${fixed} platform binaries." - - name: Download version info uses: actions/download-artifact@v5 with: @@ -868,58 +820,3 @@ jobs: run: | VERSION=$(cat version.txt) node scripts/publish-npm.js "${VERSION}" ./npm-dist - - # Attach the CLI archives (built by the `build` matrix above) to the GitHub - # Release that release-please already created for this tag. This lives here — - # not in release-please.yml — because the archives and the tag context are - # both in-run, so no cross-workflow polling (and its timeout race) is needed. - # cargo-binstall, mise, and ubi install from these release assets. - upload-cli-binaries: - name: Upload CLI binaries to release - needs: build - # Only tag pushes have a release-please-created GitHub Release to attach to; - # workflow_dispatch (manual/test/preview) runs produce no such release. - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') - runs-on: ubuntu-latest - permissions: - contents: write - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - - steps: - - name: Download CLI archives - uses: actions/download-artifact@v5 - with: - pattern: cli-archive-*-${{ github.run_id }} - path: cli-archives/ - merge-multiple: true - - - name: Upload CLI archives to GitHub Release - shell: bash - run: | - TAG_NAME="${{ github.ref_name }}" - - # release-please creates the Release before the tag push triggers this - # workflow; create it defensively for manually pushed tags so the - # upload always has a target. - if ! gh release view "$TAG_NAME" >/dev/null 2>&1; then - echo "Release $TAG_NAME not found; creating it." - gh release create "$TAG_NAME" --title "$TAG_NAME" --generate-notes - fi - - shopt -s nullglob - uploaded=0 - for file in cli-archives/*; do - if [[ -f "$file" ]]; then - echo "Uploading: $(basename "$file")" - gh release upload "$TAG_NAME" "$file" --clobber - uploaded=$((uploaded + 1)) - fi - done - - if [[ "$uploaded" -eq 0 ]]; then - echo "::error::No CLI archives found to upload" - exit 1 - fi - echo "Uploaded ${uploaded} CLI archives to release: $TAG_NAME" diff --git a/.gitignore b/.gitignore index cd3a0fd4..17426395 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,3 @@ __pycache__/ *.egg-info/ dist/ .mypy_cache/ -.claude/worktrees/ -.claude/setting.local.json.DS_Store -.DS_Store -.env -target/llvm-cov/cobertura.xml diff --git a/.kiro/agents/kiro_default.json b/.kiro/agents/kiro_default.json deleted file mode 100644 index 06cf8b72..00000000 --- a/.kiro/agents/kiro_default.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name" : "kiro_default", - "description" : "Default agent for the mehen repo. Rust-focused, with skills loaded from .agents/skills (shared with other assistants).", - "prompt" : "You are the default Kiro agent for the mehen repository — a Rust CLI for heuristic source code metrics. Follow the repo's AGENTS.md and README conventions: keep metric behavior deterministic, never edit generated files (src/languages/language_*.rs), and prefer cargo nextest + cargo insta for verification. Use the loaded skills when their descriptions match the task.", - "resources" : [ "file://AGENTS.md", "file://README.md", "file://Cargo.toml", "skill://.agents/skills/**/SKILL.md" ], - "toolsSettings" : { - "execute_bash" : { - "autoAllowReadonly" : true, - "allowedCommands" : [ "cargo check", "cargo build", "cargo fmt --all", "cargo clippy --all-targets --all-features --locked", "cargo nextest run --all-features", "cargo insta test --all-features --check --unreferenced reject --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest" ] - } - }, - "welcomeMessage" : "mehen agent ready. Skills from .agents/skills are loaded (pr-comment, mintlify).", - "mcpServers" : { - "creds-agent" : { - "command" : "aim", - "args" : [ "mcp", "start-server", "local-creds-agent-mcp" ] - } - }, - "tools" : [ "@creds-agent" ], - "allowedTools" : [ "@creds-agent" ] -} \ No newline at end of file diff --git a/.kiro/settings/cli.json b/.kiro/settings/cli.json deleted file mode 100644 index 70f233f5..00000000 --- a/.kiro/settings/cli.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "chat.defaultModel": "claude-opus-4.7", - "chat.ui": "tui", - "chat.enableTodoList": true, - "chat.enableSubagent": true, - "chat.enableCodeIntelligence": true, - "chat.enableThinking": true -} \ No newline at end of file diff --git a/.kiro/settings/lsp.json b/.kiro/settings/lsp.json deleted file mode 100644 index 13fdde0c..00000000 --- a/.kiro/settings/lsp.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "languages": { - "rust": { - "name": "rust-analyzer", - "command": "rust-analyzer", - "args": [], - "file_extensions": [ - "rs" - ], - "project_patterns": [ - "Cargo.toml" - ], - "exclude_patterns": [ - "**/target/**" - ], - "multi_workspace": false, - "initialization_options": { - "cargo": { - "buildScripts": { - "enable": true - } - }, - "diagnostics": { - "enable": true, - "enableExperimental": true - }, - "workspace": { - "symbol": { - "search": { - "scope": "workspace" - } - } - } - }, - "request_timeout_secs": 60 - } - } -} \ No newline at end of file diff --git a/.pre-commit-audit-config.yaml b/.pre-commit-audit-config.yaml new file mode 100644 index 00000000..afd9750d --- /dev/null +++ b/.pre-commit-audit-config.yaml @@ -0,0 +1,14 @@ +# Use a separate pre-commit config that runs only when Rust dependencies +# are added, removed or modified. +repos: +- repo: local + hooks: + - id: audit + name: audit + language: system + files: 'Cargo\.lock|Cargo\.toml$' + entry: cargo audit + pass_filenames: false + +default_language_version: + python: python3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..603adf8e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,47 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + - id: check-json + exclude: enums/templates/json.json +- repo: https://github.com/marco-c/taskcluster_yml_validator + rev: v0.0.12 + hooks: + - id: taskcluster_yml +- repo: local + hooks: + # FIXME: Uncomment when fmt is fixed + # - id: fmt + # name: fmt + # language: system + # files: '\.rs$' + # exclude: '.*/templates/.*\.rs$' + # entry: cargo fmt -- --check --verbose + + - id: clippy + name: clippy + language: system + files: '\.rs$' + entry: cargo clippy --all-targets --all -- -D warnings + pass_filenames: false + + - id: udeps + name: udeps + language: system + files: '\.rs$' + entry: cargo +nightly udeps --all-targets + pass_filenames: false + + - id: test + name: test + language: system + files: '\.rs$' + entry: cargo test + pass_filenames: false + +default_language_version: + python: python3 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ce4f35c2..b7888c91 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.10.0" + ".": "0.0.1" } diff --git a/.serena/.gitignore b/.serena/.gitignore deleted file mode 100644 index 2e510aff..00000000 --- a/.serena/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/cache -/project.local.yml diff --git a/.serena/memories/conventions.md b/.serena/memories/conventions.md deleted file mode 100644 index d0032189..00000000 --- a/.serena/memories/conventions.md +++ /dev/null @@ -1,7 +0,0 @@ -# Conventions - -- Keep behavior centered on the `mehen` CLI binary; avoid library-only dead paths unless they are consumed by the CLI. -- Metric behavior should stay deterministic across platforms. -- Do not edit `crates/mehen-*/src/grammar.rs` directly; these are generated by `cargo xtask tree-sitter generate `. -- For grammar bumps or new tree-sitter-backed languages, update both `xtask/Cargo.toml` and the owning `crates/mehen-/Cargo.toml`, then regenerate with `cargo xtask tree-sitter generate --all`. -- Preserve mixed-worktree changes not made for the current task; stage only intended files when committing. \ No newline at end of file diff --git a/.serena/memories/core.md b/.serena/memories/core.md deleted file mode 100644 index 0e49e24c..00000000 --- a/.serena/memories/core.md +++ /dev/null @@ -1,7 +0,0 @@ -# Core - -- CLI-first Rust workspace for `mehen`; default cargo member is `crates/mehen-cli`, so plain `cargo build` / `cargo run` targets the binary. -- Workspace members are language analyzer crates plus shared crates: `mehen-core`, `mehen-metrics`, `mehen-tree-sitter`, `mehen-engine`, `mehen-git`, `mehen-report`, `mehen-cli`, and `xtask`. -- Read `mem:tech_stack` for language/tool pins and parser substrate notes. -- Read `mem:conventions` before editing analyzers or generated parser artifacts. -- Read `mem:suggested_commands` and `mem:task_completion` for local validation commands. \ No newline at end of file diff --git a/.serena/memories/memory_maintenance.md b/.serena/memories/memory_maintenance.md deleted file mode 100644 index 6f84514d..00000000 --- a/.serena/memories/memory_maintenance.md +++ /dev/null @@ -1,33 +0,0 @@ -# Memory Maintenance - -## Discovery Model - -- Core principle: progressive discovery through references, building a graph of memories. -- Initially, agents are provided with the list of all memories (names only). -- Agents should read `mem:core` as the top-level entry point (graph root). - This memory should contain references to other memories covering major project domains. - The referenced memories shall, in turn, shall contain references to even more specific memories, and so on. - The depth of the graph shall depend on the project complexity. -- Use topics/folders to group related memories in order to make the content structure explicit. - Folders can mirror project structure (e.g. modules like frontend/backend) or topics like debugging, architecture, etc. -- Memory references must use a mem: prefix inside backticks, e.g. `mem:frontend/core`. - The surrounding text should clearly indicate when to read the memory/which content to expect. - The text should provide more precise guidance than the memory name alone, - i.e. avoid a reference like "frontend debugging: `mem:frontend/debugging` and instead make clear which aspects of frontend debugging are covered. -- Memories themselves should not contain information about when to read them; this is the responsibility of the referring memory. - -## Style - -Dense agent notes, not prose docs. Prefer invariants, terse bullets. -Avoid obvious context, rationale, and examples unless they prevent likely mistakes. -Keep guidance durable and generalizable, not task-local. - -## Add/update threshold - -Add or update memories only with stable, non-obvious project conventions that avoid complex rediscovery in the future. -Do not add: quick-read facts; generic language/framework knowledge; one-off task notes; volatile line-level details; behavior likely to change soon. - -## Maintenance Actions - -- Renaming memories: References are updated automatically if handled via Serena's memory rename tool. -- Checking for stale memories (e.g. after deletion): Call `serena memories check` for a report. \ No newline at end of file diff --git a/.serena/memories/suggested_commands.md b/.serena/memories/suggested_commands.md deleted file mode 100644 index 96eb806f..00000000 --- a/.serena/memories/suggested_commands.md +++ /dev/null @@ -1,10 +0,0 @@ -# Suggested Commands - -- Build binary/default member: `cargo build` -- Type/check default member: `cargo check` -- Format workspace: `cargo fmt --all` -- Lint all targets/features with lockfile: `cargo clippy --all-targets --all-features --locked` -- Preferred test runner: `cargo nextest run --all-features` -- Snapshot check: `cargo insta test --all-features --check --unreferenced reject --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest` -- Snapshot review/update: `cargo insta test --all-features --review --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest` -- Tree-sitter generation: `cargo xtask tree-sitter generate ` or `cargo xtask tree-sitter generate --all`. \ No newline at end of file diff --git a/.serena/memories/task_completion.md b/.serena/memories/task_completion.md deleted file mode 100644 index e98c1e7a..00000000 --- a/.serena/memories/task_completion.md +++ /dev/null @@ -1,6 +0,0 @@ -# Task Completion - -- Standard code-change closeout from repo root: `cargo fmt --all`, `cargo check`, `cargo build`, `cargo clippy --all-targets --all-features --locked`. -- Run tests with `cargo nextest run --all-features`. -- For snapshot-sensitive changes, run `cargo insta test --all-features --check --unreferenced reject --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest`; use the review form only when intentionally updating snapshots. -- For parser generation work, regenerate with `cargo xtask tree-sitter generate ...` instead of hand-editing generated grammar files. \ No newline at end of file diff --git a/.serena/memories/tech_stack.md b/.serena/memories/tech_stack.md deleted file mode 100644 index ea4d9e49..00000000 --- a/.serena/memories/tech_stack.md +++ /dev/null @@ -1,7 +0,0 @@ -# Tech Stack - -- Rust workspace, edition 2024, rust-version 1.95.0. -- Root `Cargo.toml` pins shared dependencies; single-consumer dependencies are usually pinned in the owning crate. -- Tree-sitter remains the parser substrate for several language analyzers through `mehen-tree-sitter` and generated `grammar.rs` files. -- `xtask` is reached as `cargo xtask ...` via `.cargo/config.toml` and owns tree-sitter kind-enum generation. -- Snapshot testing uses `insta`; local test execution prefers `cargo nextest`. \ No newline at end of file diff --git a/.serena/project.yml b/.serena/project.yml deleted file mode 100644 index c8daa1db..00000000 --- a/.serena/project.yml +++ /dev/null @@ -1,169 +0,0 @@ -# the name by which the project can be referenced within Serena/when chatting with the LLM. -project_name: "mehen" - -# the encoding used by text files in the project -# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings -encoding: "utf-8" - -# line ending convention to use when writing source files. -# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) -# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. -line_ending: - -# The language backend to use for this project. -# If not set, the global setting from serena_config.yml is used. -# Valid values: LSP, JetBrains -# Note: the backend is fixed at startup. If a project with a different backend -# is activated post-init, an error will be returned. -language_backend: - -# whether to use project's .gitignore files to ignore files -ignore_all_files_in_gitignore: true - -# advanced configuration option allowing to configure language server-specific options. -# Maps the language key to the options. -# The settings are considered only if the project is trusted (see global configuration to define trusted projects). -# See https://oraios.github.io/serena/02-usage/050_configuration.html#language-server-specific-settings -ls_specific_settings: {} - -# list of additional paths to ignore in this project. -# Same syntax as gitignore, so you can use * and **. -# Important: quote patterns that start with `*`, otherwise YAML treats them as aliases. -# Example: -# ignored_paths: -# - "examples/**" -# - ".worktrees/**" -# - "**/bin/**" -# - "**/obj/**" -# Note: global ignored_paths from serena_config.yml are also applied additively. -ignored_paths: [] - -# whether the project is in read-only mode -# If set to true, all editing tools will be disabled and attempts to use them will result in an error -# Added on 2025-04-18 -read_only: false - -# list of tool names to exclude. -# This extends the existing exclusions (e.g. from the global configuration) -# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html -excluded_tools: [] - -# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default). -# This extends the existing inclusions (e.g. from the global configuration). -# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html -included_optional_tools: [] - -# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. -# This cannot be combined with non-empty excluded_tools or included_optional_tools. -# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html -fixed_tools: [] - -# list of mode names that are to be activated by default, overriding the setting in the global configuration. -# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes. -# If the setting is undefined/empty, the default_modes from the global configuration (serena_config.yml) apply. -# Otherwise, this overrides the setting from the global configuration (serena_config.yml). -# Therefore, you can set this to [] if you do not want the default modes defined in the global config to apply -# for this project. -# This setting can, in turn, be overridden by CLI parameters (--mode). -# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes -default_modes: - -# list of mode names to be activated additionally for this project, e.g. ["query-projects"] -# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes. -# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes -added_modes: - -# initial prompt for the project. It will always be given to the LLM upon activating the project -# (contrary to the memories, which are loaded on demand). -initial_prompt: "" - -# time budget (seconds) per tool call for the retrieval of additional symbol information -# such as docstrings or parameter information. -# This overrides the corresponding setting in the global configuration; see the documentation there. -# If null or missing, use the setting from the global configuration. -symbol_info_budget: - -# list of regex patterns which, when matched, mark a memory entry as read‑only. -# Extends the list from the global configuration, merging the two lists. -read_only_memory_patterns: [] - -# list of regex patterns for memories to completely ignore. -# Matching memories will not appear in list_memories or activate_project output -# and cannot be accessed via read_memory or write_memory. -# To access ignored memory files, use the read_file tool on the raw file path. -# Extends the list from the global configuration, merging the two lists. -# Example: ["_archive/.*", "_episodes/.*"] -ignored_memory_patterns: [] - -# list of additional workspace folder paths for cross-package reference support. -# Paths can be absolute or relative to the project root. -# Each folder is registered as an LSP workspace folder, enabling language servers to discover -# symbols and references across package boundaries, but these folders are not indexed by Serena, -# i.e. the respective symbols will not be found using Serena's symbol search tools. -# Example: -# additional_workspace_folders: -# - ../sibling-package -# - ../shared-lib -ls_additional_workspace_folders: [] - -# list of language servers to start when using the LSP backend; choose from: -# ada al angular ansible bash -# bsl clojure cpp cpp_ccls crystal -# csharp csharp_omnisharp cue dart deno -# elixir elm erlang fortran fsharp -# gdscript gleam go groovy haskell -# haxe hlsl html java json -# julia kotlin latex lean4 lua -# luau markdown matlab msl nextflow -# nix ocaml pascal perl php -# php_phpactor php_phpantom powershell python python_basedpyright -# python_jedi python_pyrefly python_ty qml r -# rego ruby ruby_solargraph rust scala -# scss solidity svelte swift systemverilog -# terraform toml typescript typescript_vts vue -# wolfram yaml zig -# (This list may be outdated; generated with scripts/print_language_list.py; -# For the current list, see values of the LanguageServerId enum here: -# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py) -# For some languages, there are several alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) -# Note: -# - For C, use cpp -# - For JavaScript, use typescript -# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root) -# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm) -# - For Deno projects, use deno (serves the same .ts/.js files as typescript; requires the deno CLI on PATH) -# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three) -# - For Free Pascal/Lazarus, use pascal -# Special requirements: -# Some language servers require additional setup/installations. -# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers -# When using multiple language servers, the first language server that supports a given file will be used for that file. -# The first language server is the default language and the respective language server will be used as a fallback. -# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. -language_servers: -- rust - -# list of workspace folder paths (LSP backend only). -# These folders will be used to build up Serena's symbol index. -# Paths must be within the project root and should thus be relative to the project root. -# Furthermore, the paths should not be filtered by ignore settings. -# Default setting: The entire project root folder (".") is considered. -# In (large) monorepos, this can be used to index only subfolders of the project root, e.g. -# ls_workspace_folders: -# - "./subproject1" -# - "./subproject2" -ls_workspace_folders: -- . - -# optional shell command to run before the language backend (LSP or JetBrains) is initialised. -# the command runs in the project root directory and is only executed if the project is trusted -# (see trusted_project_path_patterns in the global configuration). -# serena waits for the command to exit: a non-zero exit code is logged as an error but does not -# abort activation. a per-project timeout (activation_command_timeout, default 180s) is the safety -# backstop for non-terminating commands; on expiry the process is killed and activation continues. -# example: activation_command: "npx nx run-many -t build" -activation_command: - -# maximum time in seconds to wait for activation_command to complete before killing it (default 180s). -# must be a positive number. -activation_command_timeout: 180.0 diff --git a/.typos.toml b/.typos.toml index 3bbbfda5..79ea15e3 100644 --- a/.typos.toml +++ b/.typos.toml @@ -1,36 +1,4 @@ -# https://github.com/crate-ci/typos -# cargo install typos-cli -# typos -[files] -# https://github.com/crate-ci/typos/issues/868 -extend-exclude = [ - "tree-sitter-*/examples/", - "**/CHANGELOG.md", - "**/snapshots/**/*", - # Machine-generated ANTLR lexer/parser modules and the vendored `.g4` - # grammars they're generated from. These are not hand-authored prose — - # Unicode class names like `UNICODE_CLASS_ND` trip the spell checker - # (`ND` -> `AND`). Same rationale as the generated-snapshot exclude - # above; regenerate via `cargo xtask antlr generate `. - "**/src/generated/**", - # Hand-written `.g4.in` fragments spliced into the generated grammar carry - # the same Unicode class names, and the standalone `repro/` grammars are - # generated copies of the C# pair. - "crates/mehen-*/grammar/*.g4", - "crates/mehen-*/grammar/*.g4.in", - "repro/**/*.g4", - # Prose-metric dictionaries intentionally contain non-words, cliches, - # hedges, and weasel phrases for the analyzer to flag. Excluding them - # from typo checking keeps the analyzer lists authoritative. - "crates/mehen-markdown/src/data/nonwords.txt", - "crates/mehen-markdown/src/data/cliches.txt", - "crates/mehen-markdown/src/data/hedges.txt", - "crates/mehen-markdown/src/data/weasels.txt", - "crates/mehen-markdown/src/data/wordy_phrases.txt", - "crates/mehen-markdown/src/data/inclusive_flags.txt", - "crates/mehen-markdown/src/data/ja_weak_phrases.txt", - "crates/mehen-markdown/src/data/ja_redundant.txt", -] +# See https://github.com/crate-ci/typos/blob/master/docs/reference.md to configure typos [default.extend-identifiers] # Common Rust abbreviation for "type" (reserved keyword) @@ -38,57 +6,13 @@ typ = "typ" typs = "typs" typs1 = "typs1" typs2 = "typs2" -# Short for "inherited" in lang_detect.rs block-language inheritance logic. -inh = "inh" [default.extend-words] -# Intentional misspellings in negative-path tests for the `--fail-on` -# value parser (`src/diff.rs` rejects unknown names via clap). -borken = "borken" -hihg = "hihg" -# Intentional typo in the negative-path test for `history.*` selector -# validation (`metric_selector.rs` rejects unknown history keys). -frequncy = "frequncy" -# Intentional typo in the negative-path test for the SQL published-key -# catalogue (`mehen-sql` rejects unknown `sql.statement.kind_count.*` -# members). -selec = "selec" # Intentional name of a removed language parser Ccomment = "Ccomment" -"Winn" = "Winn" -"ALOC" = "ALOC" -"ine" = "ine" -"Hge" = "Hge" -"ccontains" = "ccontains" -"Seh" = "Seh" -# Readability formula by Caylor, Sticht, Fox & Ford (1973) — proper noun -"FORCAST" = "FORCAST" -"forcast" = "forcast" -# Proper noun: Jean Ure (lexical density, 1971) -"Ure" = "Ure" -# Proper noun: Yukio Ono (Japanese readability, Tateishi/Ono/Yamada 1988) -"Ono" = "Ono" -# Acronym for Wording Quality Score (§33.11, §36.7) -"WQS" = "WQS" -# Journal abbreviation: Information and Software Technology (Radjenović et al. -# 2013 citation in design-docs/mehen_post_classical_metrics_research_foundation.md) -"IST" = "IST" -# Proper noun: Automattic (harper Rust grammar checker vendor) -"Automattic" = "Automattic" -# Suffix-pattern fragment cited in §33.6 nominalizations (-ment) -"ment" = "ment" -"Dereferencable" = "Dereferencable" -"ue" = "ue" -"mis" = "mis" -"Hashi" = "Hashi" -"requireds" = "requireds" -# Deliberately malformed SQL keyword in the error-recovery probe input quoted -# by design-docs/sql_parser_comparison.md §8.2. The misspelling *is* the test: -# it is what makes `sqlparser::Parser::parse_sql` return a hard `Err` while -# sqruff recovers with an `Unparsable` node. Keep verbatim so the probe stays -# reproducible. -"SELCT" = "SELCT" -# Latin-1 "café" written as raw bytes (`b"# caf\xe9\n"`) in non-UTF-8 -# fixture files across the git-history tests; the invalid byte splits -# the word and the checker sees a bare `caf`. -"caf" = "caf" + +[files] +extend-exclude = [ + "enums/data/", + "tree-sitter-*/examples/", +] diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 6551b491..00000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "recommendations": [ - "tekumara.typos-vscode" - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e4103040..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "sarif-viewer.connectToGithubCodeScanning": "off", - "cSpell.enabled": false -} \ No newline at end of file diff --git a/.zed/settings.json b/.zed/settings.json deleted file mode 100644 index 83c93644..00000000 --- a/.zed/settings.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "tasks": { - "prefer_lsp": true, - }, - "project_name": "Mehen - Code Quality Watcher", - "semantic_tokens": "combined", - "lsp": { - "rust-analyzer": { - "initialization_options": { - "check": { - "command": "clippy" - }, - "cargo": { - "allFeatures": true - } - }, - "enable_lsp_tasks": true, - }, - "pkl": { - "enable_lsp_tasks": true, - }, - }, - "format_on_save": "on", - "formatter": "language_server", -} diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 380c2d94..00000000 --- a/AGENTS.md +++ /dev/null @@ -1,48 +0,0 @@ -# AGENTS - -## Scope - -This repository is a CLI-first Rust project (`mehen`). Prefer changes that keep behavior centered on the `mehen` binary. - -## Educational and Research Objective - -mehen's heuristic source-code metrics are also an educational and research instrument, not just a CI gate. When touching metrics: - -- When adding a new metric or improving an existing one, close the explainability gap: emit contribution evidence (`MetricEvidence` — span + reason code + amount) so output can answer *why* a value moved, and keep the evidence-sum invariants in each crate's `tests/contributions.rs` intact. -- Keep errors and warnings approachable for users without deep metrics knowledge — concise yet explanatory messaging over jargon or bare codes. -- Every metric page under `docs/metrics/` keeps a schoolbook style — scientific but teaching-oriented — with high-quality paper links in its `## References` section. - -## Build and Test - -Use these commands from the repo root: - -```bash -cargo build -cargo check -cargo fmt --all -cargo clippy --all-targets --all-features --locked -``` - -## Recommended Test Runner - -Use `nextest` as the default test runner for local and CI work. - -```bash -cargo nextest run --all-features -``` - -## Snapshot Tests (insta) - -`insta` is used heavily in metric tests. Prefer running snapshot checks via `cargo insta` on top of `nextest`: - -```bash -cargo insta test --all-features --check --workspace --unreferenced reject --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest -``` - -## Notes for Code Changes - -- Keep metric behavior deterministic across platforms. -- Avoid introducing dead code paths; this project is consumed as a CLI. -- Never edit `crates/mehen-*/src/grammar.rs` directly: these files are generated by `cargo xtask tree-sitter generate `. This applies only to tree-sitter-backed crates; `mehen-markdown` is `pulldown-cmark`-backed and has no `grammar.rs` — its node-kind enum in `crates/mehen-markdown/src/kind.rs` is hand-authored and edited directly. -- For grammar bumps or new tree-sitter-backed languages, update the pin in both `xtask/Cargo.toml` and the owning `crates/mehen-/Cargo.toml`, then regenerate with `cargo xtask tree-sitter generate --all`. -- Keep the workspace `antlr-rust-runtime` and `antlr-rust-codegen` pins in lockstep. xtask links codegen directly; after either pin changes, run `cargo xtask antlr generate --all` and commit every generated parser artifact. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 2a68a018..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,439 +0,0 @@ -# Changelog - -## [1.10.0](https://github.com/ophi-dev/mehen/compare/v1.9.0...v1.10.0) (2026-08-19) - - -### Features - -* base coverage for mehen diff via action retrieval (cache + codecov) ([#250](https://github.com/ophi-dev/mehen/issues/250)) ([b8d2d8a](https://github.com/ophi-dev/mehen/commit/b8d2d8a46686eb84c3603934c0de7d87cd8f27b0)) -* coverage metric category — ingestion, auto-discovery, gates ([#246](https://github.com/ophi-dev/mehen/issues/246)) ([a2ac86a](https://github.com/ophi-dev/mehen/commit/a2ac86abbe3f3b2201c4200684f101f1339448b0)) - -## [1.9.0](https://github.com/ophi-dev/mehen/compare/v1.8.1...v1.9.0) (2026-08-17) - - -### Features - -* add mehen.toml per-metric threshold gates ([#243](https://github.com/ophi-dev/mehen/issues/243)) ([cf606c2](https://github.com/ophi-dev/mehen/commit/cf606c2087e3bb019a567526a4e06a5664541125)) -* git history metrics family + history-aware default PR-comment columns ([#236](https://github.com/ophi-dev/mehen/issues/236)) ([cf64502](https://github.com/ophi-dev/mehen/commit/cf645020abcc615914bc28abab59a9c6834e199f)) -* upgrade antlr-rust-runtime to 0.33.1, adopt generated drivers ([#245](https://github.com/ophi-dev/mehen/issues/245)) ([5ebcac3](https://github.com/ophi-dev/mehen/commit/5ebcac39beeb90eda861dfc40d07d78c11ca57d0)) - - -### Bug Fixes - -* address PR review comment ([885ec7e](https://github.com/ophi-dev/mehen/commit/885ec7edda10f055ce4931a57a583354d10f9c12)) -* address PR review comments ([2267dc3](https://github.com/ophi-dev/mehen/commit/2267dc3ec91f9080be9769fa11bda9f62372bfc5)) -* **csharp:** attribute a primary constructor's whole header to its space ([d2e91c3](https://github.com/ophi-dev/mehen/commit/d2e91c3cdc0a4e7641ce0c8e001dac292a96cc02)), closes [#219](https://github.com/ophi-dev/mehen/issues/219) -* **csharp:** parse a local generic declaration as a declaration ([5a03880](https://github.com/ophi-dev/mehen/commit/5a038802753ae1cf1932c947119ff9b69ce7b9fa)), closes [#218](https://github.com/ophi-dev/mehen/issues/218) -* **csharp:** stop constructor attribution at the base-constructor call ([0a3dd76](https://github.com/ophi-dev/mehen/commit/0a3dd761cc539bee8d37cf0573579b19ed227b33)) -* **kotlin:** stop prefix ! from breaking a cognitive boolean run ([5afc2ab](https://github.com/ophi-dev/mehen/commit/5afc2ab7e02a4a6526cdeea1e4a03391dd694613)), closes [#217](https://github.com/ophi-dev/mehen/issues/217) - - -### Parser & Grammar Updates - -* bump mago-syntax-core from 1.45.0 to 1.46.0 in the mago group ([#240](https://github.com/ophi-dev/mehen/issues/240)) ([d81ab22](https://github.com/ophi-dev/mehen/commit/d81ab22a601fd681991d61f5d4b9a16e713be1a4)) -* bump ra_ap_syntax from 0.0.345 to 0.0.347 ([#242](https://github.com/ophi-dev/mehen/issues/242)) ([2019f23](https://github.com/ophi-dev/mehen/commit/2019f2328d6b034650f3d985cea67e2f20a1dd0a)) -* bump the mago group with 4 updates ([#231](https://github.com/ophi-dev/mehen/issues/231)) ([139a972](https://github.com/ophi-dev/mehen/commit/139a972a96c52109384832eef91cab020563ebe7)) -* bump the oxc group with 6 updates ([#239](https://github.com/ophi-dev/mehen/issues/239)) ([c8191b1](https://github.com/ophi-dev/mehen/commit/c8191b1637969190273c29ad45d7263788e371c8)) -* bump tree-sitter from 0.26.11 to 0.26.12 in the tree-sitter group ([#238](https://github.com/ophi-dev/mehen/issues/238)) ([78d12ed](https://github.com/ophi-dev/mehen/commit/78d12ed2efcdd793892bbf6587d0156056cee022)) - -## [1.8.1](https://github.com/ophi-dev/mehen/compare/v1.8.0...v1.8.1) (2026-08-05) - - -### Parser & Grammar Updates - -* bump mago-syntax-core from 1.43.0 to 1.45.0 in the mago group ([#222](https://github.com/ophi-dev/mehen/issues/222)) ([1e1ec8c](https://github.com/ophi-dev/mehen/commit/1e1ec8ce6eaf9db56d9b48cef6f29a01f7aae5f7)) -* bump ra_ap_syntax from 0.0.344 to 0.0.345 ([#224](https://github.com/ophi-dev/mehen/issues/224)) ([4cf4f36](https://github.com/ophi-dev/mehen/commit/4cf4f36fc69d5f3334e3cc0ae79ec3a4dd559094)) -* bump the oxc group with 6 updates ([#221](https://github.com/ophi-dev/mehen/issues/221)) ([cb6fd54](https://github.com/ophi-dev/mehen/commit/cb6fd54daad22c11ac8795f3b58ec13a7e6a0722)) - -## [1.8.0](https://github.com/ophi-dev/mehen/compare/v1.7.0...v1.8.0) (2026-08-03) - - -### Features - -* **antlr:** upgrade runtime to 0.18.0 + exact JavaParserBase predicate semantics ([#211](https://github.com/ophi-dev/mehen/issues/211)) ([d91a556](https://github.com/ophi-dev/mehen/commit/d91a55607cf91fdb869d20b23ab13333f4769b7a)) -* **parser-crates:** generate consume-me READMEs from a shared template ([bb00c4f](https://github.com/ophi-dev/mehen/commit/bb00c4f3f1feeea85d844846bc35d5691b9b157b)) - - -### Parser & Grammar Updates - -* bump ra_ap_syntax from 0.0.342 to 0.0.343 ([#205](https://github.com/ophi-dev/mehen/issues/205)) ([a504bb0](https://github.com/ophi-dev/mehen/commit/a504bb0a412e2f69be838aaa1cda6e2c7bf0883e)) -* bump ra_ap_syntax from 0.0.343 to 0.0.344 ([#215](https://github.com/ophi-dev/mehen/issues/215)) ([ebb0399](https://github.com/ophi-dev/mehen/commit/ebb03993729eba4f39f32381e57bb33f929c6428)) -* bump the mago group with 3 updates ([#203](https://github.com/ophi-dev/mehen/issues/203)) ([d132408](https://github.com/ophi-dev/mehen/commit/d1324084f75413c088c0efe063026aaa8030e9f2)) -* bump the oxc group with 6 updates ([#202](https://github.com/ophi-dev/mehen/issues/202)) ([fe0bff8](https://github.com/ophi-dev/mehen/commit/fe0bff8e1b610705e3db80fc0eb4c5a2daf5df6c)) -* bump the oxc group with 6 updates ([#214](https://github.com/ophi-dev/mehen/issues/214)) ([f77b1c3](https://github.com/ophi-dev/mehen/commit/f77b1c3d43e24ebb6c777251f42c417111e26f84)) - -## [1.7.0](https://github.com/ophi-dev/mehen/compare/v1.6.0...v1.7.0) (2026-07-24) - - -### chore - -* release 1.7.0 ([db1ad1d](https://github.com/ophi-dev/mehen/commit/db1ad1d8a479c5edb1d9289c63ef6f1fbdb1a104)) - -## [1.6.0](https://github.com/ophi-dev/mehen/compare/v1.5.1...v1.6.0) (2026-07-21) - - -### chore - -* release 1.6.0 ([67952a9](https://github.com/ophi-dev/mehen/commit/67952a92211a446692e218a253b327ddb05a9383)) - -## [1.5.1](https://github.com/ophi-dev/mehen/compare/v1.5.0...v1.5.1) (2026-07-19) - - -### Bug Fixes - -* import Parser trait in -parser crate doctests + guard doctests in CI ([1e0fb40](https://github.com/ophi-dev/mehen/commit/1e0fb40d30ae6ff0af719280f11705ca16cafb9e)) - -## [1.5.0](https://github.com/ophi-dev/mehen/compare/v1.4.1...v1.5.0) (2026-07-19) - - -### Features - -* publishable mehen-<lang>-parser crates + antlr-rust-runtime 0.13.0 upgrade ([#189](https://github.com/ophi-dev/mehen/issues/189)) ([af45797](https://github.com/ophi-dev/mehen/commit/af45797779c7ed6100e734516b88d18796939346)) - -## [1.4.1](https://github.com/ophi-dev/mehen/compare/v1.4.0...v1.4.1) (2026-07-18) - - -### Parser & Grammar Updates - -* bump mago-syntax from 1.42.0 to 1.43.0 in the mago group ([#179](https://github.com/ophi-dev/mehen/issues/179)) ([575f1a1](https://github.com/ophi-dev/mehen/commit/575f1a17c20a0a6c5c16ca386097c61ef7485af6)) -* bump ra_ap_syntax from 0.0.341 to 0.0.342 ([#188](https://github.com/ophi-dev/mehen/issues/188)) ([6c5d952](https://github.com/ophi-dev/mehen/commit/6c5d9529bde876c85c0c9c1d52dd9ac1790a6dd8)) -* bump the oxc group with 6 updates ([#184](https://github.com/ophi-dev/mehen/issues/184)) ([5a23f0c](https://github.com/ophi-dev/mehen/commit/5a23f0c1e078b353da4ae1ecbd75ec326e86191e)) -* bump the ruff group with 3 updates ([#180](https://github.com/ophi-dev/mehen/issues/180)) ([7b6748a](https://github.com/ophi-dev/mehen/commit/7b6748a4b3326315ccea56a9a5408f2dd9e24dea)) -* bump tree-sitter from 0.26.10 to 0.26.11 in the tree-sitter group ([#183](https://github.com/ophi-dev/mehen/issues/183)) ([07a8968](https://github.com/ophi-dev/mehen/commit/07a89686aba86ef439037538d4c3e2bf55ff3d44)) - -## [1.4.0](https://github.com/ophi-dev/mehen/compare/v1.3.0...v1.4.0) (2026-07-10) - - -### Features - -* **metrics:** explain SQL change risk contributions ([#176](https://github.com/ophi-dev/mehen/issues/176)) ([e67f380](https://github.com/ophi-dev/mehen/commit/e67f3805f931f93dcd10fd5a5f4a11b19ef1afc3)) - -## [1.3.0](https://github.com/ophi-dev/mehen/compare/v1.2.0...v1.3.0) (2026-07-07) - - -### Features - -* add Java analyzer and upgrade antlr-rust-runtime to 0.6.3 ([#160](https://github.com/ophi-dev/mehen/issues/160)) ([3ec7ccb](https://github.com/ophi-dev/mehen/commit/3ec7ccb2724fdc32528ab39a7d80b015bede38e2)) - -## [1.2.0](https://github.com/ophi-dev/mehen/compare/v1.1.0...v1.2.0) (2026-07-02) - - -### Features - -* **sql:** SQL metrics analyzer (mehen-sql, sqruff-backed) ([#152](https://github.com/ophi-dev/mehen/issues/152)) ([1ff3be5](https://github.com/ophi-dev/mehen/commit/1ff3be549259c36d439b3a01fe5090caf17d4e7b)) - -## [1.1.0](https://github.com/ophi-dev/mehen/compare/v1.0.2...v1.1.0) (2026-06-22) - - -### Features - -* **kotlin:** replace tree-sitter with ANTLR backend ([#149](https://github.com/ophi-dev/mehen/issues/149)) ([bc0f7fc](https://github.com/ophi-dev/mehen/commit/bc0f7fc1ff827f2dadb387da558661985f801185)) - -## [1.0.0](https://github.com/ophi-dev/mehen/compare/v1.0.0...v1.0.0) (2026-06-01) - - -### ⚠ BREAKING CHANGES - -* **metrics:** close class-metric gaps, remove --ops/--comments ([#65](https://github.com/ophi-dev/mehen/issues/65)) -* **diff:** `mehen diff --metrics mi` (and the action's `metrics:` / `thresholds:` keys referencing `mi`, `maintainability`, or `maintainabilityindex`) no longer resolve — pick an explicit variant (`mi.original`, `mi.sei`, `mi.visual_studio`). Users relying on the default automatically get `mi.visual_studio` now. - -### Features - -* **action:** retitle comment, add ABC default, auto-exclude tests ([#60](https://github.com/ophi-dev/mehen/issues/60)) ([67225e1](https://github.com/ophi-dev/mehen/commit/67225e1b8eaefae9a46f4d686daf2c0075998b29)) -* add `mehen diff` subcommand ([#24](https://github.com/ophi-dev/mehen/issues/24)) ([abcbd57](https://github.com/ophi-dev/mehen/commit/abcbd5777d4326429503e47f407aeef4127cd095)) -* add reusable mehen metrics action ([#55](https://github.com/ophi-dev/mehen/issues/55)) ([b30c91a](https://github.com/ophi-dev/mehen/commit/b30c91aa184a6d04c8e8e707c0a59ff26cfd67e3)) -* add Ruby language support ([#57](https://github.com/ophi-dev/mehen/issues/57)) ([a88bb87](https://github.com/ophi-dev/mehen/commit/a88bb8753859bacb704e0b46068d69197d6c6ed1)) -* align Go metrics with language semantics ([#59](https://github.com/ophi-dev/mehen/issues/59)) ([427393e](https://github.com/ophi-dev/mehen/commit/427393ed2535cff530cd1ef7068f66f64686a54e)) -* **cli:** add --version --json and surface version in action footer ([#77](https://github.com/ophi-dev/mehen/issues/77)) ([a233b3f](https://github.com/ophi-dev/mehen/commit/a233b3f5abf49a65aaf0b464c34ecade28528825)) -* **cli:** add top-offenders subcommand ([#71](https://github.com/ophi-dev/mehen/issues/71)) ([00e4bf0](https://github.com/ophi-dev/mehen/commit/00e4bf00ab254094c5b5e0a23cff23029b8fd05e)) -* **diff:** add Markdown Documentation Metrics section to PR comment (§39) ([#89](https://github.com/ophi-dev/mehen/issues/89)) ([2742bc4](https://github.com/ophi-dev/mehen/commit/2742bc4ffc7d48e0a964c1d699552469652f3451)) -* **diff:** split mi into mi.original/mi.sei/mi.visual_studio, default to Visual Studio ([#64](https://github.com/ophi-dev/mehen/issues/64)) ([7c8e4bc](https://github.com/ophi-dev/mehen/commit/7c8e4bc9c7b75bd5ed483017d7b0a598e4be55bc)) -* **langs:** add C language support ([#80](https://github.com/ophi-dev/mehen/issues/80)) ([954bb9b](https://github.com/ophi-dev/mehen/commit/954bb9b7da8d16c0733dc7a48ad428b67f16c655)) -* **langs:** route JavaScript/JSX through TypeScript/TSX grammars ([#79](https://github.com/ophi-dev/mehen/issues/79)) ([229f37d](https://github.com/ophi-dev/mehen/commit/229f37d0ae732025ddeb17ceeb21c6478c037356)) -* **markdown:** add EN+JA prose metric layer (Tier 0, §§29-38) ([#85](https://github.com/ophi-dev/mehen/issues/85)) ([3108e26](https://github.com/ophi-dev/mehen/commit/3108e266cbc3a61470ca6df94214e8b2fd9eb2a7)) -* **markdown:** add grounding, evidence, filler risk, RCI, section balance, good scaffold (§§15–21) ([#87](https://github.com/ophi-dev/mehen/issues/87)) ([6fba906](https://github.com/ophi-dev/mehen/commit/6fba9063cebbff4323548086aaee9d24cce1bb01)) -* **markdown:** add link debt, visual scaffold, table burden, and artifact debt (§§11–14, §19) ([#84](https://github.com/ophi-dev/mehen/issues/84)) ([8e86186](https://github.com/ophi-dev/mehen/commit/8e861861ee50b077dc35278ea9815b71b9f431cb)) -* **markdown:** add MRPC, MCC, Markdown Halstead, and DMI core (§§7–10) ([#83](https://github.com/ophi-dev/mehen/issues/83)) ([9e6eef0](https://github.com/ophi-dev/mehen/commit/9e6eef0a51468a80e5337fa60d73cf11a810c4d6)) -* **metrics:** add Kotlin language support ([#66](https://github.com/ophi-dev/mehen/issues/66)) ([f543cef](https://github.com/ophi-dev/mehen/commit/f543cefa1cb0afd1a01a2c7d3a2a07f04f565990)) -* **metrics:** add PowerShell language support ([#69](https://github.com/ophi-dev/mehen/issues/69)) ([47b17ac](https://github.com/ophi-dev/mehen/commit/47b17ac4494c9687937b57460be0cda8a1db749e)) -* **metrics:** close class-metric gaps, remove --ops/--comments ([#65](https://github.com/ophi-dev/mehen/issues/65)) ([cee0526](https://github.com/ophi-dev/mehen/commit/cee0526b59dc1c46258edae8e8f654749830a727)) -* **metrics:** gate wmc/npa/npm by language applicability ([#61](https://github.com/ophi-dev/mehen/issues/61)) ([e4c7cc9](https://github.com/ophi-dev/mehen/commit/e4c7cc959f0ef1f0c1a2878ad4965bd1c674b8c3)) -* **php:** add PHP language support ([3cddaf2](https://github.com/ophi-dev/mehen/commit/3cddaf227f7bc674829b5a10145b2de3b72502fd)) -* support cargo binstall via GitHub Release archives ([#122](https://github.com/ophi-dev/mehen/issues/122)) ([5f6ff3a](https://github.com/ophi-dev/mehen/commit/5f6ff3a3694dec2711d5886cc0aa3d46a24554ae)) - - -### Bug Fixes - -* address PR review comment ([62a7b95](https://github.com/ophi-dev/mehen/commit/62a7b9582fc1ee4cd6bef72823ba03d7d3c29761)) -* address PR review comment ([4af0199](https://github.com/ophi-dev/mehen/commit/4af0199ae644200c0fa5623016ad959c84ba1bd1)) -* address PR review comment ([e74731a](https://github.com/ophi-dev/mehen/commit/e74731a885eb672eebc00c97eb82a12995db1cc5)) -* address PR review comment ([a9d5571](https://github.com/ophi-dev/mehen/commit/a9d5571482a86191ffa3706ba02b4bec6cb5289c)) -* address PR review comment ([3dbcfb4](https://github.com/ophi-dev/mehen/commit/3dbcfb48e27a14fd020bdec3f3374886bb93d9a4)) -* address PR review comment ([ba68728](https://github.com/ophi-dev/mehen/commit/ba68728fecd66b786372a6aa2922f24d73ad6d19)) -* address PR review comment ([1b764e7](https://github.com/ophi-dev/mehen/commit/1b764e73824a16da7d1a333e123bb606d5de4632)) -* address PR review comment ([4a6eca8](https://github.com/ophi-dev/mehen/commit/4a6eca8914e971c54dfa82d146f8b3eff837aa63)) -* address PR review comments ([12eb0d5](https://github.com/ophi-dev/mehen/commit/12eb0d54c9b6db022858f48201d6fd453296bef2)) -* address PR review comments ([f9b0ee3](https://github.com/ophi-dev/mehen/commit/f9b0ee39e94e3624267d943b814a93d3affc9029)) -* check PR author instead of event actor in regeneration workflow ([62c82e4](https://github.com/ophi-dev/mehen/commit/62c82e45ee5cea86ae0e460d42ea0b3f4f990aa8)) -* **ci:** bump wheel build to manylinux_2_28 for modern libclang ([c5040d2](https://github.com/ophi-dev/mehen/commit/c5040d26a8be9b9604c0e270d62134f8ab13880c)) -* **ci:** install libclang in maturin wheel build container ([9645c9f](https://github.com/ophi-dev/mehen/commit/9645c9fa99f9b2f596be0918440e4d4ba5999dfe)) -* **ci:** remove broken npm@11 global install from static-analysis ([#48](https://github.com/ophi-dev/mehen/issues/48)) ([7f4cae8](https://github.com/ophi-dev/mehen/commit/7f4cae81b1f018de380d0f98419398489a894e1f)) -* handle unmapped Unicode chars in enum generator ([#15](https://github.com/ophi-dev/mehen/issues/15)) ([c972b1d](https://github.com/ophi-dev/mehen/commit/c972b1d451b0cf3bfc3df372213ded864034a056)) -* **metrics:** align cyclomatic and cognitive with language semantics ([#63](https://github.com/ophi-dev/mehen/issues/63)) ([e3f436d](https://github.com/ophi-dev/mehen/commit/e3f436d70794ea71d51d415189c723de7f7ab78f)) -* **npm:** restore +x on platform binaries and surface spawn errors ([#75](https://github.com/ophi-dev/mehen/issues/75)) ([b5f6104](https://github.com/ophi-dev/mehen/commit/b5f610476db964e999427c797bab4cd04ce9b43c)) -* Rust metric edge cases ([#73](https://github.com/ophi-dev/mehen/issues/73)) ([63238d2](https://github.com/ophi-dev/mehen/commit/63238d2729788ee9d7318a3af0ce53973233f1f5)) -* trigger on Cargo.lock ([24e216e](https://github.com/ophi-dev/mehen/commit/24e216e0571ab8fff247009ef4fa9d6b67c1c432)) -* update README.md ([87ea2b1](https://github.com/ophi-dev/mehen/commit/87ea2b1685d7436bcf9818064047ccb46e4a060c)) -* update typos config ([8b8bc9b](https://github.com/ophi-dev/mehen/commit/8b8bc9b3cc485bad5be4696d13bae6f88a64ba4b)) -* use GitHub App token in release-please workflow ([#20](https://github.com/ophi-dev/mehen/issues/20)) ([8db91a5](https://github.com/ophi-dev/mehen/commit/8db91a523d36fe949a4ff32e5e650c4a8fae7a09)) - - -### Miscellaneous Chores - -* release 0.1.1 ([8f32dba](https://github.com/ophi-dev/mehen/commit/8f32dba7a28775b7cf7f71e2f8c9e1d5fd5dc647)) -* release 0.3.0 ([7041e4c](https://github.com/ophi-dev/mehen/commit/7041e4cfdcd33a7e44bbe82d338c1f9f1016b362)) -* release 0.4.0 ([8b7a4d3](https://github.com/ophi-dev/mehen/commit/8b7a4d3ec847aa5d003aa5513aa6e893b6ab3851)) -* release 0.5.0 ([e0befc2](https://github.com/ophi-dev/mehen/commit/e0befc2e743a3be82f4eca7930146302d7d573d3)) -* release 1.0.0 ([285b16a](https://github.com/ophi-dev/mehen/commit/285b16aff747298d1ff3e3085fc2b949850f7ecb)) - -## [1.0.0](https://github.com/ophidiarium/mehen/compare/v0.7.0...v1.0.0) (2026-06-01) - - -### ⚠ BREAKING CHANGES - -* **metrics:** close class-metric gaps, remove --ops/--comments ([#65](https://github.com/ophidiarium/mehen/issues/65)) -* **diff:** `mehen diff --metrics mi` (and the action's `metrics:` / `thresholds:` keys referencing `mi`, `maintainability`, or `maintainabilityindex`) no longer resolve — pick an explicit variant (`mi.original`, `mi.sei`, `mi.visual_studio`). Users relying on the default automatically get `mi.visual_studio` now. - -### Features - -* **action:** retitle comment, add ABC default, auto-exclude tests ([#60](https://github.com/ophidiarium/mehen/issues/60)) ([67225e1](https://github.com/ophidiarium/mehen/commit/67225e1b8eaefae9a46f4d686daf2c0075998b29)) -* add `mehen diff` subcommand ([#24](https://github.com/ophidiarium/mehen/issues/24)) ([abcbd57](https://github.com/ophidiarium/mehen/commit/abcbd5777d4326429503e47f407aeef4127cd095)) -* add reusable mehen metrics action ([#55](https://github.com/ophidiarium/mehen/issues/55)) ([b30c91a](https://github.com/ophidiarium/mehen/commit/b30c91aa184a6d04c8e8e707c0a59ff26cfd67e3)) -* add Ruby language support ([#57](https://github.com/ophidiarium/mehen/issues/57)) ([a88bb87](https://github.com/ophidiarium/mehen/commit/a88bb8753859bacb704e0b46068d69197d6c6ed1)) -* align Go metrics with language semantics ([#59](https://github.com/ophidiarium/mehen/issues/59)) ([427393e](https://github.com/ophidiarium/mehen/commit/427393ed2535cff530cd1ef7068f66f64686a54e)) -* **cli:** add --version --json and surface version in action footer ([#77](https://github.com/ophidiarium/mehen/issues/77)) ([a233b3f](https://github.com/ophidiarium/mehen/commit/a233b3f5abf49a65aaf0b464c34ecade28528825)) -* **cli:** add top-offenders subcommand ([#71](https://github.com/ophidiarium/mehen/issues/71)) ([00e4bf0](https://github.com/ophidiarium/mehen/commit/00e4bf00ab254094c5b5e0a23cff23029b8fd05e)) -* **diff:** add Markdown Documentation Metrics section to PR comment (§39) ([#89](https://github.com/ophidiarium/mehen/issues/89)) ([2742bc4](https://github.com/ophidiarium/mehen/commit/2742bc4ffc7d48e0a964c1d699552469652f3451)) -* **diff:** split mi into mi.original/mi.sei/mi.visual_studio, default to Visual Studio ([#64](https://github.com/ophidiarium/mehen/issues/64)) ([7c8e4bc](https://github.com/ophidiarium/mehen/commit/7c8e4bc9c7b75bd5ed483017d7b0a598e4be55bc)) -* **langs:** add C language support ([#80](https://github.com/ophidiarium/mehen/issues/80)) ([954bb9b](https://github.com/ophidiarium/mehen/commit/954bb9b7da8d16c0733dc7a48ad428b67f16c655)) -* **langs:** route JavaScript/JSX through TypeScript/TSX grammars ([#79](https://github.com/ophidiarium/mehen/issues/79)) ([229f37d](https://github.com/ophidiarium/mehen/commit/229f37d0ae732025ddeb17ceeb21c6478c037356)) -* **markdown:** add EN+JA prose metric layer (Tier 0, §§29-38) ([#85](https://github.com/ophidiarium/mehen/issues/85)) ([3108e26](https://github.com/ophidiarium/mehen/commit/3108e266cbc3a61470ca6df94214e8b2fd9eb2a7)) -* **markdown:** add grounding, evidence, filler risk, RCI, section balance, good scaffold (§§15–21) ([#87](https://github.com/ophidiarium/mehen/issues/87)) ([6fba906](https://github.com/ophidiarium/mehen/commit/6fba9063cebbff4323548086aaee9d24cce1bb01)) -* **markdown:** add link debt, visual scaffold, table burden, and artifact debt (§§11–14, §19) ([#84](https://github.com/ophidiarium/mehen/issues/84)) ([8e86186](https://github.com/ophidiarium/mehen/commit/8e861861ee50b077dc35278ea9815b71b9f431cb)) -* **markdown:** add MRPC, MCC, Markdown Halstead, and DMI core (§§7–10) ([#83](https://github.com/ophidiarium/mehen/issues/83)) ([9e6eef0](https://github.com/ophidiarium/mehen/commit/9e6eef0a51468a80e5337fa60d73cf11a810c4d6)) -* **metrics:** add Kotlin language support ([#66](https://github.com/ophidiarium/mehen/issues/66)) ([f543cef](https://github.com/ophidiarium/mehen/commit/f543cefa1cb0afd1a01a2c7d3a2a07f04f565990)) -* **metrics:** add PowerShell language support ([#69](https://github.com/ophidiarium/mehen/issues/69)) ([47b17ac](https://github.com/ophidiarium/mehen/commit/47b17ac4494c9687937b57460be0cda8a1db749e)) -* **metrics:** close class-metric gaps, remove --ops/--comments ([#65](https://github.com/ophidiarium/mehen/issues/65)) ([cee0526](https://github.com/ophidiarium/mehen/commit/cee0526b59dc1c46258edae8e8f654749830a727)) -* **metrics:** gate wmc/npa/npm by language applicability ([#61](https://github.com/ophidiarium/mehen/issues/61)) ([e4c7cc9](https://github.com/ophidiarium/mehen/commit/e4c7cc959f0ef1f0c1a2878ad4965bd1c674b8c3)) -* **php:** add PHP language support ([3cddaf2](https://github.com/ophidiarium/mehen/commit/3cddaf227f7bc674829b5a10145b2de3b72502fd)) -* support cargo binstall via GitHub Release archives ([#122](https://github.com/ophidiarium/mehen/issues/122)) ([5f6ff3a](https://github.com/ophidiarium/mehen/commit/5f6ff3a3694dec2711d5886cc0aa3d46a24554ae)) - - -### Bug Fixes - -* address PR review comment ([62a7b95](https://github.com/ophidiarium/mehen/commit/62a7b9582fc1ee4cd6bef72823ba03d7d3c29761)) -* address PR review comment ([4af0199](https://github.com/ophidiarium/mehen/commit/4af0199ae644200c0fa5623016ad959c84ba1bd1)) -* address PR review comment ([e74731a](https://github.com/ophidiarium/mehen/commit/e74731a885eb672eebc00c97eb82a12995db1cc5)) -* address PR review comment ([a9d5571](https://github.com/ophidiarium/mehen/commit/a9d5571482a86191ffa3706ba02b4bec6cb5289c)) -* address PR review comment ([3dbcfb4](https://github.com/ophidiarium/mehen/commit/3dbcfb48e27a14fd020bdec3f3374886bb93d9a4)) -* address PR review comment ([ba68728](https://github.com/ophidiarium/mehen/commit/ba68728fecd66b786372a6aa2922f24d73ad6d19)) -* address PR review comment ([1b764e7](https://github.com/ophidiarium/mehen/commit/1b764e73824a16da7d1a333e123bb606d5de4632)) -* address PR review comment ([4a6eca8](https://github.com/ophidiarium/mehen/commit/4a6eca8914e971c54dfa82d146f8b3eff837aa63)) -* address PR review comments ([12eb0d5](https://github.com/ophidiarium/mehen/commit/12eb0d54c9b6db022858f48201d6fd453296bef2)) -* address PR review comments ([f9b0ee3](https://github.com/ophidiarium/mehen/commit/f9b0ee39e94e3624267d943b814a93d3affc9029)) -* check PR author instead of event actor in regeneration workflow ([62c82e4](https://github.com/ophidiarium/mehen/commit/62c82e45ee5cea86ae0e460d42ea0b3f4f990aa8)) -* **ci:** remove broken npm@11 global install from static-analysis ([#48](https://github.com/ophidiarium/mehen/issues/48)) ([7f4cae8](https://github.com/ophidiarium/mehen/commit/7f4cae81b1f018de380d0f98419398489a894e1f)) -* handle unmapped Unicode chars in enum generator ([#15](https://github.com/ophidiarium/mehen/issues/15)) ([c972b1d](https://github.com/ophidiarium/mehen/commit/c972b1d451b0cf3bfc3df372213ded864034a056)) -* **metrics:** align cyclomatic and cognitive with language semantics ([#63](https://github.com/ophidiarium/mehen/issues/63)) ([e3f436d](https://github.com/ophidiarium/mehen/commit/e3f436d70794ea71d51d415189c723de7f7ab78f)) -* **npm:** restore +x on platform binaries and surface spawn errors ([#75](https://github.com/ophidiarium/mehen/issues/75)) ([b5f6104](https://github.com/ophidiarium/mehen/commit/b5f610476db964e999427c797bab4cd04ce9b43c)) -* Rust metric edge cases ([#73](https://github.com/ophidiarium/mehen/issues/73)) ([63238d2](https://github.com/ophidiarium/mehen/commit/63238d2729788ee9d7318a3af0ce53973233f1f5)) -* trigger on Cargo.lock ([24e216e](https://github.com/ophidiarium/mehen/commit/24e216e0571ab8fff247009ef4fa9d6b67c1c432)) -* update README.md ([87ea2b1](https://github.com/ophidiarium/mehen/commit/87ea2b1685d7436bcf9818064047ccb46e4a060c)) -* update typos config ([8b8bc9b](https://github.com/ophidiarium/mehen/commit/8b8bc9b3cc485bad5be4696d13bae6f88a64ba4b)) -* use GitHub App token in release-please workflow ([#20](https://github.com/ophidiarium/mehen/issues/20)) ([8db91a5](https://github.com/ophidiarium/mehen/commit/8db91a523d36fe949a4ff32e5e650c4a8fae7a09)) - - -### Miscellaneous Chores - -* release 0.1.1 ([8f32dba](https://github.com/ophidiarium/mehen/commit/8f32dba7a28775b7cf7f71e2f8c9e1d5fd5dc647)) -* release 0.3.0 ([7041e4c](https://github.com/ophidiarium/mehen/commit/7041e4cfdcd33a7e44bbe82d338c1f9f1016b362)) -* release 0.4.0 ([8b7a4d3](https://github.com/ophidiarium/mehen/commit/8b7a4d3ec847aa5d003aa5513aa6e893b6ab3851)) -* release 0.5.0 ([e0befc2](https://github.com/ophidiarium/mehen/commit/e0befc2e743a3be82f4eca7930146302d7d573d3)) -* release 1.0.0 ([285b16a](https://github.com/ophidiarium/mehen/commit/285b16aff747298d1ff3e3085fc2b949850f7ecb)) - -## [0.7.0](https://github.com/ophidiarium/mehen/compare/v0.6.1...v0.7.0) (2026-05-18) - - -### Features - -* **php:** add PHP language support ([4b42b9e](https://github.com/ophidiarium/mehen/commit/4b42b9ef39a9255d932737a0bc597139da8b603f)) - - -### Bug Fixes - -* address PR review comment ([d29c594](https://github.com/ophidiarium/mehen/commit/d29c594f6520a05713b18ead105ccc3d692a15c9)) -* address PR review comment ([6f04185](https://github.com/ophidiarium/mehen/commit/6f0418513cb5dcdf753e40cdf903f05c77a098c9)) -* address PR review comment ([580d09b](https://github.com/ophidiarium/mehen/commit/580d09b143d8b26076aea1bd83ed3612213ac13d)) -* address PR review comment ([64cec1e](https://github.com/ophidiarium/mehen/commit/64cec1e761afcf849a88ea6f4e20623c2e82db2c)) -* address PR review comment ([b8d773a](https://github.com/ophidiarium/mehen/commit/b8d773a914187e8c64436e1f00bd479fd28ceae6)) -* address PR review comment ([2f84abf](https://github.com/ophidiarium/mehen/commit/2f84abf5c50b0dfe01b0958e5515398d9f84a841)) -* address PR review comment ([08435b5](https://github.com/ophidiarium/mehen/commit/08435b5ab050eab4c89a9207031150f1f4af9fd1)) -* address PR review comment ([06d79f5](https://github.com/ophidiarium/mehen/commit/06d79f57b61f0e0a4faa736644978082dc3bd0f8)) -* address PR review comments ([5d0559d](https://github.com/ophidiarium/mehen/commit/5d0559d5d453dd21fd11bc8ce2a33c9eba8b5e95)) -* address PR review comments ([56028e7](https://github.com/ophidiarium/mehen/commit/56028e7dede525b661db88dd8ab16a0c6a65330f)) - -## [0.6.1](https://github.com/ophidiarium/mehen/compare/v0.6.0...v0.6.1) (2026-05-15) - - -### Bug Fixes - -* update README.md ([8fe00df](https://github.com/ophidiarium/mehen/commit/8fe00dfd2844ea153b06eb3765fdd1cca2844b5b)) - -## [0.6.0](https://github.com/ophidiarium/mehen/compare/v0.5.0...v0.6.0) (2026-05-13) - - -### Features - -* **diff:** add Markdown Documentation Metrics section to PR comment (§39) ([#89](https://github.com/ophidiarium/mehen/issues/89)) ([1563333](https://github.com/ophidiarium/mehen/commit/15633339e9c4b3f68a0513682a68d6fb813cc611)) -* **markdown:** add EN+JA prose metric layer (Tier 0, §§29-38) ([#85](https://github.com/ophidiarium/mehen/issues/85)) ([da64470](https://github.com/ophidiarium/mehen/commit/da644705c5d006ee902601505a2dd5437acc9953)) -* **markdown:** add grounding, evidence, filler risk, RCI, section balance, good scaffold (§§15–21) ([#87](https://github.com/ophidiarium/mehen/issues/87)) ([a948fbc](https://github.com/ophidiarium/mehen/commit/a948fbc43b136becfe5c5fbd5bd36a93d3ecb89a)) -* **markdown:** add link debt, visual scaffold, table burden, and artifact debt (§§11–14, §19) ([#84](https://github.com/ophidiarium/mehen/issues/84)) ([9e23a0a](https://github.com/ophidiarium/mehen/commit/9e23a0a93a50759cd0bbdd5a52920e46b01b2893)) -* **markdown:** add MRPC, MCC, Markdown Halstead, and DMI core (§§7–10) ([#83](https://github.com/ophidiarium/mehen/issues/83)) ([2fdd4d1](https://github.com/ophidiarium/mehen/commit/2fdd4d11ac7458eb1a9d6b6ba45aa7cba0e5c9ea)) - -## [0.5.0](https://github.com/ophidiarium/mehen/compare/v0.4.3...v0.5.0) (2026-05-11) - - -### Features - -* **cli:** add --version --json and surface version in action footer ([#77](https://github.com/ophidiarium/mehen/issues/77)) ([199e37d](https://github.com/ophidiarium/mehen/commit/199e37d31bfb1fec1746f78f484330b0056614ea)) -* **langs:** add C language support ([#80](https://github.com/ophidiarium/mehen/issues/80)) ([783a1e8](https://github.com/ophidiarium/mehen/commit/783a1e886cf43907f8370693f6bf09e859dcc508)) -* **langs:** route JavaScript/JSX through TypeScript/TSX grammars ([#79](https://github.com/ophidiarium/mehen/issues/79)) ([a6fb345](https://github.com/ophidiarium/mehen/commit/a6fb345898ea965bfb7f77983c774d6558b842a6)) - - -### Miscellaneous Chores - -* release 0.5.0 ([b9f81c3](https://github.com/ophidiarium/mehen/commit/b9f81c3ee5223736d72f21fbf933724e86000945)) - -## [0.4.3](https://github.com/ophidiarium/mehen/compare/v0.4.2...v0.4.3) (2026-05-09) - - -### Bug Fixes - -* **npm:** restore +x on platform binaries and surface spawn errors ([#75](https://github.com/ophidiarium/mehen/issues/75)) ([e12549e](https://github.com/ophidiarium/mehen/commit/e12549eb9bcccb586f424101a5d1ee50a41aec6d)) - -## [0.4.2](https://github.com/ophidiarium/mehen/compare/v0.4.1...v0.4.2) (2026-05-08) - - -### Bug Fixes - -* Rust metric edge cases ([#73](https://github.com/ophidiarium/mehen/issues/73)) ([8bccab4](https://github.com/ophidiarium/mehen/commit/8bccab409c6e8cac29e737b085baebbf4ba14d61)) - -## [0.4.1](https://github.com/ophidiarium/mehen/compare/v0.4.0...v0.4.1) (2026-05-07) - - -### Features - -* **cli:** add top-offenders subcommand ([#71](https://github.com/ophidiarium/mehen/issues/71)) ([e07c061](https://github.com/ophidiarium/mehen/commit/e07c061463ed55fa5736b9e71f09979eba1d39a4)) - -## [0.4.0](https://github.com/ophidiarium/mehen/compare/v0.3.0...v0.4.0) (2026-05-05) - - -### Features - -* **metrics:** add PowerShell language support ([#69](https://github.com/ophidiarium/mehen/issues/69)) ([7a34436](https://github.com/ophidiarium/mehen/commit/7a344361c086214f0b98730e6bae10f02b0ab22a)) - - -### Miscellaneous Chores - -* release 0.4.0 ([5a3a699](https://github.com/ophidiarium/mehen/commit/5a3a69986f6193a17bfbbed0831d8c648075c0b7)) - -## [0.3.0](https://github.com/ophidiarium/mehen/compare/v0.2.0...v0.3.0) (2026-05-02) - - -### Features - -* **metrics:** add Kotlin language support ([#66](https://github.com/ophidiarium/mehen/issues/66)) ([028f93b](https://github.com/ophidiarium/mehen/commit/028f93b802241d742e16d4952d798dc980a8535a)) - - -### Miscellaneous Chores - -* release 0.3.0 ([8b6dad6](https://github.com/ophidiarium/mehen/commit/8b6dad68dc3668a55666e46498b539dff073dd4f)) - -## [0.2.0](https://github.com/ophidiarium/mehen/compare/v0.1.1...v0.2.0) (2026-04-30) - - -### ⚠ BREAKING CHANGES - -* **metrics:** close class-metric gaps, remove --ops/--comments ([#65](https://github.com/ophidiarium/mehen/issues/65)) -* **diff:** `mehen diff --metrics mi` (and the action's `metrics:` / `thresholds:` keys referencing `mi`, `maintainability`, or `maintainabilityindex`) no longer resolve — pick an explicit variant (`mi.original`, `mi.sei`, `mi.visual_studio`). Users relying on the default automatically get `mi.visual_studio` now. - -### Features - -* **diff:** split mi into mi.original/mi.sei/mi.visual_studio, default to Visual Studio ([#64](https://github.com/ophidiarium/mehen/issues/64)) ([cb22ed6](https://github.com/ophidiarium/mehen/commit/cb22ed6afd0def04b0f8b9336a95389469fcf361)) -* **metrics:** close class-metric gaps, remove --ops/--comments ([#65](https://github.com/ophidiarium/mehen/issues/65)) ([25a8218](https://github.com/ophidiarium/mehen/commit/25a8218f1c67c7d620f19ddc6f7fb70d7e00c7ab)) -* **metrics:** gate wmc/npa/npm by language applicability ([#61](https://github.com/ophidiarium/mehen/issues/61)) ([975726a](https://github.com/ophidiarium/mehen/commit/975726a87c9ee112da7c4a2385ac687c805abd6a)) - - -### Bug Fixes - -* **metrics:** align cyclomatic and cognitive with language semantics ([#63](https://github.com/ophidiarium/mehen/issues/63)) ([7425460](https://github.com/ophidiarium/mehen/commit/7425460f91c87c360dee2443878d925b2bce0b4f)) - -## [0.1.1](https://github.com/ophidiarium/mehen/compare/v0.0.6...v0.1.1) (2026-04-30) - - -### Features - -* **action:** retitle comment, add ABC default, auto-exclude tests ([#60](https://github.com/ophidiarium/mehen/issues/60)) ([fb470d6](https://github.com/ophidiarium/mehen/commit/fb470d6772c5e46e88ead129e14871ca54afd944)) -* add Ruby language support ([#57](https://github.com/ophidiarium/mehen/issues/57)) ([fb8d53c](https://github.com/ophidiarium/mehen/commit/fb8d53cca1d88a916a15e0d2e9e9297df2f8c145)) -* align Go metrics with language semantics ([#59](https://github.com/ophidiarium/mehen/issues/59)) ([ae3cf53](https://github.com/ophidiarium/mehen/commit/ae3cf53684e78e717457c9edee9b4eaa29640587)) - - -### Miscellaneous Chores - -* release 0.1.1 ([03018d7](https://github.com/ophidiarium/mehen/commit/03018d76f4978f8e219b93b0c2f625c3f7b922d7)) - -## [0.0.6](https://github.com/ophidiarium/mehen/compare/v0.0.5...v0.0.6) (2026-04-25) - - -### Features - -* add reusable mehen metrics action ([#55](https://github.com/ophidiarium/mehen/issues/55)) ([11c5a52](https://github.com/ophidiarium/mehen/commit/11c5a529e4d006fa74f15cd453fb188c36ab9c40)) - -## [0.0.5](https://github.com/ophidiarium/mehen/compare/v0.0.4...v0.0.5) (2026-04-07) - - -### Bug Fixes - -* **ci:** remove broken npm@11 global install from static-analysis ([#48](https://github.com/ophidiarium/mehen/issues/48)) ([1774559](https://github.com/ophidiarium/mehen/commit/17745598d764638d2736e2ca539872ff7666c42b)) - -## [0.0.4](https://github.com/ophidiarium/mehen/compare/v0.0.3...v0.0.4) (2026-02-16) - - -### Features - -* add `mehen diff` subcommand ([#24](https://github.com/ophidiarium/mehen/issues/24)) ([8edfcdf](https://github.com/ophidiarium/mehen/commit/8edfcdfef6b98c726becc681533bbb6a89c237db)) - -## [0.0.3](https://github.com/ophidiarium/mehen/compare/v0.0.2...v0.0.3) (2026-02-16) - - -### Bug Fixes - -* update typos config ([a41a4a4](https://github.com/ophidiarium/mehen/commit/a41a4a462e96d965641a4615e2403646c4e0885a)) -* use GitHub App token in release-please workflow ([#20](https://github.com/ophidiarium/mehen/issues/20)) ([88cf7ba](https://github.com/ophidiarium/mehen/commit/88cf7ba030b4ffbe74203cef9250e7d56702184b)) - -## [0.0.2](https://github.com/ophidiarium/mehen/compare/v0.0.1...v0.0.2) (2026-02-15) - - -### Features - -* Add Go language support ([4ed54eb](https://github.com/ophidiarium/mehen/commit/4ed54ebbebde67ae6429c1ef31349d8a2b866dd4)) -* Expose inner tree-sitter::Node for advanced use cases ([#1210](https://github.com/ophidiarium/mehen/issues/1210)) ([2e167b0](https://github.com/ophidiarium/mehen/commit/2e167b00f906629b2341450e4485b570f8c02f0e)) - - -### Bug Fixes - -* Address clippy collapsible_if warnings with let-chains ([#1211](https://github.com/ophidiarium/mehen/issues/1211)) ([383c639](https://github.com/ophidiarium/mehen/commit/383c639cfe3ca6aa84f3c73e1df68beaff7151c7)) -* check PR author instead of event actor in regeneration workflow ([9c91fcc](https://github.com/ophidiarium/mehen/commit/9c91fcce6eaef2bb212e3146d70cb66f8ea8a080)) -* handle unmapped Unicode chars in enum generator ([#15](https://github.com/ophidiarium/mehen/issues/15)) ([1f3e115](https://github.com/ophidiarium/mehen/commit/1f3e115dba83f4e2d488718a6d2e0fea82d830d6)) -* hanging server ([#806](https://github.com/ophidiarium/mehen/issues/806)) ([08c61f4](https://github.com/ophidiarium/mehen/commit/08c61f48ad7ea3ad20bff9deb64fd211e7f93857)) -* trigger on Cargo.lock ([3ec887b](https://github.com/ophidiarium/mehen/commit/3ec887b89732c64004fcc97191728fe5de0ae48a)) diff --git a/CLAUDE.md b/CLAUDE.md index b829643e..b08e6054 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,99 +1,377 @@ # CLAUDE.md - AI Assistant Guide for Mehen -## Project Scope -- `mehen` is a **CLI-only** Rust project focused on code analysis and metrics. -- The analyzer/engine/CLI code is **not** a library or API for external use; it is internal to the CLI tool. The sole exception is the generated-only `crates/mehen--parser/` crates, which are intentionally **publishable** so external tools can consume the vendored ANTLR parsers standalone (they carry no mehen-specific logic — just the generated lexer/parser + grammar on `antlr4_runtime`). - -## Educational and Research Objective - -mehen's heuristic source-code metrics double as an educational and research instrument — the tool should teach what it measures, not just gate on it. When working on metrics: - -- **Explainability first**: when adding a new metric or improving an existing one, fill or improve the explainability gap — record contribution evidence (`MetricEvidence` in `mehen-metrics`: span + reason code + amount) so `mehen metrics` can answer *why* a value moved. Keep the evidence-sum invariants pinned by each crate's `tests/contributions.rs`. -- **Approachable messaging**: errors and warnings must be understandable by users without deep knowledge of the metric's theory — prefer concise yet explanatory wording over jargon or bare codes. -- **Schoolbook docs**: each metric's page under `docs/metrics/` maintains a scientific yet learning-oriented style, with high-quality papers cited in its `## References` section (see `docs/metrics/code/cognitive.mdx` for the pattern). - -## Repository Structure (current) -- `crates/mehen-cli/`: CLI binary (entry point, command routing, exit codes). -- `crates/mehen-engine/`: pipeline orchestration (`run_diff`, `run_top_offenders`, registry, language detection). -- `crates/mehen-core/`: parser-neutral domain types and the `LanguageAnalyzer` trait. -- `crates/mehen-metrics/`: shared metric formulas, accumulators, and finalization helpers. -- `crates/mehen-/`: per-language analyzers — each owns parsing (walker) and metric interpretation. Tree-sitter-backed languages keep their own `grammar.rs`; ANTLR-backed ones (e.g. `mehen-kotlin`, `mehen-java`, `mehen-csharp`) depend on a separate generated-only crate `crates/mehen--parser/` that holds the vendored grammar + generated lexer/parser. -- `crates/mehen--parser/`: generated-only, **publishable** crates holding the ANTLR-generated lexer/parser + vendored `.g4` grammar for an ANTLR-backed language (`mehen-kotlin-parser`, `mehen-java-parser`, `mehen-csharp-parser`). Split out so external tools can depend on just the parser via a git tag (the way this repo consumes ruff/oxc/sqruff). They depend only on `antlr4_runtime`. -- `crates/mehen-tree-sitter/`: shared tree-sitter wrapper and CST traversal helpers. -- `crates/mehen-antlr/`: shared support for ANTLR-backed analyzers — re-exports the `antlr4_runtime` runtime and provides span conversion (char→byte), recovered-error diagnostics, and hidden-channel comment (CLOC) extraction. -- `crates/mehen-markdown/`: Markdown analyzer with embedded-code dispatch via `LanguageDispatcher`. Backed by `pulldown-cmark` (not tree-sitter): its `src/syntax_tree.rs` reifies the event stream into a small owned tree whose node kinds are a hand-authored enum in `src/kind.rs` — there is no generated `grammar.rs` here. -- `crates/mehen-sql/`: SQL analyzer (sqruff-backed). Like Markdown, it publishes a dedicated flat-key family (`sql.*`) instead of the source-code metric families; the sqruff CST is confined to `facts.rs` behind a parser-neutral `SqlFileFacts` adapter. -- `crates/mehen-git/`, `crates/mehen-report/`: git operations and rendering (JSON, GitHub Markdown). -- `xtask/`: developer-only commands (kind-enum codegen, AST dumps, audits). -- `docs/`: Mintlify documentation site (replaces the legacy `mehen-book/`). - -## Build and Lint -Run from repo root: +This document provides context for AI assistants working with the Mehen codebase. + +## Project Overview + +**Mehen** is a focused code analysis library that computes software metrics for Go, Python, Rust, and TypeScript/TSX source code. It uses Tree-sitter parsers for accurate AST-based analysis. + +**Origin**: Forked from mozilla/rust-code-analysis, streamlined to support only 4 languages instead of 10+. + +**Author**: Konstantin Vyatkin +**Repository**: https://github.com/ophidiarium/mehen +**License**: MPL-2.0 + +## Supported Languages ONLY + +This is critical - the codebase **only** supports these 4 languages: + +1. **Go** (.go) - via tree-sitter-go v0.23.4 +2. **Python** (.py) - via tree-sitter-python v0.23.6 +3. **Rust** (.rs) - via tree-sitter-rust v0.23.2 +4. **TypeScript** (.ts, .jsw, .jsmw) - via tree-sitter-typescript v0.23.2 +5. **TSX** (.tsx) - via tree-sitter-typescript v0.23.2 + +### Removed Languages (DO NOT reference these) + +The following were intentionally removed: +- Java, Kotlin, C, C++, JavaScript, Mozjs, Ccomment, Preproc +- Any references to `JavaCode`, `KotlinCode`, `CppCode`, `MozjsCode`, `JavascriptCode`, `CcommentCode`, `PreprocCode` are errors +- Any references to `JavaParser`, `CppParser`, etc. are errors + +## Build Requirements + +### Rust Version Requirements + +**Minimum**: Rust **1.93.1** (current stable as of Feb 2025) +**Edition**: 2024 + +The codebase uses **let chains** syntax: + +```rust +if let Some(label_child) = node.child(1) + && let Label = label_child.kind_id().into() +{ + // ... +} +``` + +This feature requires Rust 1.88.0+ with edition 2024. ```bash -cargo check cargo build -cargo fmt --all -cargo clippy --all-targets --all-features --locked +cargo test +cargo check ``` -For dead-code cleanup work, use: +## Project Structure -```bash -cargo clippy --all-targets --all-features --locked -- -W dead_code -W unreachable_pub ``` +mehen/ +├── src/ # Core library +│ ├── languages/ # Language-specific AST enums (5 files) +│ │ ├── language_go.rs +│ │ ├── language_python.rs +│ │ ├── language_rust.rs +│ │ ├── language_tsx.rs +│ │ └── language_typescript.rs +│ ├── metrics/ # Metric implementations +│ │ ├── abc.rs # ABC metric +│ │ ├── cognitive.rs # Cognitive complexity +│ │ ├── cyclomatic.rs # Cyclomatic complexity +│ │ ├── exit.rs # Number of exits +│ │ ├── halstead.rs # Halstead metrics +│ │ ├── loc.rs # Lines of code (SLOC, PLOC, LLOC, CLOC) +│ │ ├── mi.rs # Maintainability Index +│ │ ├── nargs.rs # Number of arguments +│ │ ├── nom.rs # Number of methods +│ │ ├── npa.rs # Number of public attributes +│ │ ├── npm.rs # Number of public methods +│ │ └── wmc.rs # Weighted Methods per Class +│ ├── alterator.rs # AST node transformation +│ ├── checker.rs # Language-specific code checks +│ ├── getter.rs # Extract information from nodes +│ ├── langs.rs # Language definitions (mk_langs! macro) +│ ├── parser.rs # Parser wrapper +│ └── lib.rs # Library entry point +├── mehen-cli/ # Command-line interface +├── mehen-book/ # Documentation (mdBook) +└── enums/ # Code generator for language enums -## Testing (nextest-first) -Use `nextest` by default when available. +Tests: tests/, inline in src/metrics/*.rs +``` -Detection + fallback: +## Key Architecture Patterns -```bash -if cargo nextest --version >/dev/null 2>&1; then - cargo nextest run --all-features -else - cargo test --all-targets --locked -fi +### 1. Language Definition Pattern + +Languages are defined using the `mk_langs!` macro in `src/langs.rs`: + +```rust +mk_langs!( + ( + Rust, + "The `Rust` language", + "rust", + RustCode, // Type for trait implementations + RustParser, // Parser type + tree_sitter_rust, + [rs], // File extensions + ["rust"] // Emacs modes + ), + // ... other languages +); ``` -## Snapshot Tests (`insta`) -`insta` is heavily used in metric tests. +### 2. Trait Implementation Pattern + +Each language must implement these traits: +- `Checker` - Language-specific checks (comments, functions, etc.) +- `Getter` - Extract space kinds, operators, operands +- `Alterator` - Transform AST nodes +- Metric traits: `Abc`, `Cognitive`, `Cyclomatic`, `Exit`, `Halstead`, `Loc`, `Mi`, `NArgs`, `Nom`, `Npa`, `Npm`, `Wmc` + +### 3. Metric Trait Pattern + +Most metrics follow this pattern: + +```rust +pub trait MetricName { + fn compute(node: &Node, stats: &mut Stats, ...); +} + +impl MetricName for GoCode { + fn compute(node: &Node, stats: &mut Stats, ...) { + use crate::Go::*; + match node.kind_id().into() { + // Handle language-specific nodes + _ => {} + } + } +} + +// For languages with empty/default implementations +implement_metric_trait!(MetricName, PythonCode, RustCode); +``` + +## Important Implementation Details + +### Language-Specific Type Safety -Always pass `--workspace`. Without it, `cargo insta` only runs tests -from the default-member (`mehen-cli`) and reports every other crate's -snapshots as `unreferenced`, making `--unreferenced reject` falsely fail. +Each language has its own enum type defined in `src/languages/language_*.rs`: +- `Go` enum for Go AST nodes +- `Python` enum for Python AST nodes +- `Rust` enum for Rust AST nodes +- `Typescript` enum for TypeScript AST nodes +- `Tsx` enum for TSX AST nodes -Check snapshots (CI-style): +These enums are auto-generated and should NOT be manually edited (marked with `// Code generated; DO NOT EDIT.`). + +### TypeScript/TSX Relationship + +TypeScript and TSX share the same tree-sitter grammar but have separate enums. They often share implementation logic. + +### JavaScript Handling + +There is NO JavaScript support. TypeScript handles `.ts` files, TSX handles `.tsx` files. Do not add JavaScript-specific code. + +### Preprocessing Infrastructure + +All C/C++ preprocessing infrastructure has been removed: +- No `PreprocParser`, `PreprocResults`, `PreprocCode` +- No `get_macros()`, `fix_includes()`, `preprocess()` functions +- No `c_macro.rs` or `c_langs_macros/` module + +## Testing + +### Test Organization + +1. **Inline tests**: Each metric file has `#[cfg(test)] mod tests { ... }` +2. **Integration tests**: `tests/` directory (minimal - most removed) +3. **Test helper**: Uses `insta` for snapshot testing + +### Running Tests ```bash -cargo insta test --workspace --all-features --check --unreferenced reject --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest +cargo test --lib # Library tests only +cargo test # All tests +cargo test -- --nocapture # With output ``` -Update snapshots intentionally: +### Test Pattern + +```rust +#[test] +fn go_simple_function() { + check_metrics::( + "package main\n\nfunc f() { ... }", + "foo.go", + |metric| { + insta::assert_json_snapshot!(metric.cyclomatic, @r###"..."###); + }, + ); +} +``` + +## Common Tasks + +### Adding Support for a Metric to a Language + +1. Find the metric trait in `src/metrics/*.rs` +2. Add `impl MetricName for LanguageCode { fn compute(...) { ... } }` +3. Use `crate::LanguageName::*` to access AST node types +4. Add tests following existing patterns + +### Adding a New Language (Hypothetically) + +1. Add tree-sitter dependency to `Cargo.toml` and `enums/Cargo.toml` +2. Generate enum with enums tool: `cd enums && cargo run -- --language NewLang` +3. Add language module to `src/languages/mod.rs` +4. Add language to `src/langs.rs` using `mk_langs!` macro +5. Add to `enums/src/languages.rs` +6. Implement required traits in trait files +7. Add tests for each metric + +### Modifying Metrics + +- Metrics are computed during AST traversal +- Each node type can increment counters in `Stats` +- Use pattern matching on `node.kind_id().into()` to handle specific nodes +- Reference existing implementations for similar languages + +## Critical Files + +### Language Configuration +- `src/langs.rs` - Main language registry (mk_langs! macro) +- `enums/src/languages.rs` - Enum generator registry +- `enums/src/macros.rs` - get_language() match statement + +### Core Traits +- `src/checker.rs` - Define what is a comment, function, closure, etc. +- `src/getter.rs` - Extract space kinds, Halstead operators/operands +- `src/alterator.rs` - Transform AST nodes for serialization + +### Parser Infrastructure +- `src/parser.rs` - Main Parser struct +- `src/node.rs` - Node wrapper around tree-sitter::Node +- `src/traits.rs` - Core trait definitions + +## Dependencies + +### Required Tree-sitter Versions (Exact) +- tree-sitter = "=0.25.3" +- tree-sitter-typescript = "=0.23.2" +- tree-sitter-python = "=0.23.6" +- tree-sitter-rust = "=0.23.2" +- tree-sitter-go = "=0.23.4" + +These versions must match exactly - the `=` prefix means no automatic updates. + +## Metrics Computed + +All metrics are computed per-function and aggregated: + +1. **Cyclomatic Complexity (CC)** - Control flow complexity +2. **Cognitive Complexity** - Human-perceived complexity with nesting +3. **Halstead Metrics** - Volume, difficulty, effort, bugs prediction +4. **Lines of Code**: + - SLOC: Source lines (total non-blank) + - PLOC: Physical lines (excluding comments) + - LLOC: Logical lines (statements) + - CLOC: Comment lines +5. **ABC Metric** - Assignments, Branches, Conditionals +6. **Maintainability Index (MI)** - Overall maintainability score +7. **NOM** - Number of Methods +8. **NArgs** - Number of Arguments per function +9. **NExit** - Number of exit points +10. **NPA** - Number of Public Attributes +11. **NPM** - Number of Public Methods +12. **WMC** - Weighted Methods per Class + +## Common Patterns to Avoid + +### Don't Add Back Removed Languages + +If you see references to these in git history, ignore them: +- ❌ Java/Kotlin implementations +- ❌ C/C++ preprocessing +- ❌ Mozilla JavaScript (Mozjs) variants +- ❌ Ccomment/Preproc parsers + +### Rust Version Matters + +The project requires Rust 1.88.0+ (or nightly for older versions) due to `let_chains` feature usage. + +### Don't Break the Macro System + +The `mk_langs!` macro generates lots of boilerplate. Changes to language registration must be synchronized across: +1. `src/langs.rs` +2. `enums/src/languages.rs` +3. `enums/src/macros.rs` +4. All trait implementation files + +## Workspace Members + +The workspace has 2 packages: + +1. **mehen** (root) - Core library +2. **mehen-cli** - Command-line tool (binary name: `mehen`) + +The `enums` crate is excluded from the workspace (it's a build-time code generator). + +## Git Conventions + +- Run tests before committing +- This project inherited history from mozilla/rust-code-analysis +- The fork point is commit `4ed54eb` (feat: Add Go language support) + +## Documentation + +- Code documentation: `cargo doc --open` +- Book: `mehen-book/` (mdBook format) +- API docs are published at https://docs.rs/mehen/ + +## External Links to Preserve + +Do NOT change these legitimate external references: +- https://tree-sitter.github.io/tree-sitter/ (Tree-sitter homepage) +- https://www.mozilla.org/MPL/2.0/ (MPL 2.0 license text) +- Academic paper citations with original authors + +## Quick Reference ```bash -cargo insta test --workspace --all-features --review --test-runner nextest --no-test-runner-fallback --disable-nextest-doctest +# Build everything +cargo build --workspace + +# Run all tests +cargo test --lib + +# Check compilation +cargo check --workspace + +# Format code +cargo fmt --all + +# Run CLI +cargo run -p mehen-cli -- -m -p test.go ``` -## Language/Grammar Changes -Hard rule: never edit `crates/mehen-*/src/grammar.rs` directly. These files are generated by `cargo xtask tree-sitter generate ` and direct edits will be overwritten on the next regeneration. CI runs `cargo xtask tree-sitter check-generated` to catch drift. (This applies only to tree-sitter-backed crates. `mehen-markdown` is `pulldown-cmark`-backed and has no `grammar.rs`; its node-kind enum in `src/kind.rs` is hand-authored and edited directly.) +## Key Insights from the Cleanup + +1. **Massive Simplification**: Removed 861k+ lines, kept 628 lines of new code +2. **Language Focus**: 4 languages cover most modern development needs +3. **Dead Code**: Removed entire subsystems (preprocessing, C-specific macros) +4. **Type Safety**: Each language has its own strongly-typed AST enum +5. **Metric Completeness**: All 5 supported languages have full metric coverage + +## When Working on This Codebase -When adding or updating a tree-sitter-backed language: -1. Pin the grammar in the owning `crates/mehen-/Cargo.toml` (and in `xtask/Cargo.toml` so the codegen links the same version). -2. Add a `GeneratorTarget` entry to `xtask/src/tree_sitter.rs::TARGETS`. -3. Run `cargo xtask tree-sitter generate ` and commit the resulting `grammar.rs`. -4. Register the analyzer in `mehen-engine`'s registry (`crates/mehen-engine/src/registry.rs`). -5. Add per-language metric tests under `crates/mehen-/tests/`. +✅ **Do**: +- Use nightly Rust +- Test with all 4 supported languages +- Follow existing trait implementation patterns +- Add tests for new functionality +- Keep language support focused -ANTLR-backed languages (e.g. Kotlin, Java, C#) follow the same hard rule for generated code, but the generated modules now live in the dedicated `crates/mehen--parser/` crate: never edit `crates/mehen--parser/src/generated/*.rs` or the JSON sidecars beside them — they are produced by `cargo xtask antlr generate ` from the vendored `.g4` grammar in `crates/mehen--parser/grammar/`. Each generated `.rs` self-wraps in a `#[rustfmt::skip] mod __antlr4_rust_generated` and is loaded via `#[path] pub mod` from the parser crate's `lib.rs`. xtask links the workspace-pinned `antlr-rust-codegen` crate directly, so no external generator binary is needed; keep its pin in lockstep with `antlr-rust-runtime`. `cargo xtask antlr check-generated` always guards drift (`.rs`, JSON sidecars, and parser-crate README). Generation always uses the equivalent of `--sem-unknown error --require-full-semantics`: every grammar semantic helper must be lowered via the target's `grammar/patterns.toml` (pure pattern or typed hook), hook-implemented grammar options acknowledged via the target's `option_hooks`, and `hook` lowerings backed by a hand-written port in the parser crate's `src/hooks.rs` (installed with `with_typed_hooks`; see `mehen-java`). See `docs/developers/new-language.mdx` ("Adding an ANTLR-backed language") and `crates/mehen-kotlin-parser/grammar/PROVENANCE.md`. +❌ **Don't**: +- Add back removed languages without discussion +- Break the macro-generated code +- Add preprocessing or C/C++ specific features +- Reference removed parser types in code -## Coding Expectations -- Keep internals internal (`pub(crate)`/private) unless a real external API is needed. -- Prefer explicit imports over wildcard re-exports. -- Avoid dead code; this is a CLI-focused codebase. -- Preserve deterministic metric behavior across platforms. +## Contact -## Useful References -- `README.md` -- `AGENTS.md` -- `docs/developers/new-language.mdx` +For questions about this codebase, refer to: +- GitHub Issues: https://github.com/ophidiarium/mehen/issues +- Original upstream: https://github.com/mozilla/rust-code-analysis (for historical context only) diff --git a/Cargo.lock b/Cargo.lock index 5338c115..0fc86849 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,34 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.4", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.4" @@ -39,26 +11,11 @@ dependencies = [ "memchr", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android_system_properties" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" -dependencies = [ - "libc", -] - [[package]] name = "anstream" -version = "1.0.0" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -71,15 +28,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.14" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "1.0.0" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] @@ -105,5454 +62,975 @@ dependencies = [ ] [[package]] -name = "antlr-rust-codegen" -version = "0.33.1" +name = "anyhow" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "908b00de3cab56708fba2c4946b14b50f4fca38fd23b1fe34fef0fc063aa4bcb" -dependencies = [ - "anstream", - "anstyle", - "antlr-rust-g4-parser", - "antlr-rust-rs-parser", - "antlr-rust-runtime", - "antlr-rust-toml-parser", - "clap", - "hmac-sha256", - "icu_casemap", - "icu_properties", - "intl", - "miette", - "petgraph", - "rustpython-pylib", - "rustpython-vm", - "serde", - "serde_json", - "tempfile", - "thiserror", -] +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] -name = "antlr-rust-g4-parser" -version = "0.33.1" +name = "autocfg" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9eb7d871302bffa8a2dcd0b8ca0116fbeef35cb3df75ea3304dbc3fa4d42f0a" -dependencies = [ - "antlr-rust-runtime", -] +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "antlr-rust-rs-parser" -version = "0.33.1" +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89f98f7b8f85515b84678ed841850e37b6d01feabec35745f7c80ef3b73f1d6" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "antlr-rust-runtime", + "generic-array", ] [[package]] -name = "antlr-rust-runtime" -version = "0.33.1" +name = "bstr" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39181d80059d13a09039e4594bffe8454232a74794e8e9ebe00f29eff6c010cf" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", - "stacker", - "thiserror", + "serde", ] [[package]] -name = "antlr-rust-toml-parser" -version = "0.33.1" +name = "cc" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "541e472e9c2942dee05b07566f43018eb389e71178a1e6374b8411b30f2aa317" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ - "antlr-rust-runtime", - "toml_datetime", + "find-msvc-tools", + "shlex", ] [[package]] -name = "anyhow" -version = "1.0.102" +name = "cfg-if" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] -name = "ar_archive_writer" -version = "0.5.2" +name = "clap" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4087686b4b0a3427190bae57a1d9a478dbb2d40c5dc1bd6e2b6d797913bdd348" +checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806" dependencies = [ - "object", + "clap_builder", + "clap_derive", ] [[package]] -name = "arc-swap" -version = "1.9.1" +name = "clap_builder" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" +checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2" dependencies = [ - "rustversion", + "anstream", + "anstyle", + "clap_lex", + "strsim", ] [[package]] -name = "ariadne" -version = "0.6.0" +name = "clap_derive" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8454c8a44ce2cb9cc7e7fae67fc6128465b343b92c6631e94beca3c8d1524ea5" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ - "unicode-width 0.2.2", - "yansi", + "heck", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" +name = "clap_lex" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] -name = "ascii" -version = "1.1.0" +name = "colorchoice" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] -name = "askama" -version = "0.16.0" +name = "console" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ - "askama_macros", - "itoa", - "percent-encoding", - "serde", - "serde_json", + "encode_unicode", + "libc", + "once_cell", + "windows-sys 0.59.0", ] [[package]] -name = "askama_derive" -version = "0.16.0" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "askama_parser", - "basic-toml", - "glob", - "memchr", - "proc-macro2", - "quote", - "rustc-hash 2.1.2", - "serde", - "serde_derive", - "syn 2.0.117", + "libc", ] [[package]] -name = "askama_macros" -version = "0.16.0" +name = "crossbeam" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "askama_derive", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", ] [[package]] -name = "askama_parser" -version = "0.16.0" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "rustc-hash 2.1.2", - "serde", - "serde_derive", - "unicode-ident", - "winnow 1.0.3", + "crossbeam-utils", ] [[package]] -name = "attribute-derive" -version = "0.10.5" +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05832cdddc8f2650cc2cc187cc2e952b8c133a48eb055f35211f61ee81502d77" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "attribute-derive-macro", - "derive-where", - "manyhow", - "proc-macro2", - "quote", - "syn 2.0.117", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "attribute-derive-macro" -version = "0.10.5" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7cdbbd4bd005c5d3e2e9c885e6fa575db4f4a3572335b974d8db853b6beb61" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "collection_literals", - "interpolator", - "manyhow", - "proc-macro-utils", - "proc-macro2", - "quote", - "quote-use", - "syn 2.0.117", + "crossbeam-utils", ] [[package]] -name = "autocfg" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" - -[[package]] -name = "backtrace" -version = "0.3.76" +name = "crossbeam-queue" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", + "crossbeam-utils", ] [[package]] -name = "backtrace-ext" -version = "0.2.1" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" -dependencies = [ - "backtrace", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "basic-toml" -version = "0.1.10" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "serde", + "generic-array", + "typenum", ] [[package]] -name = "bindgen" -version = "0.72.1" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 2.1.2", - "shlex 1.3.0", - "syn 2.0.117", -] +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] -name = "bisync" -version = "0.3.0" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5020822f6d6f23196ccaf55e228db36f9de1cf788052b37992e17cbc96ec41a7" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "bisync_macros", + "block-buffer", + "crypto-common", ] [[package]] -name = "bisync_macros" -version = "0.2.3" +name = "encode_unicode" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d21f40d350a700f6aa107e45fb26448cf489d34794b2ba4522181dc9f1173af6" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] -name = "bit-set" -version = "0.8.0" +name = "equivalent" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "bit-vec" -version = "0.8.0" +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] [[package]] -name = "bitflags" -version = "2.13.0" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "bitflagset" -version = "0.0.3" +name = "find-msvc-tools" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b6ee310aa7af14142c8c9121775774ff601ae055ed98ba7fac96098bcde1b9" -dependencies = [ - "num-integer", - "num-traits", - "radium", - "ref-cast", -] +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] -name = "blake3" -version = "1.8.5" +name = "fixedbitset" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", - "cpufeatures 0.3.0", -] +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] -name = "blink-alloc" -version = "0.3.1" +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e669f146bb8b2327006ed94c69cf78c8ec81c100192564654230a40b4f091d82" -dependencies = [ - "allocator-api2", - "parking_lot", -] +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] -name = "block-buffer" -version = "0.10.4" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "generic-array", + "typenum", + "version_check", ] [[package]] -name = "borsh" -version = "1.6.1" +name = "getrandom" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" dependencies = [ - "bytes", - "cfg_aliases", + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", ] [[package]] -name = "bstr" -version = "1.12.1" +name = "globset" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ - "memchr", + "aho-corasick", + "bstr", + "log", "regex-automata", - "serde", + "regex-syntax", ] [[package]] -name = "bumpalo" -version = "3.20.3" +name = "half" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] -name = "bytecount" -version = "0.6.9" +name = "hashbrown" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] [[package]] -name = "bytemuck" -version = "1.25.2" +name = "hashbrown" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] -name = "byteorder" -version = "1.5.0" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "bytes" -version = "1.11.1" +name = "id-arena" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] -name = "camino" -version = "1.2.5" +name = "indexmap" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", "serde_core", ] [[package]] -name = "caseless" -version = "0.2.2" +name = "insta" +version = "1.46.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8" +checksum = "e82db8c87c7f1ccecb34ce0c24399b8a73081427f3c7c50a5d597925356115e4" dependencies = [ - "unicode-normalization", -] - -[[package]] -name = "castaway" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" -dependencies = [ - "rustversion", -] - -[[package]] -name = "cc" -version = "1.2.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" -dependencies = [ - "find-msvc-tools", - "shlex 2.0.1", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "char_str" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576ba56f6ca18ebb069d0d07260407171712aff4dfe15ee3f8982dc16a455bcf" -dependencies = [ - "castaway", - "get-size2 0.10.3", - "itoa", - "ryu", -] - -[[package]] -name = "chrono" -version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" -dependencies = [ - "iana-time-zone", - "num-traits", - "windows-link", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading 0.8.9", -] - -[[package]] -name = "clap" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 3.0.3", -] - -[[package]] -name = "clap_lex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" - -[[package]] -name = "clipboard-win" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" -dependencies = [ - "error-code", -] - -[[package]] -name = "clru" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197fd99cb113a8d5d9b6376f3aa817f32c1078f2343b714fff7d2ca44fdf67d5" -dependencies = [ - "hashbrown 0.16.1", -] - -[[package]] -name = "codespan-reporting" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" -dependencies = [ - "serde", - "termcolor", - "unicode-width 0.1.14", -] - -[[package]] -name = "collection_literals" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2550f75b8cfac212855f6b1885455df8eaee8fe8e246b647d69146142e016084" - -[[package]] -name = "colorchoice" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" - -[[package]] -name = "compact_str" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" -dependencies = [ - "castaway", - "cfg-if", - "itoa", - "rustversion", - "ryu", - "static_assertions", -] - -[[package]] -name = "compact_str" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79fcda08c33bb58b97008b2cdada6622500e949e060f5913361763121abd2416" -dependencies = [ - "castaway", - "cfg-if", - "itoa", - "static_assertions", - "zmij", -] - -[[package]] -name = "console" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" -dependencies = [ - "encode_unicode", - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "constant_time_eq" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "countme" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" - -[[package]] -name = "cow-utils" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "dashmap" -version = "6.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "derive-where" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "displaydoc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", -] - -[[package]] -name = "dragonbox_ecma" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8e701084c37e7ef62d3f9e453b618130cbc0ef3573847785952a3ac3f746bf" - -[[package]] -name = "drop_bomb" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "either" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" - -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "enum_dispatch" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "env_filter" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "error-code" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5343afd4a8365a643ac588dab4cf234a190c7f6c88c9f6dd6ffe00837661b7" - -[[package]] -name = "exitcode" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" - -[[package]] -name = "fancy-regex" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "476de73bddf2ef8490aa4ee8f1cf40b430bf1d56c48c22080e5186952cd580e6" -dependencies = [ - "bit-set", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "faster-hex" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73" -dependencies = [ - "heapless", - "serde", -] - -[[package]] -name = "fastrand" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" - -[[package]] -name = "fd-lock" -version = "4.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" -dependencies = [ - "cfg-if", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "filetime" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" -dependencies = [ - "cfg-if", - "libc", -] - -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "futures-core" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" - -[[package]] -name = "futures-task" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" - -[[package]] -name = "futures-util" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "get-size-derive2" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b6d1e2f75c16bfbcd0f95d84f99858a6e2f885c2287d1f5c3a96e8444a34b4" -dependencies = [ - "attribute-derive", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "get-size-derive2" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c736d226c32e496b8377813b52269e11ad3a48d8373b68862d0364f04fd1229d" -dependencies = [ - "attribute-derive", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "get-size2" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49cf31a6d70300cf81461098f7797571362387ef4bf85d32ac47eaa59b3a5a1a" -dependencies = [ - "compact_str 0.9.1", - "get-size-derive2 0.7.4", - "hashbrown 0.16.1", - "ordermap", - "smallvec", -] - -[[package]] -name = "get-size2" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b411f34418305908ab15a82ff78958c2a9aee9a272b2a2e663836b20a4e4b9d3" -dependencies = [ - "compact_str 0.10.0", - "get-size-derive2 0.10.3", - "hashbrown 0.17.1", - "ordermap", - "smallvec", - "thin-vec", -] - -[[package]] -name = "getopts" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" -dependencies = [ - "unicode-width 0.2.2", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi 5.3.0", - "wasip2", -] - -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "wasip2", - "wasip3", -] - -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - -[[package]] -name = "gix" -version = "0.86.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb3790fd8981cba7949f1ba924ef865d902df731627bc5998d14164063892fce" -dependencies = [ - "gix-actor", - "gix-attributes", - "gix-command", - "gix-commitgraph", - "gix-config", - "gix-date", - "gix-diff", - "gix-discover", - "gix-error", - "gix-features", - "gix-filter", - "gix-fs", - "gix-glob", - "gix-hash", - "gix-hashtable", - "gix-ignore", - "gix-index", - "gix-lock", - "gix-object", - "gix-odb", - "gix-pack", - "gix-path", - "gix-pathspec", - "gix-protocol", - "gix-ref", - "gix-refspec", - "gix-revision", - "gix-revwalk", - "gix-sec", - "gix-shallow", - "gix-submodule", - "gix-tempfile", - "gix-trace", - "gix-traverse", - "gix-url", - "gix-utils", - "gix-validate", - "gix-worktree", - "gix-worktree-stream", - "gix-zlib", - "nonempty", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-actor" -version = "0.41.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33f9308ad6fd35b2a865cbe4117ac61b2be59e4a9ef1621c7a9794f7c8e52c5b" -dependencies = [ - "bstr", - "gix-date", - "gix-error", -] - -[[package]] -name = "gix-attributes" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31c593692ebdc1e38858d9a2b56f6a594c501e24a38971fe6685571f5a07be0" -dependencies = [ - "bstr", - "gix-features", - "gix-glob", - "gix-path", - "gix-quote", - "gix-trace", - "smallvec", - "thiserror", - "unicode-bom", -] - -[[package]] -name = "gix-bitmap" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd1d118d0f5d88b96e6f6e13b566475fef4797ead4a02c26fed36c1375066f7" -dependencies = [ - "gix-error", -] - -[[package]] -name = "gix-chunk" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a871e5cab12ba568845714473505deefffb3c04eb47f4708ce344cd459c1cc" -dependencies = [ - "gix-error", -] - -[[package]] -name = "gix-command" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00706d4fef135ef4b01680d5218c6ee40cda8baf697b864296cbc887d19118f6" -dependencies = [ - "bstr", - "gix-path", - "gix-quote", - "gix-trace", - "shell-words", -] - -[[package]] -name = "gix-commitgraph" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2cd7f054ae2727223fe46dd39c012f066b12f532962d336d29ee193261787da" -dependencies = [ - "bstr", - "gix-chunk", - "gix-error", - "gix-hash", - "memmap2", - "nonempty", -] - -[[package]] -name = "gix-config" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "103d11bef95c467577ecfa8b7b86a22e65af3507b2c9bfa3809a4afbae7df301" -dependencies = [ - "bstr", - "gix-config-value", - "gix-features", - "gix-glob", - "gix-path", - "gix-ref", - "gix-sec", - "gix-utils", - "smallvec", - "thiserror", - "unicode-bom", -] - -[[package]] -name = "gix-config-value" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f813e312a3f7f327187823cd4c754a3e4d948c98907d11e8f37554a2b6b8059" -dependencies = [ - "bitflags", - "bstr", - "gix-path", - "libc", - "thiserror", -] - -[[package]] -name = "gix-date" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e47b9e8cdc688296609b706428de570f88b1e0eed7156dde7b4a89d26fa4567" -dependencies = [ - "bstr", - "gix-error", - "itoa", - "jiff", -] - -[[package]] -name = "gix-diff" -version = "0.66.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee7d89a3c507491cdfc57a1d1e0e300214720b4f7709ebc253e422f99822bfc" -dependencies = [ - "bstr", - "gix-command", - "gix-filter", - "gix-fs", - "gix-hash", - "gix-imara-diff", - "gix-object", - "gix-path", - "gix-tempfile", - "gix-trace", - "gix-traverse", - "gix-worktree", - "thiserror", -] - -[[package]] -name = "gix-discover" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f517766fa1101dfe2606c1a19a8ffa699099030995a9194445446dfe261bdf" -dependencies = [ - "bstr", - "dunce", - "gix-fs", - "gix-path", - "gix-ref", - "gix-sec", - "thiserror", -] - -[[package]] -name = "gix-error" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9292309fd944e71b2a3c96d3c03a6feb8852db646febdde7cbb9f79cb5f329" -dependencies = [ - "bstr", -] - -[[package]] -name = "gix-features" -version = "0.49.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20aa09e83a48dc02c5f5f08578aa79d3ab1bab4618b8c362f88684645a02bdcc" -dependencies = [ - "bytes", - "crc32fast", - "crossbeam-channel", - "gix-path", - "gix-trace", - "gix-utils", - "libc", - "once_cell", - "parking_lot", - "prodash", - "walkdir", -] - -[[package]] -name = "gix-filter" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e7b5dbf524d97e839f642930c76d7f011c0791e7d11d8148989ac5af7c76aa8" -dependencies = [ - "bstr", - "encoding_rs", - "gix-attributes", - "gix-command", - "gix-hash", - "gix-object", - "gix-packetline", - "gix-path", - "gix-quote", - "gix-trace", - "gix-utils", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-fs" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865cf13fcaf5455220546cb9607c416bd1be9a6caafd143655a362fdeab64e80" -dependencies = [ - "bstr", - "gix-features", - "gix-path", - "gix-utils", - "thiserror", -] - -[[package]] -name = "gix-glob" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "421e92a711554fa5827d1b0599d3389acdd0f6729e97a8c5a57d79af1e50bf36" -dependencies = [ - "bitflags", - "bstr", - "gix-features", - "gix-path", -] - -[[package]] -name = "gix-hash" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13adaa73415fd6c902310923f68d0b98e8cecf14b33ea58c02cc387cee56f54e" -dependencies = [ - "faster-hex", - "gix-features", - "sha1-checked", - "thiserror", -] - -[[package]] -name = "gix-hashtable" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78fccd6fea3bcf0b39c076bae60ae49b08daaf538b950202101a981f9d3c01d3" -dependencies = [ - "gix-hash", - "hashbrown 0.17.1", - "parking_lot", -] - -[[package]] -name = "gix-ignore" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cff8e8aa125e39377456073e63df3334d9e5741372ddcc226198015076dda2" -dependencies = [ - "bstr", - "gix-glob", - "gix-path", - "gix-trace", - "unicode-bom", -] - -[[package]] -name = "gix-imara-diff" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a791e6620676a875f362f3156ed213e73ca099a09bf992c18812abe65cc37b1" -dependencies = [ - "bstr", - "hashbrown 0.15.5", -] - -[[package]] -name = "gix-index" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5009c4e7e9f9b4cfaaab1153e49133eb04d79c015b5702d6c3d2ab94271a89c6" -dependencies = [ - "bitflags", - "bstr", - "filetime", - "fnv", - "gix-bitmap", - "gix-features", - "gix-fs", - "gix-hash", - "gix-lock", - "gix-object", - "gix-traverse", - "gix-utils", - "gix-validate", - "hashbrown 0.17.1", - "itoa", - "libc", - "memmap2", - "rustix", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-lock" -version = "24.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c69157820343bf1c6e4b88b9808e920900de02e18aaf5862b30ada43814848" -dependencies = [ - "gix-tempfile", - "gix-utils", - "thiserror", -] - -[[package]] -name = "gix-object" -version = "0.63.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e48c235e7f886eb819fc878af75be889333dd3c38bee02ed7af48ae2cf596c4" -dependencies = [ - "bstr", - "gix-actor", - "gix-date", - "gix-features", - "gix-hash", - "gix-hashtable", - "gix-utils", - "gix-validate", - "itoa", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-odb" -version = "0.83.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd494ffb5037e62b8220109e894d2861ff2150a2cacbfccdba57ae1ebab2b96" -dependencies = [ - "arc-swap", - "gix-features", - "gix-fs", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-pack", - "gix-path", - "gix-quote", - "gix-zlib", - "memmap2", - "parking_lot", - "tempfile", - "thiserror", -] - -[[package]] -name = "gix-pack" -version = "0.73.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d5446127b269706e85998065267ddd2ccc3550179da6780b22fe496175ccb20" -dependencies = [ - "clru", - "gix-chunk", - "gix-error", - "gix-features", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-path", - "gix-zlib", - "memmap2", - "smallvec", - "thiserror", - "uluru", -] - -[[package]] -name = "gix-packetline" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3766025c72319c4accdd854a18e6f0dd176c8eb0f3bc8a60a7765be2b50cabf2" -dependencies = [ - "bstr", - "faster-hex", - "gix-trace", - "thiserror", -] - -[[package]] -name = "gix-path" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ed3e8d7a82e886e17a72e03d4ba0c13db6f2219b6cd4e2900b4cae426ec20c9" -dependencies = [ - "bstr", - "gix-trace", - "gix-validate", - "thiserror", -] - -[[package]] -name = "gix-pathspec" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f6fa5f8007f008187c3f60b4373209ca83d1cc947f35ede03e16cd15a4d137" -dependencies = [ - "bitflags", - "bstr", - "gix-attributes", - "gix-config-value", - "gix-glob", - "gix-path", - "thiserror", -] - -[[package]] -name = "gix-protocol" -version = "0.64.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dede40e89c1e90f548415f50636bb051f6d9c60f68b8b710bc07825722d19588" -dependencies = [ - "bisync", - "bstr", - "gix-date", - "gix-features", - "gix-hash", - "gix-ref", - "gix-shallow", - "gix-transport", - "gix-utils", - "nonempty", - "thiserror", -] - -[[package]] -name = "gix-quote" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e541fc33cc2b783b7979040d445a0c86a2eca747c8faea4ca84230d06ae6ef" -dependencies = [ - "bstr", - "gix-error", - "gix-utils", -] - -[[package]] -name = "gix-ref" -version = "0.66.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb0c90a8f6202ceaaa22996cbf837c943ccb2d8af9ff3490f0758305e6b7883" -dependencies = [ - "gix-actor", - "gix-features", - "gix-fs", - "gix-hash", - "gix-lock", - "gix-object", - "gix-path", - "gix-tempfile", - "gix-utils", - "gix-validate", - "memmap2", - "thiserror", -] - -[[package]] -name = "gix-refspec" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7406282cc0259b51f6aee299ca3d31279a020530363152a2e6c96e8a7f7bbc83" -dependencies = [ - "bstr", - "gix-error", - "gix-glob", - "gix-hash", - "gix-revision", - "gix-validate", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-revision" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55e09d4a1ecf2beecc8c09cafcad37979e805b31f588b0e957e191df5783681" -dependencies = [ - "bitflags", - "bstr", - "gix-commitgraph", - "gix-date", - "gix-error", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", - "gix-trace", - "nonempty", -] - -[[package]] -name = "gix-revwalk" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c113c0a53294dc6280ffc06cbcc4f50f820397e97d6a00b429a44b8db26e29" -dependencies = [ - "gix-commitgraph", - "gix-date", - "gix-error", - "gix-hash", - "gix-hashtable", - "gix-object", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-sec" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4fe6c152c1d50aea36f299825702cd37e303307832fec1d0fdd5844e47ce2f" -dependencies = [ - "bitflags", - "gix-path", - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "gix-shallow" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecc9f4b40537043e4bbd7d3d1760e74fb8e7b07a546166b558acaa73ad97f4a" -dependencies = [ - "bstr", - "gix-hash", - "gix-lock", - "nonempty", - "thiserror", -] - -[[package]] -name = "gix-submodule" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd98077a56d08886112e6b08dc94076d03539f4bc0b9d7880e4be2b8a640d8c" -dependencies = [ - "bstr", - "gix-config", - "gix-path", - "gix-pathspec", - "gix-refspec", - "gix-url", - "thiserror", -] - -[[package]] -name = "gix-tempfile" -version = "24.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b675b920bd5a61d17ad542772f03ec34c60feb8ff683e1560c03ae967363731e" -dependencies = [ - "dashmap", - "gix-fs", - "libc", - "parking_lot", - "tempfile", -] - -[[package]] -name = "gix-trace" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be3eb81d9dc914335923e50d52829c551feefd6a72d176c4130c546b67a60814" - -[[package]] -name = "gix-transport" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c1bcf30081eb8ab04540a5795c67a2fcb22cb2e976e8b1a4ea657b1ed61469" -dependencies = [ - "bstr", - "gix-command", - "gix-features", - "gix-packetline", - "gix-path", - "gix-quote", - "gix-sec", - "gix-url", - "thiserror", -] - -[[package]] -name = "gix-traverse" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008c5cd879e46e86b5c2469e633611978b18775d53d05668d691bc13088bd409" -dependencies = [ - "bitflags", - "gix-commitgraph", - "gix-date", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-url" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d10e53b8eae21ee601687f47bbbd6cb2ed7162cb4c1cafdd422fb7ec64cbee" -dependencies = [ - "bstr", - "gix-path", - "gix-utils", - "percent-encoding", - "thiserror", -] - -[[package]] -name = "gix-utils" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1795bd2a970ca8b2185318c2abb97d955c71992f1cf28de73ad3b593a9f3ce8" -dependencies = [ - "bstr", - "fastrand", - "getrandom 0.4.2", - "unicode-normalization", -] - -[[package]] -name = "gix-validate" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a034e84d1e04e1b1f20f51f12491da230b6ac8b925d0c8e1b89bcd87a7c5ccc" -dependencies = [ - "bstr", -] - -[[package]] -name = "gix-worktree" -version = "0.55.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31eb8e675122e83585e461fe28f68ff8c5ed55b49017b697e7e76423ff973424" -dependencies = [ - "bstr", - "gix-attributes", - "gix-features", - "gix-fs", - "gix-glob", - "gix-hash", - "gix-ignore", - "gix-index", - "gix-object", - "gix-path", - "gix-validate", -] - -[[package]] -name = "gix-worktree-stream" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b088c8724e7be120c4798dd86925cf05332c9d356a463542578600c50c7a549" -dependencies = [ - "gix-attributes", - "gix-error", - "gix-features", - "gix-filter", - "gix-fs", - "gix-hash", - "gix-object", - "gix-path", - "gix-traverse", - "parking_lot", -] - -[[package]] -name = "gix-zlib" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e8813f5579b3075ff9c90f7c59cd2b62b4ebb639361f0911648b22d7446cc7c" -dependencies = [ - "thiserror", - "zlib-rs", -] - -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - -[[package]] -name = "globset" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", -] - -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", - "serde", - "serde_core", -] - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "hmac-sha256" -version = "1.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec9d92d097f4749b64e8cc33d924d9f40a2d4eb91402b458014b781f5733d60f" - -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_casemap" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "070f98b5b82798fcb93654bf96ed9f40064fc44c86f51a09ea711092cd5cc5be" -dependencies = [ - "icu_casemap_data", - "icu_collections", - "icu_locale_core", - "icu_properties", - "icu_provider", - "potential_utf", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_casemap_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "846b0857ca091204be3c874bc93daaf89d4777e8d2d20b0d3ffe8f671d98014b" - -[[package]] -name = "icu_collections" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" -dependencies = [ - "displaydoc", - "potential_utf", - "serde", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" -dependencies = [ - "displaydoc", - "litemap", - "serde", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_properties" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "serde", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" - -[[package]] -name = "icu_provider" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" -dependencies = [ - "displaydoc", - "icu_locale_core", - "serde", - "stable_deref_trait", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[package]] -name = "ignore" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata", - "same-file", - "walkdir", - "winapi-util", -] - -[[package]] -name = "indexmap" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown 0.17.1", - "serde", - "serde_core", -] - -[[package]] -name = "inotify" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "insta" -version = "1.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0f8fee8c926415c58d6ae43a08523a26faccb2323f5e6b644fe7dd4ef6b82" -dependencies = [ - "console", - "once_cell", - "pest", - "pest_derive", - "serde", - "similar", - "tempfile", -] - -[[package]] -name = "interpolator" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" - -[[package]] -name = "intl" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c21e11d6a1018820ee57bc5cbdc75d71462b1b0b5f188730a7c005cd55b1a" - -[[package]] -name = "is-macro" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "is_ci" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "jiff" -version = "0.2.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102" -dependencies = [ - "jiff-static", - "jiff-tzdb-platform", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", - "windows-link", -] - -[[package]] -name = "jiff-static" -version = "0.2.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "jiff-tzdb" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" - -[[package]] -name = "jiff-tzdb-platform" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" -dependencies = [ - "jiff-tzdb", -] - -[[package]] -name = "jod-thread" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a037eddb7d28de1d0fc42411f501b53b75838d313908078d6698d064f3029b24" - -[[package]] -name = "js-sys" -version = "0.3.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" -dependencies = [ - "cfg-if", - "futures-util", - "wasm-bindgen", -] - -[[package]] -name = "junction" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfc352a66ba903c23239ef51e809508b6fc2b0f90e3476ac7a9ff47e863ae95" -dependencies = [ - "scopeguard", - "windows-sys 0.61.2", -] - -[[package]] -name = "kqueue" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "273c0752728918e0ac4976f2b275b6fefb9ecd400585dec929419f3844cd87b5" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "lexical-parse-float" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" -dependencies = [ - "lexical-parse-integer", - "lexical-util", -] - -[[package]] -name = "lexical-parse-integer" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" -dependencies = [ - "lexical-util", -] - -[[package]] -name = "lexical-util" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" - -[[package]] -name = "libc" -version = "0.2.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libffi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8d526bc07aa02e6826944ec446ecd8d228bd97b1cbd21e5bc5e3407a09a585" -dependencies = [ - "libc", - "libffi-sys", -] - -[[package]] -name = "libffi-sys" -version = "4.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54d39d034f5ea2662814789448722078d01cc9431a2a09ff15e55f0df7120bae" -dependencies = [ - "cc", -] - -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - -[[package]] -name = "libloading" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" -dependencies = [ - "cfg-if", - "windows-link", -] - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" - -[[package]] -name = "lz4_flex" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef0d4ed8669f8f8826eb00dc878084aa8f253506c4fd5e8f58f5bce72ddb97e" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "mago-allocator" -version = "1.47.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b083fd718cbb255b23dd6d3507b45be74e198662ad04f06f9a1865ef5db05cd" -dependencies = [ - "allocator-api2", - "blink-alloc", - "hashbrown 0.17.1", -] - -[[package]] -name = "mago-database" -version = "1.47.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49f7dc70d58c3082fd118fb0bcb04455adde1a120419a52aca3d5365aef83df" -dependencies = [ - "foldhash 0.2.0", - "glob", - "globset", - "memchr", - "notify", - "rayon", - "tracing", - "walkdir", -] - -[[package]] -name = "mago-php-version" -version = "1.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a1f83e66a6f38a5eb2d94f04663e65e73903d23759851f4725fa83a385611b" -dependencies = [ - "schemars", -] - -[[package]] -name = "mago-reporting" -version = "1.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12235f943de861dc9bd47df5dfcf542c1b5cf69ec9fafa8d35c886d07ea0aaa9" -dependencies = [ - "ariadne", - "blake3", - "codespan-reporting", - "foldhash 0.2.0", - "mago-database", - "mago-span", - "mago-text-edit", - "regex", - "schemars", - "strum", - "termcolor", - "tracing", -] - -[[package]] -name = "mago-span" -version = "1.47.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7874d65d2dec0ef9127c93bd5f7f014519dc72b1b5bba1666c06d60301f2904" -dependencies = [ - "mago-database", -] - -[[package]] -name = "mago-syntax" -version = "1.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83cf318dcd287ed33af5f7fc431c88983a4b9d5df12f01d3317b8e16d0c42e4e" -dependencies = [ - "mago-allocator", - "mago-database", - "mago-php-version", - "mago-reporting", - "mago-span", - "mago-syntax-core", - "memchr", - "ordered-float", - "paste", - "strum", -] - -[[package]] -name = "mago-syntax-core" -version = "1.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90db7e12c57a030e86cc616e0033b7d323fab2a6b2405f8a0fc219b74882e502" -dependencies = [ - "mago-allocator", - "mago-database", - "mago-span", - "memchr", -] - -[[package]] -name = "mago-text-edit" -version = "1.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b22bdba02d288a2184fbe5d286fd824e7aea1ebceef0e3dcc34dd03fb31eeee" - -[[package]] -name = "malachite-base" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f44099731f17094b07825c88ccb5fbd1bfa1f82fafff7daa33e8b8652db16e" -dependencies = [ - "hashbrown 0.16.1", - "itertools 0.14.0", - "libm", - "ryu", -] - -[[package]] -name = "malachite-bigint" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc58206ba15e9c406e20c95c5f86efa07b12f94080945908e910b3a0faa23fef" -dependencies = [ - "malachite-base", - "malachite-nz", - "num-integer", - "num-traits", - "paste", -] - -[[package]] -name = "malachite-nz" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a137660cdba20f136c8a223125f08088adb4e0b72fbb8466f08c43e31cc0427d" -dependencies = [ - "itertools 0.14.0", - "libm", - "malachite-base", - "wide", -] - -[[package]] -name = "malachite-q" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffcbeed95e34c0fcc3864ccd146e129cbbf7de1513d3afbcfb47c7674c82d94" -dependencies = [ - "itertools 0.14.0", - "libm", - "malachite-base", - "malachite-nz", -] - -[[package]] -name = "manyhow" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" -dependencies = [ - "manyhow-macros", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "manyhow-macros" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" -dependencies = [ - "proc-macro-utils", - "proc-macro2", - "quote", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "mehen" -version = "1.10.0" -dependencies = [ - "camino", - "clap", - "env_logger", - "insta", - "log", - "mehen-core", - "mehen-engine", - "mehen-report", - "serde_json", - "tempfile", -] - -[[package]] -name = "mehen-antlr" -version = "1.10.0" -dependencies = [ - "antlr-rust-runtime", - "mehen-core", -] - -[[package]] -name = "mehen-c" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-metrics", - "mehen-report", - "mehen-tree-sitter", - "num", - "num-derive", - "num-traits", - "serde_json", - "smol_str", - "tree-sitter", - "tree-sitter-c", -] - -[[package]] -name = "mehen-core" -version = "1.10.0" -dependencies = [ - "camino", - "serde", - "smol_str", -] - -[[package]] -name = "mehen-coverage" -version = "1.10.0" -dependencies = [ - "camino", - "insta", - "pretty_assertions", - "quick-xml", - "serde", - "serde_json", -] - -[[package]] -name = "mehen-coverage-discovery" -version = "1.10.0" -dependencies = [ - "camino", - "globset", - "ignore", - "insta", - "log", - "mehen-coverage", - "pretty_assertions", - "quick-xml", - "serde", - "serde_json", - "tempfile", - "toml", -] - -[[package]] -name = "mehen-csharp" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-antlr", - "mehen-core", - "mehen-csharp-parser", - "mehen-metrics", - "mehen-report", - "serde_json", - "smol_str", -] - -[[package]] -name = "mehen-csharp-parser" -version = "1.10.0" -dependencies = [ - "antlr-rust-runtime", -] - -[[package]] -name = "mehen-engine" -version = "1.10.0" -dependencies = [ - "camino", - "clap", - "gix", - "globset", - "ignore", - "insta", - "log", - "mehen-c", - "mehen-core", - "mehen-coverage", - "mehen-coverage-discovery", - "mehen-csharp", - "mehen-git", - "mehen-go", - "mehen-java", - "mehen-kotlin", - "mehen-markdown", - "mehen-metrics", - "mehen-php", - "mehen-powershell", - "mehen-python", - "mehen-report", - "mehen-ruby", - "mehen-rust", - "mehen-sql", - "mehen-typescript", - "miette", - "pretty_assertions", - "serde", - "serde_json", - "tempfile", - "toml", -] - -[[package]] -name = "mehen-git" -version = "1.10.0" -dependencies = [ - "gix", - "log", - "tempfile", -] - -[[package]] -name = "mehen-go" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-metrics", - "mehen-report", - "mehen-tree-sitter", - "num", - "num-derive", - "num-traits", - "serde_json", - "smol_str", - "tree-sitter", - "tree-sitter-go", -] - -[[package]] -name = "mehen-java" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-antlr", - "mehen-core", - "mehen-java-parser", - "mehen-metrics", - "mehen-report", - "serde_json", - "smol_str", -] - -[[package]] -name = "mehen-java-parser" -version = "1.10.0" -dependencies = [ - "antlr-rust-runtime", -] - -[[package]] -name = "mehen-kotlin" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-antlr", - "mehen-core", - "mehen-kotlin-parser", - "mehen-metrics", - "mehen-report", - "serde_json", - "smol_str", -] - -[[package]] -name = "mehen-kotlin-parser" -version = "1.10.0" -dependencies = [ - "antlr-rust-runtime", -] - -[[package]] -name = "mehen-markdown" -version = "1.10.0" -dependencies = [ - "camino", - "insta", - "mehen-core", - "mehen-engine", - "pretty_assertions", - "pulldown-cmark", - "regex", - "serde", - "serde_json", - "tempfile", - "unicode-script", - "unicode-segmentation", -] - -[[package]] -name = "mehen-metrics" -version = "1.10.0" -dependencies = [ - "mehen-core", - "serde", - "smol_str", -] - -[[package]] -name = "mehen-php" -version = "1.10.0" -dependencies = [ - "insta", - "mago-allocator", - "mago-database", - "mago-span", - "mago-syntax", - "mago-syntax-core", - "mehen-core", - "mehen-metrics", - "mehen-report", - "serde_json", - "smol_str", -] - -[[package]] -name = "mehen-powershell" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-metrics", - "mehen-report", - "mehen-tree-sitter", - "smol_str", - "tree-sitter", - "tree-sitter-pwsh", -] - -[[package]] -name = "mehen-python" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-metrics", - "mehen-report", - "ruff_python_ast", - "ruff_python_parser", - "ruff_text_size", - "serde_json", - "smol_str", -] - -[[package]] -name = "mehen-report" -version = "1.10.0" -dependencies = [ - "mehen-core", - "mehen-markdown", - "serde", - "serde_json", -] - -[[package]] -name = "mehen-ruby" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-metrics", - "mehen-report", - "ruby-prism", - "serde_json", - "smol_str", -] - -[[package]] -name = "mehen-rust" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-metrics", - "mehen-report", - "ra_ap_syntax", - "serde_json", - "smol_str", -] - -[[package]] -name = "mehen-sql" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-report", - "serde_json", - "smol_str", - "sqruff-lib-core", - "sqruff-lib-dialects", - "strum", -] - -[[package]] -name = "mehen-tree-sitter" -version = "1.10.0" -dependencies = [ - "mehen-core", - "mehen-metrics", - "smol_str", - "tree-sitter", -] - -[[package]] -name = "mehen-typescript" -version = "1.10.0" -dependencies = [ - "insta", - "mehen-core", - "mehen-metrics", - "mehen-report", - "oxc_allocator", - "oxc_ast", - "oxc_ast_visit", - "oxc_parser", - "oxc_span", - "oxc_syntax", - "serde_json", - "smol_str", -] - -[[package]] -name = "memchr" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" - -[[package]] -name = "memmap2" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miette" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" -dependencies = [ - "backtrace", - "backtrace-ext", - "cfg-if", - "miette-derive", - "owo-colors", - "supports-color", - "supports-hyperlinks", - "supports-unicode", - "terminal_size", - "textwrap", - "unicode-width 0.1.14", -] - -[[package]] -name = "miette-derive" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "miow" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nonempty" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9737e026353e5cd0736f98eddae28665118eb6f6600902a7f50db585621fecb6" - -[[package]] -name = "nonmax" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" - -[[package]] -name = "notify" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" -dependencies = [ - "bitflags", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "notify-types", - "walkdir", - "windows-sys 0.60.2", -] - -[[package]] -name = "notify-types" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint 0.4.6", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e7820bc0a80a0238e650327316f929ba18d5be054b647490a3a6a339f3e7c0" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e98dc3b890f6c23a0f9d3d491a2823d0dea0fa656302a13dd225fa924112a8" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - -[[package]] -name = "optional" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978aa494585d3ca4ad74929863093e87cac9790d81fe7aba2b3dc2890643a0fc" - -[[package]] -name = "ordered-float" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" -dependencies = [ - "num-traits", - "rand", -] - -[[package]] -name = "ordermap" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7476a5b122ff1fce7208e7ee9dccd0a516e835f5b8b19b8f3c98a34cf757c1" -dependencies = [ - "indexmap", -] - -[[package]] -name = "owo-colors" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" - -[[package]] -name = "oxc_allocator" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "064fce871c5cb07e557049ed27c8ca2aa530db797f73424c67e4bb8cfe61175e" -dependencies = [ - "allocator-api2", - "hashbrown 0.17.1", - "oxc_data_structures", - "rustc-hash 2.1.2", -] - -[[package]] -name = "oxc_ast" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a999fd4494b604fc0328fc43443bc1298722500587d87d7e993118bd82c65d7b" -dependencies = [ - "bitflags", - "oxc_allocator", - "oxc_ast_macros", - "oxc_data_structures", - "oxc_diagnostics", - "oxc_estree", - "oxc_regular_expression", - "oxc_span", - "oxc_str", - "oxc_syntax", -] - -[[package]] -name = "oxc_ast_macros" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d715e3c300c95b1d797b05526567161fd86fcac2ac68235101c61b736f216cde" -dependencies = [ - "phf 0.14.0", - "proc-macro2", - "quote", - "syn 3.0.3", -] - -[[package]] -name = "oxc_ast_visit" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9d77b5c27575ef7d624de1f226caeca3c0d3fcc2347bdaa788d5c4a85512d" -dependencies = [ - "oxc_allocator", - "oxc_ast", - "oxc_span", - "oxc_syntax", -] - -[[package]] -name = "oxc_data_structures" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15a23b57a931fda6bc9a4fdc3fbabcac6a2edfd0b7216cb7c81432f0e9f54d9" - -[[package]] -name = "oxc_diagnostics" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d0ce1ec51b07b6501eecedd5ab50835b7ebe5c8463cada3b2e6d984d0943af" -dependencies = [ - "bytecount", - "cow-utils", - "itoa", - "memchr", - "owo-colors", - "oxc_span", - "percent-encoding", - "smallvec", - "textwrap", - "unicode-segmentation", - "unicode-width 0.2.2", -] - -[[package]] -name = "oxc_ecmascript" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b5d3d07165b7aadcd021f62cd95fb7d62cb6977b8bbfb42fa12adbfb7e75257" -dependencies = [ - "dragonbox_ecma", - "itoa", - "num-bigint 0.5.1", - "num-traits", - "oxc_ast", - "oxc_data_structures", - "oxc_span", - "oxc_syntax", -] - -[[package]] -name = "oxc_estree" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7af86a59b7aeb2845ffea2cc21ae259053865b175e9ac936a7d72f2744abe5" - -[[package]] -name = "oxc_index" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "191884bee6c3744909a51acc7d78d4ae370d817b25875b10642f632327b6296e" -dependencies = [ - "nonmax", - "serde", -] - -[[package]] -name = "oxc_parser" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311c29dfdf55ea8bf065cf300b3d0dca5fe1c0fb8059c9ba70a6c98cce75306e" -dependencies = [ - "bitflags", - "cow-utils", - "memchr", - "num-bigint 0.5.1", - "num-traits", - "oxc_allocator", - "oxc_ast", - "oxc_data_structures", - "oxc_diagnostics", - "oxc_ecmascript", - "oxc_regular_expression", - "oxc_span", - "oxc_str", - "oxc_syntax", - "rustc-hash 2.1.2", - "seq-macro", -] - -[[package]] -name = "oxc_regular_expression" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31839a373ad02a37fad54244a3eb710f9a94b5e2e16ca0e1d28a37b4c75b8ebc" -dependencies = [ - "bitflags", - "oxc_allocator", - "oxc_ast_macros", - "oxc_diagnostics", - "oxc_span", - "oxc_str", - "phf 0.14.0", - "rustc-hash 2.1.2", - "unicode-id-start", -] - -[[package]] -name = "oxc_span" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c355ae1fa3e865c28cb8a85735ecafd1bb6340a5b880c638d127c1f2d61a98a5" -dependencies = [ - "compact_str 0.10.0", - "oxc_allocator", - "oxc_ast_macros", - "oxc_estree", - "oxc_str", -] - -[[package]] -name = "oxc_str" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba45ef9efa8296e647aa37b2b21936cb520953031edc1ef6352281bbea22faa" -dependencies = [ - "compact_str 0.10.0", - "hashbrown 0.17.1", - "oxc_allocator", - "oxc_estree", -] - -[[package]] -name = "oxc_syntax" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0970d9be099a082711b574d58add258549580a70fe6546b99a067bbd7ad4a264" -dependencies = [ - "bitflags", - "cow-utils", - "dragonbox_ecma", - "nonmax", - "oxc_allocator", - "oxc_ast_macros", - "oxc_estree", - "oxc_index", - "oxc_span", - "oxc_str", - "phf 0.14.0", - "unicode-id-start", -] - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pest" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "pest_meta" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" -dependencies = [ - "pest", - "sha2", -] - -[[package]] -name = "petgraph" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" -dependencies = [ - "fixedbitset", - "hashbrown 0.15.5", - "indexmap", -] - -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_shared 0.11.3", -] - -[[package]] -name = "phf" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" -dependencies = [ - "phf_macros 0.13.1", - "phf_shared 0.13.1", -] - -[[package]] -name = "phf" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "010378780309880b08997fae13be7834dba947d36393bd372f2b1556deb2a2f6" -dependencies = [ - "phf_macros 0.14.0", - "phf_shared 0.14.0", - "serde", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared 0.11.3", - "rand", -] - -[[package]] -name = "phf_generator" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" -dependencies = [ - "fastrand", - "phf_shared 0.13.1", -] - -[[package]] -name = "phf_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb62e0959d5a1bebc965f4d15d9e2b7cea002b6b0f5ba8cde6cc26738467100" -dependencies = [ - "fastrand", - "phf_shared 0.14.0", -] - -[[package]] -name = "phf_macros" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" -dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "phf_macros" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fa8d0ca26d424d27630da600c6624696e7dec8bf7b3b492b383c5dc49e5e085" -dependencies = [ - "phf_generator 0.14.0", - "phf_shared 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fd9027e2d9319be6349febd1db4e8d02aa544921200c9b777720ac34a3aa89" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pmutil" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "portable-atomic-util" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" -dependencies = [ - "serde_core", - "writeable", - "zerovec", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "pretty_assertions" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" -dependencies = [ - "diff", - "yansi", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - -[[package]] -name = "proc-macro-utils" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" -dependencies = [ - "proc-macro2", - "quote", - "smallvec", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prodash" -version = "31.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962200e2d7d551451297d9fdce85138374019ada198e30ea9ede38034e27604c" -dependencies = [ - "parking_lot", -] - -[[package]] -name = "psm" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea" -dependencies = [ - "ar_archive_writer", - "cc", -] - -[[package]] -name = "pulldown-cmark" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" -dependencies = [ - "bitflags", - "memchr", - "unicase", -] - -[[package]] -name = "quick-xml" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "quote-use" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e" -dependencies = [ - "quote", - "quote-use-macros", -] - -[[package]] -name = "quote-use-macros" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35" -dependencies = [ - "proc-macro-utils", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "ra-ap-rustc_lexer" -version = "0.166.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527c12b3731b7d0692498012810b85b2b8dfdb8b514321ed6afc434bd1c70191" -dependencies = [ - "memchr", - "unicode-ident", - "unicode-properties", -] - -[[package]] -name = "ra_ap_edition" -version = "0.0.348" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8c90ffac4361bd329fe2360e858d92bb55fbcf92eee0a8aba1dc73177685b45" - -[[package]] -name = "ra_ap_parser" -version = "0.0.348" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9e5e8bba8eb47e76f228d0bd13b09e55295b956043f4520641b50458f9aeb8" -dependencies = [ - "drop_bomb", - "ra-ap-rustc_lexer", - "ra_ap_edition", - "rustc-literal-escaper", - "tracing", - "winnow 0.7.15", -] - -[[package]] -name = "ra_ap_stdx" -version = "0.0.348" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28196cfcf2da5ba087ff2fe535763642ce5f1b028d3c369c8b00631f30b6015f" -dependencies = [ - "crossbeam-channel", - "crossbeam-utils", - "itertools 0.15.0", - "jod-thread", - "libc", - "miow", - "tracing", - "windows-sys 0.61.2", -] - -[[package]] -name = "ra_ap_syntax" -version = "0.0.348" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeda1039f9e669fee08df80409b08e952795f1609dec09745e7ad890e59aa3c" -dependencies = [ - "either", - "itertools 0.15.0", - "ra-ap-rustc_lexer", - "ra_ap_parser", - "ra_ap_stdx", - "rowan", - "rustc-hash 2.1.2", - "rustc-literal-escaper", - "smallvec", - "smol_str", - "tracing", - "triomphe", -] - -[[package]] -name = "radium" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1775bc532a9bfde46e26eba441ca1171b91608d14a3bae71fea371f18a00cffe" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - -[[package]] -name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rayon" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "ref-cast" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "regex" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" - -[[package]] -name = "result-like" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffa194499266bd8a1ac7da6ac7355aa0f81ffa1a5db2baaf20dd13854fd6f4e" -dependencies = [ - "result-like-derive", -] - -[[package]] -name = "result-like-derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d3b03471c9700a3a6bd166550daaa6124cb4a146ea139fb028e4edaa8f4277" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "rowan" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b574c58582fa59fa43a2feb6608b8744184659f08a2e0117e4b8224d95ed61" -dependencies = [ - "countme", - "hashbrown 0.14.5", - "memoffset", - "rustc-hash 1.1.0", - "text-size", -] - -[[package]] -name = "ruby-prism" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b302f00359d0b5423a600314935ca5f994484e15da2db5345631d28c6e029d6" -dependencies = [ - "ruby-prism-sys", - "serde", - "serde_json", -] - -[[package]] -name = "ruby-prism-sys" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f85fd9571455bdca2b3bf0b2f543cd13ac39d5de0026a8eb2deb94ffd264f00" -dependencies = [ - "bindgen", - "cc", -] - -[[package]] -name = "ruff_python_ast" -version = "0.0.7" -source = "git+https://github.com/astral-sh/ruff?tag=0.16.1#80790b348b5188e7fc253665540f442c6ec7dd05" -dependencies = [ - "aho-corasick", - "arrayvec", - "bitflags", - "char_str", - "compact_str 0.10.0", - "get-size2 0.10.3", - "is-macro", - "memchr", - "ruff_python_trivia", - "ruff_source_file", - "ruff_text_size", - "rustc-hash 2.1.2", - "thin-vec", - "thiserror", -] - -[[package]] -name = "ruff_python_parser" -version = "0.0.7" -source = "git+https://github.com/astral-sh/ruff?tag=0.16.1#80790b348b5188e7fc253665540f442c6ec7dd05" -dependencies = [ - "bitflags", - "bstr", - "drop_bomb", - "get-size2 0.10.3", - "memchr", - "ruff_python_ast", - "ruff_python_trivia", - "ruff_text_size", - "rustc-hash 2.1.2", - "static_assertions", - "thin-vec", - "unicode-ident", - "unicode-normalization", - "unicode_names2 1.3.0", -] - -[[package]] -name = "ruff_python_trivia" -version = "0.0.7" -source = "git+https://github.com/astral-sh/ruff?tag=0.16.1#80790b348b5188e7fc253665540f442c6ec7dd05" -dependencies = [ - "itertools 0.15.0", - "ruff_source_file", - "ruff_text_size", - "rustc-hash 2.1.2", - "unicode-ident", -] - -[[package]] -name = "ruff_source_file" -version = "0.0.7" -source = "git+https://github.com/astral-sh/ruff?tag=0.16.1#80790b348b5188e7fc253665540f442c6ec7dd05" -dependencies = [ - "memchr", - "ruff_text_size", -] - -[[package]] -name = "ruff_text_size" -version = "0.0.7" -source = "git+https://github.com/astral-sh/ruff?tag=0.16.1#80790b348b5188e7fc253665540f442c6ec7dd05" -dependencies = [ - "get-size2 0.10.3", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - -[[package]] -name = "rustc-literal-escaper" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be87abb9e40db7466e0681dc8ecd9dcfd40360cb10b4c8fe24a7c4c3669b198" - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustpython-codegen" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e4fc1331357a7afc6d52d637796a946b1efaaca07c914132f8fd4fd69d595f" -dependencies = [ - "ahash", - "bitflags", - "indexmap", - "itertools 0.14.0", - "log", - "malachite-bigint", - "memchr", - "num-complex", - "num-traits", - "rustpython-compiler-core", - "rustpython-literal", - "rustpython-ruff_python_ast", - "rustpython-ruff_text_size", - "rustpython-wtf8", - "thiserror", - "unicode_names2 2.0.0", -] - -[[package]] -name = "rustpython-common" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3c0808a170ea900e0489a06d6aa04ce5d27d62b347836c2f98df958f47f243" -dependencies = [ - "ascii", - "bitflags", - "cfg-if", - "getrandom 0.3.4", - "itertools 0.14.0", - "libc", - "lock_api", - "malachite-base", - "malachite-bigint", - "malachite-q", - "nix", - "num-complex", - "num-traits", - "radium", - "rustpython-literal", - "rustpython-wtf8", - "siphasher", - "unicode_names2 2.0.0", - "widestring", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustpython-compiler" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fa83b852bbc5461c5214060099d7597785d201aa0bf1a87d77967518f60144" -dependencies = [ - "rustpython-codegen", - "rustpython-compiler-core", - "rustpython-ruff_python_ast", - "rustpython-ruff_python_parser", - "rustpython-ruff_source_file", - "rustpython-ruff_text_size", - "thiserror", -] - -[[package]] -name = "rustpython-compiler-core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f18ba67b55aec49c3e2d223bbdcacff0d7e0f5d304fb0e64b044b8dca13c7c" -dependencies = [ - "bitflags", - "bitflagset", - "itertools 0.14.0", - "lz4_flex", - "malachite-bigint", - "num-complex", - "rustpython-ruff_source_file", - "rustpython-wtf8", -] - -[[package]] -name = "rustpython-derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6c04350bee9e54b241b93675a0558c2b33fe982213e47a6da0924898af0f2" -dependencies = [ - "rustpython-compiler", - "rustpython-derive-impl", - "syn 2.0.117", -] - -[[package]] -name = "rustpython-derive-impl" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322d64ea8a21d52cd769db0f6190b6e7c17963b13c8c17f39d7364e68af96731" -dependencies = [ - "itertools 0.14.0", - "maplit", - "proc-macro2", - "quote", - "rustpython-compiler-core", - "rustpython-doc", - "syn 2.0.117", - "syn-ext", - "textwrap", -] - -[[package]] -name = "rustpython-doc" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f286d8b5872aa53dceb7a8d8c6a29fe85150f0a137fecf1c9a3e0a8345cbc19b" -dependencies = [ - "phf 0.13.1", -] - -[[package]] -name = "rustpython-literal" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb46f7afce00e4797f82062e09881ec5e7226d858104bf4a8a9c3b996de2b4a" -dependencies = [ - "hexf-parse", - "is-macro", - "lexical-parse-float", - "num-traits", - "rustpython-wtf8", - "unic-ucd-category", -] - -[[package]] -name = "rustpython-pylib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1878a8c2fb45dfcbcee1d4bba8d4a3d9b65c4f20dc70d08179c3efa223bbab" -dependencies = [ - "glob", - "rustpython-compiler-core", - "rustpython-derive", -] - -[[package]] -name = "rustpython-ruff_python_ast" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f021ff72cabf5e2cd6d8ec8813d376a8445a228dc610ab56c27bd9054cda70d4" -dependencies = [ - "aho-corasick", - "bitflags", - "compact_str 0.9.1", - "get-size2 0.7.4", - "is-macro", - "memchr", - "rustc-hash 2.1.2", - "rustpython-ruff_python_trivia", - "rustpython-ruff_source_file", - "rustpython-ruff_text_size", - "thiserror", -] - -[[package]] -name = "rustpython-ruff_python_parser" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e6ee78bd9671fb5766664b2695fe1f2a92a961f4d9101646c570d8acdb1e0b" -dependencies = [ - "bitflags", - "bstr", - "compact_str 0.9.1", - "get-size2 0.7.4", - "memchr", - "rustc-hash 2.1.2", - "rustpython-ruff_python_ast", - "rustpython-ruff_python_trivia", - "rustpython-ruff_text_size", - "static_assertions", - "unicode-ident", - "unicode-normalization", - "unicode_names2 1.3.0", -] - -[[package]] -name = "rustpython-ruff_python_trivia" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e7cfd1056f3a02ff0d2d0e4474286ca963260782f878b7b81c1dd87432e682" -dependencies = [ - "itertools 0.14.0", - "rustpython-ruff_source_file", - "rustpython-ruff_text_size", - "unicode-ident", -] - -[[package]] -name = "rustpython-ruff_source_file" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "948107aad62ddb12a11fc7bf68a49e52a0b0a3737d415a2505e54f5a9edac737" -dependencies = [ - "memchr", - "rustpython-ruff_text_size", -] - -[[package]] -name = "rustpython-ruff_text_size" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8291ee0f5a779e54ccd4e0151a0c426f8b49a123f99b5b6545db17ccdd4277aa" -dependencies = [ - "get-size2 0.7.4", -] - -[[package]] -name = "rustpython-sre_engine" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad4b7bd82b2a531f7c2ad96864ce11285959fc7d8524f1ba54db8ce3a23a3d2c" -dependencies = [ - "bitflags", - "num_enum", - "optional", - "rustpython-wtf8", -] - -[[package]] -name = "rustpython-vm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1880770161cef896bf9c7e065dae574e3b4c3cf6172e485f1ce86f0483816ab2" -dependencies = [ - "ahash", - "ascii", - "bitflags", - "bstr", - "caseless", - "cfg-if", - "chrono", - "constant_time_eq", - "crossbeam-utils", - "errno", - "exitcode", - "getrandom 0.3.4", - "glob", - "half", - "hex", - "indexmap", - "is-macro", - "itertools 0.14.0", - "junction", - "libc", - "libffi", - "libloading 0.9.0", - "log", - "malachite-bigint", - "memchr", - "nix", - "num-complex", - "num-integer", - "num-traits", - "num_cpus", - "num_enum", - "optional", - "parking_lot", - "paste", - "psm", - "result-like", - "rustix", - "rustpython-codegen", - "rustpython-common", - "rustpython-compiler", - "rustpython-compiler-core", - "rustpython-derive", - "rustpython-literal", - "rustpython-ruff_python_ast", - "rustpython-ruff_python_parser", - "rustpython-ruff_text_size", - "rustpython-sre_engine", - "rustyline", - "scoped-tls", - "scopeguard", - "static_assertions", - "strum", - "strum_macros", - "thiserror", - "timsort", - "uname", - "unic-ucd-bidi", - "unic-ucd-category", - "unic-ucd-ident", - "unicode-casing", - "which", - "widestring", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustpython-wtf8" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ada88d2f69ff5516d69e0f3294e9db2ff8ee71a15291b8f3f8584f07ad1ca28d" -dependencies = [ - "ascii", - "bstr", - "itertools 0.14.0", - "memchr", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "rustyline" -version = "17.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e902948a25149d50edc1a8e0141aad50f54e22ba83ff988cf8f7c9ef07f50564" -dependencies = [ - "bitflags", - "cfg-if", - "clipboard-win", - "fd-lock", - "home", - "libc", - "log", - "memchr", - "nix", - "radix_trie", - "unicode-segmentation", - "unicode-width 0.2.2", - "utf8parse", - "windows-sys 0.60.2", -] - -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - -[[package]] -name = "safe_arch" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42c6efa15875e6ecb39ca61fb0b0c1a40b84fac5a5ffe71eef7d1000c8eb3f5f" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schemars" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" -dependencies = [ - "dyn-clone", - "ref-cast", - "schemars_derive", + "console", + "once_cell", + "pest", + "pest_derive", "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.117", + "similar", + "tempfile", ] [[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - -[[package]] -name = "seq-macro" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" - -[[package]] -name = "serde" -version = "1.0.228" +name = "is_terminal_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] -name = "serde_core" -version = "1.0.228" +name = "itoa" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] -name = "serde_derive" -version = "1.0.228" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] -name = "serde_derive_internals" -version = "0.29.1" +name = "libc" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] -name = "serde_json" -version = "1.0.151" +name = "linux-raw-sys" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" -dependencies = [ - "indexmap", - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] -name = "serde_spanned" -version = "1.1.1" +name = "log" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" -dependencies = [ - "serde_core", -] +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +name = "mehen" +version = "0.0.1" dependencies = [ - "indexmap", - "itoa", - "ryu", + "crossbeam", + "globset", + "insta", + "num", + "num-derive", + "num-format", + "num-traits", + "petgraph", + "pretty_assertions", + "regex", "serde", - "unsafe-libyaml", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest", -] - -[[package]] -name = "sha1-checked" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423" -dependencies = [ - "digest", - "sha1", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest", + "termcolor", + "tree-sitter", + "tree-sitter-go", + "tree-sitter-python", + "tree-sitter-rust", + "tree-sitter-typescript", + "walkdir", ] [[package]] -name = "shell-words" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "shlex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" - -[[package]] -name = "similar" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" - -[[package]] -name = "siphasher" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "smallvec" -version = "1.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +name = "mehen-cli" +version = "0.0.1" dependencies = [ + "clap", + "globset", + "mehen", "serde", -] - -[[package]] -name = "smawk" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" - -[[package]] -name = "smol_str" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" -dependencies = [ - "borsh", - "serde_core", -] - -[[package]] -name = "sqruff-lib-core" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbd9d34c545d18dd806f286b47f88eb55aa0be76df213c580420a7293c4dd3f" -dependencies = [ - "enum_dispatch", - "fancy-regex", - "hashbrown 0.17.1", - "indexmap", - "itertools 0.15.0", - "log", - "nohash-hasher", - "pretty_assertions", - "regex-automata", - "smol_str", - "strum", - "strum_macros", - "thiserror", -] - -[[package]] -name = "sqruff-lib-dialects" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb5b3fe08edc8df724b3fab2919f5b23d5e755d3650d4da6628b15119bc7c22" -dependencies = [ - "hashbrown 0.17.1", - "itertools 0.15.0", + "serde_cbor", + "serde_json", "serde_yaml", - "sqruff-lib-core", - "strum", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "stacker" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.61.2", + "toml", ] [[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.28.0" +name = "memchr" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" -dependencies = [ - "strum_macros", -] +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] -name = "strum_macros" -version = "0.28.0" +name = "num" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", ] [[package]] -name = "supports-color" -version = "3.0.2" +name = "num-bigint" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "is_ci", + "num-integer", + "num-traits", ] [[package]] -name = "supports-hyperlinks" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" - -[[package]] -name = "supports-unicode" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" - -[[package]] -name = "syn" -version = "2.0.117" +name = "num-complex" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "num-traits", ] [[package]] -name = "syn" -version = "3.0.3" +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "syn", ] [[package]] -name = "syn-ext" -version = "0.5.0" +name = "num-format" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b126de4ef6c2a628a68609dd00733766c3b015894698a438ebdf374933fc31d1" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "arrayvec", + "itoa", ] [[package]] -name = "synstructure" -version = "0.13.2" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "num-traits", ] [[package]] -name = "tempfile" -version = "3.27.0" +name = "num-iter" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix", - "windows-sys 0.61.2", + "autocfg", + "num-integer", + "num-traits", ] [[package]] -name = "termcolor" -version = "1.4.1" +name = "num-rational" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "winapi-util", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] -name = "terminal_size" -version = "0.4.4" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "rustix", - "windows-sys 0.61.2", + "autocfg", ] [[package]] -name = "text-size" -version = "1.1.1" +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "textwrap" -version = "0.16.2" +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" -dependencies = [ - "smawk", - "unicode-linebreak", - "unicode-width 0.2.2", -] +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] -name = "thin-vec" -version = "0.2.18" +name = "pest" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f7e269b48f0a7dd0146680fa24b50cc67fc0373f086a5b2f99bd084639b482" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] [[package]] -name = "thiserror" -version = "2.0.18" +name = "pest_derive" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ - "thiserror-impl", + "pest", + "pest_generator", ] [[package]] -name = "thiserror-impl" -version = "2.0.18" +name = "pest_generator" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ + "pest", + "pest_meta", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] -name = "timsort" -version = "0.1.3" +name = "pest_meta" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "639ce8ef6d2ba56be0383a94dd13b92138d58de44c62618303bb798fa92bdc00" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" +dependencies = [ + "pest", + "sha2", +] [[package]] -name = "tinystr" +name = "petgraph" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ - "displaydoc", - "serde_core", - "zerovec", + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", + "serde", ] [[package]] -name = "tinyvec" -version = "1.11.0" +name = "pretty_assertions" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ - "tinyvec_macros", + "diff", + "yansi", ] [[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "toml" -version = "1.1.4+spec-1.1.0" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "indexmap", - "serde_core", - "serde_spanned", - "toml_datetime", - "toml_parser", - "toml_writer", - "winnow 1.0.3", + "proc-macro2", + "syn", ] [[package]] -name = "toml_datetime" -version = "1.1.1+spec-1.1.0" +name = "proc-macro2" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ - "serde_core", + "unicode-ident", ] [[package]] -name = "toml_parser" -version = "1.1.3+spec-1.1.0" +name = "quote" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ - "winnow 1.0.3", + "proc-macro2", ] [[package]] -name = "toml_writer" -version = "1.1.2+spec-1.1.0" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "tracing" -version = "0.1.44" +name = "regex" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "tracing-attributes" -version = "0.1.31" +name = "regex-automata" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "tracing-core" -version = "0.1.36" +name = "regex-syntax" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] -name = "tree-sitter" -version = "0.26.12" +name = "rustix" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c567a8e18ae93f20982c90370b16fd24023aeaf52f6052b96957ab253a0fec" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "cc", - "regex", - "regex-syntax", - "serde_json", - "streaming-iterator", - "tree-sitter-language", + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] -name = "tree-sitter-c" -version = "0.24.2" +name = "ryu" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b2eb57a55fed6b00812912e730b7a275cf4fe98bfd6a5d76263d4438371728" -dependencies = [ - "cc", - "tree-sitter-language", -] +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] -name = "tree-sitter-go" -version = "0.25.0" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8560a4d2f835cc0d4d2c2e03cbd0dde2f6114b43bc491164238d333e28b16ea" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "cc", - "tree-sitter-language", + "winapi-util", ] [[package]] -name = "tree-sitter-language" -version = "0.1.7" +name = "semver" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] -name = "tree-sitter-pwsh" -version = "0.38.1" +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c21a16f9f436a8030280f764e0691941b93d94fbd5b4f9421f8a69ec67193" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ - "cc", - "tree-sitter-language", + "serde_core", + "serde_derive", ] [[package]] -name = "triomphe" -version = "0.1.15" +name = "serde_cbor" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] [[package]] -name = "twox-hash" -version = "2.1.3" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8464ec13c3691491391d9fce00f6416c9a48e46972f72d7865688be2080192c9" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] [[package]] -name = "typenum" -version = "1.20.1" +name = "serde_derive" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "ucd-trie" -version = "0.1.7" +name = "serde_json" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] [[package]] -name = "uluru" -version = "3.1.0" +name = "serde_spanned" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c8a2469e56e6e5095c82ccd3afb98dad95f7af7929aab6d8ba8d6e0f73657da" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ - "arrayvec", + "serde_core", ] [[package]] -name = "uname" -version = "0.1.1" +name = "serde_yaml" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "libc", + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", ] [[package]] -name = "unic-char-property" -version = "0.9.0" +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "unic-char-range", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "unic-char-range" -version = "0.9.0" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "unic-common" -version = "0.9.0" +name = "similar" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] -name = "unic-ucd-bidi" -version = "0.9.0" +name = "streaming-iterator" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1d568b51222484e1f8209ce48caa6b430bf352962b877d592c29ab31fb53d8c" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" [[package]] -name = "unic-ucd-category" -version = "0.9.0" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8d4591f5fcfe1bd4453baaf803c40e1b1e69ff8455c47620440b46efef91c0" -dependencies = [ - "matches", - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "unic-ucd-ident" -version = "0.9.0" +name = "syn" +version = "2.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "unic-ucd-version" -version = "0.9.0" +name = "tempfile" +version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ - "unic-common", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys 0.61.2", ] [[package]] -name = "unicase" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" - -[[package]] -name = "unicode-bom" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" - -[[package]] -name = "unicode-casing" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061dbb8cc7f108532b6087a0065eff575e892a4bcb503dc57323a197457cc202" - -[[package]] -name = "unicode-id-start" -version = "1.4.0" +name = "termcolor" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] [[package]] -name = "unicode-ident" -version = "1.0.24" +name = "toml" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] [[package]] -name = "unicode-linebreak" -version = "0.1.5" +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] [[package]] -name = "unicode-normalization" -version = "0.1.25" +name = "toml_parser" +version = "1.0.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" dependencies = [ - "tinyvec", + "winnow", ] [[package]] -name = "unicode-properties" -version = "0.1.4" +name = "toml_writer" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] -name = "unicode-script" -version = "0.5.8" +name = "tree-sitter" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" +checksum = "b9ac5ea5e7f2f1700842ec071401010b9c59bf735295f6e9fa079c3dc035b167" +dependencies = [ + "cc", + "regex", + "regex-syntax", + "serde_json", + "streaming-iterator", + "tree-sitter-language", +] [[package]] -name = "unicode-segmentation" -version = "1.13.3" +name = "tree-sitter-go" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +checksum = "b13d476345220dbe600147dd444165c5791bf85ef53e28acbedd46112ee18431" +dependencies = [ + "cc", + "tree-sitter-language", +] [[package]] -name = "unicode-width" -version = "0.1.14" +name = "tree-sitter-language" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782" [[package]] -name = "unicode-width" -version = "0.2.2" +name = "tree-sitter-python" +version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +checksum = "3d065aaa27f3aaceaf60c1f0e0ac09e1cb9eb8ed28e7bcdaa52129cffc7f4b04" +dependencies = [ + "cc", + "tree-sitter-language", +] [[package]] -name = "unicode-xid" -version = "0.2.6" +name = "tree-sitter-rust" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "a4d64d449ca63e683c562c7743946a646671ca23947b9c925c0cfbe65051a4af" +dependencies = [ + "cc", + "tree-sitter-language", +] [[package]] -name = "unicode_names2" -version = "1.3.0" +name = "tree-sitter-typescript" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1673eca9782c84de5f81b82e4109dcfb3611c8ba0d52930ec4a9478f547b2dd" +checksum = "6c5f76ed8d947a75cc446d5fccd8b602ebf0cde64ccf2ffa434d873d7a575eff" dependencies = [ - "phf 0.11.3", - "unicode_names2_generator 1.3.0", + "cc", + "tree-sitter-language", ] [[package]] -name = "unicode_names2" -version = "2.0.0" +name = "typenum" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d189085656ca1203291e965444e7f6a2723fbdd1dd9f34f8482e79bafd8338a0" -dependencies = [ - "phf 0.11.3", - "unicode_names2_generator 2.0.0", -] +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] -name = "unicode_names2_generator" -version = "1.3.0" +name = "ucd-trie" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91e5b84611016120197efd7dc93ef76774f4e084cd73c9fb3ea4a86c570c56e" -dependencies = [ - "getopts", - "log", - "phf_codegen", - "rand", -] +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] -name = "unicode_names2_generator" -version = "2.0.0" +name = "unicode-ident" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1262662dc96937c71115228ce2e1d30f41db71a7a45d3459e98783ef94052214" -dependencies = [ - "phf_codegen", - "rand", -] +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] -name = "unsafe-libyaml" -version = "0.2.11" +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] -name = "utf8_iter" -version = "1.0.4" +name = "unsafe-libyaml" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "utf8parse" @@ -5576,19 +1054,13 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen 0.57.1", + "wit-bindgen 0.46.0", ] [[package]] @@ -5600,51 +1072,6 @@ dependencies = [ "wit-bindgen 0.51.0", ] -[[package]] -name = "wasm-bindgen" -version = "0.2.127" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.127" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.127" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn 2.0.117", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.127" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" -dependencies = [ - "unicode-ident", -] - [[package]] name = "wasm-encoder" version = "0.244.0" @@ -5679,31 +1106,6 @@ dependencies = [ "semver", ] -[[package]] -name = "which" -version = "8.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3ef584124b911bcc3875c2f1472e80f24361ceb789bd1c62b3e9a3df9ff43c" -dependencies = [ - "libc", -] - -[[package]] -name = "wide" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2aaf408e58689c2096682331b1f42bb2d9f2ed6b11560407d023cd0a6c634e" -dependencies = [ - "bytemuck", - "safe_arch", -] - -[[package]] -name = "widestring" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" - [[package]] name = "winapi-util" version = "0.1.11" @@ -5713,81 +1115,19 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", + "windows-targets", ] [[package]] @@ -5805,31 +1145,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -5838,110 +1161,59 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" -version = "0.7.15" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" [[package]] -name = "winnow" -version = "1.0.3" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" -dependencies = [ - "memchr", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "wit-bindgen" @@ -5952,12 +1224,6 @@ dependencies = [ "wit-bindgen-rust-macro", ] -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -5979,7 +1245,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.117", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -5995,7 +1261,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -6037,136 +1303,12 @@ dependencies = [ "wasmparser", ] -[[package]] -name = "writeable" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" - -[[package]] -name = "xtask" -version = "1.10.0" -dependencies = [ - "antlr-rust-codegen", - "askama", - "clap", - "mehen-c", - "mehen-go", - "serde_json", - "tree-sitter", -] - [[package]] name = "yansi" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" -[[package]] -name = "yoke" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zerofrom" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "zerotrie" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "zerovec" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" -dependencies = [ - "serde", - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zlib-rs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" - [[package]] name = "zmij" version = "1.0.21" diff --git a/Cargo.toml b/Cargo.toml index a2f43384..5519ada3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,140 +1,40 @@ -[workspace] -resolver = "2" -members = [ - "crates/mehen-core", - "crates/mehen-metrics", - "crates/mehen-tree-sitter", - "crates/mehen-antlr", - "crates/mehen-kotlin-parser", - "crates/mehen-java-parser", - "crates/mehen-csharp-parser", - "crates/mehen-markdown", - "crates/mehen-python", - "crates/mehen-typescript", - "crates/mehen-php", - "crates/mehen-ruby", - "crates/mehen-rust", - "crates/mehen-go", - "crates/mehen-c", - "crates/mehen-kotlin", - "crates/mehen-java", - "crates/mehen-csharp", - "crates/mehen-powershell", - "crates/mehen-sql", - "crates/mehen-engine", - "crates/mehen-git", - "crates/mehen-coverage", - "crates/mehen-coverage-discovery", - "crates/mehen-report", - "crates/mehen-cli", - "xtask", -] -# `cargo run` / `cargo build` (with no `-p`) target the `mehen` -# package in `crates/mehen-cli/`. The xtask binary is reached via -# `cargo xtask …` (per `.cargo/config.toml`). -default-members = ["crates/mehen-cli"] - -[workspace.lints.rust] -# Catch `pub` items in internal crates that are never re-exported across -# crate boundaries — they should be `pub(crate)` so dead-code detection -# stays effective. Members opt in with `[lints] workspace = true`. -unreachable_pub = "warn" - -[workspace.package] -version = "1.10.0" -authors = ["Konstantin Vyatkin "] -edition = "2024" -rust-version = "1.95.0" -repository = "https://github.com/ophi-dev/mehen" -license = "AGPL-3.0-only" +[package] +name = "mehen" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +readme = "README.md" +keywords = ["metrics"] +description = "Tool to compute and export code metrics" +license.workspace = true -[workspace.dependencies] -# Internal crates (path-only, never published) -mehen-core = { path = "crates/mehen-core" } -mehen-metrics = { path = "crates/mehen-metrics" } -mehen-tree-sitter = { path = "crates/mehen-tree-sitter" } -mehen-antlr = { path = "crates/mehen-antlr" } -# Generated-only ANTLR parser crates. Unlike the other `mehen-*` crates -# (path-only, `publish = false`), these are publishable so external tools -# can depend on just the parser via a git tag — the same way this repo -# consumes ruff/oxc/sqruff parser crates. The owning analyzer crates -# (`mehen-kotlin`, `mehen-java`, `mehen-csharp`) depend on them for the -# generated grammar. -mehen-kotlin-parser = { path = "crates/mehen-kotlin-parser" } -mehen-java-parser = { path = "crates/mehen-java-parser" } -mehen-csharp-parser = { path = "crates/mehen-csharp-parser" } -mehen-markdown = { path = "crates/mehen-markdown" } -mehen-python = { path = "crates/mehen-python" } -mehen-typescript = { path = "crates/mehen-typescript" } -mehen-php = { path = "crates/mehen-php" } -mehen-ruby = { path = "crates/mehen-ruby" } -mehen-rust = { path = "crates/mehen-rust" } -mehen-go = { path = "crates/mehen-go" } -mehen-c = { path = "crates/mehen-c" } -mehen-kotlin = { path = "crates/mehen-kotlin" } -mehen-java = { path = "crates/mehen-java" } -mehen-csharp = { path = "crates/mehen-csharp" } -mehen-powershell = { path = "crates/mehen-powershell" } -mehen-sql = { path = "crates/mehen-sql" } -mehen-engine = { path = "crates/mehen-engine" } -mehen-git = { path = "crates/mehen-git" } -mehen-coverage = { path = "crates/mehen-coverage" } -mehen-coverage-discovery = { path = "crates/mehen-coverage-discovery" } -mehen-report = { path = "crates/mehen-report" } - -# Shared third-party deps with pinned versions. Single-consumer deps -# (e.g. `oxc_*`, `ra_ap_syntax`, `ruby-prism`, `env_logger`, `globset`, -# `ignore`, `regex`, `tree-sitter-pwsh`, `unicode-*`) are pinned inline in -# their consuming crate's `Cargo.toml` instead of here. -camino = { version = "^1.1", features = ["serde1"] } -clap = { version = "^4.6", features = ["derive"] } -log = "^0.4" +[dependencies] +crossbeam = { version = "^0.8", features = ["crossbeam-channel"] } +globset = "^0.4" num = "^0.4" -num-derive = "^0.5" +num-derive = "^0.4" +num-format = "^0.4" num-traits = "^0.2" +petgraph = "^0.8" +regex = "^1.7" serde = { version = "^1.0", features = ["derive"] } -serde_json = "^1.0" -smol_str = { version = "^0.3", features = ["serde"] } -gix = { version = "^0.86", default-features = false, features = ["attributes", "blob-diff", "max-performance-safe", "revision", "sha1"] } -# Read-only XML pull parsing for coverage reports (JaCoCo/Clover/Cobertura) -# and `phpunit.xml` introspection. Shared by `mehen-coverage` and -# `mehen-coverage-discovery`. Both optional features (`serialize`, -# `encoding`) stay off: parsing is hand-rolled streaming, and non-UTF-8 -# report encodings are rejected as diagnostics. Keep ≥0.41 — it carries the -# fixes for RUSTSEC-2026-0194/-0195. -quick-xml = "^0.41" -# `globset`, `ignore`, and `toml` graduated from mehen-engine-inline pins -# to workspace pins when `mehen-coverage-discovery` became their second -# consumer (artifact scanning walks and declarative tool-config -# introspection mirror the engine's filtering/walking/config concerns). -globset = "^0.4" -ignore = "^0.4" -toml = "^1.1" +termcolor = "^1.2" +walkdir = "^2.3" -# ANTLR v4 Rust runtime and code generator (`ophi-dev/antlr-rust-runtime`). -# The runtime package's library is imported as `antlr4_runtime`, so alias it -# here to match generated source. The separate codegen package is linked only -# into xtask; normal `cargo build` uses the checked-in generated modules and -# does not compile it. Keep the exact pins in lockstep, then regenerate with -# `cargo xtask antlr generate --all` so generated source and runtime agree. -antlr4_runtime = { package = "antlr-rust-runtime", version = "=0.33.1" } -antlr_rust_codegen = { package = "antlr-rust-codegen", version = "=0.33.1" } +tree-sitter = "=0.25.3" +tree-sitter-typescript = "=0.23.2" +tree-sitter-python = "=0.23.6" +tree-sitter-rust = "=0.23.2" +tree-sitter-go = "=0.23.4" -tree-sitter = "=0.26.12" -# Per-language grammars (`tree-sitter-c`, `tree-sitter-go`, -# `tree-sitter-pwsh`) -# are pinned inline in their consuming analyzer crate. xtask reaches -# each grammar through the analyzer's `__grammar_language()` accessor -# instead of pinning grammars itself, so the kind-enum generator and -# the runtime parser always link the same revision. -# Kotlin is no longer tree-sitter-backed — it uses an ANTLR grammar -# (see the `antlr4_runtime` pin above and `crates/mehen-kotlin`). -# `tree-sitter-ruby` was removed in Phase 9 (Prism) — Ruby now flows -# through `mehen-ruby` (ruby-prism) per plan §6.5. +[package.metadata.cargo-machete] +ignored = ["num-traits", "tree-sitter-go", "tree-sitter-python", "tree-sitter-rust"] -insta = { version = "1.47.2", features = ["yaml", "json", "redactions"] } +[dev-dependencies] +insta = { version = "1.29.0", features = ["yaml", "json", "redactions"] } pretty_assertions = "^1.3" -tempfile = "^3" [profile.dev.package.insta] opt-level = 3 @@ -142,6 +42,18 @@ opt-level = 3 [profile.dev.package.similar] opt-level = 3 +[workspace] +members = ["mehen-cli"] +exclude = ["enums"] + +[workspace.package] +version = "0.0.1" +authors = ["Konstantin Vyatkin "] +edition = "2024" +rust-version = "1.93.1" +repository = "https://github.com/ophidiarium/mehen" +license = "MPL-2.0" + [profile.release] opt-level = 3 debug = false diff --git a/LICENSE b/LICENSE index be3f7b28..d0a1fa14 100644 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,373 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/LICENSE-THIRD-PARTY b/LICENSE-THIRD-PARTY deleted file mode 100644 index 0e7f2ebd..00000000 --- a/LICENSE-THIRD-PARTY +++ /dev/null @@ -1,184 +0,0 @@ -# Third-Party Data and License Notices - -Mehen bundles several small data files derived from third-party sources. -This file documents the origin, license, and attribution for each. The -mehen Rust workspace itself is released under AGPL-3.0-only (see -`LICENSE`); the bundled Markdown data lives under `src/markdown/data/` -and follows the licenses below. - -## covrs coverage-report parsers (adapted source code) - -- Files: `crates/mehen-coverage/src/model.rs`, - `crates/mehen-coverage/src/parsers/{mod,lcov,gocover,istanbul,jacoco,clover,cobertura}.rs`, - and the parser test fixtures under - `crates/mehen-coverage/tests/fixtures/`. -- Origin: covrs 0.3.2 — code coverage ingestion and reporting, by - Scott Nelson. https://github.com/scttnlsn/covrs -- License: MIT, as declared by the upstream `Cargo.toml` `license` - field (the upstream repository ships no standalone LICENSE file; the - crates.io metadata is the license statement of record). The complete - MIT permission notice is reproduced below per its terms. -- Use: The six coverage-report format parsers (LCOV, Go coverprofile, - Istanbul JSON, JaCoCo XML, Clover XML, Cobertura XML), their shared - detection helpers, the uniform coverage model, and the parser test - fixtures were adapted into `mehen-coverage`. Local modifications - (house error type, camino paths, quick-xml 0.41 API, record - normalization, regex removal) are noted in each file's provenance - header and are licensed under the repository's AGPL-3.0-only terms. - -```text -MIT License - -Copyright (c) Scott Nelson - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` - -## NGSL 1.2 (New General Service List) - -- File: `src/markdown/data/ngsl_1_2.txt` -- Origin: Browne, C., Culligan, B., & Phillips, J. (2013). The New - General Service List. http://www.newgeneralservicelist.com/ -- License: Creative Commons Attribution-ShareAlike 4.0 International - (CC BY-SA 4.0). https://creativecommons.org/licenses/by-sa/4.0/ -- Attribution: "The New General Service List by Charles Browne, Brent - Culligan, and Joseph Phillips is licensed under CC BY-SA 4.0." -- Use: Powers the Dale-Chall-style "familiar word" lookup for §31.7. - Mehen does NOT bundle the Dale-Chall 3000-word list because that list - is copyrighted (Chall and Dale heirs). - -## NLTK English Stopword List - -- File: `src/markdown/data/nltk_stopwords_en.txt` -- Origin: Natural Language Toolkit corpus package, `stopwords.english`. - https://github.com/nltk/nltk_data -- License: The NLTK code is Apache 2.0; individual corpora distributed - with NLTK have varying licenses. The English stopword list - (nltk_data/corpora/stopwords/english) is a public-domain list of 175 - common English function words. -- Use: Backs the `lexical_density ≈ 1 − stopwords/tokens` estimator - (§32.1). - -## write-good passive-voice irregular past participles - -- File: `src/markdown/data/passive_irregulars.txt` -- Origin: write-good 1.0.8 — `lib/passive.js`. - https://github.com/btford/write-good -- License: MIT — Copyright (c) 2014 Brett Foster. -- Use: Disambiguates passive-voice matches in §33.1. Combined with the - UAX #29 tokenizer this is the core passive-voice detector. - -## words/hedges hedge-word list - -- File: `src/markdown/data/hedges.txt` -- Origin: https://github.com/words/hedges -- License: MIT — Copyright (c) Titus Wormer. -- Use: §33.2 hedge-density computation. - -## write-good weasel-word list - -- File: `src/markdown/data/weasels.txt` -- Origin: write-good `lib/weasel.js` — same source as above. -- License: MIT — Copyright (c) 2014 Brett Foster. -- Use: §33.3 weasel-density computation. - -## retext-simplify wordy-phrase list - -- File: `src/markdown/data/wordy_phrases.txt` -- Origin: https://github.com/retextjs/retext-simplify -- License: MIT — Copyright (c) Titus Wormer. -- Use: §33.4 wordy-density computation. Only the phrase list is bundled; - the suggested replacements are not currently exposed in the output. - -## words/no-cliches cliché list (subset) - -- File: `src/markdown/data/cliches.txt` -- Origin: https://github.com/words/no-cliches -- License: MIT — Copyright (c) Titus Wormer. -- Use: §33.9 cliche-density computation. The bundled file is a - representative subset of the upstream ~700-entry list; the exact - subset is documented in the file's header comment. - -## proselint nonword list (subset) - -- File: `src/markdown/data/nonwords.txt` -- Origin: proselint (https://github.com/amperser/proselint) — - checks/misc/illogic. -- License: BSD 3-Clause — Copyright (c) 2015-2023 Amperser Labs. -- Use: §33.9 `nonword_count` flag. - -## alex / retext-equality inclusive-language flags - -- File: `src/markdown/data/inclusive_flags.txt` -- Origin: Derived from alex / retext-equality - (https://github.com/retextjs/retext-equality) and the Inclusive Naming - Initiative mappings (https://inclusivenaming.org/). -- License: MIT — Copyright (c) Titus Wormer (for retext-equality); the - Inclusive Naming Initiative publishes its mappings under Apache-2.0. -- Use: §33.12 Inclusive-language scoring. - -## Jōyō kanji list - -- File: `src/markdown/data/jouyou_kanji.txt` -- Origin: Japanese Ministry of Education (文部科学省) "Jōyō Kanji - Table" (2010 revision). Published at - https://www.mext.go.jp/a_menu/shotou/new-cs/youryou/syo/kokugo/001.htm -- License: Public domain (Japanese government policy document, - distributed under Japan's government-works rule). -- Use: §35.2 Jōyō grade proxy and §36.5 JTF rule 3 (hyōgai detection). - The bundled file assigns grades 1–6 (Kyōiku grades) and grade 7 - (secondary Jōyō) to individual kanji. - -## textlint-rule-preset-ja-technical-writing — weak-phrase and - redundant-expression lists - -- Files: `src/markdown/data/ja_weak_phrases.txt`, - `src/markdown/data/ja_redundant.txt` -- Origin: https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing -- License: MIT — Copyright (c) textlint-ja contributors. -- Use: §36.6 `ja-no-weak-phrase` and `ja-no-redundant-expression` rules. - -## English abbreviation list - -- File: `src/markdown/data/abbreviations_en.txt` -- Origin: Synthesized from write-good (MIT), proselint (BSD-3-Clause), - retext-smartypants (MIT), and standard journalism style guides. -- License: Each source permits redistribution under MIT or BSD-3-Clause; - the synthesized list is released under MIT here for consistency. -- Use: §31.12 abbreviation-aware sentence segmentation. - ---- - -## Tier 1/2 (feature-gated) dictionaries — NOT bundled in this phase - -The following resources are **not** bundled in the Tier-0 default build -but may be enabled via Cargo features in future phases. The list is kept -here for advance license planning. - -- CMU Pronouncing Dictionary (Tier 1a, `syllables-cmu`). Public domain. -- JLPT N5–N1 word and kanji lists (Tier 1c, `japanese-jlpt`). No official - release from JEES/JF; community-maintained lists under various - licenses. Mehen would bundle J-LEX-derived lists with attribution. -- IPADIC via Lindera (Tier 2a, `japanese-morph`). IPA/IPAdic license; - Lindera's NOTICE file propagation is required. -- UniDic via Vibrato (Tier 2b, `japanese-unidic`). BSD-like with NINJAL - credit; external dictionary, not bundled in-binary. -- Lingua language-detection models (Tier 1d, `lingua`). Apache-2.0. Full - model multi-megabyte. diff --git a/README.md b/README.md index c916377a..dfb3108e 100644 --- a/README.md +++ b/README.md @@ -1,146 +1,99 @@ # mehen -**mehen** is a Rust-powered CLI for detecting heuristic source code metrics at scale: complexity, -maintainability, lines of code, documentation health, and more. +**mehen** is a Rust library to analyze and extract information +from source code written in many different programming languages. +It is based on a parser generator tool and an incremental parsing library +called +Tree Sitter. -It is designed for fast, deterministic analysis over large codebases, helping both human and AI -engineers track how complexity evolves over time. -📚 **Documentation: ** +A command line tool called **mehen** is provided to interact with the API of the library. -## What is Mehen? +This tool can be used to: -In Ophidiarium projects, names matter. **Mehen** is a mythical ancient Egyptian serpent associated with -guarding Ra. In the same spirit, `mehen` helps guard your codebase from slowly collapsing under -complexity. +- Print nodes and metrics information +- Export metrics in different formats +- Analyze code complexity and maintainability -## Why teams use mehen -- **Polyglot by design** — per-file language detection across eleven source languages plus Markdown - and SQL. Useful for monorepos. -- **Real language parsers** — Ruff for Python, Oxc for TS/JS/JSX/TSX, Mago for PHP, Prism for Ruby, - `ra_ap_syntax` for Rust, ANTLR (Kotlin spec grammar for Kotlin, grammars-v4 for Java and C#), - pulldown-cmark for Markdown, sqruff for SQL, tree-sitter for Go, C, PowerShell. -- **Code, documentation, and SQL in one tool** — source-code complexity, Markdown documentation - health, *and* a dedicated relational metric family for `.sql` files. -- **Bring-your-own coverage** — ingests LCOV, Cobertura, JaCoCo, Clover, Istanbul, and Go - coverprofile reports, auto-discovers them in their idiomatic (usually gitignored) locations, - and publishes `coverage.*` as a rankable, gateable metric family down to per-function values. -- **Deterministic, no network** — pure static analysis. Same input → same output. Safe for air-gapped - CI. -- **Pull-request native** — built-in `mehen diff` plus a sticky comment GitHub Action. +# Usage -## Install +**mehen** computes a variety of software metrics for Go, Python, Rust, and TypeScript/TSX code. -```bash -# npm -npm install -g mehen +Run `mehen --help` to see all available commands and options. -# PyPI / uv -uv tool install mehen -# or: pip install mehen +## Building -# cargo binstall -cargo binstall --git https://github.com/ophi-dev/mehen mehen -``` - -Full installation guide: . +To build the `mehen` library, you need to run the following +command: -## Quick start - -```bash -# Analyze a single file -mehen metrics src/main.py --pretty +```console +cargo build +``` -# Rank the worst offenders in a tree -mehen top-offenders src --metric cognitive +If you want to build the `cli`: -# Diff metrics against main -mehen diff --from main --to HEAD --paths src --output-format markdown +```console +cargo build -p mehen-cli ``` -Quickstart: . +To build everything: -## Configuration +```console +cargo build --workspace +``` -Drop a `mehen.toml` (or `.mehen.toml`) anywhere between the directory you run `mehen` from and -the git repository root — discovery walks upward and stops at the repository boundary — or pin an -explicit file with `--config `: +## Testing -```toml -[thresholds] -cognitive = 15 # higher-is-worse metrics: the limit is a maximum -"loc.lloc" = 500 -mi.visual_studio = 40 # higher-is-better metrics (mi.*): the limit is a minimum +To verify whether all tests pass, run the `cargo test` command. -[languages.python.thresholds] -cognitive = 10 # overrides the global limit for Python files only +```console +cargo test --workspace --all-features --verbose ``` -Every command that reports a configured metric enforces it: `mehen metrics` checks the full -metric set of the analyzed file, while `mehen diff` (head side) and `mehen top-offenders` check -the metrics selected for output — across *all* analyzed files, not just the displayed rows. Any -crossed limit prints a grouped report on stderr and fails the command with exit code 1: - -```text - × 2 metric threshold violations (config: /repo/mehen.toml) - │ - │ src/app/core.py - │ cognitive = 23 — exceeds max 10 (set by languages.python.thresholds) - │ loc.lloc = 640 — exceeds max 500 (set by thresholds) - help: adjust or remove the limit at the configuration path shown, or bring the file back within it. +### Updating insta tests +We use [insta](https://insta.rs), to update the snapshot tests you should install [cargo insta](https://crates.io/crates/cargo-insta) + +``` console +cargo insta test --review ``` -Configuration mistakes fail fast with a caret into the TOML source and a suggestion ("unknown -metric `cognitve` … did you mean `cognitive`?"): every metric name is validated against the keys -the analyzers actually publish — including the `sql.*` and `markdown.*` namespaces — so a typo -can never silently disable a gate. Full reference: . +Will run the tests, generate the new snapshot references and let you review them. -## GitHub Action +### Updating grammars -Drop the action into a workflow to publish per-PR metric trends: +See `mehen-book/src/developers/update-grammars.md` to learn how to update language grammars. -```yaml -permissions: - contents: read - pull-requests: write - issues: write +# Contributing -steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - uses: ophi-dev/mehen@v1 - with: - paths: src -``` +If you want to contribute to the development of this software, please open an issue or pull request on our +[GitHub repository](https://github.com/ophidiarium/mehen). See `mehen-book/src/developers/` for developer documentation. -Full reference: . -## Documentation +# License -Everything else lives in the docs site: +**mehen** and **mehen-cli** (binary: `mehen`) are released under the +Mozilla Public License v2.0. -- [Code metrics](https://mehen.ophi.dev/metrics/code/overview) — cyclomatic, cognitive, Halstead, MI, - ABC, LOC family, NOM, NPA, NPM, WMC. -- [Markdown metrics](https://mehen.ophi.dev/metrics/markdown/overview) — DMI, MRPC, MCC, link debt, - filler/lazy risk, English/Japanese prose layer. -- [SQL metrics](https://mehen.ophi.dev/metrics/sql/overview) — CTE graphs, join/subquery structure, - object-touch risk, SQL Halstead, and composite scores via `mehen-sql` (sqruff-backed). -- [Coverage metrics](https://mehen.ophi.dev/metrics/coverage/overview) — ingest test-coverage - reports (six formats, auto-discovered), gate on line/branch/function coverage, rank the - least-tested files. -- [Commands](https://mehen.ophi.dev/commands/overview) — `mehen metrics`, `mehen diff`, - `mehen top-offenders`. -- [Configuration](https://mehen.ophi.dev/configuration) — `mehen.toml` thresholds and - per-language overrides. -- [Developers guide](https://mehen.ophi.dev/developers/overview) — build, test, contribute, add a - language. +# Credits -## Contributing +Mehen is based on the excellent [rust-code-analysis](https://github.com/mozilla/rust-code-analysis) project by Mozilla. While mehen has taken a different direction by focusing on a streamlined set of languages (Go, Python, Rust, and TypeScript/TSX), the core architecture and metric implementations are built upon that foundation. -Issues and pull requests welcome at . +If you use this software in academic work, please cite the original rust-code-analysis paper: -## License +```bibtex +@article{ARDITO2020100635, + title = {rust-code-analysis: A Rust library to analyze and extract maintainability information from source codes}, + journal = {SoftwareX}, + volume = {12}, + pages = {100635}, + year = {2020}, + issn = {2352-7110}, + doi = {https://doi.org/10.1016/j.softx.2020.100635}, + url = {https://www.sciencedirect.com/science/article/pii/S2352711020303484}, + author = {Luca Ardito and Luca Barbato and Marco Castelluccio and Riccardo Coppola and Calixte Denizet and Sylvestre Ledru and Michele Valsesia}, + keywords = {Algorithm, Software metrics, Software maintainability, Software quality} +} +``` -`mehen` is released under the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.html). +We thank the Mozilla team and all contributors to rust-code-analysis for their foundational work. diff --git a/action.yml b/action.yml deleted file mode 100644 index 4778b6ab..00000000 --- a/action.yml +++ /dev/null @@ -1,216 +0,0 @@ -name: "mehen Source Metrics" -description: "Publish source code metric trends for pull requests" -author: "Ophidiarium" -branding: - icon: "activity" - color: "green" - -inputs: - version: - description: "Version of the mehen npm package to run. Empty means latest." - required: false - default: "" - install-method: - description: "How to provide the mehen CLI: npm, cargo, or path." - required: false - default: "npm" - mehen-path: - description: "Path to a mehen executable when install-method is path." - required: false - default: "mehen" - node-version: - description: "Node.js version used by the action runner." - required: false - default: "24" - paths: - description: "Repository-relative files or directories to compare. Newline, comma, or semicolon separated." - required: false - default: "." - include: - description: "Glob patterns to include. Newline, comma, or semicolon separated." - required: false - default: "" - exclude: - description: "Glob patterns to exclude. Newline, comma, or semicolon separated." - required: false - default: "" - exclude-tests: - description: "Exclude common test-file patterns (e.g. *_test.go, **/__tests__/**, *.spec.ts) in addition to any user-provided excludes." - required: false - default: "true" - metrics: - description: "Comma-separated metrics passed to mehen diff." - required: false - default: "" - from: - description: "Base git revision. Defaults to the PR base branch or main." - required: false - default: "" - to: - description: "Head git revision. Defaults to the PR head SHA or HEAD." - required: false - default: "" - show-unchanged: - description: "Include files where all selected metrics are unchanged." - required: false - default: "false" - comment: - description: "Create or update a pull request comment." - required: false - default: "true" - github-token: - description: "GitHub token used to update pull request comments." - required: false - default: "" - thresholds: - description: "Adverse per-file delta limits, for example: cyclomatic=5,cognitive=3,loc.lloc=100." - required: false - default: "" - fail-on-threshold: - description: "Fail the action when any configured threshold is exceeded." - required: false - default: "true" - comment-title: - description: "Markdown heading used for the sticky pull request comment." - required: false - default: "## 📊 Source Code Metrics" - coverage-files: - description: >- - Coverage report paths produced by an earlier test step (newline, comma, or semicolon - separated; literal paths, no globs). Passed to mehen diff as head-side --coverage reports. - On pull requests the same logical reports are retrieved for the base revision and passed - as --base-coverage (see coverage-base-source); on pushes to the default branch they are - saved to the Actions cache as future pull-request baselines. - required: false - default: "" - coverage-base-source: - description: >- - Where base-revision coverage comes from on pull requests: auto (exact cache hit, then - workflow artifact, then codecov.io, then nearest default-branch cache, then absent), - cache, artifact, codecov, or off. Every fallback level is disclosed in the PR comment. - required: false - default: "auto" - coverage-artifact-name: - description: >- - Name of a workflow artifact holding coverage report(s), used as a base-coverage source - on pull requests: the artifact uploaded by the run for the PR's base SHA is downloaded - and its files are passed as --base-coverage. Artifacts persist ~90 days (the Actions - cache evicts after 7 unused days), and many repositories already upload coverage - artifacts — including for GitHub Code Quality's upload job. The artifact should contain - only coverage report files. Requires `actions: read` permission on the job. - required: false - default: "" - codecov-token: - description: >- - Codecov API access token for coverage-base-source auto/codecov: a personal API access - token generated under Settings -> Access on app.codecov.io — NOT the repository upload - token (the API rejects upload tokens). Optional for public repositories; required for - private ones. - required: false - default: "" - -outputs: - violations: - description: "Number of threshold violations (delta thresholds from the `thresholds` input plus repository `mehen.toml` breaches)." - value: ${{ steps.run.outputs.violations }} - report_json: - description: "Path to the JSON diff report produced by mehen." - value: ${{ steps.run.outputs.report_json }} - report_markdown: - description: "Path to the rendered Markdown report." - value: ${{ steps.run.outputs.report_markdown }} - -runs: - using: "composite" - steps: - - name: Set up Node.js - uses: actions/setup-node@v6 - with: - node-version: ${{ inputs.node-version }} - - - name: Set up Rust toolchain - if: ${{ inputs.install-method == 'cargo' }} - uses: dtolnay/rust-toolchain@stable - - # ── Base coverage retrieval (issue #248) ────────────────────────── - # Push to the default branch: copy the just-produced coverage - # reports into a staging directory and save them under the pushed - # SHA, so future pull requests can restore their base revision's - # reports by exact key. The staging directory lives under - # runner.temp — restoring it on a PR run can never overwrite the - # head reports the caller's test step just wrote into the - # workspace. - - name: Stage coverage reports for the base cache - id: coverage-stage - if: ${{ inputs.coverage-files != '' && (inputs.coverage-base-source == 'auto' || inputs.coverage-base-source == 'cache') && github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} - shell: bash - env: - GHA_MEHEN_COVERAGE_FILES: ${{ inputs.coverage-files }} - MEHEN_COVERAGE_DIR: ${{ runner.temp }}/mehen-base-coverage - run: | - staged=0 - mkdir -p "$MEHEN_COVERAGE_DIR" - while IFS= read -r entry; do - f="$(printf '%s' "$entry" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - [ -z "$f" ] && continue - if [ -f "$f" ]; then - dest="$MEHEN_COVERAGE_DIR/${f#/}" - mkdir -p "$(dirname "$dest")" - cp "$f" "$dest" - staged=$((staged + 1)) - else - echo "::warning::mehen: coverage file '$f' not found; it will be missing from the base-coverage cache" - fi - done < <(printf '%s\n' "$GHA_MEHEN_COVERAGE_FILES" | tr ',;' '\n\n') - echo "staged=$staged" >> "$GITHUB_OUTPUT" - - - name: Save base coverage cache - if: ${{ steps.coverage-stage.outputs.staged != '' && steps.coverage-stage.outputs.staged != '0' }} - uses: actions/cache/save@v4 - with: - path: ${{ runner.temp }}/mehen-base-coverage - key: mehen-coverage-${{ github.sha }} - - # Pull request: restore the base revision's reports by exact key. - # On a miss, the prefix restore-key falls back to the most recent - # default-branch entry — recency-based, not ancestor-aware, so the - # runner script discloses that level explicitly (and prefers - # codecov by exact SHA over the fallback under 'auto'). - - name: Restore base coverage cache - id: coverage-restore - if: ${{ inputs.coverage-files != '' && (inputs.coverage-base-source == 'auto' || inputs.coverage-base-source == 'cache') && github.event_name == 'pull_request' }} - uses: actions/cache/restore@v4 - with: - path: ${{ runner.temp }}/mehen-base-coverage - key: mehen-coverage-${{ github.event.pull_request.base.sha }} - restore-keys: | - mehen-coverage- - - - name: Publish mehen metrics - id: run - shell: bash - run: node "$GITHUB_ACTION_PATH/scripts/github-action.mjs" - env: - GHA_MEHEN_VERSION: ${{ inputs.version }} - GHA_MEHEN_INSTALL_METHOD: ${{ inputs.install-method }} - GHA_MEHEN_PATH: ${{ inputs.mehen-path }} - GHA_MEHEN_PATHS: ${{ inputs.paths }} - GHA_MEHEN_INCLUDE: ${{ inputs.include }} - GHA_MEHEN_EXCLUDE: ${{ inputs.exclude }} - GHA_MEHEN_EXCLUDE_TESTS: ${{ inputs.exclude-tests }} - GHA_MEHEN_METRICS: ${{ inputs.metrics }} - GHA_MEHEN_FROM: ${{ inputs.from }} - GHA_MEHEN_TO: ${{ inputs.to }} - GHA_MEHEN_SHOW_UNCHANGED: ${{ inputs.show-unchanged }} - GHA_MEHEN_COMMENT: ${{ inputs.comment }} - GHA_MEHEN_GITHUB_TOKEN: ${{ inputs.github-token || github.token }} - GHA_MEHEN_THRESHOLDS: ${{ inputs.thresholds }} - GHA_MEHEN_FAIL_ON_THRESHOLD: ${{ inputs.fail-on-threshold }} - GHA_MEHEN_COMMENT_TITLE: ${{ inputs.comment-title }} - GHA_MEHEN_COVERAGE_FILES: ${{ inputs.coverage-files }} - GHA_MEHEN_COVERAGE_BASE_SOURCE: ${{ inputs.coverage-base-source }} - GHA_MEHEN_COVERAGE_ARTIFACT_NAME: ${{ inputs.coverage-artifact-name }} - GHA_MEHEN_CODECOV_TOKEN: ${{ inputs.codecov-token }} - GHA_MEHEN_COVERAGE_BASE_DIR: ${{ runner.temp }}/mehen-base-coverage - GHA_MEHEN_COVERAGE_CACHE_HIT: ${{ steps.coverage-restore.outputs.cache-hit }} - GHA_MEHEN_COVERAGE_CACHE_KEY: ${{ steps.coverage-restore.outputs.cache-matched-key }} diff --git a/check-grammar-crate.py b/check-grammar-crate.py new file mode 100755 index 00000000..b6b4f698 --- /dev/null +++ b/check-grammar-crate.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python3 + +"""check-grammar-crate +This script checks whether breaking changes could be introduced in +mehen code after the update of a tree-sitter-grammar crate. +To do so, it compares the differences between the metrics, computed on a +chosen repository, before and after a tree-sitter-grammar update. + + +To compute metrics: + +./check-grammar-crate.py compute-metrics -u REPO_URL -p LOCAL_DIR -l TREE_SITTER_GRAMMAR + +NOTE: The compute-metrics subcommand MUST be run on a clean master branch! + +To compute metrics on a continuous integration system: + +./check-grammar-crate.py compute-ci-metrics -p LOCAL_DIR -l TREE_SITTER_GRAMMAR + +To compare metrics and retrieve metrics differences and minimal tests: + +1. Install json-minimal-tests from here: https://github.com/Luni-4/json-minimal-tests/releases + +./check-grammar-crate.py compare-metrics -l TREE_SITTER_GRAMMAR + +NOTE: Add the paths of the software above to the PATH environment variable! +""" + +import argparse +import pathlib +import subprocess +import sys +import typing as T + +# The /tmp directory will be used as workdir +WORKDIR = pathlib.Path("/tmp") +# Suffix for the directory containing the old metrics +OLD_SUFFIX = "-old" +# Suffix for the directory containing the new metrics +NEW_SUFFIX = "-new" + +# Extensions parsed by each tree-sitter-grammar +EXTENSIONS = { + "tree-sitter-tsx": ["*.tsx"], + "tree-sitter-typescript": ["*.ts", "*.jsw", "*.jsmw"], + "tree-sitter-go": ["*.go"], + "tree-sitter-rust": ["*.rs"], + "tree-sitter-python": ["*.py"], +} + +# Run a subprocess. +def run_subprocess(cmd: str, *args: T.Union[str, pathlib.Path]) -> None: + subprocess.run([cmd, *args]) + + +# Run mehen on the chosen repository to compute metrics. +def run_rca( + repo_dir: pathlib.Path, + output_dir: pathlib.Path, + manifest_path: T.Optional[pathlib.Path], + include_grammars: T.List[str], +) -> None: + run_subprocess( + "cargo", + "run", + "--manifest-path", + manifest_path / "Cargo.toml" if manifest_path else "Cargo.toml", + "--release", + "--package", + "mehen-cli", + "--", + "--metrics", + "--output-format=json", + "--pr", + "-I", + *include_grammars, + "-p", + repo_dir, + "-o", + output_dir, + ) + + +# Compute continuous integration metrics before and after a +# tree-sitter-grammar update. +def compute_ci_metrics(args: argparse.Namespace) -> None: + + if args.grammar != "tree-sitter" and args.grammar not in EXTENSIONS.keys(): + print(args.grammar, "is not a valid tree-sitter grammar") + sys.exit(1) + + # Use the specified grammar + grammar = args.grammar + + # Repository passed as input + repo_dir = pathlib.Path(args.path) + + # Create mehen repository path + rca_path = WORKDIR / "mehen" + + # Old metrics directory + old_dir = WORKDIR / (args.grammar + OLD_SUFFIX) + # New metrics directory + new_dir = WORKDIR / (args.grammar + NEW_SUFFIX) + + # Create output directories + old_dir.mkdir(parents=True, exist_ok=True) + new_dir.mkdir(parents=True, exist_ok=True) + + # Git clone mehen main branch repository + print(f"Cloning mehen main branch into /tmp") + run_subprocess( + "git", + "clone", + "--depth=1", + "-j8", + "https://github.com/ophidiarium/mehen", + rca_path, + ) + + # Compute old metrics + print("\nComputing metrics before the update and saving them in", old_dir) + run_rca(repo_dir, old_dir, rca_path, EXTENSIONS[grammar]) + + # Compute new metrics + print("\nComputing metrics after the update and saving them in", new_dir) + run_rca(repo_dir, new_dir, None, EXTENSIONS[grammar]) + + +# Compute metrics before and after a tree-sitter-grammar update. +def compute_metrics(args: argparse.Namespace) -> None: + + if args.grammar not in EXTENSIONS.keys(): + print(args.grammar, "is not a valid tree-sitter grammar") + sys.exit(1) + + # Repository local directory + repo_dir = WORKDIR / args.path + # Old metrics directory + old_dir = WORKDIR / (args.grammar + OLD_SUFFIX) + # New metrics directory + new_dir = WORKDIR / (args.grammar + NEW_SUFFIX) + + # Create output directories + old_dir.mkdir(parents=True, exist_ok=True) + new_dir.mkdir(parents=True, exist_ok=True) + + # Skip if only new metrics are requested + if not args.only_new: + + # Git clone the chosen repository + print(f"Cloning {args.url} into {repo_dir}") + run_subprocess("git", "clone", "--depth=1", args.url, repo_dir) + + # Compute old metrics + print("\nComputing metrics before the update and saving them in", old_dir) + run_rca(repo_dir, old_dir, None, EXTENSIONS[args.grammar]) + + # Create a new branch + print("\nCreate a new branch called", args.grammar) + run_subprocess("git", "checkout", "-B", args.grammar) + + # Compute new metrics + print("\nComputing metrics after the update and saving them in", new_dir) + run_rca(repo_dir, new_dir, None, EXTENSIONS[args.grammar]) + + +# Compare metrics and dump the differences whether there are some. +def compare_metrics(args: argparse.Namespace) -> None: + # Old metrics directory + old_dir = WORKDIR / (args.grammar + OLD_SUFFIX) + # New metrics directory + new_dir = WORKDIR / (args.grammar + NEW_SUFFIX) + + # Compare metrics directory + compare_dir = WORKDIR / (args.grammar + "-compare") + + # Create compare directory + compare_dir.mkdir(parents=True, exist_ok=True) + + # Get JSON differences and minimal tests + print("\nSave minimal tests in", compare_dir) + run_subprocess("json-minimal-tests", "-o", compare_dir, old_dir, new_dir) + + +def main() -> None: + parser = argparse.ArgumentParser( + prog="check-grammar-crate", + description="This tool computes the metrics of a chosen repository " + "before and after a tree-sitter grammar update.", + epilog="The source code of this program can be found on " + "GitHub at https://github.com/ophidiarium/mehen", + ) + + # Subcommands parsers + commands = parser.add_subparsers(help="Sub-command help") + + # Compute metrics command + compute_metrics_cmd = commands.add_parser( + "compute-metrics", + help="Computes the metrics of a chosen repository before and after " + "a tree-sitter grammar update.", + ) + + # Optional arguments + compute_metrics_cmd.add_argument( + "--only-new", + "-n", + action="store_true", + help="Only compute the metrics after a tree-sitter grammar update", + ) + + # Arguments + compute_metrics_cmd.add_argument( + "-u", + "--url", + type=str, + required=True, + help="URL of the repository used to compute the metrics", + ) + + compute_metrics_cmd.add_argument( + "-p", + "--path", + type=str, + required=True, + help="Path where the repository will be saved locally", + ) + + compute_metrics_cmd.add_argument( + "-g", + "--grammar", + type=str, + required=True, + help="tree-sitter grammar to be updated", + ) + compute_metrics_cmd.set_defaults(func=compute_metrics) + + # Compute continuous integration metrics command + compute_ci_metrics_cmd = commands.add_parser( + "compute-ci-metrics", + help="Computes the metrics of a chosen repository before and after " + "a tree-sitter grammar update on a continuous integration system.", + ) + + # Arguments + compute_ci_metrics_cmd.add_argument( + "-p", + "--path", + type=str, + required=True, + help="Path where the mehen repository is saved on the " + "continuous integration system", + ) + compute_ci_metrics_cmd.add_argument( + "-g", + "--grammar", + type=str, + required=True, + help="tree-sitter grammar to be updated", + ) + + compute_ci_metrics_cmd.set_defaults(func=compute_ci_metrics) + + # Compare metrics command + compare_metrics_cmd = commands.add_parser( + "compare-metrics", + help="Compares the metrics before and after " + "a tree-sitter grammar update in order to discover whether " + "there are differences.", + ) + + # Arguments + compare_metrics_cmd.add_argument( + "-g", + "--grammar", + type=str, + required=True, + help="tree-sitter grammar used to compare the metrics", + ) + compare_metrics_cmd.set_defaults(func=compare_metrics) + + # Parse arguments + args = parser.parse_args() + + # Call the command + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/check-grammars-crates.sh b/check-grammars-crates.sh new file mode 100755 index 00000000..56bde710 --- /dev/null +++ b/check-grammars-crates.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# Stop at the first error +set -e + +# Get tree-sitter-grammar +TS_CRATE=`grep $1 Cargo.toml | tr -d ' '` + +# Disable/Enable CI flag +RUN_CI="no" + +# Temporary main branch Cargo.toml filename +MAIN_CARGO_TOML="main-cargo.toml" + +# Download main branch Cargo.toml and save it in a temporary file +wget -LqO - https://raw.githubusercontent.com/ophidiarium/mehen/main/Cargo.toml | tr -d ' ' > $MAIN_CARGO_TOML + +# Get the name of the current crate +TS_CRATE_NAME=`echo $TS_CRATE | cut -f1 -d "="` + +# Get the crate name from the master branch Cargo.toml +MASTER_TS_CRATE_NAME=`grep $TS_CRATE_NAME $MAIN_CARGO_TOML | head -n 1 | cut -f1 -d "="` + +# If the current crate name is not present in master branch, exit the script +if [ -z "$MASTER_TS_CRATE_NAME" ] +then + exit 0 +fi + +# Get the same crate from the master branch Cargo.toml +MASTER_TS_CRATE=`grep $TS_CRATE $MAIN_CARGO_TOML | head -n 1` + +# If the current crate has been updated, save the crate name +if [ -z "$MASTER_TS_CRATE" ] +then + # Enable CI flag + RUN_CI="yes" + # Name of tree-sitter crate + TREE_SITTER_CRATE=$TS_CRATE_NAME +fi + +# Remove temporary master branch Cargo.toml file +rm -rf $MAIN_CARGO_TOML + +# If any crates have been updated, exit the script +if [ "$RUN_CI" = "no" ]; then + exit 0 +fi + +# Install json minimal tests +JMT_LINK="https://github.com/Luni-4/json-minimal-tests/releases/download" +JMT_VERSION="0.1.9" +curl -L "$JMT_LINK/v$JMT_VERSION/json-minimal-tests-linux.tar.gz" | +tar xz -C $CARGO_HOME/bin + +# Use a test repository (configure your own test repository) +TEST_REPO="${TEST_REPO_PATH:-/cache/test-repo}" + +# Compute metrics +./check-grammar-crate.py compute-ci-metrics -p $TEST_REPO -g $TREE_SITTER_CRATE + +# Count files in metrics directories +OLD=`ls /tmp/$TREE_SITTER_CRATE-old | wc -l` +NEW=`ls /tmp/$TREE_SITTER_CRATE-new | wc -l` + +# Print number of files contained in metrics directories +echo "$TREE_SITTER_CRATE-old: $OLD" +echo "$TREE_SITTER_CRATE-new: $NEW" + +# If metrics directories differ in number of files, +# print only the files that are in a directory but not in the other one +if [ $OLD != $NEW ] +then + ONLY_FILES=`diff -q /tmp/$TREE_SITTER_CRATE-old /tmp/$TREE_SITTER_CRATE-new | grep "Only in"` + echo "$ONLY_FILES" +fi + +# Compare metrics +./check-grammar-crate.py compare-metrics -g $TREE_SITTER_CRATE + +# Create artifacts to be uploaded (if there are any) +COMPARE=/tmp/$TREE_SITTER_CRATE-compare +if [ "$(ls -A $COMPARE)" ]; then + # Maximum number of considered minimal tests for a metric + MT_THRESHOLD=30 + + # Output directory path + OUTPUT_DIR=/tmp/output-$TREE_SITTER_CRATE + + # Grammar name (removes tree-sitter- prefix) + GRAMMAR_NAME=`echo $TREE_SITTER_CRATE | cut -c 13-` + + # Split files into distinct directories depending on + # their metric differences + ./split-minimal-tests.py -i $COMPARE -o $OUTPUT_DIR -t $MT_THRESHOLD + + tar -czvf /tmp/json-diffs-and-minimal-tests-$GRAMMAR_NAME.tar.gz $COMPARE $OUTPUT_DIR +fi diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index 16f15fb3..00000000 --- a/codecov.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Codecov configuration. -# See https://docs.codecov.com/docs/codecov-yaml for the schema. - -# The per-language tree-sitter kind enums at `crates/mehen-*/src/grammar.rs` -# are generated by `cargo xtask tree-sitter generate ` from the -# pinned grammar's `node-kind` table. They contain no business logic — -# just a flat `enum` of every tree-sitter node kind plus `From` / -# `From<&str>` glue — so their coverage is dominated by `unreachable!()`- -# style default branches that are semantically unreachable when the -# grammar is well-formed. Excluding them keeps the coverage report -# focused on hand-written analysis code. -ignore: - - "crates/*/src/grammar.rs" diff --git a/crates/mehen-antlr/Cargo.toml b/crates/mehen-antlr/Cargo.toml deleted file mode 100644 index ba795db5..00000000 --- a/crates/mehen-antlr/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "mehen-antlr" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — shared support for ANTLR-backed analyzer crates (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -# `antlr4_runtime` is the lib name of the `antlr-rust-runtime` package -# (`ophi-dev/antlr-rust-runtime`). Pinned exactly here — like every other -# parser dependency (ra_ap_syntax, ruby-prism) — because parser-level -# behavior must be reproducible across builds. This crate is the single -# point where the workspace depends on the ANTLR runtime; analyzer crates -# (mehen-kotlin, …) reach the runtime through `mehen_antlr`'s re-export so -# they never pin the version independently. -antlr4_runtime = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-antlr/src/comments.rs b/crates/mehen-antlr/src/comments.rs deleted file mode 100644 index f534b8ef..00000000 --- a/crates/mehen-antlr/src/comments.rs +++ /dev/null @@ -1,462 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC token extraction from the ANTLR token stream. -//! -//! ANTLR lexers route comments and whitespace to a hidden channel, so they -//! never appear in the parse tree — but the buffered [`CommonTokenStream`] -//! retains every token in source order. LOC is therefore computed from a -//! single ordered pass over that full token list rather than from the tree: -//! comments and code tokens are observed *interleaved*, so a comment that -//! shares a line with code is correctly classified as a code-comment (not -//! comment-only), and per-space `loc.cloc`/`loc.ploc` reflect the tokens -//! inside each scope's body when routed through -//! `mehen_metrics::SpaceRangeTracker`. -//! -//! This mirrors how the token-driven analyzers (`mehen-rust`, `mehen-python`, -//! `mehen-typescript`) drive LOC: a flat, source-ordered token sweep. -//! -//! Since the 0.11 runtime rewrite there is no owned `CommonToken`: tokens live -//! once in the parser-owned [`TokenStore`](antlr4_runtime::TokenStore) and are -//! read through borrowing [`TokenView`]s. The LOC sweep therefore takes an -//! iterator of `TokenView` — e.g. `CommonTokenStream::tokens()` — instead of a -//! `&[CommonToken]` slice. - -use antlr4_runtime::token::{Token, TokenView}; - -/// How a token contributes to LOC. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum LocTokenKind { - /// A code token — its start row is a PLOC line. - Code, - /// A comment token — contributes CLOC across `[start_row, end_row]`. - Comment, -} - -/// A source-ordered LOC observation: a code or comment token with the byte -/// range used to route it to the deepest enclosing space, and the 0-based -/// rows it spans. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct LocToken { - pub kind: LocTokenKind, - /// Byte offsets (UTF-8) for `SpaceRangeTracker` routing. - pub start_byte: u32, - pub end_byte: u32, - /// 0-based start row (matches the LOC accumulator's row convention). - pub start_row: u32, - /// 0-based end row (`> start_row` only for multi-line block comments). - pub end_row: u32, -} - -/// Build the source-ordered LOC token list from the buffered token stream. -/// -/// `comment_token_types` is the set of lexer token types that denote a -/// comment. `skip_token_types` is the set that contributes nothing to LOC -/// (whitespace, newlines). `trivia_bearing_token_types` is the set of -/// operator tokens whose lexer rules fold optional comments into the token -/// text (e.g. Kotlin's `EXCL_WS`/`NOT_IS`/`NOT_IN`/`QUEST_WS`/`AS_*`); their -/// text is scanned for embedded comments. Every other token is treated as -/// code (its start row is a PLOC line). The end-of-file token (`< 0`) is -/// skipped. -/// -/// Restricting the embedded-comment scan to `trivia_bearing_token_types` -/// (rather than every token) avoids false positives from `//` or `/*` that -/// appear inside string-literal text tokens (e.g. a URL `"http://x"`). -/// -/// Byte ranges come from the runtime's UTF-8 token spans, so routing stays -/// correct for non-ASCII source. -/// -/// `tokens` is any source-ordered iterator of [`TokenView`]s over the full -/// (hidden-channel-inclusive) token stream. The owned -/// [`ParsedFile`](antlr4_runtime::ParsedFile)'s token store satisfies this -/// directly — `&TokenStore` is `IntoIterator` since the 0.15 runtime (issue -/// #123) — so callers pass `parsed.tokens()`; a live -/// [`CommonTokenStream::tokens`](antlr4_runtime::CommonTokenStream::tokens) -/// works too. -pub fn loc_tokens<'a>( - tokens: impl IntoIterator>, - comment_token_types: &[i32], - skip_token_types: &[i32], - trivia_bearing_token_types: &[i32], - line_index: &mehen_core::LineIndex, -) -> Vec { - let tokens = tokens.into_iter(); - let mut out = Vec::with_capacity(tokens.size_hint().0); - for tok in tokens { - // Since the 0.15 runtime `TokenView::text()` returns `Option<&str>` - // (aligned with the `Token` trait); `text_or_empty()` is the runtime's - // own convenience for the "empty when absent" behavior the LOC - // classifier wants (a token with no recorded text contributes no - // embedded newlines). Everything past this point works on plain - // fields, so the classification is unit-testable without a - // `TokenStore`. - // Byte offsets are optional since the 0.23 runtime (a token source that - // cannot resolve them reports `None`). A token with no position cannot - // be attributed to a source row, so it contributes no LOC — the same - // treatment absent text already gets above. - let (Some(start_byte), Some(stop_byte)) = (tok.start_byte(), tok.stop_byte()) else { - continue; - }; - // BOTH rows come from `LineIndex`, not from `tok.line()` and not from counting - // terminators in the token text. - // - // The start row, because the runtime's lexer advances its line counter on `\n` - // alone while `LineIndex` may count more — so after any other terminator the - // token's own line is short, and a comment gets routed onto the preceding code - // row with its real row falling out as a phantom blank. - // - // The end row, because *which characters break a row is the caller's policy*. - // This used to count the five C# terminators inline, which was wrong for every - // caller that does not share that policy: Java and Kotlin pass - // `LineIndex::new` (LF/CRLF only), so `/*ab*/` was counted as two - // comment rows against a one-row file — CLOC 2 > SLOC 1, which also skews - // `blank = sloc - ploc - only_comment` and every MI variant downstream. Asking - // the index resolves it for free and leaves the terminator set knowledge in one - // place. - let start_row = line_index.line_at(mehen_core::byte_offset_clamped(start_byte)); - let end_row = line_index.line_at(mehen_core::byte_offset_clamped(stop_byte)); - push_loc_token( - tok.token_type(), - start_byte, - stop_byte, - start_row, - end_row.max(start_row), - tok.text_or_empty(), - comment_token_types, - skip_token_types, - trivia_bearing_token_types, - &mut out, - line_index, - ); - } - out -} - -/// Classify a single token's plain fields into zero or more [`LocToken`]s, -/// pushing them onto `out`. Split out of [`loc_tokens`] so the classification -/// is exercised by unit tests without constructing runtime -/// [`TokenView`]s (which the 0.11 rewrite made un-buildable outside a real -/// `TokenStore`). `text` is the token's UTF-8 text (empty when absent). -/// -/// `start_line` and `end_line` are 1-based rows already resolved through -/// `line_index` — this function deliberately derives no row from the token text, -/// since which characters break a row is per-language policy. `line_index` itself is -/// still needed to resolve rows *inside* a trivia-bearing token (see -/// [`emit_embedded_comments`]). -#[allow(clippy::too_many_arguments)] -fn push_loc_token( - tt: i32, - start_byte: usize, - stop_byte: usize, - start_line: u32, - end_line: u32, - text: &str, - comment_token_types: &[i32], - skip_token_types: &[i32], - trivia_bearing_token_types: &[i32], - out: &mut Vec, - line_index: &mehen_core::LineIndex, -) { - if tt < 0 || skip_token_types.contains(&tt) { - return; - } - let start_byte = mehen_core::byte_offset_clamped(start_byte); - let end_byte = mehen_core::byte_offset_clamped(stop_byte).max(start_byte); - let start_row = start_line.saturating_sub(1); - if comment_token_types.contains(&tt) { - // A delimited comment's text may span multiple rows, so its end row comes from - // the end byte. A line comment's two rows coincide, which needs no special - // case. - out.push(LocToken { - kind: LocTokenKind::Comment, - start_byte, - end_byte, - start_row, - end_row: end_line.saturating_sub(1).max(start_row), - }); - } else { - out.push(LocToken { - kind: LocTokenKind::Code, - start_byte, - end_byte, - start_row, - end_row: start_row, - }); - // Some lexers fold optional trivia into operator tokens — e.g. - // Kotlin's `EXCL_WS: '!' Hidden`, `NOT_IS: '!is' (Hidden|NL)` — - // so a comment glued to the operator (`!is/* c */`) is part of - // the token text rather than a standalone comment token. Recover - // those as comments so CLOC isn't undercounted, using the same - // byte span the embedded comment occupies and rows resolved through - // the same index. Only the declared trivia-bearing operator tokens - // are scanned, so a `//` or `/*` inside string-literal text is never - // misread. - if trivia_bearing_token_types.contains(&tt) { - emit_embedded_comments(text, start_byte, out, line_index); - } - } -} - -/// Scan an operator-token's `text` for embedded `/* … */` or `// …` comment -/// runs and push a [`LocTokenKind::Comment`] for each, with the byte span offset -/// from the token's `token_start_byte`. Handles multi-line block comments. -/// -/// Rows are resolved through `line_index` from the absolute byte offsets, not by -/// counting `\n` in the text. This scan is byte-oriented (it looks for `/*`, `*/`, and -/// `//` in the UTF-8 bytes) and a multi-byte terminator like U+2028 cannot be recognized -/// there without decoding — but the row question is already answered by the index, whose -/// policy is the caller's. Counting `\n` alone attributed a comment split by a lone CR to -/// one CLOC row in a two-row file, leaving the second row to fall out as a phantom blank. -fn emit_embedded_comments( - text: &str, - token_start_byte: u32, - out: &mut Vec, - line_index: &mehen_core::LineIndex, -) { - // 0-based row for an offset within `text`, via the absolute byte position. - let row_at = |offset: usize| { - line_index - .line_at(token_start_byte.saturating_add(mehen_core::byte_offset_clamped(offset))) - .saturating_sub(1) - }; - let bytes = text.as_bytes(); - let mut i = 0usize; - while i + 1 < bytes.len() { - match (bytes[i], bytes[i + 1]) { - (b'/', b'*') => { - let comment_start = i; - i += 2; - // Find the closing `*/`. - while i + 1 < bytes.len() && !(bytes[i] == b'*' && bytes[i + 1] == b'/') { - i += 1; - } - i += 2; // consume `*/` (or run off the end on an unclosed comment) - let end = i.min(bytes.len()); - let start_row = row_at(comment_start); - out.push(LocToken { - kind: LocTokenKind::Comment, - start_byte: token_start_byte + comment_start as u32, - end_byte: token_start_byte + end as u32, - start_row, - // From the end byte, so every terminator the caller's policy counts - // is included — `end.saturating_sub(1)` stays inside the comment, - // since the range is half-open. - end_row: row_at(end.saturating_sub(1)).max(start_row), - }); - } - (b'/', b'/') => { - // Line comment runs to the next `\n` (or token end). Scanning for `\n` - // is right here regardless of policy: a line comment ends at the first - // terminator, and any policy counts `\n` as one. A comment ended by a - // *different* terminator would run slightly long in the byte span, which - // the row lookup below then reports on the correct row anyway. - let comment_start = i; - while i < bytes.len() && bytes[i] != b'\n' { - i += 1; - } - let start_row = row_at(comment_start); - out.push(LocToken { - kind: LocTokenKind::Comment, - start_byte: token_start_byte + comment_start as u32, - end_byte: token_start_byte + i as u32, - start_row, - end_row: start_row, - }); - } - _ => i += 1, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - /// One fake token's fields, mirroring what a [`TokenView`] would expose. - /// The 0.11 runtime rewrite made real tokens un-buildable outside a - /// parser-owned `TokenStore`, so the classification is exercised through - /// [`push_loc_token`] on plain fields instead. - /// `line` / `end_line` are the 1-based rows the caller resolves through its - /// [`LineIndex`](mehen_core::LineIndex) — `push_loc_token` no longer derives the end - /// row from the text, because which characters break a row is per-language policy. - struct Tok { - tt: i32, - line: usize, - end_line: usize, - start: usize, - stop: usize, - text: &'static str, - } - - /// A token occupying one row. - const fn tok(tt: i32, line: usize, start: usize, stop: usize, text: &'static str) -> Tok { - Tok { - tt, - line, - end_line: line, - start, - stop, - text, - } - } - - /// A token spanning `line..=end_line`, as `LineIndex` would resolve it. - const fn spanning_tok( - tt: i32, - line: usize, - end_line: usize, - start: usize, - stop: usize, - text: &'static str, - ) -> Tok { - Tok { - tt, - line, - end_line, - start, - stop, - text, - } - } - - /// Run the LOC classification over a fake token list, mirroring what - /// [`loc_tokens`] does per [`TokenView`]. - /// - /// The rows come from each `Tok`'s own `line`/`end_line` (the caller resolves those - /// in real use), so an empty index suffices for every case except a - /// trivia-bearing token — whose *embedded* comment rows are looked up by byte - /// offset. [`classify_in`] supplies real source for those. - fn classify(tokens: &[Tok], comment: &[i32], skip: &[i32], trivia: &[i32]) -> Vec { - classify_in("", tokens, comment, skip, trivia) - } - - /// [`classify`] against a known `source`, so embedded-comment rows resolve through a - /// real [`LineIndex`] over it. - fn classify_in( - source: &str, - tokens: &[Tok], - comment: &[i32], - skip: &[i32], - trivia: &[i32], - ) -> Vec { - let line_index = mehen_core::LineIndex::new(source); - let mut out = Vec::new(); - for t in tokens { - push_loc_token( - t.tt, - t.start, - t.stop, - t.line as u32, - t.end_line as u32, - t.text, - comment, - skip, - trivia, - &mut out, - &line_index, - ); - } - out - } - - #[test] - fn classifies_code_and_comment_in_source_order() { - // `code // a` then a code token on the next line. - let tokens = [ - tok(2, 1, 0, 3, "code"), // code - tok(1, 1, 5, 8, "// a"), // comment (type 1) - tok(2, 2, 10, 10, "x"), // code - ]; - let locs = classify(&tokens, &[1], &[], &[]); - assert_eq!(locs.len(), 3); - assert_eq!(locs[0].kind, LocTokenKind::Code); - assert_eq!(locs[1].kind, LocTokenKind::Comment); - assert_eq!(locs[1].start_row, 0); - assert_eq!(locs[2].kind, LocTokenKind::Code); - assert_eq!(locs[2].start_row, 1); - } - - #[test] - fn multiline_comment_spans_rows_and_skips_whitespace() { - let tokens = [ - spanning_tok(1, 1, 3, 0, 10, "/* a\nb\nc */"), // 3-line comment - tok(99, 3, 11, 11, " "), // whitespace (skipped) - ]; - let locs = classify(&tokens, &[1], &[99], &[]); - assert_eq!(locs.len(), 1); - assert_eq!(locs[0].kind, LocTokenKind::Comment); - assert_eq!(locs[0].start_row, 0); - assert_eq!(locs[0].end_row, 2); - } - - #[test] - fn a_comments_end_row_comes_from_the_caller_not_from_its_text() { - // REGRESSION. This counted the five C# line terminators inline, which was wrong - // for every caller not sharing that policy: Java and Kotlin pass - // `LineIndex::new` (LF/CRLF only), so `/*ab*/` was reported as two - // comment rows in a one-row file — CLOC 2 against SLOC 1, which also skews - // `blank = sloc - ploc - only_comment` and every MI variant downstream. - // - // The text here HAS a U+2028 and the caller says one row, which is what a - // LF/CRLF-only index resolves. The end row must follow the caller. - let one_row = classify(&[tok(1, 1, 0, 9, "/*a\u{2028}b*/")], &[1], &[], &[]); - assert_eq!(one_row[0].end_row, 0, "the caller's index says one row"); - - // Same text, a caller whose policy DOES split on U+2028 (C#'s does). - let two_rows = classify( - &[spanning_tok(1, 1, 2, 0, 9, "/*a\u{2028}b*/")], - &[1], - &[], - &[], - ); - assert_eq!(two_rows[0].end_row, 1); - } - - #[test] - fn an_end_row_never_precedes_the_start_row() { - // A synthesized or zero-width token can resolve both ends to the same byte, and - // a caller could in principle hand back an inverted pair; clamping keeps the - // range well-formed rather than underflowing the row subtraction. - let locs = classify(&[spanning_tok(1, 3, 1, 5, 5, "//x")], &[1], &[], &[]); - assert_eq!(locs[0].start_row, 2); - assert_eq!(locs[0].end_row, 2); - } - - #[test] - fn eof_token_is_skipped() { - let tokens = [tok(-1, 1, 0, 0, "")]; - assert!(classify(&tokens, &[], &[], &[]).is_empty()); - } - - #[test] - fn recovers_comment_embedded_in_trivia_bearing_operator() { - // Operator token type 105 (`!is`) with a glued comment: `!is/* c */`. - // Source: `a !is/* c */ B` — operator token spans chars 2..=10. - let tokens = [ - tok(7, 1, 0, 0, "a"), // identifier (code) - tok(105, 1, 2, 10, "!is/* c */"), // NOT_IS with embedded comment - tok(7, 1, 13, 13, "B"), // identifier (code) - ]; - // 105 is declared trivia-bearing → its embedded `/* c */` is recovered. - let locs = classify(&tokens, &[2], &[], &[105]); - let comments: Vec<_> = locs - .iter() - .filter(|t| t.kind == LocTokenKind::Comment) - .collect(); - assert_eq!(comments.len(), 1, "embedded comment must be recovered"); - assert_eq!(comments[0].start_row, 0); - } - - #[test] - fn does_not_scan_non_trivia_tokens_for_comments() { - // A string-literal text token containing `//` (e.g. a URL) must NOT - // be misread as a comment — only declared trivia-bearing tokens are - // scanned. Token type 7 is not in the trivia-bearing set. - let tokens = [tok(7, 1, 0, 9, "\"http://x\"")]; - let locs = classify(&tokens, &[2], &[], &[105]); - assert!( - locs.iter().all(|t| t.kind == LocTokenKind::Code), - "the // inside a string literal must not become a comment" - ); - } -} diff --git a/crates/mehen-antlr/src/diagnostics.rs b/crates/mehen-antlr/src/diagnostics.rs deleted file mode 100644 index e48d9984..00000000 --- a/crates/mehen-antlr/src/diagnostics.rs +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Structured diagnostic collection for ANTLR lexers and parse trees. -//! -//! Lexer errors are reported through runtime listeners because an unrecognized -//! character can be skipped before the parser sees the token stream. Parser -//! recovery instead surfaces as `ParseTree::Error` leaves embedded in an -//! otherwise-complete tree. Per mehen's diagnostic contract (rewrite plan -//! §9.3), both must become `error`-severity diagnostics so that `mehen metrics` -//! exits 1 and `mehen diff` records the file under `analysis_errors`. -//! -//! Hard parser failures (the entry-rule call itself returning `Err`) are a -//! separate, `fatal` path handled by the analyzer crate; this module only -//! covers listener diagnostics and recovered `Error` nodes. - -use std::sync::{Arc, Mutex}; - -use antlr4_runtime::token::Token; -use antlr4_runtime::{ErrorListener, Node, Recognizer}; -use mehen_core::{ParseDiagnostic, SourceSpan, byte_offset_clamped}; - -#[derive(Clone, Debug)] -struct CollectedDiagnostic { - line: usize, - column: usize, - message: String, - /// Byte range of the offending source text, when the runtime resolved one. - /// - /// Since the 0.23 runtime (upstream #257) `syntax_error` receives a - /// [`SyntaxErrorEvent`] carrying the resolved byte span directly, so this no - /// longer has to be reconstructed from the offending token. Absent for - /// custom streams that cannot resolve byte offsets. - span: Option<(u32, u32)>, -} - -/// Cloneable runtime listener that records diagnostics without writing to -/// stderr. -#[derive(Clone, Debug, Default)] -pub struct DiagnosticCollector { - diagnostics: Arc>>, -} - -impl ErrorListener for DiagnosticCollector -where - R: Recognizer + ?Sized, -{ - fn syntax_error(&mut self, _recognizer: &R, event: &antlr4_runtime::SyntaxErrorEvent<'_>) { - // The event's span is already a half-open byte range, so it only needs - // narrowing to mehen's `u32` offsets. `max` keeps the range well-formed - // if clamping collapsed the two ends. - let span = event.span.as_ref().map(|range| { - let start = byte_offset_clamped(range.start); - (start, byte_offset_clamped(range.end).max(start)) - }); - self.diagnostics - .lock() - .expect("ANTLR diagnostic collector lock poisoned") - .push(CollectedDiagnostic { - line: event.line, - column: event.column, - message: event.message.to_owned(), - span, - }); - } -} - -impl DiagnosticCollector { - /// Convert at most `max_diagnostics` collected runtime diagnostics to - /// mehen's structured form. - /// - /// `line_index` resolves the span's *end* line. A single token can cover - /// several rows — a verbatim or raw string literal is one token spanning as - /// many lines as it contains — so deriving `end_line` from the end byte keeps - /// the byte range and the line range describing the same region. Taking - /// `end_line` from the start line instead yields a `SourceSpan` whose halves - /// disagree, which a renderer highlighting by line would get wrong. - pub fn diagnostics( - &self, - code: &str, - max_diagnostics: usize, - line_index: &mehen_core::LineIndex, - ) -> Vec { - self.diagnostics - .lock() - .expect("ANTLR diagnostic collector lock poisoned") - .iter() - .take(max_diagnostics) - .map(|diagnostic| { - // The offending token's byte range, when the runtime had one. - let span = diagnostic.span.map(|(start_byte, end_byte)| { - // From the byte offset for the same reason as `collect_errors` - // below: the runtime counts only `\n`, `LineIndex` may count more, - // and a span whose halves disagree misdirects any renderer that - // highlights by line. - let start_line = line_index.line_at(start_byte); - SourceSpan { - start_byte, - end_byte, - start_line, - end_line: line_index.line_at(end_byte).max(start_line), - } - }); - // The *message* row comes from the same place as the span's, so the two - // cannot contradict each other. Printing the runtime's own `line` - // produced a diagnostic that named row 1 while its structured span - // highlighted row 2, on any file using a terminator the runtime's lexer - // does not count. Without a span there is nothing better to use, so the - // runtime's row stands — it is at least self-consistent then. - // - // The column is left as reported: `LineIndex` resolves rows, not - // columns, and re-deriving one would need the row's start byte plus a - // decision about tabs and grapheme clusters that no consumer asks for. - let line = span.map_or(diagnostic.line, |s| s.start_line as usize); - let mut out = ParseDiagnostic::error( - code, - format!( - "ANTLR error at line {}:{}: {}", - line, diagnostic.column, diagnostic.message - ), - ); - out.span = span; - out - }) - .collect() - } - - #[cfg(test)] - fn push_for_test(&self, line: usize, column: usize, span: Option<(u32, u32)>) { - self.diagnostics - .lock() - .expect("ANTLR diagnostic collector lock poisoned") - .push(CollectedDiagnostic { - line, - column, - message: "test".to_string(), - span, - }); - } -} - -/// Walk `tree` and emit one `error`-severity [`ParseDiagnostic`] per recovered -/// error leaf ([`NodeKind::Error`](antlr4_runtime::NodeKind::Error)), capped at -/// `max_diagnostics` to bound noise on heavily corrupted input. -/// -/// `code` is the language-namespaced diagnostic code, e.g. -/// `"kotlin.syntax_error"`. Returns an empty `Vec` for a clean parse. -/// -/// Since the 0.11 runtime rewrite the tree is a flat arena traversed through -/// borrowing [`Node`] views. [`Node::descendants`] yields a pre-order iterator -/// over the whole subtree, so error leaves are collected by filtering it with -/// [`Node::as_error`] — no hand-rolled recursion. -pub fn collect_errors( - tree: Node<'_>, - code: &str, - max_diagnostics: usize, - line_index: &mehen_core::LineIndex, -) -> Vec { - tree.descendants() - .filter_map(Node::as_error) - .take(max_diagnostics) - .map(|err| { - let token = err.symbol(); - // The error leaf owns the offending token, so the diagnostic can carry - // its byte range. `stop_byte` is **exclusive** — the runtime's own - // `Token::byte_span` is `start_byte()..stop_byte()` — so it is used - // directly. This used to add 1, which made every diagnostic span one - // byte too long: a `(` reported as `"( "`, swallowing the next - // character. `span.rs` and `comments.rs` already used it directly, so - // the `+1` was also inconsistent within this crate. - // - // `max` keeps the range well-formed if clamping collapsed the two ends - // (a synthesized recovery token can be zero-width). - // - // Both offsets are optional since the 0.23 runtime: a token source - // that cannot resolve byte offsets reports `None`. Leave the span - // off in that case rather than inventing one — the line number in - // the message still locates the error. - // - // `end_line` comes from the end byte, not from `line`: the offending - // token may be a multi-row literal (see `diagnostics` above). - let span = token - .start_byte() - .zip(token.stop_byte()) - .map(|(start, stop)| { - let start_byte = byte_offset_clamped(start); - let end_byte = byte_offset_clamped(stop).max(start_byte); - // From the byte offset, not the token's `line()`: the runtime's - // lexer advances its line counter on `\n` alone, while `LineIndex` - // (and the C# lexer) also treat CR, NEL, U+2028, and U+2029 as - // terminators. Taking `line()` produced a span whose `start_byte` - // was on row 2 and whose `start_line` said row 1. - let start_line = line_index.line_at(start_byte); - SourceSpan { - start_byte, - end_byte, - start_line, - end_line: line_index.line_at(end_byte).max(start_line), - } - }); - // The message row comes from the span, so the prose and the structured span - // agree — printing `token.line()` alongside a `LineIndex`-derived span made - // the message name row 1 while the span highlighted row 2. Falls back to the - // runtime's row only when there is no span to derive one from. - let line = span.map_or_else(|| token.line(), |s| s.start_line as usize); - let mut out = ParseDiagnostic::error( - code.to_string(), - format!("ANTLR error node at line {line}"), - ); - out.span = span; - out - }) - .collect() -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::LineIndex; - - /// A diagnostic whose byte range covers several rows must report an `end_line` - /// that matches — a single token CAN span rows (a verbatim or raw string - /// literal), and forcing `end_line` to the start line yields a `SourceSpan` - /// whose byte range and line range describe different regions. - /// - /// Driven through the collector directly rather than through a real parse: the - /// ANTLR recovery strategy consistently attributes the error to a short token - /// beside the multi-row literal rather than to the literal itself, so no C# - /// input reaches this path. The span arithmetic is still wrong if it assumes a - /// single row, and this pins it. - #[test] - fn a_multi_row_span_reports_its_real_end_line() { - let source = "let s = @\"row1\nrow2\nrow3\";\n"; - let line_index = LineIndex::new(source); - // The literal starts on row 1 and ends on row 3. - let start = source.find('@').expect("literal present") as u32; - let end = source.find(';').expect("terminator present") as u32; - - let collector = DiagnosticCollector::default(); - collector.push_for_test(1, 8, Some((start, end))); - let diagnostics = collector.diagnostics("test.syntax_error", 16, &line_index); - - let span = diagnostics[0].span.expect("span present"); - assert_eq!(span.start_line, 1); - assert_eq!(span.end_line, 3, "the literal covers three rows"); - } - - /// Both rows come from the byte offsets, so the runtime's own line counter cannot - /// contradict the span — and `end_line` is still clamped to at least `start_line` - /// so a zero-width range never inverts. - /// - /// The injected `line` here is deliberately wrong (row 3 for a byte on row 1): the - /// runtime's lexer advances its counter on `\n` alone, while `LineIndex` counts all - /// five terminators, so the two disagree on any file that uses another one. The - /// byte offset is the authority. - #[test] - fn rows_come_from_the_byte_offsets_not_the_runtime_line() { - let line_index = LineIndex::new("one\ntwo\nthree\n"); - let collector = DiagnosticCollector::default(); - collector.push_for_test(3, 0, Some((0, 0))); - let diagnostics = collector.diagnostics("test.syntax_error", 16, &line_index); - - let span = diagnostics[0].span.expect("span present"); - assert_eq!( - span.start_line, 1, - "byte 0 is row 1, whatever `line` claimed" - ); - assert_eq!(span.end_line, 1); - } -} diff --git a/crates/mehen-antlr/src/lib.rs b/crates/mehen-antlr/src/lib.rs deleted file mode 100644 index 2ebf24d8..00000000 --- a/crates/mehen-antlr/src/lib.rs +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-antlr` — shared support for ANTLR-backed analyzer crates. -//! -//! This is the ANTLR peer of [`mehen-tree-sitter`]. It does **not** own any -//! language's semantics — anything that interprets a rule index or token -//! type belongs in the owning `mehen-` crate. It provides the plumbing -//! every ANTLR-backed analyzer needs: -//! -//! - **runtime re-export** ([`runtime`]) so analyzer crates depend on the -//! ANTLR runtime through this crate and never pin its version themselves, -//! - **span conversion** ([`span`]) lifting ANTLR token byte spans into -//! mehen's byte-offset [`SourceSpan`](mehen_core::SourceSpan)s, -//! - **diagnostics** ([`diagnostics`]) collecting runtime listener errors and -//! recovered `ParseTree::Error` leaves as mehen -//! [`ParseDiagnostic`](mehen_core::ParseDiagnostic)s, -//! - **LOC tokens** ([`comments`]) a source-ordered code/comment token list -//! for LOC, recovered from the hidden-channel-inclusive -//! token stream (comments are absent from the parse tree). -//! -//! Each ANTLR-backed analyzer owns its own recursive walk over the -//! [`ParseTree`](runtime::ParseTree) — matching the per-language `Visitor` -//! pattern that `mehen-rust` and `mehen-ruby` use — because metric -//! interpretation (which rule opens a space, how cognitive nesting is -//! threaded) is language-specific and ANTLR's parent-less tree means -//! parent context has to be threaded top-down by the owning walker. This -//! crate deliberately does *not* impose a generic walker; a shared walker -//! can be extracted once a second ANTLR grammar shows what is truly common. -//! -//! ## Why ANTLR is a first-class backend -//! -//! mehen already runs analyzers on non-tree-sitter parsers (`ra_ap_syntax` -//! for Rust, Prism for Ruby, Ruff for Python, Oxc for TS). The -//! [`LanguageAnalyzer`](mehen_core::LanguageAnalyzer) trait is parser-neutral -//! and [`AnalysisBackend`](mehen_core::AnalysisBackend) is an open enum. -//! ANTLR slots in as a peer backend: an analyzer parses with a generated -//! ANTLR parser, walks the resulting [`ParseTree`](runtime::ParseTree), and -//! returns an owned `LanguageAnalysis`. The generated parser/lexer modules -//! are produced offline by `cargo xtask antlr generate ` from a -//! vendored `.g4` grammar — the same generate-and-check-in workflow used -//! for tree-sitter kind enums. - -#![forbid(unsafe_code)] - -mod comments; -mod diagnostics; -mod span; - -use mehen_core::{MetricSpace, SourceSpan, SpaceId, SpaceKind}; - -/// Re-export of the ANTLR v4 Rust runtime (`antlr4_runtime`, the library of -/// the `antlr-rust-runtime` package). Generated parser/lexer modules and -/// analyzer crates reach the runtime through this path so the version is -/// pinned in exactly one place ([`mehen-antlr`'s `Cargo.toml`]). -pub use antlr4_runtime as runtime; - -pub use comments::{LocToken, LocTokenKind, loc_tokens}; -pub use diagnostics::{DiagnosticCollector, collect_errors}; -pub use span::{ctx_span, span_from_tokens}; - -/// Build an "empty" unit space — used by analyzers when the parser fails -/// before any walk can happen. -pub fn empty_space(span: SourceSpan) -> MetricSpace { - MetricSpace::new(SpaceId(0), SpaceKind::Unit, span) -} diff --git a/crates/mehen-antlr/src/span.rs b/crates/mehen-antlr/src/span.rs deleted file mode 100644 index 55a72c2b..00000000 --- a/crates/mehen-antlr/src/span.rs +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Span and position conversion between the ANTLR runtime and mehen. -//! -//! `antlr-rust-runtime` exposes token positions in both its native Unicode -//! scalar index space (`Token::start`/`Token::stop`) and UTF-8 byte space -//! (`Token::start_byte`/`Token::stop_byte`). mehen uses UTF-8 byte offsets -//! throughout, so this module lifts ANTLR rule token ranges into byte/line -//! [`SourceSpan`](mehen_core::SourceSpan)s. -//! -//! Since the 0.11 runtime rewrite the concrete syntax tree is a flat arena -//! addressed by [`NodeId`](antlr4_runtime::NodeId) and traversed through -//! borrowing views. A rule's covered token range is read from a -//! [`RuleNodeView`], whose `start`/`stop` accessors return [`TokenView`]s -//! directly — the view already carries the shared [`TokenStore`], so no token -//! store has to be threaded through here. - -use antlr4_runtime::RuleNodeView; -use antlr4_runtime::token::{TOKEN_EOF, Token}; -use mehen_core::{LineIndex, SourceSpan, byte_offset_clamped}; - -/// Lift an ANTLR token span into a byte- and line-resolved [`SourceSpan`]. -/// -/// Generic over [`Token`] so it works with both the parser-owned -/// [`TokenView`](antlr4_runtime::TokenView) and any test double. -pub fn span_from_tokens( - start_token: &impl Token, - stop_token: &impl Token, - line_index: &LineIndex, - source_len: usize, -) -> SourceSpan { - // Byte offsets are optional since the 0.23 runtime: a token source that - // cannot resolve them reports `None`. mehen's streams always can, so this is - // defensive — an unresolvable start yields an empty span rather than a - // fabricated one, keeping every downstream metric span truthful. - let Some(start) = start_token.start_byte() else { - return SourceSpan::empty(); - }; - let start_byte = byte_offset_clamped(start); - let stop_byte = if stop_token.token_type() == TOKEN_EOF { - Some(source_len) - } else { - stop_token.stop_byte() - }; - let end_byte = stop_byte.map_or(start_byte, |stop| byte_offset_clamped(stop).max(start_byte)); - SourceSpan { - start_byte, - end_byte, - start_line: line_index.line_at(start_byte), - end_line: line_index.line_at(end_byte.saturating_sub(1).max(start_byte)), - } -} - -/// Lift a rule node's covered token range into a [`SourceSpan`]. -/// -/// Reads the rule's `start`/`stop` tokens and maps their runtime-provided byte -/// span to mehen's byte/line coordinates. A rule covering no tokens (an empty -/// optional rule) yields [`SourceSpan::empty`]. -pub fn ctx_span(rule: RuleNodeView<'_>, line_index: &LineIndex, source_len: usize) -> SourceSpan { - match rule.start() { - Some(start_tok) => { - let stop_tok = rule.stop().unwrap_or(start_tok); - span_from_tokens(&start_tok, &stop_tok, line_index, source_len) - } - None => SourceSpan::empty(), - } -} - -#[cfg(test)] -mod tests { - use super::*; - use antlr4_runtime::token::{TOKEN_EOF, TokenId}; - - /// Minimal [`Token`] test double. The 0.11 runtime rewrite made real - /// tokens live only inside the parser-owned `TokenStore` (no public - /// builder), but `span_from_tokens` is generic over [`Token`], so its - /// byte-math contract is exercised through a local impl instead. - #[derive(Debug)] - struct FakeToken { - token_type: i32, - start_byte: usize, - stop_byte: usize, - } - - impl Token for FakeToken { - fn token_id(&self) -> TokenId { - TokenId::try_from(0usize).expect("0 is a valid token id") - } - fn token_type(&self) -> i32 { - self.token_type - } - fn channel(&self) -> i32 { - 0 - } - fn start(&self) -> usize { - self.start_byte - } - fn stop(&self) -> usize { - self.stop_byte - } - fn line(&self) -> usize { - 1 - } - fn column(&self) -> usize { - 0 - } - fn text(&self) -> Option<&str> { - None - } - fn source_name(&self) -> &str { - "" - } - fn start_byte(&self) -> Option { - Some(self.start_byte) - } - fn stop_byte(&self) -> Option { - Some(self.stop_byte) - } - } - - #[test] - fn span_uses_runtime_byte_bounds() { - let src = "fun f() {}\nclass C\n"; - let li = LineIndex::new(src); - // A token covering `class C` on line 2 (bytes 11..=17, exclusive 18). - let start = FakeToken { - token_type: 1, - start_byte: 11, - stop_byte: 16, - }; - let stop = FakeToken { - token_type: 1, - start_byte: 17, - stop_byte: 18, - }; - let span = span_from_tokens(&start, &stop, &li, src.len()); - assert_eq!(span.start_byte, 11); - assert_eq!(span.end_byte, 18); - assert_eq!(span.start_line, 2); - } - - #[test] - fn eof_stop_uses_source_byte_len() { - let src = "é\nx"; - let li = LineIndex::new(src); - // `é` is 2 bytes; the EOF stop token forces the span end to the full - // source byte length rather than the EOF token's own byte offset. - let start = FakeToken { - token_type: 1, - start_byte: 0, - stop_byte: 2, - }; - let eof = FakeToken { - token_type: TOKEN_EOF, - start_byte: 0, - stop_byte: 0, - }; - - let span = span_from_tokens(&start, &eof, &li, src.len()); - - assert_eq!(span.start_byte, 0); - assert_eq!(span.end_byte, 4); - assert_eq!(span.end_line, 2); - } -} diff --git a/crates/mehen-c/Cargo.toml b/crates/mehen-c/Cargo.toml deleted file mode 100644 index da4d6d93..00000000 --- a/crates/mehen-c/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "mehen-c" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — C language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -mehen-tree-sitter = { workspace = true } -num = { workspace = true } -num-derive = { workspace = true } -# Required transitively by `num_derive::FromPrimitive` in `grammar.rs` -# — the derive expansion references `num_traits::FromPrimitive` by -# absolute path. Keep as a direct dependency and silence cargo-machete. -num-traits = { workspace = true } -smol_str = { workspace = true } -tree-sitter = { workspace = true } -# `mehen-c` is the sole consumer of tree-sitter-c after the legacy-engine -# C migration, so the workspace indirection earned nothing. Pin the -# version directly here. -tree-sitter-c = "=0.24.2" - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[package.metadata.cargo-machete] -ignored = ["num-traits"] - -[lints] -workspace = true diff --git a/crates/mehen-c/src/grammar.rs b/crates/mehen-c/src/grammar.rs deleted file mode 100644 index 6a09a1cf..00000000 --- a/crates/mehen-c/src/grammar.rs +++ /dev/null @@ -1,773 +0,0 @@ -// Code generated; DO NOT EDIT. - -#![allow(clippy::enum_variant_names)] -#![allow(clippy::upper_case_acronyms)] - -use num_derive::FromPrimitive; - -#[derive(Clone, Copy, Debug, PartialEq, Eq, FromPrimitive)] -pub(crate) enum C { - End = 0, - Identifier = 1, - HASHinclude = 2, - PreprocIncludeToken2 = 3, - HASHdefine = 4, - LPAREN = 5, - DOTDOTDOT = 6, - COMMA = 7, - RPAREN = 8, - HASHif = 9, - LF = 10, - HASHendif = 11, - HASHifdef = 12, - HASHifndef = 13, - HASHelse = 14, - HASHelif = 15, - HASHelifdef = 16, - HASHelifndef = 17, - PreprocArg = 18, - PreprocDirective = 19, - LPAREN2 = 20, - Defined = 21, - BANG = 22, - TILDE = 23, - DASH = 24, - PLUS = 25, - STAR = 26, - SLASH = 27, - PERCENT = 28, - PIPEPIPE = 29, - AMPAMP = 30, - PIPE = 31, - CARET = 32, - AMP = 33, - EQEQ = 34, - BANGEQ = 35, - GT = 36, - GTEQ = 37, - LTEQ = 38, - LT = 39, - LTLT = 40, - GTGT = 41, - SEMI = 42, - Extension = 43, - Typedef = 44, - Extern = 45, - Attribute2 = 46, - Attribute3 = 47, - COLONCOLON = 48, - LBRACKLBRACK = 49, - RBRACKRBRACK = 50, - Declspec = 51, - Based = 52, - Cdecl = 53, - Clrcall = 54, - Stdcall = 55, - Fastcall = 56, - Thiscall = 57, - Vectorcall = 58, - MsRestrictModifier = 59, - MsUnsignedPtrModifier = 60, - MsSignedPtrModifier = 61, - Unaligned = 62, - Unaligned2 = 63, - LBRACE = 64, - RBRACE = 65, - Signed = 66, - Unsigned = 67, - Long = 68, - Short = 69, - LBRACK = 70, - Static = 71, - RBRACK = 72, - EQ = 73, - Auto = 74, - Register = 75, - Inline = 76, - Inline2 = 77, - Inline3 = 78, - Forceinline = 79, - ThreadLocal = 80, - Thread = 81, - Const = 82, - Constexpr = 83, - Volatile = 84, - Restrict = 85, - Restrict2 = 86, - Atomic = 87, - Noreturn = 88, - Noreturn2 = 89, - Nonnull = 90, - Alignas = 91, - Alignas2 = 92, - PrimitiveType = 93, - Enum = 94, - COLON = 95, - Struct = 96, - Union = 97, - If = 98, - Else = 99, - Switch = 100, - Case = 101, - Default = 102, - While = 103, - Do = 104, - For = 105, - Return = 106, - Break = 107, - Continue = 108, - Goto = 109, - Try = 110, - Except = 111, - Finally = 112, - Leave = 113, - QMARK = 114, - STAREQ = 115, - SLASHEQ = 116, - PERCENTEQ = 117, - PLUSEQ = 118, - DASHEQ = 119, - LTLTEQ = 120, - GTGTEQ = 121, - AMPEQ = 122, - CARETEQ = 123, - PIPEEQ = 124, - DASHDASH = 125, - PLUSPLUS = 126, - Sizeof = 127, - Alignof = 128, - Alignof2 = 129, - Alignof3 = 130, - Alignof4 = 131, - Alignof5 = 132, - Offsetof = 133, - Generic = 134, - Asm = 135, - Asm2 = 136, - Asm3 = 137, - Volatile2 = 138, - DOT = 139, - DASHGT = 140, - NumberLiteral = 141, - LSQUOTE = 142, - USQUOTE = 143, - USQUOTE2 = 144, - U8SQUOTE = 145, - SQUOTE = 146, - Character = 147, - LDQUOTE = 148, - UDQUOTE = 149, - UDQUOTE2 = 150, - U8DQUOTE = 151, - DQUOTE = 152, - StringContent = 153, - EscapeSequence = 154, - SystemLibString = 155, - True = 156, - False = 157, - NULL = 158, - Nullptr = 159, - Comment = 160, - TranslationUnit = 161, - TopLevelItem = 162, - BlockItem = 163, - PreprocInclude = 164, - PreprocDef = 165, - PreprocFunctionDef = 166, - PreprocParams = 167, - PreprocCall = 168, - PreprocIf = 169, - PreprocIfdef = 170, - PreprocElse = 171, - PreprocElif = 172, - PreprocElifdef = 173, - PreprocIf2 = 174, - PreprocIfdef2 = 175, - PreprocElse2 = 176, - PreprocElif2 = 177, - PreprocElifdef2 = 178, - PreprocIf3 = 179, - PreprocIfdef3 = 180, - PreprocElse3 = 181, - PreprocElif3 = 182, - PreprocElifdef3 = 183, - PreprocIf4 = 184, - PreprocIfdef4 = 185, - PreprocElse4 = 186, - PreprocElif4 = 187, - PreprocElifdef4 = 188, - PreprocExpression = 189, - ParenthesizedExpression = 190, - PreprocDefined = 191, - UnaryExpression = 192, - CallExpression = 193, - ArgumentList = 194, - BinaryExpression = 195, - FunctionDefinition = 196, - FunctionDefinition2 = 197, - Declaration = 198, - TypeDefinition = 199, - TypeDefinitionType = 200, - TypeDefinitionDeclarators = 201, - DeclarationModifiers = 202, - DeclarationSpecifiers = 203, - LinkageSpecification = 204, - AttributeSpecifier = 205, - Attribute = 206, - AttributeDeclaration = 207, - MsDeclspecModifier = 208, - MsBasedModifier = 209, - MsCallModifier = 210, - MsUnalignedPtrModifier = 211, - MsPointerModifier = 212, - DeclarationList = 213, - Declarator = 214, - DeclarationDeclarator = 215, - FieldDeclarator = 216, - TypeDeclarator = 217, - AbstractDeclarator = 218, - ParenthesizedDeclarator = 219, - ParenthesizedDeclarator2 = 220, - ParenthesizedDeclarator3 = 221, - AbstractParenthesizedDeclarator = 222, - AttributedDeclarator = 223, - AttributedDeclarator2 = 224, - AttributedDeclarator3 = 225, - PointerDeclarator = 226, - PointerDeclarator2 = 227, - PointerDeclarator3 = 228, - AbstractPointerDeclarator = 229, - FunctionDeclarator = 230, - FunctionDeclarator2 = 231, - FunctionDeclarator3 = 232, - FunctionDeclarator4 = 233, - AbstractFunctionDeclarator = 234, - FunctionDeclarator5 = 235, - ArrayDeclarator = 236, - ArrayDeclarator2 = 237, - ArrayDeclarator3 = 238, - AbstractArrayDeclarator = 239, - InitDeclarator = 240, - CompoundStatement = 241, - StorageClassSpecifier = 242, - TypeQualifier = 243, - AlignasQualifier = 244, - TypeSpecifier = 245, - SizedTypeSpecifier = 246, - EnumSpecifier = 247, - EnumeratorList = 248, - StructSpecifier = 249, - UnionSpecifier = 250, - FieldDeclarationList = 251, - FieldDeclarationListItem = 252, - FieldDeclaration = 253, - FieldDeclarationDeclarator = 254, - BitfieldClause = 255, - Enumerator = 256, - VariadicParameter = 257, - ParameterList = 258, - ParameterList2 = 259, - ParameterDeclaration = 260, - AttributedStatement = 261, - Statement = 262, - TopLevelStatement = 263, - LabeledStatement = 264, - ExpressionStatement = 265, - ExpressionStatement2 = 266, - IfStatement = 267, - ElseClause = 268, - SwitchStatement = 269, - CaseStatement = 270, - WhileStatement = 271, - DoStatement = 272, - ForStatement = 273, - ForStatementBody = 274, - ReturnStatement = 275, - BreakStatement = 276, - ContinueStatement = 277, - GotoStatement = 278, - SehTryStatement = 279, - SehExceptClause = 280, - SehFinallyClause = 281, - SehLeaveStatement = 282, - Expression = 283, - String = 284, - CommaExpression = 285, - ConditionalExpression = 286, - AssignmentExpression = 287, - PointerExpression = 288, - UnaryExpression2 = 289, - BinaryExpression2 = 290, - UpdateExpression = 291, - CastExpression = 292, - TypeDescriptor = 293, - SizeofExpression = 294, - AlignofExpression = 295, - OffsetofExpression = 296, - GenericExpression = 297, - SubscriptExpression = 298, - CallExpression2 = 299, - GnuAsmExpression = 300, - GnuAsmQualifier = 301, - GnuAsmOutputOperandList = 302, - GnuAsmOutputOperand = 303, - GnuAsmInputOperandList = 304, - GnuAsmInputOperand = 305, - GnuAsmClobberList = 306, - GnuAsmGotoList = 307, - ExtensionExpression = 308, - ArgumentList2 = 309, - FieldExpression = 310, - CompoundLiteralExpression = 311, - ParenthesizedExpression2 = 312, - InitializerList = 313, - InitializerPair = 314, - SubscriptDesignator = 315, - SubscriptRangeDesignator = 316, - FieldDesignator = 317, - CharLiteral = 318, - ConcatenatedString = 319, - StringLiteral = 320, - Null = 321, - EmptyDeclaration = 322, - MacroTypeSpecifier = 323, - TranslationUnitRepeat1 = 324, - PreprocParamsRepeat1 = 325, - PreprocIfRepeat1 = 326, - PreprocIfInFieldDeclarationListRepeat1 = 327, - PreprocIfInEnumeratorListRepeat1 = 328, - PreprocIfInEnumeratorListNoCommaRepeat1 = 329, - PreprocArgumentListRepeat1 = 330, - OldStyleFunctionDefinitionRepeat1 = 331, - DeclarationRepeat1 = 332, - TypeDefinitionRepeat1 = 333, - TypeDefinitionTypeRepeat1 = 334, - TypeDefinitionDeclaratorsRepeat1 = 335, - DeclarationSpecifiersRepeat1 = 336, - AttributeDeclarationRepeat1 = 337, - AttributedDeclaratorRepeat1 = 338, - PointerDeclaratorRepeat1 = 339, - FunctionDeclaratorRepeat1 = 340, - ArrayDeclaratorRepeat1 = 341, - SizedTypeSpecifierRepeat1 = 342, - EnumeratorListRepeat1 = 343, - FieldDeclarationDeclaratorRepeat1 = 344, - ParameterListRepeat1 = 345, - OldStyleParameterListRepeat1 = 346, - CaseStatementRepeat1 = 347, - GenericExpressionRepeat1 = 348, - GnuAsmExpressionRepeat1 = 349, - GnuAsmOutputOperandListRepeat1 = 350, - GnuAsmInputOperandListRepeat1 = 351, - GnuAsmClobberListRepeat1 = 352, - GnuAsmGotoListRepeat1 = 353, - ArgumentListRepeat1 = 354, - InitializerListRepeat1 = 355, - InitializerPairRepeat1 = 356, - CharLiteralRepeat1 = 357, - ConcatenatedStringRepeat1 = 358, - StringLiteralRepeat1 = 359, - FieldIdentifier = 360, - StatementIdentifier = 361, - TypeIdentifier = 362, - Error = 363, -} - -impl From for &'static str { - #[inline(always)] - fn from(tok: C) -> Self { - match tok { - C::End => "end", - C::Identifier => "identifier", - C::HASHinclude => "#include", - C::PreprocIncludeToken2 => "preproc_include_token2", - C::HASHdefine => "#define", - C::LPAREN => "(", - C::DOTDOTDOT => "...", - C::COMMA => ",", - C::RPAREN => ")", - C::HASHif => "#if", - C::LF => "\n", - C::HASHendif => "#endif", - C::HASHifdef => "#ifdef", - C::HASHifndef => "#ifndef", - C::HASHelse => "#else", - C::HASHelif => "#elif", - C::HASHelifdef => "#elifdef", - C::HASHelifndef => "#elifndef", - C::PreprocArg => "preproc_arg", - C::PreprocDirective => "preproc_directive", - C::LPAREN2 => "(", - C::Defined => "defined", - C::BANG => "!", - C::TILDE => "~", - C::DASH => "-", - C::PLUS => "+", - C::STAR => "*", - C::SLASH => "/", - C::PERCENT => "%", - C::PIPEPIPE => "||", - C::AMPAMP => "&&", - C::PIPE => "|", - C::CARET => "^", - C::AMP => "&", - C::EQEQ => "==", - C::BANGEQ => "!=", - C::GT => ">", - C::GTEQ => ">=", - C::LTEQ => "<=", - C::LT => "<", - C::LTLT => "<<", - C::GTGT => ">>", - C::SEMI => ";", - C::Extension => "__extension__", - C::Typedef => "typedef", - C::Extern => "extern", - C::Attribute2 => "__attribute__", - C::Attribute3 => "__attribute", - C::COLONCOLON => "::", - C::LBRACKLBRACK => "[[", - C::RBRACKRBRACK => "]]", - C::Declspec => "__declspec", - C::Based => "__based", - C::Cdecl => "__cdecl", - C::Clrcall => "__clrcall", - C::Stdcall => "__stdcall", - C::Fastcall => "__fastcall", - C::Thiscall => "__thiscall", - C::Vectorcall => "__vectorcall", - C::MsRestrictModifier => "ms_restrict_modifier", - C::MsUnsignedPtrModifier => "ms_unsigned_ptr_modifier", - C::MsSignedPtrModifier => "ms_signed_ptr_modifier", - C::Unaligned => "_unaligned", - C::Unaligned2 => "__unaligned", - C::LBRACE => "{", - C::RBRACE => "}", - C::Signed => "signed", - C::Unsigned => "unsigned", - C::Long => "long", - C::Short => "short", - C::LBRACK => "[", - C::Static => "static", - C::RBRACK => "]", - C::EQ => "=", - C::Auto => "auto", - C::Register => "register", - C::Inline => "inline", - C::Inline2 => "__inline", - C::Inline3 => "__inline__", - C::Forceinline => "__forceinline", - C::ThreadLocal => "thread_local", - C::Thread => "__thread", - C::Const => "const", - C::Constexpr => "constexpr", - C::Volatile => "volatile", - C::Restrict => "restrict", - C::Restrict2 => "__restrict__", - C::Atomic => "_Atomic", - C::Noreturn => "_Noreturn", - C::Noreturn2 => "noreturn", - C::Nonnull => "_Nonnull", - C::Alignas => "alignas", - C::Alignas2 => "_Alignas", - C::PrimitiveType => "primitive_type", - C::Enum => "enum", - C::COLON => ":", - C::Struct => "struct", - C::Union => "union", - C::If => "if", - C::Else => "else", - C::Switch => "switch", - C::Case => "case", - C::Default => "default", - C::While => "while", - C::Do => "do", - C::For => "for", - C::Return => "return", - C::Break => "break", - C::Continue => "continue", - C::Goto => "goto", - C::Try => "__try", - C::Except => "__except", - C::Finally => "__finally", - C::Leave => "__leave", - C::QMARK => "?", - C::STAREQ => "*=", - C::SLASHEQ => "/=", - C::PERCENTEQ => "%=", - C::PLUSEQ => "+=", - C::DASHEQ => "-=", - C::LTLTEQ => "<<=", - C::GTGTEQ => ">>=", - C::AMPEQ => "&=", - C::CARETEQ => "^=", - C::PIPEEQ => "|=", - C::DASHDASH => "--", - C::PLUSPLUS => "++", - C::Sizeof => "sizeof", - C::Alignof => "__alignof__", - C::Alignof2 => "__alignof", - C::Alignof3 => "_alignof", - C::Alignof4 => "alignof", - C::Alignof5 => "_Alignof", - C::Offsetof => "offsetof", - C::Generic => "_Generic", - C::Asm => "asm", - C::Asm2 => "__asm__", - C::Asm3 => "__asm", - C::Volatile2 => "__volatile__", - C::DOT => ".", - C::DASHGT => "->", - C::NumberLiteral => "number_literal", - C::LSQUOTE => "L'", - C::USQUOTE => "u'", - C::USQUOTE2 => "U'", - C::U8SQUOTE => "u8'", - C::SQUOTE => "'", - C::Character => "character", - C::LDQUOTE => "L\"", - C::UDQUOTE => "u\"", - C::UDQUOTE2 => "U\"", - C::U8DQUOTE => "u8\"", - C::DQUOTE => "\"", - C::StringContent => "string_content", - C::EscapeSequence => "escape_sequence", - C::SystemLibString => "system_lib_string", - C::True => "true", - C::False => "false", - C::NULL => "NULL", - C::Nullptr => "nullptr", - C::Comment => "comment", - C::TranslationUnit => "translation_unit", - C::TopLevelItem => "_top_level_item", - C::BlockItem => "_block_item", - C::PreprocInclude => "preproc_include", - C::PreprocDef => "preproc_def", - C::PreprocFunctionDef => "preproc_function_def", - C::PreprocParams => "preproc_params", - C::PreprocCall => "preproc_call", - C::PreprocIf => "preproc_if", - C::PreprocIfdef => "preproc_ifdef", - C::PreprocElse => "preproc_else", - C::PreprocElif => "preproc_elif", - C::PreprocElifdef => "preproc_elifdef", - C::PreprocIf2 => "preproc_if", - C::PreprocIfdef2 => "preproc_ifdef", - C::PreprocElse2 => "preproc_else", - C::PreprocElif2 => "preproc_elif", - C::PreprocElifdef2 => "preproc_elifdef", - C::PreprocIf3 => "preproc_if", - C::PreprocIfdef3 => "preproc_ifdef", - C::PreprocElse3 => "preproc_else", - C::PreprocElif3 => "preproc_elif", - C::PreprocElifdef3 => "preproc_elifdef", - C::PreprocIf4 => "preproc_if", - C::PreprocIfdef4 => "preproc_ifdef", - C::PreprocElse4 => "preproc_else", - C::PreprocElif4 => "preproc_elif", - C::PreprocElifdef4 => "preproc_elifdef", - C::PreprocExpression => "_preproc_expression", - C::ParenthesizedExpression => "parenthesized_expression", - C::PreprocDefined => "preproc_defined", - C::UnaryExpression => "unary_expression", - C::CallExpression => "call_expression", - C::ArgumentList => "argument_list", - C::BinaryExpression => "binary_expression", - C::FunctionDefinition => "function_definition", - C::FunctionDefinition2 => "function_definition", - C::Declaration => "declaration", - C::TypeDefinition => "type_definition", - C::TypeDefinitionType => "_type_definition_type", - C::TypeDefinitionDeclarators => "_type_definition_declarators", - C::DeclarationModifiers => "_declaration_modifiers", - C::DeclarationSpecifiers => "_declaration_specifiers", - C::LinkageSpecification => "linkage_specification", - C::AttributeSpecifier => "attribute_specifier", - C::Attribute => "attribute", - C::AttributeDeclaration => "attribute_declaration", - C::MsDeclspecModifier => "ms_declspec_modifier", - C::MsBasedModifier => "ms_based_modifier", - C::MsCallModifier => "ms_call_modifier", - C::MsUnalignedPtrModifier => "ms_unaligned_ptr_modifier", - C::MsPointerModifier => "ms_pointer_modifier", - C::DeclarationList => "declaration_list", - C::Declarator => "_declarator", - C::DeclarationDeclarator => "_declaration_declarator", - C::FieldDeclarator => "_field_declarator", - C::TypeDeclarator => "_type_declarator", - C::AbstractDeclarator => "_abstract_declarator", - C::ParenthesizedDeclarator => "parenthesized_declarator", - C::ParenthesizedDeclarator2 => "parenthesized_declarator", - C::ParenthesizedDeclarator3 => "parenthesized_declarator", - C::AbstractParenthesizedDeclarator => "abstract_parenthesized_declarator", - C::AttributedDeclarator => "attributed_declarator", - C::AttributedDeclarator2 => "attributed_declarator", - C::AttributedDeclarator3 => "attributed_declarator", - C::PointerDeclarator => "pointer_declarator", - C::PointerDeclarator2 => "pointer_declarator", - C::PointerDeclarator3 => "pointer_declarator", - C::AbstractPointerDeclarator => "abstract_pointer_declarator", - C::FunctionDeclarator => "function_declarator", - C::FunctionDeclarator2 => "function_declarator", - C::FunctionDeclarator3 => "function_declarator", - C::FunctionDeclarator4 => "function_declarator", - C::AbstractFunctionDeclarator => "abstract_function_declarator", - C::FunctionDeclarator5 => "function_declarator", - C::ArrayDeclarator => "array_declarator", - C::ArrayDeclarator2 => "array_declarator", - C::ArrayDeclarator3 => "array_declarator", - C::AbstractArrayDeclarator => "abstract_array_declarator", - C::InitDeclarator => "init_declarator", - C::CompoundStatement => "compound_statement", - C::StorageClassSpecifier => "storage_class_specifier", - C::TypeQualifier => "type_qualifier", - C::AlignasQualifier => "alignas_qualifier", - C::TypeSpecifier => "type_specifier", - C::SizedTypeSpecifier => "sized_type_specifier", - C::EnumSpecifier => "enum_specifier", - C::EnumeratorList => "enumerator_list", - C::StructSpecifier => "struct_specifier", - C::UnionSpecifier => "union_specifier", - C::FieldDeclarationList => "field_declaration_list", - C::FieldDeclarationListItem => "_field_declaration_list_item", - C::FieldDeclaration => "field_declaration", - C::FieldDeclarationDeclarator => "_field_declaration_declarator", - C::BitfieldClause => "bitfield_clause", - C::Enumerator => "enumerator", - C::VariadicParameter => "variadic_parameter", - C::ParameterList => "parameter_list", - C::ParameterList2 => "parameter_list", - C::ParameterDeclaration => "parameter_declaration", - C::AttributedStatement => "attributed_statement", - C::Statement => "statement", - C::TopLevelStatement => "_top_level_statement", - C::LabeledStatement => "labeled_statement", - C::ExpressionStatement => "expression_statement", - C::ExpressionStatement2 => "expression_statement", - C::IfStatement => "if_statement", - C::ElseClause => "else_clause", - C::SwitchStatement => "switch_statement", - C::CaseStatement => "case_statement", - C::WhileStatement => "while_statement", - C::DoStatement => "do_statement", - C::ForStatement => "for_statement", - C::ForStatementBody => "_for_statement_body", - C::ReturnStatement => "return_statement", - C::BreakStatement => "break_statement", - C::ContinueStatement => "continue_statement", - C::GotoStatement => "goto_statement", - C::SehTryStatement => "seh_try_statement", - C::SehExceptClause => "seh_except_clause", - C::SehFinallyClause => "seh_finally_clause", - C::SehLeaveStatement => "seh_leave_statement", - C::Expression => "expression", - C::String => "_string", - C::CommaExpression => "comma_expression", - C::ConditionalExpression => "conditional_expression", - C::AssignmentExpression => "assignment_expression", - C::PointerExpression => "pointer_expression", - C::UnaryExpression2 => "unary_expression", - C::BinaryExpression2 => "binary_expression", - C::UpdateExpression => "update_expression", - C::CastExpression => "cast_expression", - C::TypeDescriptor => "type_descriptor", - C::SizeofExpression => "sizeof_expression", - C::AlignofExpression => "alignof_expression", - C::OffsetofExpression => "offsetof_expression", - C::GenericExpression => "generic_expression", - C::SubscriptExpression => "subscript_expression", - C::CallExpression2 => "call_expression", - C::GnuAsmExpression => "gnu_asm_expression", - C::GnuAsmQualifier => "gnu_asm_qualifier", - C::GnuAsmOutputOperandList => "gnu_asm_output_operand_list", - C::GnuAsmOutputOperand => "gnu_asm_output_operand", - C::GnuAsmInputOperandList => "gnu_asm_input_operand_list", - C::GnuAsmInputOperand => "gnu_asm_input_operand", - C::GnuAsmClobberList => "gnu_asm_clobber_list", - C::GnuAsmGotoList => "gnu_asm_goto_list", - C::ExtensionExpression => "extension_expression", - C::ArgumentList2 => "argument_list", - C::FieldExpression => "field_expression", - C::CompoundLiteralExpression => "compound_literal_expression", - C::ParenthesizedExpression2 => "parenthesized_expression", - C::InitializerList => "initializer_list", - C::InitializerPair => "initializer_pair", - C::SubscriptDesignator => "subscript_designator", - C::SubscriptRangeDesignator => "subscript_range_designator", - C::FieldDesignator => "field_designator", - C::CharLiteral => "char_literal", - C::ConcatenatedString => "concatenated_string", - C::StringLiteral => "string_literal", - C::Null => "null", - C::EmptyDeclaration => "_empty_declaration", - C::MacroTypeSpecifier => "macro_type_specifier", - C::TranslationUnitRepeat1 => "translation_unit_repeat1", - C::PreprocParamsRepeat1 => "preproc_params_repeat1", - C::PreprocIfRepeat1 => "preproc_if_repeat1", - C::PreprocIfInFieldDeclarationListRepeat1 => { - "preproc_if_in_field_declaration_list_repeat1" - } - C::PreprocIfInEnumeratorListRepeat1 => "preproc_if_in_enumerator_list_repeat1", - C::PreprocIfInEnumeratorListNoCommaRepeat1 => { - "preproc_if_in_enumerator_list_no_comma_repeat1" - } - C::PreprocArgumentListRepeat1 => "preproc_argument_list_repeat1", - C::OldStyleFunctionDefinitionRepeat1 => "_old_style_function_definition_repeat1", - C::DeclarationRepeat1 => "declaration_repeat1", - C::TypeDefinitionRepeat1 => "type_definition_repeat1", - C::TypeDefinitionTypeRepeat1 => "_type_definition_type_repeat1", - C::TypeDefinitionDeclaratorsRepeat1 => "_type_definition_declarators_repeat1", - C::DeclarationSpecifiersRepeat1 => "_declaration_specifiers_repeat1", - C::AttributeDeclarationRepeat1 => "attribute_declaration_repeat1", - C::AttributedDeclaratorRepeat1 => "attributed_declarator_repeat1", - C::PointerDeclaratorRepeat1 => "pointer_declarator_repeat1", - C::FunctionDeclaratorRepeat1 => "function_declarator_repeat1", - C::ArrayDeclaratorRepeat1 => "array_declarator_repeat1", - C::SizedTypeSpecifierRepeat1 => "sized_type_specifier_repeat1", - C::EnumeratorListRepeat1 => "enumerator_list_repeat1", - C::FieldDeclarationDeclaratorRepeat1 => "_field_declaration_declarator_repeat1", - C::ParameterListRepeat1 => "parameter_list_repeat1", - C::OldStyleParameterListRepeat1 => "_old_style_parameter_list_repeat1", - C::CaseStatementRepeat1 => "case_statement_repeat1", - C::GenericExpressionRepeat1 => "generic_expression_repeat1", - C::GnuAsmExpressionRepeat1 => "gnu_asm_expression_repeat1", - C::GnuAsmOutputOperandListRepeat1 => "gnu_asm_output_operand_list_repeat1", - C::GnuAsmInputOperandListRepeat1 => "gnu_asm_input_operand_list_repeat1", - C::GnuAsmClobberListRepeat1 => "gnu_asm_clobber_list_repeat1", - C::GnuAsmGotoListRepeat1 => "gnu_asm_goto_list_repeat1", - C::ArgumentListRepeat1 => "argument_list_repeat1", - C::InitializerListRepeat1 => "initializer_list_repeat1", - C::InitializerPairRepeat1 => "initializer_pair_repeat1", - C::CharLiteralRepeat1 => "char_literal_repeat1", - C::ConcatenatedStringRepeat1 => "concatenated_string_repeat1", - C::StringLiteralRepeat1 => "string_literal_repeat1", - C::FieldIdentifier => "field_identifier", - C::StatementIdentifier => "statement_identifier", - C::TypeIdentifier => "type_identifier", - C::Error => "ERROR", - } - } -} - -impl From for C { - #[inline(always)] - fn from(x: u16) -> Self { - num::FromPrimitive::from_u16(x).unwrap_or(Self::Error) - } -} - -// C == u16 -impl PartialEq for C { - #[inline(always)] - fn eq(&self, x: &u16) -> bool { - *self == Into::::into(*x) - } -} - -// u16 == C -impl PartialEq for u16 { - #[inline(always)] - fn eq(&self, x: &C) -> bool { - *x == *self - } -} diff --git a/crates/mehen-c/src/lib.rs b/crates/mehen-c/src/lib.rs deleted file mode 100644 index ed21bf9f..00000000 --- a/crates/mehen-c/src/lib.rs +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-c` — C language analyzer. -//! -//! Drives a C-specific tree-sitter walker (`walker::walk_program`) that -//! mirrors every legacy `legacy::metrics::*::compute for CCode` arm -//! byte-identically. See `walker.rs` for the per-metric coverage notes. - -#![forbid(unsafe_code)] - -mod grammar; -mod walker; - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, ParseDiagnostic, - Result, SourceFile, SourceSpan, byte_offset_clamped, -}; -use mehen_tree_sitter::{MetricEvidence, TreeSitterParser, collect_recovered_errors, empty_space}; - -/// Tree-sitter `Language` accessor for `xtask tree-sitter generate`. -/// -/// Exposed so the kind-enum generator reaches the grammar through this -/// crate instead of pinning `tree-sitter-c` itself, which kept xtask's -/// pin and the analyzer's pin in lockstep by hand. With this accessor, -/// the analyzer's pin is the single source of truth. -#[doc(hidden)] -pub fn __grammar_language() -> tree_sitter::Language { - tree_sitter_c::LANGUAGE.into() -} - -pub struct CAnalyzer; - -impl CAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for CAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for CAnalyzer { - fn language(&self) -> Language { - Language::C - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::TreeSitter - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - let parser = match TreeSitterParser::new( - tree_sitter_c::LANGUAGE.into(), - source.text.clone().into_bytes(), - ) { - Ok(p) => p, - Err(e) => { - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: source.line_index.line_count(), - }; - return Ok(LanguageAnalysis { - language: Language::C, - backend: AnalysisBackend::TreeSitter, - diagnostics: vec![ParseDiagnostic::fatal( - "c.parse_error", - format!("tree-sitter-c failed: {e}"), - )], - root: empty_space(span), - contributions: Vec::new(), - }); - } - }; - - let mut evidence = MetricEvidence::new("c", config.emit_contributions); - let root = walker::walk_program( - parser.root(), - parser.source(), - &source.line_index, - &mut evidence, - ); - // Tree-sitter recovers from syntax errors by inserting ERROR / - // missing nodes; surface them as `error` diagnostics so the - // metric output can't masquerade as clean (plan §9.3). - let diagnostics = collect_recovered_errors(parser.root(), "c.syntax_error", 16); - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::C, - backend: AnalysisBackend::TreeSitter, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} diff --git a/crates/mehen-c/src/walker.rs b/crates/mehen-c/src/walker.rs deleted file mode 100644 index d91ad488..00000000 --- a/crates/mehen-c/src/walker.rs +++ /dev/null @@ -1,618 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Tree-sitter-c walker producing per-space metric output that matches -//! the pre-1.0 `legacy::metrics::*::compute for CCode` arms exactly. -//! -//! The walker plugs language-specific classification into the shared -//! [`mehen_tree_sitter::WalkerHooks`] scaffold so the visit recursion, -//! cognitive context save/restore, kinds-stack bookkeeping, and unit -//! finalize stay byte-identical with the Go and Kotlin walkers. -//! -//! Metric coverage: -//! - **Cyclomatic** (legacy `cyclomatic.rs:112-135`): one decision per -//! `if_statement | case_statement | for_statement | while_statement | -//! do_statement | conditional_expression | && | ||`. `switch` itself -//! is not a decision (`case` arms are); `default` is fallthrough. -//! - **Cognitive** (legacy `cognitive.rs:234-294`): -//! * Increase nesting on `if_statement` (skipping the inner `if` of an -//! `else if` whose parent is `else_clause`), `for_statement | -//! while_statement | do_statement | switch_statement | -//! conditional_expression`. `function_definition` / -//! `function_definition2` reset nesting and bump function depth. -//! * `else_clause`: flat `+1` plus `boolean_seq.reset()`. -//! * `expression_statement | expression_statement2 | return_statement -//! | declaration`: `boolean_seq.reset()`. -//! * `binary_expression | binary_expression2`: drive the -//! `BoolSequence` collapser per `&&`/`||` operator child. -//! * No closures or lambdas in C. -//! - **ABC** (legacy `abc.rs:233-281`): -//! * Assignments: `assignment_expression`, `init_declarator` with an -//! `=` direct child, `update_expression`. -//! * Branches: every `call_expression | call_expression2`. -//! * Conditions: `if_statement | else_clause | case_statement | -//! for_statement | while_statement | do_statement | -//! conditional_expression | == | != | < | <= | > | >= | && | || | -//! !`. -//! - **NExit** (legacy `exit.rs:117-128`): `return_statement` only. -//! `break`/`continue`/`goto` are intra-function flow. -//! - **NArgs** (legacy `nargs.rs:230-275`, `compute_c_args`): walk -//! `child_by_field_name("declarator")` inward through -//! `function_declarator` chains until a `parameter_list` is found, -//! filter `parameter_declaration` children, exclude `variadic_parameter` -//! (`...`), and apply the `(void)` rule (lone parameter whose source -//! text equals `void` → 0 args). -//! - **NOM** (legacy `nom.rs:180-189`): every `function_definition` / -//! `function_definition2` opens a function space. C has no closures. -//! - **LOC** (legacy `loc.rs:567-613`): PLOC default arm, -//! LLOC for the 36-variant statement / preprocessor-container set, -//! CLOC for `comment` nodes via `observe_comment`. -//! - **Halstead** (legacy `getter.rs::get_op_type for CCode`): operators -//! for ~70 keyword/punctuation kinds, operands for the 14 identifier- -//! shaped + literal kinds. Operands dedup by text only (kind = -//! `"Operand"`); operators dedup by kind. Same convention as -//! `mehen-go/src/walker.rs`. -//! - **NPA / NPM / WMC** (legacy `npa.rs:202-205`, `npm.rs:203-206`, -//! `wmc.rs:142-145`): C is excluded from class-aware metrics; all -//! three are intentionally no-ops here. -//! - **MI**: derived in `mehen_metrics::state::apply_state_to` from -//! loc/cyclomatic/halstead — no C-specific logic. - -use mehen_core::{LineIndex, MetricSpace, SpaceKind}; -use mehen_metrics::{HalsteadOperand, HalsteadOperator, MetricEvidence, State}; -use mehen_tree_sitter::{OpenSpaceRequest, WalkerCtx, WalkerHooks, node_span, run, text_of}; -use smol_str::SmolStr; -use tree_sitter::Node; - -use crate::grammar::C; - -/// Drive the walker over the parsed C tree and return the populated -/// `MetricSpace`. Plugs C classification into the shared -/// [`mehen_tree_sitter::run`] scaffold. Contribution evidence is -/// recorded into the caller-owned `evidence` sink (plan §5.4). -pub(crate) fn walk_program( - root: Node<'_>, - source: &[u8], - line_index: &LineIndex, - evidence: &mut MetricEvidence, -) -> MetricSpace { - let mut hooks = CHooks; - run(&mut hooks, root, source, line_index, evidence) -} - -struct CHooks; - -impl WalkerHooks for CHooks { - fn open_space(&mut self, ctx: &mut WalkerCtx<'_>, node: &Node<'_>) -> Option { - match C::from(node.kind_id()) { - C::FunctionDefinition | C::FunctionDefinition2 => { - let name = function_name(node, ctx.source).map(|s| s.to_string()); - let span = node_span(node, ctx.line_index); - let mut state = State::new(); - state.loc.set_span( - node.start_position().row as u32, - node.end_position().row as u32, - false, - ); - state.nom.record_function(); - let argc = count_c_args(node, ctx.source); - state.nargs.record_function_args(argc); - if ctx.evidence.is_enabled() { - ctx.evidence.function(span, node.kind()); - ctx.evidence.function_args(span, argc, node.kind()); - } - Some(OpenSpaceRequest { - kind: SpaceKind::Function, - name, - span, - state, - }) - } - _ => None, - } - } - - fn on_space_enter(&mut self, ctx: &mut WalkerCtx<'_>, kind: SpaceKind) { - if matches!(kind, SpaceKind::Function) { - // Legacy `Cognitive for CCode`'s `FunctionDefinition | - // FunctionDefinition2` arm: reset nesting; bump function - // depth when nested. C nested-function syntax is GCC-only - // and rare, but the depth bump is preserved for parity. - let nested_inside_function = ctx - .ancestor_kinds() - .any(|k| matches!(k, SpaceKind::Function)); - ctx.cognitive.nesting = 0; - if nested_inside_function { - ctx.cognitive.depth = ctx.cognitive.depth.saturating_add(1); - } - } - } - - fn before_close(&mut self, state: &mut State, closed_kind: SpaceKind, _parent: SpaceKind) { - if matches!(closed_kind, SpaceKind::Function) { - // Mirrors the legacy `wmc::Stats` close path. WMC is - // class-aware; C has no classes, so this value is never - // published — but the bookkeeping is kept so per-space - // walker shape stays uniform with Go/Kotlin. - state.wmc.set_cyclomatic(state.cyclomatic.cyclomatic + 1); - } - } - - fn classify(&mut self, ctx: &mut WalkerCtx<'_>, node: &Node<'_>) { - let kind = C::from(node.kind_id()); - - // Cyclomatic — legacy `Cyclomatic for CCode`. - if matches!( - kind, - C::IfStatement - | C::CaseStatement - | C::ForStatement - | C::WhileStatement - | C::DoStatement - | C::ConditionalExpression - | C::AMPAMP - | C::PIPEPIPE - ) { - ctx.current().cyclomatic.record_decision(); - ctx.record_evidence(node, |e, s| e.decision(s, node.kind())); - } - - classify_cognitive(ctx, node, kind); - classify_abc(ctx, node, kind); - - // NExit — legacy `Exit for CCode`. Only `return_statement`; - // break/continue/goto are intra-function flow. - if matches!(kind, C::ReturnStatement) { - ctx.current().nexit.record_exit(); - ctx.record_evidence(node, |e, s| e.exit(s, node.kind())); - } - - classify_loc(ctx, node, kind); - classify_halstead(ctx, node, kind); - } -} - -fn classify_cognitive(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: C) { - match kind { - // Outer `if`. `is_else_if` checks parent == ElseClause: when - // true, the structural +1 is paid by the surrounding `else - // clause` arm and only the boolean-seq reset stays here - // (defense-in-depth duplicate of the ElseClause reset). - C::IfStatement if !is_else_if(node) => { - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.increase_nesting(effective); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(node, |e, s| e.cognitive(s, delta, node.kind())); - } - C::IfStatement => { - ctx.current().cognitive.boolean_seq.reset(); - } - C::ForStatement - | C::WhileStatement - | C::DoStatement - | C::SwitchStatement - | C::ConditionalExpression => { - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.increase_nesting(effective); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(node, |e, s| e.cognitive(s, delta, node.kind())); - } - C::ElseClause => { - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.increment_by_one(); - ctx.current().cognitive.boolean_seq.reset(); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(node, |e, s| e.cognitive(s, delta, node.kind())); - } - C::ExpressionStatement | C::ExpressionStatement2 | C::ReturnStatement | C::Declaration => { - ctx.current().cognitive.boolean_seq.reset(); - } - C::BinaryExpression | C::BinaryExpression2 => { - // Legacy `compute_booleans::(node, &AMP, &PIPEPIPE)`: - // walk the children and feed each `&&`/`||` operator into - // the sequence collapser. Evidence spans point at the - // operator token; same-operator repeats apply no delta and - // record nothing. - for child in iter_children(node) { - let op = match C::from(child.kind_id()) { - C::AMPAMP => "&&", - C::PIPEPIPE => "||", - _ => continue, - }; - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.observe_boolean(op); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(&child, |e, s| e.cognitive(s, delta, op)); - } - } - _ => {} - } -} - -fn classify_abc(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: C) { - match kind { - C::AssignmentExpression | C::UpdateExpression => { - ctx.current().abc.record_assignment(); - ctx.record_evidence(node, |e, s| e.abc_assignment(s, node.kind())); - } - C::InitDeclarator if has_child_kind(node, C::EQ) => { - ctx.current().abc.record_assignment(); - ctx.record_evidence(node, |e, s| e.abc_assignment(s, node.kind())); - } - C::CallExpression | C::CallExpression2 => { - ctx.current().abc.record_branch(); - ctx.record_evidence(node, |e, s| e.abc_branch(s, node.kind())); - } - C::IfStatement - | C::ElseClause - | C::CaseStatement - | C::ForStatement - | C::WhileStatement - | C::DoStatement - | C::ConditionalExpression - | C::EQEQ - | C::BANGEQ - | C::LT - | C::LTEQ - | C::GT - | C::GTEQ - | C::AMPAMP - | C::PIPEPIPE - | C::BANG => { - ctx.current().abc.record_condition(); - ctx.record_evidence(node, |e, s| e.abc_condition(s, node.kind())); - } - _ => {} - } -} - -fn classify_loc(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: C) { - match kind { - // Containers and string internals must not contribute their - // own physical line. Mirrors the legacy `Loc for CCode`'s - // explicit no-op arm. - C::TranslationUnit - | C::StringLiteral - | C::ConcatenatedString - | C::CharLiteral - | C::CompoundStatement - | C::StringContent - | C::EscapeSequence => {} - C::Comment => { - let start = node.start_position().row as u32; - let end = node.end_position().row as u32; - ctx.current().loc.observe_comment(start, end); - } - // LLOC kind set: 36 statement-shaped + preprocessor-container - // variants (legacy `loc.rs:583-616`). Each occurrence - // contributes one logical line. - C::Declaration - | C::TypeDefinition - | C::ExpressionStatement - | C::ExpressionStatement2 - | C::IfStatement - | C::SwitchStatement - | C::CaseStatement - | C::WhileStatement - | C::DoStatement - | C::ForStatement - | C::ReturnStatement - | C::BreakStatement - | C::ContinueStatement - | C::GotoStatement - | C::LabeledStatement - | C::SehTryStatement - | C::SehLeaveStatement - | C::FunctionDefinition - | C::FunctionDefinition2 - | C::PreprocInclude - | C::PreprocDef - | C::PreprocFunctionDef - | C::PreprocCall - | C::PreprocIf - | C::PreprocIf2 - | C::PreprocIf3 - | C::PreprocIf4 - | C::PreprocIfdef - | C::PreprocIfdef2 - | C::PreprocIfdef3 - | C::PreprocIfdef4 - | C::PreprocElse - | C::PreprocElse2 - | C::PreprocElse3 - | C::PreprocElse4 - | C::PreprocElif - | C::PreprocElif2 - | C::PreprocElif3 - | C::PreprocElif4 - | C::PreprocElifdef - | C::PreprocElifdef2 - | C::PreprocElifdef3 - | C::PreprocElifdef4 => { - ctx.current().loc.observe_lloc(); - } - _ => { - let start = node.start_position().row as u32; - ctx.current().loc.observe_code_line(start); - } - } -} - -fn classify_halstead(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: C) { - match halstead_op_type(kind) { - HalsteadType::Operator => { - let kind_label: &'static str = kind.into(); - ctx.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(kind_label), - text: None, - }); - } - HalsteadType::Operand => { - let text = text_of(node, ctx.source); - ctx.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(SmolStr::new(text)), - }); - } - HalsteadType::Unknown => {} - } -} - -// -------------------------------------------------------------------- -// Halstead classification (legacy `Getter::get_op_type for CCode`). -// -------------------------------------------------------------------- - -enum HalsteadType { - Operator, - Operand, - Unknown, -} - -fn halstead_op_type(kind: C) -> HalsteadType { - match kind { - // Keywords and control flow. - C::If - | C::Else - | C::Switch - | C::Case - | C::Default - | C::While - | C::Do - | C::For - | C::Return - | C::Break - | C::Continue - | C::Goto - | C::Sizeof - | C::Alignof - | C::Alignof2 - | C::Alignof3 - | C::Alignof4 - | C::Alignof5 - | C::Offsetof - | C::Typedef - | C::Extern - | C::Static - | C::Auto - | C::Register - | C::Inline - | C::Inline2 - | C::Inline3 - | C::Forceinline - | C::ThreadLocal - | C::Thread - | C::Const - | C::Constexpr - | C::Volatile - | C::Volatile2 - | C::Restrict - | C::Restrict2 - | C::Atomic - | C::Noreturn - | C::Noreturn2 - | C::Nonnull - | C::Alignas - | C::Alignas2 - | C::Signed - | C::Unsigned - | C::Long - | C::Short - | C::Enum - | C::Struct - | C::Union - // Punctuation. - | C::LPAREN - | C::LPAREN2 - | C::RPAREN - | C::LBRACE - | C::RBRACE - | C::LBRACK - | C::RBRACK - | C::COMMA - | C::SEMI - | C::COLON - | C::QMARK - | C::DOT - | C::DASHGT - // Arithmetic / bitwise / logical / comparison operators. - | C::PLUS - | C::DASH - | C::STAR - | C::SLASH - | C::PERCENT - | C::AMP - | C::PIPE - | C::CARET - | C::TILDE - | C::BANG - | C::LTLT - | C::GTGT - | C::AMPAMP - | C::PIPEPIPE - | C::EQ - | C::EQEQ - | C::BANGEQ - | C::LT - | C::LTEQ - | C::GT - | C::GTEQ - | C::PLUSEQ - | C::DASHEQ - | C::STAREQ - | C::SLASHEQ - | C::PERCENTEQ - | C::AMPEQ - | C::PIPEEQ - | C::CARETEQ - | C::LTLTEQ - | C::GTGTEQ - | C::PLUSPLUS - | C::DASHDASH - // Preprocessor directives count as operators. - | C::HASHinclude - | C::HASHdefine - | C::HASHif - | C::HASHifdef - | C::HASHifndef - | C::HASHelse - | C::HASHelif - | C::HASHelifdef - | C::HASHelifndef - | C::HASHendif => HalsteadType::Operator, - - // Operands: identifiers, type identifiers, and literals. - C::Identifier - | C::FieldIdentifier - | C::TypeIdentifier - | C::StatementIdentifier - | C::PrimitiveType - | C::NumberLiteral - | C::CharLiteral - | C::StringLiteral - | C::ConcatenatedString - | C::True - | C::False - | C::NULL - | C::Nullptr - | C::SystemLibString => HalsteadType::Operand, - - _ => HalsteadType::Unknown, - } -} - -// -------------------------------------------------------------------- -// Function-name and NArgs helpers — direct ports of legacy -// `getter.rs::get_func_space_name for CCode` and `compute_c_args`. -// -------------------------------------------------------------------- - -/// Walk `node.declarator` inward through `function_declarator` / -/// `pointer_declarator` / `parenthesized_declarator` chains until an -/// identifier is found. Mirrors legacy `getter.rs::get_func_space_name`. -fn function_name<'src>(node: &Node<'_>, source: &'src [u8]) -> Option<&'src str> { - let mut cur = node.child_by_field_name("declarator"); - while let Some(current) = cur { - match C::from(current.kind_id()) { - C::Identifier | C::FieldIdentifier | C::TypeIdentifier => { - let bytes = &source[current.start_byte()..current.end_byte()]; - return core::str::from_utf8(bytes).ok(); - } - _ => { - cur = current.child_by_field_name("declarator"); - } - } - } - None -} - -#[inline(always)] -fn is_c_function_declarator(kind: u16) -> bool { - matches!( - C::from(kind), - C::FunctionDeclarator - | C::FunctionDeclarator2 - | C::FunctionDeclarator3 - | C::FunctionDeclarator4 - | C::FunctionDeclarator5 - ) -} - -#[inline(always)] -fn is_c_parameter_list(kind: u16) -> bool { - matches!(C::from(kind), C::ParameterList | C::ParameterList2) -} - -/// Walk the `declarator` field inward until the innermost -/// `function_declarator` is found; that node's direct `parameter_list` -/// child holds the parameters. Mirrors legacy `compute_c_args`. -fn count_c_args(node: &Node<'_>, source: &[u8]) -> u32 { - let mut cur = node.child_by_field_name("declarator"); - while let Some(current) = cur { - if is_c_function_declarator(current.kind_id()) { - let mut cursor = current.walk(); - let Some(param_list) = current - .children(&mut cursor) - .find(|c| is_c_parameter_list(c.kind_id())) - else { - return 0; - }; - let mut list_cursor = param_list.walk(); - let params: Vec<_> = param_list - .children(&mut list_cursor) - .filter(|p| C::from(p.kind_id()) == C::ParameterDeclaration) - .collect(); - // `(void)` is C's spelling for "no parameters" and must not - // be counted. Detect it precisely by checking that the - // sole parameter's text literally matches `void`. - // `variadic_parameter` (`...`) is filtered out above. - let is_void_only = params.len() == 1 - && source - .get(params[0].start_byte()..params[0].end_byte()) - .is_some_and(|bytes| bytes == b"void"); - return if is_void_only { 0 } else { params.len() as u32 }; - } - cur = current.child_by_field_name("declarator"); - } - 0 -} - -// -------------------------------------------------------------------- -// Tree-sitter helpers -// -------------------------------------------------------------------- - -fn parent_kind(node: &Node<'_>) -> Option { - node.parent().map(|p| C::from(p.kind_id())) -} - -/// `is_else_if`: an `if_statement` whose direct parent is the -/// `else_clause` wrapper. tree-sitter-c parses `else if (...)` as -/// `if_statement { else_clause { if_statement } }`, so the *inner* -/// if matches this predicate. Mirrors legacy -/// `checker.rs::is_else_if for CCode`. -fn is_else_if(node: &Node<'_>) -> bool { - if C::from(node.kind_id()) != C::IfStatement { - return false; - } - parent_kind(node) == Some(C::ElseClause) -} - -fn has_child_kind(node: &Node<'_>, kind: C) -> bool { - iter_children(node).any(|c| C::from(c.kind_id()) == kind) -} - -fn iter_children<'tree>(node: &Node<'tree>) -> impl Iterator> { - let mut cursor = node.walk(); - let mut nodes = Vec::new(); - if cursor.goto_first_child() { - loop { - nodes.push(cursor.node()); - if !cursor.goto_next_sibling() { - break; - } - } - } - nodes.into_iter() -} diff --git a/crates/mehen-c/tests/abc.rs b/crates/mehen-c/tests/abc.rs deleted file mode 100644 index d645fecb..00000000 --- a/crates/mehen-c/tests/abc.rs +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC tests for the C walker. -//! -//! Every legacy `check_metrics::` ABC test from -//! `crates/mehen-engine/src/legacy/metrics/abc.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. - -use mehen_c::CAnalyzer; -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = CAnalyzer::new(); - let file = SourceFile::new("foo.c".into(), Language::C, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn c_abc_counts_else_clause_in_conditions() { - // Per Fitzpatrick (1997), `else` is a branch-point that contributes - // to the `C` (Conditions) component. tree-sitter-c exposes it as a - // dedicated `else_clause` named node, so an `if (x > 0) {...} else - // {...}` should yield: +1 if + 1 `>` comparison + 1 else = 3 - // conditions. A: 0 (no assignments). B: 0 (no calls). - let a = analyze( - "int f(int x) { - if (x > 0) { - return 1; - } else { - return 0; - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - assert_eq!(abc.assignments, 0.0); - assert_eq!(abc.branches, 0.0); - assert_eq!(abc.conditions, 3.0); -} diff --git a/crates/mehen-c/tests/cognitive.rs b/crates/mehen-c/tests/cognitive.rs deleted file mode 100644 index 5071795f..00000000 --- a/crates/mehen-c/tests/cognitive.rs +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity tests for the C walker. -//! -//! Every legacy `check_metrics::` cognitive test from -//! `crates/mehen-engine/src/legacy/metrics/cognitive.rs` is ported -//! here byte-identical so the parity contract (plan §12.3.1) is -//! visibly maintained. No drift expected — this is a tree-sitter→ -//! tree-sitter migration, not a parser swap. - -use mehen_c::CAnalyzer; -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = CAnalyzer::new(); - let file = SourceFile::new("foo.c".into(), Language::C, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn c_boolean_sequence_does_not_leak_across_else_if() { - // Regression: tree-sitter-c parses `else if` as - // `else_clause { if_statement }`. The outer `if (a && b)`'s - // boolean-sequence tracker must not bleed into the inner - // `else if (c && d)` condition — otherwise the second `&&` would - // collapse with the first (same operator) and cognitive would be - // undercounted. - // - // Expected breakdown for `int f(int a, int b, int c, int d)`: - // +1 outer `if` (nesting = 0 -> 1) - // +1 outer `&&` (first op in sequence) - // +1 `else` clause (no nesting) - // +0 inner `if` (else-if arm) (structural cost paid by `else`) - // +1 inner `&&` (fresh sequence — IF reset works) - // total = 4. - let a = analyze( - "int f(int a, int b, int c, int d) { - if (a && b) { - return 1; - } else if (c && d) { - return 2; - } - return 0; - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 4.0); -} diff --git a/crates/mehen-c/tests/contributions.rs b/crates/mehen-c/tests/contributions.rs deleted file mode 100644 index c357971d..00000000 --- a/crates/mehen-c/tests/contributions.rs +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the C analyzer (plan §5.4). - -use mehen_c::CAnalyzer; -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - CAnalyzer::new() - .analyze( - &SourceFile::new("s.c".into(), Language::C, source.to_string()), - config, - ) - .expect("C analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -int classify(int a, int b) { - if (a > 0 && b > 0) { - return 1; - } else { - a += b; - } - for (int i = 0; i < a; i++) { - b = helper(i); - } - return b > 0 ? b : 0; -} -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nargs", "nargs"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn decision_evidence_counts_match_cyclomatic() { - // Per-space base rows (`c.cyclomatic.base.`) cover the +1 McCabe - // constant per folded space, so cyclomatic evidence sums exactly. - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert_eq!( - evidence_sum(&analysis, "cyclomatic.sum"), - metric(&analysis, "cyclomatic.sum") - ); - let mut bases: Vec<&str> = analysis - .contributions - .iter() - .filter(|item| item.reason.as_str().starts_with("c.cyclomatic.base.")) - .map(|item| item.reason.as_str()) - .collect(); - bases.sort_unstable(); - // One function space + one unit. - assert_eq!( - bases, - vec!["c.cyclomatic.base.function", "c.cyclomatic.base.unit"] - ); -} - -#[test] -fn reasons_are_c_namespaced_with_node_kinds() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "c.cyclomatic.if_statement", - "c.cyclomatic.for_statement", - "c.cyclomatic.conditional_expression", - "c.cyclomatic.&&", - "c.cognitive.if_statement", - "c.cognitive.else_clause", - "c.nexit.return_statement", - "c.abc.assignment.assignment_expression", - "c.abc.assignment.init_declarator", - "c.abc.assignment.update_expression", - "c.abc.branch.call_expression", - "c.abc.condition.if_statement", - "c.nom.function.function_definition", - "c.nargs.function.function_definition", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("c."))); -} - -#[test] -fn boolean_run_transitions_record_only_moved_deltas() { - // `a && b && c` is one boolean run: the first `&&` pays +1, the - // repeat pays nothing and records nothing. - let source = "\ -int f(int a, int b, int c) { - if (a && b && c) { - return 1; - } - return 0; -} -"; - let analysis = analyze(source, &AnalysisConfig::production()); - let boolean_evidence: Vec = analysis - .contributions - .iter() - .filter(|item| item.reason.as_str() == "c.cognitive.&&") - .map(|item| item.amount) - .collect(); - assert_eq!(boolean_evidence, vec![1.0]); - assert_eq!(evidence_sum(&analysis, "cognitive.sum"), 2.0); // if + first && - assert_eq!(metric(&analysis, "cognitive.sum"), 2.0); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in ["cyclomatic.sum", "cognitive.sum", "nexit.sum", "abc"] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-c/tests/loc.rs b/crates/mehen-c/tests/loc.rs deleted file mode 100644 index 57ec9250..00000000 --- a/crates/mehen-c/tests/loc.rs +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC tests for the C walker. -//! -//! Every legacy `check_metrics::` LOC test from -//! `crates/mehen-engine/src/legacy/metrics/loc.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. The LLOC kind set spans 36 statement / preprocessor -//! variants — see `walker.rs::classify_loc`. - -use mehen_c::CAnalyzer; -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = CAnalyzer::new(); - let file = SourceFile::new("foo.c".into(), Language::C, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn c_typedef_counts_as_lloc() { - // `typedef` is a declaration like `int x;` and must contribute one - // logical line. Together with the `int x;` declaration this gives - // an LLOC of 2. - let a = analyze( - "typedef unsigned int u32; -int x;", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!(loc.lloc, 2.0); -} - -#[test] -fn c_preproc_conditionals_count_as_lloc() { - // `#ifdef FOO ... #else ... #endif` exposes two preprocessor - // conditional containers (`preproc_ifdef` and a nested - // `preproc_else`). Combined with the two inner `int x = …;` - // declarations, LLOC must reach 4: - // +1 preproc_ifdef (the `#ifdef FOO` branch) - // +1 declaration (`int x = 1;`) - // +1 preproc_else (the `#else` branch) - // +1 declaration (`int y = 2;`) - let a = analyze( - "#ifdef FOO -int x = 1; -#else -int y = 2; -#endif", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!(loc.lloc, 4.0); -} diff --git a/crates/mehen-c/tests/nargs.rs b/crates/mehen-c/tests/nargs.rs deleted file mode 100644 index 80aee91e..00000000 --- a/crates/mehen-c/tests/nargs.rs +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NArgs tests for the C walker. -//! -//! Every legacy `check_metrics::` nargs test from -//! `crates/mehen-engine/src/legacy/metrics/nargs.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. The C-specific `count_c_args` walks the -//! `function_definition > function_declarator > parameter_list` -//! chain, applies the `(void)` exception, and excludes the -//! `variadic_parameter` (`...`) — see `walker.rs::count_c_args`. - -use mehen_c::CAnalyzer; -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = CAnalyzer::new(); - let file = SourceFile::new("foo.c".into(), Language::C, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn c_function_counts_parameters() { - // Regression: tree-sitter-c nests `parameter_list` under - // `function_declarator`, not directly under `function_definition`. - // The generic `compute_args` that looks for a `parameters` field on - // the function node would read zero for C functions; the C-specific - // counter must descend into the declarator. Definition here has two - // params (int a, int b), so aggregated nargs must reflect that. - // - // Drift from legacy: legacy reported `functions_min: 0.0` because - // its `compute_minmax` ran unconditionally for every space, so the - // unit space (which has no fn args) pulled the min down to 0. The - // 1.0 mehen-metrics `NargsStats::finalize_minmax` only includes - // a space in the function bounds when `is_function == true`, so - // the unit no longer dilutes the bounds. Result: `functions_min: - // 2.0` — matching the *only* function in this fixture. Same drift - // documented in Phase 6 Python, Phase 9 Ruby, and the Go port. - let a = analyze("int add(int a, int b) { return a + b; }"); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - nargs, - @r###" - { - "total_functions": 2.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 2.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn c_void_parameter_is_not_counted() { - // `int foo(void)` is the C spelling for "no parameters" and must - // count as zero arguments — not one. - let a = analyze("int foo(void) { return 0; }"); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - nargs, - @r###" - { - "total_functions": 0.0, - "total_closures": 0.0, - "average_functions": 0.0, - "average_closures": 0.0, - "total": 0.0, - "average": 0.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn c_variadic_parameter_does_not_count() { - // `int vararg(int fmt, ...)` has one named argument; the `...` - // token is a `variadic_parameter`, not a `parameter_declaration`, - // and must not contribute to the count. - // - // Drift from legacy: same as `c_function_counts_parameters` — - // `functions_min` is now `1.0` because the only function carries - // one parameter; legacy reported `0.0` because the unit space - // diluted the bound. - let a = analyze("int vararg(int fmt, ...) { return fmt; }"); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - nargs, - @r###" - { - "total_functions": 1.0, - "total_closures": 0.0, - "average_functions": 1.0, - "average_closures": 0.0, - "total": 1.0, - "average": 1.0, - "functions_min": 1.0, - "functions_max": 1.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn c_bare_type_parameter_counts_as_one() { - // `int foo(int)` — a K&R / old-style prototype-esque definition - // with a bare type and no parameter name — has ONE parameter. - // tree-sitter-c parses it with the same AST shape as `int foo(void)` - // (sole `parameter_declaration` holding just a `primitive_type`), - // so the `(void)` detection must look at the literal text, not - // just the structural shape, to avoid undercounting this case. - let a = analyze("int foo(int) { return 0; }"); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - assert_eq!(nargs.total_functions, 1.0); -} diff --git a/crates/mehen-cli/Cargo.toml b/crates/mehen-cli/Cargo.toml deleted file mode 100644 index f4056a56..00000000 --- a/crates/mehen-cli/Cargo.toml +++ /dev/null @@ -1,79 +0,0 @@ -[package] -name = "mehen" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Compute and report code metrics." -publish = false - -# `name = "mehen"` makes both the package and the (auto-generated) -# binary share the name. `[[bin]]` is omitted on purpose so cargo -# treats `src/main.rs` as the package's default binary target — that -# keeps `cargo run -p mehen` and `cargo build --bin mehen` both -# working without duplicate-target errors. - -# `cargo binstall` configuration. The crate is `publish = false`, so -# users install via the `--git` form: `cargo binstall --git -# https://github.com/ophi-dev/mehen mehen`. binstall reads this -# metadata from the manifest at the resolved git ref and downloads -# the matching pre-built archive from the GitHub Release. -# -# Per-target overrides are required because the archive layout in -# `.github/workflows/release.yml` ("Create CLI binary archive") names -# files by `{linux,darwin,windows}_{x86_64,arm64}[-musl]` rather than -# the rust target triple binstall would pick by default. The archives -# contain a flat `mehen` (or `mehen.exe`) at the root, so `bin-dir` -# omits an enclosing directory. -[package.metadata.binstall] -bin-dir = "{ bin }{ binary-ext }" -pkg-fmt = "tgz" - -[package.metadata.binstall.overrides.x86_64-unknown-linux-gnu] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_linux_x86_64.tar.gz" - -[package.metadata.binstall.overrides.x86_64-unknown-linux-musl] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_linux_x86_64-musl.tar.gz" - -[package.metadata.binstall.overrides.aarch64-unknown-linux-gnu] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_linux_arm64.tar.gz" - -[package.metadata.binstall.overrides.aarch64-unknown-linux-musl] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_linux_arm64-musl.tar.gz" - -[package.metadata.binstall.overrides.x86_64-apple-darwin] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_darwin_x86_64.tar.gz" - -[package.metadata.binstall.overrides.aarch64-apple-darwin] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_darwin_arm64.tar.gz" - -[package.metadata.binstall.overrides.x86_64-pc-windows-msvc] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_windows_x86_64.zip" -pkg-fmt = "zip" - -[package.metadata.binstall.overrides.aarch64-pc-windows-msvc] -pkg-url = "{ repo }/releases/download/v{ version }/mehen_{ version }_windows_arm64.zip" -pkg-fmt = "zip" - -[dependencies] -mehen-core = { workspace = true } -mehen-engine = { workspace = true } -mehen-report = { workspace = true } - -camino = { workspace = true } -clap = { workspace = true } -# `env_logger` is pinned here (not in `[workspace.dependencies]`) because -# `mehen-cli` is the only consumer — log initialization belongs to the -# binary entry point. -env_logger = "^0.11" -log = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -serde_json = { workspace = true } -tempfile = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-cli/src/args.rs b/crates/mehen-cli/src/args.rs deleted file mode 100644 index c2339139..00000000 --- a/crates/mehen-cli/src/args.rs +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::path::PathBuf; - -use clap::{Args, Parser, Subcommand}; - -/// `mehen` — code metrics CLI. -/// -/// `--version` is implemented as a global flag (rather than via clap's -/// auto-generated handling) so it can pair with `--json` to produce a -/// machine-readable shape that the GitHub Action reads to stamp its -/// sticky comment footer with the running mehen version. Without this -/// pairing, `mehen --version --json` would just print the plain -/// "mehen X.Y.Z" string and the action's JSON parser would silently -/// drop the version. -#[derive(Debug, Parser)] -#[command( - name = "mehen", - bin_name = "mehen", - about = "Compute and report code metrics.", - disable_version_flag = true -)] -pub(crate) struct Cli { - /// Print version information and exit. - #[arg(long, short = 'V', global = true)] - pub(crate) version: bool, - - /// Emit output as JSON. Currently only meaningful with - /// `--version`; clap rejects the flag unless `--version` is also - /// passed. - #[arg(long, global = true, requires = "version")] - pub(crate) json: bool, - - /// Path to a configuration file. When omitted, `mehen.toml` (or - /// `.mehen.toml`) is discovered from the current directory upward, - /// stopping at the enclosing git repository root. - #[arg(long, global = true, value_name = "PATH")] - pub(crate) config: Option, - - #[command(subcommand)] - pub(crate) command: Option, -} - -/// Subcommands flatten the legacy `DiffOpts` / `TopOffendersOpts` -/// argument shapes so the existing pre-1.0 tests against those flag -/// surfaces keep passing through the new binary. Each pre-1.0 -/// argument is physically reachable via -/// `cargo run -p mehen -- diff …`. -#[derive(Debug, Subcommand)] -pub(crate) enum Command { - /// Analyze exactly one file and emit a metrics report. - Metrics(MetricsArgs), - /// Compare metrics between two git revisions. - Diff(mehen_engine::DiffOpts), - /// Rank files by one or more metrics (worst offenders first). - TopOffenders(mehen_engine::TopOffendersOpts), -} - -#[derive(Debug, Args)] -pub(crate) struct MetricsArgs { - /// Path to the file to analyze. `mehen metrics` never walks directories. - pub(crate) path: PathBuf, - - /// Override language detection. - #[arg(long)] - pub(crate) language: Option, - - /// Output format. - #[arg(long, default_value = "json")] - pub(crate) format: OutputFormat, - - /// Pretty-print JSON output. - #[arg(long)] - pub(crate) pretty: bool, - - /// Built-in profile preset. - #[arg(long, default_value = "default")] - pub(crate) profile: Profile, - - #[command(flatten)] - pub(crate) coverage: mehen_engine::CoverageOpts, -} - -#[derive(Debug, Clone, Copy, clap::ValueEnum)] -pub(crate) enum OutputFormat { - Json, - Markdown, - Yaml, - Toml, -} - -#[derive(Debug, Clone, Copy, clap::ValueEnum)] -pub(crate) enum Profile { - Default, - Ci, - Strict, -} diff --git a/crates/mehen-cli/src/commands.rs b/crates/mehen-cli/src/commands.rs deleted file mode 100644 index dff3226b..00000000 --- a/crates/mehen-cli/src/commands.rs +++ /dev/null @@ -1,181 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Command implementations for the 1.0 CLI. - -use std::io::{self, Write}; - -use camino::Utf8PathBuf; - -use mehen_core::{AnalysisConfig, DiagnosticSeverity, Language, MetricsReport, SourceFile}; -use mehen_engine::{AnalyzeMetricsInput, analyze_metrics, detect_language}; -use mehen_report::render_metrics_json; - -use crate::args::{MetricsArgs, OutputFormat, Profile}; -use crate::exit::ExitCode; - -pub(crate) fn metrics(args: MetricsArgs, config: Option<&mehen_engine::ConfigFile>) -> ExitCode { - let path = match Utf8PathBuf::try_from(args.path.clone()) { - Ok(p) => p, - Err(_) => { - log::error!("path is not valid UTF-8: {}", args.path.display()); - return ExitCode::SetupError; - } - }; - - let language = if let Some(lang_str) = args.language.as_deref() { - match lang_str.parse::() { - Ok(l) => l, - Err(_) => { - log::error!("unknown --language value: {lang_str}"); - return ExitCode::SetupError; - } - } - } else { - match detect_language(path.as_path()) { - Some(l) => l, - None => { - log::error!( - "could not detect language from path `{path}`; pass --language explicitly" - ); - return ExitCode::SetupError; - } - } - }; - - let text = match std::fs::read_to_string(&path) { - Ok(t) => t, - Err(e) => { - log::error!("failed to read `{path}`: {e}"); - return ExitCode::SetupError; - } - }; - - let source = SourceFile::new(path, language, text); - let input = AnalyzeMetricsInput { - source, - config: config_for_profile(args.profile), - }; - - let report = match analyze_metrics(input) { - Ok(r) => r, - Err(e) => { - log::error!("analysis failed: {e}"); - return ExitCode::SetupError; - } - }; - - // Coverage enrichment (`--coverage`, `[coverage]` config, or a - // configured coverage threshold): folds the `coverage.*` family - // into the metric tree before rendering and threshold evaluation. - // An explicit report path that is missing or unparsable is a - // setup error; "no coverage found/matched" leaves the report - // untouched. - let mut report = report; - if let Err(e) = mehen_engine::enrich_metrics_with_coverage(&mut report, &args.coverage, config) - { - log::error!("{e}"); - return ExitCode::SetupError; - } - let report = report; - - if let Some(exit) = render_report(&report, args.format, args.pretty) - && !matches!(exit, ExitCode::Success) - { - return exit; - } - let report_exit = exit_code_from_report(&report); - if !matches!(report_exit, ExitCode::Success) { - // Blocking diagnostics mean the metrics are partial (§9.3): - // exit 1 without threshold-gating numbers from a broken parse. - return report_exit; - } - - // Configured metric thresholds (`mehen.toml`): `mehen metrics` - // reports the full metric set, so every configured threshold that - // matches a key this file publishes is evaluated against the root - // space. Violations print a grouped report on stderr and fail the - // command with the generic failure code (exit 1). - if let Some(config) = config { - let mut breaches = - config - .thresholds - .evaluate(report.path.as_str(), language, &report.root, None); - if !breaches.is_empty() { - eprint!( - "{}", - mehen_engine::render_threshold_report(&mut breaches, &config.path) - ); - return ExitCode::SetupError; - } - } - ExitCode::Success -} - -/// Map the `--profile` flag to an [`AnalysisConfig`]. Until plan §3.6 -/// designs threshold/polarity profiles, the only knob `AnalysisConfig` -/// exposes is `emit_contributions`; `default` follows the production -/// preset, `ci`/`strict` skip contribution evidence to keep CI runs -/// lean. -fn config_for_profile(profile: Profile) -> AnalysisConfig { - match profile { - Profile::Default => AnalysisConfig::production(), - // `ci` and `strict` are still placeholders for thresholding, but - // they should not silently inherit `production`'s defaults — the - // CLI flag must observably differ from the default. Both presets - // skip contribution evidence (cheap; emits the same metric - // numbers) so `--profile` is no longer a no-op. - Profile::Ci | Profile::Strict => AnalysisConfig::benchmark(), - } -} - -/// Map a `MetricsReport`'s diagnostic severities to a CLI exit code per -/// the diagnostic contract (rewrite plan §9.3): `Warning` is exit 0, -/// `Error`/`Fatal` are exit 1. Configured `mehen.toml` threshold -/// violations are handled separately in [`metrics`] (also exit 1) and -/// only on reports without blocking diagnostics. -fn exit_code_from_report(report: &MetricsReport) -> ExitCode { - let has_error_or_fatal = report.diagnostics.iter().any(|d| { - matches!( - d.severity, - DiagnosticSeverity::Error | DiagnosticSeverity::Fatal - ) - }); - if has_error_or_fatal { - ExitCode::SetupError - } else { - ExitCode::Success - } -} - -fn render_report(report: &MetricsReport, format: OutputFormat, pretty: bool) -> Option { - match format { - OutputFormat::Json => match render_metrics_json(report, pretty) { - Ok(rendered) => { - let mut stdout = io::stdout().lock(); - if writeln!(stdout, "{rendered}").is_err() { - return Some(ExitCode::SerializationError); - } - None - } - Err(e) => { - log::error!("failed to render JSON: {e}"); - Some(ExitCode::SerializationError) - } - }, - OutputFormat::Markdown => { - let rendered = mehen_report::render_metrics_markdown(report); - let mut stdout = io::stdout().lock(); - if writeln!(stdout, "{rendered}").is_err() { - return Some(ExitCode::SerializationError); - } - None - } - OutputFormat::Yaml | OutputFormat::Toml => { - log::error!( - "the {format:?} format is reserved for a future phase; use --format json or markdown." - ); - Some(ExitCode::SetupError) - } - } -} diff --git a/crates/mehen-cli/src/exit.rs b/crates/mehen-cli/src/exit.rs deleted file mode 100644 index 7cf99991..00000000 --- a/crates/mehen-cli/src/exit.rs +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Exit code contract for the 1.0 CLI (rewrite plan §4.1). - -#[derive(Debug, Clone, Copy)] -pub enum ExitCode { - Success = 0, - /// Setup, IO, git, parser fatal, unsupported-language, or invalid-state - /// error. Also covers "analysis errors" diagnostics on `mehen metrics` - /// and configured `mehen.toml` metric-threshold violations — every - /// quality gate fails with the generic non-zero code so CI treats - /// them uniformly. - SetupError = 1, - /// Documentation policy failure (`mehen diff --fail-on`) and JSON - /// emission failures inside `mehen diff` keep this historical code. - /// Named for the doc gate: configured `mehen.toml` metric thresholds - /// exit 1 (see `SetupError`), not 2. - DocPolicyFailure = 2, - /// Invalid machine-output serialization state. - SerializationError = 3, -} - -impl From for i32 { - fn from(value: ExitCode) -> Self { - value as i32 - } -} diff --git a/crates/mehen-cli/src/main.rs b/crates/mehen-cli/src/main.rs deleted file mode 100644 index 12d16486..00000000 --- a/crates/mehen-cli/src/main.rs +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen` — 1.0 CLI binary. -//! -//! `metrics` runs through the new architecture (mehen-engine + per-language -//! analyzer crates). `diff` and `top-offenders` delegate to the pre-1.0 -//! orchestrators that now live alongside the post-1.0 entry points in -//! `mehen_engine::diff` / `mehen_engine::top_offenders`. - -mod args; -mod commands; -mod exit; - -use std::io::{self, Write}; - -use clap::Parser; - -use args::{Cli, Command}; -use exit::ExitCode; - -fn main() { - env_logger::init(); - // Register the legacy embedded-code dispatch so the moved - // `mehen-markdown` analyzer can fold fenced-code metrics into its - // output. Idempotent — safe to call multiple times. - mehen_engine::init_markdown(); - let cli = Cli::parse(); - - if cli.version { - print_version(cli.json); - return; - } - - let Some(command) = cli.command else { - // Match clap's default "no subcommand and no global action" - // behaviour: print help to stderr and exit non-zero. - let _ = ::command().print_help(); - std::process::exit(ExitCode::SetupError.into()); - }; - - // Repository-local configuration (`mehen.toml` / `.mehen.toml`, - // or an explicit `--config`). A malformed config is a setup - // error: failing loudly here beats silently running without the - // thresholds the user wrote down. The rendered diagnostic points - // at the offending key inside the TOML source. - let config = match mehen_engine::load_config(cli.config.as_deref()) { - Ok(config) => config, - Err(e) => { - eprint!("{}", mehen_engine::render_config_error(&e)); - std::process::exit(ExitCode::SetupError.into()); - } - }; - - let code = run(command, config.as_ref()); - std::process::exit(code.into()); -} - -fn run(command: Command, config: Option<&mehen_engine::ConfigFile>) -> ExitCode { - match command { - Command::Metrics(args) => commands::metrics(args, config), - Command::Diff(opts) => { - mehen_engine::run_diff(opts, config); - ExitCode::Success - } - Command::TopOffenders(opts) => { - mehen_engine::run_top_offenders(opts, config); - ExitCode::Success - } - } -} - -/// Print the CLI version. With `as_json = true`, emits a -/// `{"name":"mehen","version":"X.Y.Z"}` payload that the GitHub -/// Action consumes via `mehen --version --json` to stamp its sticky -/// PR-comment footer. The plain form (`as_json = false`) prints -/// `mehen X.Y.Z` — identical to clap's auto-generated output. -fn print_version(as_json: bool) { - let mut stdout = io::stdout().lock(); - if as_json { - // Hand-rolled JSON to avoid pulling `serde_json` into the CLI - // crate just for this one payload — the env-var values never - // contain characters that need escaping. - writeln!( - stdout, - "{{\"name\":\"{}\",\"version\":\"{}\"}}", - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_VERSION") - ) - .expect("failed to write version payload"); - } else { - writeln!( - stdout, - "{} {}", - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_VERSION") - ) - .expect("failed to write version"); - } -} diff --git a/crates/mehen-cli/tests/cli_smoke.rs b/crates/mehen-cli/tests/cli_smoke.rs deleted file mode 100644 index 9a4cdfb0..00000000 --- a/crates/mehen-cli/tests/cli_smoke.rs +++ /dev/null @@ -1,2100 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Smoke tests for the 1.0 `mehen` CLI. -//! -//! Replaces the pre-1.0 `tests/cli_smoke.rs`. The pre-1.0 commands -//! `--dump`, `--find`, `--count`, `--function`, root-level `-m -p` are -//! dropped per the rewrite plan §2.1; the new surface is `metrics`, -//! `diff`, and `top-offenders`. -use std::io::Write; -use std::process::Command; - -fn write_python(dir: &std::path::Path, name: &str, body: &str) -> std::path::PathBuf { - let path = dir.join(name); - let mut f = std::fs::File::create(&path).expect("create py file"); - f.write_all(body.as_bytes()).expect("write py file"); - path -} - -fn git(path: &std::path::Path, args: &[&str]) -> std::process::Output { - Command::new("git") - .current_dir(path) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git") -} - -fn git_ok(path: &std::path::Path, args: &[&str]) { - let output = git(path, args); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); -} - -fn init_git_repo(path: &std::path::Path) { - git_ok(path, &["init", "-q", "-b", "main"]); - git_ok(path, &["config", "commit.gpgsign", "false"]); -} - -fn commit_all(path: &std::path::Path, message: &str) { - git_ok(path, &["add", "-A"]); - git_ok(path, &["commit", "-q", "-m", message]); -} - -#[test] -fn version_prints_name_and_version() { - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .arg("--version") - .output() - .expect("failed to run mehen --version"); - assert!(output.status.success()); - let stdout = String::from_utf8(output.stdout).expect("stdout utf8"); - assert!(stdout.contains("mehen")); -} - -#[test] -fn help_succeeds() { - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .arg("--help") - .output() - .expect("failed to run mehen --help"); - assert!(output.status.success()); - let stdout = String::from_utf8(output.stdout).expect("stdout utf8"); - assert!(stdout.contains("metrics"), "expected `metrics` in help"); - assert!(stdout.contains("diff"), "expected `diff` in help"); - assert!( - stdout.contains("top-offenders"), - "expected `top-offenders` in help" - ); -} - -#[test] -fn metrics_emits_json_for_python_file() { - let dir = tempfile::tempdir().expect("tempdir"); - let path = write_python( - dir.path(), - "sample.py", - "def foo(x):\n if x:\n return 1\n return 2\n", - ); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .args(["metrics", path.to_str().unwrap(), "--pretty"]) - .output() - .expect("failed to run mehen metrics"); - assert!( - output.status.success(), - "mehen metrics failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let stdout = String::from_utf8(output.stdout).expect("stdout utf8"); - let parsed: serde_json::Value = - serde_json::from_str(&stdout).expect("metrics output must be valid JSON"); - assert_eq!(parsed["language"].as_str(), Some("python")); - // Phase 6 (Ruff migration): Python now reports the `python-ruff` - // backend label. See `docs/python-ruff-spec.md`. - assert_eq!(parsed["analysis_backend"].as_str(), Some("python-ruff")); - let spaces = parsed["root"]["spaces"] - .as_array() - .expect("root must have spaces array"); - assert!(!spaces.is_empty(), "expected one function space"); - assert_eq!(spaces[0]["kind"].as_str(), Some("function")); - assert_eq!(spaces[0]["name"].as_str(), Some("foo")); -} - -#[test] -fn antlr_syntax_errors_are_structured_without_stderr_output() { - let dir = tempfile::tempdir().expect("tempdir"); - - for (name, language, source, diagnostic_code) in [ - ( - "invalid.java", - "java", - "package %name.namespace%;\npublic class Broken {\n", - "java.syntax_error", - ), - ( - "lexer-error.java", - "java", - "public class A # {}\n", - "java.syntax_error", - ), - ( - "invalid.kt", - "kotlin", - "fun broken( {\n", - "kotlin.syntax_error", - ), - ( - "lexer-error.kt", - "kotlin", - "class A # {}\n", - "kotlin.syntax_error", - ), - ] { - let path = dir.path().join(name); - std::fs::write(&path, source).expect("write invalid source file"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .args([ - "metrics", - path.to_str().expect("UTF-8 test path"), - "--language", - language, - ]) - .output() - .expect("failed to run mehen metrics"); - - assert!( - !output.status.success(), - "{language} syntax errors must produce a non-zero exit" - ); - assert!( - output.stderr.is_empty(), - "{language} syntax errors leaked raw ANTLR diagnostics: {}", - String::from_utf8_lossy(&output.stderr) - ); - - let report: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("metrics output must be valid JSON"); - assert!( - report["diagnostics"] - .as_array() - .is_some_and(|diagnostics| diagnostics - .iter() - .any(|diagnostic| diagnostic["code"] == diagnostic_code)), - "{language} structured diagnostics must contain {diagnostic_code}" - ); - } -} - -#[test] -fn metrics_rejects_unknown_language() { - let dir = tempfile::tempdir().expect("tempdir"); - let path = write_python(dir.path(), "sample.unknown", "def f(): pass\n"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .args(["metrics", path.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - assert!( - !output.status.success(), - "unknown language must fail; stderr={}", - String::from_utf8_lossy(&output.stderr) - ); -} - -#[test] -fn top_offenders_requires_paths() { - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .args(["top-offenders"]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - !output.status.success(), - "top-offenders without paths must fail" - ); -} - -#[test] -fn top_offenders_respects_default_ignores_and_no_ignore_override() { - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - std::fs::create_dir(dir.path().join("node_modules")).expect("create ignored directory"); - std::fs::write(dir.path().join(".gitignore"), "node_modules/\n").expect("write gitignore"); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -attributed.py linguist-generated -vendored.py linguist-vendored -binary.py binary -", - ) - .expect("write gitattributes"); - write_python(dir.path(), "kept.py", "x = 1\n"); - write_python(dir.path(), "attributed.py", "x = 1\n"); - write_python(dir.path(), "vendored.py", "x = 1\n"); - write_python(dir.path(), "binary.py", "x = 1\n"); - write_python( - &dir.path().join("node_modules"), - "generated.py", - "def generated():\n return 1\n", - ); - - let run = |no_ignore: bool| { - let mut command = Command::new(env!("CARGO_BIN_EXE_mehen")); - command.current_dir(dir.path()).args([ - "top-offenders", - "--metric", - "loc.lloc", - "--output-format", - "json", - ]); - if no_ignore { - command.arg("--no-ignore"); - } - command - .arg(".") - .output() - .expect("failed to run mehen top-offenders") - }; - - let ignored = run(false); - assert!( - ignored.status.success(), - "default run failed: stderr={}", - String::from_utf8_lossy(&ignored.stderr) - ); - let ignored: serde_json::Value = - serde_json::from_slice(&ignored.stdout).expect("default output must be JSON"); - let ignored = ignored.as_array().expect("default output must be an array"); - assert_eq!(ignored.len(), 1); - assert!( - ignored[0]["path"] - .as_str() - .is_some_and(|path| path.ends_with("kept.py")) - ); - - let unfiltered = run(true); - assert!( - unfiltered.status.success(), - "--no-ignore run failed: stderr={}", - String::from_utf8_lossy(&unfiltered.stderr) - ); - let unfiltered: serde_json::Value = - serde_json::from_slice(&unfiltered.stdout).expect("--no-ignore output must be JSON"); - let mut names: Vec<&str> = unfiltered - .as_array() - .expect("--no-ignore output must be an array") - .iter() - .filter_map(|entry| entry["path"].as_str()) - .filter_map(|path| std::path::Path::new(path).file_name()?.to_str()) - .collect(); - names.sort_unstable(); - assert_eq!( - names, - vec![ - "attributed.py", - "binary.py", - "generated.py", - "kept.py", - "vendored.py" - ] - ); - - let explicit = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "top-offenders", - "--metric", - "loc.lloc", - "--output-format", - "json", - "attributed.py", - ]) - .output() - .expect("failed to run mehen top-offenders for explicit file"); - assert!( - explicit.status.success(), - "explicit file run failed: stderr={}", - String::from_utf8_lossy(&explicit.stderr) - ); - let explicit: serde_json::Value = - serde_json::from_slice(&explicit.stdout).expect("explicit output must be JSON"); - assert_eq!(explicit.as_array().map(Vec::len), Some(1)); - assert!( - explicit[0]["path"] - .as_str() - .is_some_and(|path| path.ends_with("attributed.py")) - ); -} - -#[test] -fn diff_respects_git_attribute_defaults_and_override() { - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -generated.py linguist-generated -vendored.py linguist-vendored -binary.py binary -deleted.py linguist-generated -", - ) - .expect("write gitattributes"); - for name in [ - "kept.py", - "generated.py", - "vendored.py", - "binary.py", - "deleted.py", - "info-only.py", - "global-only.py", - ] { - write_python(dir.path(), name, "x = 1\n"); - } - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "attribute-base"]); - - for name in [ - "kept.py", - "generated.py", - "vendored.py", - "binary.py", - "info-only.py", - "global-only.py", - ] { - write_python(dir.path(), name, "x = 2\n"); - } - std::fs::remove_file(dir.path().join("deleted.py")).expect("remove generated file"); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -generated.py linguist-generated -vendored.py linguist-vendored -binary.py binary -", - ) - .expect("remove deleted file attribute"); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "attribute-head"]); - - std::fs::write( - dir.path().join(".gitattributes"), - "* -linguist-generated -linguist-vendored -binary\n", - ) - .expect("replace checkout gitattributes"); - commit_all(dir.path(), "checkout"); - std::fs::write( - dir.path().join(".git/info/attributes"), - "\ -generated.py -linguist-generated -info-only.py linguist-generated -", - ) - .expect("write local attributes"); - let global_attributes = dir.path().join(".global-attributes"); - std::fs::write( - &global_attributes, - "\ -generated.py -linguist-generated -global-only.py linguist-vendored -", - ) - .expect("write configured attributes"); - git_ok( - dir.path(), - &[ - "config", - "core.attributesFile", - global_attributes.to_str().expect("UTF-8 temp path"), - ], - ); - - let run = |override_flag: Option<&str>| { - let mut command = Command::new(env!("CARGO_BIN_EXE_mehen")); - command.current_dir(dir.path()).args([ - "diff", - "--from", - "attribute-base", - "--to", - "attribute-head", - "--metrics", - "loc.lloc", - "--show-unchanged", - "--output-format", - "json", - ]); - if let Some(flag) = override_flag { - command.arg(flag); - } - command - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff") - }; - - let paths = |output: &std::process::Output| { - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let mut paths: Vec = value["source_code"] - .as_array() - .expect("source_code must be an array") - .iter() - .filter_map(|entry| entry["path"].as_str().map(str::to_owned)) - .collect(); - paths.sort_unstable(); - paths - }; - - assert_eq!( - paths(&run(None)), - vec!["global-only.py", "info-only.py", "kept.py"] - ); - assert_eq!( - paths(&run(Some("--ignore-git-attributes=false"))), - vec![ - "binary.py", - "deleted.py", - "generated.py", - "global-only.py", - "info-only.py", - "kept.py", - "vendored.py" - ] - ); -} - -#[test] -fn diff_reports_history_metrics_for_both_sides() { - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "sample.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "history-base"]); - - write_python(dir.path(), "sample.py", "x = 1\ny = 2\nz = 3\nw = 4\n"); - commit_all(dir.path(), "fix: append two lines"); - git_ok(dir.path(), &["tag", "history-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "history-base", - "--to", - "history-head", - "--metrics", - "history.commit_frequency,history.churn.abs,history.bugfix_commits", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - assert_eq!(files.len(), 1); - assert_eq!(files[0]["path"].as_str(), Some("sample.py")); - - let metric = |name: &str| -> (f64, f64) { - let m = files[0]["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some(name)) - .unwrap_or_else(|| panic!("missing metric {name}")); - ( - m["current"].as_f64().expect("current"), - m["baseline"].as_f64().expect("baseline"), - ) - }; - - // Head history: 2 commits, 2+2 lines added; base history: 1 commit, - // 2 lines. Only the head commit message matches the bug-fix - // heuristic. - assert_eq!(metric("history.commit_frequency"), (2.0, 1.0)); - assert_eq!(metric("history.churn.abs"), (4.0, 2.0)); - assert_eq!(metric("history.bugfix_commits"), (1.0, 0.0)); -} - -#[test] -fn diff_history_composites_read_na_when_head_is_undecodable() { - // A head side whose static analysis is unavailable (non-UTF-8 - // content) cannot value the static-dependent composites. The keys - // are omitted from its synthetic space — and the diff must report - // them as *unavailable* (no fabricated `hotspot 12 → 0` - // improvement), while plain history metrics keep reading real - // values. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python( - dir.path(), - "sample.py", - "def foo(x):\n if x:\n return 1\n return 2\n", - ); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "na-base"]); - - std::fs::write( - dir.path().join("sample.py"), - b"# caf\xe9\ndef foo(x):\n if x:\n return 1\n return 3\n" as &[u8], - ) - .expect("write undecodable head"); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "na-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "na-base", - "--to", - "na-head", - "--metrics", - "cognitive,history.hotspot,history.churn.relative,history.churn.abs", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - // The undecodable head is recorded as a failed analysis (exit is - // non-zero by design); the JSON payload must still be honest. - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - assert_eq!(files.len(), 1); - let metric = |name: &str| -> serde_json::Value { - files[0]["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some(name)) - .unwrap_or_else(|| panic!("missing metric {name}")) - .clone() - }; - - for name in ["cognitive", "history.hotspot", "history.churn.relative"] { - let m = metric(name); - assert_eq!( - m["current_unavailable"].as_bool(), - Some(true), - "{name} must be flagged unavailable on the undecodable head" - ); - assert_eq!( - m["delta"].as_f64(), - Some(0.0), - "{name} must not claim an improvement from the placeholder" - ); - } - // The parser-independent metric still reads real history values on - // both sides and is not flagged. - let churn_abs = metric("history.churn.abs"); - assert_eq!(churn_abs["current_unavailable"].as_bool(), None); - assert!(churn_abs["current"].as_f64().expect("current") > 0.0); -} - -#[test] -fn diff_reads_history_for_merge_created_zero_touch_files() { - // A blob created purely by merge conflict resolution has no walk - // accumulator (`RepositoryHistory::file` is `None`), but its - // synthesized zero-touch entry carries a real creation-based age - // — the diff must read it via `tracked_file` instead of - // fabricating `history.age_months = 0`. - let dir = tempfile::tempdir().expect("tempdir"); - let date = |n: i64| format!("{} +0000", 1_700_000_000 + n * 100_000); - let git_at = |args: &[&str], n: i64| -> String { - let output = Command::new("git") - .current_dir(dir.path()) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .env("GIT_AUTHOR_DATE", date(n)) - .env("GIT_COMMITTER_DATE", date(n)) - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - String::from_utf8(output.stdout) - .expect("git stdout utf8") - .trim() - .to_string() - }; - git_at(&["init", "-q", "-b", "main"], 0); - git_at(&["config", "commit.gpgsign", "false"], 0); - write_python(dir.path(), "a.py", "x = 1\n"); - git_at(&["add", "-A"], 0); - git_at(&["commit", "-q", "-m", "root"], 0); - let root = git_at(&["rev-parse", "HEAD"], 0); - - git_at(&["checkout", "-q", "-b", "side"], 1); - write_python(dir.path(), "b.py", "y = 1\n"); - git_at(&["add", "-A"], 1); - git_at(&["commit", "-q", "-m", "side"], 1); - let side = git_at(&["rev-parse", "HEAD"], 1); - - // The merge tree carries a file absent from both parents. - write_python(dir.path(), "merge_only.py", "m = 1\n"); - git_at(&["add", "-A"], 2); - let tree = git_at(&["write-tree"], 2); - let merge = git_at( - &[ - "commit-tree", - &tree, - "-p", - &root, - "-p", - &side, - "-m", - "merge with new file", - ], - 2, - ); - // Advance HEAD one commit (100 000 s) past the creating merge - // without touching the merge-created blob. - git_at(&["checkout", "-q", &merge], 3); - git_at(&["checkout", "-q", "-b", "after"], 3); - write_python(dir.path(), "a.py", "x = 1\nz = 2\n"); - git_at(&["commit", "-q", "-am", "later"], 3); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - &root, - "--to", - "HEAD", - "--metrics", - "history.age_months", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let row = value["source_code"] - .as_array() - .expect("source_code must be an array") - .iter() - .find(|f| f["path"].as_str() == Some("merge_only.py")) - .expect("merge-created file must have a row") - .clone(); - let age = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.age_months")) - .expect("age metric present")["current"] - .as_f64() - .expect("current"); - // Creation at t2, HEAD at t3: 100 000 seconds. - let expected = 100_000.0 / (30.436875 * 86_400.0); - assert!( - (age - expected).abs() < 1e-6, - "age must come from the creating merge, got {age}" - ); -} - -#[test] -fn top_offenders_ranks_by_history_metrics() { - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - // busy.py is touched by three commits, calm.py by one. - write_python(dir.path(), "busy.py", "a = 1\n"); - write_python(dir.path(), "calm.py", "b = 1\n"); - commit_all(dir.path(), "initial"); - write_python(dir.path(), "busy.py", "a = 1\na2 = 2\n"); - commit_all(dir.path(), "grow busy"); - write_python(dir.path(), "busy.py", "a = 1\na2 = 2\na3 = 3\n"); - commit_all(dir.path(), "grow busy more"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - assert_eq!(offenders.len(), 2); - // Worst first: busy.py with 3 commits, then calm.py with 1. - assert!( - offenders[0]["path"] - .as_str() - .expect("path") - .ends_with("busy.py") - ); - assert_eq!(offenders[0]["metrics"][0]["value"].as_f64(), Some(3.0)); - assert!( - offenders[1]["path"] - .as_str() - .expect("path") - .ends_with("calm.py") - ); - assert_eq!(offenders[1]["metrics"][0]["value"].as_f64(), Some(1.0)); -} - -#[test] -fn diff_default_columns_include_history_hotspot_and_churn() { - // Research foundation §9.4: the default PR-comment set is - // Cognitive, ABC, MI, Hotspot, Churn — the last two computed from - // the git history walk without any explicit `--metrics`. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python( - dir.path(), - "sample.py", - "def foo(x):\n if x:\n return 1\n return 2\n", - ); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "default-base"]); - - write_python( - dir.path(), - "sample.py", - "def foo(x):\n if x:\n return 1\n if x > 2:\n return 3\n return 2\n", - ); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "default-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "default-base", - "--to", - "default-head", - "--output-format", - "markdown", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let stdout = String::from_utf8(output.stdout).expect("stdout utf8"); - assert!( - stdout.contains("| File | Cognitive | ABC | MI | Hotspot | Churn |"), - "expected the §9.4 default column header, got:\n{stdout}" - ); - assert!(stdout.contains("sample.py"), "row missing:\n{stdout}"); -} - -#[test] -fn top_offenders_discovers_history_from_the_analyzed_paths() { - // `mehen top-offenders -M history.… /path/to/repo` must load - // *that* repository's history even when the process CWD is not - // inside it (or is inside a different repository). - let repo_dir = tempfile::tempdir().expect("repo tempdir"); - init_git_repo(repo_dir.path()); - write_python(repo_dir.path(), "tracked.py", "a = 1\n"); - commit_all(repo_dir.path(), "one"); - write_python(repo_dir.path(), "tracked.py", "a = 1\nb = 2\n"); - commit_all(repo_dir.path(), "two"); - - let elsewhere = tempfile::tempdir().expect("non-repo tempdir"); - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(elsewhere.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - repo_dir.path().to_str().expect("UTF-8 temp path"), - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - assert_eq!(offenders.len(), 1); - assert!( - offenders[0]["path"] - .as_str() - .expect("path") - .ends_with("tracked.py") - ); - assert_eq!(offenders[0]["metrics"][0]["value"].as_f64(), Some(2.0)); -} - -#[test] -fn diff_joins_rename_pairs_and_carries_baseline_history() { - // A renamed file must appear once, compared against its old path's - // metrics and history — not as a deleted row plus a 🆕 row whose - // entire accumulated history shows up as a fresh delta. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "before.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "rename-base"]); - - git_ok(dir.path(), &["mv", "before.py", "after.py"]); - write_python(dir.path(), "after.py", "x = 1\ny = 2\nz = 3\n"); - commit_all(dir.path(), "rename and extend"); - git_ok(dir.path(), &["tag", "rename-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "rename-base", - "--to", - "rename-head", - "--metrics", - "loc.lloc,history.commit_frequency", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - // One joined row for the rename — not before.py deleted + after.py new. - assert_eq!(files.len(), 1, "expected one joined rename row: {files:?}"); - assert_eq!(files[0]["path"].as_str(), Some("after.py")); - assert_eq!(files[0]["is_new"].as_bool(), Some(false)); - assert_eq!(files[0]["is_deleted"].as_bool(), Some(false)); - - let metric = |name: &str| -> (f64, f64) { - let m = files[0]["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some(name)) - .unwrap_or_else(|| panic!("missing metric {name}")); - ( - m["current"].as_f64().expect("current"), - m["baseline"].as_f64().expect("baseline"), - ) - }; - // Static baseline comes from the old path (2 lines → 3 lines). - assert_eq!(metric("loc.lloc"), (3.0, 2.0)); - // History baseline is the old path's history (1 commit → 2 commits, - // with the rename walk carrying identity across the rename). - assert_eq!(metric("history.commit_frequency"), (2.0, 1.0)); -} - -#[test] -fn top_offenders_loads_history_for_every_repository_root() { - // Input roots spanning two repositories must each read their own - // repository's history rather than the first root's. - let repo_a = tempfile::tempdir().expect("repo a"); - init_git_repo(repo_a.path()); - write_python(repo_a.path(), "a.py", "a = 1\n"); - commit_all(repo_a.path(), "one"); - write_python(repo_a.path(), "a.py", "a = 1\nb = 2\n"); - commit_all(repo_a.path(), "two"); - write_python(repo_a.path(), "a.py", "a = 1\nb = 2\nc = 3\n"); - commit_all(repo_a.path(), "three"); - - let repo_b = tempfile::tempdir().expect("repo b"); - init_git_repo(repo_b.path()); - write_python(repo_b.path(), "b.py", "b = 1\n"); - commit_all(repo_b.path(), "only"); - - let elsewhere = tempfile::tempdir().expect("non-repo tempdir"); - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(elsewhere.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - repo_a.path().to_str().expect("UTF-8 temp path"), - repo_b.path().to_str().expect("UTF-8 temp path"), - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - assert_eq!(offenders.len(), 2); - // a.py (3 commits in repo A) ranks above b.py (1 commit in repo B) — - // and b.py reads its own repo's history, not zero. - assert!( - offenders[0]["path"] - .as_str() - .expect("path") - .ends_with("a.py") - ); - assert_eq!(offenders[0]["metrics"][0]["value"].as_f64(), Some(3.0)); - assert!( - offenders[1]["path"] - .as_str() - .expect("path") - .ends_with("b.py") - ); - assert_eq!(offenders[1]["metrics"][0]["value"].as_f64(), Some(1.0)); -} - -#[cfg(unix)] -#[test] -fn top_offenders_does_not_borrow_history_through_symlinks() { - // A tracked symlink `alias.py -> real.py` must keep its own - // (empty) history: canonicalizing the full path would resolve the - // final component and enrich the alias row with the target file's - // churn and commit count. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - write_python(dir.path(), "real.py", "r = 1\n"); - commit_all(dir.path(), "one"); - write_python(dir.path(), "real.py", "r = 1\ns = 2\n"); - commit_all(dir.path(), "two"); - std::os::unix::fs::symlink("real.py", dir.path().join("alias.py")).expect("symlink"); - commit_all(dir.path(), "add alias symlink"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - let by_name = |suffix: &str| -> Option { - offenders - .iter() - .find(|o| o["path"].as_str().expect("path").ends_with(suffix)) - .unwrap_or_else(|| panic!("missing {suffix} in {offenders:?}"))["metrics"][0]["value"] - .as_f64() - }; - // real.py has two content commits; the alias symlink has none of - // them (symlinks are non-blob entries in the history walk) — its - // history is unmeasurable, not zero. - assert_eq!(by_name("real.py"), Some(2.0)); - assert_eq!(by_name("alias.py"), None); -} - -#[test] -fn top_offenders_loads_history_for_nested_repositories() { - // A nested repository discovered *during traversal* (not passed as - // its own root) must read its own history, not zeros from the - // outer repository. - let outer = tempfile::tempdir().expect("outer repo"); - init_git_repo(outer.path()); - write_python(outer.path(), "outer.py", "o = 1\n"); - commit_all(outer.path(), "outer one"); - - let nested_dir = outer.path().join("vendor").join("inner"); - std::fs::create_dir_all(&nested_dir).expect("nested dir"); - init_git_repo(&nested_dir); - write_python(&nested_dir, "inner.py", "i = 1\n"); - commit_all(&nested_dir, "inner one"); - write_python(&nested_dir, "inner.py", "i = 1\nj = 2\n"); - commit_all(&nested_dir, "inner two"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(outer.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - let by_name = |suffix: &str| -> f64 { - offenders - .iter() - .find(|o| o["path"].as_str().expect("path").ends_with(suffix)) - .unwrap_or_else(|| panic!("missing {suffix} in {offenders:?}"))["metrics"][0]["value"] - .as_f64() - .expect("value") - }; - // inner.py reads the nested repository's 2 commits (outer sees it - // as untracked); outer.py reads its own single commit. - assert_eq!(by_name("inner.py"), 2.0); - assert_eq!(by_name("outer.py"), 1.0); -} - -#[cfg(unix)] -#[test] -fn top_offenders_follows_directory_symlink_roots() { - // `mehen top-offenders -M history.… /outside/link-to-repo` where - // the link's parent is not a repository must discover the target - // repository instead of failing with RepoNotFound. - let repo_dir = tempfile::tempdir().expect("repo tempdir"); - init_git_repo(repo_dir.path()); - write_python(repo_dir.path(), "linked.py", "a = 1\n"); - commit_all(repo_dir.path(), "one"); - write_python(repo_dir.path(), "linked.py", "a = 1\nb = 2\n"); - commit_all(repo_dir.path(), "two"); - - let outside = tempfile::tempdir().expect("non-repo tempdir"); - let link = outside.path().join("link-to-repo"); - std::os::unix::fs::symlink(repo_dir.path(), &link).expect("dir symlink"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(outside.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - link.to_str().expect("UTF-8 temp path"), - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - assert_eq!(offenders.len(), 1); - assert_eq!(offenders[0]["metrics"][0]["value"].as_f64(), Some(2.0)); -} - -#[test] -fn cross_language_rename_to_markdown_keeps_deletion_history() { - // `a.py → a.md` splits into a deletion + addition, and the - // Markdown destination is routed to the documentation pipeline, - // which carries no history columns. The Python deletion row must - // therefore keep its baseline history — suppressing it too (as - // for a split whose destination stays in the source-code - // pipeline) would erase the lineage from the output entirely. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "a.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "base"); - write_python(dir.path(), "a.py", "x = 1\ny = 2\nz = 3\n"); - commit_all(dir.path(), "grow"); - git_ok(dir.path(), &["tag", "md-base"]); - - git_ok(dir.path(), &["mv", "a.py", "a.md"]); - commit_all(dir.path(), "convert to markdown"); - git_ok(dir.path(), &["tag", "md-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "md-base", - "--to", - "md-head", - "--metrics", - "history.commit_frequency", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.py")) - .unwrap_or_else(|| panic!("a.py deletion row must survive: {files:?}")); - assert_eq!(row["is_deleted"].as_bool(), Some(true)); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.commit_frequency")) - .expect("history.commit_frequency must be present"); - // Two commits touched a.py before the conversion. - assert_eq!(metric["baseline"].as_f64(), Some(2.0)); - assert_eq!(metric["current"].as_f64(), Some(0.0)); -} - -#[test] -fn cross_language_rename_to_sql_keeps_deletion_history_under_defaults() { - // `a.py → a.sql` splits, and the SQL destination *stays* in the - // source-code pipeline — but under default metrics SQL's - // selectors are history-free, so the destination reads no history - // columns. The Python deletion row must keep its baseline history - // or the lineage vanishes from the default report. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "a.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "base"); - write_python(dir.path(), "a.py", "x = 1\ny = 2\nz = 3\n"); - commit_all(dir.path(), "grow"); - git_ok(dir.path(), &["tag", "sql-base"]); - - git_ok(dir.path(), &["mv", "a.py", "a.sql"]); - commit_all(dir.path(), "convert to sql"); - git_ok(dir.path(), &["tag", "sql-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "sql-base", - "--to", - "sql-head", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.py")) - .unwrap_or_else(|| panic!("a.py deletion row must survive: {files:?}")); - assert_eq!(row["is_deleted"].as_bool(), Some(true)); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.churn.relative")) - .unwrap_or_else(|| panic!("history.churn.relative must be present: {row:?}")); - // a.py churned lines across two commits before the conversion — - // the baseline history must not be suppressed. - let baseline = metric["baseline"].as_f64().expect("baseline"); - assert!(baseline > 0.0, "baseline history suppressed: {metric:?}"); -} - -#[test] -fn modified_then_reverted_files_report_history_deltas() { - // The endpoint trees are identical for a.py (modified in one - // range commit, reverted in the next), so the endpoint diff has - // no row — but the head history gained two commits and churn. - // With history selectors active the file must appear. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "a.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "revert-base"]); - - write_python(dir.path(), "a.py", "x = 1\ny = 2\nz = 3\n"); - commit_all(dir.path(), "grow"); - write_python(dir.path(), "a.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "revert"); - git_ok(dir.path(), &["tag", "revert-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "revert-base", - "--to", - "revert-head", - "--metrics", - "history.commit_frequency", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.py")) - .unwrap_or_else(|| panic!("reverted file must appear: {files:?}")); - assert_eq!(row["is_new"].as_bool(), Some(false)); - assert_eq!(row["is_deleted"].as_bool(), Some(false)); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.commit_frequency")) - .expect("history.commit_frequency must be present"); - assert_eq!(metric["baseline"].as_f64(), Some(1.0)); - assert_eq!(metric["current"].as_f64(), Some(3.0)); -} - -#[test] -fn non_utf8_content_still_reports_history_metrics() { - // Static analysis rejects non-UTF-8 (non-binary) content, but - // history metrics don't depend on decoding the blob: an explicit - // history selector must read real values, not zeros. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - // Latin-1 content: 0xE9 is invalid UTF-8 but contains no NUL. - std::fs::write(dir.path().join("a.py"), b"# caf\xe9\nx = 1\n").unwrap(); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "latin-base"]); - - std::fs::write(dir.path().join("a.py"), b"# caf\xe9\nx = 1\ny = 2\n").unwrap(); - commit_all(dir.path(), "grow"); - git_ok(dir.path(), &["tag", "latin-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "latin-base", - "--to", - "latin-head", - "--metrics", - "history.commit_frequency", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.py")) - .unwrap_or_else(|| panic!("non-UTF-8 file must appear: {files:?}")); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.commit_frequency")) - .expect("history.commit_frequency must be present"); - assert_eq!(metric["baseline"].as_f64(), Some(1.0)); - assert_eq!(metric["current"].as_f64(), Some(2.0)); -} - -#[test] -fn authoritative_empty_push_payloads_suppress_history_augmentation() { - // A branch created at an existing commit: the payload's commit - // fold is authoritatively empty, but resolve_refs falls back to - // HEAD~1..HEAD. The history range augmentation must not - // repopulate the report with the tip's previous commit. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "old.py", "x = 1\n"); - commit_all(dir.path(), "one"); - write_python(dir.path(), "newer.py", "y = 2\n"); - commit_all(dir.path(), "two"); - - let event = dir.path().join("event.json"); - std::fs::write( - &event, - serde_json::json!({ - "before": "0000000000000000000000000000000000000000", - "size": 0, - "commits": [] - }) - .to_string(), - ) - .unwrap(); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args(["diff", "--output-format", "json"]) - .env("GITHUB_ACTIONS", "true") - .env("GITHUB_EVENT_NAME", "push") - .env("GITHUB_EVENT_PATH", &event) - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - assert!( - files.is_empty(), - "an authoritatively-empty push must stay empty: {files:?}" - ); -} - -#[test] -fn history_diffs_support_annotated_tags() { - // Annotated tag objects must be peeled before the range walk — - // endpoint diffing and the history walks already peel them. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "a.py", "x = 1\n"); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "-a", "-m", "release base", "ann-base"]); - write_python(dir.path(), "a.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "grow"); - git_ok(dir.path(), &["tag", "-a", "-m", "release head", "ann-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "ann-base", - "--to", - "ann-head", - "--metrics", - "history.commit_frequency", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.py")) - .unwrap_or_else(|| panic!("a.py must appear: {files:?}")); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.commit_frequency")) - .expect("history.commit_frequency must be present"); - assert_eq!(metric["baseline"].as_f64(), Some(1.0)); - assert_eq!(metric["current"].as_f64(), Some(2.0)); -} - -#[test] -fn reversed_ranges_report_history_decreases() { - // The touched-path augmentation must walk both sides of the - // range: comparing back from a tip whose extra commits modified - // and restored a file leaves identical endpoint trees, but the - // *baseline* history is richer and the decrease must be visible. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "a.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "rev-old"]); - - write_python(dir.path(), "a.py", "x = 1\ny = 2\nz = 3\n"); - commit_all(dir.path(), "grow"); - write_python(dir.path(), "a.py", "x = 1\ny = 2\n"); - commit_all(dir.path(), "revert"); - git_ok(dir.path(), &["tag", "rev-new"]); - - // Reversed: from the newer tag back to the older one. - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "rev-new", - "--to", - "rev-old", - "--metrics", - "history.commit_frequency", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.py")) - .unwrap_or_else(|| panic!("from-side-only history must surface: {files:?}")); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.commit_frequency")) - .expect("history.commit_frequency must be present"); - assert_eq!(metric["baseline"].as_f64(), Some(3.0)); - assert_eq!(metric["current"].as_f64(), Some(1.0)); -} - -#[test] -fn restored_markdown_stays_out_of_history_augmentation() { - // Markdown routes to the documentation pipeline, which reads no - // history selectors and applies no unchanged-row filter: a - // modified-then-restored README must not be resurrected by the - // history augmentation under default metrics. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - std::fs::write(dir.path().join("README.md"), "# Title\n\nStable body.\n").unwrap(); - write_python(dir.path(), "code.py", "x = 1\n"); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "md-rev-base"]); - - std::fs::write(dir.path().join("README.md"), "# Title\n\nTemporary body.\n").unwrap(); - commit_all(dir.path(), "touch readme"); - std::fs::write(dir.path().join("README.md"), "# Title\n\nStable body.\n").unwrap(); - commit_all(dir.path(), "restore readme"); - git_ok(dir.path(), &["tag", "md-rev-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "md-rev-base", - "--to", - "md-rev-head", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - output.status.success(), - "diff failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - if let Some(docs) = value.get("markdown").and_then(|d| d.as_array()) { - assert!( - !docs.iter().any(|f| f["path"].as_str() == Some("README.md")), - "an unchanged document must not be reported: {docs:?}" - ); - } - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - assert!( - !files - .iter() - .any(|f| f["path"].as_str() == Some("README.md")), - "markdown must not enter the source-code table: {files:?}" - ); -} - -#[test] -fn top_offenders_rank_non_utf8_files_on_history() { - // Static analysis cannot decode the Latin-1 file, but its - // repository history is real — a history selector must rank it - // instead of silently dropping it. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\n").unwrap(); - write_python(dir.path(), "plain.py", "y = 1\n"); - commit_all(dir.path(), "base"); - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\nz = 2\n").unwrap(); - commit_all(dir.path(), "grow latin"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - // latin.py leads with 2 commits; plain.py has 1. - assert_eq!(offenders.len(), 2, "non-UTF-8 file dropped: {offenders:?}"); - assert!( - offenders[0]["path"] - .as_str() - .expect("path") - .ends_with("latin.py") - ); - assert_eq!(offenders[0]["metrics"][0]["value"].as_f64(), Some(2.0)); -} - -#[test] -fn split_rename_history_composites_use_source_static_inputs() { - // Cross-language rename: the destination row's baseline hotspot - // must be cognitive.sum(source) × commit_frequency(source), not - // zero — otherwise the whole current hotspot masquerades as new. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - // Python with cognitive complexity 1 (one `if`). - let py = "def f(x):\n if x:\n return 1\n return 0\n"; - write_python(dir.path(), "a.py", py); - commit_all(dir.path(), "base"); - write_python( - dir.path(), - "a.py", - "def f(x):\n if x:\n return 1\n return 0\n\n\ndef g():\n return 2\n", - ); - commit_all(dir.path(), "grow"); - git_ok(dir.path(), &["tag", "split-base"]); - - git_ok(dir.path(), &["mv", "a.py", "a.rs"]); - commit_all(dir.path(), "cross-language move"); - git_ok(dir.path(), &["tag", "split-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "split-base", - "--to", - "split-head", - "--metrics", - "cognitive,history.hotspot", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - - // The Rust analyzer may reject the moved Python text (that is the - // point of a cross-language split) — assert on the report itself, - // not the exit code. - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.rs")) - .unwrap_or_else(|| panic!("split destination row must exist: {files:?}")); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.hotspot")) - .expect("history.hotspot must be present"); - // Source lineage at split-base: cognitive.sum = 1, two commits. - assert_eq!( - metric["baseline"].as_f64(), - Some(2.0), - "baseline hotspot must use the source's static inputs: {metric:?}" - ); - // The staged composite inputs must not leak into displayed static - // selectors: the new row's cognitive baseline stays 0 (the paired - // deletion row already carries the source's static baseline, and - // leaking here would double-count it). - let cognitive = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("cognitive")) - .expect("cognitive must be present"); - assert_eq!( - cognitive["baseline"].as_f64(), - Some(0.0), - "composite inputs leaked into displayed selectors: {cognitive:?}" - ); - let deletion = files - .iter() - .find(|f| f["path"].as_str() == Some("a.py")) - .expect("deletion row must exist"); - let deletion_cognitive = deletion["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("cognitive")) - .expect("cognitive must be present"); - assert_eq!(deletion_cognitive["baseline"].as_f64(), Some(1.0)); -} - -#[test] -fn top_offenders_history_supports_container_roots() { - // The root itself is not inside Git but contains a repository: - // per-file lazy discovery must resolve the nested repository - // instead of the eager root check failing the whole run. - let outer = tempfile::tempdir().expect("tempdir"); - let proj = outer.path().join("proj"); - std::fs::create_dir(&proj).unwrap(); - init_git_repo(&proj); - - write_python(&proj, "tracked.py", "x = 1\n"); - commit_all(&proj, "one"); - write_python(&proj, "tracked.py", "x = 1\ny = 2\n"); - commit_all(&proj, "two"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(outer.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "container root must not fail: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - assert_eq!(offenders.len(), 1, "{offenders:?}"); - assert!( - offenders[0]["path"] - .as_str() - .expect("path") - .ends_with("tracked.py") - ); - assert_eq!(offenders[0]["metrics"][0]["value"].as_f64(), Some(2.0)); -} - -#[test] -fn untracked_files_do_not_inherit_dead_occupant_history() { - // HEAD deleted the tracked file; an untracked workspace file now - // occupies the path. Ranking must not assign it the dead - // occupant's commits. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "ghost.py", "x = 1\n"); - write_python(dir.path(), "alive.py", "y = 1\n"); - commit_all(dir.path(), "base"); - write_python(dir.path(), "ghost.py", "x = 1\nx2 = 2\n"); - commit_all(dir.path(), "grow ghost"); - git_ok(dir.path(), &["rm", "-q", "ghost.py"]); - commit_all(dir.path(), "drop ghost"); - - // An untracked file re-occupies the path in the workspace only. - write_python(dir.path(), "ghost.py", "unrelated = 1\n"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - let ghost = offenders - .iter() - .find(|o| o["path"].as_str().expect("path").ends_with("ghost.py")) - .expect("untracked file is still ranked"); - assert!( - ghost["metrics"][0]["value"].is_null(), - "an untracked path has no measurable history — it must read null \ - (and never the dead occupant's commits): {ghost:?}" - ); -} - -#[test] -fn top_offenders_rank_unparsable_files_on_history_only() { - // A file with blocking parse errors has incomplete static metrics; - // ranking must fall back to history-only (empty static space) - // instead of feeding partial cognitive/SLOC values into the - // history composites. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "broken.py", "def broken(:\n"); - write_python(dir.path(), "fine.py", "y = 1\n"); - commit_all(dir.path(), "base"); - write_python(dir.path(), "broken.py", "def broken(:\n# more\n"); - commit_all(dir.path(), "grow broken"); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "top-offenders", - "-M", - "history.commit_frequency", - "--output-format", - "json", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - assert!( - output.status.success(), - "top-offenders failed: stderr={}", - String::from_utf8_lossy(&output.stderr) - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("top-offenders output must be JSON"); - let offenders = value.as_array().expect("offender array"); - assert_eq!(offenders.len(), 2, "{offenders:?}"); - assert!( - offenders[0]["path"] - .as_str() - .expect("path") - .ends_with("broken.py") - ); - assert_eq!(offenders[0]["metrics"][0]["value"].as_f64(), Some(2.0)); -} - -#[test] -fn diff_reports_history_only_for_unparsable_files() { - // A malformed head file has no trustworthy static metrics: the - // row must show zeros for statics (not partial values blended - // into history composites) while history reads real values. The - // run still exits non-zero for the blocking diagnostics. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - write_python(dir.path(), "broken.py", "x = 1\n"); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "broken-cli-base"]); - write_python(dir.path(), "broken.py", "def broken(:\n"); - commit_all(dir.path(), "break it"); - git_ok(dir.path(), &["tag", "broken-cli-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "broken-cli-base", - "--to", - "broken-cli-head", - "--metrics", - "cognitive,history.commit_frequency,history.churn.relative", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - !output.status.success(), - "blocking diagnostics must fail the run" - ); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("broken.py")) - .unwrap_or_else(|| panic!("broken.py must appear: {files:?}")); - let metric = |name: &str| { - row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some(name)) - .unwrap_or_else(|| panic!("missing metric {name}")) - .clone() - }; - // History is real; the partial static root was rejected. - assert_eq!( - metric("history.commit_frequency")["current"].as_f64(), - Some(2.0) - ); - assert_eq!(metric("cognitive")["current"].as_f64(), Some(0.0)); - // Static-dependent composites are omitted on the synthetic side: - // relative churn must not read absolute churn divided by 1. - assert_eq!( - metric("history.churn.relative")["current"].as_f64(), - Some(0.0) - ); -} - -#[test] -fn split_rename_baselines_reject_blocked_source_analyses() { - // The split-rename baseline staging re-analyzes the *source* blob - // for composite inputs; a source with blocking parse errors must - // stage nothing (baseline hotspot 0) instead of partial - // cognitive/SLOC values. - let dir = tempfile::tempdir().expect("tempdir"); - init_git_repo(dir.path()); - - // Parseable prefix (cognitive 1) followed by a syntax error: a - // partial tree would report non-zero composite inputs. - let broken = "def f(x):\n if x:\n return 1\n return 0\n\n\ndef broken(:\n"; - write_python(dir.path(), "a.py", broken); - commit_all(dir.path(), "base"); - write_python( - dir.path(), - "a.py", - "def f(x):\n if x:\n return 1\n return 0\n\n\ndef broken(:\n# more\n", - ); - commit_all(dir.path(), "grow"); - git_ok(dir.path(), &["tag", "blocked-split-base"]); - - git_ok(dir.path(), &["mv", "a.py", "a.rs"]); - commit_all(dir.path(), "cross-language move"); - git_ok(dir.path(), &["tag", "blocked-split-head"]); - - let output = Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "blocked-split-base", - "--to", - "blocked-split-head", - "--metrics", - "history.commit_frequency,history.hotspot", - "--output-format", - "json", - ]) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("diff output must be JSON"); - let files = value["source_code"] - .as_array() - .expect("source_code must be an array"); - let row = files - .iter() - .find(|f| f["path"].as_str() == Some("a.rs")) - .unwrap_or_else(|| panic!("split destination row must exist: {files:?}")); - let metric = row["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("history.hotspot")) - .expect("history.hotspot must be present"); - assert_eq!( - metric["baseline"].as_f64(), - Some(0.0), - "partial source statics staged into the synthetic baseline: {metric:?}" - ); -} diff --git a/crates/mehen-cli/tests/config_thresholds.rs b/crates/mehen-cli/tests/config_thresholds.rs deleted file mode 100644 index 1d257c23..00000000 --- a/crates/mehen-cli/tests/config_thresholds.rs +++ /dev/null @@ -1,577 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Integration tests for `mehen.toml` metric thresholds. -//! -//! The configuration contract: per-metric limits in `[thresholds]`, -//! per-language overrides in `[languages..thresholds]`; every -//! command that reports a configured metric exits 1 when a limit is -//! crossed, after a grouped violation report on stderr. - -use std::process::Command; - -/// A Python body with cognitive complexity 3 and `loc.lloc` 4. -const COMPLEX_PY: &str = - "def foo(x):\n if x:\n if x > 1:\n return 1\n return 2\n"; -/// A Python body with cognitive complexity 0 and `loc.lloc` 1. -const SIMPLE_PY: &str = "def foo():\n return 1\n"; - -fn write_file(dir: &std::path::Path, name: &str, body: &str) -> std::path::PathBuf { - let path = dir.join(name); - std::fs::write(&path, body).expect("write test file"); - path -} - -fn mehen() -> Command { - let mut command = Command::new(env!("CARGO_BIN_EXE_mehen")); - // Diff derives refs from CI context when present; tests must not - // inherit a real Actions environment. - command - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY"); - command -} - -fn git_ok(path: &std::path::Path, args: &[&str]) { - let output = Command::new("git") - .current_dir(path) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); -} - -fn stderr_of(output: &std::process::Output) -> String { - String::from_utf8_lossy(&output.stderr).into_owned() -} - -#[test] -fn metrics_exits_one_on_threshold_violation_with_grouped_report() { - let dir = tempfile::tempdir().expect("tempdir"); - write_file( - dir.path(), - "mehen.toml", - "[thresholds]\ncognitive = 2\nloc.lloc = 3\n", - ); - let file = write_file(dir.path(), "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert_eq!(output.status.code(), Some(1)); - let stderr = stderr_of(&output); - assert!( - stderr.contains("2 metric threshold violations"), - "stderr must summarize the violation count: {stderr}" - ); - assert!( - stderr.contains("cognitive = 3 — exceeds max 2 (set by thresholds)"), - "stderr must name value, limit, and config path: {stderr}" - ); - assert!( - stderr.contains("loc.lloc = 4 — exceeds max 3 (set by thresholds)"), - "stderr must report every crossed metric: {stderr}" - ); - assert!( - stderr.contains("help:"), - "stderr must carry the actionable help line: {stderr}" - ); - // The JSON report still lands on stdout before the gate fails. - let parsed: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("stdout must remain valid JSON"); - assert_eq!(parsed["language"].as_str(), Some("python")); -} - -#[test] -fn metrics_succeeds_when_within_thresholds() { - let dir = tempfile::tempdir().expect("tempdir"); - write_file( - dir.path(), - "mehen.toml", - "[thresholds]\ncognitive = 50\nloc.lloc = 50\n", - ); - let file = write_file(dir.path(), "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert!( - output.status.success(), - "within-limit run must pass: {}", - stderr_of(&output) - ); -} - -#[test] -fn metrics_language_override_wins_and_is_named_in_report() { - let dir = tempfile::tempdir().expect("tempdir"); - // Global limit passes (50); the Python override (1) is crossed. - write_file( - dir.path(), - "mehen.toml", - "[thresholds]\ncognitive = 50\n\n[languages.python.thresholds]\ncognitive = 1\n", - ); - let file = write_file(dir.path(), "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert_eq!(output.status.code(), Some(1)); - let stderr = stderr_of(&output); - assert!( - stderr.contains("cognitive = 3 — exceeds max 1 (set by languages.python.thresholds)"), - "the override limit and its config path must be reported: {stderr}" - ); -} - -#[test] -fn missing_explicit_config_fails_with_path_in_message() { - let dir = tempfile::tempdir().expect("tempdir"); - let file = write_file(dir.path(), "sample.py", SIMPLE_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["--config", "absent.toml", "metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert_eq!(output.status.code(), Some(1)); - let stderr = stderr_of(&output); - assert!( - stderr.contains("config file not found") && stderr.contains("absent.toml"), - "an explicit --config must fail loudly: {stderr}" - ); - assert!( - output.stdout.is_empty(), - "a missing requested config must fail before any analysis output" - ); -} - -#[test] -fn metrics_language_override_does_not_affect_other_languages() { - let dir = tempfile::tempdir().expect("tempdir"); - // Only Python is limited; an equally complex Rust file passes. - write_file( - dir.path(), - "mehen.toml", - "[languages.python.thresholds]\ncognitive = 1\n", - ); - let file = write_file( - dir.path(), - "sample.rs", - "fn foo(x: i32) -> i32 {\n if x > 0 {\n if x > 1 {\n return 1;\n }\n }\n 2\n}\n", - ); - - let output = mehen() - .current_dir(dir.path()) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert!( - output.status.success(), - "a python-only override must not gate rust files: {}", - stderr_of(&output) - ); -} - -#[test] -fn metrics_without_config_is_unchanged() { - let dir = tempfile::tempdir().expect("tempdir"); - let file = write_file(dir.path(), "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert!(output.status.success()); - assert!( - !stderr_of(&output).contains("threshold"), - "no config means no threshold machinery in the output" - ); -} - -#[test] -fn explicit_config_flag_bypasses_discovery() { - let dir = tempfile::tempdir().expect("tempdir"); - // The discoverable config passes; the explicit one fails. - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 50\n"); - let strict = write_file(dir.path(), "strict.toml", "[thresholds]\ncognitive = 1\n"); - let file = write_file(dir.path(), "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args([ - "--config", - strict.to_str().unwrap(), - "metrics", - file.to_str().unwrap(), - ]) - .output() - .expect("failed to run mehen metrics"); - - assert_eq!(output.status.code(), Some(1)); - assert!( - stderr_of(&output).contains("strict.toml"), - "the report must point at the explicitly selected config" - ); -} - -#[test] -fn config_is_discovered_from_parent_directory() { - let dir = tempfile::tempdir().expect("tempdir"); - // Discovery walks upward within the enclosing git repository. - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 1\n"); - let nested = dir.path().join("src/deep"); - std::fs::create_dir_all(&nested).expect("mkdirs"); - let file = write_file(&nested, "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(&nested) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert_eq!( - output.status.code(), - Some(1), - "a repo-root mehen.toml must apply: {}", - stderr_of(&output) - ); -} - -#[test] -fn config_above_the_repository_root_is_ignored() { - // outer/mehen.toml sits above the repository at outer/repo — it - // cannot belong to the project, so the run stays ungated. - let dir = tempfile::tempdir().expect("tempdir"); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 1\n"); - let repo = dir.path().join("repo"); - std::fs::create_dir_all(&repo).expect("mkdirs"); - git_ok(&repo, &["init", "-q", "-b", "main"]); - let file = write_file(&repo, "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(&repo) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert!( - output.status.success(), - "a config outside the repository must not gate the run: {}", - stderr_of(&output) - ); -} - -#[test] -fn malformed_config_fails_with_actionable_suggestion() { - let dir = tempfile::tempdir().expect("tempdir"); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitve = 5\n"); - let file = write_file(dir.path(), "sample.py", SIMPLE_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert_eq!(output.status.code(), Some(1)); - let stderr = stderr_of(&output); - assert!( - stderr.contains("unknown metric `cognitve`"), - "typos must fail at load time: {stderr}" - ); - assert!( - stderr.contains("did you mean `cognitive`?"), - "typos should carry a suggestion: {stderr}" - ); - assert!( - output.stdout.is_empty(), - "a broken config must fail before any analysis output" - ); -} - -#[test] -fn invalid_config_syntax_fails_cleanly() { - let dir = tempfile::tempdir().expect("tempdir"); - write_file(dir.path(), "mehen.toml", "[thresholds\ncognitive = 5\n"); - let file = write_file(dir.path(), "sample.py", SIMPLE_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["metrics", file.to_str().unwrap()]) - .output() - .expect("failed to run mehen metrics"); - - assert_eq!(output.status.code(), Some(1)); - assert!( - stderr_of(&output).contains("invalid TOML"), - "syntax errors must name the file and the problem: {}", - stderr_of(&output) - ); -} - -#[test] -fn top_offenders_reports_violations_beyond_max_results_and_exits_one() { - let dir = tempfile::tempdir().expect("tempdir"); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 1\n"); - write_file(dir.path(), "aaa.py", COMPLEX_PY); - write_file(dir.path(), "bbb.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args([ - "top-offenders", - "-M", - "cognitive", - "--max-results", - "1", - ".", - ]) - .output() - .expect("failed to run mehen top-offenders"); - - assert_eq!(output.status.code(), Some(1)); - let stdout = String::from_utf8_lossy(&output.stdout); - // The ranking table respects --max-results… - assert!(stdout.contains("aaa.py")); - assert!(!stdout.contains("bbb.py")); - // …but the violation report covers every analyzed file, so a - // breach cannot hide below the cut. - let stderr = stderr_of(&output); - assert!( - stderr.contains("aaa.py") && stderr.contains("bbb.py"), - "all violating files must be reported: {stderr}" - ); -} - -#[test] -fn top_offenders_ignores_thresholds_for_unselected_metrics() { - let dir = tempfile::tempdir().expect("tempdir"); - // The limit targets loc.lloc, but the ranking only reports - // cognitive — thresholds gate the metrics a command outputs. - write_file(dir.path(), "mehen.toml", "[thresholds]\n\"loc.lloc\" = 1\n"); - write_file(dir.path(), "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["top-offenders", "-M", "cognitive", "."]) - .output() - .expect("failed to run mehen top-offenders"); - - assert!( - output.status.success(), - "unselected metrics must not gate the run: {}", - stderr_of(&output) - ); -} - -#[test] -fn top_offenders_gates_published_aggregate_selectors() { - let dir = tempfile::tempdir().expect("tempdir"); - // `cognitive.max` is a published aggregate key: configurable as a - // threshold and selectable as a ranking column, so the gate fires. - write_file( - dir.path(), - "mehen.toml", - "[thresholds]\n\"cognitive.max\" = 1\n", - ); - write_file(dir.path(), "sample.py", COMPLEX_PY); - - let output = mehen() - .current_dir(dir.path()) - .args(["top-offenders", "-M", "cognitive.max", "."]) - .output() - .expect("failed to run mehen top-offenders"); - - assert_eq!(output.status.code(), Some(1)); - let stderr = stderr_of(&output); - assert!( - stderr.contains("cognitive.max = 3 — exceeds max 1"), - "aggregate selectors must be gated: {stderr}" - ); -} - -#[test] -fn diff_exits_one_when_head_side_crosses_threshold() { - let dir = tempfile::tempdir().expect("tempdir"); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - write_file(dir.path(), "sample.py", SIMPLE_PY); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - write_file(dir.path(), "sample.py", COMPLEX_PY); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 1\n"); - - let output = mehen() - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "HEAD~1", - "--to", - "HEAD", - "--metrics", - "cognitive", - ]) - .output() - .expect("failed to run mehen diff"); - - assert_eq!(output.status.code(), Some(1)); - let stderr = stderr_of(&output); - assert!( - stderr.contains("sample.py") && stderr.contains("exceeds max 1"), - "diff must report the head-side breach: {stderr}" - ); - // The summary table still prints before the gate fails. - assert!(String::from_utf8_lossy(&output.stdout).contains("sample.py")); -} - -#[test] -fn diff_passes_when_head_within_thresholds() { - let dir = tempfile::tempdir().expect("tempdir"); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - write_file(dir.path(), "sample.py", SIMPLE_PY); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - write_file(dir.path(), "sample.py", COMPLEX_PY); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 100\n"); - - let output = mehen() - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "HEAD~1", - "--to", - "HEAD", - "--metrics", - "cognitive", - ]) - .output() - .expect("failed to run mehen diff"); - - assert!( - output.status.success(), - "within-limit diff must pass: {}", - stderr_of(&output) - ); -} - -#[test] -fn diff_analysis_failure_outranks_the_threshold_gate() { - // One file crosses the threshold, another has a hard syntax error: - // the run must fail as an analysis failure — JSON without the - // machine-readable gate signal — so CI consumers do not publish a - // partial report as an ordinary gate failure. - let dir = tempfile::tempdir().expect("tempdir"); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - write_file(dir.path(), "sample.py", SIMPLE_PY); - write_file(dir.path(), "broken.py", "def ok():\n return 1\n"); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - write_file(dir.path(), "sample.py", COMPLEX_PY); - write_file(dir.path(), "broken.py", "def broken(:\n return 1\n"); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 1\n"); - - let output = mehen() - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "HEAD~1", - "--to", - "HEAD", - "--metrics", - "cognitive", - "--output-format", - "json", - ]) - .output() - .expect("failed to run mehen diff"); - - assert_eq!(output.status.code(), Some(1)); - let value: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("JSON still emitted"); - assert!( - value.get("threshold_violations").is_none(), - "an analysis failure must withhold the gate signal: {value}" - ); -} - -#[test] -fn diff_json_output_still_emitted_before_threshold_failure() { - let dir = tempfile::tempdir().expect("tempdir"); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - write_file(dir.path(), "sample.py", SIMPLE_PY); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - write_file(dir.path(), "sample.py", COMPLEX_PY); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - write_file(dir.path(), "mehen.toml", "[thresholds]\ncognitive = 1\n"); - - let output = mehen() - .current_dir(dir.path()) - .args([ - "diff", - "--from", - "HEAD~1", - "--to", - "HEAD", - "--metrics", - "cognitive", - "--output-format", - "json", - ]) - .output() - .expect("failed to run mehen diff"); - - assert_eq!(output.status.code(), Some(1)); - let value: serde_json::Value = serde_json::from_slice(&output.stdout) - .expect("machine output must stay parseable when the gate fails"); - assert!(value["source_code"].is_array()); - // The explicit gate signal machine consumers (e.g. the GitHub - // Action) use to distinguish a quality-gate exit from an analysis - // failure, which also exits 1 but without this key. - let violations = value["threshold_violations"] - .as_array() - .expect("gate failures must carry threshold_violations"); - assert_eq!(violations.len(), 1); - assert_eq!(violations[0]["metric"].as_str(), Some("cognitive")); - assert_eq!(violations[0]["path"].as_str(), Some("sample.py")); - assert_eq!(violations[0]["limit"].as_f64(), Some(1.0)); -} diff --git a/crates/mehen-cli/tests/coverage_cli.rs b/crates/mehen-cli/tests/coverage_cli.rs deleted file mode 100644 index 55055686..00000000 --- a/crates/mehen-cli/tests/coverage_cli.rs +++ /dev/null @@ -1,955 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! End-to-end CLI tests for the `coverage.*` category: `--coverage` -//! flag semantics on `mehen metrics` and `mehen top-offenders`, -//! auto-discovery inside gitignored directories, `[coverage]` config -//! handling, and coverage thresholds. - -use std::process::Command; - -const PYTHON_BODY: &str = "def hit(flag):\n if flag:\n return 1\n return 2\n\n\ndef missed():\n return 3\n"; - -/// LCOV describing `app.py`: `hit` executed (lines 1–4, line 3 missed), -/// `missed` never executed. 4 of 6 instrumented lines hit; one of two -/// branch arms taken; one of two functions executed. -const LCOV: &str = "TN:\nSF:app.py\nFN:1,hit\nFN:7,missed\nFNDA:5,hit\nFNDA:0,missed\nDA:1,5\nDA:2,5\nDA:3,0\nDA:4,5\nDA:7,1\nDA:8,0\nBRDA:2,0,0,5\nBRDA:2,0,1,0\nend_of_record\n"; - -fn write(dir: &std::path::Path, name: &str, body: &str) { - let path = dir.join(name); - std::fs::create_dir_all(path.parent().unwrap()).unwrap(); - std::fs::write(path, body).unwrap(); -} - -fn mehen(dir: &std::path::Path, args: &[&str]) -> std::process::Output { - Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir) - .args(args) - .output() - .expect("failed to run mehen") -} - -fn json_stdout(output: &std::process::Output) -> serde_json::Value { - assert!( - output.status.success(), - "mehen failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - serde_json::from_slice(&output.stdout).expect("stdout is JSON") -} - -#[test] -fn metrics_with_explicit_coverage_report_publishes_the_family() { - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "app.py", PYTHON_BODY); - write(dir.path(), "lcov.info", LCOV); - - let output = mehen(dir.path(), &["metrics", "app.py", "--coverage=lcov.info"]); - let json = json_stdout(&output); - - let coverage = &json["metrics"]["coverage"]; - assert_eq!(coverage["line"]["covered"], 4, "{coverage}"); - assert_eq!(coverage["line"]["total"], 6); - assert!((coverage["line"]["percent"].as_f64().unwrap() - 400.0 / 6.0).abs() < 1e-9); - assert_eq!(coverage["branch"]["covered"], 1); - assert_eq!(coverage["branch"]["total"], 2); - assert_eq!(coverage["function"]["covered"], 1); - assert_eq!(coverage["function"]["total"], 2); - - // Per-function injection: the root space tree carries span-scoped - // line coverage on each function space (the CRAP input). - let spaces = json["root"]["spaces"].as_array().expect("spaces"); - let function_coverage: Vec<(String, f64)> = spaces - .iter() - .filter(|s| s["kind"] == "function") - .map(|s| { - ( - s["name"].as_str().unwrap_or_default().to_string(), - s["metrics"]["coverage.line"].as_f64().unwrap_or(-1.0), - ) - }) - .collect(); - assert!( - function_coverage.contains(&("hit".to_string(), 75.0)), - "hit spans lines 1..=4: 3 of 4 hit → 75%; got {function_coverage:?}" - ); - assert!( - function_coverage.contains(&("missed".to_string(), 50.0)), - "missed spans lines 7..=8: the `def` line executes at import \ - (DA:7,1) while the body never runs (DA:8,0) → 50%; got {function_coverage:?}" - ); -} - -#[test] -fn metrics_without_coverage_omits_the_family() { - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "app.py", PYTHON_BODY); - write(dir.path(), "lcov.info", LCOV); - - // No flag, no config, no threshold: coverage must not load — and - // the JSON must omit the family entirely (absent ≠ 0). - let output = mehen(dir.path(), &["metrics", "app.py"]); - let json = json_stdout(&output); - assert!( - json["metrics"].get("coverage").is_none(), - "coverage family must be absent: {}", - json["metrics"] - ); - - // `--coverage off` beats an opting-in config section. - write(dir.path(), "mehen.toml", "[coverage]\ndiscover = true\n"); - let output = mehen(dir.path(), &["metrics", "app.py", "--coverage=off"]); - let json = json_stdout(&output); - assert!(json["metrics"].get("coverage").is_none()); -} - -#[test] -fn metrics_auto_discovers_reports_in_gitignored_directories() { - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "app.py", PYTHON_BODY); - // The idiomatic layout: report inside a gitignored coverage/ dir. - write(dir.path(), ".gitignore", "coverage/\n"); - write(dir.path(), "coverage/lcov.info", LCOV); - - let output = mehen(dir.path(), &["metrics", "app.py", "--coverage"]); - let json = json_stdout(&output); - assert_eq!(json["metrics"]["coverage"]["line"]["covered"], 4); -} - -#[test] -fn config_coverage_section_opts_in_and_extra_patterns_extend_the_scan() { - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "app.py", PYTHON_BODY); - // A location no built-in pattern covers… - write(dir.path(), "qa/run.lcovdata", LCOV); - write( - dir.path(), - "mehen.toml", - "[coverage]\ndiscover = true\nextra-patterns = [\"qa/*.lcovdata\"]\n", - ); - - // No CLI flag: the [coverage] section opts the run in. - let output = mehen(dir.path(), &["metrics", "app.py"]); - let json = json_stdout(&output); - assert_eq!(json["metrics"]["coverage"]["line"]["covered"], 4); -} - -#[test] -fn coverage_threshold_gates_the_metrics_command() { - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "app.py", PYTHON_BODY); - write(dir.path(), "lcov.info", LCOV); - // Higher-is-better: the configured limit is a minimum. 66.7% < 80. - write( - dir.path(), - "mehen.toml", - "[thresholds]\n\"coverage.line\" = 80\n", - ); - - // The threshold itself is the lazy trigger — no flag needed. - let output = mehen(dir.path(), &["metrics", "app.py"]); - assert_eq!( - output.status.code(), - Some(1), - "66.7% line coverage must fail a min-80 gate: {}", - String::from_utf8_lossy(&output.stderr) - ); - let stderr = String::from_utf8_lossy(&output.stderr); - assert!( - stderr.contains("coverage.line"), - "violation must name the metric: {stderr}" - ); - - // A permissive limit passes. - write( - dir.path(), - "mehen.toml", - "[thresholds]\n\"coverage.line\" = 50\n", - ); - let output = mehen(dir.path(), &["metrics", "app.py"]); - assert!( - output.status.success(), - "66.7% must pass a min-50 gate: {}", - String::from_utf8_lossy(&output.stderr) - ); - - // A file absent from the report is unmeasured: the gate must be - // skipped, not fired against a fabricated 0%. - write(dir.path(), "other.py", "a = 1\n"); - write( - dir.path(), - "mehen.toml", - "[thresholds]\n\"coverage.line\" = 80\n", - ); - let output = mehen(dir.path(), &["metrics", "other.py"]); - assert!( - output.status.success(), - "unmeasured file must not fail a coverage gate: {}", - String::from_utf8_lossy(&output.stderr) - ); -} - -#[test] -fn metrics_with_missing_explicit_report_is_a_setup_error() { - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "app.py", PYTHON_BODY); - - let output = mehen( - dir.path(), - &["metrics", "app.py", "--coverage=nonexistent.info"], - ); - assert_eq!(output.status.code(), Some(1)); - let stderr = String::from_utf8_lossy(&output.stderr); - assert!( - stderr.contains("nonexistent.info"), - "error must name the missing report: {stderr}" - ); - - // Conflicting flag values are a usage error too. - let output = mehen( - dir.path(), - &["metrics", "app.py", "--coverage=auto", "--coverage=off"], - ); - assert_eq!(output.status.code(), Some(1)); - - // Explicit report paths require the `=` spelling: a space-separated - // value would otherwise swallow a positional path - // (`top-offenders --coverage src/`), so clap rejects it outright. - let output = mehen( - dir.path(), - &["metrics", "app.py", "--coverage", "lcov.info"], - ); - assert!( - !output.status.success(), - "space-separated --coverage value must be rejected" - ); -} - -#[test] -fn bare_coverage_flag_does_not_swallow_positional_paths() { - // Regression: with `require_equals`, bare `--coverage` never - // consumes the following positional argument as its value. - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "covered.py", PYTHON_BODY); - write(dir.path(), "lcov.info", LCOV); - - let output = mehen( - dir.path(), - &[ - "top-offenders", - "--metric", - "coverage.line", - "--coverage", - ".", - ], - ); - let json = json_stdout(&mehen( - dir.path(), - &[ - "top-offenders", - "--metric", - "coverage.line", - "--coverage", - "-O", - "json", - ".", - ], - )); - assert!( - output.status.success(), - "paths after bare --coverage must survive: {}", - String::from_utf8_lossy(&output.stderr) - ); - assert!( - json.as_array().is_some_and(|rows| !rows.is_empty()), - "the positional path must be walked: {json}" - ); -} - -#[test] -fn top_offenders_ranks_by_coverage_ascending_risk() { - let dir = tempfile::tempdir().unwrap(); - write(dir.path(), "covered.py", PYTHON_BODY); - write(dir.path(), "uncovered.py", PYTHON_BODY); - write( - dir.path(), - "lcov.info", - "TN:\nSF:covered.py\nDA:1,5\nDA:2,5\nend_of_record\nSF:uncovered.py\nDA:1,0\nDA:2,0\nend_of_record\n", - ); - - let output = mehen( - dir.path(), - &[ - "top-offenders", - "--metric", - "coverage.line", - "--coverage=lcov.info", - "-O", - "json", - ".", - ], - ); - let json = json_stdout(&output); - let rows = json.as_array().expect("offender array"); - // Suffix-match on the full component — `./uncovered.py` also ends - // with the bytes `covered.py`, and Windows walk output spells the - // separator as `\`. - let value_for = |name: &str| { - rows.iter() - .find(|r| { - let path = r["path"].as_str().unwrap_or_default(); - path.ends_with(&format!("/{name}")) || path.ends_with(&format!("\\{name}")) - }) - .map(|r| r["metrics"][0]["value"].clone()) - }; - assert_eq!(value_for("uncovered.py"), Some(serde_json::json!(0.0))); - assert_eq!(value_for("covered.py"), Some(serde_json::json!(100.0))); - // Higher-is-better polarity: the least-covered file is the worst - // offender and sorts first. - assert!( - rows[0]["path"] - .as_str() - .unwrap_or_default() - .ends_with("uncovered.py"), - "least covered first: {json}" - ); -} - -/// SQL routines are function-shaped scopes too: mehen-sql nests -/// `SpaceKind::Function` spaces (one per routine) under their -/// `sql.statement` space, and the engine's coverage recursion annotates -/// them through the statement layer. An Oracle package body with one -/// covered and one uncovered routine must publish per-routine -/// `coverage.line` — the utPLSQL-style lines-only report also pins the -/// absent-dimension rule at routine granularity (no branch/function -/// keys on the spaces). -#[test] -fn sql_package_routines_receive_per_function_coverage() { - let dir = tempfile::tempdir().unwrap(); - write( - dir.path(), - "pkg_demo.sql", - "-- sqlfluff:dialect:oracle\ncreate or replace package body pkg_demo is\n function get_a return number is\n begin\n return 1;\n end get_a;\n\n procedure set_b(p number) is\n begin\n null;\n end set_b;\nend pkg_demo;\n/\n", - ); - // Lines-only Cobertura, the shape utPLSQL emits with -source_path - // file mapping: get_a's body lines hit, set_b's never executed. - write( - dir.path(), - "cobertura.xml", - r#" - - - - - - - - - - - - -"#, - ); - - let output = mehen( - dir.path(), - &["metrics", "pkg_demo.sql", "--coverage=cobertura.xml"], - ); - let json = json_stdout(&output); - - // Root: 2 of 4 measured lines covered. SQL publishes its flat - // metric map verbatim (no families pivot), so the keys sit in - // root.metrics. - let root_metrics = &json["root"]["metrics"]; - assert_eq!(root_metrics["coverage.line.covered"], 2, "{root_metrics}"); - assert_eq!(root_metrics["coverage.line.total"], 4); - - // The statement space carries the two routine spaces; each gets - // span-scoped line coverage (get_a: lines 3..=6 → 2/2 hit; set_b: - // lines 8..=11 → 0/2), and no branch/function keys — the report - // has no such dimensions (absent, not zero). - let statement = &json["root"]["spaces"][0]; - assert_eq!(statement["kind"]["custom"], "sql.statement", "{statement}"); - let routines = statement["spaces"].as_array().expect("routine spaces"); - let coverage_of = |name: &str| { - let space = routines - .iter() - .find(|s| s["name"] == name) - .unwrap_or_else(|| panic!("missing routine space {name}: {routines:?}")); - assert_eq!(space["kind"], "function"); - assert!( - space["metrics"].get("coverage.branch").is_none() - && space["metrics"].get("coverage.function").is_none(), - "unmeasured dimensions must stay absent: {}", - space["metrics"] - ); - ( - space["metrics"]["coverage.line"].clone(), - space["metrics"]["coverage.line.covered"].clone(), - space["metrics"]["coverage.line.total"].clone(), - ) - }; - assert_eq!( - coverage_of("get_a"), - ( - serde_json::json!(100.0), - serde_json::json!(2), - serde_json::json!(2) - ) - ); - assert_eq!( - coverage_of("set_b"), - ( - serde_json::json!(0.0), - serde_json::json!(0), - serde_json::json!(2) - ) - ); -} - -// ─── `mehen diff` coverage: head `--coverage` + base `--base-coverage` ─── - -fn git(path: &std::path::Path, args: &[&str]) -> std::process::Output { - Command::new("git") - .current_dir(path) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git") -} - -fn git_ok(path: &std::path::Path, args: &[&str]) { - let output = git(path, args); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); -} - -fn init_git_repo(path: &std::path::Path) { - git_ok(path, &["init", "-q", "-b", "main"]); - git_ok(path, &["config", "commit.gpgsign", "false"]); -} - -fn commit_all(path: &std::path::Path, message: &str) { - git_ok(path, &["add", "-A"]); - git_ok(path, &["commit", "-q", "-m", message]); -} - -/// Run `mehen diff` with the CI env scrubbed so GitHub Actions -/// detection never hijacks ref resolution on a developer machine or in -/// this repo's own CI. `RUST_LOG=warn` surfaces `log::warn!` output -/// (the staleness warning) on stderr — `env_logger`'s default filter -/// is error-only. -fn mehen_diff(dir: &std::path::Path, args: &[&str]) -> std::process::Output { - Command::new(env!("CARGO_BIN_EXE_mehen")) - .current_dir(dir) - .arg("diff") - .args(args) - .env("RUST_LOG", "warn") - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff") -} - -/// The `coverage.line` entry of one file's metrics array, if present. -/// Panics when the file has no diff row at all. -fn coverage_line_metric(json: &serde_json::Value, path: &str) -> Option { - let files = json["source_code"].as_array().expect("source_code array"); - let file = files - .iter() - .find(|f| f["path"].as_str() == Some(path)) - .unwrap_or_else(|| panic!("missing diff row for {path}: {json}")); - file["metrics"] - .as_array() - .expect("metrics array") - .iter() - .find(|m| m["name"].as_str() == Some("coverage.line")) - .cloned() -} - -/// Base body: cognitive 1 (one `if`). -const PYTHON_V1: &str = "def hit(flag):\n if flag:\n return 1\n return 2\n"; -/// Head body: cognitive 3 (nested `if`) — the statics delta keeps a -/// row alive even when its coverage entry is omitted. -const PYTHON_V2: &str = "def hit(flag):\n if flag:\n if flag > 1:\n return 0\n return 1\n return 2\n\n\ndef extra():\n return 3\n"; - -/// Base report: `app.py` 1 of 2 instrumented lines hit → 50%. -const BASE_LCOV: &str = "TN:\nSF:app.py\nDA:1,1\nDA:2,0\nend_of_record\n"; -/// Head report: `app.py` 3 of 3 instrumented lines hit → 100%. -const HEAD_LCOV: &str = "TN:\nSF:app.py\nDA:1,1\nDA:2,1\nDA:5,1\nend_of_record\n"; - -#[test] -fn diff_carries_coverage_trend_when_both_sides_have_reports() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - write(dir.path(), "app.py", PYTHON_V1); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - write(dir.path(), "app.py", PYTHON_V2); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - // Reports written *after* both commits: fresher than the base - // commit, so no staleness warning may fire. - write(dir.path(), "base.info", BASE_LCOV); - write(dir.path(), "head.info", HEAD_LCOV); - - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--metrics", - "cognitive,coverage.line", - "--coverage=head.info", - "--base-coverage=base.info", - "--output-format", - "json", - ], - ); - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - let json = json_stdout(&output); - - let m = coverage_line_metric(&json, "app.py").expect("coverage.line entry"); - assert_eq!(m["current"], 100.0, "{m}"); - assert_eq!(m["baseline"], 50.0); - assert_eq!(m["delta"], 50.0); - // Both sides measured: the unavailable flags are omitted from JSON. - assert!(m.get("baseline_unavailable").is_none(), "{m}"); - assert!(m.get("current_unavailable").is_none()); - assert!( - !stderr.contains("predates the base commit"), - "fresh report must not warn: {stderr}" - ); -} - -#[test] -fn diff_defaults_surface_coverage_column_when_reports_resolve() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - write(dir.path(), "app.py", PYTHON_V1); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - write(dir.path(), "app.py", PYTHON_V2); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - // A name discovery never picks up (content-sniffed as LCOV on the - // explicit path): head-side discovery must find only the idiomatic - // `coverage/lcov.info`, not accidentally ingest the base report. - write(dir.path(), "base-report.data", BASE_LCOV); - // The idiomatic discoverable location for the head report. - write(dir.path(), "coverage/lcov.info", HEAD_LCOV); - - // `--base-coverage` alone implies coverage for the head side: the - // lazy trigger runs discovery, which finds `coverage/lcov.info`. - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--base-coverage=base-report.data", - "--output-format", - "json", - ], - ); - let json = json_stdout(&output); - let m = coverage_line_metric(&json, "app.py").expect("default coverage column"); - assert_eq!(m["current"], 100.0, "{m}"); - assert_eq!(m["baseline"], 50.0); - assert_eq!(m["label"], "Coverage"); - - // Markdown: the default column set gains a `Coverage` column with - // a real higher-is-better trend cell. - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--base-coverage=base-report.data", - ], - ); - assert!(output.status.success()); - let markdown = String::from_utf8_lossy(&output.stdout).to_string(); - assert!(markdown.contains("| Coverage |"), "{markdown}"); - assert!(markdown.contains(": 50) \u{1F7E2}"), "{markdown}"); // 🟢 +50pp - // Without any coverage request, the defaults stay coverage-free. - let output = mehen_diff(dir.path(), &["--from", "cov-base", "--to", "cov-head"]); - assert!(output.status.success()); - let markdown = String::from_utf8_lossy(&output.stdout).to_string(); - assert!(!markdown.contains("| Coverage |"), "{markdown}"); -} - -#[test] -fn diff_renders_one_sided_coverage_as_measurement_change_and_omits_unmeasured() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - for file in ["app.py", "helper.py", "lone.py"] { - write(dir.path(), file, PYTHON_V1); - } - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - for file in ["app.py", "helper.py", "lone.py"] { - write(dir.path(), file, PYTHON_V2); - } - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - // Head report measures only `app.py`; base report only `helper.py`; - // `lone.py` is measured on neither side. - write(dir.path(), "head.info", HEAD_LCOV); - write( - dir.path(), - "base.info", - "TN:\nSF:helper.py\nDA:1,1\nDA:2,0\nend_of_record\n", - ); - - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--metrics", - "cognitive,coverage.line", - "--coverage=head.info", - "--base-coverage=base.info", - "--output-format", - "json", - ], - ); - let json = json_stdout(&output); - - // Newly measured: head value real, no fabricated regression — the - // base side reads *unavailable* (absent ≠ 0, extended to diff). - let app = coverage_line_metric(&json, "app.py").expect("app.py coverage"); - assert_eq!(app["current"], 100.0, "{app}"); - assert_eq!(app["baseline_unavailable"], true); - assert_eq!(app["delta"], 0.0, "no direction may be claimed: {app}"); - - // Lost measurement: base value real, head side unavailable. - let helper = coverage_line_metric(&json, "helper.py").expect("helper.py coverage"); - assert_eq!(helper["baseline"], 50.0, "{helper}"); - assert_eq!(helper["current_unavailable"], true); - assert_eq!(helper["delta"], 0.0); - - // Measured on neither side: the entry is omitted entirely (the - // column renders `–`), never an `n/a`-forever row or a fabricated - // `0`. - assert!( - coverage_line_metric(&json, "lone.py").is_none(), - "unmeasured file must omit the coverage entry" - ); - - // The same scope in Markdown pins the `–` cell for the unmeasured - // file. - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--metrics", - "cognitive,coverage.line", - "--coverage=head.info", - "--base-coverage=base.info", - ], - ); - assert!(output.status.success()); - let markdown = String::from_utf8_lossy(&output.stdout).to_string(); - let lone_row = markdown - .lines() - .find(|line| line.starts_with("| lone.py")) - .expect("lone.py row"); - assert!(lone_row.contains('\u{2013}'), "expected – cell: {lone_row}"); -} - -#[test] -fn diff_new_and_deleted_files_keep_honest_coverage_cells() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - // Contents are deliberately unrelated: rename tracking must not - // pair the deletion with the addition. - write( - dir.path(), - "old.py", - "def legacy(a, b):\n while a:\n a -= b\n return a\n", - ); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - std::fs::remove_file(dir.path().join("old.py")).unwrap(); - write( - dir.path(), - "new.py", - "class Greeter:\n def greet(self, name):\n if name:\n return f\"hi {name}\"\n return \"hi\"\n", - ); - write( - dir.path(), - "unmeasured_new.py", - "VALUES = [1, 2, 3]\n\n\ndef total():\n return sum(VALUES)\n", - ); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - write( - dir.path(), - "head.info", - "TN:\nSF:new.py\nDA:1,1\nDA:2,1\nDA:5,1\nend_of_record\n", - ); - write( - dir.path(), - "base.info", - "TN:\nSF:old.py\nDA:1,1\nDA:2,0\nend_of_record\n", - ); - - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--metrics", - "coverage.line", - "--coverage=head.info", - "--base-coverage=base.info", - "--output-format", - "json", - ], - ); - let json = json_stdout(&output); - - let new = coverage_line_metric(&json, "new.py").expect("new.py coverage"); - assert_eq!(new["is_new"], true, "{new}"); - assert_eq!(new["current"], 100.0); - let old = coverage_line_metric(&json, "old.py").expect("old.py coverage"); - assert_eq!(old["is_deleted"], true, "{old}"); - assert_eq!(old["baseline"], 50.0); - - // A new file measured by no report has no coverage entry, and with - // coverage as the only selected column its row carries no signal - // at all — it must drop out rather than render an empty row. - assert!( - json["source_code"] - .as_array() - .expect("source_code array") - .iter() - .all(|f| f["path"].as_str() != Some("unmeasured_new.py")), - "unmeasured new file must not produce a row: {json}" - ); -} - -#[test] -fn diff_base_report_predating_base_commit_warns_once_and_is_configurable() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - write(dir.path(), "app.py", PYTHON_V1); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - write(dir.path(), "app.py", PYTHON_V2); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - write(dir.path(), "base.info", BASE_LCOV); - // Backdate the report to 1970: it cannot describe the base commit. - let report = std::fs::File::options() - .write(true) - .open(dir.path().join("base.info")) - .unwrap(); - report - .set_modified(std::time::UNIX_EPOCH + std::time::Duration::from_secs(1_000_000)) - .unwrap(); - drop(report); - - let args = [ - "--from", - "cov-base", - "--to", - "cov-head", - "--metrics", - "coverage.line", - "--base-coverage=base.info", - "--coverage=off", - "--output-format", - "json", - ]; - let output = mehen_diff(dir.path(), &args); - assert!(output.status.success()); - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - assert!( - stderr.contains("predates the base commit"), - "backdated base report must warn: {stderr}" - ); - - // `stale-warning = false` under `[coverage]` silences it. - write( - dir.path(), - "mehen.toml", - "[coverage]\nstale-warning = false\n", - ); - let output = mehen_diff(dir.path(), &args); - assert!(output.status.success()); - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - assert!( - !stderr.contains("predates the base commit"), - "stale-warning = false must silence the warning: {stderr}" - ); -} - -#[test] -fn diff_missing_base_coverage_report_is_a_setup_error() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - write(dir.path(), "app.py", PYTHON_V1); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - write(dir.path(), "app.py", PYTHON_V2); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--base-coverage=nonexistent.info", - ], - ); - assert_eq!(output.status.code(), Some(1)); - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - assert!( - stderr.contains("nonexistent.info"), - "error must name the missing report: {stderr}" - ); - - // The `=` spelling is mandatory, mirroring `--coverage`. - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--base-coverage", - "base.info", - ], - ); - assert!( - !output.status.success(), - "space-separated --base-coverage value must be rejected" - ); -} - -#[test] -fn diff_coverage_threshold_gates_head_side_via_lazy_trigger() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - write(dir.path(), "app.py", PYTHON_V1); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - write(dir.path(), "app.py", PYTHON_V2); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - // Head report at the idiomatic discoverable location: 1 of 3 → 33%. - write( - dir.path(), - "coverage/lcov.info", - "TN:\nSF:app.py\nDA:1,1\nDA:2,0\nDA:5,0\nend_of_record\n", - ); - // The configured minimum is the lazy ingestion trigger — no flag. - write( - dir.path(), - "mehen.toml", - "[thresholds]\n\"coverage.line\" = 80\n", - ); - - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--output-format", - "json", - ], - ); - assert_eq!( - output.status.code(), - Some(1), - "33% line coverage must fail a min-80 gate: {}", - String::from_utf8_lossy(&output.stderr) - ); - let json: serde_json::Value = - serde_json::from_slice(&output.stdout).expect("gate-failing diff still emits JSON"); - let violations = json["threshold_violations"] - .as_array() - .expect("threshold_violations array"); - assert!( - violations - .iter() - .any(|v| v["metric"].as_str() == Some("coverage.line")), - "violation must name coverage.line: {json}" - ); -} - -#[test] -fn diff_renamed_file_reads_base_coverage_from_old_path() { - let dir = tempfile::tempdir().unwrap(); - init_git_repo(dir.path()); - write(dir.path(), "app.py", PYTHON_V1); - commit_all(dir.path(), "base"); - git_ok(dir.path(), &["tag", "cov-base"]); - // Rename with a one-line edit: similar enough for rename tracking - // (the diff row appears under the new path with the old path as - // its baseline), while the coverage trend keeps the row alive. - git_ok(dir.path(), &["mv", "app.py", "renamed.py"]); - let mut renamed = PYTHON_V1.to_string(); - renamed.push_str("\n\nLIMIT = 3\n"); - write(dir.path(), "renamed.py", &renamed); - commit_all(dir.path(), "head"); - git_ok(dir.path(), &["tag", "cov-head"]); - // The base report measured the file under its *old* path. - write(dir.path(), "base.info", BASE_LCOV); - write( - dir.path(), - "head.info", - "TN:\nSF:renamed.py\nDA:1,1\nDA:2,1\nDA:5,1\nend_of_record\n", - ); - - let output = mehen_diff( - dir.path(), - &[ - "--from", - "cov-base", - "--to", - "cov-head", - "--metrics", - "cognitive,coverage.line", - "--coverage=head.info", - "--base-coverage=base.info", - "--output-format", - "json", - ], - ); - let json = json_stdout(&output); - let m = coverage_line_metric(&json, "renamed.py").expect("renamed.py coverage"); - assert_eq!(m["baseline"], 50.0, "old-path base lookup: {m}"); - assert_eq!(m["current"], 100.0); - assert!(m.get("baseline_unavailable").is_none(), "{m}"); -} diff --git a/crates/mehen-cli/tests/pr_comment_catalog.rs b/crates/mehen-cli/tests/pr_comment_catalog.rs deleted file mode 100644 index 96625167..00000000 --- a/crates/mehen-cli/tests/pr_comment_catalog.rs +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Template-catalog linter covering §39.5.2 / §39.5.3 at test time. -//! -//! Complements `scripts/check_pr_template_catalog.sh`: both run the same -//! inspection against `src/diff_markdown.rs`. This test variant keeps the -//! safety-net inside the workspace's regular test suite so pushes that -//! slip past CI scripts are still rejected. - -use std::path::PathBuf; - -fn diff_markdown_source() -> String { - // Walk up from `crates/mehen-cli/` to the workspace root. - let workspace_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .parent() - .and_then(|p| p.parent()) - .expect("workspace root") - .to_path_buf(); - let path = workspace_root.join("crates/mehen-report/src/github_markdown_docs.rs"); - std::fs::read_to_string(&path) - .expect("failed to read crates/mehen-report/src/github_markdown_docs.rs") -} - -/// Each phrase from §39.5.3. Exact, verbatim match with the spec. -const FORBIDDEN_PHRASES: &[&str] = &[ - "because", - "due to", - "caused by", - "following", - "since", - "likely", - "probably", - "appears to", - "seems", - "may indicate", - "suggests", - "possibly", -]; - -fn line_is_comment(line: &str) -> bool { - let trimmed = line.trim_start(); - trimmed.starts_with("//") || trimmed.starts_with("/*") || trimmed.starts_with('*') -} - -/// Returns `Some(name)` if `line` declares a function, either at column 0 -/// or inside an `impl` block (leading whitespace OK). Accepts `fn`, `pub fn`, -/// `pub(crate) fn`, `pub(super) fn`, and `async fn`. -fn parse_top_level_fn(line: &str) -> Option { - let mut rest = line.trim_start(); - for prefix in ["pub(crate) ", "pub(super) ", "pub ", ""] { - if let Some(r) = rest.strip_prefix(prefix) { - rest = r; - break; - } - } - if let Some(r) = rest.strip_prefix("async ") { - rest = r; - } - rest = rest.strip_prefix("fn ")?; - let name: String = rest - .chars() - .take_while(|c| c.is_alphanumeric() || *c == '_') - .collect(); - if name.is_empty() { None } else { Some(name) } -} - -#[test] -fn no_forbidden_phrases_in_emitter() { - let src = diff_markdown_source(); - let mut hits: Vec<(usize, String, String)> = Vec::new(); - for (idx, line) in src.lines().enumerate() { - if line_is_comment(line) { - continue; - } - let lower = line.to_ascii_lowercase(); - for phrase in FORBIDDEN_PHRASES { - if lower.contains(phrase) { - hits.push((idx + 1, phrase.to_string(), line.to_string())); - } - } - } - assert!( - hits.is_empty(), - "§39.5.3 forbidden phrases in emitter:\n{}", - hits.iter() - .map(|(n, p, l)| format!(" L{n}: `{p}` :: {l}")) - .collect::>() - .join("\n") - ); -} - -/// Allow-listed mechanical rendering helpers that legitimately call -/// `format!` / `write!`. Keep in sync with -/// `scripts/check_pr_template_catalog.sh`. -const ALLOWED_FUNCS: &[&str] = &[ - "render_doc_section", - "render_drill_down", - "render_drill_structural", - "render_drill_en_wording", - "render_drill_en_lexical", - "render_drill_ja", - "render_filler_contributors", - "write_headline_table", - "heading_scope", - "format_int_thousands", - "format_link_list", - "format_surface_list_without_line", - "format_value", - "build_file_link", - "render", -]; - -/// Strip the trailing content of a `//` line comment. String literals in -/// emitter code may contain `//` (URLs), but the linter's `line_is_comment` -/// already skips whole-line comments, and brace-depth tracking only needs -/// approximate accuracy. -fn strip_line_comment(line: &str) -> &str { - if let Some(idx) = line.find("//") { - &line[..idx] - } else { - line - } -} - -/// Count `{` minus `}` tokens on a single line (approximate, line-comment -/// stripped). Good enough for the emitter file's structure; the linter -/// doesn't need lexical-perfection, only "did we leave the `fn` body yet". -fn net_braces(line: &str) -> i32 { - let trimmed = strip_line_comment(line); - let open = trimmed.matches('{').count() as i32; - let close = trimmed.matches('}').count() as i32; - open - close -} - -/// Shared per-line state update: advance brace depth, promote a function -/// signature into a body once the opening `{` appears, and clear -/// `current_fn` once the body closes. -fn advance_scope( - line: &str, - depth: &mut i32, - current_fn: &mut Option, - fn_open_depth: &mut i32, - inside_body: &mut bool, -) { - *depth += net_braces(line); - if current_fn.is_some() && !*inside_body && *depth > *fn_open_depth { - *inside_body = true; - } - if current_fn.is_some() && *inside_body && *depth <= *fn_open_depth { - *current_fn = None; - *inside_body = false; - } -} - -#[test] -fn all_format_calls_live_inside_template_or_allow_list() { - let src = diff_markdown_source(); - // Track the enclosing top-level function using brace depth so that code - // between two `fn` definitions (e.g. a `const` initialized with - // `format!`) is attributed to `(top-level)` rather than the preceding - // function. `inside_body` flips to true only after we actually see the - // opening `{`, so a multi-line signature doesn't clear the association - // prematurely. - let mut current_fn: Option = None; - let mut fn_open_depth: i32 = 0; - let mut inside_body: bool = false; - let mut depth: i32 = 0; - let mut hits: Vec<(usize, String)> = Vec::new(); - - for (idx, line) in src.lines().enumerate() { - let line_no = idx + 1; - // Top-level `fn` declarations start a new enclosing function. - if let Some(name) = parse_top_level_fn(line) { - current_fn = Some(name); - fn_open_depth = depth; - inside_body = false; - advance_scope( - line, - &mut depth, - &mut current_fn, - &mut fn_open_depth, - &mut inside_body, - ); - continue; - } - if line_is_comment(line) { - advance_scope( - line, - &mut depth, - &mut current_fn, - &mut fn_open_depth, - &mut inside_body, - ); - continue; - } - if line.contains("format!(") || line.contains("write!(") || line.contains("writeln!(") { - let enclosing = current_fn.as_deref().unwrap_or("(top-level)"); - let permitted = enclosing.starts_with("tmpl_") || ALLOWED_FUNCS.contains(&enclosing); - if !permitted { - hits.push((line_no, format!("fn {enclosing}: {}", line.trim()))); - } - } - advance_scope( - line, - &mut depth, - &mut current_fn, - &mut fn_open_depth, - &mut inside_body, - ); - } - assert!( - hits.is_empty(), - "format!/write! calls outside §39.5.2 catalog:\n{}", - hits.iter() - .map(|(n, l)| format!(" L{n}: {l}")) - .collect::>() - .join("\n") - ); -} diff --git a/crates/mehen-cli/tests/pr_comment_golden.rs b/crates/mehen-cli/tests/pr_comment_golden.rs deleted file mode 100644 index d69dd8c8..00000000 --- a/crates/mehen-cli/tests/pr_comment_golden.rs +++ /dev/null @@ -1,266 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Golden-output snapshot tests for the Markdown PR-comment section (§39.9). -//! -//! Each test fixture exercises one of the §39 paths documented in the -//! reference mock: improvement, new-file summary, regression with broken -//! links + long sentences, and a filler-risk high attention marker on an -//! otherwise-unchanged file. Output is captured via `insta` and must stay -//! byte-identical across runs — the emitter is deterministic by design. - -use std::process::Command; - -use insta::assert_snapshot; - -/// Path to the `mehen` binary built by the surrounding `mehen-cli` -/// crate. The CLI delegates `diff` to the still-in-place -/// `mehen::diff::run_diff` orchestrator while phase-4/5 follow-ups -/// physically relocate it into `mehen-engine`/`mehen-report`. -fn mehen_bin() -> String { - env!("CARGO_BIN_EXE_mehen").to_string() -} - -fn git(repo: &std::path::Path, args: &[&str]) -> std::process::Output { - Command::new("git") - .args(args) - .current_dir(repo) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .env("GIT_AUTHOR_DATE", "2025-01-01T00:00:00Z") - .env("GIT_COMMITTER_DATE", "2025-01-01T00:00:00Z") - .output() - .expect("failed to spawn git") -} - -fn git_ok(repo: &std::path::Path, args: &[&str]) { - let out = git(repo, args); - assert!( - out.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&out.stderr) - ); -} - -fn init_repo() -> tempfile::TempDir { - let dir = tempfile::tempdir().expect("tempdir"); - let path = dir.path(); - git_ok(path, &["init", "-q", "-b", "main"]); - git_ok(path, &["config", "user.name", "Mehen Test"]); - git_ok(path, &["config", "user.email", "test@mehen.invalid"]); - git_ok(path, &["config", "commit.gpgsign", "false"]); - dir -} - -fn commit(path: &std::path::Path, msg: &str) { - git_ok(path, &["add", "-A"]); - git_ok(path, &["commit", "-q", "-m", msg, "--allow-empty"]); -} - -fn write_file(root: &std::path::Path, relative: &str, content: &str) { - let full = root.join(relative); - if let Some(parent) = full.parent() { - std::fs::create_dir_all(parent).expect("create dir"); - } - std::fs::write(&full, content).expect("write fixture"); -} - -fn run_mehen_diff(repo: &std::path::Path, from: &str, to: &str) -> String { - let out = Command::new(mehen_bin()) - .args([ - "diff", - "--from", - from, - "--to", - to, - "--output-format", - "markdown", - ]) - .current_dir(repo) - .env_remove("GITHUB_ACTIONS") - .env_remove("GITHUB_EVENT_NAME") - .env_remove("GITHUB_BASE_REF") - .env_remove("GITHUB_SHA") - .env_remove("GITHUB_REPOSITORY") - .output() - .expect("failed to run mehen diff"); - assert!( - out.status.success(), - "mehen diff failed: stderr={}", - String::from_utf8_lossy(&out.stderr) - ); - String::from_utf8(out.stdout).expect("stdout utf8") -} - -fn redact_sha_markers(s: &str) -> String { - // Shorten any 40-hex SHAs to a stable `[sha]` token so snapshots don't - // drift across runs. We also collapse the `main` label when git's - // friendly-ref resolution differs by host (e.g. some tempdir paths - // yield `HEAD` instead). - let mut out = String::new(); - let mut chars = s.chars().peekable(); - while let Some(c) = chars.next() { - if c.is_ascii_hexdigit() { - let mut run = String::from(c); - while let Some(&next) = chars.peek() { - if next.is_ascii_hexdigit() { - run.push(next); - chars.next(); - } else { - break; - } - } - if run.len() == 40 { - out.push_str("[sha]"); - } else { - out.push_str(&run); - } - } else { - out.push(c); - } - } - out -} - -#[test] -fn golden_new_file_summary() { - // Fixture: repo starts with only a base commit; head adds a new - // `docs/architecture/runtime.md`. The Markdown-docs section must emit - // a `new_file_summary` callout. - let dir = init_repo(); - let path = dir.path(); - write_file(path, "README.md", "# Placeholder\n"); - commit(path, "base commit"); - - write_file( - path, - "docs/architecture/runtime.md", - "# Runtime architecture\n\nThe runtime schedules tasks across a pool of workers. \ - Each worker owns a mailbox and pulls work from a central queue at startup. \ - When a worker receives a task, it dispatches through the router and executes \ - the handler. The handler may emit events which flow back into the queue.\n\n\ - ## Workers\n\nEach worker process registers with the supervisor on startup. \ - The supervisor tracks the set of healthy workers and routes new work based \ - on load. Workers heartbeat every five seconds and are reaped after three \ - missed beats.\n\n## Queue\n\nThe queue is a durable append-only log. \ - Producers append events with a monotonic sequence; consumers track their \ - read position in a companion log. Rebalancing happens transparently.\n\n\ - ```rust\nfn main() {\n println!(\"hello\");\n}\n```\n\n\ - See [the supervisor guide](../supervisor.md) for details.\n", - ); - commit(path, "add runtime architecture doc"); - - let rendered = run_mehen_diff(path, "HEAD~1", "HEAD"); - let redacted = redact_sha_markers(&rendered); - assert_snapshot!("new_file_summary", redacted); -} - -#[test] -fn golden_regression_broken_links_and_long_sentences() { - // Fixture: base has a clean API doc; head adds a broken relative link - // and several 35+-word sentences. Expected output includes - // `broken_relative_link_added`, `long_sentences_added`, and - // `readability_target_breach` callouts. - let dir = init_repo(); - let path = dir.path(); - write_file( - path, - "docs/api/auth.md", - "# Authentication\n\nThe authentication API issues session tokens to clients.\n\n\ - ## Sessions\n\nCall the login endpoint with a username and password. \ - On success, the server returns a signed session token. Clients include \ - this token in subsequent requests.\n\n## Tokens\n\nTokens expire after 24 hours.\n", - ); - commit(path, "base auth doc"); - - write_file( - path, - "docs/api/auth.md", - "# Authentication\n\nThe authentication API issues session tokens to clients that have \ - completed the initial handshake which involves three round trips across the wire \ - and then one additional validation step which verifies the client certificate \ - chain back to the root authority which is pinned in configuration at build time.\n\n\ - ## Sessions\n\nCall the login endpoint with a username and password following \ - the protocol outlined in the companion guide at [session guide](../../guide/sessions.md) \ - and also read the tokens page at [tokens refresh](./tokens.md#refresh) before \ - proceeding so that every client understands the full handshake before the server \ - starts routing traffic to backend services that will reject unauthenticated \ - requests on the edge without providing any diagnostic context back to the caller.\n\n\ - On success, the server returns a signed session token. Clients include this \ - token in subsequent requests. The signing key rotates weekly and the rotation \ - ceremony requires at least two operators to be present in the secure room with \ - physical access badges that the facility manager distributes every Monday morning.\n\n\ - ## Tokens\n\nTokens expire after 24 hours of wall-clock time measured from the \ - moment the server issued the token to the requesting client in the response body \ - which includes both the token itself and a matching expiration timestamp.\n", - ); - commit(path, "expand auth doc"); - - let rendered = run_mehen_diff(path, "HEAD~1", "HEAD"); - let redacted = redact_sha_markers(&rendered); - assert_snapshot!("regression_broken_links", redacted); -} - -#[test] -fn golden_filler_risk_high_unchanged_file_attention() { - // Fixture: both base and head contain the same 'generated-overview' file - // with high filler risk. Attention marker is expected per §39.4. - let dir = init_repo(); - let path = dir.path(); - - // A deliberately low-grounded, heavy-fluff doc — high filler risk. - let filler_doc = r#"# Project Overview - -This is a comprehensive and robust approach to building scalable enterprise -solutions in a cloud-native architecture. The system leverages cutting-edge -technologies to deliver seamless user experiences across various touchpoints. - -## Architecture - -Our platform implements a sophisticated orchestration layer that provides -end-to-end visibility into the operational health of the system. Stakeholders -benefit from granular insights derived from telemetry across the stack. - -## Deployment - -Deployment follows industry best practices and delivers continuous value to -customers. The automation pipeline is resilient and supports rapid iteration. - -## Observability - -Observability is achieved through comprehensive instrumentation that captures -detailed operational metrics. Teams leverage these insights to drive data- -informed decisions across all organizational levels. - -## Security - -Security is embedded throughout the software development lifecycle. The -platform adheres to industry-leading standards and maintains rigorous -compliance posture against evolving regulatory landscapes. - -## Scale - -Scale is a first-class concern at every layer of the platform. The system -transparently handles fluctuations in demand and maintains performance -characteristics under sustained load with minimal operational overhead. -"#; - - write_file(path, "docs/generated/overview.md", filler_doc); - commit(path, "base: generated overview"); - - // Touch a trailing blank line so the overview is in the PR diff. The - // filler score stays above the 0.60 warn threshold either way, so the - // headline row renders ⚠️ per §39.4. - write_file( - path, - "docs/generated/overview.md", - &format!("{filler_doc}\n"), - ); - commit(path, "head: touch overview"); - - let rendered = run_mehen_diff(path, "HEAD~1", "HEAD"); - let redacted = redact_sha_markers(&rendered); - assert_snapshot!("filler_risk_unchanged_attention", redacted); -} diff --git a/crates/mehen-cli/tests/snapshots/pr_comment_golden__filler_risk_unchanged_attention.snap b/crates/mehen-cli/tests/snapshots/pr_comment_golden__filler_risk_unchanged_attention.snap deleted file mode 100644 index 802e4fea..00000000 --- a/crates/mehen-cli/tests/snapshots/pr_comment_golden__filler_risk_unchanged_attention.snap +++ /dev/null @@ -1,50 +0,0 @@ ---- -source: crates/mehen-cli/tests/pr_comment_golden.rs -expression: redacted ---- - -## [Mehen](https://github.com/ophi-dev/mehen) Summary (`HEAD~1`..`HEAD`) - -No metric changes detected. - - -## 📝 Documentation Metrics (this PR vs `HEAD~1`) - -| File | DMI | Words | FKGL | Link Debt | Filler Risk | -|---|---:|---:|---:|---:|---:| -| `docs/generated/overview.md` | 90 ⚪ | 154 ⚪ | 14.7 ⚪ | 0.00 ⚪ | 0.67 (HEAD~1: 0.67) ⚠️ | - -**Callouts** - -- ⚠️ **docs/generated/overview.md** — filler/lazy risk 0.67 (HIGH); top contributors: large-unanchored-prose 1.00, low-artifact-density 1.00, low-repository-grounding 1.00 - -
-Full metric breakdown (structural · wording · lexical · readability) - -### Structural / review - -| File | RCI | MCC | MRPC | Evidence | Grounding | -|---|---:|---:|---:|---:|---:| -| `docs/generated/overview.md` | 0 ⚪ | 0 ⚪ | 1 ⚪ | 0.00 ⚪ | 0.00 ⚪ | - -### English wording quality - -| File | WQS | Passive % | Hedges /100w | Long sent. | Nominalizations | -|---|---:|---:|---:|---:|---:| -| `docs/generated/overview.md` | 1.00 ⚪ | 11% ⚪ | 0.0 ⚪ | 0 ⚪ | 8% ⚪ | - -### English lexical & readability ensemble - -| File | MATTR₅₀ | Hapax | Fog | SMOG | ARI | Coleman-Liau | -|---|---:|---:|---:|---:|---:|---:| -| `docs/generated/overview.md` | 0.85 ⚪ | 0.80 ⚪ | 16.2 ⚪ | — | 14.9 ⚪ | 20.5 ⚪ | - -### Filler risk contributors (files with risk > 0.40) - -- **`docs/generated/overview.md` (0.67)** — large-unanchored-prose 1.00, low-artifact-density 1.00, low-repository-grounding 1.00 - -
- -> Legend: 🟢 improvement · 🔴 regression · ⚠️ attention · 🆕 new file · ⚪ no material change - -> Generated by [mehen](https://github.com/ophi-dev/mehen) — the code quality watcher. diff --git a/crates/mehen-cli/tests/snapshots/pr_comment_golden__new_file_summary.snap b/crates/mehen-cli/tests/snapshots/pr_comment_golden__new_file_summary.snap deleted file mode 100644 index ea198f0b..00000000 --- a/crates/mehen-cli/tests/snapshots/pr_comment_golden__new_file_summary.snap +++ /dev/null @@ -1,50 +0,0 @@ ---- -source: crates/mehen-cli/tests/pr_comment_golden.rs -expression: redacted ---- - -## [Mehen](https://github.com/ophi-dev/mehen) Summary (`HEAD~1`..`HEAD`) - -No metric changes detected. - - -## 📝 Documentation Metrics (this PR vs `HEAD~1`) - -| File | DMI | Words | FKGL | Link Debt | Filler Risk | -|---|---:|---:|---:|---:|---:| -| `docs/architecture/runtime.md` | 87 🆕 | 117 🆕 | 7.1 🆕 | 0.45 🆕 | 0.56 🆕 | - -**Callouts** - -- 🆕 **docs/architecture/runtime.md** — 117 words, 3 headings, 1 code fence(s), 0 diagram(s), 0 table(s); DMI 87, filler risk 0.56 (MODERATE) - -
-Full metric breakdown (structural · wording · lexical · readability) - -### Structural / review - -| File | RCI | MCC | MRPC | Evidence | Grounding | -|---|---:|---:|---:|---:|---:| -| `docs/architecture/runtime.md` | 3 🆕 | 1 🆕 | 1 🆕 | 0.10 🆕 | 0.04 🆕 | - -### English wording quality - -| File | WQS | Passive % | Hedges /100w | Long sent. | Nominalizations | -|---|---:|---:|---:|---:|---:| -| `docs/architecture/runtime.md` | 1.00 🆕 | 7% 🆕 | 0.0 🆕 | 0 🆕 | 2% 🆕 | - -### English lexical & readability ensemble - -| File | MATTR₅₀ | Hapax | Fog | SMOG | ARI | Coleman-Liau | -|---|---:|---:|---:|---:|---:|---:| -| `docs/architecture/runtime.md` | 0.77 🆕 | 0.78 🆕 | 8.4 🆕 | — | 7.0 🆕 | 10.8 🆕 | - -### Filler risk contributors (files with risk > 0.40) - -- **`docs/architecture/runtime.md` (0.56)** — specificity-scarcity 1.00, low-repository-grounding 0.96, large-unanchored-prose 0.75 - -
- -> Legend: 🟢 improvement · 🔴 regression · ⚠️ attention · 🆕 new file · ⚪ no material change - -> Generated by [mehen](https://github.com/ophi-dev/mehen) — the code quality watcher. diff --git a/crates/mehen-cli/tests/snapshots/pr_comment_golden__regression_broken_links.snap b/crates/mehen-cli/tests/snapshots/pr_comment_golden__regression_broken_links.snap deleted file mode 100644 index 33c4d31a..00000000 --- a/crates/mehen-cli/tests/snapshots/pr_comment_golden__regression_broken_links.snap +++ /dev/null @@ -1,53 +0,0 @@ ---- -source: crates/mehen-cli/tests/pr_comment_golden.rs -expression: redacted ---- - -## [Mehen](https://github.com/ophi-dev/mehen) Summary (`HEAD~1`..`HEAD`) - -No metric changes detected. - - -## 📝 Documentation Metrics (this PR vs `HEAD~1`) - -| File | DMI | Words | FKGL | Link Debt | Filler Risk | -|---|---:|---:|---:|---:|---:| -| `docs/api/auth.md` | 85 (HEAD~1: 90) 🔴 | 197 (HEAD~1: 38) ⚪ | 13.7 (HEAD~1: 0.0) 🔴 | 0.45 (HEAD~1: 0.00) 🔴 | 0.67 (HEAD~1: 0.67) ⚠️ | - -**Callouts** - -- 🔴 **docs/api/auth.md** — 2 unresolved relative link(s) added: `../../guide/sessions.md` (L7), `./tokens.md#refresh` (L7) -- 🔴 **docs/api/auth.md** — DMI 90 → 85, crossed Excellent → Good (§10.4) -- ⚠️ **docs/api/auth.md** — filler/lazy risk 0.67 (HIGH); top contributors: large-unanchored-prose 1.00, low-artifact-density 1.00, low-repository-grounding 1.00 -- 🔴 **docs/api/auth.md** — 4 sentence(s) exceed 30 words (new): L0, L0, L0, L0 - -
-Full metric breakdown (structural · wording · lexical · readability) - -### Structural / review - -| File | RCI | MCC | MRPC | Evidence | Grounding | -|---|---:|---:|---:|---:|---:| -| `docs/api/auth.md` | 4 (HEAD~1: 0) ⚪ | 1 (HEAD~1: 0) ⚪ | 1 ⚪ | 0.00 ⚪ | 0.00 ⚪ | - -### English wording quality - -| File | WQS | Passive % | Hedges /100w | Long sent. | Nominalizations | -|---|---:|---:|---:|---:|---:| -| `docs/api/auth.md` | 0.92 (HEAD~1: 0.99) 🟢 | 11% (HEAD~1: 0%) 🔴 | 0.0 ⚪ | 4 (HEAD~1: 0) ⚪ | 6% (HEAD~1: 10%) 🟢 | - -### English lexical & readability ensemble - -| File | MATTR₅₀ | Hapax | Fog | SMOG | ARI | Coleman-Liau | -|---|---:|---:|---:|---:|---:|---:| -| `docs/api/auth.md` | 0.82 (HEAD~1: 0.78) 🔴 | 0.81 (HEAD~1: 0.78) 🔴 | 14.3 (HEAD~1: 0.0) 🔴 | — | 15.2 (HEAD~1: 0.0) 🔴 | 14.6 (HEAD~1: 0.0) 🔴 | - -### Filler risk contributors (files with risk > 0.40) - -- **`docs/api/auth.md` (0.67)** — large-unanchored-prose 1.00, low-artifact-density 1.00, low-repository-grounding 1.00 - -
- -> Legend: 🟢 improvement · 🔴 regression · ⚠️ attention · 🆕 new file · ⚪ no material change - -> Generated by [mehen](https://github.com/ophi-dev/mehen) — the code quality watcher. diff --git a/crates/mehen-core/Cargo.toml b/crates/mehen-core/Cargo.toml deleted file mode 100644 index 399ab938..00000000 --- a/crates/mehen-core/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "mehen-core" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — parser-neutral domain types and analyzer traits (internal)." -publish = false - -[dependencies] -camino = { workspace = true } -serde = { workspace = true } -smol_str = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-core/src/analysis.rs b/crates/mehen-core/src/analysis.rs deleted file mode 100644 index d59a3c5e..00000000 --- a/crates/mehen-core/src/analysis.rs +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::collections::BTreeMap; - -use serde::{Deserialize, Serialize}; - -use crate::backend::AnalysisBackend; -use crate::diagnostic::ParseDiagnostic; -use crate::language::Language; -use crate::metric_key::MetricKey; -use crate::space::MetricSpace; -use crate::span::SourceSpan; - -/// A metric value carried in `MetricSet`. Float and integer are kept distinct -/// so reports preserve their natural shape (parity tolerance also depends on -/// it — integers are bit-exact, floats have per-metric tolerance). -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -pub enum MetricValue { - Int(i64), - Float(f64), -} - -impl MetricValue { - pub fn as_f64(&self) -> f64 { - match self { - MetricValue::Int(i) => *i as f64, - MetricValue::Float(f) => *f, - } - } -} - -impl From for MetricValue { - fn from(v: i64) -> Self { - MetricValue::Int(v) - } -} - -impl From for MetricValue { - fn from(v: u32) -> Self { - MetricValue::Int(i64::from(v)) - } -} - -impl From for MetricValue { - fn from(v: u64) -> Self { - // Saturate large counts into a `Float` so values that exceed - // `i64::MAX` are still representable instead of silently wrapping - // to a negative integer. - if v <= i64::MAX as u64 { - MetricValue::Int(v as i64) - } else { - MetricValue::Float(v as f64) - } - } -} - -impl From for MetricValue { - fn from(v: usize) -> Self { - if v <= i64::MAX as usize { - MetricValue::Int(v as i64) - } else { - MetricValue::Float(v as f64) - } - } -} - -impl From for MetricValue { - fn from(v: f64) -> Self { - MetricValue::Float(v) - } -} - -/// The metric values published by an analyzer for a single space. -/// -/// Stored ordered (`BTreeMap`) so JSON snapshots are deterministic without -/// requiring a separate sort step at render time. -#[derive(Clone, Debug, Default, Serialize, Deserialize)] -#[serde(transparent)] -pub struct MetricSet(BTreeMap); - -impl MetricSet { - pub fn new() -> Self { - Self::default() - } - - pub fn insert(&mut self, key: impl Into, value: impl Into) { - self.0.insert(key.into(), value.into()); - } - - pub fn get(&self, key: &MetricKey) -> Option { - self.0.get(key).copied() - } - - pub fn remove(&mut self, key: &MetricKey) -> Option { - self.0.remove(key) - } - - pub fn iter(&self) -> impl Iterator { - self.0.iter() - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -/// A single fact contributed by an analyzer toward a metric. -/// -/// Per the rewrite plan §5.4: this is the explainability primitive. It lets -/// `mehen diff` answer "why did `cognitive` move +3 here" with a span and a -/// reason code. Not all analyzers need to produce contributions in 1.0 — the -/// shape exists so they can be added per metric without changing the report -/// schema. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct MetricContribution { - pub metric: MetricKey, - pub span: SourceSpan, - pub amount: f64, - pub reason: ContributionReason, -} - -/// Optional, deterministically ordered sink for analyzer contribution evidence. -/// -/// Analyzers can construct this directly from -/// [`crate::AnalysisConfig::emit_contributions`]. When disabled, [`record`](Self::record) -/// is a cheap no-op; when enabled, [`finish`](Self::finish) returns entries in -/// source order so JSON and snapshot output remain stable across parser walk -/// implementations and platforms. -#[derive(Debug)] -pub struct ContributionCollector { - enabled: bool, - entries: Vec, -} - -impl ContributionCollector { - pub fn new(enabled: bool) -> Self { - Self { - enabled, - entries: Vec::new(), - } - } - - pub fn is_enabled(&self) -> bool { - self.enabled - } - - pub fn record( - &mut self, - metric: impl Into, - span: SourceSpan, - amount: f64, - reason: impl Into, - ) { - if !self.enabled { - return; - } - self.entries.push(MetricContribution { - metric: metric.into(), - span, - amount, - reason: ContributionReason::new(reason), - }); - } - - pub fn finish(mut self) -> Vec { - self.entries.sort_by(|a, b| { - ( - a.span.start_byte, - a.span.end_byte, - &a.metric, - a.reason.as_str(), - ) - .cmp(&( - b.span.start_byte, - b.span.end_byte, - &b.metric, - b.reason.as_str(), - )) - .then_with(|| a.amount.total_cmp(&b.amount)) - }); - self.entries - } -} - -/// A namespaced reason code attached to a [`MetricContribution`]. -/// -/// Stored as a string so language crates can publish their own reason codes -/// (`python.match_case`, `typescript.decorator_stack`, -/// `markdown.heading_skip`) without coordinating an enum across crates. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(transparent)] -pub struct ContributionReason(pub String); - -impl ContributionReason { - pub fn new(s: impl Into) -> Self { - Self(s.into()) - } - - pub fn as_str(&self) -> &str { - &self.0 - } -} - -/// The canonical owned result returned by every language analyzer. -/// -/// `LanguageAnalysis` and everything inside it must be `'static` and `Send` — -/// no parser-arena borrows leak across the API boundary. This is the -/// invariant that keeps Oxc's bumpalo, Mago's Bump, and Ruff's text arenas -/// confined to the analyzer crate. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct LanguageAnalysis { - pub language: Language, - pub backend: AnalysisBackend, - pub diagnostics: Vec, - pub root: MetricSpace, - pub contributions: Vec, -} - -#[cfg(test)] -mod tests { - use super::*; - - fn assert_send_static() {} - - #[test] - fn language_analysis_is_send_static() { - // Compile-time check that the analyzer output never borrows from a - // parser arena. If a future field violates this, the build breaks - // and forces an explicit decision rather than a silent regression. - assert_send_static::(); - } - - #[test] - fn metric_set_is_ordered() { - let mut set = MetricSet::new(); - set.insert("z", 1u64); - set.insert("a", 2u64); - let keys: Vec<&str> = set.iter().map(|(k, _)| k.as_str()).collect(); - assert_eq!(keys, vec!["a", "z"]); - } - - #[test] - fn contribution_collector_is_gated_and_deterministic() { - let later = SourceSpan::new(20, 24, 3, 3); - let earlier = SourceSpan::new(2, 6, 1, 1); - let mut collector = ContributionCollector::new(true); - collector.record("risk", later, 2.0, "risk.write"); - collector.record("risk", earlier, 8.0, "risk.drop"); - let entries = collector.finish(); - assert_eq!(entries[0].span, earlier); - assert_eq!(entries[1].span, later); - - let mut disabled = ContributionCollector::new(false); - disabled.record("risk", earlier, 8.0, "risk.drop"); - assert!(disabled.finish().is_empty()); - } -} diff --git a/crates/mehen-core/src/analyzer.rs b/crates/mehen-core/src/analyzer.rs deleted file mode 100644 index 09b64b31..00000000 --- a/crates/mehen-core/src/analyzer.rs +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use crate::Result; -use crate::analysis::LanguageAnalysis; -use crate::backend::AnalysisBackend; -use crate::config::AnalysisConfig; -use crate::language::Language; -use crate::source::SourceFile; - -/// One language's analyzer. -/// -/// Implementors: -/// - own their parser instance per call (or per worker); analyzers are -/// constructed by the engine, never shared as parser instances, -/// - return owned [`LanguageAnalysis`] — no borrows from parser arenas, -/// - emit recoverable issues via `LanguageAnalysis::diagnostics`, not via -/// the `Result`. -/// -/// Crates that ship multiple analyzers (a tree-sitter baseline plus a future -/// Ruff/Oxc/Mago/Prism backend) implement this trait once per backend. -pub trait LanguageAnalyzer: Send + Sync { - fn language(&self) -> Language; - fn backend(&self) -> AnalysisBackend; - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result; -} - -/// The re-entrance hook used by Markdown's embedded-code metric and any -/// future analyzer that must analyze a nested language fragment. -/// -/// `mehen-engine` is the only implementor in 1.0. The seam exists so that -/// `mehen-markdown` does not need a compile-time dependency on every -/// language crate (rewrite plan review §3.3, §4.1). -pub trait LanguageDispatcher: Send + Sync { - /// Analyze a nested source file. Recursion limits, source-size limits, - /// and feature availability checks are enforced by the dispatcher - /// implementation, not by the caller. - fn analyze(&self, source: SourceFile, config: &AnalysisConfig) -> Result; -} diff --git a/crates/mehen-core/src/backend.rs b/crates/mehen-core/src/backend.rs deleted file mode 100644 index 395f233a..00000000 --- a/crates/mehen-core/src/backend.rs +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::{Deserialize, Serialize}; - -/// Identifies the parser backend that produced a [`crate::LanguageAnalysis`]. -/// -/// Surfaced in JSON output and snapshots so parity work and migration -/// snapshots can tell which backend was active. Per the rewrite plan, parser -/// choice is internal — there is no user-facing override flag — but the -/// label is still useful in reports. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub enum AnalysisBackend { - TreeSitter, - /// Ruff parser + semantic. Reserved for the Phase 6 Python migration. - PythonRuff, - /// Oxc parser. Reserved for the Phase 7 TypeScript/JS migration. - Oxc, - /// Mago syntax. Reserved for the Phase 8 PHP migration. - Mago, - /// `ruby-prism`. Reserved for the Phase 9 Ruby migration. - Prism, - /// rust-analyzer's `ra_ap_syntax` parser. Used by `mehen-rust` from - /// Phase 9 of the rewrite onward, replacing tree-sitter-rust. - RaApSyntax, - /// Pulldown-cmark parser used by `mehen-markdown`. - PulldownCmark, - /// sqruff (`quarylabs/sqruff`) dialect-aware SQL parser. Used by - /// `mehen-sql`. sqruff parses SQL into a single dialect-agnostic - /// `SyntaxKind` CST and ships the CTE/scope/wildcard analysis the SQL - /// metric family consumes (see `design-docs/sql_parser_comparison.md`). - Sqruff, - /// A parser generated from an ANTLR v4 grammar, running on the - /// `antlr4_runtime` Rust runtime (`ophi-dev/antlr-rust-runtime`). Used - /// by `mehen-kotlin` (official Kotlin spec grammar) and the substrate - /// for any future ANTLR-backed analyzer. The grammar's `.g4` files are - /// vendored per analyzer crate and the Rust parser/lexer modules are - /// generated by `cargo xtask antlr generate ` (cf. the - /// tree-sitter kind-enum generator). - Antlr, - /// Anything not yet covered. - Other(String), -} - -impl AnalysisBackend { - pub fn label(&self) -> &str { - match self { - AnalysisBackend::TreeSitter => "tree-sitter", - AnalysisBackend::PythonRuff => "python-ruff", - AnalysisBackend::Oxc => "oxc", - AnalysisBackend::Mago => "mago", - AnalysisBackend::Prism => "prism", - AnalysisBackend::RaApSyntax => "rust-ra-ap-syntax", - AnalysisBackend::PulldownCmark => "pulldown-cmark", - AnalysisBackend::Sqruff => "sqruff", - AnalysisBackend::Antlr => "antlr", - AnalysisBackend::Other(s) => s.as_str(), - } - } -} diff --git a/crates/mehen-core/src/config.rs b/crates/mehen-core/src/config.rs deleted file mode 100644 index f774feec..00000000 --- a/crates/mehen-core/src/config.rs +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::{Deserialize, Serialize}; - -/// Configuration handed to a [`crate::LanguageAnalyzer::analyze`] call. -/// -/// Kept intentionally small in 1.0 — analyzer-specific options should live -/// inside the analyzer's own crate. This struct exists so analyzers see -/// engine-level decisions (max recursion depth for embedded analysis, -/// whether to compute contributions, …) without each analyzer reinventing -/// the parameter shape. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct AnalysisConfig { - /// If true, analyzers should populate `LanguageAnalysis::contributions` - /// with explainable evidence. When false, analyzers may skip the work - /// for performance. - /// - /// `Default::default()` and [`AnalysisConfig::benchmark`] leave this - /// `false`; [`AnalysisConfig::production`] sets it to `true`. - pub emit_contributions: bool, - - /// Maximum recursion depth for [`crate::LanguageDispatcher::analyze`] - /// requests. Used by Markdown's embedded-code path to bound nested - /// fence-in-fence cases. Zero disables nested analysis entirely. - pub max_dispatch_depth: u8, - - /// The current dispatch depth — incremented by the dispatcher on each - /// recursive call. Analyzers do not need to read this; the dispatcher - /// uses it to enforce `max_dispatch_depth`. - pub dispatch_depth: u8, -} - -/// Default `max_dispatch_depth` for `production()` / `benchmark()` / -/// `Default`. Bounds embedded-code recursion (Markdown fences, future -/// dispatch-driven analyzers); the value is large enough to cover every -/// realistic doc-in-doc chain we ship. -const DEFAULT_MAX_DISPATCH_DEPTH: u8 = 4; - -impl Default for AnalysisConfig { - /// Produce a config that callers can use without immediately tripping - /// the dispatch-depth guard. The derived `Default` would have set - /// `max_dispatch_depth = 0`, which makes `EngineDispatcher::analyze` - /// reject on the very first call — see PR #95 review and the - /// `default_allows_at_least_one_dispatch` test below. - fn default() -> Self { - Self { - emit_contributions: false, - max_dispatch_depth: DEFAULT_MAX_DISPATCH_DEPTH, - dispatch_depth: 0, - } - } -} - -impl AnalysisConfig { - /// Defaults appropriate for production CLI use. - pub fn production() -> Self { - Self { - emit_contributions: true, - max_dispatch_depth: DEFAULT_MAX_DISPATCH_DEPTH, - dispatch_depth: 0, - } - } - - /// Defaults appropriate for benchmarks where contribution evidence is - /// not consumed. - pub fn benchmark() -> Self { - Self { - emit_contributions: false, - max_dispatch_depth: DEFAULT_MAX_DISPATCH_DEPTH, - dispatch_depth: 0, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn default_allows_at_least_one_dispatch() { - // Regression: the derived `Default` impl set `max_dispatch_depth` - // to `0`, which made `EngineDispatcher::analyze` (which rejects - // when `dispatch_depth >= max_dispatch_depth`) fail on the very - // first dispatch with "max dispatch depth exceeded (0)". The - // manual impl below sets the depth to a realistic ceiling so - // callers using `AnalysisConfig::default()` aren't immediately - // blocked. - let config = AnalysisConfig::default(); - assert!( - config.max_dispatch_depth > config.dispatch_depth, - "Default config must allow at least one dispatch; got \ - max_dispatch_depth={} dispatch_depth={}", - config.max_dispatch_depth, - config.dispatch_depth - ); - } - - #[test] - fn default_matches_production_depth_budget() { - // The dispatch budget is shared across the named constructors so - // that callers who pick `default()` get the same recursion ceiling - // as `production()` — only `emit_contributions` differs. - let default = AnalysisConfig::default(); - let production = AnalysisConfig::production(); - assert_eq!(default.max_dispatch_depth, production.max_dispatch_depth); - assert_eq!(default.dispatch_depth, production.dispatch_depth); - assert_eq!(default.dispatch_depth, 0); - } -} diff --git a/crates/mehen-core/src/diagnostic.rs b/crates/mehen-core/src/diagnostic.rs deleted file mode 100644 index 56b1327c..00000000 --- a/crates/mehen-core/src/diagnostic.rs +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::{Deserialize, Serialize}; - -use crate::span::SourceSpan; - -/// Severity of a [`ParseDiagnostic`]. -/// -/// Per the rewrite plan §9.3: -/// - `Warning`: recoverable, exit 0 unless thresholds fail. -/// - `Error`: analysis incomplete; `mehen metrics` exits 1, `mehen diff` -/// records under `analysis_errors`. -/// - `Fatal`: IO/toolchain/invariant failure; exit 1. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum DiagnosticSeverity { - Warning, - Error, - Fatal, -} - -/// A diagnostic emitted by an analyzer. -/// -/// Diagnostics are *non-fatal* by default — analyzers should produce the -/// best partial report they can and attach the diagnostic instead of -/// returning an error. Only the engine's exit-code mapping -/// (`mehen-engine::ci::exit_code_from_diagnostics`) translates severity -/// into a process exit code. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct ParseDiagnostic { - pub severity: DiagnosticSeverity, - /// Stable identifier (`"python.parse_error"`, `"markdown.unclosed_fence"`). - pub code: String, - pub message: String, - pub span: Option, -} - -impl ParseDiagnostic { - pub fn warning(code: impl Into, message: impl Into) -> Self { - Self { - severity: DiagnosticSeverity::Warning, - code: code.into(), - message: message.into(), - span: None, - } - } - - pub fn error(code: impl Into, message: impl Into) -> Self { - Self { - severity: DiagnosticSeverity::Error, - code: code.into(), - message: message.into(), - span: None, - } - } - - pub fn fatal(code: impl Into, message: impl Into) -> Self { - Self { - severity: DiagnosticSeverity::Fatal, - code: code.into(), - message: message.into(), - span: None, - } - } - - pub fn with_span(mut self, span: SourceSpan) -> Self { - self.span = Some(span); - self - } -} diff --git a/crates/mehen-core/src/language.rs b/crates/mehen-core/src/language.rs deleted file mode 100644 index 71947583..00000000 --- a/crates/mehen-core/src/language.rs +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use core::fmt; -use core::str::FromStr; - -use serde::{Deserialize, Serialize}; - -/// The set of languages mehen knows how to identify. -/// -/// The enum is intentionally not feature-gated. A variant can exist even -/// when its analyzer crate is disabled in the current build — in that case, -/// `mehen-engine` returns an `AnalyzerUnavailable` diagnostic. This keeps -/// `match` statements stable across feature combinations. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum Language { - Python, - TypeScript, - Tsx, - JavaScript, - Jsx, - Php, - Ruby, - Rust, - Go, - Kotlin, - Java, - CSharp, - PowerShell, - C, - Markdown, - Sql, -} - -/// Error returned by [`Language::from_str`] for unknown identifiers. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct LanguageParseError(String); - -impl fmt::Display for LanguageParseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "unknown language identifier: `{}`", self.0) - } -} - -impl core::error::Error for LanguageParseError {} - -impl Language { - /// The canonical lowercase identifier used in JSON and CLI output. - pub fn canonical(&self) -> &'static str { - match self { - Language::Python => "python", - Language::TypeScript => "typescript", - Language::Tsx => "tsx", - Language::JavaScript => "javascript", - Language::Jsx => "jsx", - Language::Php => "php", - Language::Ruby => "ruby", - Language::Rust => "rust", - Language::Go => "go", - Language::Kotlin => "kotlin", - Language::Java => "java", - Language::CSharp => "csharp", - Language::PowerShell => "powershell", - Language::C => "c", - Language::Markdown => "markdown", - Language::Sql => "sql", - } - } -} - -impl fmt::Display for Language { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.canonical()) - } -} - -impl FromStr for Language { - type Err = LanguageParseError; - - fn from_str(s: &str) -> Result { - // Mapping documented in the rewrite plan §4.2. - let normalized = s.trim().to_ascii_lowercase(); - let lang = match normalized.as_str() { - "python" | "py" => Language::Python, - "typescript" | "ts" | "mts" | "cts" => Language::TypeScript, - "javascript" | "js" | "mjs" | "cjs" => Language::JavaScript, - "tsx" => Language::Tsx, - "jsx" => Language::Jsx, - "php" | "php3" | "php4" | "php5" | "php7" | "php8" | "phtml" => Language::Php, - "ruby" | "rb" => Language::Ruby, - "rust" | "rs" => Language::Rust, - "go" => Language::Go, - "kotlin" | "kt" | "kts" => Language::Kotlin, - "java" => Language::Java, - // `cs` is the file extension; `csx` is a C# script. `c#`/`c-sharp` - // are accepted spellings a user may type on the CLI. - "csharp" | "cs" | "csx" | "c#" | "c-sharp" => Language::CSharp, - "powershell" | "pwsh" | "ps1" | "psm1" | "psd1" => Language::PowerShell, - "c" | "h" => Language::C, - "markdown" | "md" | "mdx" | "mdown" | "mkd" | "mkdn" => Language::Markdown, - "sql" | "ddl" | "dml" => Language::Sql, - _ => return Err(LanguageParseError(s.to_string())), - }; - Ok(lang) - } -} - -/// Returns the list of accepted identifiers for a given language. Useful for -/// CLI help text and migration guides. -pub fn language_aliases(lang: Language) -> &'static [&'static str] { - match lang { - Language::Python => &["python", "py"], - Language::TypeScript => &["typescript", "ts", "mts", "cts"], - Language::JavaScript => &["javascript", "js", "mjs", "cjs"], - Language::Tsx => &["tsx"], - Language::Jsx => &["jsx"], - Language::Php => &["php", "php3", "php4", "php5", "php7", "php8", "phtml"], - Language::Ruby => &["ruby", "rb"], - Language::Rust => &["rust", "rs"], - Language::Go => &["go"], - Language::Kotlin => &["kotlin", "kt", "kts"], - Language::Java => &["java"], - Language::CSharp => &["csharp", "cs", "csx", "c#", "c-sharp"], - Language::PowerShell => &["powershell", "pwsh", "ps1", "psm1", "psd1"], - Language::C => &["c", "h"], - Language::Markdown => &["markdown", "md", "mdx", "mdown", "mkd", "mkdn"], - Language::Sql => &["sql", "ddl", "dml"], - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parses_canonical_identifiers() { - for lang in [ - Language::Python, - Language::TypeScript, - Language::Tsx, - Language::JavaScript, - Language::Jsx, - Language::Php, - Language::Ruby, - Language::Rust, - Language::Go, - Language::Kotlin, - Language::Java, - Language::CSharp, - Language::PowerShell, - Language::C, - Language::Markdown, - ] { - assert_eq!(lang.canonical().parse::().unwrap(), lang); - } - } - - #[test] - fn parses_aliases() { - assert_eq!("py".parse::().unwrap(), Language::Python); - assert_eq!("MTS".parse::().unwrap(), Language::TypeScript); - assert_eq!("rb".parse::().unwrap(), Language::Ruby); - assert_eq!("kts".parse::().unwrap(), Language::Kotlin); - assert_eq!("mdx".parse::().unwrap(), Language::Markdown); - assert_eq!("cs".parse::().unwrap(), Language::CSharp); - assert_eq!("C#".parse::().unwrap(), Language::CSharp); - } - - #[test] - fn rejects_unknown() { - assert!("klingon".parse::().is_err()); - } -} diff --git a/crates/mehen-core/src/lib.rs b/crates/mehen-core/src/lib.rs deleted file mode 100644 index a3dc762f..00000000 --- a/crates/mehen-core/src/lib.rs +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-core` — parser-neutral domain types and analyzer traits. -//! -//! This crate is the contract layer between language analyzers and the -//! orchestration in `mehen-engine`. It exposes the shape of an analyzer's -//! output (`LanguageAnalysis`), the trait analyzers implement -//! (`LanguageAnalyzer`), and the re-entrance hook (`LanguageDispatcher`) -//! used by Markdown's embedded-code path and any future analyzer that -//! needs to recursively analyze a nested language fragment. -//! -//! Design notes (see `docs/mehen-1-0-from-scratch-rewrite-plan.md`): -//! - `LanguageAnalysis` is owned and `Send + 'static` — no parser-arena -//! borrows leak across the API boundary. -//! - `SpaceKind` is intentionally open via `Custom(SmolStr)` so declarative -//! analyzers (CloudFormation, Terraform, Kubernetes) can publish their -//! own scope kinds without amending a closed enum. -//! - `MetricKey` is an open namespace, not a closed enum, for the same -//! reason — language families can publish their own keys -//! (e.g. `cloudformation.iam_spcm`) under the shared namespace. - -#![forbid(unsafe_code)] - -mod analysis; -mod analyzer; -mod backend; -mod config; -mod diagnostic; -mod language; -mod line_index; -mod metric_key; -mod report; -mod selector; -mod source; -mod space; -mod span; -mod threshold; - -pub use analysis::{ - ContributionCollector, ContributionReason, LanguageAnalysis, MetricContribution, MetricSet, - MetricValue, -}; -pub use analyzer::{LanguageAnalyzer, LanguageDispatcher}; -pub use backend::AnalysisBackend; -pub use config::AnalysisConfig; -pub use diagnostic::{DiagnosticSeverity, ParseDiagnostic}; -pub use language::{Language, LanguageParseError, language_aliases}; -pub use line_index::LineIndex; -pub use metric_key::{MetricKey, keys}; -pub use report::{ - AnalysisErrorRecord, AnalyzeMetricsInput, DiffFile, DiffInput, DiffReport, DiffSide, - MetricsReport, TopOffenderEntry, TopOffendersInput, TopOffendersReport, -}; -pub use selector::{MetricSelector, SelectorAggregator, SelectorParseError}; -pub use source::SourceFile; -pub use space::{MetricSpace, SpaceId, SpaceKind}; -// `SmolStr` is part of the public API via `SpaceKind::Custom(SmolStr)`, so -// re-export it — callers (and tests) can construct custom spaces without a -// separate `smol_str` dependency. -pub use smol_str::SmolStr; -pub use span::{SourceSpan, byte_offset_checked, byte_offset_clamped}; -pub use threshold::{Polarity, Threshold, ThresholdEvaluation, ThresholdViolation}; - -/// The result type used by analyzers and the dispatcher. -pub type Result = core::result::Result; - -/// Errors that flow through the analyzer interface. Recoverable issues -/// (parse errors, partial reports) belong on [`LanguageAnalysis::diagnostics`] -/// instead — `AnalysisError` is reserved for fatal conditions that prevent -/// producing any report at all. -#[derive(Debug)] -#[non_exhaustive] -pub enum AnalysisError { - /// The requested language is structurally invalid for the operation. - UnsupportedLanguage(Language), - /// The owning analyzer crate was not compiled into this build. - AnalyzerUnavailable(Language), - /// Internal invariant violation — file a bug. - Internal(String), - /// IO failure reaching the source. - Io(String), -} - -impl core::fmt::Display for AnalysisError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Self::UnsupportedLanguage(l) => write!(f, "unsupported language: {l:?}"), - Self::AnalyzerUnavailable(l) => { - write!( - f, - "language `{l:?}` has no registered analyzer in this build" - ) - } - Self::Internal(msg) => write!(f, "internal invariant: {msg}"), - Self::Io(msg) => write!(f, "io error: {msg}"), - } - } -} - -impl core::error::Error for AnalysisError {} - -impl From for AnalysisError { - fn from(value: std::io::Error) -> Self { - AnalysisError::Io(value.to_string()) - } -} diff --git a/crates/mehen-core/src/line_index.rs b/crates/mehen-core/src/line_index.rs deleted file mode 100644 index 4ffc9629..00000000 --- a/crates/mehen-core/src/line_index.rs +++ /dev/null @@ -1,252 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::{Deserialize, Serialize}; - -/// Maps byte offsets to 1-based line numbers within a source file. -/// -/// This exists in `mehen-core` rather than each analyzer crate because every -/// analyzer needs a single canonical byte/line mapping implementation. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct LineIndex { - /// Byte offsets at which each line starts. `line_starts[0]` is always 0. - line_starts: Vec, -} - -impl Default for LineIndex { - fn default() -> Self { - Self { - line_starts: vec![0], - } - } -} - -impl LineIndex { - /// Build the row index for `text`. - /// - /// A row ends at `\n`, and CRLF is one break rather than two. This is the - /// **default** policy, and the one every tree-sitter-backed analyzer needs: - /// tree-sitter's own `Point::row` advances at LF only, and a space's LOC span is set - /// from those rows, so an index counting more terminators than the parser would claim - /// rows the walker never routes tokens to. - /// - /// A **lone** `\r` therefore does NOT end a row here. It did briefly, and that was - /// the same over-reach as counting the Unicode separators unconditionally: a Go or C - /// file containing a classic-Mac line ending gained a row in the index that - /// tree-sitter never reports, so a byte-derived `SourceSpan` landed on row 2 while the - /// LOC observations stayed on row 1. - /// - /// Use [`LineIndex::with_unicode_separators`] for a language whose *lexer* treats the - /// other four terminators as row breaks — C# does (ECMA-334 §6.3.1 lists all five). - /// When the index and the lexer disagree, a file parses correctly while reporting the - /// wrong number of rows and attributing declarations to rows they are not on. - pub fn new(text: &str) -> Self { - Self::build(text, false) - } - - /// As [`LineIndex::new`], but a lone `\r`, NEL (U+0085), LS (U+2028), and PS - /// (U+2029) also end a row. - /// - /// For a language whose lexer accepts them, which makes them real row breaks in that - /// file. Kept opt-in rather than universal because the row *source* has to agree: a - /// tree-sitter parser reports LF-only rows, so widening the index there produces - /// spans whose `end_line` exceeds any row the walker observes — a phantom blank - /// line. - /// - /// The name says "unicode separators" for the three that are; the lone `\r` rides - /// along because it needs the identical treatment and no caller wants one without the - /// other. - pub fn with_unicode_separators(text: &str) -> Self { - Self::build(text, true) - } - - /// Scanning `char_indices` rather than bytes keeps the multi-byte separators from - /// being missed when `extended` is set. - fn build(text: &str, extended: bool) -> Self { - let mut line_starts = Vec::with_capacity(text.len() / 32 + 1); - line_starts.push(0u32); - let mut chars = text.char_indices().peekable(); - while let Some((i, c)) = chars.next() { - let is_break = match c { - // CRLF is a single break under either policy. Consume the `\n` here so - // the pair does not push two row starts; the break itself is then - // unconditional, since the `\n` would have counted anyway. - '\r' => { - if chars.peek().is_some_and(|&(_, next)| next == '\n') { - chars.next(); - true - } else { - // A LONE `\r` follows the extended policy, exactly as the three - // Unicode separators do and for the same reason: tree-sitter - // reports LF-only rows, so counting it in the default index gives - // a file a row the walker never observes. - extended - } - } - '\n' => true, - '\u{85}' | '\u{2028}' | '\u{2029}' => extended, - _ => false, - }; - if is_break { - // The next row starts after whatever was consumed, which for CRLF is - // two characters. - let consumed = if c == '\r' && text[i..].starts_with("\r\n") { - 2 - } else { - c.len_utf8() - }; - line_starts.push((i + consumed) as u32); - } - } - Self { line_starts } - } - - /// Returns the 1-based line number containing `byte_offset`. - pub fn line_at(&self, byte_offset: u32) -> u32 { - // Binary search for the largest `line_starts[i] <= byte_offset`. - match self.line_starts.binary_search(&byte_offset) { - Ok(i) => (i + 1) as u32, - Err(i) => i.max(1) as u32, - } - } - - /// Total line count (a final blank line is included). - pub fn line_count(&self) -> u32 { - self.line_starts.len() as u32 - } - - /// Returns `(start_byte, end_byte)` for a 1-based line number, exclusive - /// of the trailing newline. Returns `None` for out-of-range lines. - pub fn line_byte_range(&self, line: u32, total_len: u32) -> Option<(u32, u32)> { - if line == 0 || (line as usize) > self.line_starts.len() { - return None; - } - let idx = (line - 1) as usize; - let start = self.line_starts[idx]; - let end = self - .line_starts - .get(idx + 1) - .map(|next| next.saturating_sub(1)) - .unwrap_or(total_len); - Some((start, end)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn unicode_line_separators_start_new_rows_when_opted_in() { - // REGRESSION. Only `\n` counted, so a file split by NEL / U+2028 / U+2029 - // reported one physical row and attributed every declaration to it. C#'s lexer - // accepts all five terminators (ECMA-334 §6.3.1), so it could tokenize a - // multi-row file that this index called one line. - for separator in ['\n', '\u{85}', '\u{2028}', '\u{2029}'] { - let text = format!("a{separator}b"); - let index = LineIndex::with_unicode_separators(&text); - assert_eq!( - index.line_count(), - 2, - "U+{:04X} must start a new row", - separator as u32 - ); - // The character after the separator is on row 2. - let after = (1 + separator.len_utf8()) as u32; - assert_eq!(index.line_at(after), 2); - } - } - - #[test] - fn the_default_policy_ignores_unicode_separators() { - // `new` stays LF/CRLF-only, and that is load-bearing rather than conservative: - // every tree-sitter-backed analyzer sets a space's LOC span from tree-sitter's - // own `Point::row`, which advances at LF alone. An index counting more - // terminators than the parser claims rows the walker never routes tokens to — - // a phantom blank line in, say, a Go raw string containing U+2028. - for separator in ['\u{85}', '\u{2028}', '\u{2029}'] { - let text = format!("a{separator}b"); - assert_eq!( - LineIndex::new(&text).line_count(), - 1, - "U+{:04X} is not a row break under the default policy", - separator as u32 - ); - } - // LF and CRLF break under both policies. - assert_eq!(LineIndex::new("a\nb").line_count(), 2); - assert_eq!(LineIndex::new("a\r\nb").line_count(), 2); - } - - #[test] - fn a_lone_carriage_return_follows_the_extended_policy() { - // This test has been inverted twice, and the history is the point. - // - // Originally a bare `\r` was excluded, on the reasoning that CRLF works through - // its `\n` and a stray `\r` is a classic-Mac artifact. That is wrong for a - // language whose *lexer* treats it as a terminator — C#'s does (ECMA-334 §6.3.1) - // — so the index disagreed with the lexer that produced the tokens and every - // declaration after a `\r` was attributed to the previous row. - // - // It was then made unconditional, which over-reached in the other direction: - // tree-sitter's `Point::row` advances at LF only, so a Go or C file with a - // classic-Mac line ending gained a row the walker never observes — a byte-derived - // `SourceSpan` on row 2 against LOC observations on row 1. - // - // Both are true at once, which means it is a *policy* question rather than a - // single right answer — exactly like the three Unicode separators, which had - // already been split for the identical reason. So the lone `\r` is gated the same - // way, and neither language is wrong about its own files. - assert_eq!( - LineIndex::new("a\rb").line_count(), - 1, - "the default (tree-sitter) policy counts LF only" - ); - let extended = LineIndex::with_unicode_separators("a\rb"); - assert_eq!(extended.line_count(), 2); - assert_eq!(extended.line_at(2), 2); - } - - #[test] - fn crlf_is_one_break_under_both_policies() { - // The `\r` of a CRLF pair breaks regardless, because the `\n` after it would - // have. Only a LONE `\r` is policy-dependent, so the pair must not become two - // rows under the extended policy nor zero under the default. - assert_eq!(LineIndex::new("a\r\nb").line_count(), 2); - assert_eq!(LineIndex::with_unicode_separators("a\r\nb").line_count(), 2); - } - - #[test] - fn crlf_counts_one_row_break() { - let index = LineIndex::new("a\r\nb"); - assert_eq!(index.line_count(), 2); - } - - #[test] - fn empty_text_has_one_line() { - let idx = LineIndex::new(""); - assert_eq!(idx.line_count(), 1); - assert_eq!(idx.line_at(0), 1); - } - - #[test] - fn line_at_boundaries() { - // bytes: 0 1 2 3 4 5 6 7 8 9 - // text: a b \n c d \n e f \n - let idx = LineIndex::new("ab\ncd\nef\n"); - assert_eq!(idx.line_at(0), 1); - assert_eq!(idx.line_at(2), 1); // '\n' on line 1 - assert_eq!(idx.line_at(3), 2); - assert_eq!(idx.line_at(5), 2); - assert_eq!(idx.line_at(6), 3); - } - - #[test] - fn byte_range_for_line() { - let text = "ab\ncd\nef"; - let idx = LineIndex::new(text); - assert_eq!(idx.line_byte_range(1, text.len() as u32), Some((0, 2))); - assert_eq!(idx.line_byte_range(2, text.len() as u32), Some((3, 5))); - assert_eq!(idx.line_byte_range(3, text.len() as u32), Some((6, 8))); - } -} diff --git a/crates/mehen-core/src/metric_key.rs b/crates/mehen-core/src/metric_key.rs deleted file mode 100644 index c4fd28d5..00000000 --- a/crates/mehen-core/src/metric_key.rs +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use core::fmt; - -use serde::{Deserialize, Serialize}; -use smol_str::SmolStr; - -/// A metric identifier in mehen's open metric namespace. -/// -/// The shared contract names a *minimum* metric set for source-code languages -/// (`cyclomatic`, `cognitive`, `halstead.volume`, …). Language analyzers may -/// publish additional keys under the same namespace (for example, -/// `cloudformation.iam_spcm`, `terraform.dependency_depth`, -/// `markdown.heading_skip`). -/// -/// Keys are stored as `SmolStr` so common keys are inline and free of -/// allocation, while custom namespaced keys remain available without changing -/// the type. -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -#[serde(transparent)] -pub struct MetricKey(SmolStr); - -impl MetricKey { - pub fn new(key: impl Into) -> Self { - Self(key.into()) - } - - pub fn as_str(&self) -> &str { - self.0.as_str() - } -} - -impl fmt::Display for MetricKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.0.as_str()) - } -} - -impl From<&str> for MetricKey { - fn from(s: &str) -> Self { - Self::new(s) - } -} - -impl From for MetricKey { - fn from(s: String) -> Self { - Self::new(s) - } -} - -/// Stable string keys for the source-code minimum metric family. Language -/// analyzers should prefer these constants over ad-hoc string literals so that -/// renames stay in one place. -pub mod keys { - pub const CYCLOMATIC: &str = "cyclomatic"; - /// Rolled-up cyclomatic complexity (`Σ decisions + 1` per folded - /// space) as published by the shared walker. Contribution evidence - /// attaches here — the bare per-space key does not move when a - /// nested function's complexity changes. - pub const CYCLOMATIC_SUM: &str = "cyclomatic.sum"; - pub const COGNITIVE: &str = "cognitive"; - pub const LOC: &str = "loc"; - pub const LOC_LLOC: &str = "loc.lloc"; - pub const LOC_SLOC: &str = "loc.sloc"; - pub const LOC_PLOC: &str = "loc.ploc"; - pub const LOC_CLOC: &str = "loc.cloc"; - pub const LOC_BLANK: &str = "loc.blank"; - pub const HALSTEAD: &str = "halstead"; - pub const HALSTEAD_VOLUME: &str = "halstead.volume"; - pub const HALSTEAD_DIFFICULTY: &str = "halstead.difficulty"; - pub const HALSTEAD_EFFORT: &str = "halstead.effort"; - pub const HALSTEAD_VOCABULARY: &str = "halstead.vocabulary"; - pub const HALSTEAD_LENGTH: &str = "halstead.length"; - pub const MI_VS: &str = "mi.visual_studio"; - pub const MI_ORIGINAL: &str = "mi.original"; - pub const MI_SEI: &str = "mi.sei"; - pub const ABC: &str = "abc"; - /// ABC bucket sub-keys, published by `mehen-metrics::state::publish_abc` - /// and referenced by contribution evidence — shared so the two cannot - /// drift apart. - pub const ABC_ASSIGNMENTS: &str = "abc.assignments"; - pub const ABC_BRANCHES: &str = "abc.branches"; - pub const ABC_CONDITIONS: &str = "abc.conditions"; - pub const NARGS: &str = "nargs"; - pub const NOM: &str = "nom"; - /// NOM bucket sub-keys, shared between `state::publish_nom` and - /// contribution evidence. - pub const NOM_FUNCTIONS: &str = "nom.functions"; - pub const NOM_CLOSURES: &str = "nom.closures"; - pub const NEXIT: &str = "nexit"; - /// Rolled-up exit count across folded spaces — the aggregate that - /// moves when a function gains an exit; contribution evidence - /// attaches here. - pub const NEXIT_SUM: &str = "nexit.sum"; - pub const NPA: &str = "npa"; - pub const NPM: &str = "npm"; - pub const WMC: &str = "wmc"; - /// Rolled-up cognitive complexity as published onto the root - /// `MetricSpace` by the shared walker. - pub const COGNITIVE_SUM: &str = "cognitive.sum"; - - // SQL- and Markdown-analyzer-owned keys referenced by the engine's - // history composites (relative churn and hotspot read each - // language family's equivalents of `loc.sloc` / `cognitive.sum`). - pub const SQL_LOC_CODE: &str = "sql.loc.code"; - pub const SQL_COGNITIVE_COMPLEXITY: &str = "sql.cognitive_complexity"; - pub const MARKDOWN_LOC_TLOC: &str = "markdown.loc.tloc"; - pub const MARKDOWN_COGNITIVE_COMPLEXITY: &str = "markdown.complexity.cognitive_complexity"; - - // Git history process metrics (`history.*` family, research - // foundation §6). Repository-scope: published by the engine's - // history enrichment, not by language analyzers. - pub const HISTORY_CHURN_ABS: &str = "history.churn.abs"; - pub const HISTORY_CHURN_RELATIVE: &str = "history.churn.relative"; - pub const HISTORY_AGE_MONTHS: &str = "history.age_months"; - pub const HISTORY_AUTHORS: &str = "history.authors"; - pub const HISTORY_MINOR_CONTRIBUTORS: &str = "history.minor_contributors"; - pub const HISTORY_OWNERSHIP: &str = "history.ownership"; - pub const HISTORY_COMMIT_FREQUENCY: &str = "history.commit_frequency"; - pub const HISTORY_HOTSPOT: &str = "history.hotspot"; - pub const HISTORY_SUM_OF_COUPLING: &str = "history.sum_of_coupling"; - pub const HISTORY_TWR: &str = "history.twr"; - pub const HISTORY_BUGFIX_COMMITS: &str = "history.bugfix_commits"; - - /// The complete `history.*` family. Unlike the extensible - /// language-owned namespaces, these engine-published keys are - /// fixed — selector parsing validates `history.*` names against - /// this set so a typo is rejected up front instead of triggering - /// the expensive repository walk and reading `0.0` through the - /// missing-key fallback. - pub const HISTORY_ALL: &[&str] = &[ - HISTORY_CHURN_ABS, - HISTORY_CHURN_RELATIVE, - HISTORY_AGE_MONTHS, - HISTORY_AUTHORS, - HISTORY_MINOR_CONTRIBUTORS, - HISTORY_OWNERSHIP, - HISTORY_COMMIT_FREQUENCY, - HISTORY_HOTSPOT, - HISTORY_SUM_OF_COUPLING, - HISTORY_TWR, - HISTORY_BUGFIX_COMMITS, - ]; - - // Test-coverage metrics (`coverage.*` family). Report-scope: - // published by the engine's coverage enrichment from ingested - // coverage reports (LCOV, Cobertura, JaCoCo, …), not by language - // analyzers. Rates are percentages in `0.0..=100.0`; counts are - // covered/total pairs. A file absent from every report publishes - // nothing — "unmeasured" must stay distinguishable from "0%". - pub const COVERAGE_LINE: &str = "coverage.line"; - pub const COVERAGE_LINE_COVERED: &str = "coverage.line.covered"; - pub const COVERAGE_LINE_TOTAL: &str = "coverage.line.total"; - pub const COVERAGE_BRANCH: &str = "coverage.branch"; - pub const COVERAGE_BRANCH_COVERED: &str = "coverage.branch.covered"; - pub const COVERAGE_BRANCH_TOTAL: &str = "coverage.branch.total"; - pub const COVERAGE_FUNCTION: &str = "coverage.function"; - pub const COVERAGE_FUNCTION_COVERED: &str = "coverage.function.covered"; - pub const COVERAGE_FUNCTION_TOTAL: &str = "coverage.function.total"; - - /// The complete `coverage.*` family — fixed, like - /// [`HISTORY_ALL`], so selector/threshold typos are rejected up - /// front instead of triggering report discovery and parsing only - /// to read an unpublished key. - pub const COVERAGE_ALL: &[&str] = &[ - COVERAGE_LINE, - COVERAGE_LINE_COVERED, - COVERAGE_LINE_TOTAL, - COVERAGE_BRANCH, - COVERAGE_BRANCH_COVERED, - COVERAGE_BRANCH_TOTAL, - COVERAGE_FUNCTION, - COVERAGE_FUNCTION_COVERED, - COVERAGE_FUNCTION_TOTAL, - ]; -} diff --git a/crates/mehen-core/src/report.rs b/crates/mehen-core/src/report.rs deleted file mode 100644 index a7adab51..00000000 --- a/crates/mehen-core/src/report.rs +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use camino::Utf8PathBuf; -use serde::{Deserialize, Serialize}; - -use crate::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, MetricContribution, - MetricSelector, MetricSpace, ParseDiagnostic, SourceFile, SourceSpan, SpaceId, SpaceKind, - Threshold, ThresholdViolation, -}; - -/// Inputs to `analyze_metrics`. -#[derive(Clone, Debug)] -pub struct AnalyzeMetricsInput { - pub source: SourceFile, - pub config: AnalysisConfig, -} - -/// `mehen metrics` JSON output shape (rewrite plan §9.1). -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct MetricsReport { - pub schema_version: String, - pub tool: String, - pub path: Utf8PathBuf, - pub language: Language, - pub analysis_backend: AnalysisBackend, - pub diagnostics: Vec, - pub root: MetricSpace, - /// Source-resolved evidence emitted by the analyzer. Empty for analyzers - /// or profiles that do not request contribution collection. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub contributions: Vec, -} - -impl MetricsReport { - pub fn empty() -> Self { - // Used as the seed shape in tests / docs. Production callers go - // through `From`. - Self { - schema_version: "1.0".to_string(), - tool: "mehen".to_string(), - path: Utf8PathBuf::new(), - language: Language::Markdown, - analysis_backend: AnalysisBackend::TreeSitter, - diagnostics: Vec::new(), - root: MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()), - contributions: Vec::new(), - } - } -} - -impl From for MetricsReport { - fn from(analysis: LanguageAnalysis) -> Self { - Self { - schema_version: "1.0".to_string(), - tool: "mehen".to_string(), - path: Utf8PathBuf::new(), - language: analysis.language, - analysis_backend: analysis.backend, - diagnostics: analysis.diagnostics, - root: analysis.root, - contributions: analysis.contributions, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ContributionReason, MetricContribution, MetricKey}; - - #[test] - fn language_analysis_conversion_preserves_contributions() { - let contribution = MetricContribution { - metric: MetricKey::new("sql.change_risk_score"), - span: SourceSpan::new(0, 4, 1, 1), - amount: 8.0, - reason: ContributionReason::new("sql.change_risk.drop"), - }; - let analysis = LanguageAnalysis { - language: Language::Sql, - backend: AnalysisBackend::Sqruff, - diagnostics: Vec::new(), - root: MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()), - contributions: vec![contribution.clone()], - }; - - let report = MetricsReport::from(analysis); - assert_eq!(report.contributions, vec![contribution]); - } -} - -/// Inputs to `analyze_diff`. -/// -/// Changed files marked `linguist-generated`, `linguist-vendored`, or -/// `binary` by Git attributes are excluded from analysis. Added and modified -/// files use attributes from the requested head revision; deleted files use -/// attributes from the base revision where they still exist. -#[derive(Clone, Debug)] -pub struct DiffInput { - pub from: String, - pub to: String, - pub paths: Vec, - pub thresholds: Vec, - pub config: AnalysisConfig, -} - -/// `mehen diff --format json` output shape (rewrite plan §9.2). -#[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct DiffReport { - pub schema_version: String, - pub base: String, - pub head: String, - pub files: Vec, - pub markdown_files: Vec, - pub analysis_errors: Vec, - pub threshold_violations: Vec, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DiffFile { - pub path: Utf8PathBuf, - // Phase 5 fills in metric deltas. Kept skeletal here so diff JSON has a - // documented shape even before the orchestrator lands. -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct AnalysisErrorRecord { - pub path: Utf8PathBuf, - pub side: DiffSide, - pub diagnostics: Vec, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum DiffSide { - Base, - Head, -} - -/// Inputs to `rank_top_offenders`. -/// -/// Directory paths are traversed with standard ignore rules: hidden entries, -/// `.ignore`, `.gitignore`, `.git/info/exclude`, parent rules, and the user's -/// global Git excludes are respected. Files marked `linguist-generated`, -/// `linguist-vendored`, or `binary` by Git attributes are also excluded. An -/// explicitly supplied file path is still analyzed even when a default ignore -/// rule matches it. -#[derive(Clone, Debug)] -pub struct TopOffendersInput { - pub paths: Vec, - pub include: Vec, - pub exclude: Vec, - pub selectors: Vec, - pub max_results: usize, - pub config: AnalysisConfig, - /// Explicit coverage report files (LCOV, Cobertura, JaCoCo, - /// Clover, Istanbul, Go coverprofile) backing `coverage.*` - /// selectors. The library boundary takes explicit paths only — no - /// filesystem discovery — so rankings stay a pure function of the - /// declared inputs; the CLI layers auto-discovery on top. - pub coverage_reports: Vec, -} - -/// `mehen top-offenders --format json` output shape. -#[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct TopOffendersReport { - pub schema_version: String, - pub selectors: Vec, - pub entries: Vec, - /// Files dropped from the ranking with a non-fatal reason — - /// e.g. the language was detected but no analyzer is registered - /// (feature-gated build), or the analyzer returned a blocking - /// diagnostic. Mirrors [`DiffReport::analysis_errors`] so callers - /// can distinguish "no offenders" from "offenders silently - /// skipped" (rewrite plan §3.5). `side` carries no real meaning - /// here and is set to `Head` by convention. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub analysis_errors: Vec, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct TopOffenderEntry { - pub path: Utf8PathBuf, - pub language: Language, - /// One score per selector in [`TopOffendersInput::selectors`], in - /// the same order. `scores[0]` is the primary ranking key; the rest - /// break ties. `None` (JSON `null`) marks a score that could not - /// be computed for this file — e.g. a static-dependent history - /// composite (`history.hotspot`, `history.churn.relative`) on a - /// file whose static analysis is unavailable; such entries rank - /// as least concerning on that key rather than as a fabricated - /// zero. - pub scores: Vec>, -} diff --git a/crates/mehen-core/src/selector.rs b/crates/mehen-core/src/selector.rs deleted file mode 100644 index d4d7565b..00000000 --- a/crates/mehen-core/src/selector.rs +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use core::fmt; -use core::str::FromStr; - -use crate::MetricKey; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -/// A metric reference used by `mehen diff --threshold`, `mehen top-offenders -/// --metric`, and the action's `metrics` input. -/// -/// Format examples: -/// -/// - `cognitive` — bare key; maps to [`SelectorAggregator::Root`] (file- -/// level / root-unit value only, no aggregation across nested spaces). -/// - `cognitive.max` — explicit max-of-spaces aggregator. -/// - `loc.lloc` — namespaced metric, also resolves to -/// [`SelectorAggregator::Root`]. -/// - `loc.lloc.sum` — namespaced metric with explicit aggregator. -/// -/// Aggregator suffixes recognized: `min`, `max`, `avg`, `sum`. Anything else -/// is treated as part of the metric key. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct MetricSelector { - pub key: MetricKey, - pub aggregator: SelectorAggregator, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum SelectorAggregator { - /// Compute on the file-level (root unit) value only. - Root, - Min, - Max, - Avg, - Sum, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct SelectorParseError(String); - -impl fmt::Display for SelectorParseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "invalid metric selector: `{}`", self.0) - } -} - -impl core::error::Error for SelectorParseError {} - -impl FromStr for MetricSelector { - type Err = SelectorParseError; - - fn from_str(s: &str) -> Result { - let trimmed = s.trim(); - if trimmed.is_empty() { - return Err(SelectorParseError(s.to_string())); - } - let (key_part, aggregator) = match trimmed.rsplit_once('.') { - Some((rest, suffix)) => match suffix { - "min" => (rest, SelectorAggregator::Min), - "max" => (rest, SelectorAggregator::Max), - "avg" => (rest, SelectorAggregator::Avg), - "sum" => (rest, SelectorAggregator::Sum), - _ => (trimmed, SelectorAggregator::Root), - }, - None => (trimmed, SelectorAggregator::Root), - }; - - if key_part.is_empty() { - return Err(SelectorParseError(s.to_string())); - } - - Ok(Self { - key: MetricKey::new(key_part.to_string()), - aggregator, - }) - } -} - -impl fmt::Display for MetricSelector { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.aggregator { - SelectorAggregator::Root => write!(f, "{}", self.key), - SelectorAggregator::Min => write!(f, "{}.min", self.key), - SelectorAggregator::Max => write!(f, "{}.max", self.key), - SelectorAggregator::Avg => write!(f, "{}.avg", self.key), - SelectorAggregator::Sum => write!(f, "{}.sum", self.key), - } - } -} - -impl Serialize for MetricSelector { - fn serialize(&self, serializer: S) -> Result { - serializer.collect_str(self) - } -} - -impl<'de> Deserialize<'de> for MetricSelector { - fn deserialize>(deserializer: D) -> Result { - let s = String::deserialize(deserializer)?; - s.parse().map_err(serde::de::Error::custom) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parses_plain_metric() { - let s: MetricSelector = "cognitive".parse().unwrap(); - assert_eq!(s.key.as_str(), "cognitive"); - assert_eq!(s.aggregator, SelectorAggregator::Root); - } - - #[test] - fn parses_namespaced_metric() { - let s: MetricSelector = "loc.lloc".parse().unwrap(); - assert_eq!(s.key.as_str(), "loc.lloc"); - assert_eq!(s.aggregator, SelectorAggregator::Root); - } - - #[test] - fn parses_aggregator_suffix() { - let s: MetricSelector = "cyclomatic.max".parse().unwrap(); - assert_eq!(s.key.as_str(), "cyclomatic"); - assert_eq!(s.aggregator, SelectorAggregator::Max); - } - - #[test] - fn parses_namespaced_with_aggregator() { - let s: MetricSelector = "loc.lloc.sum".parse().unwrap(); - assert_eq!(s.key.as_str(), "loc.lloc"); - assert_eq!(s.aggregator, SelectorAggregator::Sum); - } - - #[test] - fn rejects_empty() { - assert!("".parse::().is_err()); - assert!(".max".parse::().is_err()); - } - - #[test] - fn round_trip_via_display() { - for input in [ - "cognitive", - "loc.lloc", - "cyclomatic.max", - "halstead.volume.avg", - ] { - let parsed: MetricSelector = input.parse().unwrap(); - assert_eq!(parsed.to_string(), input); - } - } -} diff --git a/crates/mehen-core/src/source.rs b/crates/mehen-core/src/source.rs deleted file mode 100644 index bc7e10b0..00000000 --- a/crates/mehen-core/src/source.rs +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use camino::Utf8PathBuf; -use serde::{Deserialize, Deserializer, Serialize}; - -use crate::{Language, LineIndex}; - -/// One source artifact handed to a language analyzer. -/// -/// `SourceFile` is owned. Holding it does not borrow from any parser arena -/// or buffer the analyzer might construct internally. -#[derive(Debug, Clone, Serialize)] -pub struct SourceFile { - /// Repository-relative or filesystem path. Always forward-slash - /// separated when serialized for snapshots and reports — see the - /// path normalization rule in the rewrite plan §4.8. - pub path: Utf8PathBuf, - pub language: Language, - pub text: String, - /// Pre-computed byte→line index. Reconstructible from `text`, but the - /// engine builds it once and reuses it for diagnostics, span->line - /// translation, and line classification across all metrics. Skipped - /// when serializing — see the custom `Deserialize` impl below, which - /// rebuilds the index from `text` so deserialized `SourceFile`s have - /// a populated `line_index` rather than the empty default. - #[serde(skip)] - pub line_index: LineIndex, -} - -impl SourceFile { - /// Build a source file by computing the line index from `text`. - pub fn new(path: Utf8PathBuf, language: Language, text: String) -> Self { - let line_index = LineIndex::new(&text); - Self { - path, - language, - text, - line_index, - } - } -} - -#[derive(Deserialize)] -struct SourceFileWire { - path: Utf8PathBuf, - language: Language, - text: String, -} - -impl<'de> Deserialize<'de> for SourceFile { - fn deserialize>(deserializer: D) -> Result { - let wire = SourceFileWire::deserialize(deserializer)?; - Ok(SourceFile::new(wire.path, wire.language, wire.text)) - } -} diff --git a/crates/mehen-core/src/space.rs b/crates/mehen-core/src/space.rs deleted file mode 100644 index 0736be33..00000000 --- a/crates/mehen-core/src/space.rs +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::{Deserialize, Serialize}; -use smol_str::SmolStr; - -use crate::analysis::MetricSet; -use crate::span::SourceSpan; - -/// Identifies a `MetricSpace` within one analysis. Stable across one -/// analyzer call; not stable across runs. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct SpaceId(pub u32); - -/// The kind of metric space. -/// -/// `Custom(SmolStr)` keeps the enum open: declarative analyzers can publish -/// scopes such as `cloudformation.resource`, `terraform.module`, or -/// `kubernetes.object` without amending the source-code variants. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum SpaceKind { - /// File-level scope. Always exactly one Unit per `LanguageAnalysis`. - Unit, - Function, - Closure, - Class, - Interface, - Trait, - Impl, - Enum, - /// Namespaced custom scope kind for declarative analyzers. - Custom(SmolStr), -} - -impl SpaceKind { - /// Stable name used for serialization, log lines, and snapshots. - pub fn as_str(&self) -> &str { - match self { - SpaceKind::Unit => "unit", - SpaceKind::Function => "function", - SpaceKind::Closure => "closure", - SpaceKind::Class => "class", - SpaceKind::Interface => "interface", - SpaceKind::Trait => "trait", - SpaceKind::Impl => "impl", - SpaceKind::Enum => "enum", - SpaceKind::Custom(s) => s.as_str(), - } - } -} - -/// One node in the analysis tree. -/// -/// `MetricSpace` is owned data — it never borrows from a parser arena. The -/// tree is fully assembled before being handed back from -/// [`crate::LanguageAnalyzer::analyze`]. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct MetricSpace { - pub id: SpaceId, - pub kind: SpaceKind, - pub name: Option, - pub span: SourceSpan, - pub metrics: MetricSet, - pub spaces: Vec, -} - -impl MetricSpace { - pub fn new(id: SpaceId, kind: SpaceKind, span: SourceSpan) -> Self { - Self { - id, - kind, - name: None, - span, - metrics: MetricSet::default(), - spaces: Vec::new(), - } - } -} diff --git a/crates/mehen-core/src/span.rs b/crates/mehen-core/src/span.rs deleted file mode 100644 index ba2e5df0..00000000 --- a/crates/mehen-core/src/span.rs +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::{Deserialize, Serialize}; - -/// Byte- and line-resolved location inside a source file. -/// -/// Both byte and line are kept on the struct so consumers don't need to -/// re-derive one from the other. Producers (analyzers) populate both during -/// the parse walk; the `LineIndex` makes byte→line conversion cheap. -/// -/// Byte offsets are stored as `u32`. mehen does not analyze sources larger -/// than `u32::MAX` bytes (~4 GiB); use [`byte_offset_clamped`] or -/// [`byte_offset_checked`] when converting from `usize` to surface or -/// silence the limit explicitly. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct SourceSpan { - pub start_byte: u32, - pub end_byte: u32, - pub start_line: u32, - pub end_line: u32, -} - -impl SourceSpan { - pub fn new(start_byte: u32, end_byte: u32, start_line: u32, end_line: u32) -> Self { - Self { - start_byte, - end_byte, - start_line, - end_line, - } - } - - pub fn empty() -> Self { - Self::new(0, 0, 1, 1) - } -} - -/// Convert a `usize` byte offset into the `u32` shape used by [`SourceSpan`], -/// clamping to `u32::MAX` for sources that would otherwise overflow. -/// -/// Use this when the caller is fine with a clamp (the only real-world case -/// is "we don't analyze sources larger than 4 GiB; the upper edge is fine"). -pub fn byte_offset_clamped(offset: usize) -> u32 { - u32::try_from(offset).unwrap_or(u32::MAX) -} - -/// Same as [`byte_offset_clamped`] but returns `None` on overflow so the -/// caller can decline to produce a span at all. -pub fn byte_offset_checked(offset: usize) -> Option { - u32::try_from(offset).ok() -} diff --git a/crates/mehen-core/src/threshold.rs b/crates/mehen-core/src/threshold.rs deleted file mode 100644 index a3e1f98d..00000000 --- a/crates/mehen-core/src/threshold.rs +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::{Deserialize, Serialize}; - -use crate::selector::MetricSelector; - -/// Whether higher values of a metric are worse (`HigherIsWorse`) or better -/// (`HigherIsBetter`). Per the rewrite plan §5.1 this lives with the metric -/// contract because the same number means different things across metrics: -/// `cognitive` going up is bad, `mi.visual_studio` going up is good. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum Polarity { - HigherIsWorse, - HigherIsBetter, -} - -/// A user-supplied threshold rule. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Threshold { - pub selector: MetricSelector, - /// Limit value. The polarity decides which side of `value` is a - /// violation. - pub value: f64, - pub polarity: Polarity, -} - -impl Threshold { - pub fn new(selector: MetricSelector, value: f64, polarity: Polarity) -> Self { - Self { - selector, - value, - polarity, - } - } - - /// True when `actual` violates this threshold. - pub fn violated_by(&self, actual: f64) -> bool { - match self.polarity { - Polarity::HigherIsWorse => actual > self.value, - Polarity::HigherIsBetter => actual < self.value, - } - } -} - -/// Result of evaluating one threshold against an actual measurement. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ThresholdEvaluation { - pub selector: MetricSelector, - pub actual: f64, - pub limit: f64, - pub polarity: Polarity, - pub violated: bool, -} - -/// Convenience violation envelope. Used in `mehen diff --format json`. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ThresholdViolation { - pub path: String, - pub evaluation: ThresholdEvaluation, -} - -#[cfg(test)] -mod tests { - use super::*; - - fn sel(s: &str) -> MetricSelector { - s.parse().unwrap() - } - - #[test] - fn higher_is_worse_violation() { - let t = Threshold::new(sel("cognitive"), 5.0, Polarity::HigherIsWorse); - assert!(!t.violated_by(5.0)); - assert!(t.violated_by(5.1)); - assert!(!t.violated_by(0.0)); - } - - #[test] - fn higher_is_better_violation() { - let t = Threshold::new(sel("mi.visual_studio"), 50.0, Polarity::HigherIsBetter); - assert!(!t.violated_by(50.0)); - assert!(t.violated_by(49.9)); - } -} diff --git a/crates/mehen-coverage-discovery/Cargo.toml b/crates/mehen-coverage-discovery/Cargo.toml deleted file mode 100644 index 01ea7194..00000000 --- a/crates/mehen-coverage-discovery/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "mehen-coverage-discovery" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — automatic coverage-report discovery: bounded artifact scanning of ignored/hidden directories plus declarative tool-config introspection (internal)." -publish = false - -[dependencies] -mehen-coverage = { workspace = true } - -camino = { workspace = true } -globset = { workspace = true } -ignore = { workspace = true } -log = { workspace = true } -quick-xml = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -toml = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -pretty_assertions = { workspace = true } -tempfile = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-coverage-discovery/src/introspect.rs b/crates/mehen-coverage-discovery/src/introspect.rs deleted file mode 100644 index 6aa48363..00000000 --- a/crates/mehen-coverage-discovery/src/introspect.rs +++ /dev/null @@ -1,394 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Declarative tool-config introspection — tier 1 of discovery. -//! -//! Only *data* formats are read: JSON (the c8/nyc rc family), TOML -//! (`pyproject.toml`, `tarpaulin.toml`/`.tarpaulin.toml`), and XML -//! (`phpunit.xml`/`.dist`). Executable -//! configs — `jest.config.ts`, `vitest.config.ts`, `.simplecov`, Gradle -//! DSLs, Pester scripts — are **never executed and never regex-scraped**: -//! their values are routinely computed (template strings, env vars, -//! imported constants), so extraction would be wrong often enough to be -//! worse than the fallback, and the artifact scan already covers every -//! default location those tools write to. -//! -//! Configured paths are validated like any scan candidate (existence, -//! size, content sniff) and must stay inside the root — a config naming -//! `../../elsewhere` yields a diagnostic, not a read. - -use camino::{Utf8Path, Utf8PathBuf}; - -use crate::select::Candidate; -use crate::walk::validate_candidate; -use crate::{DiscoveryCaps, DiscoveryDiagnostics, RejectReason, Rejected, ReportOrigin}; - -/// Run every introspector against one root. -pub(crate) fn introspect_root( - root: &Utf8Path, - caps: &DiscoveryCaps, - candidates: &mut Vec, - diagnostics: &mut DiscoveryDiagnostics, -) { - let canonical_root: Vec = std::fs::canonicalize(root.as_std_path()) - .ok() - .into_iter() - .collect(); - let mut sink = Sink { - root, - caps, - canonical_root: &canonical_root, - candidates, - diagnostics, - }; - - introspect_js_rc(root, &mut sink); - introspect_pyproject(root, &mut sink); - introspect_phpunit(root, &mut sink); - introspect_tarpaulin(root, &mut sink); -} - -/// Shared candidate-submission plumbing for the introspectors. -struct Sink<'a> { - root: &'a Utf8Path, - caps: &'a DiscoveryCaps, - canonical_root: &'a [std::path::PathBuf], - candidates: &'a mut Vec, - diagnostics: &'a mut DiscoveryDiagnostics, -} - -impl Sink<'_> { - /// Submit a config-named report location. `configured` is the raw - /// value from the tool config, resolved against the root; it must - /// not escape it. - fn submit(&mut self, config: &Utf8Path, configured: &str) { - let Some(resolved) = resolve_inside_root(self.root, configured) else { - self.reject(config, Utf8PathBuf::from(configured)); - return; - }; - if !resolved.is_file() { - self.reject(config, resolved); - return; - } - self.diagnostics.candidates_matched += 1; - match validate_candidate( - &resolved, - ReportOrigin::ToolConfig(config.to_path_buf()), - self.canonical_root, - self.caps, - ) { - Ok(candidate) => self.candidates.push(candidate), - Err(reason) => self.diagnostics.rejected.push(Rejected { - path: resolved, - reason, - }), - } - } - - fn reject(&mut self, config: &Utf8Path, path: Utf8PathBuf) { - log::info!( - "coverage config {config} names a report location that does not resolve: {path}" - ); - self.diagnostics.rejected.push(Rejected { - path, - reason: RejectReason::ToolConfigPathInvalid(config.to_path_buf()), - }); - } -} - -/// Resolve a config-spelled path against the root, rejecting absolute -/// spellings and `..` escapes lexically (no filesystem access — the -/// escape must be caught before any read). -fn resolve_inside_root(root: &Utf8Path, configured: &str) -> Option { - let trimmed = configured.trim(); - if trimmed.is_empty() { - return None; - } - let mut components: Vec<&str> = Vec::new(); - // Absolute, UNC, or drive-qualified (`C:…`) spellings are outside - // our contract. A bare ':' elsewhere is a legal POSIX filename byte - // — `out/run:1` must resolve. - let drive_qualified = { - let bytes = trimmed.as_bytes(); - bytes.len() >= 2 && bytes[0].is_ascii_alphabetic() && bytes[1] == b':' - }; - if trimmed.starts_with('/') || trimmed.starts_with('\\') || drive_qualified { - return None; - } - for part in trimmed.split(['/', '\\']) { - match part { - "" | "." => {} - ".." => { - components.pop()?; - } - other => components.push(other), - } - } - if components.is_empty() { - return None; - } - let mut resolved = root.to_path_buf(); - for part in components { - resolved.push(part); - } - Some(resolved) -} - -/// The Istanbul reporter artifacts a configured `reports-dir` can -/// contain, in detection-priority order. -const ISTANBUL_DIR_ARTIFACTS: &[&str] = &[ - "lcov.info", - "coverage-final.json", - "clover.xml", - "cobertura-coverage.xml", -]; - -/// c8 / nyc JSON rc family. c8 searches exactly this list upward from -/// the CWD; we read the first present at the root, mirroring its -/// precedence. Keys: `reports-dir` (c8) / `report-dir` (nyc) name the -/// directory the Istanbul reporters write into. -fn introspect_js_rc(root: &Utf8Path, sink: &mut Sink<'_>) { - const RC_NAMES: &[&str] = &[".c8rc", ".c8rc.json", ".nycrc", ".nycrc.json"]; - let Some(config) = RC_NAMES - .iter() - .map(|name| root.join(name)) - .find(|p| p.is_file()) - else { - return; - }; - let Ok(bytes) = std::fs::read(&config) else { - return; - }; - let Ok(value) = serde_json::from_slice::(&bytes) else { - log::warn!("malformed JSON in {config}; skipping introspection"); - return; - }; - let Some(dir) = value - .get("reports-dir") - .or_else(|| value.get("report-dir")) - .and_then(|v| v.as_str()) - else { - return; // default `coverage/` is covered by the artifact scan - }; - let Some(resolved_dir) = resolve_inside_root(root, dir) else { - sink.reject(&config, Utf8PathBuf::from(dir)); - return; - }; - if !resolved_dir.is_dir() { - sink.reject(&config, resolved_dir); - return; - } - for artifact in ISTANBUL_DIR_ARTIFACTS { - let path = resolved_dir.join(artifact); - if path.is_file() { - let relative = path.strip_prefix(root).unwrap_or(&path).to_string(); - sink.submit(&config, &relative); - } - } -} - -/// `pyproject.toml` — coverage.py's `[tool.coverage.xml] output` / -/// `[tool.coverage.lcov] output`. Only *customized* outputs need -/// introspection; the defaults (`coverage.xml`, `coverage.lcov`) are in -/// the artifact-scan pattern table. -fn introspect_pyproject(root: &Utf8Path, sink: &mut Sink<'_>) { - let config = root.join("pyproject.toml"); - if !config.is_file() { - return; - } - let Ok(text) = std::fs::read_to_string(&config) else { - return; - }; - let Ok(table) = text.parse::() else { - log::warn!("malformed TOML in {config}; skipping introspection"); - return; - }; - let coverage = table.get("tool").and_then(|tool| tool.get("coverage")); - let Some(coverage) = coverage else { - return; - }; - for section in ["xml", "lcov"] { - if let Some(output) = coverage - .get(section) - .and_then(|s| s.get("output")) - .and_then(|o| o.as_str()) - { - sink.submit(&config, output); - } - } -} - -/// `phpunit.xml` then `phpunit.xml.dist` (PHPUnit's own read order). -/// PHPUnit writes **no** coverage file unless configured, so this is -/// the only zero-config discovery path for PHP. Handles both the -/// modern `` shape -/// (PHPUnit ≥ 9.3) and the legacy `` shape. -fn introspect_phpunit(root: &Utf8Path, sink: &mut Sink<'_>) { - const CONFIG_NAMES: &[&str] = &["phpunit.xml", "phpunit.xml.dist"]; - let Some(config) = CONFIG_NAMES - .iter() - .map(|name| root.join(name)) - .find(|p| p.is_file()) - else { - return; - }; - let Ok(bytes) = std::fs::read(&config) else { - return; - }; - - let mut reader = quick_xml::reader::Reader::from_reader(bytes.as_slice()); - reader.config_mut().trim_text(true); - let mut buf = Vec::new(); - let mut outputs: Vec = Vec::new(); - loop { - match reader.read_event_into(&mut buf) { - Err(error) => { - log::warn!("malformed XML in {config}: {error}; skipping introspection"); - return; - } - Ok(quick_xml::events::Event::Eof) => break, - Ok(quick_xml::events::Event::Start(ref e)) - | Ok(quick_xml::events::Event::Empty(ref e)) => match e.name().as_ref() { - b"clover" | b"cobertura" => { - if let Some(output) = attr(e, b"outputFile") { - outputs.push(output); - } - } - b"log" => { - // Legacy PHPUnit < 9.3 logging block. - let kind = attr(e, b"type"); - if matches!( - kind.as_deref(), - Some("coverage-clover") | Some("coverage-cobertura") - ) && let Some(target) = attr(e, b"target") - { - outputs.push(target); - } - } - _ => {} - }, - _ => {} - } - buf.clear(); - } - - for output in outputs { - sink.submit(&config, &output); - } -} - -/// `tarpaulin.toml` / `.tarpaulin.toml` (cargo-tarpaulin). Every -/// top-level table is a run profile — plus the reserved `[report]` -/// table, which only affects reporting — and any of them may carry -/// `out = ["Xml", "Lcov", …]` with an optional `output-dir` -/// redirect. The output *file names* are fixed by tarpaulin -/// (`cobertura.xml`, `lcov.info` inside `output-dir`), so only the -/// directory is configuration. Defaults need no introspection: without -/// `output-dir` the files land in the project root, which the artifact -/// scan's `**/cobertura.xml` / `**/lcov.info` patterns already match — -/// introspection recovers redirects into scan-pruned territory (e.g. -/// `output-dir = "target/cov"`, where the walk's `target/` descent -/// admits only `llvm-cov|tarpaulin|site`). -fn introspect_tarpaulin(root: &Utf8Path, sink: &mut Sink<'_>) { - const CONFIG_NAMES: &[&str] = &["tarpaulin.toml", ".tarpaulin.toml"]; - let Some(config) = CONFIG_NAMES - .iter() - .map(|name| root.join(name)) - .find(|p| p.is_file()) - else { - return; - }; - let Ok(text) = std::fs::read_to_string(&config) else { - return; - }; - let Ok(table) = text.parse::() else { - log::warn!("malformed TOML in {config}; skipping introspection"); - return; - }; - - // `out` and `output-dir` need not share a table: the reserved - // `[report]` table applies its reporting options to every run - // profile, so `out = ["Xml"]` under `[report]` combines with an - // `output-dir` set in a profile. Collect the union of both keys - // across all tables and emit the cross-product — every candidate - // is existence-checked and content-sniffed before anything - // believes it, so an over-approximate pair costs one stat call. - let mut dirs: Vec<&str> = Vec::new(); - let mut artifacts: Vec<&str> = Vec::new(); - for profile in table.values() { - let Some(profile) = profile.as_table() else { - continue; - }; - if let Some(dir) = profile.get("output-dir").and_then(|v| v.as_str()) - && !dirs.contains(&dir) - { - dirs.push(dir); - } - for format in profile - .get("out") - .and_then(|v| v.as_array()) - .into_iter() - .flatten() - .filter_map(|v| v.as_str()) - { - // Ingestable formats only: Html/Json/Markdown/Stdout are - // not report formats mehen parses. Values are PascalCase - // per tarpaulin's `OutputFile` enum; compare loosely so a - // hand-written lowercase spelling still resolves. - let artifact = match format.to_ascii_lowercase().as_str() { - "xml" => "cobertura.xml", - "lcov" => "lcov.info", - _ => continue, - }; - if !artifacts.contains(&artifact) { - artifacts.push(artifact); - } - } - } - // Without `output-dir` the fixed-name files land in the project - // root — scan territory, no introspection needed. - for dir in dirs { - for artifact in &artifacts { - let configured = format!("{}/{artifact}", dir.trim_end_matches(['/', '\\'])); - sink.submit(&config, &configured); - } - } -} - -fn attr(e: &quick_xml::events::BytesStart<'_>, name: &[u8]) -> Option { - let attribute = e.try_get_attribute(name).ok()??; - attribute - .normalized_value(quick_xml::XmlVersion::Implicit1_0) - .ok() - .map(|v| v.into_owned()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn resolve_inside_root_rejects_escapes() { - let root = Utf8Path::new("/repo"); - assert_eq!( - resolve_inside_root(root, "build/logs/clover.xml"), - Some(Utf8PathBuf::from("/repo/build/logs/clover.xml")) - ); - assert_eq!( - resolve_inside_root(root, "./reports/../reports/cov.xml"), - Some(Utf8PathBuf::from("/repo/reports/cov.xml")) - ); - assert_eq!(resolve_inside_root(root, "../../etc/passwd"), None); - assert_eq!(resolve_inside_root(root, "/etc/passwd"), None); - assert_eq!(resolve_inside_root(root, "C:\\windows\\system32"), None); - assert_eq!(resolve_inside_root(root, ""), None); - assert_eq!(resolve_inside_root(root, "."), None); - // A ':' inside a segment is a legal POSIX filename byte, not a - // drive qualifier. - assert_eq!( - resolve_inside_root(root, "out/run:1/lcov.info"), - Some(Utf8PathBuf::from("/repo/out/run:1/lcov.info")) - ); - } -} diff --git a/crates/mehen-coverage-discovery/src/lib.rs b/crates/mehen-coverage-discovery/src/lib.rs deleted file mode 100644 index c0007158..00000000 --- a/crates/mehen-coverage-discovery/src/lib.rs +++ /dev/null @@ -1,236 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Automatic, bounded discovery of coverage-report files. -//! -//! Coverage artifacts live exactly where mehen's source walk refuses to -//! look: gitignored directories (`coverage/`, `target/`, `build/`, -//! `TestResults/`) and hidden ones (`.nyc_output/`). This crate runs a -//! *dedicated* walk with the inverse policy — every ignore rule off, -//! hidden entries visible — while staying bounded and deterministic: -//! -//! * an explicit prune list (`node_modules`, `vendor`, `.venv`, `.git`, -//! caches) that no coverage tool writes reports into; -//! * targeted descent inside the two huge-but-relevant trees: only -//! `target/{llvm-cov,tarpaulin,site}` and -//! `build/{reports,logs,coverage}` are entered; -//! * hard caps on depth, directory entries, sniffed candidates, -//! per-directory candidates, and report size; -//! * `sort_by_file_name` traversal + order-independent selection rules, -//! so the outcome is byte-identical across runs and platforms. -//! -//! Two tiers feed one candidate pool (an explicit `--coverage ` is -//! handled by the caller and bypasses discovery entirely): -//! -//! 1. **Tool-config introspection** — *declarative* configs only: -//! the c8/nyc JSON rc family, `pyproject.toml` -//! (`[tool.coverage.xml|lcov] output`), `phpunit.xml`/`.dist` -//! report elements, and `tarpaulin.toml`/`.tarpaulin.toml` -//! (`out` + `output-dir`). Executable configs (`jest.config.ts`, -//! `.simplecov`, Gradle DSL, Pester scripts) are never executed and -//! never regex-scraped — their tools' default output locations are -//! already in the artifact-scan pattern table. -//! 2. **Artifact scan** — well-known report names/locations, each -//! candidate confirmed by `mehen_coverage::detect_format` content -//! sniffing (first 4 KiB) before it is believed. -//! -//! Selection collapses the pool deterministically: canonical-path -//! dedupe, same-directory multi-format supersede (one Jest run writes -//! `lcov.info` + `coverage-final.json` + `clover.xml`; only the -//! highest-priority format survives), and newest-run-wins inside -//! `TestResults//` re-run clusters. - -#![deny(unsafe_code)] - -mod introspect; -mod select; -mod walk; - -use camino::{Utf8Path, Utf8PathBuf}; -use mehen_coverage::CoverageFormat; -use serde::Serialize; - -/// Where a discovered report came from — recorded for diagnostics and -/// used as the primary selection/sort tier. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)] -#[serde(rename_all = "snake_case", tag = "origin", content = "config")] -pub enum ReportOrigin { - /// Named by a tool's own declarative configuration file. - ToolConfig(Utf8PathBuf), - /// Found by the artifact scan. - Scan, -} - -/// One validated coverage report the caller should parse. -#[derive(Debug, Clone, Serialize)] -pub struct DiscoveredReport { - /// Path as walked (root-joined), forward-slash separated. - pub path: Utf8PathBuf, - /// Sniffed format — already confirmed against file content. - pub format: CoverageFormat, - /// Which tier produced the candidate. - pub origin: ReportOrigin, - /// Report size in bytes. - #[serde(skip)] - pub size_bytes: u64, - /// Filesystem mtime, when the platform provides one. Used by the - /// caller for the warn-only staleness check against the HEAD commit - /// time (source mtimes are meaningless after a CI clone; the report - /// artifact's own mtime is the only surviving signal). - #[serde(skip)] - pub mtime: Option, -} - -/// Why a candidate was dropped. Recorded, not fatal — discovery never -/// fails a run. -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -#[serde(rename_all = "snake_case", tag = "reason", content = "detail")] -pub enum RejectReason { - /// Matched a filename pattern but no format sniffer accepted it - /// (expected for e.g. plain-text `coverage.txt` summaries). - SniffMismatch, - /// Larger than [`DiscoveryCaps::max_report_bytes`]. - TooLarge, - /// Zero-byte file. - Empty, - /// A file symlink whose target escapes every walk root. - SymlinkEscape, - /// A same-directory sibling of a higher-priority format supersedes - /// this report (they describe the same test run). - Superseded(Utf8PathBuf), - /// An older `TestResults//` sibling of the kept report. - OlderRun(Utf8PathBuf), - /// A tool config names a report location that is missing, escapes - /// the root, or fails validation. - ToolConfigPathInvalid(Utf8PathBuf), - /// The per-directory candidate cap dropped this file. - PerDirCandidateCap, -} - -/// A dropped candidate plus the reason. -#[derive(Debug, Clone, Serialize)] -pub struct Rejected { - pub path: Utf8PathBuf, - #[serde(flatten)] - pub reason: RejectReason, -} - -/// Walk/selection observability counters and records, serialized under -/// the `coverage_discovery` key of mehen's JSON output. -#[derive(Debug, Default, Serialize)] -pub struct DiscoveryDiagnostics { - /// Directory entries visited across all roots. - pub dirents_visited: u64, - /// Candidates that matched a pattern or a tool config. - pub candidates_matched: u32, - /// Dropped candidates, sorted by path. - pub rejected: Vec, - /// Which caps fired, if any (`dirents`, `candidates`, …). - pub caps_hit: Vec, -} - -/// The discovery result: reports to parse plus diagnostics. -#[derive(Debug, Default, Serialize)] -pub struct DiscoveryOutcome { - /// Validated reports, sorted by (origin tier, path). - pub reports: Vec, - pub diagnostics: DiscoveryDiagnostics, -} - -/// Bounds converting pathological repositories from "hangs" into -/// "warns". All defaults are deliberate; see the crate docs. -#[derive(Debug, Clone)] -pub struct DiscoveryCaps { - /// Maximum directory depth below each root. The deepest idiomatic - /// artifact path is ~7 components - /// (`packages/

/build/reports/jacoco/test/jacocoTestReport.xml`); - /// 12 leaves monorepo headroom. - pub max_depth: usize, - /// Maximum directory entries visited per `discover` call. - pub max_dirents: u64, - /// Maximum candidates content-sniffed per call (each sniff is one - /// 4 KiB read). - pub max_candidates: u32, - /// Maximum candidates accepted per directory — bounds `.nyc_output` - /// shard floods; the walk is name-sorted, so the lexicographically - /// first shards win deterministically. - pub max_per_dir: u32, - /// Maximum size of a single report file. - pub max_report_bytes: u64, -} - -impl Default for DiscoveryCaps { - fn default() -> Self { - Self { - max_depth: 12, - max_dirents: 500_000, - max_candidates: 256, - max_per_dir: 64, - max_report_bytes: 256 * 1024 * 1024, - } - } -} - -/// Input to [`discover`]. -#[derive(Debug, Default)] -pub struct DiscoveryOptions { - /// Directories to scan — typically one repository workdir per - /// analysis root, canonicalized and deduplicated by the caller. - pub roots: Vec, - /// Additive scan globs from configuration (matched relative to each - /// root). A pattern whose first component is a literal directory - /// name also lifts that name from the prune list, so - /// `node_modules/.cache/**/lcov.info` actually reaches its target. - pub extra_patterns: Vec, - /// Bounds; `Default::default()` for the documented caps. - pub caps: DiscoveryCaps, -} - -/// Discover coverage reports under the given roots. -/// -/// Never fails: I/O problems, malformed configs, and cap overruns -/// degrade to [`DiscoveryDiagnostics`]. An empty outcome means "no -/// coverage available", which callers must keep distinct from 0%. -#[must_use] -pub fn discover(options: &DiscoveryOptions) -> DiscoveryOutcome { - let mut diagnostics = DiscoveryDiagnostics::default(); - let mut candidates: Vec = Vec::new(); - - // Deduplicate + order roots for deterministic multi-root budgets. - let mut roots: Vec<&Utf8Path> = options - .roots - .iter() - .map(Utf8PathBuf::as_path) - .filter(|root| { - let keep = root.is_dir(); - if !keep { - log::warn!("coverage discovery root is not a directory, skipping: {root}"); - } - keep - }) - .collect(); - roots.sort_unstable(); - roots.dedup(); - - // Tier 1: declarative tool-config introspection at each root. - for root in &roots { - introspect::introspect_root(root, &options.caps, &mut candidates, &mut diagnostics); - } - - // Tier 2: bounded artifact scan. - walk::scan_roots( - &roots, - &options.extra_patterns, - &options.caps, - &mut candidates, - &mut diagnostics, - ); - - let reports = select::select(candidates, &mut diagnostics); - diagnostics.rejected.sort_by(|a, b| a.path.cmp(&b.path)); - - DiscoveryOutcome { - reports, - diagnostics, - } -} diff --git a/crates/mehen-coverage-discovery/src/select.rs b/crates/mehen-coverage-discovery/src/select.rs deleted file mode 100644 index 1980374d..00000000 --- a/crates/mehen-coverage-discovery/src/select.rs +++ /dev/null @@ -1,331 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Deterministic selection over the candidate pool. Every rule is -//! order-independent or keyed on sorted data, so permuting candidate -//! arrival order can never change the outcome: -//! -//! 1. **Canonical dedupe** — one entry per on-disk file; `ToolConfig` -//! origin outranks `Scan` for the same file. -//! 2. **Same-directory format supersede** — one test run often emits -//! the same data in several formats at once (Jest: `lcov.info` + -//! `coverage-final.json` + `clover.xml`); only the format highest in -//! [`CoverageFormat::DETECTION_ORDER`] survives per directory. -//! Parsing all three would triple cost to learn nothing. -//! 3. **`TestResults//` re-run clusters** — sibling run -//! directories under a common `TestResults/` parent holding -//! identically-named reports are re-runs of the same producer: the -//! newest report mtime wins, lexicographically smallest path breaks -//! ties. (Newest-*mtime*-wins is scoped to exactly this shape — git -//! checkouts don't preserve mtimes, so a global newest-wins rule -//! would be meaningless on fresh CI clones.) - -use std::collections::BTreeMap; - -use camino::Utf8PathBuf; -use mehen_coverage::CoverageFormat; - -use crate::{DiscoveredReport, DiscoveryDiagnostics, RejectReason, Rejected, ReportOrigin}; - -/// A validated candidate awaiting selection. -#[derive(Debug, Clone)] -pub(crate) struct Candidate { - pub path: Utf8PathBuf, - /// On-disk identity for deduplication. - pub canonical: std::path::PathBuf, - pub format: CoverageFormat, - pub origin: ReportOrigin, - pub size_bytes: u64, - pub mtime: Option, -} - -/// Position in the detection priority order — lower is higher priority. -fn priority(format: CoverageFormat) -> usize { - CoverageFormat::DETECTION_ORDER - .iter() - .position(|&f| f == format) - .unwrap_or(usize::MAX) -} - -pub(crate) fn select( - candidates: Vec, - diagnostics: &mut DiscoveryDiagnostics, -) -> Vec { - // 1. Canonical dedupe. BTreeMap keys give deterministic iteration; - // for one file, ToolConfig origin wins, then the smaller walked - // path spelling. - let mut by_identity: BTreeMap = BTreeMap::new(); - for candidate in candidates { - match by_identity.entry(candidate.canonical.clone()) { - std::collections::btree_map::Entry::Vacant(slot) => { - slot.insert(candidate); - } - std::collections::btree_map::Entry::Occupied(mut slot) => { - let kept = slot.get(); - let replace = (candidate_rank(&candidate)) < (candidate_rank(kept)); - if replace { - slot.insert(candidate); - } - } - } - } - let mut pool: Vec = by_identity.into_values().collect(); - pool.sort_by(|a, b| a.path.cmp(&b.path)); - - // 2. Same-directory format supersede. First pass records, per - // directory, the best (lowest) format priority and the - // lexicographically first candidate carrying it; second pass - // drops everything with a worse format, attributing the keeper. - let mut best_in_dir: BTreeMap = BTreeMap::new(); - for candidate in &pool { - if let Some(parent) = candidate.path.parent() { - let rank = priority(candidate.format); - match best_in_dir.entry(parent.to_path_buf()) { - std::collections::btree_map::Entry::Vacant(slot) => { - slot.insert((rank, candidate.path.clone())); - } - std::collections::btree_map::Entry::Occupied(mut slot) => { - // The pool is path-sorted, so on equal rank the - // existing (earlier) path stays. - if rank < slot.get().0 { - slot.insert((rank, candidate.path.clone())); - } - } - } - } - } - let mut survivors: Vec = Vec::with_capacity(pool.len()); - for candidate in pool { - let best = candidate - .path - .parent() - .and_then(|parent| best_in_dir.get(parent)); - match best { - Some((rank, keeper)) if priority(candidate.format) > *rank => { - diagnostics.rejected.push(Rejected { - path: candidate.path, - reason: RejectReason::Superseded(keeper.clone()), - }); - } - _ => survivors.push(candidate), - } - } - - // 3. TestResults re-run clusters. Key: (path of the TestResults - // ancestor, path relative to the run directory). The newest - // mtime wins; missing mtimes sort oldest; ties break on the - // lexicographically smallest path. - let mut clusters: BTreeMap<(Utf8PathBuf, Utf8PathBuf), Vec> = BTreeMap::new(); - let mut unclustered: Vec = Vec::new(); - for candidate in survivors { - match test_results_cluster_key(&candidate.path) { - Some(key) => clusters.entry(key).or_default().push(candidate), - None => unclustered.push(candidate), - } - } - let mut selected = unclustered; - for (_, mut cluster) in clusters { - // Sort so the winner is first: newest mtime, then smallest path. - cluster.sort_by(|a, b| b.mtime.cmp(&a.mtime).then_with(|| a.path.cmp(&b.path))); - let mut iter = cluster.into_iter(); - let winner = iter.next().expect("cluster groups are never empty"); - let winner_path = winner.path.clone(); - selected.push(winner); - for loser in iter { - diagnostics.rejected.push(Rejected { - path: loser.path, - reason: RejectReason::OlderRun(winner_path.clone()), - }); - } - } - - // 4. Final deterministic order: origin tier, then path. - selected.sort_by(|a, b| { - origin_tier(&a.origin) - .cmp(&origin_tier(&b.origin)) - .then_with(|| a.path.cmp(&b.path)) - }); - selected - .into_iter() - .map(|c| DiscoveredReport { - path: c.path, - format: c.format, - origin: c.origin, - size_bytes: c.size_bytes, - mtime: c.mtime, - }) - .collect() -} - -/// Dedupe rank for two candidates naming the same on-disk file: lower -/// wins. Tool-config attribution beats the scan; then the smaller -/// walked spelling. -fn candidate_rank(candidate: &Candidate) -> (u8, &Utf8PathBuf) { - (origin_tier(&candidate.origin), &candidate.path) -} - -fn origin_tier(origin: &ReportOrigin) -> u8 { - match origin { - ReportOrigin::ToolConfig(_) => 0, - ReportOrigin::Scan => 1, - } -} - -/// If the path has the shape `/TestResults//`, -/// return the cluster key `(prefix/TestResults, rest)`. -fn test_results_cluster_key(path: &camino::Utf8Path) -> Option<(Utf8PathBuf, Utf8PathBuf)> { - let components: Vec<&str> = path.components().map(|c| c.as_str()).collect(); - // Find the *last* TestResults component with at least a run dir and - // a file below it. - let idx = components - .iter() - .rposition(|&c| c == "TestResults") - .filter(|&idx| idx + 2 < components.len())?; - let ancestor: Utf8PathBuf = components[..=idx].iter().collect(); - let rest: Utf8PathBuf = components[idx + 2..].iter().collect(); - Some((ancestor, rest)) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn candidate(path: &str, format: CoverageFormat) -> Candidate { - Candidate { - path: Utf8PathBuf::from(path), - canonical: std::path::PathBuf::from(path), - format, - origin: ReportOrigin::Scan, - size_bytes: 10, - mtime: None, - } - } - - #[test] - fn same_directory_multi_format_keeps_highest_priority() { - // The Jest triple: one run, three artifacts, one survivor. - let pool = vec![ - candidate("coverage/clover.xml", CoverageFormat::Clover), - candidate("coverage/coverage-final.json", CoverageFormat::Istanbul), - candidate("coverage/lcov.info", CoverageFormat::Lcov), - ]; - let mut diagnostics = DiscoveryDiagnostics::default(); - let selected = select(pool, &mut diagnostics); - assert_eq!(selected.len(), 1); - assert_eq!(selected[0].path, "coverage/lcov.info"); - assert_eq!(selected[0].format, CoverageFormat::Lcov); - assert_eq!(diagnostics.rejected.len(), 2); - for rejected in &diagnostics.rejected { - assert!(matches!( - &rejected.reason, - RejectReason::Superseded(kept) if kept == "coverage/lcov.info" - )); - } - } - - #[test] - fn same_format_same_directory_all_survive() { - // simplecov-lcov per-file mode: many .lcov files in one dir — - // they are disjoint parts of one run and all merge. - let pool = vec![ - candidate("coverage/lcov/a.lcov", CoverageFormat::Lcov), - candidate("coverage/lcov/b.lcov", CoverageFormat::Lcov), - ]; - let mut diagnostics = DiscoveryDiagnostics::default(); - let selected = select(pool, &mut diagnostics); - assert_eq!(selected.len(), 2); - assert!(diagnostics.rejected.is_empty()); - } - - #[test] - fn test_results_reruns_keep_newest() { - let old_time = std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(1_000); - let new_time = std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(2_000); - let mut older = candidate( - "TestResults/aaaa/coverage.cobertura.xml", - CoverageFormat::Cobertura, - ); - older.mtime = Some(old_time); - let mut newer = candidate( - "TestResults/bbbb/coverage.cobertura.xml", - CoverageFormat::Cobertura, - ); - newer.mtime = Some(new_time); - - for permutation in [ - vec![older.clone(), newer.clone()], - vec![newer.clone(), older.clone()], - ] { - let mut diagnostics = DiscoveryDiagnostics::default(); - let selected = select(permutation, &mut diagnostics); - assert_eq!(selected.len(), 1); - assert_eq!(selected[0].path, "TestResults/bbbb/coverage.cobertura.xml"); - assert_eq!(diagnostics.rejected.len(), 1); - assert!(matches!( - &diagnostics.rejected[0].reason, - RejectReason::OlderRun(kept) if kept == "TestResults/bbbb/coverage.cobertura.xml" - )); - } - } - - #[test] - fn multi_project_test_results_keep_one_per_assembly() { - // Two projects, each with its own TestResults tree: separate - // clusters, both survive. - let a = candidate( - "svc-a/TestResults/1111/coverage.cobertura.xml", - CoverageFormat::Cobertura, - ); - let b = candidate( - "svc-b/TestResults/2222/coverage.cobertura.xml", - CoverageFormat::Cobertura, - ); - let mut diagnostics = DiscoveryDiagnostics::default(); - let selected = select(vec![a, b], &mut diagnostics); - assert_eq!(selected.len(), 2); - } - - #[test] - fn tool_config_origin_wins_dedupe_and_sorts_first() { - let scan = candidate("build/logs/clover.xml", CoverageFormat::Clover); - let mut config = candidate("build/logs/clover.xml", CoverageFormat::Clover); - config.origin = ReportOrigin::ToolConfig(Utf8PathBuf::from("phpunit.xml")); - - for permutation in [ - vec![scan.clone(), config.clone()], - vec![config.clone(), scan.clone()], - ] { - let mut diagnostics = DiscoveryDiagnostics::default(); - let selected = select(permutation, &mut diagnostics); - assert_eq!(selected.len(), 1); - assert!( - matches!(&selected[0].origin, ReportOrigin::ToolConfig(c) if c == "phpunit.xml") - ); - } - } - - #[test] - fn cluster_key_shapes() { - assert_eq!( - test_results_cluster_key(Utf8PathBuf::from("TestResults/x/coverage.xml").as_path()), - Some(( - Utf8PathBuf::from("TestResults"), - Utf8PathBuf::from("coverage.xml") - )) - ); - assert_eq!( - test_results_cluster_key( - Utf8PathBuf::from("a/TestResults/run-1/sub/coverage.info").as_path() - ), - Some(( - Utf8PathBuf::from("a/TestResults"), - Utf8PathBuf::from("sub/coverage.info") - )) - ); - // A file directly inside TestResults/ has no run directory. - assert_eq!( - test_results_cluster_key(Utf8PathBuf::from("TestResults/coverage.xml").as_path()), - None - ); - } -} diff --git a/crates/mehen-coverage-discovery/src/walk.rs b/crates/mehen-coverage-discovery/src/walk.rs deleted file mode 100644 index 316e5e2e..00000000 --- a/crates/mehen-coverage-discovery/src/walk.rs +++ /dev/null @@ -1,475 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! The bounded artifact scan: a dedicated serial walk with the inverse -//! of mehen's source-walk policy (every ignore rule off, hidden entries -//! visible), an explicit prune list, targeted descent inside `target/` -//! and `build/`, and deterministic name-sorted traversal. - -use std::collections::BTreeSet; -use std::io::Read; - -use camino::{Utf8Path, Utf8PathBuf}; -use globset::{Glob, GlobSet, GlobSetBuilder}; -use ignore::WalkBuilder; - -use crate::select::Candidate; -use crate::{DiscoveryCaps, DiscoveryDiagnostics, RejectReason, Rejected, ReportOrigin}; - -/// Filename/location patterns for the artifact scan, matched against the -/// root-relative path. Breadth is cheap — every match is confirmed by -/// content sniffing before anything believes it — but each entry is -/// still justified by a real tool convention: -/// -/// * LCOV: `lcov -o`, cargo-llvm-cov/tarpaulin, simplecov-lcov -/// (`coverage/lcov/.lcov`), coverlet lcov (`coverage.info`), -/// coverage.py (`coverage.lcov`). -/// * Go: `go test -coverprofile` has *no* default filename; these are -/// the community's dominant spellings (`coverage.out`, `cover.out`, -/// `coverage.txt`, `profile.cov`, `c.out`, `*.coverprofile`) — all -/// guarded by the `mode:` content sniff. -/// * Istanbul: Jest/Vitest/nyc/c8 `coverage-final.json` plus raw -/// `.nyc_output/*.json` shards. -/// * JaCoCo: Maven `target/site/jacoco/jacoco.xml`, Gradle -/// `build/reports/jacoco/test/jacocoTestReport.xml`, Kotlin Kover's -/// JaCoCo-compatible `build/reports/kover/*.xml`, Pester 5's default -/// `coverage.xml` (JaCoCo format — content sniffing separates it from -/// coverage.py's Cobertura file of the same name). -/// * Clover: PHPUnit/Jenkins `clover.xml` (`build/logs/clover.xml`), -/// Jest/Vitest clover reporters. -/// * Cobertura: coverage.py `coverage.xml`, coverlet -/// `TestResults//coverage.cobertura.xml`, gcovr/tarpaulin -/// `cobertura.xml`. -const ARTIFACT_PATTERNS: &[&str] = &[ - // LCOV - "**/lcov.info", - "**/coverage.info", - "**/*.lcov", - // Go coverprofile - "**/coverage.out", - "**/cover.out", - "**/coverage.txt", - "**/profile.cov", - "**/c.out", - "**/*.coverprofile", - // Istanbul JSON - "**/coverage-final.json", - "**/.nyc_output/*.json", - // JaCoCo XML (+ Pester's coverage.xml, sniff-disambiguated) - "**/jacoco.xml", - "**/jacocoTestReport.xml", - "**/site/jacoco/*.xml", - "**/reports/jacoco/**/*.xml", - "**/reports/kover/*.xml", - "**/coverage.xml", - // Clover XML - "**/clover.xml", - // Cobertura XML - "**/cobertura.xml", - "**/coverage.cobertura.xml", -]; - -/// Directory names never descended into. No mainstream coverage tool -/// defaults report output into any of these, and several are enormous; -/// an `extra-patterns` entry whose first component names one lifts it -/// from the list for that run. -const PRUNE_DIRS: &[&str] = &[ - ".git", - ".hg", - ".svn", - "node_modules", - "bower_components", - "vendor", - ".venv", - "venv", - ".tox", - ".nox", - ".direnv", - "__pycache__", - ".mypy_cache", - ".ruff_cache", - ".pytest_cache", - ".gradle", - ".m2", - ".cargo", - ".rustup", - ".npm", - ".yarn", - ".pnpm-store", - ".idea", - ".vscode", - ".terraform", -]; - -/// Whether to descend into a directory, given its name and its parent's -/// name. Implements the prune list plus targeted descent for the two -/// huge-but-relevant build trees: -/// -/// * `target/` (Cargo *and* Maven): only `llvm-cov/` (cargo-llvm-cov -/// HTML/artifacts), `tarpaulin/`, and `site/` (Maven -/// `target/site/jacoco/`) can contain reports — `target/debug` alone -/// is routinely 50k+ dirents of compiler output. -/// * `build/` (Gradle/CMake/Jenkins conventions): only `reports/`, -/// `logs/`, and `coverage/`. -/// * `coverage/tmp/` holds c8/nyc raw V8 output (never final reports). -fn should_descend( - name: &str, - parent_name: Option<&str>, - prune: &std::collections::BTreeSet, -) -> bool -where - S: std::borrow::Borrow + Ord, -{ - if prune.contains(name) { - return false; - } - match parent_name { - Some("target") => matches!(name, "llvm-cov" | "tarpaulin" | "site"), - Some("build") => matches!(name, "reports" | "logs" | "coverage"), - Some("coverage") => name != "tmp", - _ => true, - } -} - -/// Build the artifact-pattern matcher, appending configured extras. -/// Invalid or empty globs are dropped with a warning (mirroring the -/// engine's `mk_globset` behavior). -fn build_globset(extra_patterns: &[String]) -> GlobSet { - let mut builder = GlobSetBuilder::new(); - for pattern in ARTIFACT_PATTERNS - .iter() - .copied() - .chain(extra_patterns.iter().map(String::as_str)) - { - if pattern.is_empty() { - continue; - } - match Glob::new(pattern) { - Ok(glob) => { - builder.add(glob); - } - Err(error) => log::warn!("invalid coverage scan pattern '{pattern}': {error}"), - } - } - builder.build().unwrap_or_else(|_| GlobSet::empty()) -} - -/// The prune set for this run: the built-in list minus any directory -/// name that an extra pattern explicitly tunnels into (its first -/// literal component). -fn prune_set(extra_patterns: &[String]) -> BTreeSet<&'static str> { - let mut prune: BTreeSet<&'static str> = PRUNE_DIRS.iter().copied().collect(); - for pattern in extra_patterns { - if let Some(first) = pattern.split('/').next() - && !first.contains(['*', '?', '[', '{']) - && let Some(&name) = prune.iter().find(|&&p| p == first) - { - prune.remove(name); - } - } - prune -} - -/// Shared walk budget across roots. -struct Budget { - dirents_left: u64, - sniffs_left: u32, -} - -/// Scan every root, feeding validated candidates into `candidates`. -pub(crate) fn scan_roots( - roots: &[&Utf8Path], - extra_patterns: &[String], - caps: &DiscoveryCaps, - candidates: &mut Vec, - diagnostics: &mut DiscoveryDiagnostics, -) { - let globset = build_globset(extra_patterns); - let prune = prune_set(extra_patterns); - let canonical_roots: Vec = roots - .iter() - .filter_map(|root| std::fs::canonicalize(root.as_std_path()).ok()) - .collect(); - let mut budget = Budget { - dirents_left: caps.max_dirents, - sniffs_left: caps.max_candidates, - }; - // Per-directory accepted-candidate counter (bounds `.nyc_output` - // shard floods deterministically — the walk is name-sorted). - let mut per_dir: std::collections::BTreeMap = - std::collections::BTreeMap::new(); - - for root in roots { - if budget.dirents_left == 0 || budget.sniffs_left == 0 { - break; - } - scan_one_root( - root, - &globset, - &prune, - &canonical_roots, - caps, - &mut budget, - &mut per_dir, - candidates, - diagnostics, - ); - } -} - -#[expect( - clippy::too_many_arguments, - reason = "internal walk plumbing; a context struct would only rename the coupling" -)] -fn scan_one_root( - root: &Utf8Path, - globset: &GlobSet, - prune: &BTreeSet<&str>, - canonical_roots: &[std::path::PathBuf], - caps: &DiscoveryCaps, - budget: &mut Budget, - per_dir: &mut std::collections::BTreeMap, - candidates: &mut Vec, - diagnostics: &mut DiscoveryDiagnostics, -) { - let mut builder = WalkBuilder::new(root.as_std_path()); - // The inverse of the source walk: gitignored directories (coverage/, - // target/, TestResults/) and hidden entries (.nyc_output/) MUST be - // visited, so every standard filter is off. Symlinked directories - // are never followed (loops, escapes, nondeterminism). - builder - .standard_filters(false) - .follow_links(false) - .max_depth(Some(caps.max_depth)) - .sort_by_file_name(std::cmp::Ord::cmp); - - let prune_for_filter: BTreeSet = prune.iter().map(ToString::to_string).collect(); - builder.filter_entry(move |entry| { - if entry.depth() == 0 - || !entry - .file_type() - .is_some_and(|file_type| file_type.is_dir()) - { - return true; - } - let Some(name) = entry.file_name().to_str() else { - return false; // non-UTF-8 directory: skip subtree - }; - let parent_name = entry - .path() - .parent() - .and_then(|p| p.file_name()) - .and_then(|n| n.to_str()); - should_descend(name, parent_name, &prune_for_filter) - }); - - for result in builder.build() { - if budget.dirents_left == 0 { - push_cap(diagnostics, "dirents"); - return; - } - budget.dirents_left -= 1; - diagnostics.dirents_visited += 1; - - let entry = match result { - Ok(entry) => entry, - Err(error) => { - log::warn!("coverage scan failed to walk an entry: {error}"); - continue; - } - }; - let is_file = entry - .file_type() - .is_some_and(|file_type| file_type.is_file()) - || (entry.path_is_symlink() && entry.path().is_file()); - if !is_file { - continue; - } - let Some(utf8) = Utf8Path::from_path(entry.path()) else { - log::warn!( - "skipping non-UTF-8 coverage candidate path: {}", - entry.path().display() - ); - continue; - }; - let Ok(relative) = utf8.strip_prefix(root) else { - continue; - }; - if !globset.is_match(relative.as_std_path()) { - continue; - } - - diagnostics.candidates_matched += 1; - if budget.sniffs_left == 0 { - push_cap(diagnostics, "candidates"); - return; - } - budget.sniffs_left -= 1; - - let parent = utf8 - .parent() - .map_or_else(|| root.to_path_buf(), Utf8Path::to_path_buf); - let dir_count = per_dir.entry(parent).or_insert(0); - if *dir_count >= caps.max_per_dir { - push_cap(diagnostics, "per_dir_candidates"); - diagnostics.rejected.push(Rejected { - path: utf8.to_path_buf(), - reason: RejectReason::PerDirCandidateCap, - }); - continue; - } - - match validate_candidate(utf8, ReportOrigin::Scan, canonical_roots, caps) { - Ok(candidate) => { - *dir_count += 1; - candidates.push(candidate); - } - Err(reason) => diagnostics.rejected.push(Rejected { - path: utf8.to_path_buf(), - reason, - }), - } - } -} - -fn push_cap(diagnostics: &mut DiscoveryDiagnostics, cap: &str) { - if !diagnostics.caps_hit.iter().any(|c| c == cap) { - diagnostics.caps_hit.push(cap.to_string()); - } -} - -/// Validate one candidate file: regular-file check, symlink-escape -/// containment, size bounds, and content sniffing. Shared by the -/// artifact scan and tool-config introspection. -pub(crate) fn validate_candidate( - path: &Utf8Path, - origin: ReportOrigin, - canonical_roots: &[std::path::PathBuf], - caps: &DiscoveryCaps, -) -> Result { - let symlink_meta = - std::fs::symlink_metadata(path.as_std_path()).map_err(|_| RejectReason::SniffMismatch)?; - let canonical = std::fs::canonicalize(path.as_std_path()).ok(); - if symlink_meta.file_type().is_symlink() { - // A planted `lcov.info -> /etc/passwd` must not be read even - // for sniffing: the resolved target has to stay under a root. - let contained = canonical.as_ref().is_some_and(|resolved| { - canonical_roots - .iter() - .any(|root| resolved.starts_with(root)) - }); - if !contained { - return Err(RejectReason::SymlinkEscape); - } - } - - let metadata = std::fs::metadata(path.as_std_path()).map_err(|_| RejectReason::Empty)?; - if !metadata.is_file() { - return Err(RejectReason::SniffMismatch); - } - if metadata.len() == 0 { - return Err(RejectReason::Empty); - } - if metadata.len() > caps.max_report_bytes { - return Err(RejectReason::TooLarge); - } - - // The 4 KiB sniff — the only content I/O discovery performs. - let mut head = [0_u8; 4096]; - let mut file = std::fs::File::open(path.as_std_path()).map_err(|_| RejectReason::Empty)?; - let mut filled = 0; - while filled < head.len() { - match file.read(&mut head[filled..]) { - Ok(0) => break, - Ok(n) => filled += n, - Err(_) => break, - } - } - let Some(format) = mehen_coverage::detect_format(path, &head[..filled]) else { - return Err(RejectReason::SniffMismatch); - }; - - Ok(Candidate { - path: path.to_path_buf(), - canonical: canonical.unwrap_or_else(|| path.as_std_path().to_path_buf()), - format, - origin, - size_bytes: metadata.len(), - mtime: metadata.modified().ok(), - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn prune() -> BTreeSet<&'static str> { - PRUNE_DIRS.iter().copied().collect() - } - - #[test] - fn prune_list_blocks_and_extra_pattern_lifts() { - let base = prune(); - assert!(!should_descend("node_modules", Some("repo"), &base)); - assert!(!should_descend(".git", Some("repo"), &base)); - - let lifted = prune_set(&["node_modules/.cache/**/lcov.info".to_string()]); - assert!(should_descend("node_modules", Some("repo"), &lifted)); - assert!(!should_descend(".git", Some("repo"), &lifted)); - } - - #[test] - fn target_and_build_use_targeted_descent() { - let p = prune(); - assert!(should_descend("llvm-cov", Some("target"), &p)); - assert!(should_descend("tarpaulin", Some("target"), &p)); - assert!(should_descend("site", Some("target"), &p)); - assert!(!should_descend("debug", Some("target"), &p)); - assert!(!should_descend("release", Some("target"), &p)); - - assert!(should_descend("reports", Some("build"), &p)); - assert!(should_descend("logs", Some("build"), &p)); - assert!(should_descend("coverage", Some("build"), &p)); - assert!(!should_descend("classes", Some("build"), &p)); - - // c8/nyc raw V8 staging: never contains final reports. - assert!(!should_descend("tmp", Some("coverage"), &p)); - assert!(should_descend("lcov", Some("coverage"), &p)); - } - - #[test] - fn artifact_patterns_match_expected_paths() { - let set = build_globset(&[]); - for hit in [ - "lcov.info", - "coverage/lcov.info", - "packages/app/coverage/lcov.info", - "coverage/lcov/my-project.lcov", - "coverage.out", - "profile.cov", - "c.out", - "e2e.coverprofile", - "coverage/coverage-final.json", - ".nyc_output/8a1f.json", - "target/site/jacoco/jacoco.xml", - "build/reports/jacoco/test/jacocoTestReport.xml", - "build/reports/kover/report.xml", - "coverage.xml", - "sub/coverage.xml", - "build/logs/clover.xml", - "TestResults/3d1c-42/coverage.cobertura.xml", - "target/llvm-cov/lcov.info", - ] { - assert!(set.is_match(hit), "expected pattern hit: {hit}"); - } - for miss in [ - "notes.txt", - "report.xml", // only inside kover/jacoco dirs - "docs/install.info.md", // not a coverage name - "coverage.json", // coverlet's proprietary JSON - "src/lib.rs", - ] { - assert!(!set.is_match(miss), "expected pattern miss: {miss}"); - } - } -} diff --git a/crates/mehen-coverage-discovery/tests/discovery_scenarios.rs b/crates/mehen-coverage-discovery/tests/discovery_scenarios.rs deleted file mode 100644 index 447af5c9..00000000 --- a/crates/mehen-coverage-discovery/tests/discovery_scenarios.rs +++ /dev/null @@ -1,309 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! End-to-end discovery scenarios over a synthetic monorepo tempdir: -//! pattern hits inside gitignored/hidden directories, targeted descent, -//! pruning, content-sniff disambiguation, tool-config introspection, -//! same-directory supersede, `TestResults` re-run clustering, and -//! determinism of the whole outcome. - -use camino::{Utf8Path, Utf8PathBuf}; -use mehen_coverage_discovery::{DiscoveryOptions, DiscoveryOutcome, ReportOrigin, discover}; - -const LCOV: &str = "TN:\nSF:src/app.js\nDA:1,1\nDA:2,0\nend_of_record\n"; -const ISTANBUL: &str = r#"{"/w/src/app.js": {"statementMap": {"0": {"start": {"line": 1}}}, "s": {"0": 1}, "fnMap": {}, "f": {}}}"#; -const CLOVER: &str = r#""#; -const JACOCO: &str = r#""#; -const COBERTURA: &str = r#"/w"#; -const GOCOVER: &str = "mode: set\nexample.com/m/pkg/a.go:1.1,2.2 1 1\n"; - -fn write(root: &Utf8Path, relative: &str, content: &str) { - let path = root.join(relative); - std::fs::create_dir_all(path.parent().unwrap()).unwrap(); - std::fs::write(path, content).unwrap(); -} - -fn set_mtime(root: &Utf8Path, relative: &str, seconds: u64) { - let path = root.join(relative); - let file = std::fs::File::options() - .write(true) - .open(path.as_std_path()) - .unwrap(); - file.set_modified(std::time::UNIX_EPOCH + std::time::Duration::from_secs(seconds)) - .unwrap(); -} - -/// Flatten an outcome into stable, root-relative one-line records so -/// insta snapshots stay platform- and tempdir-independent (Windows -/// walk output spells `\` separators; snapshots pin the `/` form). -fn projection(root: &Utf8Path, outcome: &DiscoveryOutcome) -> Vec { - let rel = |path: &Utf8PathBuf| -> String { - path.strip_prefix(root) - .map_or_else(|_| path.to_string(), ToString::to_string) - .replace('\\', "/") - }; - let mut lines: Vec = outcome - .reports - .iter() - .map(|report| { - let origin = match &report.origin { - ReportOrigin::ToolConfig(config) => format!("tool-config:{}", rel(config)), - ReportOrigin::Scan => "scan".to_string(), - }; - format!("report {} {} ({origin})", report.format, rel(&report.path)) - }) - .collect(); - for rejected in &outcome.diagnostics.rejected { - let reason = match &rejected.reason { - mehen_coverage_discovery::RejectReason::Superseded(kept) => { - format!("Superseded by {}", rel(kept)) - } - mehen_coverage_discovery::RejectReason::OlderRun(kept) => { - format!("OlderRun kept {}", rel(kept)) - } - mehen_coverage_discovery::RejectReason::ToolConfigPathInvalid(config) => { - format!("ToolConfigPathInvalid from {}", rel(config)) - } - other => format!("{other:?}"), - }; - lines.push(format!("rejected {} {reason}", rel(&rejected.path))); - } - for cap in &outcome.diagnostics.caps_hit { - lines.push(format!("cap {cap}")); - } - lines -} - -fn build_monorepo(root: &Utf8Path) { - // Jest triple in a (conventionally gitignored) coverage/ dir. - write(root, "coverage/lcov.info", LCOV); - write(root, "coverage/coverage-final.json", ISTANBUL); - write(root, "coverage/clover.xml", CLOVER); - // c8 raw V8 staging — must not be visited. - write(root, "coverage/tmp/raw.json", ISTANBUL); - // Hidden nyc shard dir — must be visited. - write(root, ".nyc_output/aaa.json", ISTANBUL); - // Rust: cargo-llvm-cov artifact inside target/ (targeted descent). - write(root, "target/llvm-cov/lcov.info", LCOV); - // Compiler output — must not be visited. - write(root, "target/debug/deps/junk.lcov", LCOV); - // Rust: tarpaulin redirects reports into target/cov — pruned by the - // walk (target/ descent admits only llvm-cov|tarpaulin|site), so - // only introspection recovers them. `out` lives in the reserved - // [report] table while `output-dir` sits in a run profile; Html is - // not an ingestable format and must be skipped. - write( - root, - "tarpaulin.toml", - "[nightly_run]\noutput-dir = \"target/cov\"\n\n[report]\nout = [\"Xml\", \"Lcov\", \"Html\"]\n", - ); - write(root, "target/cov/cobertura.xml", COBERTURA); - write(root, "target/cov/lcov.info", LCOV); - // PHP: phpunit.xml.dist names the clover report (Jenkins layout). - write( - root, - "phpunit.xml.dist", - r#""#, - ); - write(root, "build/logs/clover.xml", CLOVER); - // Gradle output dir that is not a report location — not visited. - write(root, "build/classes/junk.lcov", LCOV); - // dotnet coverlet re-runs: GUID dirs under TestResults/. - write( - root, - "TestResults/aaaa-1111/coverage.cobertura.xml", - COBERTURA, - ); - write( - root, - "TestResults/bbbb-2222/coverage.cobertura.xml", - COBERTURA, - ); - set_mtime(root, "TestResults/aaaa-1111/coverage.cobertura.xml", 1_000); - set_mtime(root, "TestResults/bbbb-2222/coverage.cobertura.xml", 2_000); - // The coverage.xml name collision: coverage.py (Cobertura) vs - // Pester (JaCoCo) — content sniffing separates them. - write(root, "py/coverage.xml", COBERTURA); - write(root, "ps/coverage.xml", JACOCO); - // Go conventions. - write(root, "go/coverage.out", GOCOVER); - // Python: pyproject.toml routes the XML report to a custom path. - write( - root, - "pyproject.toml", - "[tool.coverage.xml]\noutput = \"qa/cov.xml\"\n", - ); - write(root, "qa/cov.xml", COBERTURA); - // Pruned locations. - write(root, "node_modules/pkg/lcov.info", LCOV); - write(root, "vendor/lib/lcov.info", LCOV); - // Pattern hits that fail validation. - write(root, "notes/coverage.txt", "a plain text summary\n"); - write(root, "empty.lcov", ""); -} - -#[test] -fn monorepo_discovery_snapshot() { - let dir = tempfile::tempdir().unwrap(); - let root = Utf8Path::from_path(dir.path()).unwrap(); - build_monorepo(root); - - let outcome = discover(&DiscoveryOptions { - roots: vec![root.to_path_buf()], - ..Default::default() - }); - - // The observability counter must reflect the walk (regression: it - // used to stay 0 while dirents_left was decremented). - assert!( - outcome.diagnostics.dirents_visited > 0, - "dirents_visited must count visited entries" - ); - - insta::assert_yaml_snapshot!("monorepo_discovery", projection(root, &outcome)); -} - -#[test] -fn discovery_is_deterministic_across_runs() { - let dir = tempfile::tempdir().unwrap(); - let root = Utf8Path::from_path(dir.path()).unwrap(); - build_monorepo(root); - - let options = DiscoveryOptions { - roots: vec![root.to_path_buf()], - ..Default::default() - }; - let first = projection(root, &discover(&options)); - let second = projection(root, &discover(&options)); - assert_eq!(first, second); - - // A copy of the same tree at a different absolute path produces the - // same relative outcome. - let dir2 = tempfile::tempdir().unwrap(); - let root2 = Utf8Path::from_path(dir2.path()).unwrap(); - build_monorepo(root2); - let elsewhere = projection( - root2, - &discover(&DiscoveryOptions { - roots: vec![root2.to_path_buf()], - ..Default::default() - }), - ); - assert_eq!(first, elsewhere); -} - -#[test] -fn tarpaulin_introspection_rejects_missing_and_escaping_outputs() { - let dir = tempfile::tempdir().unwrap(); - let root = Utf8Path::from_path(dir.path()).unwrap(); - // The Xml report was configured but never generated; the second - // profile tries to walk out of the root. Neither may produce a - // report; every probe must leave an auditable rejection. The - // introspector cross-products the union of `out` formats and - // `output-dir`s (the reserved [report] table splits them in real - // configs), so two dirs × two artifacts = four rejections. - write( - root, - ".tarpaulin.toml", - "[ci]\nout = [\"Xml\"]\noutput-dir = \"reports\"\n\n[evil]\nout = [\"Lcov\"]\noutput-dir = \"../outside\"\n", - ); - - let outcome = discover(&DiscoveryOptions { - roots: vec![root.to_path_buf()], - ..Default::default() - }); - assert!(outcome.reports.is_empty()); - let invalid = outcome - .diagnostics - .rejected - .iter() - .filter(|r| { - matches!( - &r.reason, - mehen_coverage_discovery::RejectReason::ToolConfigPathInvalid(config) - if config.file_name() == Some(".tarpaulin.toml") - ) - }) - .count(); - assert_eq!( - invalid, 4, - "absent reports and escaping output-dirs must all be rejected: {:?}", - outcome.diagnostics.rejected - ); -} - -#[test] -fn extra_patterns_lift_prune_dirs() { - let dir = tempfile::tempdir().unwrap(); - let root = Utf8Path::from_path(dir.path()).unwrap(); - write(root, "node_modules/.cache/cov/lcov.info", LCOV); - - let none = discover(&DiscoveryOptions { - roots: vec![root.to_path_buf()], - ..Default::default() - }); - assert!(none.reports.is_empty()); - - let lifted = discover(&DiscoveryOptions { - roots: vec![root.to_path_buf()], - extra_patterns: vec!["node_modules/.cache/**/lcov.info".to_string()], - ..Default::default() - }); - assert_eq!(lifted.reports.len(), 1); - assert!( - lifted.reports[0] - .path - .ends_with("node_modules/.cache/cov/lcov.info") - ); -} - -#[test] -#[cfg(unix)] -fn symlink_escape_is_rejected() { - let dir = tempfile::tempdir().unwrap(); - let root = Utf8Path::from_path(dir.path()).unwrap(); - let outside = tempfile::tempdir().unwrap(); - let secret = outside.path().join("secret.info"); - std::fs::write(&secret, LCOV).unwrap(); - std::fs::create_dir_all(root.join("coverage").as_std_path()).unwrap(); - std::os::unix::fs::symlink(&secret, root.join("coverage/lcov.info").as_std_path()).unwrap(); - - let outcome = discover(&DiscoveryOptions { - roots: vec![root.to_path_buf()], - ..Default::default() - }); - assert!(outcome.reports.is_empty()); - assert!( - outcome - .diagnostics - .rejected - .iter() - .any(|r| format!("{:?}", r.reason) == "SymlinkEscape"), - "expected a SymlinkEscape rejection, got {:?}", - outcome.diagnostics.rejected - ); -} - -#[test] -fn nyc_shard_flood_hits_per_dir_cap() { - let dir = tempfile::tempdir().unwrap(); - let root = Utf8Path::from_path(dir.path()).unwrap(); - for i in 0..80 { - write(root, &format!(".nyc_output/{i:04}.json"), ISTANBUL); - } - - let outcome = discover(&DiscoveryOptions { - roots: vec![root.to_path_buf()], - ..Default::default() - }); - // Default per-dir cap is 64; the name-sorted walk keeps the - // lexicographically first shards. - assert_eq!(outcome.reports.len(), 64); - assert!( - outcome - .diagnostics - .caps_hit - .contains(&"per_dir_candidates".to_string()) - ); - assert!(outcome.reports[0].path.ends_with(".nyc_output/0000.json")); -} diff --git a/crates/mehen-coverage-discovery/tests/snapshots/discovery_scenarios__monorepo_discovery.snap b/crates/mehen-coverage-discovery/tests/snapshots/discovery_scenarios__monorepo_discovery.snap deleted file mode 100644 index 47ce4d86..00000000 --- a/crates/mehen-coverage-discovery/tests/snapshots/discovery_scenarios__monorepo_discovery.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: crates/mehen-coverage-discovery/tests/discovery_scenarios.rs -expression: "projection(root, &outcome)" ---- -- "report clover build/logs/clover.xml (tool-config:phpunit.xml.dist)" -- "report cobertura qa/cov.xml (tool-config:pyproject.toml)" -- "report lcov target/cov/lcov.info (tool-config:tarpaulin.toml)" -- report istanbul .nyc_output/aaa.json (scan) -- report cobertura TestResults/bbbb-2222/coverage.cobertura.xml (scan) -- report lcov coverage/lcov.info (scan) -- report gocover go/coverage.out (scan) -- report jacoco ps/coverage.xml (scan) -- report cobertura py/coverage.xml (scan) -- report lcov target/llvm-cov/lcov.info (scan) -- rejected TestResults/aaaa-1111/coverage.cobertura.xml OlderRun kept TestResults/bbbb-2222/coverage.cobertura.xml -- rejected coverage/clover.xml Superseded by coverage/lcov.info -- rejected coverage/coverage-final.json Superseded by coverage/lcov.info -- rejected empty.lcov Empty -- rejected notes/coverage.txt SniffMismatch -- rejected target/cov/cobertura.xml Superseded by target/cov/lcov.info diff --git a/crates/mehen-coverage/Cargo.toml b/crates/mehen-coverage/Cargo.toml deleted file mode 100644 index 7a4c4b1e..00000000 --- a/crates/mehen-coverage/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "mehen-coverage" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — coverage-report parsing (LCOV, Go coverprofile, Istanbul, JaCoCo, Clover, Cobertura), merging, and source-path matching (internal)." -publish = false - -[dependencies] -camino = { workspace = true } -quick-xml = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -pretty_assertions = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-coverage/src/error.rs b/crates/mehen-coverage/src/error.rs deleted file mode 100644 index 69f5938e..00000000 --- a/crates/mehen-coverage/src/error.rs +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use core::fmt; - -/// Failure while reading or parsing a coverage report. -/// -/// Kept deliberately small: callers either surface the message as a -/// diagnostic (discovered reports degrade to warnings) or as a hard, -/// user-attributable error (explicit `--coverage` paths). -#[derive(Debug)] -pub enum CoverageError { - /// I/O failure while reading report bytes. - Io(std::io::Error), - /// Malformed report content. The message carries position context - /// where the underlying parser provides it. - Malformed(String), -} - -impl fmt::Display for CoverageError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Io(e) => write!(f, "I/O error reading coverage report: {e}"), - Self::Malformed(msg) => f.write_str(msg), - } - } -} - -impl std::error::Error for CoverageError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Self::Io(e) => Some(e), - Self::Malformed(_) => None, - } - } -} - -impl From for CoverageError { - fn from(e: std::io::Error) -> Self { - Self::Io(e) - } -} diff --git a/crates/mehen-coverage/src/index.rs b/crates/mehen-coverage/src/index.rs deleted file mode 100644 index 0ac6b08b..00000000 --- a/crates/mehen-coverage/src/index.rs +++ /dev/null @@ -1,536 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! The coverage path index — mapping report-spelled paths onto the files -//! mehen analyzes. -//! -//! This is where coverage integrations silently fail (the cargo-crap -//! "path-matching problem"): complexity analysis sees workspace paths, -//! while reports contain whatever the coverage tool wrote — -//! -//! 1. absolute CI paths (`/home/runner/work/repo/repo/src/lib.rs`), -//! 2. workspace-relative paths (`src/lib.rs`), -//! 3. Java package paths missing the source-root prefix -//! (`com/example/Foo.java` for `src/main/java/com/example/Foo.java`), -//! 4. Go module import paths carrying an extra prefix -//! (`github.com/org/repo/pkg/f.go` for `pkg/f.go`), -//! 5. `./`/`../`-spelled variants of any of the above. -//! -//! A naive map lookup returns nothing for 100% of files when the two -//! sides disagree, and every function reads as 0% covered. The index -//! resolves a query in two moves: -//! -//! * **Candidate collection** — report paths spelled absolute that -//! exist on this machine carry a canonicalized on-disk identity; a -//! query resolving to the same real file matches outright, and an -//! entry whose identity *provably differs* from the query's is -//! excluded. Everything else matches by component suffix (components, -//! never bytes: `/foo/bar.rs` must not match `oofoo/bar.rs`). -//! * **Alias merging** — several report entries can be -//! equivalence-proven spellings of one workspace file: the exact -//! relative spelling, the same path behind a CI-absolute prefix, an -//! `lcov -a` leg. All proven aliases *merge* (saturating-max, the -//! cross-report rule) instead of the best-ranked one shadowing the -//! rest. Distinct relative entries that merely share a suffix -//! (`src/lib.rs` vs `vendor/dep/src/lib.rs`) are **not** aliases: -//! the exact spelling wins when present, and a genuine tie is -//! reported as [`FileMatch::Ambiguous`] rather than resolved by map -//! order. -//! -//! Relative report paths are **never** canonicalized against the -//! process CWD — that would silently bind them to whatever happens to -//! exist under the tool's working directory. - -use std::borrow::Cow; -use std::collections::BTreeMap; -use std::path::PathBuf; - -use camino::Utf8Path; - -use crate::merge::{is_absolute_spelling, merge_file_into, normalize_components}; -use crate::model::{CoverageData, FileCoverage}; - -/// Result of asking the index for a workspace file's coverage. -#[derive(Debug)] -pub enum FileMatch<'a> { - /// One or more equivalence-proven report entries matched; several - /// aliases arrive pre-merged. - Found { coverage: Cow<'a, FileCoverage> }, - /// Several *distinct* report entries matched with equal - /// specificity; matching any one of them would be a coin flip, so - /// the file reads as unmeasured and the caller diagnoses it. - Ambiguous { candidates: usize }, - /// No report entry matched. - NotFound, -} - -struct Entry { - coverage: FileCoverage, - components: Vec, - /// Whether the report spelled this path absolutely. - absolute: bool, - /// On-disk identity, when the absolute spelling exists here. - canonical: Option, -} - -/// Calculate-once query structure over merged coverage data. -pub struct CoverageIndex { - entries: Vec, - /// Last path component → entry ids, deterministic order. - by_basename: BTreeMap>, -} - -impl CoverageIndex { - /// Build the index from merged, normalized coverage data (the output - /// of [`crate::merge::merge_reports`]). - #[must_use] - pub fn build(data: CoverageData) -> Self { - let mut entries = Vec::with_capacity(data.files.len()); - let mut by_basename: BTreeMap> = BTreeMap::new(); - - for file in data.files { - let absolute = is_absolute_spelling(&file.path); - let components = normalize_components(&file.path); - let Some(basename) = components.last() else { - continue; // degenerate empty path - }; - let id = entries.len(); - by_basename.entry(basename.clone()).or_default().push(id); - - // Canonicalize only paths the report spelled absolute — and - // only when they exist here. Missing paths (reports produced - // on another machine) participate through suffix matching. - // Relative paths are never resolved against the CWD. - let canonical = if absolute { - std::fs::canonicalize(absolute_spelling(&components)).ok() - } else { - None - }; - - entries.push(Entry { - coverage: file, - components, - absolute, - canonical, - }); - } - - Self { - entries, - by_basename, - } - } - - /// Number of report file entries behind the index. - #[must_use] - pub fn len(&self) -> usize { - self.entries.len() - } - - /// Whether the index holds no entries at all. - #[must_use] - pub fn is_empty(&self) -> bool { - self.entries.is_empty() - } - - /// Look up coverage for a workspace file, spelled however the caller - /// spells paths (CWD-relative, repo-relative, or absolute). - #[must_use] - pub fn file(&self, path: &Utf8Path) -> FileMatch<'_> { - let query = normalize_components(path.as_str()); - let Some(basename) = query.last() else { - return FileMatch::NotFound; - }; - let Some(bucket) = self.by_basename.get(basename) else { - return FileMatch::NotFound; - }; - // The identity probe is one syscall per query; skip it when no - // entry in this bucket carries an on-disk identity to compare - // against (relative-spelled reports: LCOV, Go, JaCoCo). - let query_canonical = if bucket - .iter() - .any(|&id| self.entries[id].canonical.is_some()) - { - std::fs::canonicalize(path.as_std_path()).ok() - } else { - None - }; - - // Candidate collection: suffix-valid entries, minus those whose - // on-disk identity provably differs from the query's. - struct Candidate { - id: usize, - suffix: usize, - entry_len: usize, - identity_match: bool, - } - let mut candidates: Vec = Vec::new(); - for &id in bucket { - let entry = &self.entries[id]; - let identity_match = match (&entry.canonical, &query_canonical) { - (Some(e), Some(q)) => { - if e != q { - continue; // provably different files - } - true - } - _ => false, - }; - let suffix = common_suffix_len(&query, &entry.components); - // Valid only when the shorter side is fully consumed: the - // report path is a tail of the workspace path (JaCoCo - // package paths) or the workspace path is a tail of the - // report path (CI prefixes, Go module prefixes). An - // identity-proven entry is valid regardless of spelling. - if !identity_match && (suffix == 0 || suffix < query.len().min(entry.components.len())) - { - continue; - } - candidates.push(Candidate { - id, - suffix, - entry_len: entry.components.len(), - identity_match, - }); - } - if candidates.is_empty() { - return FileMatch::NotFound; - } - - // Alias pool. Proven members: on-disk identity matches, exact - // component equality, or a *longer absolute* spelling ending in - // the full query (a checkout prefix from another machine — a - // longer *relative* spelling is a more deeply nested, different - // workspace file and never an alias). - let full_query = |c: &Candidate| c.suffix == query.len(); - let exact = |c: &Candidate| full_query(c) && c.suffix == c.entry_len; - let has_anchor = candidates.iter().any(|c| c.identity_match || exact(c)); - - let pool: Vec = if has_anchor { - candidates - .iter() - .filter(|c| { - c.identity_match || exact(c) || (full_query(c) && self.entries[c.id].absolute) - }) - .map(|c| c.id) - .collect() - } else { - let rel_longer: Vec<&Candidate> = candidates - .iter() - .filter(|c| full_query(c) && !self.entries[c.id].absolute && !exact(c)) - .collect(); - if rel_longer.len() > 1 { - return FileMatch::Ambiguous { - candidates: rel_longer.len(), - }; - } - let pool: Vec = candidates - .iter() - .filter(|c| full_query(c)) - .map(|c| c.id) - .collect(); - if pool.is_empty() { - // Entry-consumed direction (report path is a tail of - // the workspace path): the longest suffix wins; a tie - // between distinct entries is a coin flip we refuse. - let best = candidates.iter().map(|c| c.suffix).max().unwrap_or(0); - let tier: Vec = candidates - .iter() - .filter(|c| c.suffix == best) - .map(|c| c.id) - .collect(); - if tier.len() > 1 { - return FileMatch::Ambiguous { - candidates: tier.len(), - }; - } - tier - } else { - pool - } - }; - - match pool.as_slice() { - [] => FileMatch::NotFound, - [single] => FileMatch::Found { - coverage: Cow::Borrowed(&self.entries[*single].coverage), - }, - [first, rest @ ..] => { - // Merge equivalence-proven aliases so no spelling's - // data is silently dropped (the cross-report - // saturating-max rule, applied at query time). - let mut merged = self.entries[*first].coverage.clone(); - for &id in rest { - merge_file_into(&mut merged, &self.entries[id].coverage); - } - FileMatch::Found { - coverage: Cow::Owned(merged), - } - } - } - } -} - -/// Rebuild an absolute-spelled report path from its normalized -/// components for the on-disk identity probe. Windows drive-qualified -/// spellings (`C:\repo\src\lib.rs` → `["C:", "repo", …]`) keep the -/// drive prefix bare — a leading `/` would produce `/C:/repo/…`, which -/// `canonicalize` rejects on Windows, silently downgrading every -/// drive-spelled entry from identity matching to suffix matching. -fn absolute_spelling(components: &[String]) -> PathBuf { - let joined = components.join("/"); - let drive_qualified = components.first().is_some_and(|first| { - first.len() == 2 && first.as_bytes()[0].is_ascii_alphabetic() && first.ends_with(':') - }); - if drive_qualified { - PathBuf::from(joined) - } else { - PathBuf::from(format!("/{joined}")) - } -} - -/// Number of trailing components shared by two component lists. -fn common_suffix_len(a: &[String], b: &[String]) -> usize { - a.iter() - .rev() - .zip(b.iter().rev()) - .take_while(|(x, y)| x == y) - .count() -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::model::LineCoverage; - - fn entry(path: &str) -> FileCoverage { - entry_with_lines(path, &[(1, 1)]) - } - - fn entry_with_lines(path: &str, lines: &[(u32, u64)]) -> FileCoverage { - let mut f = FileCoverage::new(path.to_string()); - f.lines = lines - .iter() - .map(|&(line_number, hit_count)| LineCoverage { - line_number, - hit_count, - }) - .collect(); - f - } - - fn index(paths: &[&str]) -> CoverageIndex { - CoverageIndex::build(crate::merge::merge_reports(vec![CoverageData { - files: paths.iter().map(|p| entry(p)).collect(), - }])) - } - - fn found<'a>(index: &'a CoverageIndex, query: &str) -> Option> { - match index.file(Utf8Path::new(query)) { - FileMatch::Found { coverage } => Some(coverage), - _ => None, - } - } - - fn found_path(index: &CoverageIndex, query: &str) -> Option { - found(index, query).map(|c| c.path.clone()) - } - - #[test] - fn absolute_spelling_preserves_windows_drive_prefixes() { - let drive = ["C:".to_string(), "repo".into(), "lib.rs".into()]; - assert_eq!(absolute_spelling(&drive), PathBuf::from("C:/repo/lib.rs")); - // POSIX spellings regain their root slash; a first component - // that merely contains a colon (`a:b`, valid on POSIX) is not - // a drive. - let posix = ["home".to_string(), "a:b".into(), "lib.rs".into()]; - assert_eq!(absolute_spelling(&posix), PathBuf::from("/home/a:b/lib.rs")); - } - - #[test] - fn exact_relative_path_matches() { - let idx = index(&["src/lib.rs"]); - assert_eq!( - found_path(&idx, "src/lib.rs").as_deref(), - Some("src/lib.rs") - ); - } - - #[test] - fn ci_absolute_prefix_is_absorbed() { - // Report written on a CI machine whose checkout root does not - // exist here: the workspace-relative query suffix-matches. - let idx = index(&["/home/runner/work/repo/repo/src/lib.rs"]); - assert_eq!( - found_path(&idx, "src/lib.rs").as_deref(), - Some("/home/runner/work/repo/repo/src/lib.rs") - ); - } - - #[test] - fn jacoco_package_path_matches_longer_workspace_path() { - // JaCoCo spells `package/File.java`; the workspace file carries - // the `src/main/java/` prefix the report never saw. - let idx = index(&["com/example/Foo.java"]); - assert_eq!( - found_path(&idx, "src/main/java/com/example/Foo.java").as_deref(), - Some("com/example/Foo.java") - ); - } - - #[test] - fn go_module_prefix_is_absorbed() { - // Go coverprofiles spell module import paths, not filesystem - // paths. - let idx = index(&["github.com/org/repo/pkg/handler.go"]); - assert_eq!( - found_path(&idx, "pkg/handler.go").as_deref(), - Some("github.com/org/repo/pkg/handler.go") - ); - } - - #[test] - fn component_boundaries_are_respected() { - // "/foo/bar.rs" must not match "oofoo/bar.rs" — matching is on - // components, never on byte suffixes. - let idx = index(&["/foo/bar.rs"]); - assert_eq!(found_path(&idx, "oofoo/bar.rs"), None); - // Basename alone still matches (report consumed). - assert_eq!(found_path(&idx, "bar.rs").as_deref(), Some("/foo/bar.rs")); - } - - #[test] - fn exact_spelling_wins_over_deeper_relative_suffix() { - // cargo-crap spec 26: `src/lib.rs` vs `vendor/dep/src/lib.rs` — - // a deeper *relative* entry is a different workspace file, not - // an alias, so its data must not merge into the exact match. - let idx = CoverageIndex::build(crate::merge::merge_reports(vec![CoverageData { - files: vec![ - entry_with_lines("src/lib.rs", &[(1, 1)]), - entry_with_lines("vendor/dep/src/lib.rs", &[(9, 9)]), - ], - }])); - assert_eq!( - found_path(&idx, "vendor/dep/src/lib.rs").as_deref(), - Some("vendor/dep/src/lib.rs") - ); - let exact = found(&idx, "src/lib.rs").expect("exact match"); - assert_eq!(exact.path, "src/lib.rs"); - assert!( - exact.lines.iter().all(|l| l.line_number != 9), - "vendor data must not merge into the exact match" - ); - } - - #[test] - fn absolute_and_relative_aliases_merge_their_data() { - // The same file measured by two reports: one leg spelled - // repo-relative, one behind a CI-absolute prefix. Both are - // equivalence-proven spellings of the query and must merge — - // returning only the "best" one would silently drop the other - // leg's coverage. - let relative = CoverageData { - files: vec![entry_with_lines("src/lib.rs", &[(1, 1), (2, 0)])], - }; - let absolute = CoverageData { - files: vec![entry_with_lines( - "/ci/work/repo/repo/src/lib.rs", - &[(2, 3), (7, 1)], - )], - }; - let idx = CoverageIndex::build(crate::merge::merge_reports(vec![relative, absolute])); - assert_eq!(idx.len(), 2, "spellings stay distinct in the merge layer"); - - let merged = found(&idx, "src/lib.rs").expect("alias merge"); - let line = |n: u32| { - merged - .lines - .iter() - .find(|l| l.line_number == n) - .map(|l| l.hit_count) - }; - assert_eq!(line(1), Some(1)); - assert_eq!(line(2), Some(3), "max of both legs"); - assert_eq!(line(7), Some(1), "absolute-only line preserved"); - } - - #[test] - fn genuine_tie_is_ambiguous_not_map_order() { - // Two distinct report entries end in `sub/mod.rs`; a query that - // cannot tell them apart must not silently pick one. - let idx = index(&["a/sub/mod.rs", "b/sub/mod.rs"]); - match idx.file(Utf8Path::new("sub/mod.rs")) { - FileMatch::Ambiguous { candidates } => assert_eq!(candidates, 2), - other => panic!("expected ambiguous, got {other:?}"), - } - // A more specific query resolves it. - assert_eq!( - found_path(&idx, "a/sub/mod.rs").as_deref(), - Some("a/sub/mod.rs") - ); - } - - #[test] - fn relative_entries_are_not_resolved_against_cwd() { - // Regression pinned by cargo-crap: a relative report path must - // not be canonicalized against the process CWD. This index has a - // relative entry whose basename exists in *this* repository — - // matching must still go through suffix logic (and succeed on - // component identity), not through a CWD-canonicalized identity - // that would shadow differently-rooted queries. - let idx = index(&["nested/Cargo.toml"]); - assert_eq!( - found_path(&idx, "elsewhere/nested/Cargo.toml").as_deref(), - Some("nested/Cargo.toml") - ); - assert_eq!(found_path(&idx, "unrelated.rs"), None); - } - - #[test] - fn dot_spelled_variants_match() { - let idx = index(&["./src/app.py"]); - assert_eq!( - found_path(&idx, "src/app.py").as_deref(), - Some("src/app.py") - ); - } - - #[test] - fn absolute_report_path_existing_on_this_machine_matches_canonically() { - // Build a real file, spell the report path absolutely, query via - // a differently-spelled path to the same file. - let dir = std::env::temp_dir().join(format!("mehen-cov-idx-{}", std::process::id())); - std::fs::create_dir_all(dir.join("sub")).unwrap(); - let real = dir.join("sub/target_file.rs"); - std::fs::write(&real, "fn main() {}\n").unwrap(); - - let report_path = real.to_str().unwrap().to_string(); - let idx = index(&[&report_path]); - // Query through a `..`-spelled variant of the same on-disk file. - let query = format!("{}/sub/../sub/target_file.rs", dir.to_str().unwrap()); - let hit = found_path(&idx, &query).expect("canonical identity match"); - assert!(hit.ends_with("target_file.rs")); - std::fs::remove_dir_all(&dir).ok(); - } - - #[test] - fn known_different_identity_is_excluded() { - // An absolute entry that exists locally and resolves to a - // *different* file must not be offered as suffix evidence for - // this query. - let dir = std::env::temp_dir().join(format!("mehen-cov-idx2-{}", std::process::id())); - std::fs::create_dir_all(dir.join("a/sub")).unwrap(); - std::fs::create_dir_all(dir.join("b/sub")).unwrap(); - std::fs::write(dir.join("a/sub/f.rs"), "a\n").unwrap(); - std::fs::write(dir.join("b/sub/f.rs"), "b\n").unwrap(); - - let report = format!("{}/a/sub/f.rs", dir.to_str().unwrap()); - let idx = index(&[&report]); - let other = format!("{}/b/sub/f.rs", dir.to_str().unwrap()); - assert!( - found_path(&idx, &other).is_none(), - "provably different on-disk identity must not match" - ); - std::fs::remove_dir_all(&dir).ok(); - } -} diff --git a/crates/mehen-coverage/src/lib.rs b/crates/mehen-coverage/src/lib.rs deleted file mode 100644 index 9fdae2aa..00000000 --- a/crates/mehen-coverage/src/lib.rs +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Coverage-report ingestion: parsing, merging, and source-path matching. -//! -//! This crate is the format layer of mehen's `coverage.*` metric family. -//! It stays deliberately pure — no filesystem walking, no git, no metric -//! spaces — so the engine can feed it bytes from any origin (explicit CLI -//! paths, tool-config introspection, or the artifact scan in -//! `mehen-coverage-discovery`) and query the result per analyzed file: -//! -//! 1. [`detect_format`] sniffs a candidate file (path + first 4 KiB) and -//! assigns one of the six supported [`CoverageFormat`]s. -//! 2. Each format parser streams a report into per-file -//! [`FileCoverage`] records (lines, branch arms, functions). -//! 3. [`merge::merge_reports`] folds any number of reports into one -//! deterministic, normalized [`CoverageData`] (union of files, -//! saturating-max hit counts — "covered anywhere ⇒ covered"). -//! 4. [`CoverageIndex`] answers "coverage for this workspace file?" via a -//! two-level path match: canonical absolute lookup first, then a -//! component-wise longest-suffix match that absorbs CI prefixes, JaCoCo -//! package paths, and Go module import paths. -//! -//! The parsers are adapted from the MIT-licensed -//! [covrs](https://github.com/scttnlsn/covrs) project by Scott Nelson — -//! see `LICENSE-THIRD-PARTY` at the repository root for attribution and -//! the per-file provenance headers for local changes. - -#![deny(unsafe_code)] - -mod error; -mod index; -pub mod merge; -mod model; -pub mod parsers; - -pub use error::CoverageError; -pub use index::{CoverageIndex, FileMatch}; -pub use model::{ - BranchCoverage, CoverageData, FileCoverage, FunctionCoverage, LineCoverage, SpanTotals, rate, -}; -pub use parsers::{CoverageFormat, CoverageParser, detect, for_format}; - -/// Convenience result alias used across the crate. -pub type Result = std::result::Result; - -/// Sniff a candidate report (path plus the first few KiB of content) and -/// return the detected format, if any. Detection is cheap by contract: -/// extension/filename checks plus content markers within the first 4 KiB. -#[must_use] -pub fn detect_format(path: &camino::Utf8Path, head: &[u8]) -> Option { - parsers::detect(path, head).map(|p| p.format()) -} - -/// Parse a complete report of a known format from raw bytes. -pub fn parse_report(format: CoverageFormat, input: &[u8]) -> Result { - let parser = for_format(format); - let mut data = CoverageData::new(); - parser.parse_streaming(&mut &*input, &mut |file| { - data.files.push(file); - Ok(()) - })?; - Ok(data) -} diff --git a/crates/mehen-coverage/src/merge.rs b/crates/mehen-coverage/src/merge.rs deleted file mode 100644 index 1aba2d9c..00000000 --- a/crates/mehen-coverage/src/merge.rs +++ /dev/null @@ -1,323 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Deterministic multi-report merging. -//! -//! Auto-discovery (and monorepo CI) routinely yields several reports for -//! one workspace: per-package Jest runs, per-assembly dotnet -//! `TestResults`, `.nyc_output` shards, or an explicit list of paths. The -//! merge folds them into one [`CoverageData`]: -//! -//! * **Union of source files** — a file measured by any report is -//! present. -//! * **Saturating-max hit counts** for records shared between reports — -//! "covered anywhere ⇒ covered". Max is commutative and associative, -//! so the result is independent of report enumeration order; summing -//! was rejected because identical re-runs would double-count, and -//! newest-wins was rejected because git checkouts do not preserve -//! mtimes. -//! -//! Files are keyed by their *normalized* report path (forward slashes, -//! `.`/`..` segments resolved lexically) so `./src/lib.rs` and -//! `src/lib.rs` from two merged legs collapse into one record instead of -//! racing on map order. - -use std::collections::BTreeMap; - -use crate::model::{BranchCoverage, CoverageData, FileCoverage, FunctionCoverage, LineCoverage}; - -/// Normalize a report-spelled path for identity comparison and suffix -/// matching: backslashes become forward slashes (reports written on -/// Windows must match on any host), `.` segments drop, and `..` segments -/// pop lexically where possible. The result is a component list — the -/// unit of all path matching in this crate ("`/foo/bar.rs` must not -/// match `oofoo/bar.rs`"). -#[must_use] -pub(crate) fn normalize_components(path: &str) -> Vec { - let mut components: Vec = Vec::new(); - for raw in path.split(['/', '\\']) { - match raw { - "" | "." => {} - ".." => { - // Pop when possible; a leading `..` that cannot pop is - // kept literally so distinct escapes stay distinct. - if components.last().is_some_and(|c| c != "..") { - components.pop(); - } else { - components.push("..".to_string()); - } - } - other => components.push(other.to_string()), - } - } - components -} - -/// Whether the original path spelling was absolute (POSIX root or a -/// Windows drive/UNC prefix). -#[must_use] -pub(crate) fn is_absolute_spelling(path: &str) -> bool { - path.starts_with('/') - || path.starts_with('\\') - || (path.len() >= 3 - && path.as_bytes()[0].is_ascii_alphabetic() - && path.as_bytes()[1] == b':' - && matches!(path.as_bytes()[2], b'/' | b'\\')) -} - -/// Merge any number of parsed reports into one normalized -/// [`CoverageData`], ordered deterministically by normalized path. -#[must_use] -pub fn merge_reports(reports: Vec) -> CoverageData { - // Keyed by (absolute-spelling flag ++ normalized path) so an - // absolute `/ci/src/lib.rs` and a relative `src/lib.rs` stay two - // records — the index decides later whether they describe the same - // workspace file; collapsing them here would guess. - let mut by_path: BTreeMap = BTreeMap::new(); - - for report in reports { - for mut file in report.files { - file.normalize(); - let mut key = if is_absolute_spelling(&file.path) { - String::from("/") - } else { - String::new() - }; - key.push_str(&normalize_components(&file.path).join("/")); - - match by_path.entry(key.clone()) { - std::collections::btree_map::Entry::Vacant(slot) => { - // Store under the normalized spelling so identical - // files from differently-spelled legs land together. - file.path = key; - slot.insert(file); - } - std::collections::btree_map::Entry::Occupied(mut slot) => { - merge_file_into(slot.get_mut(), &file); - } - } - } - } - - CoverageData { - files: by_path.into_values().collect(), - } -} - -/// Fold `incoming` into `kept` with saturating-max semantics. Both sides -/// must be normalized. Also used by the query index to combine -/// equivalence-proven spellings of one file at lookup time. -pub(crate) fn merge_file_into(kept: &mut FileCoverage, incoming: &FileCoverage) { - // Lines: keyed by line number. - let mut lines: BTreeMap = kept - .lines - .drain(..) - .map(|l| (l.line_number, l.hit_count)) - .collect(); - for l in &incoming.lines { - let slot = lines.entry(l.line_number).or_insert(0); - *slot = (*slot).max(l.hit_count); - } - kept.lines = lines - .into_iter() - .map(|(line_number, hit_count)| LineCoverage { - line_number, - hit_count, - }) - .collect(); - - // Branch arms: keyed by (line, arm index). - let mut branches: BTreeMap<(u32, u32), u64> = kept - .branches - .drain(..) - .map(|b| ((b.line_number, b.branch_index), b.hit_count)) - .collect(); - for b in &incoming.branches { - let slot = branches.entry((b.line_number, b.branch_index)).or_insert(0); - *slot = (*slot).max(b.hit_count); - } - kept.branches = branches - .into_iter() - .map(|((line_number, branch_index), hit_count)| BranchCoverage { - line_number, - branch_index, - hit_count, - }) - .collect(); - - // Functions: keyed by (start line, name). - let mut functions: BTreeMap<(Option, String), (Option, u64)> = kept - .functions - .drain(..) - .map(|f| ((f.start_line, f.name), (f.end_line, f.hit_count))) - .collect(); - for f in &incoming.functions { - let slot = functions - .entry((f.start_line, f.name.clone())) - .or_insert((f.end_line, 0)); - slot.0 = slot.0.max(f.end_line); - slot.1 = slot.1.max(f.hit_count); - } - kept.functions = functions - .into_iter() - .map( - |((start_line, name), (end_line, hit_count))| FunctionCoverage { - name, - start_line, - end_line, - hit_count, - }, - ) - .collect(); -} - -#[cfg(test)] -mod tests { - use super::*; - - fn file(path: &str, lines: &[(u32, u64)]) -> FileCoverage { - let mut f = FileCoverage::new(path.to_string()); - f.lines = lines - .iter() - .map(|&(line_number, hit_count)| LineCoverage { - line_number, - hit_count, - }) - .collect(); - f - } - - fn data(files: Vec) -> CoverageData { - CoverageData { files } - } - - #[test] - fn merge_is_order_independent() { - let a = data(vec![file("src/lib.rs", &[(1, 0), (2, 3)])]); - let b = data(vec![ - file("src/lib.rs", &[(1, 5), (3, 0)]), - file("src/other.rs", &[(1, 1)]), - ]); - - let ab = merge_reports(vec![a.clone(), b.clone()]); - let reversed = merge_reports(vec![b, a]); - assert_eq!(ab, reversed); - - assert_eq!(ab.files.len(), 2); - let lib = &ab.files[0]; - assert_eq!(lib.path, "src/lib.rs"); - // Union of lines, max hits per line. - assert_eq!( - lib.lines, - vec![ - LineCoverage { - line_number: 1, - hit_count: 5 - }, - LineCoverage { - line_number: 2, - hit_count: 3 - }, - LineCoverage { - line_number: 3, - hit_count: 0 - }, - ] - ); - } - - #[test] - fn different_spellings_of_one_file_collapse() { - let a = data(vec![file("./src/lib.rs", &[(1, 1)])]); - let b = data(vec![file("src/lib.rs", &[(2, 1)])]); - let merged = merge_reports(vec![a, b]); - assert_eq!(merged.files.len(), 1); - assert_eq!(merged.files[0].path, "src/lib.rs"); - assert_eq!(merged.files[0].lines.len(), 2); - } - - #[test] - fn absolute_and_relative_spellings_stay_distinct() { - // Whether `/ci/build/src/lib.rs` and `src/lib.rs` are the same - // workspace file is the index's judgement call, not the merge's. - let a = data(vec![file("/ci/build/src/lib.rs", &[(1, 1)])]); - let b = data(vec![file("src/lib.rs", &[(1, 0)])]); - let merged = merge_reports(vec![a, b]); - assert_eq!(merged.files.len(), 2); - } - - #[test] - fn windows_separators_normalize() { - let a = data(vec![file(r"src\win\mod.rs", &[(1, 1)])]); - let merged = merge_reports(vec![a]); - assert_eq!(merged.files[0].path, "src/win/mod.rs"); - } - - #[test] - fn normalize_components_handles_dot_segments() { - assert_eq!( - normalize_components("./src/./lib.rs"), - vec!["src", "lib.rs"] - ); - assert_eq!( - normalize_components("src/sub/../lib.rs"), - vec!["src", "lib.rs"] - ); - assert_eq!(normalize_components("../lib.rs"), vec!["..", "lib.rs"]); - } - - #[test] - fn merge_keys_branch_arms_by_line_and_index() { - let mut a_file = FileCoverage::new("src/lib.rs".to_string()); - a_file.branches = vec![ - BranchCoverage { - line_number: 7, - branch_index: 0, - hit_count: 1, - }, - BranchCoverage { - line_number: 7, - branch_index: 1, - hit_count: 0, - }, - ]; - let mut b_file = FileCoverage::new("src/lib.rs".to_string()); - b_file.branches = vec![BranchCoverage { - line_number: 7, - branch_index: 1, - hit_count: 2, - }]; - - let merged = merge_reports(vec![data(vec![a_file]), data(vec![b_file])]); - let branches = &merged.files[0].branches; - assert_eq!(branches.len(), 2); - assert_eq!(branches[0].hit_count, 1); - assert_eq!(branches[1].hit_count, 2); - } - - #[test] - fn merge_takes_max_hits_and_widest_span_for_functions() { - // Functions merge by (start_line, name); Option ordering makes - // None.max(Some(n)) resolve to Some(n) — the widest known span - // wins, which is deliberate but not obvious. - let mut a_file = FileCoverage::new("src/lib.rs".to_string()); - a_file.functions = vec![FunctionCoverage { - name: "f".into(), - start_line: Some(10), - end_line: None, - hit_count: 0, - }]; - let mut b_file = FileCoverage::new("src/lib.rs".to_string()); - b_file.functions = vec![FunctionCoverage { - name: "f".into(), - start_line: Some(10), - end_line: Some(20), - hit_count: 4, - }]; - - let merged = merge_reports(vec![data(vec![a_file]), data(vec![b_file])]); - assert_eq!(merged.files[0].functions.len(), 1); - assert_eq!(merged.files[0].functions[0].end_line, Some(20)); - assert_eq!(merged.files[0].functions[0].hit_count, 4); - } -} diff --git a/crates/mehen-coverage/src/model.rs b/crates/mehen-coverage/src/model.rs deleted file mode 100644 index 0de5b989..00000000 --- a/crates/mehen-coverage/src/model.rs +++ /dev/null @@ -1,317 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) `src/model.rs`, -// MIT-licensed by Scott Nelson. Local changes: serde derives, record -// normalization (sort + dedupe-by-max), and span-scoped totals for -// per-function metric injection. See LICENSE-THIRD-PARTY. - -//! Uniform in-memory representation of coverage data, independent of any -//! specific report format. Parsers produce [`FileCoverage`] records; the -//! merge layer folds many reports into one [`CoverageData`]; the engine -//! queries totals at file scope and per function span. - -use serde::Serialize; - -/// Compute a coverage rate as a percentage in `0.0..=100.0`, returning -/// `None` when nothing was instrumentable — "no data" must stay -/// distinguishable from "0% covered" all the way to the metric layer. -#[must_use] -pub fn rate(covered: u64, total: u64) -> Option { - if total == 0 { - None - } else { - Some(covered as f64 * 100.0 / total as f64) - } -} - -/// A single line that was instrumentable. -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -pub struct LineCoverage { - pub line_number: u32, - pub hit_count: u64, -} - -/// A single branch arm on a given line. -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -pub struct BranchCoverage { - pub line_number: u32, - pub branch_index: u32, - pub hit_count: u64, -} - -/// A function/method that was instrumentable. -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -pub struct FunctionCoverage { - pub name: String, - pub start_line: Option, - pub end_line: Option, - pub hit_count: u64, -} - -/// Covered/total counters for one measurement dimension. -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize)] -pub struct SpanTotals { - pub covered: u64, - pub total: u64, -} - -impl SpanTotals { - /// Coverage percentage, `None` when nothing was instrumentable. - #[must_use] - pub fn rate(self) -> Option { - rate(self.covered, self.total) - } -} - -/// Coverage data for a single source file, as spelled by the report. -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)] -pub struct FileCoverage { - pub path: String, - pub lines: Vec, - pub branches: Vec, - pub functions: Vec, -} - -impl FileCoverage { - #[must_use] - pub fn new(path: String) -> Self { - Self { - path, - ..Default::default() - } - } - - /// Canonicalize record order and collapse duplicates. - /// - /// Reports produced by merge tools (`lcov -a`) or emitted with the - /// same line under two containers (Cobertura `` + ``) - /// can repeat a record; the maximum hit count wins, matching the - /// cross-report merge semantics ("covered anywhere ⇒ covered"). - /// Normalized records are the precondition for the binary-searched - /// span queries below and for deterministic serialization. - pub fn normalize(&mut self) { - self.lines.sort_by_key(|l| l.line_number); - self.lines.dedup_by(|next, kept| { - if next.line_number == kept.line_number { - kept.hit_count = kept.hit_count.max(next.hit_count); - true - } else { - false - } - }); - - self.branches - .sort_by_key(|b| (b.line_number, b.branch_index)); - self.branches.dedup_by(|next, kept| { - if (next.line_number, next.branch_index) == (kept.line_number, kept.branch_index) { - kept.hit_count = kept.hit_count.max(next.hit_count); - true - } else { - false - } - }); - - self.functions - .sort_by(|a, b| (a.start_line, &a.name).cmp(&(b.start_line, &b.name))); - self.functions.dedup_by(|next, kept| { - if next.name == kept.name && next.start_line == kept.start_line { - kept.hit_count = kept.hit_count.max(next.hit_count); - kept.end_line = kept.end_line.max(next.end_line); - true - } else { - false - } - }); - } - - /// Line totals across the whole file. - #[must_use] - pub fn line_totals(&self) -> SpanTotals { - SpanTotals { - covered: self.lines.iter().filter(|l| l.hit_count > 0).count() as u64, - total: self.lines.len() as u64, - } - } - - /// Branch-arm totals across the whole file. - #[must_use] - pub fn branch_totals(&self) -> SpanTotals { - SpanTotals { - covered: self.branches.iter().filter(|b| b.hit_count > 0).count() as u64, - total: self.branches.len() as u64, - } - } - - /// Function totals across the whole file (report-recorded functions). - #[must_use] - pub fn function_totals(&self) -> SpanTotals { - SpanTotals { - covered: self.functions.iter().filter(|f| f.hit_count > 0).count() as u64, - total: self.functions.len() as u64, - } - } - - /// Line totals restricted to an inclusive 1-based line range — - /// the query per-function metric injection runs against each - /// `MetricSpace` span. Requires [`Self::normalize`]d records. - #[must_use] - pub fn span_line_totals(&self, start_line: u32, end_line: u32) -> SpanTotals { - let from = self.lines.partition_point(|l| l.line_number < start_line); - let mut totals = SpanTotals::default(); - for line in &self.lines[from..] { - if line.line_number > end_line { - break; - } - totals.total += 1; - if line.hit_count > 0 { - totals.covered += 1; - } - } - totals - } - - /// Branch-arm totals restricted to an inclusive 1-based line range. - /// Requires [`Self::normalize`]d records. - #[must_use] - pub fn span_branch_totals(&self, start_line: u32, end_line: u32) -> SpanTotals { - let from = self - .branches - .partition_point(|b| b.line_number < start_line); - let mut totals = SpanTotals::default(); - for branch in &self.branches[from..] { - if branch.line_number > end_line { - break; - } - totals.total += 1; - if branch.hit_count > 0 { - totals.covered += 1; - } - } - totals - } -} - -/// The complete result of parsing a single coverage report. -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)] -pub struct CoverageData { - pub files: Vec, -} - -impl CoverageData { - #[must_use] - pub fn new() -> Self { - Self::default() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn line(line_number: u32, hit_count: u64) -> LineCoverage { - LineCoverage { - line_number, - hit_count, - } - } - - #[test] - fn normalize_dedupes_lines_keeping_max_hits() { - let mut file = FileCoverage::new("a.rs".into()); - file.lines = vec![line(3, 0), line(1, 2), line(3, 5), line(2, 0)]; - file.normalize(); - assert_eq!(file.lines, vec![line(1, 2), line(2, 0), line(3, 5)]); - } - - fn branch(line_number: u32, branch_index: u32, hit_count: u64) -> BranchCoverage { - BranchCoverage { - line_number, - branch_index, - hit_count, - } - } - - #[test] - fn normalize_dedupes_branch_arms_keeping_max_hits() { - // Branch identity is (line, arm index) — not just the line. - let mut file = FileCoverage::new("a.rs".into()); - file.branches = vec![branch(7, 1, 0), branch(7, 0, 2), branch(7, 1, 4)]; - file.normalize(); - assert_eq!(file.branches, vec![branch(7, 0, 2), branch(7, 1, 4)]); - } - - #[test] - fn span_branch_totals_are_inclusive_and_bounded() { - let mut file = FileCoverage::new("a.rs".into()); - file.branches = vec![ - branch(2, 0, 1), - branch(5, 0, 0), - branch(5, 1, 3), - branch(30, 0, 1), - ]; - file.normalize(); - assert_eq!( - file.span_branch_totals(5, 9), - SpanTotals { - covered: 1, - total: 2 - } - ); - // No branch arms in the span is "no data", not 0%. - assert_eq!(file.span_branch_totals(10, 29).rate(), None); - } - - #[test] - fn rate_distinguishes_no_data_from_zero() { - assert_eq!(rate(0, 0), None); - assert_eq!(rate(0, 4), Some(0.0)); - assert_eq!(rate(3, 4), Some(75.0)); - assert_eq!(rate(4, 4), Some(100.0)); - } - - #[test] - fn span_totals_are_inclusive_and_bounded() { - let mut file = FileCoverage::new("a.rs".into()); - file.lines = vec![line(1, 1), line(5, 0), line(6, 2), line(9, 0), line(20, 1)]; - file.normalize(); - // Function spanning lines 5..=9: three instrumentable lines, one hit. - let totals = file.span_line_totals(5, 9); - assert_eq!( - totals, - SpanTotals { - covered: 1, - total: 3 - } - ); - assert_eq!(totals.rate(), Some(100.0 / 3.0)); - // A span with no instrumentable lines is "no data", not 0%. - assert_eq!(file.span_line_totals(10, 19).rate(), None); - } - - #[test] - fn function_totals_count_hit_functions() { - let mut file = FileCoverage::new("a.rs".into()); - file.functions = vec![ - FunctionCoverage { - name: "hit".into(), - start_line: Some(1), - end_line: None, - hit_count: 3, - }, - FunctionCoverage { - name: "missed".into(), - start_line: Some(10), - end_line: None, - hit_count: 0, - }, - ]; - assert_eq!( - file.function_totals(), - SpanTotals { - covered: 1, - total: 2 - } - ); - } -} diff --git a/crates/mehen-coverage/src/parsers/clover.rs b/crates/mehen-coverage/src/parsers/clover.rs deleted file mode 100644 index bd219708..00000000 --- a/crates/mehen-coverage/src/parsers/clover.rs +++ /dev/null @@ -1,375 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) -// `src/parsers/clover.rs`, MIT-licensed by Scott Nelson. Local changes: -// house error type, camino paths, quick-xml 0.41 API, normalization -// before emit. See LICENSE-THIRD-PARTY. - -//! Parser for Clover XML coverage reports. -//! -//! Clover XML structure (as produced by OpenClover, Atlassian Clover, and -//! plugins like `jest --coverageReporters=clover`, PHPUnit, etc.): -//! ```text -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! ``` -//! -//! Key differences from Cobertura: -//! - Root element is `` with a `clover` attribute (version). -//! - Files live inside `` → ``. -//! - Each `` has `num`, `count`, and `type` (stmt|method|cond). -//! - Methods are `` entries. -//! - Branch coverage is expressed via `truecount`/`falsecount` on -//! `` elements. -//! - `` has a `path` attribute with the absolute path and a `name` -//! attribute with just the filename. `path` is preferred when present. - -use std::collections::HashMap; -use std::io::BufRead; - -use camino::Utf8Path; -use quick_xml::events::Event; - -use super::{CoverageFormat, CoverageParser, get_attr}; -use crate::Result; -use crate::model::{BranchCoverage, FileCoverage, FunctionCoverage, LineCoverage}; - -/// Clover XML format parser. -pub(crate) struct CloverParser; - -impl CoverageParser for CloverParser { - fn format(&self) -> CoverageFormat { - CoverageFormat::Clover - } - - fn can_parse(&self, _path: &Utf8Path, content: &[u8]) -> bool { - let head = super::sniff_head(content); - // Clover XML has a as root). - super::looks_like_xml(&head) && head.contains(" { - // Prefer the `path` attribute (absolute) over - // `name` (basename). - let file_path = get_attr(e, b"path") - .or_else(|| get_attr(e, b"name")) - .unwrap_or_default(); - current_file = Some(FileCoverage::new(file_path)); - branch_indices.clear(); - } - b"line" => { - if let Some(file) = current_file.as_mut() { - let mut num: Option = None; - let mut count: u64 = 0; - let mut line_type: Option = None; - let mut signature: Option = None; - let mut truecount: Option = None; - let mut falsecount: Option = None; - - for attr in e.attributes().flatten() { - match attr.key.as_ref() { - b"num" => { - num = super::attr_str(&attr).and_then(|v| v.parse().ok()); - } - b"count" => { - count = super::attr_str(&attr) - .and_then(|v| v.parse().ok()) - .unwrap_or(0); - } - b"type" => { - line_type = super::attr_str(&attr); - } - b"signature" => { - signature = super::attr_str(&attr); - } - b"truecount" => { - truecount = - super::attr_str(&attr).and_then(|v| v.parse().ok()); - } - b"falsecount" => { - falsecount = - super::attr_str(&attr).and_then(|v| v.parse().ok()); - } - _ => {} - } - } - - if let Some(line_number) = num { - // Line coverage — always emit. - file.lines.push(LineCoverage { - line_number, - hit_count: count, - }); - - // Method/function coverage — type="method" - // lines represent function entry points. - if line_type.as_deref() == Some("method") { - let name = signature - .unwrap_or_else(|| format!("")); - file.functions.push(FunctionCoverage { - name, - start_line: Some(line_number), - end_line: None, - hit_count: count, - }); - } - - // Branch coverage — type="cond" lines - // carry truecount/falsecount, the - // *execution counts* of the condition's - // true and false outcomes (OpenClover - // semantics). Each condition is exactly - // two arms: the true arm (hit iff - // truecount > 0) and the false arm (hit - // iff falsecount > 0). The counts must - // not be expanded into arms — a hot - // condition with truecount="10", - // falsecount="5" is still one condition - // with both outcomes exercised. - if line_type.as_deref() == Some("cond") { - let tc = truecount.unwrap_or(0); - let fc = falsecount.unwrap_or(0); - let idx = branch_indices.entry(line_number).or_insert(0); - for hit in [u64::from(tc > 0), u64::from(fc > 0)] { - file.branches.push(BranchCoverage { - line_number, - branch_index: *idx, - hit_count: hit, - }); - *idx += 1; - } - } - } - } - } - _ => {} - } - } - Ok(Event::End(ref e)) => { - if e.name().as_ref() == b"file" - && let Some(file) = current_file.take() - { - emit_normalized(file)?; - } - } - _ => {} - } - buf.clear(); - } - - // Handle unclosed file - if let Some(file) = current_file.take() { - emit_normalized(file)?; - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_clover() { - let input = include_bytes!("../../tests/fixtures/sample_clover.xml"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 2); - - let main = &data.files[0]; - assert_eq!(main.path, "/home/user/project/src/main.py"); - assert_eq!(main.lines.len(), 8); - assert_eq!(main.lines[0].line_number, 1); - assert_eq!(main.lines[0].hit_count, 1); - assert_eq!(main.lines[2].line_number, 3); - assert_eq!(main.lines[2].hit_count, 0); - - // Branch on line 8: type="cond" truecount="1" falsecount="1" - // → 1 condition × 2 arms = 2 branch entries, both hit - assert_eq!(main.branches.len(), 2); - assert_eq!(main.branches[0].line_number, 8); - assert_eq!(main.branches[0].hit_count, 1); // true arm covered - assert_eq!(main.branches[1].line_number, 8); - assert_eq!(main.branches[1].hit_count, 1); // false arm covered - - // One method extracted (line 5, type="method") - assert_eq!(main.functions.len(), 1); - assert_eq!(main.functions[0].name, "do_stuff()"); - assert_eq!(main.functions[0].start_line, Some(5)); - assert_eq!(main.functions[0].hit_count, 3); - - let util = &data.files[1]; - assert_eq!(util.path, "/home/user/project/src/util.py"); - assert_eq!(util.lines.len(), 2); - assert_eq!(util.branches.len(), 0); - } - - #[test] - fn test_parse_clover_empty() { - // A valid Clover file with no files should produce empty data. - let input = include_bytes!("../../tests/fixtures/empty_clover.xml"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 0); - } - - #[test] - fn test_parse_clover_malformed() { - // Malformed XML should produce a meaningful error with position - // info. - let input = include_bytes!("../../tests/fixtures/malformed_clover.xml"); - let result = parse(input); - assert!(result.is_err()); - let err_msg = format!("{}", result.unwrap_err()); - assert!( - err_msg.contains("position"), - "Error should contain position info: {err_msg}", - ); - } - - #[test] - fn test_can_parse_clover() { - let parser = CloverParser; - - // Clover XML with clover= attribute - let content = br#""#; - assert!(parser.can_parse(Utf8Path::new("clover.xml"), content)); - - // Cobertura should NOT match (no clover= attribute) - let content = br#""#; - assert!(!parser.can_parse(Utf8Path::new("coverage.xml"), content)); - - // JaCoCo should NOT match - let content = br#""#; - assert!(!parser.can_parse(Utf8Path::new("report.xml"), content)); - } - - #[test] - fn test_parse_clover_no_path_attr() { - // When has no `path` attribute, fall back to `name`. - let input = br#" - - - - - - - - -"#; - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 1); - assert_eq!(data.files[0].path, "app.py"); - } - - #[test] - fn test_parse_clover_branch_partially_covered() { - // A cond line with truecount=1, falsecount=0 → 1 condition, - // true arm hit, false arm missed. - let input = br#" - - - - - - - - -"#; - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 1); - let file = &data.files[0]; - - assert_eq!(file.lines.len(), 1); - assert_eq!(file.lines[0].hit_count, 2); - - // 1 condition × 2 arms - assert_eq!(file.branches.len(), 2); - assert_eq!(file.branches[0].hit_count, 1); // true arm - assert_eq!(file.branches[1].hit_count, 0); // false arm - } - - #[test] - fn test_parse_clover_counts_are_executions_not_conditions() { - // truecount/falsecount are *execution counts* of the two - // outcomes, not a number of conditions: a hot condition with - // truecount="10" falsecount="5" is exactly two arms, both - // covered — never 20 arms with 15 covered. - let input = br#" - - - - - - - - -"#; - let data = parse(input).unwrap(); - let file = &data.files[0]; - assert_eq!(file.branches.len(), 2); - assert!(file.branches.iter().all(|b| b.hit_count == 1)); - assert_eq!( - file.branch_totals(), - crate::SpanTotals { - covered: 2, - total: 2 - } - ); - } -} diff --git a/crates/mehen-coverage/src/parsers/cobertura.rs b/crates/mehen-coverage/src/parsers/cobertura.rs deleted file mode 100644 index bef2ffbd..00000000 --- a/crates/mehen-coverage/src/parsers/cobertura.rs +++ /dev/null @@ -1,630 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) -// `src/parsers/cobertura.rs`, MIT-licensed by Scott Nelson. Local -// changes: house error type, camino paths, quick-xml 0.41 API, -// hand-rolled condition-coverage parsing (drops the regex dependency), -// normalization before emit. See LICENSE-THIRD-PARTY. - -//! Parser for Cobertura XML coverage reports. -//! -//! Cobertura XML structure: -//! ```text -//! -//! ... -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! ``` -//! -//! File paths are `` values — usually relative — -//! resolved against the first non-empty `` root when present. - -use std::collections::HashMap; -use std::io::BufRead; - -use camino::Utf8Path; -use quick_xml::events::Event; - -use super::{CoverageFormat, CoverageParser, get_attr}; -use crate::Result; -use crate::model::{BranchCoverage, FileCoverage, FunctionCoverage, LineCoverage}; - -/// Cobertura XML format parser. -pub(crate) struct CoberturaParser; - -impl CoverageParser for CoberturaParser { - fn format(&self) -> CoverageFormat { - CoverageFormat::Cobertura - } - - fn can_parse(&self, _path: &Utf8Path, content: &[u8]) -> bool { - let head = super::sniff_head(content); - super::looks_like_xml(&head) && head.contains(" Result<()>, - ) -> Result<()> { - parse_streaming(reader, emit) - } -} - -/// Parse Cobertura XML coverage data from raw bytes. -#[cfg(test)] -pub(crate) fn parse(input: &[u8]) -> Result { - let mut data = crate::CoverageData::new(); - parse_streaming(&mut &*input, &mut |file| { - data.files.push(file); - Ok(()) - })?; - Ok(data) -} - -/// Extract `(covered, total)` from a Cobertura `condition-coverage` -/// attribute like `"75% (3/4)"`. Replaces the upstream regex with a -/// hand-rolled scan so the crate carries no regex dependency. -fn parse_condition_fraction(cond: &str) -> Option<(u32, u32)> { - let open = cond.find('(')?; - let rest = &cond[open + 1..]; - let close = rest.find(')')?; - let (covered, total) = rest[..close].split_once('/')?; - Some((covered.trim().parse().ok()?, total.trim().parse().ok()?)) -} - -/// Streaming Cobertura parser — calls `emit` once per ``. -fn parse_streaming( - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, -) -> Result<()> { - let mut xml = super::xml_reader(reader); - let mut buf = Vec::new(); - - // State tracking - let mut current_file: Option = None; - let mut in_method = false; - let mut current_method_name: Option = None; - let mut method_hit: bool = false; - let mut method_start_line: Option = None; - let mut branch_indices: HashMap = HashMap::new(); - let mut line_index_map: HashMap = HashMap::new(); - - // Source prefix from elements. Text accumulates until the - // closing tag because quick-xml 0.41 splits entity references out - // of text: `/srv/a&b` arrives as - // Text("/srv/a") + GeneralRef("amp") + Text("b"). - let mut sources: Vec = Vec::new(); - let mut in_source = false; - let mut source_text = String::new(); - // Set when a contains an entity reference neither resolver - // can expand: the prefix is unusable and must be dropped whole — - // storing the partial text would silently rewrite `/repo/a&custom;b` - // into `/repo/ab` and map relative filenames to the wrong paths. - let mut source_invalid = false; - - let mut emit_normalized = |mut file: FileCoverage| { - file.normalize(); - emit(file) - }; - - loop { - let event = xml.read_event_into(&mut buf); - let is_start_event = matches!(&event, Ok(Event::Start(_))); - match event { - Err(e) => return Err(super::xml_err(e, &xml)), - Ok(Event::Eof) => break, - Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e)) => { - match e.name().as_ref() { - b"source" => { - // Only set in_source for Start events; self-closing - // (Empty) has no text content and no - // corresponding End event, so setting the flag - // would cause the next unrelated Text event to be - // captured. - if is_start_event { - in_source = true; - source_text.clear(); - source_invalid = false; - } - } - b"class" => { - if let Some(filename) = get_attr(e, b"filename") { - let path = resolve_source_path(&filename, &sources); - current_file = Some(FileCoverage::new(path)); - branch_indices.clear(); - line_index_map.clear(); - } - } - b"method" => { - in_method = true; - current_method_name = get_attr(e, b"name"); - method_hit = false; - method_start_line = None; - } - b"line" => { - if let Some(file) = current_file.as_mut() { - // Extract all needed attributes in a single pass - let mut number: Option = None; - let mut hits: u64 = 0; - let mut is_branch = false; - let mut cond_cov: Option = None; - - for attr in e.attributes().flatten() { - match attr.key.as_ref() { - b"number" => { - number = - super::attr_str(&attr).and_then(|v| v.parse().ok()); - } - b"hits" => { - hits = super::attr_str(&attr) - .and_then(|v| v.parse().ok()) - .unwrap_or(0); - } - b"branch" => { - is_branch = - super::attr_str(&attr).is_some_and(|v| v == "true"); - } - b"condition-coverage" => { - cond_cov = super::attr_str(&attr); - } - _ => {} - } - } - - if let Some(line_number) = number { - let hit_count = hits; - - // Always collect line coverage. Lines may - // appear both under and - // , or only in one of them - // depending on the generator. Deduplicate - // by keeping the max hit_count per line. - if let Some(&idx) = line_index_map.get(&line_number) { - if hit_count > file.lines[idx].hit_count { - file.lines[idx].hit_count = hit_count; - } - } else { - line_index_map.insert(line_number, file.lines.len()); - file.lines.push(LineCoverage { - line_number, - hit_count, - }); - } - - // Track method start line and hit status - if in_method { - if method_start_line.is_none() { - method_start_line = Some(line_number); - } - if hit_count > 0 { - method_hit = true; - } - } - - // Branch coverage — only process on first - // encounter of this line to avoid double- - // counting when the same line appears in - // both and blocks. - if is_branch - && !branch_indices.contains_key(&line_number) - && let Some(cond) = cond_cov.as_deref() - && let Some((covered, total)) = parse_condition_fraction(cond) - { - let total = total.min(super::MAX_BRANCHES_PER_LINE); - // Clamp to the arms actually emitted: - // a malformed fraction like - // "100% (4/2)" (or a capped total) - // must not mark every arm covered. - let covered = covered.min(total); - for i in 0..total { - // Cobertura's condition-coverage - // only says how many branches were - // taken, not per-branch execution - // counts. Use 1 for covered arms - // and 0 for uncovered. - let branch_hit: u64 = u64::from(i < covered); - let idx = branch_indices.entry(line_number).or_insert(0); - file.branches.push(BranchCoverage { - line_number, - branch_index: *idx, - hit_count: branch_hit, - }); - *idx += 1; - } - } - } - } - } - _ => {} - } - } - Ok(Event::Text(ref e)) => { - if in_source && let Ok(text) = e.decode() { - source_text.push_str(&text); - } - } - Ok(Event::GeneralRef(ref e)) => { - // Entity/character references inside content. - // Only numeric char refs and the five predefined XML - // entities resolve; custom entities are never expanded - // (no DTD processing) — an unresolvable ref makes the - // prefix unusable, so the whole source is dropped with - // its records left to suffix matching. - if in_source { - if let Ok(Some(ch)) = e.resolve_char_ref() { - source_text.push(ch); - } else if let Some(entity) = e - .decode() - .ok() - .and_then(|name| quick_xml::escape::resolve_predefined_entity(&name)) - { - source_text.push_str(entity); - } else { - source_invalid = true; - } - } - } - Ok(Event::End(ref e)) => match e.name().as_ref() { - b"source" => { - if in_source && !source_invalid && !source_text.trim().is_empty() { - sources.push(std::mem::take(&mut source_text)); - } - in_source = false; - source_invalid = false; - } - b"class" => { - if let Some(file) = current_file.take() { - emit_normalized(file)?; - } - } - b"method" if in_method => { - if let (Some(file), Some(name)) = - (current_file.as_mut(), current_method_name.take()) - { - file.functions.push(FunctionCoverage { - name, - start_line: method_start_line, - end_line: None, - hit_count: u64::from(method_hit), - }); - } - in_method = false; - method_start_line = None; - } - _ => {} - }, - _ => {} - } - buf.clear(); - } - - // Handle unclosed file - if let Some(file) = current_file.take() { - emit_normalized(file)?; - } - - Ok(()) -} - -/// Resolve a filename against the list of `` prefixes. -/// -/// - If the filename is already absolute — POSIX (`/…`), Windows -/// drive-qualified (`C:\…`, `C:/…`), or UNC (`\\server\…`) — return -/// it as-is; the path index normalizes separators later. -/// - Otherwise, prepend the first non-empty source prefix. -/// - If no non-empty sources exist, return the filename unchanged. -fn resolve_source_path(filename: &str, sources: &[String]) -> String { - if is_absolute_filename(filename) { - return filename.to_string(); - } - for source in sources { - let base = source.trim_end_matches('/'); - if !base.is_empty() { - return format!("{base}/{filename}"); - } - } - filename.to_string() -} - -/// POSIX-absolute, Windows drive-qualified, or UNC spelling. -fn is_absolute_filename(filename: &str) -> bool { - if filename.starts_with('/') || filename.starts_with("\\\\") { - return true; - } - let bytes = filename.as_bytes(); - bytes.len() >= 3 - && bytes[0].is_ascii_alphabetic() - && bytes[1] == b':' - && matches!(bytes[2], b'/' | b'\\') -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_cobertura() { - let input = include_bytes!("../../tests/fixtures/sample_cobertura.xml"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 2); - - let main = &data.files[0]; - assert_eq!(main.path, "/home/user/project/src/main.py"); - assert_eq!(main.lines.len(), 8); - assert_eq!(main.lines[0].line_number, 1); - assert_eq!(main.lines[0].hit_count, 1); - assert_eq!(main.lines[2].line_number, 3); - assert_eq!(main.lines[2].hit_count, 0); - - // Branch on line 8: 50% (1/2) → 2 branch arms, one hit one miss - assert_eq!(main.branches.len(), 2); - assert_eq!(main.branches[0].line_number, 8); - assert_eq!(main.branches[0].hit_count, 1); // covered arm - assert_eq!(main.branches[1].hit_count, 0); // uncovered arm - - // One method extracted - assert_eq!(main.functions.len(), 1); - assert_eq!(main.functions[0].name, "do_stuff"); - assert_eq!(main.functions[0].start_line, Some(5)); - assert_eq!(main.functions[0].hit_count, 1); - - let util = &data.files[1]; - assert_eq!(util.path, "/home/user/project/src/util.py"); - assert_eq!(util.lines.len(), 2); - assert_eq!(util.branches.len(), 0); - } - - #[test] - fn test_parse_utplsql_real_report() { - // Real utPLSQL 3.1.6 output (see the fixture's provenance comment). - // Pins how a genuine SQL coverage report maps: the line dimension is - // fully populated while branches and functions are absent — utPLSQL - // emits `branch="false"` on every line and no elements, so - // downstream coverage.branch/coverage.function must stay unpublished - // (absent, not zero) for these files. - let input = include_bytes!("../../tests/fixtures/cobertura_utplsql.xml"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 5); - - // utPLSQL abuses as a list of DB unit names rather than - // filesystem roots, and its filenames are `schema.unit` identifiers - // (not paths), so the first "source" is prepended to every record. - // The spellings never match repository files — real-world mapping - // requires utPLSQL-cli's -source_path file mapping. This documents - // (not endorses) the raw shape. - let expected: [(&str, usize, u64); 5] = [ - ("s205031.betwnstr/s205031.betwnstr", 4, 4), - ("s205031.betwnstr/s205031.load_from_tab", 13, 0), - ("s205031.betwnstr/s205031.minimal_view", 13, 0), - ("s205031.betwnstr/s205031.pk_glb0_mail", 1174, 0), - ("s205031.betwnstr/s205031.pk_tst0_instrumentation", 29, 0), - ]; - for (file, (path, lines, covered)) in data.files.iter().zip(expected) { - assert_eq!(file.path, path); - assert_eq!(file.lines.len(), lines, "{path}: listed lines"); - assert_eq!( - file.lines.iter().filter(|l| l.hit_count > 0).count() as u64, - covered, - "{path}: covered lines", - ); - assert!(file.branches.is_empty(), "{path}: no branch dimension"); - assert!(file.functions.is_empty(), "{path}: no function dimension"); - } - - // Cross-check against the report's own totals - // (lines-valid="1233" lines-covered="4"). - let total: usize = data.files.iter().map(|f| f.lines.len()).sum(); - assert_eq!(total, 1233); - - // DBMS_PLSQL_CODE_COVERAGE line numbers are unit-source-relative; - // BETWNSTR's executable lines and hit counts arrive verbatim. - let betwnstr = &data.files[0]; - let got: Vec<(u32, u64)> = betwnstr - .lines - .iter() - .map(|l| (l.line_number, l.hit_count)) - .collect(); - assert_eq!(got, [(2, 5), (4, 5), (5, 3), (7, 5)]); - } - - #[test] - fn test_parse_cobertura_branch_dedup() { - // Branch line appears in both and . - // We must not double-count the branch arms. - let input = include_bytes!("../../tests/fixtures/cobertura_branch_in_method_and_class.xml"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 1); - let file = &data.files[0]; - - // Lines should be deduplicated: 4 unique lines, not 7 - assert_eq!(file.lines.len(), 4); - - // Branch on line 3: 50% (1/2) → exactly 2 arms, not 4 - assert_eq!(file.branches.len(), 2); - assert_eq!(file.branches[0].line_number, 3); - assert_eq!(file.branches[0].branch_index, 0); - assert_eq!(file.branches[0].hit_count, 1); // covered arm - assert_eq!(file.branches[1].line_number, 3); - assert_eq!(file.branches[1].branch_index, 1); - assert_eq!(file.branches[1].hit_count, 0); // uncovered arm - } - - #[test] - fn test_parse_cobertura_multiple_sources() { - // First is empty, second is the real prefix. - let input = include_bytes!("../../tests/fixtures/cobertura_multiple_sources.xml"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 1); - // Should use the first non-empty source as prefix, not the empty - // one. - assert_eq!(data.files[0].path, "/home/user/project/src/app.py"); - } - - #[test] - fn test_parse_cobertura_no_sources() { - let input = include_bytes!("../../tests/fixtures/cobertura_no_sources.xml"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 1); - assert_eq!(data.files[0].path, "src/f.rs"); - } - - #[test] - fn test_parse_cobertura_empty() { - // A valid Cobertura file with no classes should produce empty - // CoverageData. - let input = include_bytes!("../../tests/fixtures/empty_cobertura.xml"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 0); - } - - #[test] - fn test_parse_cobertura_malformed() { - // Malformed XML should produce a meaningful error with position - // info. - let input = include_bytes!("../../tests/fixtures/malformed_cobertura.xml"); - let result = parse(input); - assert!(result.is_err()); - let err_msg = format!("{}", result.unwrap_err()); - assert!( - err_msg.contains("position"), - "Error should contain position info: {err_msg}", - ); - } - - #[test] - fn test_parse_condition_fraction() { - assert_eq!(parse_condition_fraction("75% (3/4)"), Some((3, 4))); - assert_eq!(parse_condition_fraction("50% (1/2)"), Some((1, 2))); - assert_eq!(parse_condition_fraction("100%"), None); - assert_eq!(parse_condition_fraction("(x/y)"), None); - assert_eq!(parse_condition_fraction(""), None); - } - - #[test] - fn test_malformed_condition_fraction_cannot_exceed_arm_count() { - // A generator writing covered > total ("100% (4/2)") must not - // report more covered arms than emitted arms — coverage.branch - // backs CI gates, so an uncapped count would mask a failure. - let input = br#" - - - - - - -"#; - let data = parse(input).unwrap(); - let file = &data.files[0]; - assert_eq!(file.branches.len(), 2); - assert!(file.branches.iter().all(|b| b.hit_count == 1)); - } - - #[test] - fn test_source_with_unresolvable_entity_is_dropped_whole() { - // A custom entity never expands (no DTD processing). Keeping - // the partial text would rewrite `/repo/a&custom;b` into - // `/repo/ab` and prefix filenames with a path that never - // existed — the whole must be dropped instead, letting - // the next usable source (or none) apply. - let input = br#" -]> - - /repo/a&custom;b/srv/work - - - - - -"#; - let data = parse(input).unwrap(); - assert_eq!(data.files[0].path, "/srv/work/src/f.py"); - } - - #[test] - fn test_source_with_entity_reference_is_complete() { - // quick-xml splits `&` out of text content; the - // accumulator must reassemble the full prefix. - let input = br#" - - /srv/a&b - - - - - -"#; - let data = parse(input).unwrap(); - assert_eq!(data.files[0].path, "/srv/a&b/src/f.py"); - } - - #[test] - fn test_windows_absolute_filenames_are_preserved() { - // Drive-qualified and UNC filenames must not receive a - // prefix; the path index normalizes separators later. - for absolute in [ - r"C:\proj\src\a.cs", - "C:/proj/src/a.cs", - r"\\server\share\a.cs", - ] { - assert_eq!( - resolve_source_path(absolute, &["/ignored".to_string()]), - absolute, - "{absolute} must stay as spelled" - ); - } - // POSIX-relative still receives the prefix. - assert_eq!( - resolve_source_path("src/a.cs", &["/root".to_string()]), - "/root/src/a.cs" - ); - } - - #[test] - fn dtd_is_inert_by_construction() { - // quick-xml never resolves DTDs or expands custom entities: a - // billion-laughs preamble parses as an inert DocType event and - // the entity reference stays unexpanded (attribute unescape - // fails → attribute skipped) instead of exploding memory. This - // pins the security assumption the discovery pipeline relies on - // when sniffing untrusted artifacts. - let input = br#" - - - -]> - - /src - - - - - -"#; - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 1); - assert_eq!(data.files[0].lines.len(), 1); - } -} diff --git a/crates/mehen-coverage/src/parsers/gocover.rs b/crates/mehen-coverage/src/parsers/gocover.rs deleted file mode 100644 index f28e5794..00000000 --- a/crates/mehen-coverage/src/parsers/gocover.rs +++ /dev/null @@ -1,395 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) -// `src/parsers/gocover.rs`, MIT-licensed by Scott Nelson. Local changes: -// house error type, camino paths, normalization before emit. -// See LICENSE-THIRD-PARTY. - -//! Parser for Go's `-coverprofile` format. -//! -//! Reference: -//! -//! ```text -//! mode: set|count|atomic -//! :.,. -//! ``` -//! -//! Each line describes a basic block (a range of source lines) with the -//! number of statements in the block and how many times it was executed. -//! Since mehen tracks per-line coverage, each block expands into -//! individual line entries, assigning the block's hit count to every line -//! in the range. Note the `` component is a *module import path* -//! (`github.com/org/repo/pkg/file.go`), not a filesystem path — the -//! suffix matcher in [`crate::CoverageIndex`] absorbs the module prefix. - -use std::collections::HashMap; -use std::io::BufRead; - -use camino::Utf8Path; - -use super::{CoverageFormat, CoverageParser}; -use crate::Result; -use crate::model::{FileCoverage, LineCoverage}; - -/// Go coverage profile parser. -pub(crate) struct GocoverParser; - -impl CoverageParser for GocoverParser { - fn format(&self) -> CoverageFormat { - CoverageFormat::Gocover - } - - fn can_parse(&self, path: &Utf8Path, content: &[u8]) -> bool { - // Extension-based: .coverprofile or .gocov - if let Some(ext) = path.extension() { - let ext = ext.to_lowercase(); - if ext == "coverprofile" || ext == "gocov" { - return true; - } - } - - // Content-based: first line starts with "mode: ", or any line - // matches the block pattern (file.go:N.N,N.N N N). The fallback - // catches profiles without a mode header (rare, but possible from - // merging tools). - let head = super::sniff_head(content); - if let Some(first) = head.lines().next() - && first.starts_with("mode: ") - { - return true; - } - - head.lines().any(looks_like_go_block) - } - - fn parse_streaming( - &self, - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, - ) -> Result<()> { - parse_streaming_reader(reader, emit) - } -} - -/// Parse a Go coverage profile from raw bytes. -#[cfg(test)] -pub(crate) fn parse(input: &[u8]) -> Result { - let mut data = crate::CoverageData::new(); - parse_streaming_reader(&mut &*input, &mut |file| { - data.files.push(file); - Ok(()) - })?; - Ok(data) -} - -/// A parsed block from a single line of the coverage profile. -struct Block { - start_line: u32, - end_line: u32, - /// Column of the block's exclusive end position. When the end - /// position sits at column 1, the block ends *before* `end_line`'s - /// first character and that line is not part of the block. - end_col: u32, - count: u64, -} - -/// Quick heuristic: does this line look like a Go coverage block? -/// e.g. "github.com/user/repo/file.go:10.1,20.5 3 1" -fn looks_like_go_block(line: &str) -> bool { - let Some(colon_pos) = line.rfind(".go:") else { - return false; - }; - let after = &line[colon_pos + 4..]; - after.contains(',') && after.split_whitespace().count() >= 2 -} - -/// Maximum number of lines a single block can span. Anything larger is -/// almost certainly malformed input and expanding it would consume -/// excessive memory. -const MAX_BLOCK_LINE_SPAN: u32 = 100_000; - -/// Parse a single block line, returning (file_path, Block). -/// -/// Format: `:.,. ` -fn parse_block_line(line: &str) -> Option<(&str, Block)> { - // Anchor on the last ".go:" to split the file path from the block - // range. This naturally handles paths containing colons. - let colon_pos = line.rfind(".go:")? + 3; // position of ':' - - let file = &line[..colon_pos]; - let rest = &line[colon_pos + 1..]; - - // rest = "startLine.startCol,endLine.endCol numStmt count" - let (range, tail) = rest.split_once(' ')?; - let (start, end) = range.split_once(',')?; - - let start_line: u32 = start.split_once('.')?.0.parse().ok()?; - let (end_line_str, end_col_str) = end.split_once('.')?; - let end_line: u32 = end_line_str.parse().ok()?; - let end_col: u32 = end_col_str.parse().ok()?; - - // Reject blocks with an invalid range or an absurdly large span that - // would cause excessive memory allocation when expanded per-line. - if end_line < start_line || (end_line - start_line) > MAX_BLOCK_LINE_SPAN { - return None; - } - - let mut parts = tail.split_whitespace(); - let _num_stmt = parts.next()?; - let count: u64 = parts.next()?.parse().ok()?; - - Some(( - file, - Block { - start_line, - end_line, - end_col, - count, - }, - )) -} - -/// Streaming Go coverage parser. Collects all blocks per file, then -/// expands them into per-line coverage and emits once per source file. -fn parse_streaming_reader( - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, -) -> Result<()> { - // Collect blocks grouped by file path, preserving insertion order. - let mut file_order: Vec = Vec::new(); - let mut file_blocks: HashMap> = HashMap::new(); - - let mut raw_line = String::new(); - let mut line_number: u64 = 0; - loop { - raw_line.clear(); - let n = reader.read_line(&mut raw_line)?; - if n == 0 { - break; - } - line_number += 1; - - let line = raw_line.trim(); - if line.is_empty() || line.starts_with("mode:") { - continue; - } - - // A non-header line that is not a valid block record means the - // input is not (or is no longer) a Go coverage profile — - // silently dropping it would report misleadingly complete - // coverage from a corrupt report. - let Some((file, block)) = parse_block_line(line) else { - return Err(crate::CoverageError::Malformed(format!( - "malformed Go coverage block at line {line_number}: {line}" - ))); - }; - let file_str = file.to_string(); - if !file_blocks.contains_key(&file_str) { - file_order.push(file_str.clone()); - } - file_blocks.entry(file_str).or_default().push(block); - } - - // Emit one FileCoverage per source file. - for file_path in file_order { - if let Some(blocks) = file_blocks.remove(&file_path) { - let file_cov = blocks_to_file_coverage(file_path, &blocks); - emit(file_cov)?; - } - } - - Ok(()) -} - -/// Convert a list of blocks for one file into a `FileCoverage`. -/// -/// Go coverage blocks describe ranges of lines. Multiple blocks may -/// overlap or cover the same line. We take the maximum hit count for -/// each line across all blocks that touch it. -fn blocks_to_file_coverage(path: String, blocks: &[Block]) -> FileCoverage { - let mut line_hits: HashMap = HashMap::new(); - - for block in blocks { - // Block positions are start-inclusive with an *exclusive* end - // offset. An end column of 1 means the block ends before the - // end line's first character — that line carries none of the - // block's statements and must not inherit its count. - let last_line = if block.end_col == 1 && block.end_line > block.start_line { - block.end_line - 1 - } else { - block.end_line - }; - for line_num in block.start_line..=last_line { - let entry = line_hits.entry(line_num).or_insert(0); - if block.count > *entry { - *entry = block.count; - } - } - } - - let mut file = FileCoverage::new(path); - file.lines = line_hits - .into_iter() - .map(|(line_number, hit_count)| LineCoverage { - line_number, - hit_count, - }) - .collect(); - file.normalize(); - file -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_gocover() { - let input = include_bytes!("../../tests/fixtures/sample.gocov"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 2); - - let main = &data.files[0]; - assert_eq!(main.path, "github.com/user/project/main.go"); - // Lines 10-12 (count 5) + lines 14-16 (count 0) = 6 lines - assert_eq!(main.lines.len(), 6); - assert_eq!(main.lines[0].line_number, 10); - assert_eq!(main.lines[0].hit_count, 5); - assert_eq!(main.lines[2].line_number, 12); - assert_eq!(main.lines[2].hit_count, 5); - // Line 14 has count 0 - assert_eq!(main.lines[3].line_number, 14); - assert_eq!(main.lines[3].hit_count, 0); - - let util = &data.files[1]; - assert_eq!(util.path, "github.com/user/project/util.go"); - assert_eq!(util.lines.len(), 3); - assert_eq!(util.lines[0].hit_count, 3); - } - - #[test] - fn test_parse_gocover_overlapping_blocks() { - // When two blocks overlap on the same line, we take the max hit count. - let input = b"mode: count\n\ - example.com/pkg/f.go:5.1,10.10 3 2\n\ - example.com/pkg/f.go:8.1,12.10 2 7\n"; - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 1); - let file = &data.files[0]; - - // Lines 5-7 from first block only: count 2 - // Lines 8-10 overlap: max(2, 7) = 7 - // Lines 11-12 from second block only: count 7 - assert_eq!(file.lines.len(), 8); // lines 5..=12 - let line5 = file.lines.iter().find(|l| l.line_number == 5).unwrap(); - assert_eq!(line5.hit_count, 2); - let line8 = file.lines.iter().find(|l| l.line_number == 8).unwrap(); - assert_eq!(line8.hit_count, 7); - let line10 = file.lines.iter().find(|l| l.line_number == 10).unwrap(); - assert_eq!(line10.hit_count, 7); - let line12 = file.lines.iter().find(|l| l.line_number == 12).unwrap(); - assert_eq!(line12.hit_count, 7); - } - - #[test] - fn test_parse_gocover_empty() { - let input = include_bytes!("../../tests/fixtures/empty.gocov"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 0); - } - - #[test] - fn test_parse_gocover_no_mode_header() { - // Some merge tools produce profiles without a mode line. - let input = b"example.com/pkg/f.go:1.1,5.10 2 3\n"; - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 1); - assert_eq!(data.files[0].lines.len(), 5); - assert_eq!(data.files[0].lines[0].hit_count, 3); - } - - #[test] - fn test_end_column_one_excludes_the_end_line() { - // Block positions carry an exclusive end offset: `1.1,3.1` ends - // *before* line 3's first character, so only lines 1 and 2 - // belong to the block. - let input = b"mode: set\nexample.com/pkg/f.go:1.1,3.1 1 1\n"; - let data = parse(input).unwrap(); - let lines: Vec = data.files[0].lines.iter().map(|l| l.line_number).collect(); - assert_eq!(lines, vec![1, 2]); - - // A degenerate single-line block at column 1 still keeps its - // one line rather than vanishing. - let input = b"mode: set\nexample.com/pkg/f.go:7.1,7.1 1 1\n"; - let data = parse(input).unwrap(); - let lines: Vec = data.files[0].lines.iter().map(|l| l.line_number).collect(); - assert_eq!(lines, vec![7]); - } - - #[test] - fn test_malformed_block_line_is_an_error() { - // A non-header line that is not a block record must fail the - // parse — silently dropping it would report misleadingly - // complete coverage from a corrupt report. - let input = b"mode: count\nnot a profile\n"; - let err = parse(input).unwrap_err().to_string(); - assert!(err.contains("line 2"), "unexpected error: {err}"); - - // A record with a corrupted range is equally fatal. - let input = b"mode: count\nexample.com/pkg/f.go:9.1,3.1 1 1\n"; - assert!(parse(input).is_err()); - } - - #[test] - fn test_parse_gocover_set_mode() { - // In "set" mode, count is 0 or 1. - let input = b"mode: set\n\ - example.com/pkg/f.go:1.1,3.10 2 1\n\ - example.com/pkg/f.go:5.1,6.10 1 0\n"; - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 1); - let file = &data.files[0]; - assert_eq!(file.lines.len(), 5); - assert_eq!(file.lines[0].hit_count, 1); // line 1 - assert_eq!(file.lines[3].hit_count, 0); // line 5 - } - - #[test] - fn test_looks_like_go_block() { - assert!(looks_like_go_block( - "github.com/user/repo/file.go:10.1,20.5 3 1" - )); - assert!(!looks_like_go_block("mode: count")); - assert!(!looks_like_go_block("SF:/src/lib.rs")); - assert!(!looks_like_go_block("")); - } - - #[test] - fn test_parse_block_line() { - let (file, block) = parse_block_line("github.com/user/repo/file.go:10.1,20.5 3 1").unwrap(); - assert_eq!(file, "github.com/user/repo/file.go"); - assert_eq!(block.start_line, 10); - assert_eq!(block.end_line, 20); - assert_eq!(block.count, 1); - } - - #[test] - fn test_can_parse_by_extension() { - let parser = GocoverParser; - assert!(parser.can_parse(Utf8Path::new("coverage.coverprofile"), b"")); - assert!(parser.can_parse(Utf8Path::new("coverage.gocov"), b"")); - assert!(!parser.can_parse(Utf8Path::new("coverage.txt"), b"")); - } - - #[test] - fn test_can_parse_by_content() { - let parser = GocoverParser; - assert!(parser.can_parse(Utf8Path::new("coverage.out"), b"mode: count\n")); - assert!(parser.can_parse(Utf8Path::new("coverage.out"), b"mode: set\n")); - assert!(parser.can_parse(Utf8Path::new("coverage.out"), b"mode: atomic\n")); - assert!(!parser.can_parse(Utf8Path::new("coverage.out"), b"random data\n")); - } -} diff --git a/crates/mehen-coverage/src/parsers/istanbul.rs b/crates/mehen-coverage/src/parsers/istanbul.rs deleted file mode 100644 index 5ebe9419..00000000 --- a/crates/mehen-coverage/src/parsers/istanbul.rs +++ /dev/null @@ -1,486 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) -// `src/parsers/istanbul.rs`, MIT-licensed by Scott Nelson. Local changes: -// house error type, camino paths, normalization before emit. -// See LICENSE-THIRD-PARTY. - -//! Parser for Istanbul / NYC `coverage-final.json` format. -//! -//! Reference: -//! -//! The format is a JSON object keyed by file path. Each value contains: -//! - `statementMap`: `{ "0": { "start": { "line": 1, "column": 0 }, "end": {…} }, … }` -//! - `s`: `{ "0": 5, "1": 0, … }` — hit counts per statement -//! - `branchMap`: `{ "0": { "loc": …, "type": "if", "locations": […] }, … }` -//! - `b`: `{ "0": [5, 0], … }` — hit counts per branch arm -//! - `fnMap`: `{ "0": { "name": "foo", "decl": …, "loc": … }, … }` -//! - `f`: `{ "0": 3, … }` — hit counts per function - -use std::collections::HashMap; -use std::io::BufRead; - -use camino::Utf8Path; -use serde_json::Value; - -use super::{CoverageFormat, CoverageParser}; -use crate::model::{BranchCoverage, FileCoverage, FunctionCoverage, LineCoverage}; -use crate::{CoverageError, Result}; - -/// Istanbul / NYC JSON parser. -pub(crate) struct IstanbulParser; - -impl CoverageParser for IstanbulParser { - fn format(&self) -> CoverageFormat { - CoverageFormat::Istanbul - } - - fn can_parse(&self, path: &Utf8Path, content: &[u8]) -> bool { - // Filename-based: the canonical Istanbul output filename. - if let Some(name) = path.file_name() - && name.eq_ignore_ascii_case("coverage-final.json") - { - return true; - } - - // Content-based: JSON object whose head contains Istanbul markers. - let head = super::sniff_head(content); - looks_like_istanbul(&head) - } - - fn parse_streaming( - &self, - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, - ) -> Result<()> { - parse_streaming_reader(reader, emit) - } -} - -/// Parse Istanbul JSON from raw bytes. -#[cfg(test)] -pub(crate) fn parse(input: &[u8]) -> Result { - let mut data = crate::CoverageData::new(); - parse_streaming_reader(&mut &*input, &mut |file| { - data.files.push(file); - Ok(()) - })?; - Ok(data) -} - -/// Content-based detection: a JSON object where the visible head -/// contains `"statementMap"` and `"fnMap"`. -fn looks_like_istanbul(head: &str) -> bool { - let trimmed = head.trim(); - // Must start with '{' (JSON object) - if !trimmed.starts_with('{') { - return false; - } - // Look for Istanbul-specific keys - trimmed.contains("\"statementMap\"") && trimmed.contains("\"fnMap\"") -} - -/// Streaming parser — deserializes the top-level JSON object entry by -/// entry using a serde `MapAccess` visitor so only one file entry is in -/// memory at a time. -fn parse_streaming_reader( - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, -) -> Result<()> { - // Consume leading whitespace across buffer refills: `fill_buf` - // exposes only the current buffer, and a buffer that happens to be - // whitespace-only can still be followed by valid JSON. - loop { - let buf = reader.fill_buf()?; - if buf.is_empty() { - return Ok(()); // empty / whitespace-only input - } - let ws = buf.iter().take_while(|b| b.is_ascii_whitespace()).count(); - let all_ws = ws == buf.len(); - reader.consume(ws); - if !all_ws { - break; - } - } - - let mut deser = serde_json::Deserializer::from_reader(reader); - - // Walk the top-level object key by key, converting each value into a - // FileCoverage before moving on. `emit` failures are captured so the - // original error survives the serde error round-trip. - let mut emit_err: Option = None; - let visitor = IstanbulVisitor { - emit: &mut |fc| { - emit(fc).map_err(|e| { - let msg = e.to_string(); - emit_err = Some(e); - serde::de::Error::custom(msg) - }) - }, - }; - match serde::Deserializer::deserialize_map(&mut deser, visitor) { - Ok(()) => { - if let Some(e) = emit_err { - return Err(e); - } - // Reject trailing non-whitespace bytes: `deserialize_map` - // stops at the closing brace, and `{}garbage` must not - // parse as a clean empty report. - deser.end().map_err(|e| { - CoverageError::Malformed(format!("trailing data after Istanbul JSON object: {e}")) - }) - } - Err(e) => { - // If the error originated from `emit`, return the original. - if let Some(original) = emit_err { - return Err(original); - } - Err(CoverageError::Malformed(format!( - "invalid JSON in Istanbul report: {e}" - ))) - } - } -} - -/// Serde visitor that iterates over the top-level `{ path: entry }` map, -/// deserializing one `Value` per entry and emitting a `FileCoverage`. -struct IstanbulVisitor<'a> { - emit: &'a mut dyn FnMut(FileCoverage) -> std::result::Result<(), serde_json::Error>, -} - -impl<'de> serde::de::Visitor<'de> for IstanbulVisitor<'_> { - type Value = (); - - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("an Istanbul JSON object") - } - - fn visit_map(self, mut map: A) -> std::result::Result<(), A::Error> - where - A: serde::de::MapAccess<'de>, - { - while let Some(file_path) = map.next_key::()? { - let entry: Value = map.next_value()?; - let file_cov = parse_file_entry(&file_path, &entry); - (self.emit)(file_cov).map_err(serde::de::Error::custom)?; - } - Ok(()) - } -} - -/// Parse a single file entry from the Istanbul JSON. -fn parse_file_entry(file_path: &str, entry: &Value) -> FileCoverage { - let mut file = FileCoverage::new(file_path.to_string()); - - parse_statements(entry, &mut file); - parse_branches(entry, &mut file); - parse_functions(entry, &mut file); - - file.normalize(); - file -} - -/// Extract per-line coverage from `statementMap` + `s`. -/// -/// `statementMap` maps string indices to `{ start: { line, column }, end: {…} }`. -/// `s` maps the same indices to hit counts. -/// -/// Multiple statements can map to the same line; we take the maximum -/// hit count for each line. -fn parse_statements(entry: &Value, file: &mut FileCoverage) { - let Some(stmt_map) = entry.get("statementMap").and_then(|v| v.as_object()) else { - return; - }; - let Some(s) = entry.get("s").and_then(|v| v.as_object()) else { - return; - }; - - let mut line_hits: HashMap = HashMap::new(); - - for (idx, loc) in stmt_map { - let line = match loc - .get("start") - .and_then(|start| start.get("line")) - .and_then(|l| l.as_u64()) - { - Some(l) => l as u32, - None => continue, - }; - - let count = s.get(idx.as_str()).and_then(|v| v.as_u64()).unwrap_or(0); - - line_hits - .entry(line) - .and_modify(|e| *e = (*e).max(count)) - .or_insert(count); - } - - for (line_number, hit_count) in line_hits { - file.lines.push(LineCoverage { - line_number, - hit_count, - }); - } -} - -/// Extract branch coverage from `branchMap` + `b`. -/// -/// `branchMap` maps string indices to `{ type, locations: [{ start: { line } }, …] }`. -/// `b` maps the same indices to arrays of hit counts (one per branch arm). -fn parse_branches(entry: &Value, file: &mut FileCoverage) { - let Some(branch_map) = entry.get("branchMap").and_then(|v| v.as_object()) else { - return; - }; - let Some(b) = entry.get("b").and_then(|v| v.as_object()) else { - return; - }; - - // Track branch indices per line to assign sequential indices. - let mut line_branch_idx: HashMap = HashMap::new(); - - for (idx, branch_info) in branch_map { - // Get the line number from the branch location (use the top-level - // `loc.start.line` if available, otherwise the first location). - let line = branch_info - .get("loc") - .and_then(|loc| loc.get("start")) - .and_then(|start| start.get("line")) - .and_then(|l| l.as_u64()) - .or_else(|| { - branch_info - .get("locations") - .and_then(|locs| locs.as_array()) - .and_then(|arr| arr.first()) - .and_then(|loc| loc.get("start")) - .and_then(|start| start.get("line")) - .and_then(|l| l.as_u64()) - }); - - let line = match line { - Some(l) => l as u32, - None => continue, - }; - - let Some(counts) = b.get(idx.as_str()).and_then(|v| v.as_array()) else { - continue; - }; - - // The arm cap is per source *line*, and several branchMap - // entries can resolve to one line — budget from the arms - // already assigned to that line, not per entry. - let branch_index = line_branch_idx.entry(line).or_insert(0); - let remaining = super::MAX_BRANCHES_PER_LINE.saturating_sub(*branch_index) as usize; - for count_val in counts.iter().take(remaining) { - let hit_count = count_val.as_u64().unwrap_or(0); - file.branches.push(BranchCoverage { - line_number: line, - branch_index: *branch_index, - hit_count, - }); - *branch_index += 1; - } - } -} - -/// Extract function coverage from `fnMap` + `f`. -/// -/// `fnMap` maps string indices to `{ name, decl: { start: { line } }, loc: {…} }`. -/// `f` maps the same indices to hit counts. -fn parse_functions(entry: &Value, file: &mut FileCoverage) { - let Some(fn_map) = entry.get("fnMap").and_then(|v| v.as_object()) else { - return; - }; - let Some(f) = entry.get("f").and_then(|v| v.as_object()) else { - return; - }; - - for (idx, fn_info) in fn_map { - let name = fn_info - .get("name") - .and_then(|n| n.as_str()) - .unwrap_or("(anonymous)") - .to_string(); - - // `decl.start.line` is the declaration line; `loc` is the body. - let start_line = fn_info - .get("decl") - .or_else(|| fn_info.get("loc")) - .and_then(|loc| loc.get("start")) - .and_then(|start| start.get("line")) - .and_then(|l| l.as_u64()) - .map(|l| l as u32); - - let end_line = fn_info - .get("loc") - .and_then(|loc| loc.get("end")) - .and_then(|end| end.get("line")) - .and_then(|l| l.as_u64()) - .map(|l| l as u32); - - let hit_count = f.get(idx.as_str()).and_then(|v| v.as_u64()).unwrap_or(0); - - file.functions.push(FunctionCoverage { - name, - start_line, - end_line, - hit_count, - }); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_istanbul() { - let input = include_bytes!("../../tests/fixtures/sample_istanbul.json"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 2); - - let lib = data - .files - .iter() - .find(|f| f.path.ends_with("lib.js")) - .unwrap(); - assert_eq!(lib.lines.len(), 5); - // Lines should be sorted - assert_eq!(lib.lines[0].line_number, 1); - assert_eq!(lib.lines[0].hit_count, 5); - assert_eq!(lib.lines[2].line_number, 3); - assert_eq!(lib.lines[2].hit_count, 0); - - assert_eq!(lib.branches.len(), 2); - assert_eq!(lib.branches[0].hit_count + lib.branches[1].hit_count, 5); // one arm hit, one not - - assert_eq!(lib.functions.len(), 2); - let main_fn = lib.functions.iter().find(|f| f.name == "main").unwrap(); - assert_eq!(main_fn.hit_count, 5); - assert_eq!(main_fn.start_line, Some(1)); - - let util = data - .files - .iter() - .find(|f| f.path.ends_with("util.js")) - .unwrap(); - assert_eq!(util.lines.len(), 2); - assert_eq!(util.branches.len(), 0); - assert_eq!(util.functions.len(), 0); - } - - #[test] - fn test_parse_istanbul_empty_object() { - let input = b"{}"; - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 0); - } - - #[test] - fn test_parse_istanbul_empty_file() { - let input = include_bytes!("../../tests/fixtures/empty_istanbul.json"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 0); - } - - #[test] - fn test_parse_istanbul_multiple_statements_same_line() { - // Two statements on the same line — take the max hit count. - let input = r#"{ - "/src/app.js": { - "statementMap": { - "0": { "start": { "line": 1, "column": 0 }, "end": { "line": 1, "column": 10 } }, - "1": { "start": { "line": 1, "column": 12 }, "end": { "line": 1, "column": 20 } } - }, - "s": { "0": 3, "1": 7 }, - "branchMap": {}, - "b": {}, - "fnMap": {}, - "f": {} - } - }"#; - let data = parse(input.as_bytes()).unwrap(); - assert_eq!(data.files.len(), 1); - assert_eq!(data.files[0].lines.len(), 1); - assert_eq!(data.files[0].lines[0].hit_count, 7); // max(3, 7) - } - - #[test] - fn test_parse_istanbul_malformed() { - let result = parse(br#"{ "/src/app.js": { "statementMap": "#); - let err = result.unwrap_err().to_string(); - assert!(err.contains("Istanbul"), "unexpected error: {err}"); - } - - #[test] - fn test_trailing_garbage_is_rejected() { - let err = parse(b"{} not json").unwrap_err().to_string(); - assert!(err.contains("trailing"), "unexpected error: {err}"); - // Trailing whitespace stays fine. - assert!(parse(b"{} \n").is_ok()); - } - - #[test] - fn test_leading_whitespace_larger_than_one_buffer() { - // A whitespace run longer than any single fill_buf window must - // not read as an empty report. - let mut input = vec![b' '; 64 * 1024]; - input.extend_from_slice( - br#"{"/src/app.js": {"statementMap": {"0": {"start": {"line": 1}}}, "s": {"0": 1}, "fnMap": {}, "f": {}}}"#, - ); - let data = parse(&input).unwrap(); - assert_eq!(data.files.len(), 1); - } - - #[test] - fn test_branch_cap_is_per_line_across_entries() { - // Several branchMap entries resolving to one line share that - // line's arm budget. - let mut entries = String::new(); - let mut counts = String::new(); - let per_entry = 300; // 4 entries × 300 arms = 1200 > 1024 cap - for i in 0..4 { - if i > 0 { - entries.push(','); - counts.push(','); - } - let arms = (0..per_entry).map(|_| "1").collect::>().join(","); - entries.push_str(&format!( - r#""{i}": {{ "loc": {{ "start": {{ "line": 9 }} }} }}"# - )); - counts.push_str(&format!(r#""{i}": [{arms}]"#)); - } - let input = format!( - r#"{{"/src/big.js": {{"statementMap": {{}}, "s": {{}}, "branchMap": {{{entries}}}, "b": {{{counts}}}, "fnMap": {{}}, "f": {{}}}}}}"# - ); - let data = parse(input.as_bytes()).unwrap(); - assert_eq!( - data.files[0].branches.len(), - super::super::MAX_BRANCHES_PER_LINE as usize - ); - } - - #[test] - fn test_looks_like_istanbul() { - assert!(looks_like_istanbul( - r#"{ "/src/lib.js": { "statementMap": {}, "fnMap": {} } }"# - )); - assert!(!looks_like_istanbul(r#""#)); - assert!(!looks_like_istanbul(r"SF:/src/lib.rs")); - assert!(!looks_like_istanbul(r#"{ "unrelated": true }"#)); - // "s" alone is too generic — require "fnMap" - assert!(!looks_like_istanbul( - r#"{ "statementMap": "x", "s": true }"# - )); - } - - #[test] - fn test_can_parse_by_filename() { - let parser = IstanbulParser; - assert!(parser.can_parse(Utf8Path::new("coverage-final.json"), b"")); - assert!(parser.can_parse(Utf8Path::new("dir/coverage-final.json"), b"")); - assert!(!parser.can_parse(Utf8Path::new("coverage.json"), b"")); - assert!(!parser.can_parse(Utf8Path::new("data.json"), b"")); - } -} diff --git a/crates/mehen-coverage/src/parsers/jacoco.rs b/crates/mehen-coverage/src/parsers/jacoco.rs deleted file mode 100644 index 4ff619f7..00000000 --- a/crates/mehen-coverage/src/parsers/jacoco.rs +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) -// `src/parsers/jacoco.rs`, MIT-licensed by Scott Nelson. Local changes: -// house error type, camino paths, quick-xml 0.41 API, normalization -// before emit. See LICENSE-THIRD-PARTY. - -//! Parser for JaCoCo XML coverage reports. -//! -//! JaCoCo XML structure: -//! ```text -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! -//! ``` -//! -//! Key differences from Cobertura: -//! - Line-level data lives inside `` elements, not ``. -//! - Each `` has `nr` (line number), `mi`/`ci` (missed/covered -//! instructions), and `mb`/`cb` (missed/covered branches). -//! - There is no per-line `hits` attribute; hit status derives from -//! whether `ci > 0`. -//! - Method coverage comes from `` elements inside ``. -//! - Paths are `package name + source filename` — *Java package* paths -//! (`com/example/Foo.java`), missing any `src/main/java/` prefix; the -//! suffix matcher in [`crate::CoverageIndex`] restores the mapping. - -use std::collections::HashMap; -use std::io::BufRead; - -use camino::Utf8Path; -use quick_xml::events::Event; - -use super::{CoverageFormat, CoverageParser, get_attr}; -use crate::Result; -use crate::model::{BranchCoverage, FileCoverage, FunctionCoverage, LineCoverage}; - -/// JaCoCo XML format parser. -pub(crate) struct JacocoParser; - -impl CoverageParser for JacocoParser { - fn format(&self) -> CoverageFormat { - CoverageFormat::Jacoco - } - - fn can_parse(&self, _path: &Utf8Path, content: &[u8]) -> bool { - let head = super::sniff_head(content); - // XML with a Result<()>, - ) -> Result<()> { - parse_streaming(reader, emit) - } -} - -/// Parse JaCoCo XML coverage data from raw bytes. -#[cfg(test)] -pub(crate) fn parse(input: &[u8]) -> Result { - let mut data = crate::CoverageData::new(); - parse_streaming(&mut &*input, &mut |file| { - data.files.push(file); - Ok(()) - })?; - Ok(data) -} - -/// Streaming JaCoCo parser — calls `emit` once per ``. -fn parse_streaming( - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, -) -> Result<()> { - let mut xml = super::xml_reader(reader); - let mut buf = Vec::new(); - - // State tracking - let mut current_package: Option = None; - let mut current_sourcefile: Option = None; - let mut branch_indices: HashMap = HashMap::new(); - - // Method tracking: methods are collected from elements and - // later attached to the corresponding in the same - // package. Key: (package_name, source_filename) → Vec - let mut class_methods: HashMap<(String, String), Vec> = HashMap::new(); - let mut current_class_source: Option = None; - let mut in_method = false; - let mut current_method_name: Option = None; - let mut current_method_line: Option = None; - let mut method_hit: bool = false; - - let mut emit_normalized = |mut file: FileCoverage| { - file.normalize(); - emit(file) - }; - - loop { - let event = xml.read_event_into(&mut buf); - let is_start_event = matches!(&event, Ok(Event::Start(_))); - match event { - Err(e) => return Err(super::xml_err(e, &xml)), - Ok(Event::Eof) => break, - Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e)) => { - match e.name().as_ref() { - // Container elements set state that only a matching - // `Event::End` clears; a self-closing spelling - // (`Event::Empty`) produces no `End`, so it must - // never enter that state — an empty `` - // would otherwise capture unrelated `` - // elements, an empty `` would prefix the - // next default-package sourcefile, and an empty - // `` would leak into (and drop the - // methods of) the next one. - b"package" if is_start_event => { - current_package = get_attr(e, b"name"); - } - b"class" if is_start_event => { - current_class_source = get_attr(e, b"sourcefilename"); - } - b"method" if is_start_event => { - in_method = true; - current_method_name = get_attr(e, b"name"); - current_method_line = - get_attr(e, b"line").and_then(|v| v.parse::().ok()); - method_hit = false; - } - b"counter" if in_method => { - // Check the METHOD counter inside a to - // determine whether the method was executed. - if let Some(counter_type) = get_attr(e, b"type") - && counter_type == "METHOD" - { - let covered: u64 = get_attr(e, b"covered") - .and_then(|v| v.parse().ok()) - .unwrap_or(0); - if covered > 0 { - method_hit = true; - } - } - } - b"sourcefile" if is_start_event => { - if let Some(name) = get_attr(e, b"name") { - let path = match ¤t_package { - Some(pkg) => format!("{pkg}/{name}"), - None => name.clone(), - }; - let mut file = FileCoverage::new(path); - branch_indices.clear(); - - // Attach methods collected from elements - // that reference this source file. - if let Some(pkg) = ¤t_package { - let key = (pkg.clone(), name); - if let Some(methods) = class_methods.remove(&key) { - file.functions = methods; - } - } - current_sourcefile = Some(file); - } - } - b"line" => { - if let Some(file) = current_sourcefile.as_mut() { - let mut nr: Option = None; - let mut ci: u64 = 0; - let mut mi: u64 = 0; - let mut cb: u32 = 0; - let mut mb: u32 = 0; - - for attr in e.attributes().flatten() { - match attr.key.as_ref() { - b"nr" => { - nr = super::attr_str(&attr).and_then(|v| v.parse().ok()); - } - b"ci" => { - ci = super::attr_str(&attr) - .and_then(|v| v.parse().ok()) - .unwrap_or(0); - } - b"mi" => { - mi = super::attr_str(&attr) - .and_then(|v| v.parse().ok()) - .unwrap_or(0); - } - b"cb" => { - cb = super::attr_str(&attr) - .and_then(|v| v.parse().ok()) - .unwrap_or(0); - } - b"mb" => { - mb = super::attr_str(&attr) - .and_then(|v| v.parse().ok()) - .unwrap_or(0); - } - _ => {} - } - } - - if let Some(line_number) = nr { - // A line is "hit" if any instructions were - // covered. Use ci as the hit count; if ci is - // 0 and mi > 0 the line is instrumentable - // but missed. Only emit the line when at - // least one instruction exists (ci + mi > 0), - // otherwise it's non-instrumentable (e.g. - // comments, blank lines). - if ci > 0 || mi > 0 { - file.lines.push(LineCoverage { - line_number, - hit_count: ci, - }); - } - - // Branch coverage - let total_branches = - cb.saturating_add(mb).min(super::MAX_BRANCHES_PER_LINE); - if total_branches > 0 { - let idx = branch_indices.entry(line_number).or_insert(0); - for i in 0..total_branches { - let branch_hit: u64 = u64::from(i < cb); - file.branches.push(BranchCoverage { - line_number, - branch_index: *idx, - hit_count: branch_hit, - }); - *idx += 1; - } - } - } - } - } - _ => {} - } - } - Ok(Event::End(ref e)) => match e.name().as_ref() { - b"package" => { - current_package = None; - } - b"class" => { - current_class_source = None; - } - b"method" => { - if in_method { - if let (Some(pkg), Some(src), Some(name)) = ( - ¤t_package, - ¤t_class_source, - current_method_name.take(), - ) { - let key = (pkg.clone(), src.clone()); - class_methods - .entry(key) - .or_default() - .push(FunctionCoverage { - name, - start_line: current_method_line, - end_line: None, - hit_count: u64::from(method_hit), - }); - } - in_method = false; - current_method_name = None; - current_method_line = None; - } - } - b"sourcefile" => { - if let Some(file) = current_sourcefile.take() { - emit_normalized(file)?; - } - } - _ => {} - }, - _ => {} - } - buf.clear(); - } - - // Handle unclosed sourcefile - if let Some(file) = current_sourcefile.take() { - emit_normalized(file)?; - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_jacoco() { - let input = include_bytes!("../../tests/fixtures/sample_jacoco.xml"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 2); - - let foo = &data.files[0]; - assert_eq!(foo.path, "com/example/Foo.java"); - assert_eq!(foo.lines.len(), 5); - assert_eq!(foo.lines[0].line_number, 3); - assert_eq!(foo.lines[0].hit_count, 3); // ci=3 - assert_eq!(foo.lines[1].line_number, 10); - assert_eq!(foo.lines[1].hit_count, 5); // ci=5 - assert_eq!(foo.lines[2].line_number, 11); - assert_eq!(foo.lines[2].hit_count, 5); // ci=5 - assert_eq!(foo.lines[3].line_number, 12); - assert_eq!(foo.lines[3].hit_count, 0); // ci=0, mi=2 → missed - assert_eq!(foo.lines[4].line_number, 15); - assert_eq!(foo.lines[4].hit_count, 3); // ci=3 - - // Branch on line 11: cb=1, mb=1 → 2 branch arms - assert_eq!(foo.branches.len(), 2); - assert_eq!(foo.branches[0].line_number, 11); - assert_eq!(foo.branches[0].hit_count, 1); // covered arm - assert_eq!(foo.branches[1].line_number, 11); - assert_eq!(foo.branches[1].hit_count, 0); // missed arm - - // Methods extracted from - assert_eq!(foo.functions.len(), 2); - assert_eq!(foo.functions[0].name, ""); - assert_eq!(foo.functions[0].start_line, Some(3)); - assert_eq!(foo.functions[0].hit_count, 1); - assert_eq!(foo.functions[1].name, "doStuff"); - assert_eq!(foo.functions[1].start_line, Some(10)); - assert_eq!(foo.functions[1].hit_count, 1); - - let bar = &data.files[1]; - assert_eq!(bar.path, "com/example/Bar.java"); - assert_eq!(bar.lines.len(), 2); - assert_eq!(bar.branches.len(), 0); - } - - #[test] - fn test_parse_jacoco_no_package() { - let input = include_bytes!("../../tests/fixtures/jacoco_no_package.xml"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 1); - // Without a package, path is just the source filename. - assert_eq!(data.files[0].path, "App.java"); - assert_eq!(data.files[0].lines.len(), 2); - } - - #[test] - fn test_parse_jacoco_empty() { - let input = include_bytes!("../../tests/fixtures/empty_jacoco.xml"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 0); - } - - #[test] - fn test_self_closing_elements_do_not_corrupt_state() { - // Empty-element spellings produce no `End` event, so they must - // never enter container state: an empty `` used to - // linger as the "current" sourcefile and get emitted as a - // phantom record at EOF (carrying methods it never owned), and - // an empty `` used to capture class-level METHOD - // counters that follow it. - let input = br#" - - - - - - - - - - - -"#; - let data = parse(input).unwrap(); - // The self-closed sourcefile carries no line data and must not - // be emitted as a phantom record at EOF. - assert_eq!(data.files.len(), 0, "phantom record: {:?}", data.files); - } - - #[test] - fn test_parse_jacoco_malformed() { - let input = include_bytes!("../../tests/fixtures/malformed_jacoco.xml"); - let result = parse(input); - assert!(result.is_err()); - let err_msg = format!("{}", result.unwrap_err()); - assert!( - err_msg.contains("position"), - "Error should contain position info: {err_msg}", - ); - } - - #[test] - fn test_can_parse_jacoco() { - let parser = JacocoParser; - - // JaCoCo with DTD reference - let content = br#""#; - assert!(parser.can_parse(Utf8Path::new("jacoco.xml"), content)); - - // JaCoCo without DTD but with - let content = br#""#; - assert!(parser.can_parse(Utf8Path::new("report.xml"), content)); - - // Cobertura should NOT match - let content = br#""#; - assert!(!parser.can_parse(Utf8Path::new("coverage.xml"), content)); - } -} diff --git a/crates/mehen-coverage/src/parsers/lcov.rs b/crates/mehen-coverage/src/parsers/lcov.rs deleted file mode 100644 index c9c85b6d..00000000 --- a/crates/mehen-coverage/src/parsers/lcov.rs +++ /dev/null @@ -1,306 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) -// `src/parsers/lcov.rs`, MIT-licensed by Scott Nelson. Local changes: -// house error type, camino paths, normalization before emit. -// See LICENSE-THIRD-PARTY. - -//! Parser for the LCOV `.info` format. -//! -//! Reference: -//! -//! Key records: -//! ```text -//! TN: -//! SF: -//! FN:, -//! FNDA:, -//! FNF: -//! FNH: -//! DA:,[,] -//! BRDA:,,, ("-" means 0) -//! BRF: -//! BRH: -//! LF: -//! LH: -//! end_of_record -//! ``` - -use std::collections::HashMap; -use std::io::BufRead; - -use camino::Utf8Path; - -use super::{CoverageFormat, CoverageParser}; -use crate::Result; -use crate::model::{BranchCoverage, FileCoverage, FunctionCoverage, LineCoverage}; - -/// LCOV format parser. -pub(crate) struct LcovParser; - -impl CoverageParser for LcovParser { - fn format(&self) -> CoverageFormat { - CoverageFormat::Lcov - } - - fn can_parse(&self, path: &Utf8Path, content: &[u8]) -> bool { - // Extension-based: .info or .lcov - if let Some(ext) = path.extension() { - let ext = ext.to_lowercase(); - if ext == "info" || ext == "lcov" { - return true; - } - } - - // Content-based: lines starting with SF: and DA:/FN: - let head = super::sniff_head(content); - let has_sf = head.lines().any(|l| l.starts_with("SF:")); - let has_da_or_fn = head - .lines() - .any(|l| l.starts_with("DA:") || l.starts_with("FN:")); - has_sf && has_da_or_fn - } - - fn parse_streaming( - &self, - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, - ) -> Result<()> { - parse_streaming_reader(reader, emit) - } -} - -/// Parse LCOV format coverage data from raw bytes. -#[cfg(test)] -pub(crate) fn parse(input: &[u8]) -> Result { - let mut data = crate::CoverageData::new(); - parse_streaming_reader(&mut &*input, &mut |file| { - data.files.push(file); - Ok(()) - })?; - Ok(data) -} - -/// Streaming LCOV parser — calls `emit` once per `end_of_record`. -/// Reads line-by-line from a buffered reader so the full input need -/// not be in memory at once. -fn parse_streaming_reader( - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, -) -> Result<()> { - let mut current_file: Option = None; - - // Track branch indices per line within the current file. - let mut branch_indices: HashMap = HashMap::new(); - - // Track function definitions: name -> start_line. - // end_line is not provided in LCOV; we leave it as None. - let mut fn_defs: HashMap> = HashMap::new(); - - let mut emit_normalized = |mut file: FileCoverage| { - file.normalize(); - emit(file) - }; - - let mut raw_line = String::new(); - loop { - raw_line.clear(); - // A non-UTF-8 byte sequence surfaces as an InvalidData I/O error. - let n = reader.read_line(&mut raw_line)?; - if n == 0 { - break; // EOF - } - - let line = raw_line.trim(); - if line.is_empty() { - continue; - } - - if line == "end_of_record" { - if let Some(file) = current_file.take() { - emit_normalized(file)?; - } - branch_indices.clear(); - fn_defs.clear(); - continue; - } - - // Split on first ':' - let Some((tag, value)) = line.split_once(':') else { - continue; // Skip lines we don't understand - }; - - match tag { - "TN" => { - // Test name — ignored. - } - "SF" => { - current_file = Some(FileCoverage::new(value.to_string())); - branch_indices.clear(); - fn_defs.clear(); - } - "FN" => { - // FN:, - if let Some((line_str, name)) = value.split_once(',') - && let Ok(start_line) = line_str.parse::() - { - fn_defs.insert(name.to_string(), Some(start_line)); - } - } - "FNDA" => { - // FNDA:, - if let Some(file) = current_file.as_mut() - && let Some((count_str, name)) = value.split_once(',') - { - let hit_count = count_str.parse::().unwrap_or(0); - let start_line = fn_defs.get(name).copied().flatten(); - file.functions.push(FunctionCoverage { - name: name.to_string(), - start_line, - end_line: None, - hit_count, - }); - } - } - "DA" => { - // DA:,[,] - // Some instrumenters use negative counts (e.g., -1) to - // indicate non-instrumentable lines. We skip those entirely. - if let Some(file) = current_file.as_mut() { - let parts: Vec<&str> = value.splitn(3, ',').collect(); - if parts.len() >= 2 - && let Ok(line_number) = parts[0].parse::() - && let Ok(count) = parts[1].parse::() - && count >= 0 - { - file.lines.push(LineCoverage { - line_number, - hit_count: count as u64, - }); - } - } - } - "BRDA" => { - // BRDA:,,, - // can be "-" meaning 0. - if let Some(file) = current_file.as_mut() { - let parts: Vec<&str> = value.splitn(4, ',').collect(); - if parts.len() == 4 - && let Ok(line_number) = parts[0].parse::() - { - let hit_count = if parts[3] == "-" { - 0 - } else { - parts[3].parse::().unwrap_or(0) - }; - let idx = branch_indices.entry(line_number).or_insert(0); - file.branches.push(BranchCoverage { - line_number, - branch_index: *idx, - hit_count, - }); - *idx += 1; - } - } - } - // LF, LH, FNF, FNH, BRF, BRH — summary lines; we derive these - // from the record data instead of trusting the header. - _ => {} - } - } - - // Handle case where file ends without end_of_record - if let Some(file) = current_file.take() { - emit_normalized(file)?; - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_lcov() { - let input = include_bytes!("../../tests/fixtures/sample.lcov"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 2); - - let lib = &data.files[0]; - assert_eq!(lib.path, "/src/lib.rs"); - assert_eq!(lib.lines.len(), 5); - assert_eq!(lib.lines[0].line_number, 1); - assert_eq!(lib.lines[0].hit_count, 5); - assert_eq!(lib.lines[2].line_number, 3); - assert_eq!(lib.lines[2].hit_count, 0); - - assert_eq!(lib.branches.len(), 2); - assert_eq!(lib.branches[0].line_number, 2); - assert_eq!(lib.branches[0].branch_index, 0); - assert_eq!(lib.branches[0].hit_count, 5); - assert_eq!(lib.branches[1].branch_index, 1); - assert_eq!(lib.branches[1].hit_count, 0); - - assert_eq!(lib.functions.len(), 2); - assert_eq!(lib.functions[0].name, "main"); - assert_eq!(lib.functions[0].hit_count, 5); - assert_eq!(lib.functions[0].start_line, Some(1)); - assert_eq!(lib.functions[1].name, "helper"); - assert_eq!(lib.functions[1].hit_count, 0); - - let util = &data.files[1]; - assert_eq!(util.path, "/src/util.rs"); - assert_eq!(util.lines.len(), 2); - assert_eq!(util.branches.len(), 0); - assert_eq!(util.functions.len(), 0); - } - - #[test] - fn test_parse_lcov_no_end_of_record() { - let input = include_bytes!("../../tests/fixtures/lcov_no_end_of_record.lcov"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 1); - assert_eq!(data.files[0].lines.len(), 2); - } - - #[test] - fn test_parse_lcov_negative_counts() { - // DA lines with negative counts (e.g., -1) should be skipped as - // non-instrumentable. - let input = include_bytes!("../../tests/fixtures/lcov_negative_counts.lcov"); - let data = parse(input).unwrap(); - - assert_eq!(data.files.len(), 1); - let file = &data.files[0]; - // Line 2 has count=-1, should be skipped. Lines 1, 3, 4 remain. - assert_eq!(file.lines.len(), 3); - assert_eq!(file.lines[0].line_number, 1); - assert_eq!(file.lines[0].hit_count, 5); - assert_eq!(file.lines[1].line_number, 3); - assert_eq!(file.lines[1].hit_count, 0); - assert_eq!(file.lines[2].line_number, 4); - assert_eq!(file.lines[2].hit_count, 3); - } - - #[test] - fn test_parse_lcov_empty() { - // An LCOV file with only a test name and no records should produce - // an empty CoverageData (no files). - let input = include_bytes!("../../tests/fixtures/empty.lcov"); - let data = parse(input).unwrap(); - assert_eq!(data.files.len(), 0); - } - - #[test] - fn test_parse_lcov_duplicate_da_lines_keep_max() { - // `lcov -a`-merged tracefiles can repeat DA records for the same - // line; normalization keeps the maximum hit count. - let input = b"SF:src/lib.rs\nDA:1,0\nDA:1,7\nDA:2,1\nend_of_record\n"; - let data = parse(input).unwrap(); - assert_eq!(data.files[0].lines.len(), 2); - assert_eq!(data.files[0].lines[0].hit_count, 7); - } -} diff --git a/crates/mehen-coverage/src/parsers/mod.rs b/crates/mehen-coverage/src/parsers/mod.rs deleted file mode 100644 index 0d98159b..00000000 --- a/crates/mehen-coverage/src/parsers/mod.rs +++ /dev/null @@ -1,304 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin -// -// Adapted from covrs (https://github.com/scttnlsn/covrs) -// `src/parsers/mod.rs`, MIT-licensed by Scott Nelson. Local changes: -// camino paths, house error type, serde on `CoverageFormat`, quick-xml -// 0.41 API. See LICENSE-THIRD-PARTY. - -//! The six coverage-report format parsers and their shared detection -//! machinery. Every parser is streaming (one [`FileCoverage`] emitted per -//! source-file record) and every detector is cheap by contract: the -//! extension/filename plus content markers within the first 4 KiB. -//! -//! The per-format modules are implementation detail: external consumers -//! go through the format-neutral entry points ([`detect`], -//! [`for_format`], [`crate::detect_format`], [`crate::parse_report`]). - -pub(crate) mod clover; -pub(crate) mod cobertura; -pub(crate) mod gocover; -pub(crate) mod istanbul; -pub(crate) mod jacoco; -pub(crate) mod lcov; - -use std::io::BufRead; - -use camino::Utf8Path; -use quick_xml::events::BytesStart; -use quick_xml::reader::Reader; - -use crate::Result; -use crate::model::FileCoverage; - -/// Maximum number of branch arms to emit for a single source line. Any -/// parsed branch count above this is almost certainly malformed input and -/// expanding it would consume excessive memory. Even 1024 is far beyond -/// any real-world branch count per line. -pub(crate) const MAX_BRANCHES_PER_LINE: u32 = 1024; - -/// Parser for a specific coverage format. -pub trait CoverageParser { - /// The format this parser handles. - fn format(&self) -> CoverageFormat; - - /// Whether this parser can handle the given file, based on its path - /// and content. Implementations must be cheap — only inspect the - /// extension/filename and/or the first few KiB of content. - fn can_parse(&self, path: &Utf8Path, content: &[u8]) -> bool; - - /// Streaming parse from a buffered reader: calls `emit` once per - /// source file instead of collecting everything into memory. - fn parse_streaming( - &self, - reader: &mut dyn BufRead, - emit: &mut dyn FnMut(FileCoverage) -> Result<()>, - ) -> Result<()>; -} - -// ── Shared helpers used by the clover, cobertura & jacoco parsers ── - -/// Peek at the first 4 KiB of content as a string for format detection. -pub(crate) fn sniff_head(content: &[u8]) -> std::borrow::Cow<'_, str> { - let n = content.len().min(4096); - String::from_utf8_lossy(&content[..n]) -} - -/// Whether the given text snippet looks like XML. -pub(crate) fn looks_like_xml(head: &str) -> bool { - head.contains(", name: &[u8]) -> Option { - let attr = e.try_get_attribute(name).ok()??; - attr_str(&attr) -} - -/// Normalize an attribute value per XML 1.0 rules (the version every -/// supported coverage tool emits), swallowing malformed values. -pub(crate) fn attr_str(attr: &quick_xml::events::attributes::Attribute<'_>) -> Option { - attr.normalized_value(quick_xml::XmlVersion::Implicit1_0) - .ok() - .map(|v| v.into_owned()) -} - -/// Create a configured XML reader from a buffered source. -/// -/// quick-xml never resolves DTDs or external entities (custom entities -/// stay unexpanded), so XXE and entity-expansion attacks are structurally -/// absent — `dtd_is_inert_by_construction` in the cobertura tests pins -/// that assumption against future upgrades. -pub(crate) fn xml_reader(input: R) -> Reader { - let mut reader = Reader::from_reader(input); - reader.config_mut().trim_text(true); - reader -} - -/// Map a quick_xml error to a crate error with buffer position context. -pub(crate) fn xml_err(e: quick_xml::Error, reader: &Reader) -> crate::CoverageError { - let pos = reader.buffer_position(); - crate::CoverageError::Malformed(format!("XML parse error at position {pos}: {e}")) -} - -/// Supported coverage-report formats. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize)] -#[serde(rename_all = "lowercase")] -pub enum CoverageFormat { - Clover, - Cobertura, - Gocover, - Istanbul, - Jacoco, - Lcov, -} - -impl CoverageFormat { - /// All formats in detection priority order — most-specific content - /// markers first, so a format can never false-positive on a report - /// that a later, laxer detector would also accept. - /// - /// LCOV first: `SF:`/`DA:` markers are unambiguous. Go cover next — - /// its `mode:` header and `.go:` block pattern are equally - /// distinctive. Istanbul before the XML formats because its JSON - /// `statementMap`/`fnMap` markers cannot collide with XML. JaCoCo - /// before Cobertura since both are XML but JaCoCo's `` + - /// `jacoco`/`` markers are more specific than Cobertura's - /// ``. Clover before Cobertura because both use - /// `` as the root element, but Clover detection requires - /// the `clover=` attribute. - /// - /// The same priority order also decides which same-directory sibling - /// wins when one test run emits several formats at once (e.g. Jest - /// writing `lcov.info` + `coverage-final.json` + `clover.xml`). - pub const DETECTION_ORDER: &[CoverageFormat] = &[ - CoverageFormat::Lcov, - CoverageFormat::Gocover, - CoverageFormat::Istanbul, - CoverageFormat::Jacoco, - CoverageFormat::Clover, - CoverageFormat::Cobertura, - ]; -} - -impl std::fmt::Display for CoverageFormat { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - CoverageFormat::Clover => f.write_str("clover"), - CoverageFormat::Cobertura => f.write_str("cobertura"), - CoverageFormat::Gocover => f.write_str("gocover"), - CoverageFormat::Istanbul => f.write_str("istanbul"), - CoverageFormat::Jacoco => f.write_str("jacoco"), - CoverageFormat::Lcov => f.write_str("lcov"), - } - } -} - -impl std::str::FromStr for CoverageFormat { - type Err = String; - - fn from_str(s: &str) -> std::result::Result { - match s.to_lowercase().as_str() { - "clover" => Ok(CoverageFormat::Clover), - "cobertura" => Ok(CoverageFormat::Cobertura), - "gocover" | "go" => Ok(CoverageFormat::Gocover), - "istanbul" | "nyc" => Ok(CoverageFormat::Istanbul), - "jacoco" => Ok(CoverageFormat::Jacoco), - "lcov" => Ok(CoverageFormat::Lcov), - _ => Err(format!( - "unknown coverage format '{s}' — supported: clover, cobertura, gocover, istanbul, jacoco, lcov" - )), - } - } -} - -/// Get the parser for a specific format. -#[must_use] -pub fn for_format(format: CoverageFormat) -> &'static dyn CoverageParser { - match format { - CoverageFormat::Clover => &clover::CloverParser, - CoverageFormat::Cobertura => &cobertura::CoberturaParser, - CoverageFormat::Gocover => &gocover::GocoverParser, - CoverageFormat::Istanbul => &istanbul::IstanbulParser, - CoverageFormat::Jacoco => &jacoco::JacocoParser, - CoverageFormat::Lcov => &lcov::LcovParser, - } -} - -/// Detect the format and return the matching parser, or `None`. -#[must_use] -pub fn detect(path: &Utf8Path, content: &[u8]) -> Option<&'static dyn CoverageParser> { - CoverageFormat::DETECTION_ORDER - .iter() - .map(|&f| for_format(f)) - .find(|p| p.can_parse(path, content)) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_detect_lcov_by_extension() { - let parser = detect(Utf8Path::new("coverage.info"), b"").unwrap(); - assert_eq!(parser.format(), CoverageFormat::Lcov); - - let parser = detect(Utf8Path::new("coverage.lcov"), b"").unwrap(); - assert_eq!(parser.format(), CoverageFormat::Lcov); - } - - #[test] - fn test_detect_lcov_by_content() { - let content = b"TN:test\nSF:/src/lib.rs\nDA:1,5\nend_of_record\n"; - let parser = detect(Utf8Path::new("coverage.txt"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Lcov); - } - - #[test] - fn test_detect_jacoco_by_content() { - let content = - b"\n"; - let parser = detect(Utf8Path::new("jacoco.xml"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Jacoco); - } - - #[test] - fn test_detect_jacoco_by_doctype() { - let content = - b""; - let parser = detect(Utf8Path::new("report.xml"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Jacoco); - } - - #[test] - fn test_detect_cobertura_by_content() { - let content = b"\n"; - let parser = detect(Utf8Path::new("coverage.xml"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Cobertura); - } - - #[test] - fn test_detect_gocover_by_extension() { - let parser = detect(Utf8Path::new("coverage.coverprofile"), b"").unwrap(); - assert_eq!(parser.format(), CoverageFormat::Gocover); - - let parser = detect(Utf8Path::new("coverage.gocov"), b"").unwrap(); - assert_eq!(parser.format(), CoverageFormat::Gocover); - } - - #[test] - fn test_detect_gocover_by_content() { - let content = b"mode: count\ngithub.com/user/repo/main.go:10.1,20.5 3 1\n"; - let parser = detect(Utf8Path::new("coverage.out"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Gocover); - } - - #[test] - fn test_detect_istanbul_by_filename() { - let parser = detect(Utf8Path::new("coverage-final.json"), b"").unwrap(); - assert_eq!(parser.format(), CoverageFormat::Istanbul); - } - - #[test] - fn test_detect_istanbul_by_content() { - let content = br#"{ "/src/lib.js": { "statementMap": { "0": { "start": { "line": 1 } } }, "s": { "0": 1 }, "fnMap": {}, "f": {} } }"#; - let parser = detect(Utf8Path::new("coverage.json"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Istanbul); - } - - #[test] - fn test_detect_clover_by_content() { - let content = - b"\n"; - let parser = detect(Utf8Path::new("clover.xml"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Clover); - } - - #[test] - fn test_detect_clover_not_cobertura() { - // Cobertura XML should not be detected as Clover. - let content = b"\n"; - let parser = detect(Utf8Path::new("coverage.xml"), content).unwrap(); - assert_eq!(parser.format(), CoverageFormat::Cobertura); - } - - #[test] - fn test_detect_unknown() { - assert!(detect(Utf8Path::new("random.dat"), b"hello world").is_none()); - // GNU info documentation must not be claimed by the `.info` - // extension alone… it is: extension wins for LCOV. Content that - // is *plainly not* a coverage report but carries a coverage-ish - // name is the artifact-scan sniffing gate's problem; here we pin - // the fully-unrelated case only. - assert!(detect(Utf8Path::new("notes.txt"), b"just some text").is_none()); - } - - #[test] - fn format_round_trips_through_display_and_from_str() { - for &format in CoverageFormat::DETECTION_ORDER { - let spelled = format.to_string(); - assert_eq!(spelled.parse::().unwrap(), format); - } - assert!("perf-profile".parse::().is_err()); - } -} diff --git a/crates/mehen-coverage/tests/fixtures/cobertura_branch_in_method_and_class.xml b/crates/mehen-coverage/tests/fixtures/cobertura_branch_in_method_and_class.xml deleted file mode 100644 index 86960087..00000000 --- a/crates/mehen-coverage/tests/fixtures/cobertura_branch_in_method_and_class.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/cobertura_multiple_sources.xml b/crates/mehen-coverage/tests/fixtures/cobertura_multiple_sources.xml deleted file mode 100644 index 080c9aa7..00000000 --- a/crates/mehen-coverage/tests/fixtures/cobertura_multiple_sources.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - /home/user/project/src - /home/user/project/lib - - - - - - - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/cobertura_no_sources.xml b/crates/mehen-coverage/tests/fixtures/cobertura_no_sources.xml deleted file mode 100644 index d5e167b8..00000000 --- a/crates/mehen-coverage/tests/fixtures/cobertura_no_sources.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/cobertura_utplsql.xml b/crates/mehen-coverage/tests/fixtures/cobertura_utplsql.xml deleted file mode 100644 index 61a7121c..00000000 --- a/crates/mehen-coverage/tests/fixtures/cobertura_utplsql.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - -s205031.betwnstr -s205031.load_from_tab -s205031.minimal_view -s205031.pk_glb0_mail -s205031.pk_tst0_instrumentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/empty.gocov b/crates/mehen-coverage/tests/fixtures/empty.gocov deleted file mode 100644 index 5f02b111..00000000 --- a/crates/mehen-coverage/tests/fixtures/empty.gocov +++ /dev/null @@ -1 +0,0 @@ -mode: set diff --git a/crates/mehen-coverage/tests/fixtures/empty.lcov b/crates/mehen-coverage/tests/fixtures/empty.lcov deleted file mode 100644 index 39981588..00000000 --- a/crates/mehen-coverage/tests/fixtures/empty.lcov +++ /dev/null @@ -1 +0,0 @@ -TN:test diff --git a/crates/mehen-coverage/tests/fixtures/empty_clover.xml b/crates/mehen-coverage/tests/fixtures/empty_clover.xml deleted file mode 100644 index 6b26303e..00000000 --- a/crates/mehen-coverage/tests/fixtures/empty_clover.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/empty_cobertura.xml b/crates/mehen-coverage/tests/fixtures/empty_cobertura.xml deleted file mode 100644 index cfe35d09..00000000 --- a/crates/mehen-coverage/tests/fixtures/empty_cobertura.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - /home/user/project - - - - diff --git a/crates/mehen-coverage/tests/fixtures/empty_istanbul.json b/crates/mehen-coverage/tests/fixtures/empty_istanbul.json deleted file mode 100644 index 9e26dfee..00000000 --- a/crates/mehen-coverage/tests/fixtures/empty_istanbul.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/crates/mehen-coverage/tests/fixtures/empty_jacoco.xml b/crates/mehen-coverage/tests/fixtures/empty_jacoco.xml deleted file mode 100644 index b339de85..00000000 --- a/crates/mehen-coverage/tests/fixtures/empty_jacoco.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/jacoco_no_package.xml b/crates/mehen-coverage/tests/fixtures/jacoco_no_package.xml deleted file mode 100644 index f21e12dc..00000000 --- a/crates/mehen-coverage/tests/fixtures/jacoco_no_package.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/lcov_negative_counts.lcov b/crates/mehen-coverage/tests/fixtures/lcov_negative_counts.lcov deleted file mode 100644 index 3b181021..00000000 --- a/crates/mehen-coverage/tests/fixtures/lcov_negative_counts.lcov +++ /dev/null @@ -1,7 +0,0 @@ -TN:test -SF:/src/lib.rs -DA:1,5 -DA:2,-1 -DA:3,0 -DA:4,3 -end_of_record diff --git a/crates/mehen-coverage/tests/fixtures/lcov_no_end_of_record.lcov b/crates/mehen-coverage/tests/fixtures/lcov_no_end_of_record.lcov deleted file mode 100644 index 86f32819..00000000 --- a/crates/mehen-coverage/tests/fixtures/lcov_no_end_of_record.lcov +++ /dev/null @@ -1,3 +0,0 @@ -SF:/foo.rs -DA:1,1 -DA:2,0 diff --git a/crates/mehen-coverage/tests/fixtures/malformed_clover.xml b/crates/mehen-coverage/tests/fixtures/malformed_clover.xml deleted file mode 100644 index 7cd7da71..00000000 --- a/crates/mehen-coverage/tests/fixtures/malformed_clover.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/malformed_cobertura.xml b/crates/mehen-coverage/tests/fixtures/malformed_cobertura.xml deleted file mode 100644 index e6268dcc..00000000 --- a/crates/mehen-coverage/tests/fixtures/malformed_cobertura.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/malformed_jacoco.xml b/crates/mehen-coverage/tests/fixtures/malformed_jacoco.xml deleted file mode 100644 index a714ed3d..00000000 --- a/crates/mehen-coverage/tests/fixtures/malformed_jacoco.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/sample.gocov b/crates/mehen-coverage/tests/fixtures/sample.gocov deleted file mode 100644 index 28295bb6..00000000 --- a/crates/mehen-coverage/tests/fixtures/sample.gocov +++ /dev/null @@ -1,4 +0,0 @@ -mode: count -github.com/user/project/main.go:10.1,12.10 3 5 -github.com/user/project/main.go:14.1,16.10 2 0 -github.com/user/project/util.go:5.1,7.20 2 3 diff --git a/crates/mehen-coverage/tests/fixtures/sample.lcov b/crates/mehen-coverage/tests/fixtures/sample.lcov deleted file mode 100644 index b65ad20c..00000000 --- a/crates/mehen-coverage/tests/fixtures/sample.lcov +++ /dev/null @@ -1,26 +0,0 @@ -TN:test suite -SF:/src/lib.rs -FN:1,main -FN:10,helper -FNDA:5,main -FNDA:0,helper -DA:1,5 -DA:2,5 -DA:3,0 -DA:10,0 -DA:11,0 -BRDA:2,0,0,5 -BRDA:2,0,1,0 -LF:5 -LH:2 -FNF:2 -FNH:1 -BRF:2 -BRH:1 -end_of_record -SF:/src/util.rs -DA:1,1 -DA:2,1 -LF:2 -LH:2 -end_of_record diff --git a/crates/mehen-coverage/tests/fixtures/sample_clover.xml b/crates/mehen-coverage/tests/fixtures/sample_clover.xml deleted file mode 100644 index 4f826fa4..00000000 --- a/crates/mehen-coverage/tests/fixtures/sample_clover.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/sample_cobertura.xml b/crates/mehen-coverage/tests/fixtures/sample_cobertura.xml deleted file mode 100644 index 64bd74ce..00000000 --- a/crates/mehen-coverage/tests/fixtures/sample_cobertura.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - /home/user/project/src - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/crates/mehen-coverage/tests/fixtures/sample_istanbul.json b/crates/mehen-coverage/tests/fixtures/sample_istanbul.json deleted file mode 100644 index 87022f7c..00000000 --- a/crates/mehen-coverage/tests/fixtures/sample_istanbul.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "/src/lib.js": { - "path": "/src/lib.js", - "statementMap": { - "0": { "start": { "line": 1, "column": 0 }, "end": { "line": 1, "column": 30 } }, - "1": { "start": { "line": 2, "column": 2 }, "end": { "line": 2, "column": 20 } }, - "2": { "start": { "line": 3, "column": 2 }, "end": { "line": 3, "column": 20 } }, - "3": { "start": { "line": 4, "column": 0 }, "end": { "line": 4, "column": 10 } }, - "4": { "start": { "line": 5, "column": 0 }, "end": { "line": 5, "column": 15 } } - }, - "s": { - "0": 5, - "1": 3, - "2": 0, - "3": 2, - "4": 1 - }, - "branchMap": { - "0": { - "loc": { "start": { "line": 2, "column": 0 }, "end": { "line": 3, "column": 1 } }, - "type": "if", - "locations": [ - { "start": { "line": 2, "column": 0 }, "end": { "line": 2, "column": 20 } }, - { "start": { "line": 3, "column": 0 }, "end": { "line": 3, "column": 20 } } - ] - } - }, - "b": { - "0": [5, 0] - }, - "fnMap": { - "0": { - "name": "main", - "decl": { "start": { "line": 1, "column": 0 }, "end": { "line": 1, "column": 15 } }, - "loc": { "start": { "line": 1, "column": 0 }, "end": { "line": 4, "column": 1 } } - }, - "1": { - "name": "helper", - "decl": { "start": { "line": 5, "column": 0 }, "end": { "line": 5, "column": 15 } }, - "loc": { "start": { "line": 5, "column": 0 }, "end": { "line": 5, "column": 15 } } - } - }, - "f": { - "0": 5, - "1": 0 - } - }, - "/src/util.js": { - "path": "/src/util.js", - "statementMap": { - "0": { "start": { "line": 1, "column": 0 }, "end": { "line": 1, "column": 20 } }, - "1": { "start": { "line": 2, "column": 0 }, "end": { "line": 2, "column": 15 } } - }, - "s": { - "0": 3, - "1": 1 - }, - "branchMap": {}, - "b": {}, - "fnMap": {}, - "f": {} - } -} diff --git a/crates/mehen-coverage/tests/fixtures/sample_jacoco.xml b/crates/mehen-coverage/tests/fixtures/sample_jacoco.xml deleted file mode 100644 index 6220aa3b..00000000 --- a/crates/mehen-coverage/tests/fixtures/sample_jacoco.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/crates/mehen-csharp-parser/Cargo.toml b/crates/mehen-csharp-parser/Cargo.toml deleted file mode 100644 index 2ace830f..00000000 --- a/crates/mehen-csharp-parser/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "mehen-csharp-parser" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -# Generated from `xtask/templates/parser-readme.md` by `cargo xtask antlr -# generate csharp` — never hand-edit. Named explicitly so it ships on the -# crate's registry page when published. -readme = "README.md" -description = "ANTLR-generated C# lexer and parser (grammars-v4 C# grammar) on the antlr-rust-runtime." -# Unlike the internal `mehen-*` analyzer crates (`publish = false`), this -# crate ships ONLY the generated lexer/parser (plus the hand-written -# `CSharpLexerBase` hooks port the grammar requires) so external tools can -# depend on the C# parser alone via a git tag on this repo — the same way -# `mehen` itself consumes ruff/oxc/sqruff parser crates. It carries no -# mehen-specific logic and no dependency on `mehen-core`. -publish = true - -[dependencies] -# The generated modules reference the runtime by its real crate name -# (`use antlr4_runtime::…`). Pinned in exactly one place — the workspace -# `[workspace.dependencies]` `antlr4_runtime` entry — so every consumer -# links the same revision the modules were generated against. Regenerate -# with `cargo xtask antlr generate csharp` after any bump. -antlr4_runtime = { workspace = true } - -# The generated modules are checked in verbatim and intentionally expose -# their whole surface, so this crate deliberately does NOT opt into the -# workspace `unreachable_pub` lint (`[lints] workspace = true`) that the -# hand-written crates use. diff --git a/crates/mehen-csharp-parser/README.md b/crates/mehen-csharp-parser/README.md deleted file mode 100644 index d213f96a..00000000 --- a/crates/mehen-csharp-parser/README.md +++ /dev/null @@ -1,95 +0,0 @@ - -# mehen-csharp-parser - -ANTLR-generated **C#** lexer and parser, running on the -[`antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime) Rust -runtime. - -This crate is produced by the [`mehen`](https://github.com/ophi-dev/mehen) code-metrics tool but -carries **no mehen-specific logic** and **no dependency on `mehen-core`**: it -ships only the machine-generated lexer/parser plus the vendored `.g4` grammar. -That makes it usable on its own — the same way `mehen` itself consumes the -ruff / oxc / sqruff parser crates — so you can parse C# in your -own tool without pulling in an analyzer. - - - -## Add the dependency - -The crate is published from a git tag on the [`mehen` repository](https://github.com/ophi-dev/mehen), -not to crates.io. Depend on it by tag or branch: - -```toml -[dependencies] -# Pin a release tag (recommended) — see the repository's Releases page: -mehen-csharp-parser = { git = "https://github.com/ophi-dev/mehen", tag = "vX.Y.Z" } -# …or track the default branch: -# mehen-csharp-parser = { git = "https://github.com/ophi-dev/mehen", branch = "main" } -``` - -You do **not** need to depend on `antlr-rust-runtime` yourself: this crate -re-exports the exact runtime revision the modules were generated against as -`mehen_csharp_parser::antlr4_runtime`. Reach the runtime types (`ParsedFile`, -`Node`, `TokenView`, …) through that path so your version can never drift from -the generated code. - -## Parse some C# - -`c_sharp_parser::parse` wires up the lexer, token stream, parser, and a -chosen entry rule in one call, returning an owned `ParsedFile` that holds the -token store and the flat CST: - -```rust -use mehen_csharp_parser::c_sharp_parser::{self, CSharpParser}; -use mehen_csharp_parser::c_sharp_lexer::CSharpLexer; - -fn main() -> Result<(), mehen_csharp_parser::antlr4_runtime::AntlrError> { - let parsed = c_sharp_parser::parse( - "class C {}\n", - CSharpLexer::new, - CSharpParser::compilation_unit, - )?; - - // Walk the CST from the entry-rule root, or read the buffered tokens. - let root = parsed.tree(); - let _ = root; - Ok(()) -} -``` - -Need parser diagnostics (e.g. the syntax-error count) after the entry rule -runs? Use `parse_with_parser`, which hands the parser back: - -```rust -use mehen_csharp_parser::c_sharp_parser::{self, CSharpParser}; -use mehen_csharp_parser::c_sharp_lexer::CSharpLexer; -// `number_of_syntax_errors` is a `Parser`-trait method, so the trait must be -// in scope to call it. -use mehen_csharp_parser::antlr4_runtime::Parser; - -fn main() -> Result<(), mehen_csharp_parser::antlr4_runtime::AntlrError> { - let out = c_sharp_parser::parse_with_parser( - "class C {}\n", - CSharpLexer::new, - CSharpParser::compilation_unit, - )?; - let errors = out.parser.number_of_syntax_errors(); - let parsed = out.parser.into_parsed_file(out.result); - let _ = (errors, parsed.tree()); - Ok(()) -} -``` - -The parse tree has **no parent pointers** (the runtime stores `Node` views in a -flat arena), so thread any parent-dependent context top-down as you walk. - -## Grammar & provenance - -- **Upstream grammar:** [`dotnet/roslyn`](https://github.com/dotnet/roslyn) -- **Vendored `.g4` files + any local patches:** [`grammar/`](grammar/) — see [`grammar/PROVENANCE.md`](grammar/PROVENANCE.md) for the exact commit -- **ANTLR Rust runtime + codegen:** [`antlr-rust-runtime`](https://crates.io/crates/antlr-rust-runtime) / [`antlr-rust-codegen`](https://crates.io/crates/antlr-rust-codegen) `v0.33.1` - -## License - -`AGPL-3.0-only`, same as the `mehen` workspace. diff --git a/crates/mehen-csharp-parser/grammar/.gitignore b/crates/mehen-csharp-parser/grammar/.gitignore deleted file mode 100644 index b33775c4..00000000 --- a/crates/mehen-csharp-parser/grammar/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# Derived from the vendored `CSharp.Generated.g4` by `prepare-grammar.py`. -# -# Since the concurrency fix these land in a process-local scratch directory -# rather than here, so `cargo xtask antlr generate csharp` no longer writes them -# into this tree at all. Kept ignored so a hand-run of the script -# (`uv run prepare-grammar.py CSharp.Generated.g4 --out-dir .`, which is how you -# iterate on the transform) does not show up as untracked noise. -# -# Build artifacts either way, never sources — see PROVENANCE.md. -/CSharpLexer.g4 -/CSharpParser.g4 -/patterns.toml - -# ANTLR IDE plugin scratch output. -/.antlr/ diff --git a/crates/mehen-csharp-parser/grammar/CSharp.Generated.g4 b/crates/mehen-csharp-parser/grammar/CSharp.Generated.g4 deleted file mode 100644 index 46a322e6..00000000 --- a/crates/mehen-csharp-parser/grammar/CSharp.Generated.g4 +++ /dev/null @@ -1,1811 +0,0 @@ -// -grammar csharp; - -compilation_unit - : extern_alias_directive* using_directive* attribute_list* member_declaration* - ; - -extern_alias_directive - : 'extern' 'alias' identifier_token ';' - ; - -using_directive - : 'global'? 'using' ('static' | ('unsafe'? name_equals))? type ';' - ; - -name_equals - : identifier_name '=' - ; - -identifier_name - : 'global' - | identifier_token - ; - -attribute_list - : '[' attribute_target_specifier? attribute (',' attribute)* ']' - ; - -attribute_target_specifier - : syntax_token ':' - ; - -attribute - : name attribute_argument_list? - ; - -name - : alias_qualified_name - | qualified_name - | simple_name - ; - -alias_qualified_name - : identifier_name '::' simple_name - ; - -simple_name - : generic_name - | identifier_name - ; - -generic_name - : identifier_token type_argument_list - ; - -type_argument_list - : '<' (type (',' type)*)? '>' - ; - -qualified_name - : name '.' simple_name - ; - -attribute_argument_list - : '(' (attribute_argument (',' attribute_argument)*)? ')' - ; - -attribute_argument - : (name_equals? | name_colon?) expression - ; - -name_colon - : identifier_name ':' - ; - -member_declaration - : base_field_declaration - | base_method_declaration - | base_namespace_declaration - | base_property_declaration - | base_type_declaration - | delegate_declaration - | enum_member_declaration - | global_statement - | incomplete_member - ; - -base_field_declaration - : event_field_declaration - | field_declaration - ; - -event_field_declaration - : attribute_list* modifier* 'event' variable_declaration ';' - ; - -modifier - : 'abstract' - | 'async' - | 'closed' - | 'const' - | 'extern' - | 'file' - | 'fixed' - | 'internal' - | 'new' - | 'override' - | 'partial' - | 'private' - | 'protected' - | 'public' - | 'readonly' - | 'ref' - | 'required' - | 'safe' - | 'scoped' - | 'sealed' - | 'static' - | 'unsafe' - | 'virtual' - | 'volatile' - ; - -variable_declaration - : type variable_declarator (',' variable_declarator)* - ; - -variable_declarator - : identifier_token bracketed_argument_list? equals_value_clause? - ; - -bracketed_argument_list - : '[' argument (',' argument)* ']' - ; - -argument - : name_colon? ('ref' | 'out' | 'in')? expression - ; - -equals_value_clause - : '=' expression - ; - -field_declaration - : attribute_list* modifier* variable_declaration ';' - ; - -base_method_declaration - : constructor_declaration - | conversion_operator_declaration - | destructor_declaration - | method_declaration - | operator_declaration - ; - -constructor_declaration - : attribute_list* modifier* identifier_token parameter_list constructor_initializer? (block | (arrow_expression_clause ';')) - ; - -parameter_list - : '(' (parameter (',' parameter)*)? ')' - ; - -parameter - : attribute_list* modifier* type? (identifier_token | '__arglist')? equals_value_clause? - ; - -constructor_initializer - : ':' ('base' | 'this') argument_list - ; - -argument_list - : '(' (argument (',' argument)*)? ')' - ; - -block - : attribute_list* '{' statement* '}' - ; - -arrow_expression_clause - : '=>' expression - ; - -conversion_operator_declaration - : attribute_list* modifier* ('implicit' | 'explicit') explicit_interface_specifier? 'operator' 'checked'? type parameter_list (block | (arrow_expression_clause ';')) - ; - -explicit_interface_specifier - : name '.' - ; - -destructor_declaration - : attribute_list* modifier* '~' identifier_token parameter_list (block | (arrow_expression_clause ';')) - ; - -method_declaration - : attribute_list* modifier* type explicit_interface_specifier? identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* (block | (arrow_expression_clause ';')) - ; - -type_parameter_list - : '<' type_parameter (',' type_parameter)* '>' - ; - -type_parameter - : attribute_list* ('in' | 'out')? identifier_token - ; - -type_parameter_constraint_clause - : 'where' identifier_name ':' type_parameter_constraint (',' type_parameter_constraint)* - ; - -type_parameter_constraint - : allows_constraint_clause - | class_or_struct_constraint - | constructor_constraint - | default_constraint - | type_constraint - ; - -allows_constraint_clause - : 'allows' allows_constraint (',' allows_constraint)* - ; - -allows_constraint - : ref_struct_constraint - ; - -ref_struct_constraint - : 'ref' 'struct' - ; - -class_or_struct_constraint - : 'class' '?'? - | 'struct' '?'? - ; - -constructor_constraint - : 'new' '(' ')' - ; - -default_constraint - : 'default' - ; - -type_constraint - : type - ; - -operator_declaration - : attribute_list* modifier* type explicit_interface_specifier? 'operator' 'checked'? ('+' | '-' | '!' | '~' | '++' | '--' | '*' | '/' | '%' | '<<' | '>>' | '>>>' | '|' | '&' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | 'false' | 'true' | 'is' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '>>>=') parameter_list (block | (arrow_expression_clause ';')) - ; - -base_namespace_declaration - : file_scoped_namespace_declaration - | namespace_declaration - ; - -file_scoped_namespace_declaration - : attribute_list* modifier* 'namespace' name ';' extern_alias_directive* using_directive* member_declaration* - ; - -namespace_declaration - : attribute_list* modifier* 'namespace' name '{' extern_alias_directive* using_directive* member_declaration* '}' ';'? - ; - -base_property_declaration - : event_declaration - | indexer_declaration - | property_declaration - ; - -event_declaration - : attribute_list* modifier* 'event' type explicit_interface_specifier? identifier_token (accessor_list | ';') - ; - -accessor_list - : '{' accessor_declaration* '}' - ; - -accessor_declaration - : attribute_list* modifier* ('get' | 'set' | 'init' | 'add' | 'remove' | identifier_token) (block | (arrow_expression_clause ';')) - ; - -indexer_declaration - : attribute_list* modifier* type explicit_interface_specifier? 'this' bracketed_parameter_list (accessor_list | (arrow_expression_clause ';')) - ; - -bracketed_parameter_list - : '[' parameter (',' parameter)* ']' - ; - -property_declaration - : attribute_list* modifier* type explicit_interface_specifier? identifier_token (accessor_list | ((arrow_expression_clause | equals_value_clause) ';')) - ; - -base_type_declaration - : enum_declaration - | type_declaration - ; - -enum_declaration - : attribute_list* modifier* 'enum' identifier_token base_list? '{'? (enum_member_declaration (',' enum_member_declaration)* ','?)? '}'? ';'? - ; - -base_list - : ':' base_type (',' base_type)* - ; - -base_type - : primary_constructor_base_type - | simple_base_type - ; - -primary_constructor_base_type - : type argument_list - ; - -simple_base_type - : type - ; - -enum_member_declaration - : attribute_list* modifier* identifier_token equals_value_clause? - ; - -type_declaration - : class_declaration - | extension_block_declaration - | interface_declaration - | record_declaration - | struct_declaration - | union_declaration - ; - -class_declaration - : attribute_list* modifier* 'class' identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* '{'? member_declaration* '}'? ';'? - ; - -extension_block_declaration - : attribute_list* modifier* 'extension' type_parameter_list? parameter_list? type_parameter_constraint_clause* '{'? member_declaration* '}'? ';'? - ; - -interface_declaration - : attribute_list* modifier* 'interface' identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* '{'? member_declaration* '}'? ';'? - ; - -record_declaration - : attribute_list* modifier* syntax_token ('class' | 'struct')? identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* '{'? member_declaration* '}'? ';'? - ; - -struct_declaration - : attribute_list* modifier* 'struct' identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* '{'? member_declaration* '}'? ';'? - ; - -union_declaration - : attribute_list* modifier* 'union' identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* '{'? member_declaration* '}'? ';'? - ; - -delegate_declaration - : attribute_list* modifier* 'delegate' type identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* ';' - ; - -global_statement - : attribute_list* modifier* statement - ; - -incomplete_member - : attribute_list* modifier* type? - ; - -type - : array_type - | function_pointer_type - | name - | nullable_type - | omitted_type_argument - | pointer_type - | predefined_type - | ref_type - | scoped_type - | tuple_type - ; - -array_type - : type array_rank_specifier+ - ; - -array_rank_specifier - : '[' (expression (',' expression)*)? ']' - ; - -function_pointer_type - : 'delegate' '*' function_pointer_calling_convention? function_pointer_parameter_list - ; - -function_pointer_calling_convention - : 'managed' function_pointer_unmanaged_calling_convention_list? - | 'unmanaged' function_pointer_unmanaged_calling_convention_list? - ; - -function_pointer_unmanaged_calling_convention_list - : '[' function_pointer_unmanaged_calling_convention (',' function_pointer_unmanaged_calling_convention)* ']' - ; - -function_pointer_unmanaged_calling_convention - : identifier_token - ; - -function_pointer_parameter_list - : '<' function_pointer_parameter (',' function_pointer_parameter)* '>' - ; - -function_pointer_parameter - : attribute_list* modifier* type - ; - -nullable_type - : type '?' - ; - -omitted_type_argument - : /* epsilon */ - ; - -pointer_type - : type '*' - ; - -predefined_type - : 'bool' - | 'byte' - | 'char' - | 'decimal' - | 'double' - | 'float' - | 'int' - | 'long' - | 'object' - | 'sbyte' - | 'short' - | 'string' - | 'uint' - | 'ulong' - | 'ushort' - | 'void' - ; - -ref_type - : 'ref' 'readonly'? type - ; - -scoped_type - : 'scoped' type - ; - -tuple_type - : '(' tuple_element (',' tuple_element)+ ')' - ; - -tuple_element - : type identifier_token? - ; - -statement - : block - | break_statement - | checked_statement - | common_for_each_statement - | continue_statement - | do_statement - | empty_statement - | expression_statement - | fixed_statement - | for_statement - | goto_statement - | if_statement - | labeled_statement - | local_declaration_statement - | local_function_statement - | lock_statement - | return_statement - | switch_statement - | throw_statement - | try_statement - | unsafe_statement - | using_statement - | while_statement - | yield_statement - ; - -break_statement - : attribute_list* 'break' identifier_name? ';' - ; - -checked_statement - : attribute_list* ('checked' | 'unchecked') block - ; - -common_for_each_statement - : for_each_statement - | for_each_variable_statement - ; - -for_each_statement - : attribute_list* 'await'? 'foreach' '(' type identifier_token 'in' expression ')' statement - ; - -for_each_variable_statement - : attribute_list* 'await'? 'foreach' '(' expression 'in' expression ')' statement - ; - -continue_statement - : attribute_list* 'continue' identifier_name? ';' - ; - -do_statement - : attribute_list* 'do' statement 'while' '(' expression ')' ';' - ; - -empty_statement - : attribute_list* ';' - ; - -expression_statement - : attribute_list* expression ';' - ; - -fixed_statement - : attribute_list* 'fixed' '(' variable_declaration ')' statement - ; - -for_statement - : attribute_list* 'for' '(' (variable_declaration? | (expression (',' expression)*)?) ';' expression? ';' (expression (',' expression)*)? ')' statement - ; - -goto_statement - : attribute_list* 'goto' ('case' | 'default')? expression? ';' - ; - -if_statement - : attribute_list* 'if' '(' expression ')' statement else_clause? - ; - -else_clause - : 'else' statement - ; - -labeled_statement - : attribute_list* identifier_token ':' statement - ; - -local_declaration_statement - : attribute_list* 'await'? 'using'? modifier* variable_declaration ';' - ; - -local_function_statement - : attribute_list* modifier* type identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* (block | (arrow_expression_clause ';')) - ; - -lock_statement - : attribute_list* 'lock' '(' expression ')' statement - ; - -return_statement - : attribute_list* 'return' expression? ';' - ; - -switch_statement - : attribute_list* 'switch' '('? expression ')'? '{' switch_section* '}' - ; - -switch_section - : switch_label+ statement+ - ; - -switch_label - : case_pattern_switch_label - | case_switch_label - | default_switch_label - ; - -case_pattern_switch_label - : 'case' pattern when_clause? ':' - ; - -pattern - : binary_pattern - | constant_pattern - | declaration_pattern - | discard_pattern - | list_pattern - | parenthesized_pattern - | recursive_pattern - | relational_pattern - | slice_pattern - | type_pattern - | unary_pattern - | var_pattern - ; - -binary_pattern - : pattern ('or' | 'and') pattern - ; - -constant_pattern - : expression - ; - -declaration_pattern - : type variable_designation - ; - -variable_designation - : discard_designation - | parenthesized_variable_designation - | single_variable_designation - ; - -discard_designation - : '_' - ; - -parenthesized_variable_designation - : '(' (variable_designation (',' variable_designation)*)? ')' - ; - -single_variable_designation - : identifier_token - ; - -discard_pattern - : '_' - ; - -list_pattern - : '[' (pattern (',' pattern)* ','?)? ']' variable_designation? - ; - -parenthesized_pattern - : '(' pattern ')' - ; - -recursive_pattern - : type? positional_pattern_clause? property_pattern_clause? variable_designation? - ; - -positional_pattern_clause - : '(' (subpattern (',' subpattern)*)? ')' - ; - -subpattern - : base_expression_colon? pattern - ; - -base_expression_colon - : expression_colon - | name_colon - ; - -expression_colon - : expression ':' - ; - -property_pattern_clause - : '{' (subpattern (',' subpattern)* ','?)? '}' - ; - -relational_pattern - : '!=' expression - | '<' expression - | '<=' expression - | '==' expression - | '>' expression - | '>=' expression - ; - -slice_pattern - : '..' pattern? - ; - -type_pattern - : type - ; - -unary_pattern - : 'not' pattern - ; - -var_pattern - : 'var' variable_designation - ; - -when_clause - : 'when' expression - ; - -case_switch_label - : 'case' expression ':' - ; - -default_switch_label - : 'default' ':' - ; - -throw_statement - : attribute_list* 'throw' expression? ';' - ; - -try_statement - : attribute_list* 'try' block catch_clause* finally_clause? - ; - -catch_clause - : 'catch' catch_declaration? catch_filter_clause? block - ; - -catch_declaration - : '(' type identifier_token? ')' - ; - -catch_filter_clause - : 'when' '(' expression ')' - ; - -finally_clause - : 'finally' block - ; - -unsafe_statement - : attribute_list* 'unsafe' block - ; - -using_statement - : attribute_list* 'await'? 'using' '(' (variable_declaration | expression) ')' statement - ; - -while_statement - : attribute_list* 'while' '(' expression ')' statement - ; - -yield_statement - : attribute_list* 'yield' ('return' | 'break') expression? ';' - ; - -expression - : anonymous_function_expression - | anonymous_object_creation_expression - | array_creation_expression - | assignment_expression - | await_expression - | base_object_creation_expression - | binary_expression - | cast_expression - | checked_expression - | collection_expression - | conditional_access_expression - | conditional_expression - | declaration_expression - | default_expression - | element_access_expression - | element_binding_expression - | field_expression - | implicit_array_creation_expression - | implicit_element_access - | implicit_stack_alloc_array_creation_expression - | initializer_expression - | instance_expression - | interpolated_string_expression - | invocation_expression - | is_pattern_expression - | literal_expression - | make_ref_expression - | member_access_expression - | member_binding_expression - | omitted_array_size_expression - | parenthesized_expression - | postfix_unary_expression - | prefix_unary_expression - | query_expression - | range_expression - | ref_expression - | ref_type_expression - | ref_value_expression - | size_of_expression - | stack_alloc_array_creation_expression - | switch_expression - | throw_expression - | tuple_expression - | type - | type_of_expression - | unsafe_expression - | with_expression - ; - -anonymous_function_expression - : anonymous_method_expression - | lambda_expression - ; - -anonymous_method_expression - : modifier* 'delegate' parameter_list? block expression? - ; - -lambda_expression - : parenthesized_lambda_expression - | simple_lambda_expression - ; - -parenthesized_lambda_expression - : attribute_list* modifier* type? parameter_list '=>' (block | expression) - ; - -simple_lambda_expression - : attribute_list* modifier* parameter '=>' (block | expression) - ; - -anonymous_object_creation_expression - : 'new' '{' (anonymous_object_member_declarator (',' anonymous_object_member_declarator)* ','?)? '}' - ; - -anonymous_object_member_declarator - : name_equals? expression - ; - -array_creation_expression - : 'new' array_type initializer_expression? - ; - -initializer_expression - : '{' (expression (',' expression)* ','?)? '}' - ; - -assignment_expression - : expression ('=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|=' | '<<=' | '>>=' | '>>>=' | '??=') expression - ; - -await_expression - : 'await' expression - ; - -base_object_creation_expression - : implicit_object_creation_expression - | object_creation_expression - ; - -implicit_object_creation_expression - : 'new' argument_list initializer_expression? - ; - -object_creation_expression - : 'new' type argument_list? initializer_expression? - ; - -binary_expression - : expression ('+' | '-' | '*' | '/' | '%' | '<<' | '>>' | '>>>' | '||' | '&&' | '|' | '&' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | 'is' | 'as' | '??') expression - ; - -cast_expression - : '(' type ')' expression - ; - -checked_expression - : 'checked' '(' expression ')' - | 'unchecked' '(' expression ')' - ; - -collection_expression - : '[' (collection_element (',' collection_element)* ','?)? ']' - ; - -collection_element - : expression_element - | spread_element - | with_element - ; - -expression_element - : expression - ; - -spread_element - : '..' expression - ; - -with_element - : 'with' argument_list - ; - -conditional_access_expression - : expression '?' expression - ; - -conditional_expression - : expression '?' expression ':' expression - ; - -declaration_expression - : type variable_designation - ; - -default_expression - : 'default' '(' type ')' - ; - -element_access_expression - : expression bracketed_argument_list - ; - -element_binding_expression - : bracketed_argument_list - ; - -field_expression - : 'field' - ; - -implicit_array_creation_expression - : 'new' '[' ','* ']' initializer_expression - ; - -implicit_element_access - : bracketed_argument_list - ; - -implicit_stack_alloc_array_creation_expression - : 'stackalloc' '[' ']' initializer_expression - ; - -instance_expression - : base_expression - | this_expression - ; - -base_expression - : 'base' - ; - -this_expression - : 'this' - ; - -interpolated_string_expression - : '$"' interpolated_string_content* '"' - | '$@"' interpolated_string_content* '"' - | interpolated_multi_line_raw_string_start_token interpolated_string_content* interpolated_raw_string_end_token - | interpolated_single_line_raw_string_start_token interpolated_string_content* interpolated_raw_string_end_token - ; - -interpolated_string_content - : interpolated_string_text - | interpolation - ; - -interpolated_string_text - : interpolated_string_text_token - ; - -interpolation - : '{' expression interpolation_alignment_clause? interpolation_format_clause? '}' - ; - -interpolation_alignment_clause - : ',' expression - ; - -interpolation_format_clause - : ':' interpolated_string_text_token - ; - -interpolated_multi_line_raw_string_start_token - : '$'+ '"""' '"'* - ; - -interpolated_raw_string_end_token - : '"""' '"'* /* must match number of quotes in raw_string_start_token */ - ; - -interpolated_single_line_raw_string_start_token - : '$'+ '"""' '"'* - ; - -invocation_expression - : expression argument_list - ; - -is_pattern_expression - : expression 'is' pattern - ; - -literal_expression - : 'default' - | 'false' - | 'null' - | 'true' - | '__arglist' - | character_literal_token - | multi_line_raw_string_literal_token - | numeric_literal_token - | single_line_raw_string_literal_token - | string_literal_token - | utf8_multi_line_raw_string_literal_token - | utf8_single_line_raw_string_literal_token - | utf8_string_literal_token - ; - -utf8_multi_line_raw_string_literal_token - : multi_line_raw_string_literal_token ('U8' | 'u8') - ; - -utf8_single_line_raw_string_literal_token - : single_line_raw_string_literal_token ('U8' | 'u8') - ; - -utf8_string_literal_token - : string_literal_token ('U8' | 'u8') - ; - -make_ref_expression - : '__makeref' '(' expression ')' - ; - -member_access_expression - : expression ('.' | '->') simple_name - ; - -member_binding_expression - : '.' simple_name - ; - -omitted_array_size_expression - : /* epsilon */ - ; - -parenthesized_expression - : '(' expression ')' - ; - -postfix_unary_expression - : expression ('++' | '--' | '!') - ; - -prefix_unary_expression - : '!' expression - | '&' expression - | '*' expression - | '+' expression - | '++' expression - | '-' expression - | '--' expression - | '^' expression - | '~' expression - ; - -query_expression - : from_clause query_body - ; - -from_clause - : 'from' type? identifier_token 'in' expression - ; - -query_body - : query_clause+ select_or_group_clause query_continuation? - ; - -query_clause - : from_clause - | join_clause - | let_clause - | order_by_clause - | where_clause - ; - -join_clause - : 'join' type? identifier_token 'in' expression 'on' expression 'equals' expression join_into_clause? - ; - -join_into_clause - : 'into' identifier_token - ; - -let_clause - : 'let' identifier_token '=' expression - ; - -order_by_clause - : 'orderby' ordering (',' ordering)* - ; - -ordering - : expression ('ascending' | 'descending')? - ; - -where_clause - : 'where' expression - ; - -select_or_group_clause - : group_clause - | select_clause - ; - -group_clause - : 'group' expression 'by' expression - ; - -select_clause - : 'select' expression - ; - -query_continuation - : 'into' identifier_token query_body - ; - -range_expression - : expression? '..' expression? - ; - -ref_expression - : 'ref' expression - ; - -ref_type_expression - : '__reftype' '(' expression ')' - ; - -ref_value_expression - : '__refvalue' '(' expression ',' type ')' - ; - -size_of_expression - : 'sizeof' '(' type ')' - ; - -stack_alloc_array_creation_expression - : 'stackalloc' type initializer_expression? - ; - -switch_expression - : expression 'switch' '{' (switch_expression_arm (',' switch_expression_arm)* ','?)? '}' - ; - -switch_expression_arm - : pattern when_clause? '=>' expression - ; - -throw_expression - : 'throw' expression - ; - -tuple_expression - : '(' argument (',' argument)+ ')' - ; - -type_of_expression - : 'typeof' '(' type ')' - ; - -unsafe_expression - : 'unsafe' '(' expression ')' - ; - -with_expression - : expression 'with' initializer_expression - ; - -xml_node - : xml_comment - | xml_c_data_section - | xml_element - | xml_empty_element - | xml_processing_instruction - | xml_text - ; - -xml_comment - : '' - ; - -xml_c_data_section - : '' - ; - -xml_element - : xml_element_start_tag xml_node* xml_element_end_tag - ; - -xml_element_start_tag - : '<' xml_name xml_attribute* '>' - ; - -xml_name - : xml_prefix? identifier_token - ; - -xml_prefix - : identifier_token ':' - ; - -xml_attribute - : xml_cref_attribute - | xml_name_attribute - | xml_text_attribute - ; - -xml_cref_attribute - : xml_name '=' ('\'' | '"') cref ('\'' | '"') - ; - -cref - : member_cref - | qualified_cref - | type_cref - ; - -member_cref - : conversion_operator_member_cref - | extension_member_cref - | indexer_member_cref - | name_member_cref - | operator_member_cref - ; - -conversion_operator_member_cref - : 'explicit' 'operator' 'checked'? type cref_parameter_list? - | 'implicit' 'operator' 'checked'? type cref_parameter_list? - ; - -cref_parameter_list - : '(' (cref_parameter (',' cref_parameter)*)? ')' - ; - -cref_parameter - : 'in'? 'readonly'? type - | 'out'? 'readonly'? type - | 'ref'? 'readonly'? type - ; - -extension_member_cref - : 'extension' type_argument_list? cref_parameter_list '.' member_cref - ; - -indexer_member_cref - : 'this' cref_bracketed_parameter_list? - ; - -cref_bracketed_parameter_list - : '[' cref_parameter (',' cref_parameter)* ']' - ; - -name_member_cref - : type cref_parameter_list? - ; - -operator_member_cref - : 'operator' 'checked'? ('+' | '-' | '!' | '~' | '++' | '--' | '*' | '/' | '%' | '<<' | '>>' | '>>>' | '|' | '&' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | 'false' | 'true' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '>>>=') cref_parameter_list? - ; - -qualified_cref - : type '.' member_cref - ; - -type_cref - : type - ; - -xml_name_attribute - : xml_name '=' ('\'' | '"') identifier_name ('\'' | '"') - ; - -xml_text_attribute - : xml_name '=' ('\'' | '"') xml_text_literal_token* ('\'' | '"') - ; - -xml_element_end_tag - : '' - ; - -xml_empty_element - : '<' xml_name xml_attribute* '/>' - ; - -xml_processing_instruction - : '' - ; - -xml_text - : xml_text_literal_token* - ; - -structured_trivia - : directive_trivia - | documentation_comment_trivia - | skipped_tokens_trivia - ; - -directive_trivia - : bad_directive_trivia - | branching_directive_trivia - | define_directive_trivia - | end_if_directive_trivia - | end_region_directive_trivia - | error_directive_trivia - | ignored_directive_trivia - | line_or_span_directive_trivia - | load_directive_trivia - | nullable_directive_trivia - | pragma_checksum_directive_trivia - | pragma_warning_directive_trivia - | reference_directive_trivia - | region_directive_trivia - | shebang_directive_trivia - | undef_directive_trivia - | warning_directive_trivia - ; - -bad_directive_trivia - : '#' syntax_token - ; - -branching_directive_trivia - : conditional_directive_trivia - | else_directive_trivia - ; - -conditional_directive_trivia - : elif_directive_trivia - | if_directive_trivia - ; - -elif_directive_trivia - : '#' 'elif' expression - ; - -if_directive_trivia - : '#' 'if' expression - ; - -else_directive_trivia - : '#' 'else' - ; - -define_directive_trivia - : '#' 'define' identifier_token - ; - -end_if_directive_trivia - : '#' 'endif' - ; - -end_region_directive_trivia - : '#' 'endregion' - ; - -error_directive_trivia - : '#' 'error' - ; - -ignored_directive_trivia - : '#' ':' string_literal_token? - ; - -line_or_span_directive_trivia - : line_directive_trivia - | line_span_directive_trivia - ; - -line_directive_trivia - : '#' 'line' (numeric_literal_token | 'default' | 'hidden') string_literal_token? - ; - -line_span_directive_trivia - : '#' 'line' line_directive_position '-' line_directive_position numeric_literal_token? string_literal_token - ; - -line_directive_position - : '(' numeric_literal_token ',' numeric_literal_token ')' - ; - -load_directive_trivia - : '#' 'load' string_literal_token - ; - -nullable_directive_trivia - : '#' 'nullable' ('enable' | 'disable' | 'restore') ('warnings' | 'annotations')? - ; - -pragma_checksum_directive_trivia - : '#' 'pragma' 'checksum' string_literal_token string_literal_token string_literal_token - ; - -pragma_warning_directive_trivia - : '#' 'pragma' 'warning' ('disable' | 'restore') (expression (',' expression)*)? - ; - -reference_directive_trivia - : '#' 'r' string_literal_token - ; - -region_directive_trivia - : '#' 'region' - ; - -shebang_directive_trivia - : '#' '!' - ; - -undef_directive_trivia - : '#' 'undef' identifier_token - ; - -warning_directive_trivia - : '#' 'warning' - ; - -documentation_comment_trivia - : xml_node* - ; - -skipped_tokens_trivia - : syntax_token* - ; - -syntax_token - : character_literal_token - | identifier_token - | keyword - | numeric_literal_token - | operator_token - | punctuation_token - | string_literal_token - ; - -identifier_token - : '@'? identifier_start_character identifier_part_character - ; - -identifier_start_character - : letter_character - | underscore_character - ; - -letter_character - : /* [\p{L}\p{Nl}] category letter, all subcategories; category number, subcategory letter */ - | unicode_escape_sequence /* only escapes for categories L & Nl allowed */ - ; - -underscore_character - : '\\u005' /* unicode_escape_sequence for underscore */ - | '_' - ; - -identifier_part_character - : combining_character - | connecting_character - | decimal_digit_character - | formatting_character - | letter_character - ; - -combining_character - : /* [\p{Mn}\p{Mc}] category Mark, subcategories non-spacing and spacing combining */ - | unicode_escape_sequence /* only escapes for categories Mn & Mc allowed */ - ; - -connecting_character - : /* [\p{Pc}] category Punctuation, subcategory connector */ - | unicode_escape_sequence /* only escapes for category Pc allowed */ - ; - -decimal_digit_character - : /* [\p{Nd}] category number, subcategory decimal digit */ - | unicode_escape_sequence /* only escapes for category Nd allowed */ - ; - -formatting_character - : /* [\p{Cf}] category Other, subcategory format. */ - | unicode_escape_sequence /* only escapes for category Cf allowed */ - ; - -keyword - : 'as' - | 'base' - | 'bool' - | 'break' - | 'byte' - | 'case' - | 'catch' - | 'char' - | 'checked' - | 'class' - | 'continue' - | 'decimal' - | 'default' - | 'delegate' - | 'do' - | 'double' - | 'else' - | 'enum' - | 'event' - | 'explicit' - | 'false' - | 'finally' - | 'float' - | 'for' - | 'foreach' - | 'goto' - | 'if' - | 'implicit' - | 'in' - | 'int' - | 'interface' - | 'is' - | 'lock' - | 'long' - | 'namespace' - | 'null' - | 'object' - | 'operator' - | 'out' - | 'params' - | 'return' - | 'sbyte' - | 'short' - | 'sizeof' - | 'stackalloc' - | 'string' - | 'struct' - | 'switch' - | 'this' - | 'throw' - | 'true' - | 'try' - | 'typeof' - | 'uint' - | 'ulong' - | 'unchecked' - | 'ushort' - | 'using' - | 'void' - | 'while' - | '__arglist' - | '__makeref' - | '__reftype' - | '__refvalue' - | modifier - ; - -numeric_literal_token - : integer_literal_token - | real_literal_token - ; - -integer_literal_token - : decimal_integer_literal_token - | hexadecimal_integer_literal_token - ; - -decimal_integer_literal_token - : decimal_digit+ integer_type_suffix? - ; - -decimal_digit - : '0' - | '1' - | '2' - | '3' - | '4' - | '5' - | '6' - | '7' - | '8' - | '9' - ; - -integer_type_suffix - : 'L' - | 'l' - | 'LU' - | 'lU' - | 'Lu' - | 'lu' - | 'U' - | 'u' - | 'UL' - | 'uL' - | 'Ul' - | 'ul' - ; - -hexadecimal_integer_literal_token - : ('0x' | '0X') hexadecimal_digit+ integer_type_suffix? - ; - -hexadecimal_digit - : 'A' - | 'a' - | 'B' - | 'b' - | 'C' - | 'c' - | 'D' - | 'd' - | 'E' - | 'e' - | 'F' - | 'f' - | decimal_digit - ; - -real_literal_token - : '.' decimal_digit+ exponent_part? real_type_suffix? - | decimal_digit+ '.' decimal_digit+ exponent_part? real_type_suffix? - | decimal_digit+ exponent_part real_type_suffix? - | decimal_digit+ real_type_suffix - ; - -exponent_part - : ('E' | 'e') ('+' | '-')? decimal_digit+ - ; - -real_type_suffix - : 'D' - | 'd' - | 'F' - | 'f' - | 'M' - | 'm' - ; - -character_literal_token - : '\'' character '\'' - ; - -character - : hexadecimal_escape_sequence - | simple_escape_sequence - | single_character - | unicode_escape_sequence - ; - -hexadecimal_escape_sequence - : '\\x' hexadecimal_digit hexadecimal_digit? hexadecimal_digit? hexadecimal_digit? - ; - -simple_escape_sequence - : '\\"' - | '\\0' - | '\\a' - | '\\b' - | '\\f' - | '\\n' - | '\\r' - | '\\t' - | '\\v' - | '\\\'' - | '\\\\' - ; - -single_character - : /* ~['\\\u000D\u000A\u0085\u2028\u2029] anything but ', \\, and new_line_character */ - ; - -unicode_escape_sequence - : '\\u' hexadecimal_digit hexadecimal_digit hexadecimal_digit hexadecimal_digit - | '\\U' hexadecimal_digit hexadecimal_digit hexadecimal_digit hexadecimal_digit hexadecimal_digit hexadecimal_digit hexadecimal_digit hexadecimal_digit - ; - -string_literal_token - : regular_string_literal_token - | verbatim_string_literal_token - ; - -regular_string_literal_token - : '"' regular_string_literal_character* '"' - ; - -regular_string_literal_character - : hexadecimal_escape_sequence - | simple_escape_sequence - | single_regular_string_literal_character - | unicode_escape_sequence - ; - -single_regular_string_literal_character - : /* ~["\\\u000D\u000A\u0085\u2028\u2029] anything but ", \, and new_line_character */ - ; - -verbatim_string_literal_token - : '@"' verbatim_string_literal_character* '"' - ; - -verbatim_string_literal_character - : quote_escape_sequence - | single_verbatim_string_literal_character - ; - -quote_escape_sequence - : '""' - ; - -single_verbatim_string_literal_character - : /* anything but quotation mark (U+0022) */ - ; - -operator_token - : '!' - | '!=' - | '%' - | '%=' - | '&&' - | '&' - | '&=' - | '*' - | '*=' - | '+' - | '++' - | '+=' - | '-' - | '--' - | '-=' - | '/' - | '/=' - | '<' - | '<<' - | '<<=' - | '<=' - | '=' - | '==' - | '>' - | '>=' - | '>>' - | '>>=' - | '>>>' - | '>>>=' - | '??' - | '??=' - | 'as' - | 'is' - | '^' - | '^=' - | '|' - | '|=' - | '||' - | '~' - ; - -punctuation_token - : '"' - | '#' - | '(' - | ')' - | ',' - | '->' - | '.' - | '..' - | '/>' - | ':' - | '::' - | ';' - | '' - | '?' - | '[' - | '\'' - | '\\' - | ']' - | '{' - | '}' - ; - -base_argument_list - : argument_list - | bracketed_argument_list - ; - -base_cref_parameter_list - : cref_bracketed_parameter_list - | cref_parameter_list - ; - -base_parameter_list - : bracketed_parameter_list - | parameter_list - ; - -base_parameter - : function_pointer_parameter - | parameter - ; - -expression_or_pattern - : expression - | pattern - ; - -interpolated_string_text_token - : /* see lexical specification */ - ; - -multi_line_raw_string_literal_token - : /* see lexical specification */ - ; - -single_line_raw_string_literal_token - : /* see lexical specification */ - ; - -xml_text_literal_token - : /* see lexical specification */ - ; diff --git a/crates/mehen-csharp-parser/grammar/PROVENANCE.md b/crates/mehen-csharp-parser/grammar/PROVENANCE.md deleted file mode 100644 index 1bf1e908..00000000 --- a/crates/mehen-csharp-parser/grammar/PROVENANCE.md +++ /dev/null @@ -1,720 +0,0 @@ -# C# ANTLR grammar — provenance - -The **source of truth** is the single vendored file `CSharp.Generated.g4`, taken -verbatim from `dotnet/roslyn`. Everything else in this directory is either input -to the transform or produced by it: - -| File | Role | -|---|---| -| `CSharp.Generated.g4` | vendored upstream grammar (see Source) | -| `lexer-tokens.g4.in` | hand-written lexer rules — Roslyn publishes no lexer | -| `lexer-members.g4.in` | the lexer's `@lexer::members` state; separate because ANTLR requires named actions in the header, before any rule | -| `prepare-grammar.py` | the transform; a step of parser generation | -| `CSharpLexer.g4`, `CSharpParser.g4`, `patterns.toml` | **derived** into a process-local scratch dir, gitignored here | - -`cargo run -p xtask -- antlr generate csharp` runs the transform and then the -workspace-pinned `antlr-rust-codegen` library, writing the Rust modules in -`../src/generated/`. The transform needs [`uv`](https://docs.astral.sh/uv/); -the script's PEP 723 block pins the interpreter. - -The derived pair goes to a **process-local scratch directory**, and the generator -runs there — not in this tree. Two xtask invocations in one checkout (a developer -alongside CI, say) would otherwise each truncate and rewrite the same derived files -while the other's generator was reading them. To inspect the derived grammar, build -xtask and pass that executable to the script's reachability callback: -`cargo build -p xtask`, then -`uv run prepare-grammar.py CSharp.Generated.g4 --out-dir . --xtask ../../../target/debug/xtask`. - -## Source - -| Field | Value | -|---|---| -| Upstream | [`dotnet/roslyn`](https://github.com/dotnet/roslyn) — the C# compiler itself | -| Path | `src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4` | -| Branch | `main` | -| Repo revision | `c9f12709e0cd477febd54d1a5b5e3e3731a1ada2` (2026-07-31) | -| File last changed | `76234ec6a1ba46f05b8b07dbeaeb7e39c5054810` (2026-06-24) | - -The grammar is machine-generated from `Syntax.xml`, the same model that generates -the compiler's own syntax nodes, so it tracks **C# as implemented** — records, -`is not`, `and`/`or`/relational patterns, list patterns, collection expressions, -raw strings, primary constructors, `required` members. No community grammar does. - -It is also a *reference* grammar rather than a working parser, which is what -`prepare-grammar.py` exists to fix; the transform's repairs are catalogued below. - -### Why not `antlr/grammars-v4` - -This crate previously vendored `csharp/v7/{CSharpLexer,CSharpParser}.g4` from -`antlr/grammars-v4`. It is a genuine C# 7-era grammar, so mainstream post-7 -syntax simply does not parse — `switch` expressions, `is not`, `and`/`or` -patterns, and `record` declarations all fail, and C# 9 pattern syntax appears -throughout modern .NET. On the 322-file `System.Text.Json` corpus it parsed 93 -files cleanly versus 318 for the derived Roslyn grammar. - -Upstream's `csharp/v8-spec` is not the answer either: it stops at C# 8, so it -still lacks the C# 9 patterns that cause most failures, and its `superClass` -surface is ~35 helpers including a **symbol-table-driven scope stack** -(`EnterTypeScope`, `IsClassTypeName`, `IsTypeParameterName`, …). Those resolve -identifiers against declarations seen so far, so porting them means implementing -a semantic model rather than lookahead checks — and mehen's `--sem-unknown error` -policy requires every one to be exact or generation fails. - -Note also that the grammar is **permissive by design** — it models Roslyn's -syntax nodes (including error-recovery nodes such as `incomplete_member`), not -the exact accepted language — and it encodes **no operator precedence**, since -real C# precedence lives in Roslyn's hand-written parser. Neither matters for -mehen's token-level metrics, but both would matter for a validating parser. - -## What the transform repairs - -Roslyn's grammar needs mutual (indirect) left recursion, which ANTLR rejects and -runtime 0.21.0 accepts via hub inlining (upstream #221). Beyond that, measured on -322 files of `dotnet/runtime`'s `System.Text.Json` (`src/`, `main` branch): - -| | clean | notes | -|---|---|---| -| `grammars-v4` C# 7 (previous) | 93 | C# 8+ syntax unsupported | -| Roslyn, first working prep | 115 | interpolated strings failed | -| Roslyn, current prep | **317 / 322** | 5 with diagnostics, no crashes or timeouts | - -Measured end to end through `mehen metrics`, not just the parser: ~179 s for the -corpus. All 5 remaining files are the directive-split-expression case below. - -Note that a "clean" corpus count measures *parseability*, not correctness — this -grammar has now produced **twenty-seven** distinct silent misparses: structurally wrong -trees with zero reported errors. Each was caught by a metric test or a parse-tree -dump, never by an error count. - -| silent misparse | what the tree said instead | -|---|---| -| `declaration_expression` listed before `invocation_expression` | every method call was a declaration | -| bodiless members required a body | `void M();` fell through to `global_statement` | -| `parameter`'s elements all optional | `Zero()` had one empty parameter | -| `parameter`'s `type?` matches a tuple | `(a, b) => …` was a *simple* lambda | -| `SL_RAW_STRING_LIT` fenced with `""` | `var a = ""; f(); var b = "";` was ONE string token | -| one raw *interpolation* mode for every dollar width | `$$"""{{a && b}}"""` read its hole as escaped text — the expression vanished | -| …and for every *fence* width | `$""""a"""b""""` closed at the embedded triple, leaving the tail as stray code | -| `Escape` accepted any character after `\` | `'\q'` — not valid C# — lexed as an ordinary literal, so invalid source read as a clean analysis | -| …and so did the *interpolation* mode's own escape rule | `$\"\q\"` stayed clean after `\"\q\"` was rejected — the two spellings disagreed | -| the hex escape was unbounded | `'\x12345'` — five digits — lexed as one clean character literal | -| two independent integer suffix slots | `1uu`, `1LL`, `1uU` all lexed as ordinary integer literals | -| the hole close consumed one brace at every width | `$$"""{{v}}"""` left its second `}` as literal text, a phantom Halstead operand | -| …and so did the *format-clause* close | `$$"""{{n:D4}}"""` leaked the same brace after the non-format path was fixed | -| a digit separator could be trailing | `1_` — not valid C# — lexed as an ordinary integer literal | -| `INTERPOLATED_TEXT` absorbed line terminators | `$"ab"` was a clean parse where the plain `"ab"` is rejected | -| the `u8` suffix was dropped from the operand key | `"x"u8` and `"x"` — a span and a string — collapsed into ONE Halstead operand | -| `identifier_token` widened with `and`/`or`/`not` | `o is int and > 5` declared a variable named `and` | -| `constant_pattern` listed before `discard_pattern` | a `_ =>` arm is an expression, not the discard | -| …and before `var_pattern` | `var x =>` was a *constant* pattern, so `var_pattern` was unreachable — and an always-matching arm read as a decision | -| `base_method_declaration` listed before the type forms | `record R(int X);` was a *method* named `R` | -| …and the same for `union` | `union U { }` was a *method* named `U` (with members it parsed correctly, hiding it) | -| …and the same for `extension` | `extension(T x) { … }` was a *constructor* named `extension` (with a property member it parsed correctly, hiding it) | -| every element after `'extension'` optional | once hoisted, `extension M() { … }` grew a phantom empty extension space beside the method | -| `DIRECTIVE_LINE` was not quote-aware | `#line 1 "c:/a/*b*/c.cs"` ended at the `/*`, leaving `c.cs"` as visible tokens | -| `compilation_unit` did not end in `EOF` | `class C { } } } }` was a clean parse; the tail was never read | -| `incomplete_member` was reachable | `class C { int }` was a complete, error-free unit | -| `switch_statement`'s parens independently optional | `switch value { … }` parsed, though only the *expression* form is paren-free | -| a local generic declaration loses to the expression statement | `List l;` was the chained comparison `(List < int) > l` — two phantom ABC conditions in 119 of 322 corpus files (issue #218) | - -Ten *delete* code from the tree, nine *relabel* it, and eight accept -source that is not valid C# at all. Every shape is invisible to an error count, which is why the metric tests carry the load here -— see `crates/mehen-csharp/tests/lexer.rs`, whose assertions are all "did this -token span eat the statements after it". - -Seven of the twenty-seven share one root cause: **an alternative that is viable for the -wrong input because a contextual keyword is a legal identifier.** Roslyn resolves -each semantically — it knows whether `F` names a type, whether `and` resolves to a -declared name, whether `record` is a keyword here — and a syntax-only grammar has -only alternative order and token identity to work with. Which of those two tools -applies is not a matter of taste; see the `record` section below for a case where -order alone provably cannot do it. - -Three of those seven are the same `member_declaration` ordering hazard — `record`, -`union`, `extension` — and the last two are worth reading together, because each hid -behind the *test input* rather than behind the grammar. A `union` with members parses -correctly (a member body cannot follow a method signature), and an `extension` whose -member is a *property* parses correctly (a property is not a legal statement, so the -constructor path dies). Both had passing tests written against exactly the spelling -that works. The regression tests now assert against an equivalent *control* spelling -— an extension container must be indistinguishable from a `class` container — rather -than against a literal shape, so a test cannot sit on the one viable case again. - -**No runtime capability is missing.** Every failure traced to either the prep or -an upstream-generator blind spot, and each was fixable declaratively — every one of -the 21 semantic coordinates lowers to a SemIR pattern via the derived -`patterns.toml`, with **no hooks at all** (the parser crate has no `src/hooks.rs`; -even the interpolated-string brace bookkeeping lives in the grammar's own lexer -actions). The gaps are catalogued below; `prepare-grammar.py` is the single source -of the transform, so each is reproducible rather than hand-patched. - -Two of these were expensive to find, and both share a shape worth stating up -front: **the grammar generated cleanly and mis-parsed anyway.** Neither the -reserved-keyword nor the angle-bracket problem is visible in the grammar text — -they surface only by parsing real C# and comparing against the language. - -### Dead-rule pruning: analysis upstream, deletion in the prep - -Tokenizing Roslyn's lexical wrapper rules orphans 84 character-level helpers, and -they must be removed **before** literals are harvested — otherwise their -single-character literals become tokens that shadow `DEC_INT_LIT` and -`IDENTIFIER`, silently breaking every parse while generation stays clean. That -ordering is why the generator's own `--prune-unreachable` cannot do the job alone: -it runs inside codegen, after harvesting, so pruning there still emits the 78 junk -tokens (259 vs 181) and still mis-lexes. - -The split is therefore **analysis upstream, edit locally**. The prep no longer -walks the grammar itself; it calls xtask's private, structured reachability -query and deletes exactly the rules reported: - -```text -xtask antlr unreachable-rules .g4 --entry-rule compilation_unit -``` - -The helper selects structured `G4S078` diagnostics and reads each exact rule-name -byte span, so neither stderr nor human-readable diagnostic prose is an API. -The query needs no lexer and is iterated to a fixpoint because removing a rule -can orphan helpers only it called. - -This replaced a hand-rolled walker that scanned `\b[a-z_]\w*\b` over -comment-stripped text. Both produced byte-identical output on this grammar, but -the regex version could not distinguish a rule reference from a word inside an -action, a label, or an argument list — and it did produce a false positive -elsewhere (it wrongly called Kotlin's `script` unreachable). The generator walks -the real AST, so correctness now comes from one implementation rather than an -agreement between two. - -### Reserved vs. contextual keywords - -Roslyn spells every keyword as an inline literal, and the prep harvests those -literals into named tokens. That is correct for *reserved* keywords and wrong for -*contextual* ones: `var`, `record`, `from`, `get`, `and`, `required`, `_`, … are -ordinary identifiers wherever they have no special meaning, but a harvested token -wins the equal-length lexer match, so `var x = 1;` stopped parsing — `var` was -absent from the expected-token set entirely. - -The remedy is the standard ANTLR one, and the same shape `grammars-v4`'s C# -grammar uses: widen `identifier_token` to accept all 42 contextual keywords back. - -Two second-order lessons came out of this: - -- **The blast radius is much wider than the keyword.** `var` appears in most - idiomatic modern C#, so one wrong token classification presented as broken - support for raw strings, ranges, `using` declarations, and unbound generics - simultaneously. Seven probe failures had one cause. -- **`record_keyword` must *not* use the widened rule.** With - `record_keyword : {pred}? identifier_token`, `partial struct S { }` predicts - the record path (`record_keyword` = `partial`), and a predicate cannot prune a - path ANTLR has already committed to — it surfaces as a hard error. It uses bare - `IDENTIFIER` instead; `record` always lexes that way, so nothing is lost. - -And a third, found later: **widening has a blast radius of its own.** Making -`and`/`or`/`not` legal identifiers is right in general and wrong in exactly one -position. `single_variable_designation : identifier_token` sits inside -`declaration_pattern : type variable_designation`, so - -```csharp -o is int and > 5 -``` - -binds `and` as a *variable named `and`, of type `int`* — and the `> 5` is orphaned -along with the combinator. `binary_pattern` is listed first among `pattern`'s -alternatives and still loses, because by the time the ATN reaches that choice the -designation alternative is already viable. The prep therefore narrows that one rule -to the contextual set *minus* the three combinators (`COMBINATOR_KEYWORDS`). They -stay legal names everywhere else, and `o is int and` — a designation genuinely -named `and` — is not valid C# anyway, since the compiler reads it as a combinator -too. - -This is the mirror image of the `out _` gap below: there, a token that should have -been an identifier was not; here, tokens that should *not* be identifiers in one -position were. Both were invisible in the grammar text. - -### `out _` and unbounded error recovery - -`_` was initially excluded from the widening on the mistaken belief that it still -reached `IDENTIFIER`. It does not, so `F(out _)` could not parse — and the -consequences were far out of proportion to the gap. In `JsonObject.cs` a single -`out _` put the parser into error recovery, and recovery then accumulated -diagnostics without bound: **>4.29 × 10⁹** entries in the runtime's diagnostic -arena, **15.5 GB** peak RSS on a 406-line file, ending in either -`parser.rs:1847 diagnostic sequence arena fits in u32` or a stack overflow -depending on which resource ran out first. Fixing the one token removed all three -corpus crashes. - -### Angle brackets vs. shift operators - -The harvester minted `>>`, `>>>`, `>>=`, and `>>>=` as single tokens from -`binary_expression`, which made `List>` unparsable — the final `>>` -lexed as one right-shift token that `type_argument_list`'s `'>'` can never match. -Roslyn has no such problem because its published grammar encodes no operator -precedence at all (that lives in the hand-written parser). - -The prep emits only `'>'` and rebuilds the operators in the *parser* behind -`token_index_adjacent` adjacency predicates, exactly as the vendored C#7 grammar -does. `token_index_adjacent` compares only the last two consumed tokens, so a -three-piece operator carries the predicate at each junction. - -The cost lands on the *consumer*: C# now spells three unrelated things with `<`/`>` -and `mehen-csharp`'s walker has to tell them apart from the enclosing rule alone, -because the token stream cannot. - -| what it is | reaches the token scan as | how the walker knows | -|---|---|---| -| comparison `a < b` | `LT` / `GT` | default — counts | -| shift `a >> b` | two bare `GT` | `ChildHint::in_shift_operator` | -| generic `List` | `LT` … `GT` | `ChildHint::in_type_delimiter` | - -Both non-comparison cases were live bugs: a shift scored two ABC comparisons, and -every generic type scored two (`Dictionary>` scored four). The -generic case is the more damaging of the two, since generics appear in essentially -every real C# file. `mehen-csharp/tests/abc.rs` pins each direction, including that -a comparison *beside* a generic type still counts and that a type argument may still -contain a real comparison. - -### Optional type-body braces (performance) - -Roslyn writes every type body as `'{'? member_declaration* '}'?` — both braces -independently optional — because its parser builds a complete declaration node -even for unterminated source. That is right for a node model and pathological for -a parsing grammar: after each member, prediction must weigh "another member" -against "the type ended without a `}`", recursively outward. - -| members in one type | as-published | balanced pair | -|---|---|---| -| 32 | 2.28 s | 0.23 s | -| 64 | 6.55 s | 0.21 s | -| 128 | 22.54 s | **0.37 s** (61×) | - -Rewriting to `('{' member_declaration* '}')?` keeps what the optionality is for -(a body-less `record R(int X);`) and drops only the half-present case; verified -behaviour-identical on the brace-less forms and on nested types. - -### Smaller gaps - -- **Accessor bodies.** `accessor_declaration` had no bare `;` alternative, so - every auto-property (`{ get; set; }`) failed — 128 corpus files. -- **Parameter modifiers.** `ParameterSyntax.Modifiers` is an untyped - `SyntaxList` with no `` children, so the generator emitted - the declaration-modifier list, which lacks `out`, `in`, `params`, and `this`. -- **Auto-property initializers.** `Syntax.xml` wraps the property body in a - `` of `AccessorList` vs `(ExpressionBody | Initializer) Semicolon`. - That drives the `SyntaxFactory` overload set, not the parser: `{ get; } = true;` - is valid C# 6 and appears in 17 corpus files. The one case where the generator - transcribes the model faithfully and the *model* is stricter than the language. -- **Binary integer literals.** Roslyn's `integer_literal_token` lists only - decimal and hexadecimal; `0b1010` (C# 7.0) is absent. -- **Char-literal escapes.** A char literal holds exactly one character, so unlike - a string it has no closure to absorb a mis-sized escape — `'\ud800'` needs the - escape forms spelled out. -- **`incomplete_member` was reachable.** Roslyn's error-*recovery* node exists so the - compiler can build a tree for source being typed, where `public int` is a member the - author has not finished; Roslyn emits a diagnostic beside it, and the published - grammar carries only the node. So `class C { int }` parsed as a complete, error-free - compilation unit — which contradicts mehen's contract, where a clean parse is what - tells `mehen metrics` to exit 0. Dropping the alternative makes it a syntax error and - loses nothing legal: every real member form has its own rule. -- **The entry rule did not end in `EOF`.** Roslyn's parser reads a compilation unit - and leaves the caller to check the stream position, so its grammar does not anchor - `compilation_unit`. A syntax-only parser therefore stopped at the first token it - could not continue with and reported success on the prefix: `class C { } } } }` - was a clean parse with the stray braces never read. Anchoring makes the unconsumed - tail a syntax error. It has to run **after** pruning — the generator treats every - rule reaching `EOF` as an entry point, so anchoring first makes nothing - unreachable and the 84 orphaned helpers survive. -- **Verbatim interpolated strings.** `$@"…"` needs its own lexer mode: a - backslash is literal there and `""` is the escaped quote, so one text rule - cannot serve both flavours. Both prefix orders are legal (`$@"` and `@$"`) and - Roslyn spells only the first, so the second needs an explicit alternative. -- **Raw string fences are three quotes, in *both* forms.** The single- vs - multi-line distinction is whether the content holds a newline, not a shorter - fence — a `""` fence collides with the empty string literal and eats code (see - the silent-misparse table above). Rule order carries what a context-free rule - cannot express: the single-line form first, since both match a one-liner over the - same extent, while `~[\r\n]` structurally keeps it from claiming a multi-line one. -- **Interpolated raw strings** (`$"""a{x}b"""`) need a *third* text mode. Roslyn - spells the opening fence as three parser tokens (`DOLLAR+ TRIPLE_DQUOTE DQUOTE*`), - but the text between holes cannot be lexed in the default mode — the `a` comes - back as an `IDENTIFIER` — so both Roslyn start-token rules are retargeted at one - mode-pushing token. Quotes are literal content inside; only a run of three closes - the string. -- **Token names must not be index-derived.** The prep rejects the generator's - `OP_nnn` fallback because a literal's position shifts when any other literal is - added or removed, silently rebinding tokens that hand-written code names. The - same reasoning applies to *collision* suffixes: `U8` and `u8` both want `KW_U8`, - and disambiguating by index reintroduces exactly the instability the check exists - to prevent. The suffix is derived from the literal's own spelling instead - (`KW_U8` / `KW_U8_LOWER`). - -### Known remaining limitation: directive-split expressions - -All 5 files still reporting errors are the same class: a preprocessor directive -splitting a single expression. - -The fifth (`JsonDocument.Parse.cs`) only *became* visible when `incomplete_member` -was dropped: the directive splits a method's return type across `#if` branches, so -the parser sees two types where one belongs, and the first of them used to match as -an incomplete member. It was always this same limitation — the recovery node was -hiding it behind a clean parse. - -```csharp -if ( -#if NET9_0 - !dict.TryAdd(propertyName, value) -#else - !dict.TryAdd(propertyName, value, out int index) -#endif - ) -``` - -mehen deliberately routes directives to a channel without evaluating them, so -both branches reach the parser and cannot both be one expression. That is the -intended trade: evaluating `#if` would mean picking a symbol set, and metrics for -a subset of the code is worse than approximate metrics for all of it. - -### Roslyn's "omitted" syntax nodes - -Two rules are genuinely empty productions modelling a blank slot: -`omitted_type_argument` (the unbound generic `Dictionary<,>`) and -`omitted_array_size_expression` (the multi-dimensional `int[,]`). ANTLR forbids -an empty rule inside a closure, so the rules must go — but simply deleting their -alternatives **loses real syntax**: the `','` in -`'[' (expression (',' expression)*)? ']'` then has nothing to match on either -side, and `int[,]` / `Dictionary<,>` stop parsing. The prep instead makes the -list elements optional at the two use sites, which is exactly what an empty node -expressed there. `repro/roslyn-csharp-perf/fixtures/omitted-nodes.cs` is the -regression test; `run.sh` asserts it parses with zero errors. - -### The `record` contextual keyword - -Roslyn's `Syntax.xml` declares the record keyword as -``, and its grammar generator reads only -`` children of a ``. That is the **only** `` in the -whole file (versus 1018 plain ``), so it is the single field that hits the -blind spot: the published grammar has **no `'record'` literal at all** and falls -back to the catch-all `syntax_token`, which accepts every identifier, keyword, -literal, operator, and punctuation token. - -The cost was severe — `class` became viable as both `class_declaration` and -`record_declaration`, so full-context prediction carried the impossible record -path across every member boundary: - -| members in one class | as-published | record restored | -|---|---|---| -| 4 | 188 ms | 27 ms | -| 12 | 2 166 ms | 204 ms | -| 24 | 12 160 ms | **423 ms** | - -One real 953-line file (`JsonDocument.Parse.cs`) took **272 s**; the whole -library timed out past 600 s. Restoring the keyword brought that to -~3 m 50 s, and the balanced-brace fix above took it the rest of the way to the -~208 s / 5.1 s-worst-file figures at the top of this section. - -The prep restores it as a *contextual* keyword: the prep mints a real `KW_RECORD` -token so the lexer distinguishes the word, and then widens `identifier_token` with -it so `record` stays legal as an ordinary name (`int record = 1;`). - -Getting there took three attempts, and the two that failed are instructive because -each looked sufficient: - -1. **`record_keyword : {IsRecordKeyword()}? IDENTIFIER`** — a predicate on the token - text, lowered to a pure SemIR comparison. Fixes the performance collapse above and - is what shipped first. But `member_declaration`'s alternatives are alphabetical, so - `base_method_declaration` precedes the type forms, and `record` is a legal `type` — - so `record R(int X);` matched `method_declaration` with `record` as the return type - and `R` as the method name. Every positional record was a phantom method. -2. **Predicate + hoist `record_declaration` first.** Fixes records; breaks 29 corpus - files. Hoisting puts the record path on the *committed* path for an ordinary - property, so `T P { get => 1; set { } }` predicts `record_keyword` = `T` — and **a - predicate cannot prune a path ANTLR has already committed to**, so it surfaces as a - hard error rather than a silent rejection. This is the same wall the note in - `RECORD_KEYWORD_RULE` describes for `partial struct S { }`. -3. **A real token + the hoist.** Both halves are required and neither suffices: - without the token the hoist breaks properties; without the hoist `record` is still a - viable `type` (it has to be, to stay a legal name) and the phantom method returns. - With a real token, `T P { … }` cannot predict the record path at all, so the hoist - is safe. - -The residual trade is a method whose return type is a class *literally named* -`record`, which now reads as a record declaration. That is the only shape affected, -and `record` as a type name is vanishingly rare in real C#. - -The performance half was diagnosed by the antlr-rust-runtime team on -[`antlr-rust-runtime#248`](https://github.com/ophi-dev/antlr-rust-runtime/issues/248); -`repro/roslyn-csharp-perf/` at the repo root reproduces both variants. - -### The dollar width of a raw interpolated string - -`$$"""…"""` is not a longer `$"""…"""`: the **dollar count sets the brace width**, so with -two dollars a hole opens on `{{` and a lone `{` is literal text. C# 11 added that so -brace-heavy content — JSON, mustache templates — needs no escaping. - -The lexer had one raw-interpolation mode, whose `{{` rule read a doubled brace as escaped -text. So `$$"""{{a && b}}"""` swallowed its hole whole: `a && b` never reached the parser, -and its operators and complexity vanished with no diagnostic. `dotnet/runtime` writes -exactly this shape for embedded JSON (`$$"""{"k":{{v}}}"""`), which is both why it matters -and why it was missed — those files live under `tests/`, outside the `src/` corpus. - -One mode per width, longest-prefix first, mirroring how the raw-string *fence* widths are -enumerated in `SL_RAW_STRING_LIT`: the lowering DSL has no comparisons, so a stored width -could not be compared against anything. Two widths are covered, which is what real code -uses; a third is mechanical. - -The **fence** width is a second, independent axis, and the same shape: a four-quote -opening fence exists so an embedded `"""` is content, but a mode whose close accepts any -three-or-more run ends the string at that embedded triple and leaves the tail as stray -code. Only the close rule is fence-width-sensitive — text, quotes, braces, and holes -are all width-agnostic — so widths 3 and 4 each carry their own mode, per dollar width. -Four is the floor rather than eight as in `SL_RAW_STRING_LIT`, because a wider -interpolated fence is needed only when the *content* holds three or more consecutive -quotes; `dotnet/runtime` has none with even a four-quote fence. - -That one is a hard error rather than a silent misparse (8 diagnostics), but the metrics -around the failure are wrong too — LLOC 3 against 2 — so "it fails loudly" only went -half way. - -The width-2 text rule then needed care, and the first attempt was wrong in an instructive -way. Adding `{` to the text set let it match `{{a && b}}` entirely — 10 characters against -the hole rule's 2 — and **ANTLR takes the longest match, breaking only ties by order**, so -writing the hole rule first changed nothing and the hole was swallowed again. Splitting the -braces into their own single-character rules makes the decision length-based instead: `{{` -is two characters and `{` is one, so the hole wins whenever a doubled brace is present. -Nothing depends on rule order, which is what makes it hold. - -### A query with no body clauses - -`query_body : query_clause+ select_or_group_clause query_continuation?` demands at -least one clause between the `from` and the `select`/`group`. C# demands none — -ECMA-334 §12.20.3 spells it `query_body_clauses? select_or_group_clause …` — so the two -simplest queries the language has did not parse: - -| source | before | after | -|---|---|---| -| `from a in xs select a` | 2 diagnostics | clean | -| `from a in xs group a by a` | 4 | clean | -| `from a in xs where a == 1 select a` | clean | clean | - -Anything with a `where` / `orderby` / `let` / `join` in between parsed either way, which -is why this survived: every query in the corpus had one. Found while verifying an -unrelated review finding about the `join` clause, not by the corpus run. - -`Syntax.xml` models `QueryBodySyntax.Clauses` as a plain list, which can be empty, and -the generator renders a list as `+` — so this is a generator artifact of the same kind -as the dropped `record` contextual keyword rather than a deliberate restriction. -Widening to `*` is a pure relaxation: `query_clause+` is a subset of `query_clause*`, so -nothing that parsed before can stop. - -### `union` and `extension`: the same hazard, cheaper fixes - -Both are contextual keywords that Roslyn *does* spell as literals, so `KW_UNION` and -`KW_EXTENSION` already exist and only the hoist is needed — no minted token, none of -the three-attempt sequence above. But each collides with a different member form, and -the `extension` one is the worst of the three: - -| declaration | collides with | parsed as | -|---|---|---| -| `record R(int X);` | `method_declaration` | method `R` returning type `record` | -| `union U { }` | `method_declaration` | method `U` returning type `union` | -| `extension(T x) { … }` | `constructor_declaration` | **constructor** named `extension` | - -`constructor_declaration : attribute_list* modifier* identifier_token parameter_list -… block` is character-for-character an extension block's shape, so the members were -still counted — just attributed to a constructor that does not exist. Metrics were -byte-identical to the `E(T x) { … }` constructor spelling, which is why nothing looked -missing. - -Both survived longer than `record` for the same reason, and it is a lesson about test -inputs rather than about grammars: **each has a spelling that parses correctly, and -the existing test happened to use it.** A `union` *with members* forces the type path, -because a member body cannot follow a method signature. An `extension` whose member is -a *property* forces the type path too, because `constructor_declaration` requires a -`block` and only statements are legal inside one — `public int P => 1;` is not a -statement, so the constructor path dies. A *method* member is a legal -`local_function_statement`, so it keeps the constructor path viable end to end. - -These three are the *complete* set, not three patches to the same wall. Every other -`member_declaration` alternative either leads with a reserved word (`event`, -`namespace`, `enum`, `delegate` — never a legal identifier, so no collision is -possible) or is the method/property form being hoisted past. And of -`type_declaration`'s six alternatives, `class` / `interface` / `struct` are reserved; -only `record`, `union`, and `extension` lead with a contextual keyword. With all three -hoisted, the hazard is closed at this rule. - -Hoisting `extension` then exposed a second defect, because upstream leaves **every** -element after the keyword optional: - -```antlr -extension_block_declaration - : attribute_list* modifier* 'extension' type_parameter_list? parameter_list? - type_parameter_constraint_clause* '{'? member_declaration* '}'? ';'? -``` - -The bare token `extension` is therefore a complete extension block. Harmless while the -rule sat behind `base_method_declaration`; with priority, that zero-child match won -before `method_declaration` could take `extension` as a *return type*, so -`class C { extension M() { … } }` grew a phantom empty extension space beside the -correct method — again with no diagnostic. This is the same all-optional pathology as -the type-body braces, and the same fix: require the body -(`EXTENSION_BODY_REQUIRED`). Nothing legal is lost, because unlike every other type -form an extension block has no body-less spelling — `record R;` is valid C#, -`extension;` is not, since the receiver alone declares nothing. - -#### The residual trade, measured - -Hoisting settles an ambiguity by alternative *order*, so whichever order is chosen one -shape loses. All three keywords pay, and each pays somewhere different — worth knowing -which, since the earlier `record` section states the principle but not the map: - -| source | `extension` | `record` / `union` | -|---|---|---| -| `class KW { KW() { } }` | ctor → anonymous container | correct | -| `class C { KW M() { … } }` | correct (after the body fix) | method → a *class* named `M` | -| `class C { KW P { get; set; } }` | correct (after the body fix) | property → a *class* named `P` | -| field / parameter / local / type argument of type `KW` | correct | correct | - -So `extension` now has the *narrowest* trade of the three — one shape, an -initializer-less constructor in a type literally named `extension` — and the last two -rows are what the body fix bought: while the bare keyword was a complete extension -block, both grew a phantom space. `record` and `union` cannot be fixed the same way, -because their bodies must stay optional (`record R;` and `record R(int X);` are valid -C#, `extension;` is not). - -The remaining `extension` case is irreducible without semantics. A constructor -*initializer* does escape it — `: this(…)` is a token an extension block cannot accept, -so `extension() : this(1) { }` parses as the constructor it is — but the body cannot -disambiguate the initializer-less form, since `int x = 1;` is both a statement and a -field declaration (verified across an empty, statement, and member body: all three take -the extension path). What is left is "does `extension` name a type in scope", the -semantic question a syntax-only grammar cannot answer. - -`crates/mehen-csharp/tests/structure.rs` pins the whole table, non-colliding positions -included, so the trade stays deliberate. - -Two follow-ons in the walker, both invisible while the misparse stood: -`RULE_EXTENSION_BLOCK_DECLARATION` had to join the LLOC declaration allowlist (the -container row went uncounted), and `opens_type_like` already listed it — that arm had -simply been unreachable. - -### A local generic declaration vs. the expression statement - -The same alphabetical-order hazard one level down, in `statement` (issue #218). -Upstream lists `expression_statement` before `local_declaration_statement`, and a -generic type in *local declaration* position is viable as a chained comparison — -`List l;` reads as `(List < int) > l` — so ANTLR took the expression path with -zero errors. The `<` and `>` scored two phantom ABC conditions per generic local, and -Halstead saw the phantom expression structure (`n1=12 N1=14` against `n1=7 N1=7` for -the identical type as a field). The `ChildHint::in_type_delimiter` fix that settled -the field/parameter/return positions could not reach this one: it keys on the -enclosing `type_argument_list`, and here the tokens never entered one — a parse -problem, not a classification one. 119 of the 322 corpus files contain the shape, all -parsing cleanly, which is why it survived. - -The fix is the hoist alone (`STATEMENT_LOCAL_DECLARATION_ALT`), and unlike `record` -it needs no minted token, because the overlap is asymmetric: `variable_declarator` -*requires* a leading `identifier_token`, and no legal statement expression — ECMA-334 -§13.7 limits those to invocation, creation, assignment, increment/decrement, and -await — has an identifier after its type-viable prefix. `f(x)`, `x = 1`, `i++`, -`new T()` all kill the declaration path in prediction, so the expression alternative -still wins wherever it should. No predicate is involved, so the committed-path wall -from the `record` hoist does not apply. Measured both ways on the corpus: the same 5 -directive-split files error either way, and all 153 files whose metrics moved moved -in the correcting direction — conditions, cognitive, and cyclomatic down; the few -`n1`/`N2` upticks are true recategorizations (`uint union = …`, whose old parse the -`union` keyword had bent further). - -The hoist also settled two neighbours for free: `Span s = stackalloc int[4];` -(the finding that led here) and `string? s = null;`, whose nullable `?` scored a -phantom condition through the same wrong path. - -The residual trade is `await t;` with a *bare identifier* operand — genuinely -ambiguous C# that Roslyn resolves by asking whether the enclosing method is async, -which a syntax-only grammar cannot. It now parses as a declaration of `t` with type -`await`, exactly as `T t;` would. Qualified and call operands (`await x.M()`, -`await F()`), which is what real awaits overwhelmingly are, keep the expression path -— the corpus run confirmed zero diagnostic changes. An *indexed* operand -(`await tasks[i];`) would have been a second trade — `tasks[i]` matches the -declarator's optional `bracketed_argument_list` — but that one closes for free by -mirroring ECMA-334, which gives locals their own bracket-less declarator (§13.6.2): -the bracketed form is the fixed-size-buffer declarator (§23.8.2), a struct-field-only -construct. The prep therefore points `local_declaration_statement` at a minted -`local_variable_declaration` / `local_variable_declarator` pair with no bracket -alternative, so the indexed await stays an expression while `fixed int data[4];` -keeps its shape in field position — measured on the corpus, the split changed -nothing at all. `mehen-csharp-parser/tests/hooks.rs` -pins both directions of the order, and `mehen-csharp/tests/{abc,loc}.rs` pin the -metrics against the `var`, field, and `int` control spellings. - -## Semantic helpers — no hooks anywhere - -The vendored grammar is **unmodified** — every repair above is applied by -`prepare-grammar.py` on the way to the derived pair, never by editing -`CSharp.Generated.g4`. - -Roslyn's grammar declares no `superClass` and calls no host-language helpers (it -is generated from a syntax model, not hand-written for a parser generator), so -unlike the `grammars-v4` grammar there is no base class to port. The one semantic -surface the derived *parser* uses is introduced by the transform and lowers to -**pure SemIR patterns** in the derived `patterns.toml` — no parser hook object -exists: - -- `IsRightShift` and friends — the angle-bracket adjacency checks - (`token_index_adjacent`). - -(The `record` contextual keyword was a second one, `IsRecordKeyword`, until the -predicate proved unable to carry it; see the section above. It is now a real -`KW_RECORD` token, so the helper is gone.) - -The **lexer** is hand-written, because Roslyn publishes none — but its state -lives in the grammar too, in `@lexer::members`, and lowers through the same -`patterns.toml`. A `}` cannot know from the grammar alone whether it closes an -interpolation hole or a nested block: - -```csharp -$"a{ new[]{ 1, 2 }.Length }b" -// ^^^^^^^^^ must NOT end the hole -``` - -Telling them apart needs a brace depth per open hole and a *conditional* mode pop -— and SemIR has no conditional and no mode-changing action (its seven statements -all touch member state). The grammar therefore splits the `}` into two -predicate-gated rules over the same character, each carrying its own -*unconditional* command, so **rule selection** supplies the condition: - -```antlr -INTERP_NESTED_CLOSE : {nestDepth > 0}? '}' { nestDepth--; } -INTERP_HOLE_CLOSE : {holeStack.Count > 0}? '}' -> popMode -``` - -Order is load-bearing in two ways. Between those rules, the lowering DSL has only -`not` and truthiness — no comparisons, no `&&` — so the deeper case must come -first: reaching the second rule already proves `nestDepth == 0`. And both must -precede the unguarded `RBRACE` fallback, which is why `prepare-grammar.py` keeps -`{`, `}` and `:` out of the harvested literals block (`HOLE_SENSITIVE_LITERALS`) -and lets the hand-written file define them. - -Stack-valued member state is runtime 0.20.1+, from -[`antlr-rust-runtime#206`](https://github.com/ophi-dev/antlr-rust-runtime/issues/206) — -filed for exactly this grammar shape. - -Generation runs with `--sem-unknown error --require-full-semantics`, so any *new* -helper appearing in a future grammar update fails `cargo xtask antlr generate -csharp` instead of silently degrading parse fidelity. `tests/hooks.rs` pins the -observable consequences — nested braces in holes, format clauses, verbatim -backslashes, and nested interpolated strings restoring the enclosing depth. - -## Toolchain - -| Tool | Version | Why | -|---|---|---| -| Rust runtime + codegen | [`ophi-dev/antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime) `v0.29.0` | Runtime plus xtask-linked codegen and structured reachability | -| [`uv`](https://docs.astral.sh/uv/) | any recent | Runs `prepare-grammar.py`; the script's PEP 723 block pins the interpreter | - -Unlike the other ANTLR targets, C# needs `uv`: its grammar is derived rather than -directly generatable. `xtask` probes for it and only errors on the C# target, so a -missing `uv` does not block Kotlin/Java regeneration. - -Regenerate with: - -```bash -cargo run -p xtask -- antlr generate csharp -``` diff --git a/crates/mehen-csharp-parser/grammar/lexer-members.g4.in b/crates/mehen-csharp-parser/grammar/lexer-members.g4.in deleted file mode 100644 index 0a0cf60a..00000000 --- a/crates/mehen-csharp-parser/grammar/lexer-members.g4.in +++ /dev/null @@ -1,30 +0,0 @@ -// Interpolated-string state. Kept in the grammar rather than a hand-written Rust -// hook so the lexer is self-describing; `prepare-grammar.py` emits matching -// `[[member]]` / `[[pattern]]` declarations into `patterns.toml`, which lower -// every body below to pure SemIR (runtime 0.20.1+, upstream #206). -// -// holeStack — one entry per interpolation hole currently open, holding the -// brace-nesting depth *within* that hole. Pushed when a hole opens, -// popped when it closes, so it survives nesting like -// `$"{ $"{x}" }"`. Its depth is nonzero exactly while inside a -// hole's expression. -// nestDepth — mirror of the innermost hole's depth, kept as a scalar because -// the pattern DSL can test a scalar's truthiness directly. -// -// Two slots rather than one because the lowering DSL has only `not` and -// truthiness — no comparisons and no `&&`. Each slot must therefore answer one -// yes/no question on its own, and the *conjunction* comes from rule order: the -// deeper case is written first, so reaching a later rule already implies the -// earlier predicate was false. -// wideStack — parallel to `holeStack`: one entry per open hole, nonzero when that -// hole was opened with a DOUBLED brace (`$$"""{{v}}"""`). Its close must -// then consume two braces, and a width-one hole's must consume one, so -// `$"{v}}}"` — close plus a literal brace — keeps working. A stack rather -// than a scalar for the same reason `holeStack` is one: the width travels -// with the hole, so `$$"""{{ $"{x}" }}"""` restores the outer width when -// the inner hole closes. -@lexer::members -{private int nestDepth; -private Stack holeStack = new Stack(); -private Stack wideStack = new Stack(); -} diff --git a/crates/mehen-csharp-parser/grammar/lexer-tokens.g4.in b/crates/mehen-csharp-parser/grammar/lexer-tokens.g4.in deleted file mode 100644 index adf70309..00000000 --- a/crates/mehen-csharp-parser/grammar/lexer-tokens.g4.in +++ /dev/null @@ -1,685 +0,0 @@ -// Lexer rules supplied for Roslyn's parser-only C# grammar, spliced verbatim -// into the generated `CSharpLexer.g4` by `prepare-roslyn-grammar.py`. -// -// Roslyn's `CSharp.Generated.g4` describes its terminals as character-level -// *parser* rules (`identifier_token : '@'? identifier_start_character …`, -// `decimal_digit : '0' | '1' | …`). Those cannot stay in the parser: single -// character tokens would shadow multi-character ones, so `'C'` beats -// `IDENTIFIER` and `'1'` beats a decimal literal. Each rule below replaces one -// such Roslyn rule, following the C# lexical grammar (ECMA-334 §6.4). -// -// This file is hand-written ANTLR (not generated), kept separate from the -// script so the ANTLR-level escaping is readable and reviewable as grammar -// source rather than as nested Python string escapes. -// -// The `TOKEN <-> roslyn_rule` mapping is declared in the script's -// LEXER_TOKEN_RULES table; adding a rule here requires adding it there too. - -// §6.4.3 Identifiers. `@` is the verbatim-identifier prefix; the character -// classes follow identifier_start_character / identifier_part_character. -IDENTIFIER - : '@'? ( [\p{L}\p{Nl}_] | UnicodeEscape ) - ( [\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}] | UnicodeEscape )* - ; - -// A Unicode escape is a legal identifier character in C#: `int \u0061 = 1;` declares -// `a`. Roslyn lists `unicode_escape_sequence` in both `identifier_start_character` and -// `identifier_part_character`, so tokenizing those rules has to carry it over — without -// it the backslash could not be consumed and the declaration reported two lexer -// diagnostics. -// -// Shared with the `Escape` fragment's `\u`/`\U` forms below, but kept separate: an -// identifier admits only the Unicode forms, not `\n` or `\x41`. -// -// KNOWN over-permissiveness, deliberately left: the DECODED codepoint is not validated -// against the identifier categories, so `int \u002B = 1;` — an escape decoding to `+`, -// which does not compile — lexes as an ordinary IDENTIFIER with no diagnostic. -// -// Not fixable here. A lexer rule matches *characters*, and `\u002B` is six of them; asking -// what they decode to needs arithmetic over the hex digits plus a Unicode category lookup. -// The lowering DSL has neither, the legal codepoints span hundreds of blocks so no -// character class enumerates them, and the alternative — dropping the escape from -// `IDENTIFIER` — would reject `int \u0061 = 1;`, which IS valid C#. Trading a false accept -// for a false reject is the worse deal, since mehen measures code a compiler already -// accepted (see PROVENANCE.md on rules made stricter than the language). -// -// A typed hook could do it, at the cost of this crate's zero-hook property and a Unicode -// table at lex time. Worth revisiting only if a real file ever depends on it. -fragment UnicodeEscape - : '\\' ( 'u' HexQuad | 'U' HexQuad HexQuad ) - ; - -// §6.4.5.3 Integer literals. `IntSuffix` below covers the legal suffix combinations. -// -// A digit separator may appear only BETWEEN digits (C# 7.0, §6.4.5.3), which is why the -// tail is `( '_'* [0-9] )*` rather than `[0-9_]*`: the character-class form let a literal -// end in one, so `1_` and `1__0` — neither valid C# — lexed as ordinary integer literals -// and the analyzer reported a clean parse of invalid source. Runs of separators between -// digits ARE legal (`1__0` is not, but `1_0` and `0x1_F` are, and C# permits `1___0` -// too), hence `'_'*` rather than `'_'?`. -// -// A LEADING separator is not a literal at all: `_1` is a legal *identifier*, and it still -// lexes as one — verified, since narrowing here must not steal it. -DEC_INT_LIT - : [0-9] ( '_'* [0-9] )* IntSuffix? - ; - -HEX_INT_LIT - : '0' [xX] [0-9a-fA-F] ( '_'* [0-9a-fA-F] )* IntSuffix? - ; - -BIN_INT_LIT - : '0' [bB] [01] ( '_'* [01] )* IntSuffix? - ; - -// §6.4.5.3 integer type suffixes. At most ONE unsigned marker and at most ONE long -// marker, in either order — `1u`, `1L`, `1ul`, `1LU`, `1Lu`, `1uL`. -// -// Two independent `[uUlL]?` slots was the earlier spelling and accepted combinations C# -// rejects: `1uu`, `1LL`, `1uU` all lexed as ordinary integer literals, so the analyzer -// reported a clean parse of invalid source. Enumerating the pairs is exact and needs no -// state. -fragment IntSuffix - : [uU] [lL]? - | [lL] [uU]? - ; - -// §6.4.5.5 Real literals — embedded dot, leading dot, exponent-only, and -// suffix-only forms. -REAL_LIT - : [0-9] [0-9_]* '.' [0-9] [0-9_]* ExponentPart? [fFdDmM]? - | '.' [0-9] [0-9_]* ExponentPart? [fFdDmM]? - | [0-9] [0-9_]* ExponentPart [fFdDmM]? - | [0-9] [0-9_]* [fFdDmM] - ; - -fragment ExponentPart - : [eE] [+-]? [0-9] [0-9_]* - ; - -// §6.4.5.6 Character literals. A char literal holds exactly one character, so -// unlike STRING_LIT below it has no closure to absorb a mis-sized escape: the -// escape forms have to be spelled out, or `'\ud800'` matches `\u` and then looks -// for the closing quote at `d`. -CHAR_LIT - : '\'' ( Escape | ~['\\\r\n] ) '\'' - ; - -// §6.4.5.6 escape sequences: simple, hex (`\xA` .. `\xABCD`), and unicode — four hex -// digits after `u`, eight after `U`. -// -// The simple set is ENUMERATED rather than written `| .`. The wildcard accepted any -// character after a backslash, so `'\q'` — which is not valid C# — lexed as an ordinary -// character literal and the analyzer reported a clean, complete analysis of invalid -// source. That is the wrong direction for a tool whose contract is that a clean parse -// means something. -// -// The set is exactly ECMA-334's: `\'` `\"` `\\` `\0` `\a` `\b` `\f` `\n` `\r` `\t` `\v`. -// -// The hex form takes ONE to FOUR digits, spelled out rather than `+`. An unbounded run -// swallowed `'\x12345'` — five digits, not valid C# — as one clean character literal. -// The bound also makes the token end where the language says it does, so a fifth hex -// character after a full escape is content rather than part of it. -fragment Escape - : '\\' ( 'u' HexQuad | 'U' HexQuad HexQuad - | 'x' [0-9a-fA-F] [0-9a-fA-F]? [0-9a-fA-F]? [0-9a-fA-F]? - | ['"\\0abfnrtv] ) - ; - -fragment HexQuad - : [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] - ; - -// §6.4.5.7 String literals. The `*` closure means a mis-sized escape still lexes -// (the remaining characters match the negated set), but spell the escapes anyway -// so the token boundary is right for `"\\"` and friends. -STRING_LIT - : '"' ( Escape | ~["\\\r\n] )* '"' - ; - -VERBATIM_STRING_LIT - : '@"' ( '""' | ~'"' )* '"' - ; - -// C# 11 raw string literals (§6.4.5.7). BOTH forms are fenced by *at least* -// three quotes — the single-/multi-line distinction is whether the content -// contains a newline, not a shorter fence. The real rule also requires the -// closing fence to be at least as long as the opening one — see the note on the -// rules below for how that is approximated. -// The fence-length rule needs one alternative per length, longest first. A single -// `'"""' '"'* … '"""' '"'*` rule cannot express "close on a run at least as long as -// the opening one": the non-greedy body stops at the *first* three-quote run, so -// `""""a"""b""""` — valid C#, and the reason longer fences exist — terminated early and -// left `b""""` as stray tokens. -// -// Enumerated three through eight. The real rule is unbounded — C# allows any fence -// length — and expressing that needs *state*: a member holding the opening run's width -// and a predicate comparing each candidate closer against it. Every alternative here is -// stateless, so the set has to be finite. -// -// Eight is the ceiling because each width covers embedding one fewer quote (a six-quote -// fence exists to embed `"""""`), and content with five consecutive quotes is already -// vanishingly rare — zero occurrences in the 322-file corpus, where the *deepest* fence -// used is three. Past eight the three-quote arm still matches and terminates early, -// which costs the literal's tail rather than the file: every metric touching a string -// literal reads only its extent. -// -// If a real file ever needs a ninth quote, add an arm rather than reaching for state — -// or file it, since at that point the state is probably worth it. -// -// Order is load-bearing twice over. Longest fence first, so a four-quote literal is not -// claimed by the three-quote rule. And within each length, the single-line form precedes -// the multi-line one — both match a one-liner over the same extent, and ANTLR breaks the -// tie by rule order, so SL must come first to reach -// `single_line_raw_string_literal_token`. A multi-line literal cannot match SL at all -// (`~[\r\n]` blocks the break) and falls through to ML. -// -// Do NOT relax any opening fence to `'""'`. An empty string is `""`, so a two-quote -// fence makes `var a = ""; f(); var b = "";` lex as ONE token spanning both empty -// strings: the intervening statements vanish from every metric with no diagnostic to -// show for it (a silently wrong tree, the failure mode PROVENANCE.md warns about). -SL_RAW_STRING_LIT - : '""""""""' ~[\r\n]*? '""""""""' '"'* - | '"""""""' ~[\r\n]*? '"""""""' '"'* - | '""""""' ~[\r\n]*? '""""""' '"'* - | '"""""' ~[\r\n]*? '"""""' '"'* - | '""""' ~[\r\n]*? '""""' '"'* - | '"""' ~[\r\n]*? '"""' '"'* - ; - -ML_RAW_STRING_LIT - : '""""""""' .*? '""""""""' '"'* - | '"""""""' .*? '"""""""' '"'* - | '""""""' .*? '""""""' '"'* - | '"""""' .*? '"""""' '"'* - | '""""' .*? '""""' '"'* - | '"""' .*? '"""' '"'* - ; - -// ---- trivia ------------------------------------------------------------- -// Comments go to a dedicated channel so the CLOC sweep can read them while the -// parser never sees them. Roslyn models trivia as syntax, so its grammar has no -// rules for these at all. -// A line comment ends at any C# *line terminator*, not just CR/LF. ECMA-334 §6.3.1 -// lists five: CR, LF, NEL (U+0085), LS (U+2028), PS (U+2029). Excluding only CR and LF -// let a comment swallow the rest of the file across one of the other three — a real -// loss, because the type grammar's optional braces then allow recovery, so the -// analysis completes with the swallowed members silently missing. -// -// `NewLine` is a fragment so the comment rules and WHITESPACES cannot drift apart. -fragment NewLine : [\r\n\u0085\u2028\u2029] ; - -SINGLE_LINE_DOC_COMMENT : '///' ~[\r\n\u0085\u2028\u2029]* -> channel(COMMENTS_CHANNEL) ; -DELIMITED_DOC_COMMENT : '/**' .*? '*/' -> channel(COMMENTS_CHANNEL) ; -SINGLE_LINE_COMMENT : '//' ~[\r\n\u0085\u2028\u2029]* -> channel(COMMENTS_CHANNEL) ; -DELIMITED_COMMENT : '/*' .*? '*/' -> channel(COMMENTS_CHANNEL) ; -WHITESPACES : ( [ \t\f] | NewLine )+ -> channel(HIDDEN) ; -BYTE_ORDER_MARK : '' -> skip ; - -// A preprocessor directive line. mehen does not evaluate `#if` — directives are -// routed to their own channel, so they are neither a comment nor a *logical* line for -// LOC (they are still a physical code row; see `collect_loc_tokens`), and an inactive -// region is parsed as ordinary code. -// -// The negated set excludes `/` so the token stops before a trailing comment: -// `#if DEBUG // explain why` must leave the `// explain why` for -// SINGLE_LINE_COMMENT, or the row records no CLOC at all. A `/` *within* the -// directive text is then matched by the second alternative, which requires the next -// character not to start a comment — so `#pragma warning disable CA1024 // note` -// splits correctly while a path-like `#line 1 "a/b.cs"` stays whole. -// -// The trailing group is for a payload that *ends* with a slash — `#region generated/` -// or `#warning path/`. Neither repetition alternative can take it (the first excludes -// `/`, the second needs a following character), so without it the token stopped short -// and the slash surfaced as a visible SLASH token, erroring on valid source. -// -// It requires a line terminator or EOF after the slash, so a bare `'/'?` will not do: -// that matched the first `/` of a trailing `//` comment, which put the comment's second -// slash on the directive channel and cost the row its CLOC. Lookahead by *consuming* the -// terminator is safe here because WHITESPACES would otherwise take it as hidden trivia — -// no token needs it. -// Every alternative excludes the full `NewLine` set, not just CR/LF: a directive -// ended by NEL / U+2028 / U+2029 otherwise consumed the separator *and everything -// after it* onto the directive channel — a whole file reported as zero declarations -// with zero diagnostics. -// -// The `DirectiveString` alternative makes the scan quote-aware, which the -// comment-marker split above cannot be on its own. Roslyn's `line_directive_trivia` -// and `load_directive_trivia` both accept a `string_literal_token`, so `//` and `/*` -// inside those quotes are string *content*: -// -// #line 1 "https://host/a.cs" -// ^^ not a comment -// -// Without the atom the scan stopped at that `//` and SINGLE_LINE_COMMENT took the -// rest, inflating CLOC by a phantom comment on a row that has none. `/*` was worse: -// DELIMITED_COMMENT ran to the next `*/`, so `#line 1 "c:/a/*b*/c.cs"` left `c.cs"` -// as visible tokens and reported two errors on valid source. -// -// `"` stays in the plain negated set as well as starting the atom, so the two paths -// overlap. That is what handles an *unpaired* quote \u2014 `#error say "hi` has no closing -// quote, so the atom cannot complete. ANTLR maximizes the match for the rule as a -// whole rather than committing to the first viable alternative, so the paired case -// takes the atom (a longer total match than stopping at the quote) while the unpaired -// case falls through to the single-character path and still consumes the whole row. -// Neither case needs a predicate. -DIRECTIVE_LINE - : '#' ( DirectiveString | ~[/\r\n\u0085\u2028\u2029] | '/' ~[/*\r\n\u0085\u2028\u2029] )* - ( '/' ( [\r\n\u0085\u2028\u2029] | EOF ) )? - -> channel(DIRECTIVE) - ; - -// A quoted run inside a directive, matched as one atom by DIRECTIVE_LINE. Excludes the -// line terminators as well as `"`: a directive cannot span rows, so an unclosed quote -// must not let the atom swallow the following line. -fragment DirectiveString : '"' ~["\r\n\u0085\u2028\u2029]* '"' ; - -// ---- interpolated strings ---------------------------------------------- -// Roslyn spells interpolated strings as -// -// interpolated_string_expression -// : '$"' interpolated_string_content* '"' -// | '$@"' interpolated_string_content* '"' ; -// interpolation : '{' expression … '}' ; -// -// The *text* between holes needs its own lexer mode: in the default mode a -// broad negated set would swallow ordinary code (an earlier flat-lexer attempt -// lexed `class C ` as one token that way). -// -// The state and every mode transition live in the grammar. The one genuinely -// hard decision is the `}` that closes a hole, which is lexically identical to -// the one closing a nested block: -// -// $"a{ new[]{ 1, 2 }.Length }b" -// ^^^^^^^^^ must NOT end the hole -// -// SemIR has no conditional and no mode-changing *action* (its statements only -// touch member state), so this cannot be one rule with an `if`. Instead the two -// meanings become two rules over the same character, each gated by a predicate -// on the brace depth and each carrying its own *unconditional* command. The -// lexer evaluates predicates during ATN simulation, so the rule choice does the -// work the missing conditional would: -// -// INTERP_NESTED_CLOSE : {nestDepth > 0}? '}' { nestDepth--; } -// INTERP_HOLE_CLOSE : {holeStack.Count > 0}? '}' -> popMode -// -// Stack-valued member state is runtime 0.20.1+ (upstream #206, filed for exactly -// this shape). -// -// Regular vs. verbatim needs no state: `$"` and `$@"` push *different* text -// modes, so the mode itself records the flavour. -// -// `prepare-grammar.py` rewrites the harvested `'$"'` / `'$@"'` literals to the -// named tokens below (INTERP_TOKEN_LITERALS). `LBRACE` / `RBRACE` / `DQUOTE` / -// `COLON` are harvested literals the script pins to those names -// (STABLE_TOKEN_NAMES) so the `type(…)` commands here stay valid — the default -// `OP_nnn` names are index-derived and shift whenever the literal set changes. -// The prefixes are order-insensitive in C# 11+: `$@"…"` and `@$"…"` are the same -// string, so both spellings push the verbatim text mode. (Roslyn's grammar spells -// only `'$@"'`, which is why the `@$` form needs an explicit alternative here.) -INTERP_START : '$"' -> pushMode(INTERPOLATION) ; -INTERP_VERBATIM_START : ( '$@"' | '@$"' ) -> pushMode(INTERPOLATION_VERBATIM) ; - -// C# 11 interpolated *raw* string (`$"""a{x}b"""`). Roslyn spells the opening -// fence as three parser tokens (`DOLLAR+ TRIPLE_DQUOTE DQUOTE*`), but the text -// between holes cannot be lexed in the default mode — `a` would come back as an -// IDENTIFIER — so this is one token that pushes a third text mode, and -// `prepare-grammar.py` retargets both Roslyn start-token rules at it. -// -// `$"""` is a longer match than `$"`, so it wins over INTERP_START regardless of -// rule order; it is placed here for readability. -// -// The DOLLAR COUNT sets the brace width: with `$$"""…"""`, a hole opens on `{{` and a -// single `{` is literal text — C# 11 chose this so JSON and other brace-heavy text needs -// no escaping. One rule per width, longest first, each pushing its own mode, exactly as -// the raw-string *fence* widths are enumerated in `SL_RAW_STRING_LIT` above and for the -// same reason: the DSL has no comparisons, so a stored width could not be compared -// against anything. -// -// Two widths are covered, which is what real code uses — `$$"""{"k":{{v}}}"""` is the -// motivating shape (embedding JSON), and `dotnet/runtime` uses `$$` and nothing deeper. -// A third width needs a third mode; that is mechanical, and the comment on -// `SL_RAW_STRING_LIT` says the same thing about a ninth quote. -// -// Longest first is load-bearing: `$$"""` must not be claimed by the one-dollar rule, -// which would leave a stray `$` and lex the hole braces as text. -// -// The FENCE width matters too, and independently. A four-quote opening fence exists so -// that an embedded `"""` is content: -// -// $""""a"""b"""" -// ^^^ content, not the close -// -// so a mode whose close rule accepts any three-or-more run ends the string early and -// leaves the tail as stray code. That is a hard error rather than a silent misparse (8 -// diagnostics), but the metrics around it are wrong too, so it still has to be right. -// -// Only the CLOSE rule is width-sensitive — text, quotes, braces, and holes are all -// width-agnostic — so each fence width needs its own mode carrying its own close. -// Widths 3 and 4 are covered per dollar width. Four is the documented floor here rather -// than eight as in `SL_RAW_STRING_LIT`: a wider fence is only needed when the *content* -// contains a run of three or more quotes, and `dotnet/runtime` has no interpolated raw -// string with a four-quote fence at all, let alone five. A fifth width is another mode, -// mechanically. -// -// Ordered longest-fence-first within each dollar width, for the same reason the dollar -// widths are: `$""""` must not be claimed by the three-quote rule, which would leave a -// stray quote as content and mis-detect the close. -INTERP_RAW_START_2_4 : '$$' '""""' -> type(INTERP_RAW_START), pushMode(INTERPOLATION_RAW_2_4) ; -INTERP_RAW_START_2 : '$$' '"""' -> type(INTERP_RAW_START), pushMode(INTERPOLATION_RAW_2) ; -INTERP_RAW_START_4 : '$' '""""' -> type(INTERP_RAW_START), pushMode(INTERPOLATION_RAW_4) ; -INTERP_RAW_START : '$' '"""' -> pushMode(INTERPOLATION_RAW) ; - -// ---- braces and `:` inside an interpolation hole ----------------------- -// `{`, `}` and `:` mean different things inside a hole, so this file defines them -// rather than letting the script harvest them into the literals block: ANTLR -// breaks an equal-length match by rule order, so the gated rules have to come -// first and the plain fallbacks last. (HOLE_SENSITIVE_LITERALS in the script -// keeps the harvester from emitting duplicates.) -// -// Order is load-bearing twice over. Between the gated rules, the DSL cannot -// express `inHole && depth == 0`, so the deeper case goes first: if `nestDepth` -// is nonzero we are certainly inside a hole, and reaching the next rule proves -// `nestDepth == 0`. And all of them precede the unguarded fallbacks, which are -// what ordinary code outside any hole matches. - -// Nested block/initializer brace — unwind one level, stay in the hole. -INTERP_NESTED_CLOSE - : {nestDepth > 0}? '}' { nestDepth--; } -> type(RBRACE) - ; - -// `(`/`[` inside a hole deepen the same counter the braces use, and their closers -// unwind it. `nestDepth` is not "brace depth" but "depth of any bracketing construct -// within this hole", because the only question it has to answer is whether a `:` is -// still part of the expression. -// -// Without this, `$"{(flag ? 1 : 2)}"` failed to parse: the ternary's `:` sits at brace -// depth 0, so INTERP_FORMAT_COLON claimed it as a format delimiter and `2)` became -// interpolation text. A dictionary initializer or an indexer inside a hole has the -// same shape. -// -// These are `type(…)`-mapped to the ordinary punctuation tokens, so the parser sees -// exactly what it would outside a hole. -INTERP_NESTED_LPAREN - : {holeStack.Count > 0}? '(' { nestDepth++; } -> type(LPAREN) - ; - -INTERP_NESTED_RPAREN - : {nestDepth > 0}? ')' { nestDepth--; } -> type(RPAREN) - ; - -INTERP_NESTED_LBRACKET - : {holeStack.Count > 0}? '[' { nestDepth++; } -> type(LBRACKET) - ; - -INTERP_NESTED_RBRACKET - : {nestDepth > 0}? ']' { nestDepth--; } -> type(RBRACKET) - ; - -// `nestDepth` is 0 here, so a hole is open and this `}` closes it. Popping -// `holeStack` restores the *enclosing* hole's depth, which matters for -// `$"{ $"{x}" }"`: the inner hole's count must not clobber the outer one's. -// -// TWO braces close a hole opened with two (`$$"""{{v}}"""`), so the doubled form comes -// first — a hole's delimiter width matches its opening `$` count. Both alternatives emit a -// single `RBRACE`, which is what the parser wants either way -// (`interpolation : LBRACE expression … RBRACE`). -// -// This close lives in the *default* mode, shared by every interpolation flavour, so it -// cannot consult the width — but it does not need to: the doubled alternative is only -// reachable when a `}}` is actually present, and in a width-one hole a `}}` is a close -// followed by a literal brace, where taking both would be wrong… -// -// …which is why the doubled form is gated on `nestDepth`-free hole state *and* ordered -// first: ANTLR takes the longest match, so `}}` wins wherever it appears directly at a -// hole's end. Measured on both widths afterwards: `$$"""{{v}}"""` now reports the same -// Halstead vocabulary as `$"{v}"` (it was one higher, a phantom `}` operand emitted as -// INTERPOLATED_TEXT by the width-two mode), and `$"{v}}}"` — close plus an escaped brace -// — is unchanged. -INTERP_HOLE_CLOSE_2 - : {wideStack.Peek() > 0}? '}}' - { nestDepth = holeStack.Pop(); wideStack.Pop(); } -> type(RBRACE), popMode - ; - -INTERP_HOLE_CLOSE - : {holeStack.Count > 0}? '}' - { nestDepth = holeStack.Pop(); wideStack.Pop(); } -> type(RBRACE), popMode - ; - -// An opening brace inside a hole deepens the count. -INTERP_NESTED_OPEN - : {holeStack.Count > 0}? '{' { nestDepth++; } -> type(LBRACE) - ; - -// `{x:D4}` — a `:` at depth 0 inside a hole starts the format specifier, so the -// rest of the hole is literal text. Guarded by `nestDepth` first for the same -// reason: a `:` at any deeper level belongs to a nested construct (a ternary, a -// dictionary initializer, a label) and must stay an ordinary `COLON`. -INTERP_NESTED_COLON - : {nestDepth > 0}? ':' -> type(COLON) - ; - -INTERP_FORMAT_COLON - : {holeStack.Count > 0}? ':' -> type(COLON), pushMode(INTERPOLATION_FORMAT) - ; - -// The unguarded fallbacks, reached only when every predicate above was false — -// i.e. ordinary code outside any interpolation hole. Their names are pinned by -// STABLE_TOKEN_NAMES so the `type(…)` commands above stay valid. -LBRACE : '{' ; -RBRACE : '}' ; -COLON : ':' ; -LPAREN : '(' ; -RPAREN : ')' ; -LBRACKET : '[' ; -RBRACKET : ']' ; - -mode INTERPOLATION; - -// `{{` / `}}` are escaped literal braces, not holes — first so they win the -// longest match over the single-brace rules below. -INTERP_ESCAPED_OPEN : '{{' -> type(INTERPOLATED_TEXT) ; -INTERP_ESCAPED_CLOSE : '}}' -> type(INTERPOLATED_TEXT) ; - -// Text between holes. A backslash starts an escape sequence, so `\"` does not -// end the string and must be consumed as a unit. -// -// The forms are the SAME enumerated set as an ordinary string literal's, reusing the -// `Escape` fragment: a regular interpolated string is a string, so `$"\q"` is no more -// valid than `"\q"`. This was `'\\' .` — any character — so the two spellings disagreed -// about the same invalid source once the ordinary literal was tightened. -INTERP_ESCAPE : Escape -> type(INTERPOLATED_TEXT) ; -// A regular interpolated string follows ordinary string-literal rules, so it cannot span -// source rows — the negated set therefore excludes the full `NewLine` set as well. -// Accepting a newline here made `$"ab"` a clean parse while the plain `"ab"` was -// correctly rejected, so the two spellings disagreed about the same invalid source. The -// verbatim and raw modes stay multi-line, which is what distinguishes them. -INTERPOLATED_TEXT : ~[{}"\\\r\n\u0085\u2028\u2029]+ ; - -// A hole opens: its expression is ordinary C#, so switch to the default mode and -// start counting braces for this hole. -INTERP_HOLE_OPEN : '{' { holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0; } -> type(LBRACE), pushMode(DEFAULT_MODE) ; - -// The string ends: drop this string's entry and leave the text mode. -INTERP_END : '"' -> type(DQUOTE), popMode ; - -// A *verbatim* interpolated string (`$@"…"`) has different lexical rules for the -// same syntax: a backslash is an ordinary character (no escape sequences) and a -// doubled `""` is the escaped quote. One text rule cannot serve both flavours, -// so `$@"` pushes this mode instead. (The grammars-v4 C# lexer splits the same -// two cases for the same reason.) Braces and holes behave identically, so these -// rules mirror the ones above and emit the same token types. -mode INTERPOLATION_VERBATIM; - -INTERP_V_ESCAPED_OPEN : '{{' -> type(INTERPOLATED_TEXT) ; -INTERP_V_ESCAPED_CLOSE : '}}' -> type(INTERPOLATED_TEXT) ; - -// `""` is a literal quote inside a verbatim string, so it must not end it. -INTERP_V_ESCAPED_QUOTE : '""' -> type(INTERPOLATED_TEXT) ; -INTERP_V_TEXT : ~[{}"]+ -> type(INTERPOLATED_TEXT) ; - -INTERP_V_HOLE_OPEN : '{' { holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0; } -> type(LBRACE), pushMode(DEFAULT_MODE) ; -INTERP_V_END : '"' -> type(DQUOTE), popMode ; - -// An interpolated *raw* string (`$"""…"""`) is a third flavour: a lone `"` is -// ordinary text (only a `"""` run closes the string) and there are no backslash -// escapes. Text and hole handling otherwise mirror the two modes above. -// -// The closing fence emits TRIPLE_DQUOTE because the parser spells the end as -// `interpolated_raw_string_end_token : TRIPLE_DQUOTE DQUOTE*`. -mode INTERPOLATION_RAW; - -INTERP_R_ESCAPED_OPEN : '{{' -> type(INTERPOLATED_TEXT) ; -INTERP_R_ESCAPED_CLOSE : '}}' -> type(INTERPOLATED_TEXT) ; - -// The fence first, so a `"""` run is never split into text quotes. -INTERP_R_END : '"""' '"'* -> type(TRIPLE_DQUOTE), popMode ; - -// One or two quotes are literal content inside a raw string; only a run of three -// closes it. Kept as its own rule so the negated text set can exclude `"` -// entirely and leave fence detection to the rule above. -INTERP_R_QUOTE : '"' '"'? -> type(INTERPOLATED_TEXT) ; -INTERP_R_TEXT : ~[{}"]+ -> type(INTERPOLATED_TEXT) ; - -INTERP_R_HOLE_OPEN : '{' { holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0; } -> type(LBRACE), pushMode(DEFAULT_MODE) ; - -// The `$$"""…"""` flavour: two dollars means a hole opens on `{{` and a *single* brace is -// literal text. Everything else — the fence, quote, and text handling — is identical to -// the width-1 mode above, so only the brace rules differ. -// -// Without this mode, `$$"""{{a && b}}"""` had its hole swallowed as literal text: the -// width-1 rules read `{{` as an escaped brace, so `a && b` never reached the parser and -// its operators and complexity vanished — with zero diagnostics, the shape -// PROVENANCE.md catalogues. -// -// The close is the ordinary `}` path in the default mode: a hole's `}}` arrives as -// INTERP_NESTED_CLOSE / INTERP_HOLE_CLOSE for the first brace, and the second is then -// matched here as text — which is why `INTERP_R2_TEXT` must accept a lone brace. -mode INTERPOLATION_RAW_2; - -// A hole opens on the doubled brace. First, so `{{` is never split by the text rule. -INTERP_R2_HOLE_OPEN - : '{{' { holeStack.Push(nestDepth); wideStack.Push(1); nestDepth = 0; } -> type(LBRACE), pushMode(DEFAULT_MODE) - ; - -// The fence, before the quote rule, so a `"""` run is never split into text quotes. -INTERP_R2_END : '"""' '"'* -> type(TRIPLE_DQUOTE), popMode ; - -INTERP_R2_QUOTE : '"' '"'? -> type(INTERPOLATED_TEXT) ; - -// A run of ordinary characters. Braces are deliberately EXCLUDED from this set even -// though a lone brace is literal text at this width — that is what the two -// single-character rules below are for. -// -// The reason is ANTLR's matching rule: it takes the longest match for the rule as a whole -// and breaks only *ties* by order. A text rule that could consume `{{a && b}}` (10 -// characters) therefore beats INTERP_R2_HOLE_OPEN's 2 no matter which is written first. -// That was the first attempt here and it swallowed the hole exactly as the width-1 mode -// did — the same shape as the `""` raw-string fence bug in PROVENANCE.md. -// -// Splitting the braces out makes the decision length-based instead: `{{` is 2 characters -// and `{` is 1, so the hole rule wins on length whenever a doubled brace is present, and -// the single-brace rule fires only when it is not. Nothing depends on rule order, which is -// what makes it robust. -INTERP_R2_TEXT : ~[{}"]+ -> type(INTERPOLATED_TEXT) ; - -// A brace that did not start a hole (`{`) or close one (`}`) is literal text. One -// character each, so INTERP_R2_HOLE_OPEN's two-character `{{` always outranks them. -// `}` needs no doubled form: a hole's `}}` is consumed in the default mode — the first -// brace by INTERP_HOLE_CLOSE, the second here as text. -INTERP_R2_LBRACE : '{' -> type(INTERPOLATED_TEXT) ; -INTERP_R2_RBRACE : '}' -> type(INTERPOLATED_TEXT) ; - -// A format specifier (`{x:D4}`) is a further mode: after the `:` that ends a -// hole's expression, the remaining text up to the closing `}` is literal format -// text, not C# code — `D4` must not lex as an identifier. (The grammars-v4 C# -// lexer has an INTERPOLATION_FORMAT mode for the same reason.) Entered from the -// default mode by the `:` rule below, at brace depth 0 inside a hole. -mode INTERPOLATION_FORMAT; - -// The format text, emitted as the same token the grammar's -// `interpolation_format_clause : ':' interpolated_string_text_token` expects. -// -// ONE token for the whole clause, not one per run: the parser rule takes a single -// `interpolated_string_text_token`, so splitting an escape into its own token makes -// the clause unparsable. Hence the alternation inside the `+` rather than separate -// rules. -// -// A custom numeric format can carry a quoted literal — `$"{n:0\"kg\"}"` is valid C# -// for "the number, then kg" — and this mode previously had no rule for `"` at all, so -// the backslash lexed as text and the following quote could not be consumed: errors on -// valid source. A *bare* `"` stays excluded, since that ends the enclosing string and -// letting the format text swallow it would run the token past the literal. -// -// Both escape spellings are accepted because the enclosing string decides which is -// legal (`\"` regular, `""` verbatim). Threading the flavour into this mode would be -// the precise answer, but the format text's *extent* is all any metric reads — LOC -// rows and one Halstead operand — so accepting both costs nothing here and cannot -// mis-lex valid code either way. -INTERP_FORMAT_TEXT - : ( '\\"' | '""' | '\\' | ~[}"\\] )+ -> type(INTERPOLATED_TEXT) - ; - -// The `}` that closes the hole. Two pops: this mode, then the hole's own -// DEFAULT_MODE, landing back in the enclosing interpolation text mode. -// -// It must also pop `holeStack`, exactly as INTERP_HOLE_CLOSE does — the hole is over -// either way, and the two rules differ only in whether a format clause was entered -// first. Leaving the entry behind leaked hole state into ordinary code: after -// `$"{n:D4}"`, `holeStack.Count > 0` stayed true, so the next `:` anywhere in the file -// (a ternary, a label, a base-type list) matched INTERP_FORMAT_COLON and pushed -// INTERPOLATION_FORMAT again, swallowing the rest of the line as format text. -// Two braces when the hole opened with two, exactly as INTERP_HOLE_CLOSE_2 above — -// gated on the same `wideStack` top, and ordered first for the same reason. Without -// this the format path left the second brace to the width-two mode, which called it -// literal text: `$$"""{{n:D4}}"""` carried a phantom `}` operand that -// `$"""{n:D4}"""` does not. -INTERP_FORMAT_END_2 - : {wideStack.Peek() > 0}? '}}' - { nestDepth = holeStack.Pop(); wideStack.Pop(); } -> type(RBRACE), popMode, popMode - ; - -INTERP_FORMAT_END - : '}' { nestDepth = holeStack.Pop(); wideStack.Pop(); } -> type(RBRACE), popMode, popMode - ; - -// ---- four-quote interpolated raw strings -------------------------------- -// The same two flavours with a FOUR-quote fence, which exists so that an embedded `"""` -// is content: `$""""a"""b""""`. Only the close rule differs from the three-quote modes -// above — text, quotes, braces, and holes are all fence-width-agnostic — but a mode -// cannot parameterize a single rule, so each width carries its own. -// -// The close requires four quotes, so a three-quote run inside is claimed by the quote / -// text rules and stays content. Its trailing `'"'*` absorbs a longer run for the same -// reason the three-quote close does: C# ends a raw string at the *first* run of at least -// the opening width, and any extra quotes belong to the token. -mode INTERPOLATION_RAW_4; - -INTERP_R4_ESCAPED_OPEN : '{{' -> type(INTERPOLATED_TEXT) ; -INTERP_R4_ESCAPED_CLOSE : '}}' -> type(INTERPOLATED_TEXT) ; - -INTERP_R4_END : '""""' '"'* -> type(TRIPLE_DQUOTE), popMode ; - -// One to THREE quotes are content at this width; only a run of four closes. The -// three-quote alternative is what the width-3 mode cannot express. -INTERP_R4_QUOTE : '"' '"'? '"'? -> type(INTERPOLATED_TEXT) ; -INTERP_R4_TEXT : ~[{}"]+ -> type(INTERPOLATED_TEXT) ; - -INTERP_R4_HOLE_OPEN - : '{' { holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0; } -> type(LBRACE), pushMode(DEFAULT_MODE) - ; - -// `$$""""…""""`: a four-quote fence AND the doubled-brace hole width. Braces are split -// into single-character rules for the same length-based reason as INTERPOLATION_RAW_2. -mode INTERPOLATION_RAW_2_4; - -INTERP_R24_HOLE_OPEN - : '{{' { holeStack.Push(nestDepth); wideStack.Push(1); nestDepth = 0; } -> type(LBRACE), pushMode(DEFAULT_MODE) - ; - -INTERP_R24_END : '""""' '"'* -> type(TRIPLE_DQUOTE), popMode ; - -INTERP_R24_QUOTE : '"' '"'? '"'? -> type(INTERPOLATED_TEXT) ; -INTERP_R24_TEXT : ~[{}"]+ -> type(INTERPOLATED_TEXT) ; -INTERP_R24_LBRACE : '{' -> type(INTERPOLATED_TEXT) ; -INTERP_R24_RBRACE : '}' -> type(INTERPOLATED_TEXT) ; diff --git a/crates/mehen-csharp-parser/grammar/prepare-grammar.py b/crates/mehen-csharp-parser/grammar/prepare-grammar.py deleted file mode 100644 index 8ce74bd9..00000000 --- a/crates/mehen-csharp-parser/grammar/prepare-grammar.py +++ /dev/null @@ -1,1688 +0,0 @@ -#!/usr/bin/env -S uv run --script -# /// script -# # A developer build step, not a shipped artifact, so the floor is simply a -# # currently-supported interpreter — 3.9 reached end of life in October 2025. -# # 3.12 matches the version CI already installs (.github/workflows/release.yml). -# # Unrelated to `pyproject.toml`'s `requires-python`, which governs who can -# # install the mehen CLI. Raising this floor costs nothing because `uv` fetches a -# # matching interpreter when the machine lacks one. -# requires-python = ">=3.12" -# dependencies = [] -# /// -"""Derive a generatable ANTLR grammar pair from Roslyn's published C# grammar. - -`dotnet/roslyn` publishes `CSharp.Generated.g4`, machine-generated from -`Syntax.xml` — the same model that generates the compiler's own syntax nodes. -It therefore tracks C# *as implemented*, which no community grammar does. But -it is a **reference** grammar, not a working parser. Three classes of problem -have to be repaired before it parses real C#: - -1. **ANTLR rejects it outright.** Two `/* epsilon */` rules model Roslyn's - *omitted* syntax nodes (the blank slots in `Foo<,>` / `new int[,]`), and four - `/* see lexical specification */` rules are token stubs. An empty rule inside - a closure is `error(153)`, which propagates to 23 errors across - `compilation_unit`, every type declaration, and the XML doc-comment rules. - `incomplete_member` and the XML trivia wrappers are all-optional, making - `member_declaration*` and friends nullable. - -2. **There is no lexer.** The grammar is parser-only: terminals are inline - literals plus character-level rules (`decimal_digit : '0' | '1' | …`, - `identifier_token : '@'? identifier_start_character …`). Those must move into - a real lexer, or single-character tokens shadow multi-character ones (`'C'` - beats `IDENTIFIER`, `'1'` beats a decimal literal). Two tokens are valid only - inside a lexer *mode*: interpolated-string text and XML doc-comment text. - -3. **It generates cleanly and still mis-parses.** The larger group, and the one - that cost the most to find: contextual keywords harvested into reserved - tokens (`var`, `record`, `_`, …), `>>` eating generic closers, accessor - bodies with no bare `;`, missing `out`/`in`/`params` parameter modifiers, - absent binary literals, and `` in `Syntax.xml` rendering stricter - than Roslyn's own hand-written parser. Each is catalogued with its measured - effect in `PROVENANCE.md`; none is detectable from the grammar text alone — - they surface only by parsing real C# and comparing against the language. - -A separate performance repair also lives here: Roslyn writes every type body as -`'{'? member_declaration* '}'?`, which makes prediction quadratic in members per -type (128 members: 22.5 s → 0.37 s once the braces are a balanced pair). - -This script is a **step of parser generation**, not a one-off: `cargo xtask antlr -generate csharp` runs it before the linked Rust code generator. Only the vendored -`CSharp.Generated.g4` is checked in; the `CSharpLexer.g4` / `CSharpParser.g4` pair -and `patterns.toml` it emits are gitignored build artifacts, so the upstream -grammar stays the single source of truth exactly as the raw `.g4` does for Kotlin -and Java. See `PROVENANCE.md` for the pinned revision and the full catalogue of -what the transform repairs and why. - -Interpolation additionally needs three lexer modes and brace-depth state, because -the `}` closing a hole is lexically identical to one closing a nested block. All of -it lives in the *grammar* — `@lexer::members` plus predicate-gated rules over the -same character — so the parser crate needs **no hooks at all**. That is deliberate: -mehen is the demonstrative consumer of antlr-rust-runtime, so pushing its -`--sem-patterns` lowering as far as it goes is the point, not a cost. - -Reachability is delegated, not reimplemented: the generator's `G4S078` analysis -walks the real grammar AST, so it distinguishes a rule reference from a word -inside an action, a label, or an argument list. xtask exposes that analysis to -this Python transform through a private `antlr unreachable-rules` helper backed -by structured codegen diagnostics — see `unreachable_rules`. - -Usage: - cargo build -p xtask - uv run prepare-grammar.py CSharp.Generated.g4 --out-dir . \ - --xtask ../../../target/debug/xtask - -Running it by hand is only for iterating on the transform. -""" - -import argparse -import re -import subprocess -import sys -import tempfile -from pathlib import Path - -# --------------------------------------------------------------------------- -# Rules whose bodies belong in a lexer, mapped to the token they become. -# -# Each entry replaces the parser rule's body with a single token reference and -# contributes one lexer rule. The lexer bodies are written to match the C# -# specification's lexical grammar (ECMA-334 §6.4) for the construct the Roslyn -# rule describes. -# --------------------------------------------------------------------------- -# Roslyn parser rule -> the lexer token that replaces its body. The token's -# ANTLR definition lives in `lexer-tokens.g4.in` (hand-written grammar source, -# spliced in verbatim below) so its escaping is readable as grammar rather than -# as nested Python string escapes. -LEXER_TOKEN_RULES: dict[str, str] = { - "identifier_token": "IDENTIFIER", - "decimal_integer_literal_token": "DEC_INT_LIT", - "hexadecimal_integer_literal_token": "HEX_INT_LIT", - "real_literal_token": "REAL_LIT", - "character_literal_token": "CHAR_LIT", - "regular_string_literal_token": "STRING_LIT", - "verbatim_string_literal_token": "VERBATIM_STRING_LIT", - "multi_line_raw_string_literal_token": "ML_RAW_STRING_LIT", - "single_line_raw_string_literal_token": "SL_RAW_STRING_LIT", - # Mode-scoped: only valid inside an interpolated string / XML doc comment. - "interpolated_string_text_token": "INTERPOLATED_TEXT", - "xml_text_literal_token": "XML_TEXT_LIT", -} - -# Hand-written ANTLR source spliced into the emitted lexer (see the file's own -# header for why it is kept out of this script). -LEXER_RULES_FILE = "lexer-tokens.g4.in" - -# The `@lexer::members` block holding interpolated-string state. Separate from the -# rules file because ANTLR requires named actions in the grammar *header*, before -# any rule, while the rules must follow the harvested literal tokens. -LEXER_MEMBERS_FILE = "lexer-members.g4.in" - -# The subset of LEXER_TOKEN_RULES whose tokens are produced from a lexer mode -# rather than the default mode, so they need a `tokens {}` declaration. -MODE_SCOPED_RULES = ("interpolated_string_text_token", "xml_text_literal_token") - -# Rules that are all-optional and so make their closure-using callers nullable. -# Each is tightened to require at least one element; the XML wrappers are `x*` over a -# nullable element. -# -# `incomplete_member` used to be listed here too — it is all-optional, so it matched -# the empty string. It is now removed from `member_declaration` outright (see -# INCOMPLETE_MEMBER_ALT) and pruned as unreachable, so there is nothing left to -# tighten. -NULLABILITY_FIXES = [ - ( - "xml_text\n : xml_text_literal_token*\n ;", - "xml_text\n : xml_text_literal_token+\n ;", - ), - ( - "documentation_comment_trivia\n : xml_node*\n ;", - "documentation_comment_trivia\n : xml_node+\n ;", - ), - ( - "skipped_tokens_trivia\n : syntax_token*\n ;", - "skipped_tokens_trivia\n : syntax_token+\n ;", - ), -] - -# Roslyn's grammar generator reads only `` children of a ``, not -# ``. `RecordDeclarationSyntax.Keyword` is declared as -# -# -# -# -# -# and it is the ONLY `` in all of `Syntax.xml` (versus 1018 -# plain ``), so it is the single field that hits that blind spot. The -# published grammar therefore contains no `'record'` literal at all and spells -# the keyword as the catch-all `syntax_token`, which accepts every identifier, -# keyword, literal, operator, and punctuation token. -# -# The cost is severe: `class` becomes viable as both `class_declaration` and -# `record_declaration`, so full-context prediction carries the impossible -# record path across every member boundary — ~quadratic in members per type -# (24 members took 13.5 s; one real 953-line file took 272 s). -# -# `record` is a *contextual* keyword — legal as an ordinary name (`int record = -# 1;`) — so it must NOT become a reserved token. (Reserving it silently -# mis-parses `record R(int X);` as two enum members plus a parenthesized -# expression, with zero reported errors.) Instead the declaration position is -# restricted to an identifier whose text is `record`, via a predicate that the -# pattern DSL lowers to a pure SemIR comparison — no hooks required. -RECORD_KEYWORD_TARGET = ( - "record_declaration\n : attribute_list* modifier* syntax_token" -) -RECORD_KEYWORD_REPLACEMENT = ( - "record_declaration\n : attribute_list* modifier* record_keyword" -) -RECORD_KEYWORD_RULE = """ - -// Contextual keyword. Roslyn's grammar never spells `record` as a literal at all — -// it carries the information in , which its -// grammar generator drops — so the prep mints a dedicated `KW_RECORD` token -// (RECORD_TOKEN_RULE) and `identifier_token` is widened with it, exactly as it is -// with every other contextual keyword. `record` therefore remains a legal name -// while the declaration position predicts on a token of its own. -// -// A dedicated token rather than `{IsRecordKeyword()}? IDENTIFIER`, which was the -// first approach and does work in isolation: a predicate cannot prune a path ANTLR -// has already *committed* to, and this rule sits at a position where several -// member forms overlap. With the predicate form, `record_declaration` had to stay -// after `base_method_declaration` among `member_declaration`'s alternatives — so -// `record R(int X);` matched `method_declaration` with `record` as the return type -// and parsed as a phantom method. Hoisting it instead put the record path on the -// committed path for an ordinary property (`T P { get => 1; set { } }` predicts -// `record_keyword` = `T`), and the predicate could not reject that either: it -// surfaced as a hard error on 29 corpus files. A real token removes the ambiguity -// at its source, so alternative order stops mattering. -record_keyword - : KW_RECORD - ; -""" - -# The lexer rule for the minted token, appended to the harvested keyword block so it -# precedes `IDENTIFIER` (ANTLR breaks an equal-length match by rule order, and the -# keyword tokens are emitted before the hand-written rules). -RECORD_TOKEN_RULE = "KW_RECORD : 'record' ;" - -# `record` must stay usable as an ordinary name, so the minted token joins the -# contextual set that widens `identifier_token`. Kept separate from the harvested -# literals because it is not one — nothing in Roslyn's grammar spells it. -RECORD_TOKEN_NAME = "KW_RECORD" - -# Interpolated strings need lexer modes, so the tokens that delimit them cannot -# be plain harvested literals. These literals are therefore NOT harvested; the -# parser is rewritten to reference the named, mode-switching tokens that -# `lexer-tokens.g4.in` defines instead. -# -# `'{'`, `'}'` and `':'` are NOT harvested as plain literals: each has a -# hole-sensitive meaning, so `lexer-tokens.g4.in` defines predicate-gated rules -# for them ahead of the plain fallbacks (see HOLE_SENSITIVE_LITERALS). All the -# brace-depth bookkeeping lives in the grammar's own lexer actions, so the parser -# crate needs no hooks at all. -INTERP_TOKEN_LITERALS = { - '$"': "INTERP_START", - '$@"': "INTERP_VERBATIM_START", -} - -# The two Roslyn rules for an interpolated *raw* string's opening fence. Roslyn -# spells each as three parser tokens (`DOLLAR+ TRIPLE_DQUOTE DQUOTE*`), but the -# text between holes needs its own lexer mode — in the default mode the `a` of -# `$"""a{x}"""` lexes as an IDENTIFIER — so both are retargeted at the single -# mode-pushing INTERP_RAW_START token. The single- and multi-line spellings are -# character-identical (they differ only in whether the content holds a newline), -# so one token serves both. -INTERP_RAW_START_RULES = ( - "interpolated_multi_line_raw_string_start_token", - "interpolated_single_line_raw_string_start_token", -) -INTERP_RAW_START_TOKEN = "INTERP_RAW_START" - -# Meaningful names for every operator and punctuation literal, replacing the -# index-based `OP_nnn` fallback. -# -# The fallback name is derived from a literal's position in a sorted list, so -# adding or removing *any* literal renumbers unrelated tokens. That is harmless -# inside the generated grammar, where names are only referenced by other -# generated text, but not for anything hand-written that has to name a token: -# `lexer-tokens.g4.in` uses `type(LBRACE)` commands, and `mehen-csharp`'s walker -# classifies metrics by token (`&&` for a cognitive boolean run, `++` for an ABC -# assignment, `?` for a conditional). Index names would silently rebind those on -# the next upstream grammar update — a metric regression with no compile error. -# -# Keyword literals need no entry: they are named from their own text -# (`KW_CLASS`), which is already stable. -# Literals whose meaning depends on whether the lexer is inside an interpolation -# hole, so `lexer-tokens.g4.in` defines them itself (gated rules first, then the -# plain fallback) rather than having them harvested into the literals block above -# the hand-written rules. See HOLE_SENSITIVE_LITERALS' use in step 6. -# -# `{`, `}` and `:` are the load-bearing three: a `}` may close a hole or a nested -# block, and a `:` may open a format clause or belong to the expression. -# -# `(`, `)`, `[`, `]` are here for the *depth counter* rather than for their own -# meaning. `nestDepth` has to track every bracketing construct inside a hole, not -# just braces, or a `:` inside one of them looks like it is at depth 0 — -# `$"{(flag ? 1 : 2)}"` then loses its ternary to the format clause. They still -# emit the ordinary tokens via `type(…)`, so the parser sees no difference. -HOLE_SENSITIVE_LITERALS = frozenset({"{", "}", ":", "(", ")", "[", "]"}) - -STABLE_TOKEN_NAMES = { - # Punctuation and delimiters. - "{": "LBRACE", - "}": "RBRACE", - "(": "LPAREN", - ")": "RPAREN", - "[": "LBRACKET", - "]": "RBRACKET", - '"': "DQUOTE", - ":": "COLON", - "::": "COLON_COLON", - ";": "SEMICOLON", - ",": "COMMA", - ".": "DOT", - "..": "DOT_DOT", - "#": "HASH", - "$": "DOLLAR", - "'''": "TRIPLE_QUOTE", - '"""': "TRIPLE_DQUOTE", - "\\'": "ESCAPED_QUOTE", - "\\\\": "ESCAPED_BACKSLASH", - # Arithmetic and bitwise. - "+": "PLUS", - "-": "MINUS", - "*": "STAR", - "/": "SLASH", - "%": "PERCENT", - "&": "AMP", - "|": "PIPE", - "^": "CARET", - "~": "TILDE", - "<<": "LT_LT", - # Comparison and logic. - "!": "BANG", - "<": "LT", - ">": "GT", - "<=": "LE", - ">=": "GE", - "==": "EQ_EQ", - "!=": "NE", - "&&": "AMP_AMP", - "||": "PIPE_PIPE", - # Assignment and increment. - "=": "EQ", - "+=": "PLUS_EQ", - "-=": "MINUS_EQ", - "*=": "STAR_EQ", - "/=": "SLASH_EQ", - "%=": "PERCENT_EQ", - "&=": "AMP_EQ", - "|=": "PIPE_EQ", - "^=": "CARET_EQ", - "<<=": "LT_LT_EQ", - "++": "PLUS_PLUS", - "--": "MINUS_MINUS", - # Null handling, lambda, and misc. - "?": "QUESTION", - "??": "QUESTION_QUESTION", - "??=": "QUESTION_QUESTION_EQ", - "=>": "ARROW", - "->": "MINUS_GT", - # XML doc-comment fragments Roslyn's grammar mentions. - "": "SLASH_GT", -} - -# Two more generator blind spots, in the same family as the `record` -# loss — information Roslyn's syntax model keeps in untyped or -# prose form that its grammar generator cannot see: -# -# 1. Accessor bodies. `AccessorDeclarationSyntax`'s Body / ExpressionBody / -# SemicolonToken are all optional per the model's own PropertyComments -# ("null if there are no braces", "the optional semicolon token"), but the -# emitted rule requires `(block | (arrow_expression_clause ';'))`. A bare -# `;` body — i.e. every auto-property `{ get; set; }`, C# 3-era syntax — -# cannot parse. This led 128 of the 210 corpus error files. -# -# 2. Parameter modifiers. `ParameterSyntax.Modifiers` is an untyped -# `SyntaxList` with no children, so the generator emits -# the fixed declaration-modifier list, which lacks `out`, `in`, `params`, -# and `this`. (`ref` parses only because it is also a declaration -# modifier.) `void M(out D d)` fails while `void M(ref D d)` passes. -# Added at the `parameter` rule, not the global `modifier` rule, so the -# parameter-only keywords cannot leak into type/member declarations. -# -# Applied on the pristine literal forms, before literal harvesting. -# `declaration_expression : type variable_designation` is listed eleven -# alternatives *before* `invocation_expression : expression argument_list`, and -# both match `F(x)` — `F` as a type with `(x)` a parenthesized designation, or -# `F` as an expression with `(x)` an argument list. ANTLR takes the first viable -# alternative, so **every method call in every position** parsed as a declaration -# expression, and with zero reported errors. -# -# Roslyn's own parser resolves this semantically (it knows whether `F` names a -# type); a syntax-only grammar cannot, so alternative order has to carry it. -# Moving the declaration form last makes the common case right while leaving it -# to win where nothing else fits — `F(out int x)` still parses as a declaration, -# because `out int x` is not argument-list shaped. -# -# Same family as the `record` loss: information the compiler -# holds outside the grammar, which the published grammar therefore drops. -DECLARATION_EXPRESSION_ALT = " | declaration_expression\n" - -# `incomplete_member : attribute_list* modifier* type` is Roslyn's error-*recovery* -# node: it exists so the compiler can build a syntax tree for source that is being -# typed, where `public int` is a member the author has not finished. Roslyn'"'"'s parser -# emits a diagnostic alongside it; the published grammar carries only the node. -# -# So a syntax-only parser accepts `class C { int }` as a complete, error-free -# compilation unit. That directly contradicts mehen'"'"'s diagnostic contract, where a -# clean parse is what tells `mehen metrics` to exit 0 and `mehen diff` to trust the -# numbers — broken source has to be *visible*. -# -# Dropping the alternative makes the same input a syntax error, which is the honest -# answer. Nothing legal is lost: every real member form has its own rule, and this one -# matches only a type with no declarator after it. -INCOMPLETE_MEMBER_ALT = " | incomplete_member\n" - -# The same ordering hazard one level up, in `member_declaration`. Its alternatives -# are alphabetical, so `base_method_declaration` precedes `base_type_declaration` — -# and `record` is a contextual keyword, hence a legal `type`. So -# -# record R(int X); -# -# the single most common record spelling, matches -# `method_declaration : … type … identifier_token … parameter_list … ';'` with -# `record` as the RETURN TYPE and `R` as the method name. ANTLR takes the first -# viable alternative, so every positional record parsed as a method — reported as a -# function space rather than a class, with no NPA/NPM/WMC container and no -# diagnostic. (`record class R { }` parsed correctly, which is why this survived: the -# explicit-kind form cannot match `method_declaration`.) -# -# This one needs BOTH halves, and each is useless alone: -# -# 1. A dedicated `KW_RECORD` token (RECORD_KEYWORD_RULE), so the record path is -# selected by a token rather than by a predicate over `IDENTIFIER`. Reordering -# alone does not work: with the predicate form, hoisting `record_declaration` -# ahead of `base_method_declaration` put the record path on the *committed* path -# for an ordinary property (`T P { get => 1; set { } }` predicts `record_keyword` -# = `T`), and a predicate cannot prune a committed path — 29 corpus files failed -# with hard errors. -# 2. Hoisting `record_declaration` ahead of `base_method_declaration`. The token -# alone does not work either, because `record` must stay a legal identifier and -# is therefore widened back into `identifier_token` — so it is still a viable -# `type`, and `method_declaration` still matches first. -# -# With the real token in place the hoist is safe: `T P { … }` no longer predicts the -# record path at all, because `T` is not `KW_RECORD`. -# `union_declaration` has the identical problem for the identical reason: `union` is -# also only contextual (widened back into `identifier_token`), so `union Result { }` -# matches `method_declaration` with `union` as the return type and `Result` as the -# name. It differs from `record` in one detail — a union WITH members forces the type -# path, because a member body cannot follow a method signature — so only the empty and -# semicolon forms mis-parsed, which is why it survived longer. -# -# `extension_block_declaration` (C# 14) is the third of the same shape, and the worst -# of them, because the collision is with `constructor_declaration` rather than -# `method_declaration`: -# -# constructor_declaration -# : attribute_list* modifier* identifier_token parameter_list … block -# -# is character-for-character the shape of `extension(string s) { … }`, so an extension -# block parsed as a *constructor named `extension`* — a function space holding the -# extension's members, with metrics identical to the `E(string s) { … }` constructor -# spelling and zero diagnostics. The members were still counted, so nothing looked -# missing; they were just attributed to a constructor that does not exist. -# -# Like `union`, this one needs only the hoist: Roslyn spells `extension` as a literal, -# so `KW_EXTENSION` is a real token already. -# -# All three are hoisted together, and they are exactly the complete set. Every one of -# `member_declaration`'s other alternatives either leads with a *reserved* word -# (`event`, `namespace`, `enum`, `delegate` — never a legal identifier, so no -# collision is possible) or is itself the method/property form being hoisted past. Of -# `type_declaration`'s six alternatives, `class` / `interface` / `struct` are reserved -# and only these three lead with a contextual keyword — so the hazard is closed here, -# not merely patched three times. -# -# `record_declaration` needed a real `KW_RECORD` token for its hoist to be safe (see -# RECORD_KEYWORD_RULE); `union_declaration` and `extension_block_declaration` already -# have real `KW_UNION` / `KW_EXTENSION` tokens, since Roslyn spells both of those -# keywords as literals. -HOISTED_TYPE_ALTS = ( - " | record_declaration\n", - " | union_declaration\n", - " | extension_block_declaration\n", -) -MEMBER_METHOD_ALT = " | base_method_declaration\n" - -# The pattern-combinator keywords (C# 9 `and` / `or` / `not`). Contextual, so -# widening `identifier_token` makes each a legal name — which is correct in general -# but wrong in one position: `single_variable_designation : identifier_token` sits -# inside `declaration_pattern : type variable_designation`, so `o is int and > 5` -# binds `and` as a *variable* named `and` declared of type `int`. The `> 5` is then -# orphaned and the combinator vanishes from the tree — the same silent-misparse shape -# as the `declaration_expression` ordering bug, and with zero reported errors. -# -# `binary_pattern` is listed FIRST among `pattern`'s alternatives, so ANTLR does try -# it before the declaration form. It loses anyway: the combinator only survives if -# `and` is not consumed as the designation, and by the time the ATN reaches that -# choice the designation alternative is already viable. -# -# Excluding the three from *this one rule* is the narrow fix. They stay legal -# identifiers everywhere else (a field or parameter named `and` still parses), and a -# variable genuinely named `and` in a declaration pattern — `o is int and` — is not -# valid C# anyway, since the compiler reads that as a combinator too. -COMBINATOR_KEYWORDS = ("and", "or", "not") - -# The `member_declaration` ordering hazard again, one level down in `pattern`: -# -# v switch { 1 => 1, var x => x } -# -# parsed `var x` as a **constant pattern**, and `var_pattern` was unreachable. -# Structurally wrong with zero diagnostics — and it also defeats the catch-all -# detection, since an unguarded `var x =>` always matches (a `var` pattern tests nothing) -# and so is the fall-through exactly as `_ =>` is, which the walker cannot recognize -# through a node that never appears. -# -# TWO alternatives have to be cleared, and the second was the surprise. Measured on the -# tree, `var x` came back as `constant_pattern` (rule 115), not `declaration_pattern`: -# -# - `constant_pattern : expression` is a catch-all listed *second*, and hub inlining folds -# the whole expression cycle into one rule — including `declaration_expression`, so -# `var x` is a viable "expression". This is the same catch-all-near-the-front shape as -# `incomplete_member`. -# - `declaration_pattern : type variable_designation` would take it next anyway, because -# `var` is a contextual keyword widened back into `identifier_token` and hence a viable -# `type`. -# -# Hoisting ahead of `constant_pattern` clears both. Only the hoist is needed, as with -# `union`/`extension`: `KW_VAR` is already a real token (Roslyn spells `var` as a literal -# here), so a genuine constant or `T x` pattern cannot predict the `var` path — neither -# starts with `KW_VAR`. `var` stays a legal identifier everywhere, since the widening is -# untouched. -VAR_PATTERN_ALT = " | var_pattern\n" -PATTERN_CONSTANT_ALT = " | constant_pattern\n" - -# The `member_declaration` ordering hazard yet again, this time in `statement`, -# whose alternatives are also alphabetical — so `expression_statement` precedes -# `local_declaration_statement`, and a generic type in *local declaration* -# position never reaches `type_argument_list` at all: -# -# List l; -# -# is viable as an expression statement — the chained comparison -# `(List < int) > l` — and ANTLR takes the first viable alternative. So every -# local whose type is generic parsed as an expression, its `<` and `>` scored as -# two phantom ABC conditions, and LLOC gained a line (issue #218). The -# `ChildHint::in_type_delimiter` fix from #212 cannot reach this: it keys on the -# enclosing `type_argument_list`, and here the tokens never enter one. The same -# type in field, parameter, or return position parsed correctly, which is why -# this survived — and all 119 corpus files containing the shape parse with zero -# diagnostics either way. -# -# Hoisting `local_declaration_statement` ahead of `expression_statement` is safe -# because a declaration's shape — `type declarator (',' declarator)* ';'`, with -# `variable_declarator` REQUIRING a leading `identifier_token` — is not viable -# for any legal statement expression (ECMA-334 §13.7 limits those to invocation, -# object creation, assignment, increment/decrement, and await): after `f(x)`, -# `x = 1`, `x++`, or `new T()` no identifier follows, so the declaration path -# dies in prediction and the expression alternative still wins. No predicate is -# involved, so the record fix's committed-path wall does not apply. -# -# The one residual trade, same shape as `record`-as-a-return-type: `await t;` -# with a BARE identifier operand. `await` is contextual and widened into -# `identifier_token`, so that statement is genuinely ambiguous — a declaration -# of `t` with type `await` — and the hoist picks the declaration, exactly as it -# would for any `T t;`. Roslyn disambiguates semantically (is the enclosing -# method async?), which a syntax-only grammar cannot. Real await operands are -# overwhelmingly calls or member accesses (`await F()`, `await x.M()`), which -# stay expressions; measured on the corpus, the hoist changed no diagnostics -# (see PROVENANCE.md). `await (t);` and `_ = await t;` remain available -# spellings. -# -# `await tasks[i];` would be a SECOND trade — `tasks[i]` matches -# `variable_declarator : identifier_token bracketed_argument_list? …` — but that -# one is closed for free by mirroring ECMA-334, which gives locals their own -# bracket-less `local_variable_declarator` (§13.6.2): the bracketed form is the -# fixed-size-buffer declarator (§23.8.2), legal ONLY as a struct field. So the -# statement is pointed at a minted local pair with no bracket alternative, the -# indexed await stays an expression, and `fixed int data[4];` keeps its shape in -# field position. (The invalid-C# local `int buf[4];` still parses silently — -# the permissive expression hub reads it as an element access over a -# declaration_expression — but it no longer takes the declaration path.) -STATEMENT_LOCAL_DECLARATION_ALT = " | local_declaration_statement\n" -STATEMENT_EXPRESSION_ALT = " | expression_statement\n" -LOCAL_DECLARATION_STATEMENT_RULE = ( - "local_declaration_statement\n" - " : attribute_list* 'await'? 'using'? modifier* variable_declaration ';'\n ;" -) -LOCAL_DECLARATION_STATEMENT_REWRITTEN = ( - "local_declaration_statement\n" - " : attribute_list* 'await'? 'using'? modifier* local_variable_declaration ';'\n ;" -) -LOCAL_DECLARATOR_RULES = """ - -// Minted pair for statement position (see STATEMENT_LOCAL_DECLARATION_ALT). -// ECMA-334 gives locals a declarator with NO bracketed form — that alternative -// is the fixed-size-buffer declarator, a struct-field-only construct — and the -// distinction is load-bearing here: with brackets viable, the hoisted -// declaration alternative would claim `await tasks[i];` (`await` as the type, -// `tasks[i]` as a bracketed declarator). -local_variable_declaration - : type local_variable_declarator (',' local_variable_declarator)* - ; - -local_variable_declarator - : identifier_token equals_value_clause? - ; -""" - -# `single_variable_designation` in its post-harvest tokenized form, and the -# replacement that keeps every contextual keyword EXCEPT the combinators. -DESIGNATION_RULE = "single_variable_designation\n : identifier_token\n ;" - -# `Syntax.xml` wraps a member's body in a of Body / ExpressionBody / -# SemicolonToken, which the generator renders as `(block | (arrow_expression_clause -# ';'))` — *requiring* one of the two. But drives the SyntaxFactory -# overload set and doc comments, not the hand-written parser: an abstract, -# `extern`, `partial`, or interface member legitimately has **no** body, just a -# semicolon. -# -# Without the bodiless alternative those members cannot match their own rule and -# fall through to `global_statement` (Roslyn's C# 9 top-level-statement node), -# which happily accepts `void Scale(double f);` as an expression statement — so an -# interface method silently became a call expression, with zero reported errors. -# -# Same shape as the accessor and property-initializer gaps below: information the -# real parser holds outside the syntax model. -BODY_REQUIRING_RULES = ( - "method_declaration", - "operator_declaration", - "conversion_operator_declaration", - "constructor_declaration", - "destructor_declaration", -) - -REQUIRED_BODY = "(block | (arrow_expression_clause ';'))" -OPTIONAL_BODY = "(block | (arrow_expression_clause ';') | ';')" - -GENERATOR_GAP_FIXES = [ - # (0) `x => …` must take a bare identifier, not a whole `parameter`. - # - # `SimpleLambdaExpressionSyntax.Parameter` really is a `ParameterSyntax` in - # Roslyn's model, so the grammar is faithful — but every element of `parameter` - # is optional, including `type?`, which can match a parenthesized tuple type. - # So `(a, b) => a + b` parses as the *simple* form with `(a, b)` as one - # parameter's type, instead of the parenthesized form with two parameters. - # Roslyn's parser distinguishes them lexically (a leading `(` picks the - # parenthesized form); the grammar cannot, so the simple form is narrowed to - # what "simple" means. - ( - "simple_lambda_expression\n" - " : attribute_list* modifier* parameter '=>' (block | expression)\n ;", - "simple_lambda_expression\n" - " : attribute_list* modifier* identifier_token '=>' (block | expression)\n ;", - ), - # (1) allow a bare `;` accessor body. - ( - "accessor_declaration\n" - " : attribute_list* modifier* ('get' | 'set' | 'init' | 'add'" - " | 'remove' | identifier_token) (block | (arrow_expression_clause" - " ';'))\n ;", - "accessor_declaration\n" - " : attribute_list* modifier* ('get' | 'set' | 'init' | 'add'" - " | 'remove') (block | (arrow_expression_clause" - " ';') | ';')\n ;", - ), - # The same rewrite also DROPS the `identifier_token` alternative. That is - # Roslyn's recovery shape — an accessor the author has not finished naming — and - # combined with the bare `;` body it made `int P { banana; }` a clean parse that - # opened a real function space named `P.accessor`, inflating NOM and WMC for - # source that does not compile. The five keywords are the whole legal set. - # - # (2) parameter-position modifiers. - ( - "parameter\n" - " : attribute_list* modifier* type? (identifier_token |" - " '__arglist')? equals_value_clause?\n ;", - "parameter\n" - " : attribute_list* (modifier | 'out' | 'in' | 'params' | 'this')*" - " type? (identifier_token | '__arglist')? equals_value_clause?\n ;", - ), - # (3) auto-property initializer. `Syntax.xml` wraps the property body in a - # of `AccessorList` vs `(ExpressionBody | Initializer) - # SemicolonToken`, which the generator renders as ANTLR alternation. But - # drives the SyntaxFactory overload set and doc comments, not - # the hand-written parser: an auto-property may carry an accessor list - # AND an initializer (`public bool P { get; } = true;`, C# 6). This is - # the one gap where the generator transcribes the model faithfully and - # the *model* is stricter than the language. - ( - "property_declaration\n" - " : attribute_list* modifier* type explicit_interface_specifier?" - " identifier_token (accessor_list | ((arrow_expression_clause |" - " equals_value_clause) ';'))\n ;", - "property_declaration\n" - " : attribute_list* modifier* type explicit_interface_specifier?" - " identifier_token (accessor_list (equals_value_clause ';')? |" - " ((arrow_expression_clause | equals_value_clause) ';'))\n ;", - ), -] - -# Roslyn writes every type/enum body as `'{'? member_declaration* '}'?` — both -# braces independently optional — because its parser builds a complete -# declaration node even for unterminated source (`class C {` with no closer). -# That is right for a node model and pathological for a parsing grammar: after -# each member, prediction must weigh "another member of this type" against "the -# type ended without a `}`, so this belongs to the enclosing scope", recursively -# outward. Cost grows ~quadratically in members per type: -# -# members as-published balanced -# 32 2.28 s 0.23 s -# 64 6.55 s 0.21 s -# 128 22.54 s 0.37 s (61x) -# -# Real files pay it: one 842-line file with 77 members in one class took 125 s, -# and a 1904-line file took 417 s. -# -# Making the braces a *balanced pair* — `('{' member_declaration* '}')?` — keeps -# what the optionality is actually for (a body-less `record R(int X);`) and drops -# only the half-present case. Verified behaviour-identical on the brace-less -# forms (`record R;`, `record R(int X);`, file-scoped namespaces) and on nested -# types, so this is a semantics-preserving rewrite rather than a narrowing. -# -# `.` excludes newlines and every emitted rule body is one line, so a match can -# never span two rules. Step 4c re-checks that rather than leaving it implicit. -# `switch_statement` has the same independently-optional-delimiter shape, in -# parentheses rather than braces: -# -# switch_statement : attribute_list* 'switch' '('? expression ')'? '{' … '}' -# -# and the same consequence: `switch value { default: break; }` — which is not valid -# C# — matches without recovery and is reported as a clean analysis. The -# parenthesis-free spelling belongs to the switch *expression* (`value switch { … }`), -# a separate rule. -# -# Applied on the pristine literal forms (before harvesting), so the tokens are still -# spelled `'('` / `')'`. Made a balanced pair for the same reason as the braces: it -# drops only the half-present case, which no valid C# produces. -SWITCH_PARENS = ( - "switch_statement\n : attribute_list* 'switch' '('? expression ')'? '{' switch_section* '}'\n ;\n", - "switch_statement\n : attribute_list* 'switch' '(' expression ')' '{' switch_section* '}'\n ;\n", -) - -# `query_body : query_clause+ select_or_group_clause` requires at least ONE body clause -# between the `from` and the `select`/`group`. C# requires none — ECMA-334 §12.20.3 spells -# it `query_body : query_body_clauses? select_or_group_clause query_continuation?` — so the -# two simplest possible queries do not parse: -# -# from a in xs select a // 2 diagnostics -# from a in xs group a by a // 4 -# -# while anything with a `where` / `orderby` / `let` / `join` in between parses cleanly. -# That is why this survived: every query in the test corpus had a body clause. -# -# `Syntax.xml` models `QueryBodySyntax.Clauses` as a plain list, which can be empty; the -# generator renders a list as `+` rather than `*`, so this is a generator artifact of the -# same kind as the dropped `record` contextual keyword rather than a deliberate -# restriction. Widening to `*` is a pure relaxation — it adds the two spellings above and -# changes nothing else, since `query_clause+` is a subset of `query_clause*`. -QUERY_BODY_CLAUSES_OPTIONAL = ( - "query_body\n : query_clause+ select_or_group_clause query_continuation?\n ;", - "query_body\n : query_clause* select_or_group_clause query_continuation?\n ;", -) - -BALANCED_BRACES_PATTERN = re.compile(r"LBRACE\? (.*?) RBRACE\?") -BALANCED_BRACES_REPLACEMENT = r"(LBRACE \1 RBRACE)?" - -# `extension_block_declaration` has EVERY element after the keyword optional: -# -# KW_EXTENSION type_parameter_list? parameter_list? … (LBRACE … RBRACE)? SEMICOLON? -# -# so the bare token `extension` is a complete extension block. Harmless while the rule -# sat behind `base_method_declaration`; the moment HOISTED_TYPE_ALTS gave it priority, -# that zero-child match won before `method_declaration` could take `extension` as a -# *return type* — so `class C { extension M() { … } }` produced a phantom empty -# extension-block space beside the correct method, with zero diagnostics. -# -# This is the same all-optional pathology the brace balancing above addresses, and the -# fix is the same shape: require the body. Nothing legal is lost — unlike every other -# type form, an extension block has no body-less spelling (`record R;` is valid C#, -# `extension;` is not; the receiver is what it declares and a receiver alone declares -# nothing). Roslyn's optionality is for its error-recovery node model, as with the -# braces. -# -# The receiver `parameter_list` is deliberately left optional: `extension` with only -# type parameters is a C# 14 shape, and the trailing `SEMICOLON?` stays for a body-less -# *declaration* the compiler itself rejects but which costs nothing to accept here. -# Applied after harvesting, so the brace tokens carry their STABLE_TOKEN_NAMES names — -# and after 4c, so the pair is already balanced. -EXTENSION_BODY_REQUIRED = ( - "extension_block_declaration\n : attribute_list* modifier* KW_EXTENSION" - " type_parameter_list? parameter_list? type_parameter_constraint_clause*" - " (LBRACE member_declaration* RBRACE)? SEMICOLON?\n ;", - "extension_block_declaration\n : attribute_list* modifier* KW_EXTENSION" - " type_parameter_list? parameter_list? type_parameter_constraint_clause*" - " LBRACE member_declaration* RBRACE\n ;", -) - -# C# keywords that are *reserved*: never legal as an identifier (ECMA-334 §6.4.4 -# "Keywords", excluding the contextual ones listed there separately). Every other -# identifier-shaped literal the grammar mentions is contextual, so it must remain -# usable as a name — see CONTEXTUAL_KEYWORD_NOTE. -RESERVED_KEYWORDS = frozenset( - """ - abstract as base bool break byte case catch char checked class const continue - decimal default delegate do double else enum event explicit extern false - finally fixed float for foreach goto if implicit in int interface internal is - lock long namespace new null object operator out override params private - protected public readonly ref return sbyte sealed short sizeof stackalloc - static string struct switch this throw true try typeof uint ulong unchecked - unsafe ushort using virtual void volatile while - """.split() -) - -# Literals that look like identifiers but are never names: the UTF-8 -# string-literal suffix, which real C# lexes as part of the literal token -# (`"abc"u8`) rather than as a following word. Excluded from the contextual set so -# they do not widen `identifier_token`. -# -# `_` is deliberately NOT excluded here. It is genuinely both the discard -# designation and a legal identifier, and harvesting mints `KW__`, which wins the -# equal-length lexer match over `IDENTIFIER` — so leaving it out made `F(out _)` -# unparsable. That single gap was expensive: the seed error at one `out _` put -# the parser into error recovery, and recovery then accumulated diagnostics -# without bound (>4.29e9 links, 15.5 GB RSS) until it either overflowed the -# runtime's u32 diagnostic arena or the stack. See PROVENANCE.md. -# -# `u8`/`U8` were excluded here at first, and that was the same mistake in the same -# comment: they are *contextual* — a suffix only when directly after a string -# literal — so `class C { int u8; }` is valid C# and reported four diagnostics. -# The set is now empty, kept as the place to record that: NOTHING identifier-shaped -# should be withheld from the widening. A token that must not be an identifier in -# ONE position is narrowed at that rule instead (see COMBINATOR_KEYWORDS, which -# excludes `and`/`or`/`not` from `single_variable_designation` only). -# -# `u8`'s own special treatment survives because it is positional rather than -# lexical: `utf8_string_literal_token : string_literal_token (KW_U8 | KW_U8_LOWER)` -# requires the preceding literal, so widening `identifier_token` cannot make a bare -# `u8` into a suffix. -NON_IDENTIFIER_LITERALS: frozenset[str] = frozenset() - -# Roslyn's grammar lists only decimal and hexadecimal integer literals: -# -# integer_literal_token -# : decimal_integer_literal_token -# | hexadecimal_integer_literal_token -# ; -# -# Binary literals (`0b1010`, C# 7.0) are absent — `Syntax.xml` has a single -# `NumericLiteralToken` kind with no per-base breakdown, so the base-specific -# rules here are prose the generator emitted from the lexical spec, and that -# prose predates C# 7. `BIN_INT_LIT` therefore has to be spliced in by hand; -# without it the token lexes but no parser rule accepts it. -BINARY_LITERAL_FIX = ( - "integer_literal_token\n" - " : decimal_integer_literal_token\n" - " | hexadecimal_integer_literal_token\n ;", - "integer_literal_token\n" - " : decimal_integer_literal_token\n" - " | hexadecimal_integer_literal_token\n" - " | BIN_INT_LIT\n ;", -) - -# `>>` / `>>>` (and their compound assignments) must NOT be single lexer tokens: -# a generic closer and a shift operator are lexically identical, so -# `List>` would lex its final `>>` as one right-shift token that -# `type_argument_list`'s `'>'` can never match. This is the classic C#/Java -# angle-bracket ambiguity, and a context-free lexer cannot resolve it. -# -# The remedy is the one `grammars-v4`'s C# grammar uses and that mehen already -# ships patterns for: emit only `'>'`, and re-join the pieces in the *parser* -# behind an adjacency predicate, so `a >> b` is a shift while `List>` -# closes two generics. `token_index_adjacent` lowers to pure SemIR — no hooks. -# -# Roslyn itself has no such problem: its published grammar encodes no operator -# precedence at all (that lives in the hand-written parser), so these literals -# only exist here because the harvester minted tokens from `binary_expression`. -SHIFT_TOKEN_RULES = { - ">>": ("right_shift", "IsRightShift"), - ">>>": ("unsigned_right_shift", "IsUnsignedRightShift"), - ">>=": ("right_shift_assignment", "IsRightShiftAssignment"), - ">>>=": ("unsigned_right_shift_assignment", "IsUnsignedRightShiftAssignment"), -} - -# Emitted for each SHIFT_TOKEN_RULES entry: the pieces it is spelled with, in -# lexer-token terms. `>=` stays a single token — it is unambiguous, because a -# generic closer is never followed by `=` in a type position. -# -# `token_index_adjacent` compares only the two most recently consumed tokens -# (`LT(-2).index + 1 == LT(-1).index`), so a three-piece operator needs the -# predicate at *each* junction, not once at the end. Written as -# `'>' '>' {p}? '>' {p}?` so both gaps are checked. -SHIFT_TOKEN_PIECES = { - ">>": ("'>'", "'>'"), - ">>>": ("'>'", "'>'", "'>'"), - ">>=": ("'>'", "'>='"), - ">>>=": ("'>'", "'>'", "'>='"), -} - -# Lowerings for the interpolation state that `lexer-tokens.g4.in` keeps in -# `@lexer::members`. Emitted verbatim into the derived `patterns.toml`; the -# generator matches each `match` against the grammar's literal body text and -# lowers it to SemIR, so no hand-written Rust hook is involved. -# -# The DSL is deliberately tiny: `member`/`member_top`/`member_len`, `not`, int and -# bool literals, `set/add/push/pop_member`, and `seq`. There are no comparisons and -# no `&&`, so each predicate tests one slot's *truthiness* and the conjunction -# comes from rule order in the grammar (deeper case first). -INTERP_MEMBER_PATTERNS = """ -# ── interpolated-string state (see lexer-tokens.g4.in) ────────────────────── -# -# `nestDepth` is brace nesting inside the innermost interpolation hole; -# `holeStack` holds one saved depth per enclosing hole, so its own depth answers -# "are we inside a hole at all". Stack-valued member state is runtime 0.20.1+ -# (upstream #206). - -[[member]] -name = "nestDepth" -kind = "int" -scope = "lexer" - -[[member]] -name = "holeStack" -kind = "stack" -scope = "lexer" - -# `wideStack` is parallel to `holeStack`: one entry per open hole, nonzero when that -# hole was opened with a DOUBLED brace. A hole's close must consume as many braces as -# its open did, and `holeStack.Count > 0` cannot tell the widths apart. -[[member]] -name = "wideStack" -kind = "stack" -scope = "lexer" - -# Truthiness only: nonzero means "deeper than the hole's own level". -[[pattern]] -match = "nestDepth > 0" -lower = "not(not(member(nestDepth)))" - -# Likewise for the stack's depth: nonzero means a hole is open. -[[pattern]] -match = "holeStack.Count > 0" -lower = "not(not(member_len(holeStack)))" - -# The innermost hole's brace width: nonzero means it was opened with `{{`, so its close -# consumes `}}`. Reads the top without popping — the close's own action pops. -[[pattern]] -match = "wideStack.Peek() > 0" -lower = "not(not(member_top(wideStack)))" - -[[pattern]] -match = "nestDepth++" -lower = "add_member(nestDepth, int(1))" - -[[pattern]] -match = "nestDepth--" -lower = "add_member(nestDepth, int(-1))" - -# A hole opens: save the enclosing hole's depth, record this hole's brace width, then -# start its own depth at 0. One pattern per width, since the literal `0`/`1` is part of -# the matched body. -[[pattern]] -match = "holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0;" -lower = "seq(push_member(holeStack, member(nestDepth)), push_member(wideStack, int(0)), set_member(nestDepth, int(0)))" - -[[pattern]] -match = "holeStack.Push(nestDepth); wideStack.Push(1); nestDepth = 0;" -lower = "seq(push_member(holeStack, member(nestDepth)), push_member(wideStack, int(1)), set_member(nestDepth, int(0)))" - -# A hole closes: restore the enclosing depth and drop this hole's width. `member_top` -# reads before the pop, which is how an assignment-from-pop decomposes in this DSL. -[[pattern]] -match = "nestDepth = holeStack.Pop(); wideStack.Pop();" -lower = "seq(set_member(nestDepth, member_top(holeStack)), pop_member(holeStack), pop_member(wideStack))" -""" - -CONTEXTUAL_KEYWORD_NOTE = """ -// A C# *contextual* keyword is recognized only in the position where it has -// meaning and is otherwise an ordinary name: `var`, `record`, `from`, `get`, -// `and`, `required`, … Roslyn's grammar spells each as an inline literal, and -// harvesting those literals into named tokens makes the lexer prefer the keyword -// everywhere (ANTLR breaks an equal-length match by rule order, and the -// harvested tokens precede IDENTIFIER). Widening `identifier_token` to accept -// them back is the standard ANTLR remedy — the same shape `grammars-v4`'s C# -// grammar uses for its `identifier` rule. -// -// Without this, `var x = 1;` fails to parse: `var` is absent from the expected -// token set entirely. The damage is far wider than the keyword itself, because -// `var` appears in most idiomatic modern C# — one wrong token classification -// looks like broken support for raw strings, ranges, `using` declarations, and -// unbound generics all at once. -""" - -# Roslyn's "omitted" syntax nodes are genuinely empty productions that model a -# blank slot: `omitted_type_argument` for the unbound generic `Dictionary<,>` and -# `omitted_array_size_expression` for the multi-dimensional `int[,]`. They appear -# as alternatives of `type` and `expression` respectively. -# -# ANTLR cannot have an empty rule inside a closure, so the rules must go — but -# simply deleting their alternatives LOSES REAL SYNTAX: `int[,]` and -# `Dictionary<,>` then fail to parse, because the `','` in -# `'[' (expression (',' expression)*)? ']'` has nothing to match on either side. -# (I shipped that bug once; these two cases are now regression-tested.) -# -# The faithful rewrite makes the list *elements* optional at the two use sites, -# which is exactly what an empty node expressed there. -OMITTED_NODES = ("omitted_type_argument", "omitted_array_size_expression") - -OMITTED_USE_SITE_FIXES = [ - # Unbound generic names: `Dictionary<,>`, `List<>`. - ( - "type_argument_list\n : '<' (type (',' type)*)? '>'\n ;", - "type_argument_list\n : '<' (type? (',' type?)*)? '>'\n ;", - ), - # Multi-dimensional array ranks: `int[,]`, `int[,,]`. - ( - "array_rank_specifier\n : '[' (expression (',' expression)*)? ']'\n ;", - "array_rank_specifier\n : '[' (expression? (',' expression?)*)? ']'\n ;", - ), -] - - -def strip_comments(text: str) -> str: - """Remove block and line comments (so literals in prose aren't harvested).""" - text = re.sub(r"/\*.*?\*/", "", text, flags=re.S) - return re.sub(r"//[^\n]*", "", text) - - -def rule_span(src: str, name: str) -> re.Match[str] | None: - return re.search(rf"^{re.escape(name)}\n((?: [:|].*\n)+) ;\n", src, re.M) - - -# The grammar's single entry rule. Declared because the generator otherwise -# treats every top-level rule reaching `EOF` as its own entry, in which case -# nothing can be unreachable. -ENTRY_RULE = "compilation_unit" - -# Roslyn's `compilation_unit` does not end in `EOF`, so the parser stops at the -# first thing it cannot continue with and reports success on whatever it consumed. -# `class C { } } } }` parsed with **zero diagnostics** — the stray braces were -# simply never looked at. -# -# That is right for Roslyn's model (its parser reads a compilation unit and the -# caller checks the position) and wrong for a metrics tool, where "parsed cleanly" -# has to mean the whole file was accounted for. Anchoring the entry rule makes the -# unconsumed tail a syntax error, which the diagnostic contract turns into a -# non-zero exit. Both the Java and Kotlin grammars anchor theirs the same way. -ENTRY_RULE_ANCHOR = ( - f"{ENTRY_RULE}\n" - " : extern_alias_directive* using_directive* attribute_list* member_declaration*\n" - " ;\n" -) -ENTRY_RULE_ANCHORED = ( - f"{ENTRY_RULE}\n" - " : extern_alias_directive* using_directive* attribute_list* member_declaration* EOF\n" - " ;\n" -) - -def unreachable_rules(src: str, entry: str, xtask: Path) -> list[str]: - """Ask the generator which parser rules are unreachable from `entry`. - - The reachability analysis is `antlr-rust-codegen`'s (upstream #262 / #264): - it walks the real grammar AST, so it distinguishes a rule reference from a - word inside an action, a label, or an argument list. An earlier hand-rolled - version here scanned `\\b[a-z_]\\w*\\b` over comment-stripped text, which - happened to agree on this grammar but is not correct in general — and it - produced a false positive on Kotlin's `script`. - - xtask consumes the generator's structured `G4S078` diagnostics and returns - only the exact rule-name spans, one per stdout line. The warning's display - text is deliberately not a protocol. - """ - # ANTLR requires the filename to match the grammar declaration, and at this - # point in the pipeline the source still carries its upstream name - # (`grammar csharp;`), so derive the probe filename from the declaration - # rather than assuming the final one. - declaration = re.search(r"^(?:lexer |parser )?grammar\s+([A-Za-z_][\w]*)\s*;", src, re.M) - if not declaration: - raise RuntimeError("no grammar declaration found for the reachability probe") - with tempfile.TemporaryDirectory() as tmp: - probe = Path(tmp) / f"{declaration.group(1)}.g4" - # `tokenVocab` names a lexer that does not exist yet at this stage; the - # reachability pass does not need it, and dropping it keeps the probe to - # a single self-contained file. - probe.write_text(re.sub(r"^options \{[^}]*\}\n", "", src, flags=re.M)) - try: - result = subprocess.run( - [ - xtask, - "antlr", - "unreachable-rules", - probe.name, - "--entry-rule", - entry, - ], - cwd=tmp, - capture_output=True, - text=True, - check=False, - ) - except OSError as error: - raise RuntimeError(f"failed to launch reachability helper {xtask}: {error}") from error - # A hard generator failure here would silently look like "nothing is - # unreachable", so surface it instead of pruning zero rules. - if result.returncode != 0: - raise RuntimeError( - f"reachability probe failed ({xtask} exited {result.returncode}):\n" - f"{result.stderr.strip()[:2000]}" - ) - rules = [line.strip() for line in result.stdout.splitlines() if line.strip()] - invalid = [name for name in rules if not re.fullmatch(r"[a-z][A-Za-z_0-9]*", name)] - if invalid: - raise RuntimeError(f"reachability helper returned invalid rule names: {invalid!r}") - return sorted(set(rules)) - - -def prune_unreachable(src: str, entry: str, xtask: Path) -> tuple[str, list[str]]: - """Delete the rules the generator reports unreachable, to a fixpoint. - - Tokenizing the lexical wrapper rules (`decimal_integer_literal_token` → - `DEC_INT_LIT`) orphans the character-level helpers they used to call - (`decimal_digit : '0' | '1' | …`, `hexadecimal_digit`, `integer_type_suffix`, - `identifier_start_character`, …). Those must be removed *before* literals - are harvested: otherwise their single-character literals become named tokens - that win equal-length lexer matches, so `'1'` shadows `DEC_INT_LIT` and - `'a'` shadows `IDENTIFIER` — which silently breaks every parse while the - grammar still generates cleanly. - - This is why the generator's own `--prune-unreachable` cannot do the job on - its own: it runs inside codegen, *after* the literals here are harvested, so - pruning there still emits the junk tokens (259 vs 181) and still mis-lexes. - The split is analysis vs. edit — the generator decides *which* rules are - unreachable, this function performs the deletion at the point in the pipeline - where it has to happen. - - Iterated because removing a rule can orphan helpers only it called; the - generator reports one round at a time. - """ - removed: list[str] = [] - while dead := unreachable_rules(src, entry, xtask): - for name in dead: - if match := rule_span(src, name): - src = src[: match.start()] + src[match.end() :] - else: - raise RuntimeError(f"cannot locate reported unreachable rule {name!r}") - removed.extend(dead) - return src, removed - - -def main() -> int: - ap = argparse.ArgumentParser(description=__doc__) - ap.add_argument("source", type=Path, help="upstream CSharp.Generated.g4") - ap.add_argument("--out-dir", type=Path, default=Path(".")) - ap.add_argument( - "--xtask", - type=Path, - required=True, - help="path to the running xtask binary, used for structured rule reachability", - ) - args = ap.parse_args() - - xtask = args.xtask.expanduser().resolve() - if not xtask.is_file(): - print( - f"error: xtask helper {xtask} is not a file", - file=sys.stderr, - ) - return 1 - - src = args.source.read_text(encoding="utf-8-sig") - - # -- 1. Drop the omitted-node rules and their use sites ------------------ - for name in OMITTED_NODES: - src = re.sub(rf"^{name}\n : /\* epsilon \*/\n ;\n\n", "", src, flags=re.M) - # Preserve the syntax those empty nodes expressed (see OMITTED_USE_SITE_FIXES). - for old, new in OMITTED_USE_SITE_FIXES: - if old not in src: - print(f"error: omitted-node use site not found: {old.splitlines()[0]}", file=sys.stderr) - return 1 - src = src.replace(old, new, 1) - kept = [ - line - for line in src.split("\n") - if not re.match(rf"^\s*\|\s*({'|'.join(OMITTED_NODES)})\s*$", line) - ] - src = "\n".join(kept) - for name in OMITTED_NODES: - if name in src: - print(f"error: {name} still referenced after removal", file=sys.stderr) - return 1 - - # -- 2. Nullability fixes ----------------------------------------------- - for old, new in NULLABILITY_FIXES: - if old not in src: - print(f"error: nullability target not found: {old.splitlines()[0]}", file=sys.stderr) - return 1 - src = src.replace(old, new) - - # -- 2b. Restore the `record` contextual keyword ------------------------- - if RECORD_KEYWORD_TARGET not in src: - print("error: record_declaration shape changed upstream", file=sys.stderr) - return 1 - src = src.replace(RECORD_KEYWORD_TARGET, RECORD_KEYWORD_REPLACEMENT, 1) - src = src.rstrip() + "\n" + RECORD_KEYWORD_RULE - - # -- 2c. Repair generator blind spots (see GENERATOR_GAP_FIXES) ---------- - for old, new in GENERATOR_GAP_FIXES: - if old not in src: - print( - f"error: generator-gap target not found: {old.splitlines()[0]}", - file=sys.stderr, - ) - return 1 - src = src.replace(old, new, 1) - - # -- 2d. Split the shift operators off the generic closer ----------------- - # Each `'>>'`-family literal becomes a rule that spells the operator out of - # `'>'` pieces behind an adjacency predicate (see SHIFT_TOKEN_RULES). - shift_rules: list[str] = [] - for literal, (rule, helper) in SHIFT_TOKEN_RULES.items(): - quoted = f"'{literal}'" - if quoted not in src: - print(f"error: shift literal {quoted} not found", file=sys.stderr) - return 1 - # The predicate goes after every piece but the first, so each junction is - # checked (it only ever compares the last two consumed tokens). - head, *rest = SHIFT_TOKEN_PIECES[literal] - body = head + "".join(f" {piece} {{this.{helper}()}}?" for piece in rest) - shift_rules.append(f"\n{rule}\n : {body} // adjacent in the char stream?\n ;\n") - for literal in sorted(SHIFT_TOKEN_RULES, key=len, reverse=True): - src = src.replace(f"'{literal}'", SHIFT_TOKEN_RULES[literal][0]) - src = src.rstrip() + "\n" + "".join(shift_rules) - - # -- 2d2. Require the switch statement's parentheses --------------------- - # See SWITCH_PARENS: `switch value { … }` is not valid C# but parses cleanly. - old, new = SWITCH_PARENS - if old not in src: - print("error: switch_statement shape changed upstream", file=sys.stderr) - return 1 - src = src.replace(old, new, 1) - print("required the switch statement's parentheses") - - # -- 2d3. Let a query have no body clauses ------------------------------- - # See QUERY_BODY_CLAUSES_OPTIONAL: `from a in xs select a` — the simplest query C# - # has — did not parse, because upstream renders the clause list as `+`. - old, new = QUERY_BODY_CLAUSES_OPTIONAL - if old not in src: - print("error: query_body shape changed upstream", file=sys.stderr) - return 1 - src = src.replace(old, new, 1) - print("made the query body's clauses optional") - - # -- 2d4. Prioritize var_pattern over the catch-all pattern forms --------- - # See VAR_PATTERN_ALT: `var x => …` parsed as a *constant* pattern (whose body is a - # bare `expression`), so `var_pattern` was unreachable. - pattern_rule = rule_span(src, "pattern") - if not pattern_rule: - print("error: pattern rule not found", file=sys.stderr) - return 1 - body = pattern_rule.group(1) - if VAR_PATTERN_ALT not in body or PATTERN_CONSTANT_ALT not in body: - print( - "error: pattern's var/constant alternatives changed upstream", - file=sys.stderr, - ) - return 1 - src = src.replace( - pattern_rule.group(0), - "pattern\n" - + body.replace(VAR_PATTERN_ALT, "").replace( - PATTERN_CONSTANT_ALT, VAR_PATTERN_ALT + PATTERN_CONSTANT_ALT, 1 - ) - + " ;\n", - 1, - ) - print("hoisted var_pattern ahead of constant_pattern") - - # -- 2d5. Prioritize local declarations over expression statements -------- - # See STATEMENT_LOCAL_DECLARATION_ALT: `List l;` parsed as a chained - # comparison expression, scoring two phantom ABC conditions per generic local. - statement_rule = rule_span(src, "statement") - if not statement_rule: - print("error: statement rule not found", file=sys.stderr) - return 1 - body = statement_rule.group(1) - if ( - STATEMENT_LOCAL_DECLARATION_ALT not in body - or STATEMENT_EXPRESSION_ALT not in body - or body.index(STATEMENT_EXPRESSION_ALT) > body.index(STATEMENT_LOCAL_DECLARATION_ALT) - ): - print( - "error: statement's expression/local-declaration alternatives changed upstream", - file=sys.stderr, - ) - return 1 - src = src.replace( - statement_rule.group(0), - "statement\n" - + body.replace(STATEMENT_LOCAL_DECLARATION_ALT, "").replace( - STATEMENT_EXPRESSION_ALT, - STATEMENT_LOCAL_DECLARATION_ALT + STATEMENT_EXPRESSION_ALT, - 1, - ) - + " ;\n", - 1, - ) - print("hoisted local_declaration_statement ahead of expression_statement") - - # The hoist's companion (see LOCAL_DECLARATOR_RULES): point the statement at a - # bracket-less declarator pair so `await tasks[i];` cannot read as a - # declaration. Field/event declarations keep `variable_declaration`, and with - # it the fixed-size-buffer declarator. - if LOCAL_DECLARATION_STATEMENT_RULE not in src: - print( - "error: local_declaration_statement shape changed upstream", - file=sys.stderr, - ) - return 1 - src = src.replace( - LOCAL_DECLARATION_STATEMENT_RULE, LOCAL_DECLARATION_STATEMENT_REWRITTEN, 1 - ) - src = src.rstrip() + "\n" + LOCAL_DECLARATOR_RULES - print("split the local declarator off the field declarator (no brackets)") - - # -- 2e. Accept binary integer literals ---------------------------------- - old, new = BINARY_LITERAL_FIX - if old not in src: - print("error: integer_literal_token shape changed upstream", file=sys.stderr) - return 1 - src = src.replace(old, new, 1) - - # -- 2e2. Let members be bodiless ---------------------------------------- - # See BODY_REQUIRING_RULES: an abstract / interface / extern / partial member - # has only a semicolon, and without this it falls through to - # `global_statement` and parses as a call expression. - for rule in BODY_REQUIRING_RULES: - match = rule_span(src, rule) - if not match: - print(f"error: {rule} not found", file=sys.stderr) - return 1 - body = match.group(1) - if REQUIRED_BODY not in body: - print( - f"error: {rule} body shape changed upstream (no {REQUIRED_BODY!r})", - file=sys.stderr, - ) - return 1 - src = src.replace( - match.group(0), - f"{rule}\n{body.replace(REQUIRED_BODY, OPTIONAL_BODY, 1)} ;\n", - 1, - ) - - # -- 2f. Deprioritize declaration_expression ----------------------------- - # See DECLARATION_EXPRESSION_ALT: it shadows every invocation otherwise. - expression_rule = rule_span(src, "expression") - if not expression_rule: - print("error: expression rule not found", file=sys.stderr) - return 1 - body = expression_rule.group(1) - if DECLARATION_EXPRESSION_ALT not in body: - print( - "error: declaration_expression is not an alternative of `expression`", - file=sys.stderr, - ) - return 1 - reordered = body.replace(DECLARATION_EXPRESSION_ALT, "") + DECLARATION_EXPRESSION_ALT - src = src.replace(expression_rule.group(0), f"expression\n{reordered} ;\n", 1) - - # -- 2g. Prioritize record_declaration in member position ---------------- - # See HOISTED_TYPE_ALTS: `record R(int X);` / `union U { }` parse as phantom - # *methods* otherwise, - # because `record` is widened back into `identifier_token` and so is a viable - # return type. Safe only because `record_keyword` is a real KW_RECORD token now. - member_rule = rule_span(src, "member_declaration") - if not member_rule: - print("error: member_declaration rule not found", file=sys.stderr) - return 1 - body = member_rule.group(1) - if MEMBER_METHOD_ALT not in body: - print( - "error: base_method_declaration is not an alternative of `member_declaration`", - file=sys.stderr, - ) - return 1 - already = [alt.strip(" |\n") for alt in HOISTED_TYPE_ALTS if alt in body] - if already: - print( - "error: already a member_declaration alternative: " + ", ".join(already), - file=sys.stderr, - ) - return 1 - src = src.replace( - member_rule.group(0), - "member_declaration\n" - + body.replace(MEMBER_METHOD_ALT, "".join(HOISTED_TYPE_ALTS) + MEMBER_METHOD_ALT, 1) - + " ;\n", - 1, - ) - hoisted = ", ".join(alt.strip(" |\n") for alt in HOISTED_TYPE_ALTS) - print(f"hoisted {hoisted} ahead of base_method_declaration") - - # -- 2h. Drop the error-recovery member alternative ---------------------- - # See INCOMPLETE_MEMBER_ALT: it makes `class C { int }` an error-free parse. - member_rule = rule_span(src, "member_declaration") - if not member_rule or INCOMPLETE_MEMBER_ALT not in member_rule.group(1): - print( - "error: incomplete_member is not an alternative of `member_declaration`", - file=sys.stderr, - ) - return 1 - src = src.replace( - member_rule.group(0), - "member_declaration\n" - + member_rule.group(1).replace(INCOMPLETE_MEMBER_ALT, "", 1) - + " ;\n", - 1, - ) - print("dropped the incomplete_member recovery alternative") - - # -- 3. Point character-level rules at real lexer tokens ----------------- - lexer_bound = dict(LEXER_TOKEN_RULES) - lexer_bound.update( - (rule, INTERP_RAW_START_TOKEN) for rule in INTERP_RAW_START_RULES - ) - for rule, token in lexer_bound.items(): - m = rule_span(src, rule) - if not m: - print(f"error: lexer-bound rule not found: {rule}", file=sys.stderr) - return 1 - src = src[: m.start()] + f"{rule}\n : {token}\n ;\n" + src[m.end() :] - - # -- 3b. Prune rules the tokenization orphaned --------------------------- - try: - src, pruned = prune_unreachable(src, ENTRY_RULE, xtask) - except RuntimeError as error: - print(f"error: {error}", file=sys.stderr) - return 1 - if pruned: - print(f"pruned {len(pruned)} unreachable rules: {', '.join(sorted(pruned))}") - - # -- 3c. Anchor the entry rule at EOF ------------------------------------ - # See ENTRY_RULE_ANCHOR. Deliberately AFTER pruning: the generator treats every - # top-level rule that reaches `EOF` as an entry point, so anchoring first would - # make nothing unreachable and the 84 orphaned helpers would survive. - if ENTRY_RULE_ANCHOR not in src: - print( - f"error: {ENTRY_RULE} not in the expected unanchored form", - file=sys.stderr, - ) - return 1 - src = src.replace(ENTRY_RULE_ANCHOR, ENTRY_RULE_ANCHORED, 1) - print(f"anchored {ENTRY_RULE} at EOF") - - # -- 4. Harvest the remaining inline literals into named tokens ---------- - # A combined grammar would let ANTLR synthesize implicit tokens for these, - # but a split pair needs them named so `tokenVocab` can carry them. - body = strip_comments(src) - literals = sorted( - { - lit - for lit in re.findall(r"'((?:[^'\\\n]|\\.)*)'", body) - # Interpolation delimiters are mode-switching named tokens, not - # harvested literals (see INTERP_TOKEN_LITERALS). - if lit and lit not in INTERP_TOKEN_LITERALS - }, - key=lambda s: (-len(s), s), - ) - names: dict[str, str] = {} - unnamed: list[str] = [] - for index, lit in enumerate(literals): - if lit in STABLE_TOKEN_NAMES: - names[lit] = STABLE_TOKEN_NAMES[lit] - elif re.fullmatch(r"[a-zA-Z_][a-zA-Z_0-9]*", lit): - names[lit] = f"KW_{lit.upper()}" - else: - # Reached only for an operator STABLE_TOKEN_NAMES does not cover. - # Named by index so generation can continue and the report below can - # list every gap at once, then rejected. - names[lit] = f"OP_{index:03d}" - unnamed.append(lit) - if unnamed: - # Index names are position-derived, so they rebind on any upstream - # literal change. Failing here keeps that from reaching hand-written - # code that names tokens (the walker, `lexer-tokens.g4.in`). - print( - "error: operator literals missing from STABLE_TOKEN_NAMES: " - + ", ".join(repr(lit) for lit in unnamed), - file=sys.stderr, - ) - return 1 - # Keyword names can collide when the grammar spells the same word in two - # cases (`U8` and `u8` both want `KW_U8`). Disambiguate from the literal's own - # spelling, NOT from its index: an index suffix is exactly the position-derived - # naming rejected above, so `KW_U8_150` would rebind to a different literal the - # moment upstream adds or removes one. `KW_U8` / `KW_U8_LOWER` are stable as - # long as the two spellings are. - # - # The uppercase spelling keeps the bare name (it is what `KW_{lit.upper()}` - # already produces), so only the lowercase variant is suffixed; a collision - # between anything other than a pure case difference is a real ambiguity and - # fails the assertion below. - seen: dict[str, str] = {} - for lit in literals: - name = names[lit] - if name in seen: - names[lit] = f"{name}_LOWER" if lit.islower() else f"{name}_UPPER" - seen[names[lit]] = lit - assert len(set(names.values())) == len(literals), "token-name collision" - - for lit in literals: # longest-first so `>>=` is not clobbered by `>` - src = src.replace(f"'{lit}'", names[lit]) - # Longest-first here too: `$@"` must be replaced before `$"`. - for lit in sorted(INTERP_TOKEN_LITERALS, key=len, reverse=True): - src = src.replace(f"'{lit}'", INTERP_TOKEN_LITERALS[lit]) - - # -- 4b. Let contextual keywords be identifiers again -------------------- - # Runs after harvesting because it needs the generated token names. - contextual = sorted( - lit - for lit in literals - if re.fullmatch(r"[a-zA-Z_][a-zA-Z_0-9]*", lit) - and lit not in RESERVED_KEYWORDS - and lit not in NON_IDENTIFIER_LITERALS - and not lit.startswith("__") # `__arglist` &c. are reserved compiler-isms - ) - if not contextual: - print("error: no contextual keywords found to widen", file=sys.stderr) - return 1 - # The minted `KW_RECORD` is contextual too, and it is not among the harvested - # literals (Roslyn's grammar never spells it), so it is added by name. - contextual_tokens = [names[lit] for lit in contextual] + [RECORD_TOKEN_NAME] - identifier_alts = "\n".join(f" | {token}" for token in contextual_tokens) - old_identifier = f"identifier_token\n : {LEXER_TOKEN_RULES['identifier_token']}\n ;" - if old_identifier not in src: - print("error: identifier_token not in expected tokenized form", file=sys.stderr) - return 1 - src = src.replace( - old_identifier, - f"{CONTEXTUAL_KEYWORD_NOTE.strip()}\nidentifier_token\n" - f" : {LEXER_TOKEN_RULES['identifier_token']}\n{identifier_alts}\n ;", - 1, - ) - print(f"widened identifier_token with {len(contextual_tokens)} contextual keywords") - - # -- 4b2. Keep a pattern combinator out of a variable designation --------- - # See COMBINATOR_KEYWORDS. Spelled as the full contextual set minus the three - # combinators, rather than as `identifier_token` with exclusions, because ANTLR - # has no rule-level token subtraction. - if DESIGNATION_RULE not in src: - print( - "error: single_variable_designation not in expected tokenized form", - file=sys.stderr, - ) - return 1 - missing = [kw for kw in COMBINATOR_KEYWORDS if kw not in names] - if missing: - print( - "error: pattern combinators absent from the harvested literals: " - + ", ".join(missing), - file=sys.stderr, - ) - return 1 - excluded = {names[kw] for kw in COMBINATOR_KEYWORDS} - designation_alts = "\n".join( - f" | {token}" for token in contextual_tokens if token not in excluded - ) - src = src.replace( - DESIGNATION_RULE, - "// A pattern combinator (`and`/`or`/`not`) is excluded: it is a contextual\n" - "// keyword, so widening `identifier_token` would let `o is int and > 5` bind\n" - "// `and` as a variable name and silently drop the combinator. See\n" - "// COMBINATOR_KEYWORDS in prepare-grammar.py.\n" - "single_variable_designation\n" - f" : {LEXER_TOKEN_RULES['identifier_token']}\n{designation_alts}\n ;", - 1, - ) - print(f"narrowed single_variable_designation (excluded {', '.join(COMBINATOR_KEYWORDS)})") - - # -- 4c. Pair up the type-body braces ------------------------------------ - # After harvesting, so the brace tokens have their STABLE_TOKEN_NAMES names. - for match in BALANCED_BRACES_PATTERN.finditer(src): - if "\n" in match.group(0): - print("error: brace-balancing match spans two rules", file=sys.stderr) - return 1 - src, braced = BALANCED_BRACES_PATTERN.subn(BALANCED_BRACES_REPLACEMENT, src) - if not braced: - print("error: no optional-brace bodies found to balance", file=sys.stderr) - return 1 - print(f"balanced the brace pair in {braced} body rules") - - # -- 4d. Require an extension block to have a body ------------------------ - # See EXTENSION_BODY_REQUIRED: every element after `KW_EXTENSION` is optional - # upstream, so the bare keyword was a complete extension block — and once the rule - # was hoisted, `class C { extension M() { … } }` grew a phantom empty extension - # space beside the method. Runs after 4c so the brace pair is already balanced. - if EXTENSION_BODY_REQUIRED[0] not in src: - print( - "error: extension_block_declaration not in expected balanced form", - file=sys.stderr, - ) - return 1 - src = src.replace(*EXTENSION_BODY_REQUIRED, 1) - print("required the extension block's body") - - # -- 5. Emit the parser grammar ----------------------------------------- - src = re.sub(r"^//[^\n]*\n", "", src) # drop the auto-generated banner - src = re.sub(r"^grammar csharp;\n", "", src, flags=re.M) - parser = ( - "// @generated from Roslyn's CSharp.Generated.g4 by " - "prepare-roslyn-grammar.py — do not hand-edit.\n" - "// See PROVENANCE.md for the pinned upstream revision and the patch rationale.\n" - "parser grammar CSharpParser;\n\n" - "options { tokenVocab=CSharpLexer; }\n" + src - ) - (args.out_dir / "CSharpParser.g4").write_text(parser) - - # -- 6. Emit the lexer grammar ------------------------------------------ - # Keyword/operator/punctuation tokens come first: ANTLR breaks an - # equal-length match by rule order, so `KW_CLASS` must precede `IDENTIFIER` - # or every keyword would lex as an identifier. - def hand_written(name: str) -> Path | None: - """Locate a hand-written `.g4.in` beside the source, else beside this file.""" - candidate = args.source.parent / name - return candidate if candidate.is_file() else Path(__file__).with_name(name) - - token_rules = hand_written(LEXER_RULES_FILE) - lexer_members = hand_written(LEXER_MEMBERS_FILE) - for required in (token_rules, lexer_members): - if not required.is_file(): - print(f"error: missing {required.name}", file=sys.stderr) - return 1 - mode_tokens = sorted( - token for rule, token in LEXER_TOKEN_RULES.items() - if rule in MODE_SCOPED_RULES - ) - lexer = "\n".join( - [ - "// @generated from Roslyn's CSharp.Generated.g4 by " - "prepare-grammar.py — do not hand-edit.", - "// Roslyn publishes a parser-only grammar; this lexer supplies the", - "// terminals it references. Literal tokens below are harvested from the", - "// parser's inline literals; the rest is spliced from " - f"`{LEXER_RULES_FILE}` and `{LEXER_MEMBERS_FILE}`.", - "// See PROVENANCE.md.", - "lexer grammar CSharpLexer;", - "", - "channels { COMMENTS_CHANNEL, DIRECTIVE }", - "", - "// Emitted only from their lexer modes, but referenced by the parser,", - "// so they must be declared up front.", - "tokens { " + ", ".join(mode_tokens) + " }", - "", - # ANTLR requires named actions in the header, before any rule, so the - # `@lexer::members` block is a separate file from the rules. - lexer_members.read_text().rstrip(), - "", - "// ---- keywords, operators, punctuation (must precede IDENTIFIER) ----", - ] - # `{`, `}` and `:` are omitted here and defined by `lexer-tokens.g4.in` - # instead: inside an interpolation hole they need predicate-gated rules - # that must *precede* the plain literal, and ANTLR breaks an equal-length - # match by rule order. Everything else keeps the literals-first ordering, - # which is what makes `KW_CLASS` beat `IDENTIFIER`. - + [ - f"{names[lit]} : '{lit}' ;" - for lit in literals - if lit not in HOLE_SENSITIVE_LITERALS - ] - # `record` is the one keyword Roslyn's grammar never spells as a literal, so - # it cannot be harvested; it is minted here instead. Placed with the - # harvested keywords so it precedes IDENTIFIER, and widened back into - # `identifier_token` above so it stays a legal name. - + [RECORD_TOKEN_RULE] - + [ - "", - # No substitution needed: the tokens `lexer-tokens.g4.in` refers to - # by name are the ones STABLE_TOKEN_NAMES pins. - token_rules.read_text().rstrip(), - ] - ) - (args.out_dir / "CSharpLexer.g4").write_text(lexer + "\n") - - # -- 7. Emit the semantic-pattern file ---------------------------------- - shift_helpers = "".join( - "\n[[helper]]\n" - 'kind = "parser-predicate"\n' - f'name = "{helper}"\n' - 'returns = "bool"\n' - 'lower = "token_index_adjacent"\n' - for _rule, helper in SHIFT_TOKEN_RULES.values() - ) - (args.out_dir / "patterns.toml").write_text( - "version = 1\n\n" - "# `record` needs no helper here: Roslyn declares\n" - "# `` on\n" - "# RecordDeclarationSyntax.Keyword, but its grammar generator reads only\n" - "# ``, so the published grammar spells the keyword as the catch-all\n" - "# `syntax_token`. `prepare-grammar.py` restores the restriction by minting a\n" - "# real `KW_RECORD` token (see RECORD_KEYWORD_RULE) rather than by predicating\n" - "# over `IDENTIFIER` — a predicate cannot prune a path ANTLR has already\n" - "# committed to, and this position overlaps several member forms.\n\n" - "# `>>` / `>>>` (and their compound assignments) are spelled as adjacent\n" - "# `>` tokens so a generic closer never lexes as a shift operator (see\n" - "# SHIFT_TOKEN_RULES). Each predicate checks the pieces were adjacent in the\n" - "# char stream, so `a >> b` shifts while `List>` closes two\n" - "# generics. Same lowering the vendored grammars-v4 grammar uses.\n" - + shift_helpers - + INTERP_MEMBER_PATTERNS - ) - - print(f"wrote CSharpParser.g4, CSharpLexer.g4, patterns.toml ({len(literals)} literal tokens)") - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/crates/mehen-csharp-parser/src/generated/README.md b/crates/mehen-csharp-parser/src/generated/README.md deleted file mode 100644 index adf1169b..00000000 --- a/crates/mehen-csharp-parser/src/generated/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Generated ANTLR modules — DO NOT EDIT - -`c_sharp_lexer.rs`, `c_sharp_parser.rs`, `decisions.json`, and `semantics.json` -are generated from the vendored grammar in `../../grammar/` by -`cargo xtask antlr generate csharp`. They are checked in (like the tree-sitter -`grammar.rs` kind enums), so a normal `cargo build` uses them without compiling -xtask's `antlr-rust-codegen` dependency. All four artifacts are drift-checked by -`cargo xtask antlr check-generated`. - -Regenerate — never hand-edit — via `cargo xtask antlr generate csharp`. See -`../../grammar/PROVENANCE.md` for the exact grammar commit and runtime/codegen -versions. `cargo xtask antlr check-generated` guards against drift in CI. - -(This crate has no hand-written recognizer support at all: every semantic -coordinate lowers to pure SemIR through the derived `patterns.toml`, so there is -no `hooks.rs` and both recognizers are constructed with plain `::new`.) diff --git a/crates/mehen-csharp-parser/src/generated/c_sharp_lexer.rs b/crates/mehen-csharp-parser/src/generated/c_sharp_lexer.rs deleted file mode 100644 index b3239a04..00000000 --- a/crates/mehen-csharp-parser/src/generated/c_sharp_lexer.rs +++ /dev/null @@ -1,519 +0,0 @@ -// @generated by antlr-rust-codegen v0.33.1 - do not edit -// project: https://github.com/ophi-dev/antlr-rust-runtime -antlr4_runtime::__antlr4_rust_require_codegen_api!(14, "0.33.1"); -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -#[rustfmt::skip] -mod __antlr4_rust_generated { - -use antlr4_runtime::char_stream::CharStream; -use antlr4_runtime::atn::LexerAtn; -use antlr4_runtime::atn::lexer_dfa::CompiledLexerDfa; -use antlr4_runtime::atn::serialized::AtnDeserializer; -use antlr4_runtime::{BaseLexer, GrammarMetadata, Lexer}; -use std::sync::OnceLock; - -pub const EOF: i32 = antlr4_runtime::TOKEN_EOF; -pub const INTERPOLATED_TEXT: i32 = 1; -pub const XML_TEXT_LIT: i32 = 2; -pub const KW_REFVALUE: i32 = 3; -pub const KW_DESCENDING: i32 = 4; -pub const KW_STACKALLOC: i32 = 5; -pub const KW_ARGLIST: i32 = 6; -pub const KW_MAKEREF: i32 = 7; -pub const KW_REFTYPE: i32 = 8; -pub const KW_ASCENDING: i32 = 9; -pub const KW_EXTENSION: i32 = 10; -pub const KW_INTERFACE: i32 = 11; -pub const KW_NAMESPACE: i32 = 12; -pub const KW_PROTECTED: i32 = 13; -pub const KW_UNCHECKED: i32 = 14; -pub const KW_UNMANAGED: i32 = 15; -pub const KW_ABSTRACT: i32 = 16; -pub const KW_CONTINUE: i32 = 17; -pub const KW_DELEGATE: i32 = 18; -pub const KW_EXPLICIT: i32 = 19; -pub const KW_IMPLICIT: i32 = 20; -pub const KW_INTERNAL: i32 = 21; -pub const KW_OPERATOR: i32 = 22; -pub const KW_OVERRIDE: i32 = 23; -pub const KW_READONLY: i32 = 24; -pub const KW_REQUIRED: i32 = 25; -pub const KW_VOLATILE: i32 = 26; -pub const KW_CHECKED: i32 = 27; -pub const KW_DECIMAL: i32 = 28; -pub const KW_DEFAULT: i32 = 29; -pub const KW_FINALLY: i32 = 30; -pub const KW_FOREACH: i32 = 31; -pub const KW_MANAGED: i32 = 32; -pub const KW_ORDERBY: i32 = 33; -pub const KW_PARTIAL: i32 = 34; -pub const KW_PRIVATE: i32 = 35; -pub const KW_VIRTUAL: i32 = 36; -pub const KW_ALLOWS: i32 = 37; -pub const KW_CLOSED: i32 = 38; -pub const KW_DOUBLE: i32 = 39; -pub const KW_EQUALS: i32 = 40; -pub const KW_EXTERN: i32 = 41; -pub const KW_GLOBAL: i32 = 42; -pub const KW_OBJECT: i32 = 43; -pub const KW_PARAMS: i32 = 44; -pub const KW_PUBLIC: i32 = 45; -pub const KW_REMOVE: i32 = 46; -pub const KW_RETURN: i32 = 47; -pub const KW_SCOPED: i32 = 48; -pub const KW_SEALED: i32 = 49; -pub const KW_SELECT: i32 = 50; -pub const KW_SIZEOF: i32 = 51; -pub const KW_STATIC: i32 = 52; -pub const KW_STRING: i32 = 53; -pub const KW_STRUCT: i32 = 54; -pub const KW_SWITCH: i32 = 55; -pub const KW_TYPEOF: i32 = 56; -pub const KW_UNSAFE: i32 = 57; -pub const KW_USHORT: i32 = 58; -pub const KW_ALIAS: i32 = 59; -pub const KW_ASYNC: i32 = 60; -pub const KW_AWAIT: i32 = 61; -pub const KW_BREAK: i32 = 62; -pub const KW_CATCH: i32 = 63; -pub const KW_CLASS: i32 = 64; -pub const KW_CONST: i32 = 65; -pub const KW_EVENT: i32 = 66; -pub const KW_FALSE: i32 = 67; -pub const KW_FIELD: i32 = 68; -pub const KW_FIXED: i32 = 69; -pub const KW_FLOAT: i32 = 70; -pub const KW_GROUP: i32 = 71; -pub const KW_SBYTE: i32 = 72; -pub const KW_SHORT: i32 = 73; -pub const KW_THROW: i32 = 74; -pub const KW_ULONG: i32 = 75; -pub const KW_UNION: i32 = 76; -pub const KW_USING: i32 = 77; -pub const KW_WHERE: i32 = 78; -pub const KW_WHILE: i32 = 79; -pub const KW_YIELD: i32 = 80; -pub const KW_BASE: i32 = 81; -pub const KW_BOOL: i32 = 82; -pub const KW_BYTE: i32 = 83; -pub const KW_CASE: i32 = 84; -pub const KW_CHAR: i32 = 85; -pub const KW_ELSE: i32 = 86; -pub const KW_ENUM: i32 = 87; -pub const KW_FILE: i32 = 88; -pub const KW_FROM: i32 = 89; -pub const KW_GOTO: i32 = 90; -pub const KW_INIT: i32 = 91; -pub const KW_INTO: i32 = 92; -pub const KW_JOIN: i32 = 93; -pub const KW_LOCK: i32 = 94; -pub const KW_LONG: i32 = 95; -pub const KW_NULL: i32 = 96; -pub const KW_SAFE: i32 = 97; -pub const KW_THIS: i32 = 98; -pub const KW_TRUE: i32 = 99; -pub const KW_UINT: i32 = 100; -pub const KW_VOID: i32 = 101; -pub const KW_WHEN: i32 = 102; -pub const KW_WITH: i32 = 103; -pub const TRIPLE_DQUOTE: i32 = 104; -pub const LT_LT_EQ: i32 = 105; -pub const QUESTION_QUESTION_EQ: i32 = 106; -pub const KW_ADD: i32 = 107; -pub const KW_AND: i32 = 108; -pub const KW_FOR: i32 = 109; -pub const KW_GET: i32 = 110; -pub const KW_INT: i32 = 111; -pub const KW_LET: i32 = 112; -pub const KW_NEW: i32 = 113; -pub const KW_NOT: i32 = 114; -pub const KW_OUT: i32 = 115; -pub const KW_REF: i32 = 116; -pub const KW_SET: i32 = 117; -pub const KW_TRY: i32 = 118; -pub const KW_VAR: i32 = 119; -pub const NE: i32 = 120; -pub const PERCENT_EQ: i32 = 121; -pub const AMP_AMP: i32 = 122; -pub const AMP_EQ: i32 = 123; -pub const STAR_EQ: i32 = 124; -pub const PLUS_PLUS: i32 = 125; -pub const PLUS_EQ: i32 = 126; -pub const MINUS_MINUS: i32 = 127; -pub const MINUS_EQ: i32 = 128; -pub const MINUS_GT: i32 = 129; -pub const DOT_DOT: i32 = 130; -pub const SLASH_EQ: i32 = 131; -pub const SLASH_GT: i32 = 132; -pub const COLON_COLON: i32 = 133; -pub const LT_SLASH: i32 = 134; -pub const LT_LT: i32 = 135; -pub const LE: i32 = 136; -pub const EQ_EQ: i32 = 137; -pub const ARROW: i32 = 138; -pub const GE: i32 = 139; -pub const QUESTION_QUESTION: i32 = 140; -pub const KW_U8: i32 = 141; -pub const ESCAPED_QUOTE: i32 = 142; -pub const ESCAPED_BACKSLASH: i32 = 143; -pub const CARET_EQ: i32 = 144; -pub const KW_AS: i32 = 145; -pub const KW_BY: i32 = 146; -pub const KW_DO: i32 = 147; -pub const KW_IF: i32 = 148; -pub const KW_IN: i32 = 149; -pub const KW_IS: i32 = 150; -pub const KW_ON: i32 = 151; -pub const KW_OR: i32 = 152; -pub const KW_U8_LOWER: i32 = 153; -pub const PIPE_EQ: i32 = 154; -pub const PIPE_PIPE: i32 = 155; -pub const BANG: i32 = 156; -pub const DQUOTE: i32 = 157; -pub const HASH: i32 = 158; -pub const PERCENT: i32 = 159; -pub const AMP: i32 = 160; -pub const STAR: i32 = 161; -pub const PLUS: i32 = 162; -pub const COMMA: i32 = 163; -pub const MINUS: i32 = 164; -pub const DOT: i32 = 165; -pub const SLASH: i32 = 166; -pub const SEMICOLON: i32 = 167; -pub const LT: i32 = 168; -pub const EQ: i32 = 169; -pub const GT: i32 = 170; -pub const QUESTION: i32 = 171; -pub const CARET: i32 = 172; -pub const KW: i32 = 173; -pub const PIPE: i32 = 174; -pub const TILDE: i32 = 175; -pub const KW_RECORD: i32 = 176; -pub const IDENTIFIER: i32 = 177; -pub const DEC_INT_LIT: i32 = 178; -pub const HEX_INT_LIT: i32 = 179; -pub const BIN_INT_LIT: i32 = 180; -pub const REAL_LIT: i32 = 181; -pub const CHAR_LIT: i32 = 182; -pub const STRING_LIT: i32 = 183; -pub const VERBATIM_STRING_LIT: i32 = 184; -pub const SL_RAW_STRING_LIT: i32 = 185; -pub const ML_RAW_STRING_LIT: i32 = 186; -pub const SINGLE_LINE_DOC_COMMENT: i32 = 187; -pub const DELIMITED_DOC_COMMENT: i32 = 188; -pub const SINGLE_LINE_COMMENT: i32 = 189; -pub const DELIMITED_COMMENT: i32 = 190; -pub const WHITESPACES: i32 = 191; -pub const BYTE_ORDER_MARK: i32 = 192; -pub const DIRECTIVE_LINE: i32 = 193; -pub const INTERP_START: i32 = 194; -pub const INTERP_VERBATIM_START: i32 = 195; -pub const INTERP_RAW_START: i32 = 196; -pub const LBRACE: i32 = 197; -pub const RBRACE: i32 = 198; -pub const COLON: i32 = 199; -pub const LPAREN: i32 = 200; -pub const RPAREN: i32 = 201; -pub const LBRACKET: i32 = 202; -pub const RBRACKET: i32 = 203; -pub const INTERP_ESCAPED_OPEN: i32 = 204; -pub const INTERP_ESCAPED_CLOSE: i32 = 205; -pub const INTERP_V_ESCAPED_QUOTE: i32 = 206; - -pub const CHANNEL_COMMENTS_CHANNEL: i32 = 2; -pub const CHANNEL_DEFAULT_TOKEN_CHANNEL: i32 = 0; -pub const CHANNEL_DIRECTIVE: i32 = 3; -pub const CHANNEL_HIDDEN: i32 = 1; -pub const MODE_DEFAULT_MODE: i32 = 0; -pub const MODE_INTERPOLATION: i32 = 1; -pub const MODE_INTERPOLATION_FORMAT: i32 = 5; -pub const MODE_INTERPOLATION_RAW: i32 = 3; -pub const MODE_INTERPOLATION_RAW_2: i32 = 4; -pub const MODE_INTERPOLATION_RAW_2_4: i32 = 7; -pub const MODE_INTERPOLATION_RAW_4: i32 = 6; -pub const MODE_INTERPOLATION_VERBATIM: i32 = 2; - -pub static METADATA: GrammarMetadata = GrammarMetadata::new( - "CSharpLexer", - &["KW___REFVALUE", "KW_DESCENDING", "KW_STACKALLOC", "KW___ARGLIST", "KW___MAKEREF", "KW___REFTYPE", "KW_ASCENDING", "KW_EXTENSION", "KW_INTERFACE", "KW_NAMESPACE", "KW_PROTECTED", "KW_UNCHECKED", "KW_UNMANAGED", "KW_ABSTRACT", "KW_CONTINUE", "KW_DELEGATE", "KW_EXPLICIT", "KW_IMPLICIT", "KW_INTERNAL", "KW_OPERATOR", "KW_OVERRIDE", "KW_READONLY", "KW_REQUIRED", "KW_VOLATILE", "KW_CHECKED", "KW_DECIMAL", "KW_DEFAULT", "KW_FINALLY", "KW_FOREACH", "KW_MANAGED", "KW_ORDERBY", "KW_PARTIAL", "KW_PRIVATE", "KW_VIRTUAL", "KW_ALLOWS", "KW_CLOSED", "KW_DOUBLE", "KW_EQUALS", "KW_EXTERN", "KW_GLOBAL", "KW_OBJECT", "KW_PARAMS", "KW_PUBLIC", "KW_REMOVE", "KW_RETURN", "KW_SCOPED", "KW_SEALED", "KW_SELECT", "KW_SIZEOF", "KW_STATIC", "KW_STRING", "KW_STRUCT", "KW_SWITCH", "KW_TYPEOF", "KW_UNSAFE", "KW_USHORT", "KW_ALIAS", "KW_ASYNC", "KW_AWAIT", "KW_BREAK", "KW_CATCH", "KW_CLASS", "KW_CONST", "KW_EVENT", "KW_FALSE", "KW_FIELD", "KW_FIXED", "KW_FLOAT", "KW_GROUP", "KW_SBYTE", "KW_SHORT", "KW_THROW", "KW_ULONG", "KW_UNION", "KW_USING", "KW_WHERE", "KW_WHILE", "KW_YIELD", "KW_BASE", "KW_BOOL", "KW_BYTE", "KW_CASE", "KW_CHAR", "KW_ELSE", "KW_ENUM", "KW_FILE", "KW_FROM", "KW_GOTO", "KW_INIT", "KW_INTO", "KW_JOIN", "KW_LOCK", "KW_LONG", "KW_NULL", "KW_SAFE", "KW_THIS", "KW_TRUE", "KW_UINT", "KW_VOID", "KW_WHEN", "KW_WITH", "TRIPLE_DQUOTE", "LT_LT_EQ", "QUESTION_QUESTION_EQ", "KW_ADD", "KW_AND", "KW_FOR", "KW_GET", "KW_INT", "KW_LET", "KW_NEW", "KW_NOT", "KW_OUT", "KW_REF", "KW_SET", "KW_TRY", "KW_VAR", "NE", "PERCENT_EQ", "AMP_AMP", "AMP_EQ", "STAR_EQ", "PLUS_PLUS", "PLUS_EQ", "MINUS_MINUS", "MINUS_EQ", "MINUS_GT", "DOT_DOT", "SLASH_EQ", "SLASH_GT", "COLON_COLON", "LT_SLASH", "LT_LT", "LE", "EQ_EQ", "ARROW", "GE", "QUESTION_QUESTION", "KW_U8", "ESCAPED_QUOTE", "ESCAPED_BACKSLASH", "CARET_EQ", "KW_AS", "KW_BY", "KW_DO", "KW_IF", "KW_IN", "KW_IS", "KW_ON", "KW_OR", "KW_U8_LOWER", "PIPE_EQ", "PIPE_PIPE", "BANG", "DQUOTE", "HASH", "PERCENT", "AMP", "STAR", "PLUS", "COMMA", "MINUS", "DOT", "SLASH", "SEMICOLON", "LT", "EQ", "GT", "QUESTION", "CARET", "KW__", "PIPE", "TILDE", "KW_RECORD", "IDENTIFIER", "UnicodeEscape", "DEC_INT_LIT", "HEX_INT_LIT", "BIN_INT_LIT", "IntSuffix", "REAL_LIT", "ExponentPart", "CHAR_LIT", "Escape", "HexQuad", "STRING_LIT", "VERBATIM_STRING_LIT", "SL_RAW_STRING_LIT", "ML_RAW_STRING_LIT", "NewLine", "SINGLE_LINE_DOC_COMMENT", "DELIMITED_DOC_COMMENT", "SINGLE_LINE_COMMENT", "DELIMITED_COMMENT", "WHITESPACES", "BYTE_ORDER_MARK", "DIRECTIVE_LINE", "DirectiveString", "INTERP_START", "INTERP_VERBATIM_START", "INTERP_RAW_START_2_4", "INTERP_RAW_START_2", "INTERP_RAW_START_4", "INTERP_RAW_START", "INTERP_NESTED_CLOSE", "INTERP_NESTED_LPAREN", "INTERP_NESTED_RPAREN", "INTERP_NESTED_LBRACKET", "INTERP_NESTED_RBRACKET", "INTERP_HOLE_CLOSE_2", "INTERP_HOLE_CLOSE", "INTERP_NESTED_OPEN", "INTERP_NESTED_COLON", "INTERP_FORMAT_COLON", "LBRACE", "RBRACE", "COLON", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", "INTERP_ESCAPED_OPEN", "INTERP_ESCAPED_CLOSE", "INTERP_ESCAPE", "INTERPOLATED_TEXT", "INTERP_HOLE_OPEN", "INTERP_END", "INTERP_V_ESCAPED_OPEN", "INTERP_V_ESCAPED_CLOSE", "INTERP_V_ESCAPED_QUOTE", "INTERP_V_TEXT", "INTERP_V_HOLE_OPEN", "INTERP_V_END", "INTERP_R_ESCAPED_OPEN", "INTERP_R_ESCAPED_CLOSE", "INTERP_R_END", "INTERP_R_QUOTE", "INTERP_R_TEXT", "INTERP_R_HOLE_OPEN", "INTERP_R2_HOLE_OPEN", "INTERP_R2_END", "INTERP_R2_QUOTE", "INTERP_R2_TEXT", "INTERP_R2_LBRACE", "INTERP_R2_RBRACE", "INTERP_FORMAT_TEXT", "INTERP_FORMAT_END_2", "INTERP_FORMAT_END", "INTERP_R4_ESCAPED_OPEN", "INTERP_R4_ESCAPED_CLOSE", "INTERP_R4_END", "INTERP_R4_QUOTE", "INTERP_R4_TEXT", "INTERP_R4_HOLE_OPEN", "INTERP_R24_HOLE_OPEN", "INTERP_R24_END", "INTERP_R24_QUOTE", "INTERP_R24_TEXT", "INTERP_R24_LBRACE", "INTERP_R24_RBRACE"], - &[None, None, None, Some("\'__refvalue\'"), Some("\'descending\'"), Some("\'stackalloc\'"), Some("\'__arglist\'"), Some("\'__makeref\'"), Some("\'__reftype\'"), Some("\'ascending\'"), Some("\'extension\'"), Some("\'interface\'"), Some("\'namespace\'"), Some("\'protected\'"), Some("\'unchecked\'"), Some("\'unmanaged\'"), Some("\'abstract\'"), Some("\'continue\'"), Some("\'delegate\'"), Some("\'explicit\'"), Some("\'implicit\'"), Some("\'internal\'"), Some("\'operator\'"), Some("\'override\'"), Some("\'readonly\'"), Some("\'required\'"), Some("\'volatile\'"), Some("\'checked\'"), Some("\'decimal\'"), Some("\'default\'"), Some("\'finally\'"), Some("\'foreach\'"), Some("\'managed\'"), Some("\'orderby\'"), Some("\'partial\'"), Some("\'private\'"), Some("\'virtual\'"), Some("\'allows\'"), Some("\'closed\'"), Some("\'double\'"), Some("\'equals\'"), Some("\'extern\'"), Some("\'global\'"), Some("\'object\'"), Some("\'params\'"), Some("\'public\'"), Some("\'remove\'"), Some("\'return\'"), Some("\'scoped\'"), Some("\'sealed\'"), Some("\'select\'"), Some("\'sizeof\'"), Some("\'static\'"), Some("\'string\'"), Some("\'struct\'"), Some("\'switch\'"), Some("\'typeof\'"), Some("\'unsafe\'"), Some("\'ushort\'"), Some("\'alias\'"), Some("\'async\'"), Some("\'await\'"), Some("\'break\'"), Some("\'catch\'"), Some("\'class\'"), Some("\'const\'"), Some("\'event\'"), Some("\'false\'"), Some("\'field\'"), Some("\'fixed\'"), Some("\'float\'"), Some("\'group\'"), Some("\'sbyte\'"), Some("\'short\'"), Some("\'throw\'"), Some("\'ulong\'"), Some("\'union\'"), Some("\'using\'"), Some("\'where\'"), Some("\'while\'"), Some("\'yield\'"), Some("\'base\'"), Some("\'bool\'"), Some("\'byte\'"), Some("\'case\'"), Some("\'char\'"), Some("\'else\'"), Some("\'enum\'"), Some("\'file\'"), Some("\'from\'"), Some("\'goto\'"), Some("\'init\'"), Some("\'into\'"), Some("\'join\'"), Some("\'lock\'"), Some("\'long\'"), Some("\'null\'"), Some("\'safe\'"), Some("\'this\'"), Some("\'true\'"), Some("\'uint\'"), Some("\'void\'"), Some("\'when\'"), Some("\'with\'"), Some("\'\"\"\"\'"), Some("\'<<=\'"), Some("\'??=\'"), Some("\'add\'"), Some("\'and\'"), Some("\'for\'"), Some("\'get\'"), Some("\'int\'"), Some("\'let\'"), Some("\'new\'"), Some("\'not\'"), Some("\'out\'"), Some("\'ref\'"), Some("\'set\'"), Some("\'try\'"), Some("\'var\'"), Some("\'!=\'"), Some("\'%=\'"), Some("\'&&\'"), Some("\'&=\'"), Some("\'*=\'"), Some("\'++\'"), Some("\'+=\'"), Some("\'--\'"), Some("\'-=\'"), Some("\'->\'"), Some("\'..\'"), Some("\'/=\'"), Some("\'/>\'"), Some("\'::\'"), Some("\'\'"), Some("\'>=\'"), Some("\'??\'"), Some("\'U8\'"), Some("\'\\\'\'"), Some("\'\\\\\'"), Some("\'^=\'"), Some("\'as\'"), Some("\'by\'"), Some("\'do\'"), Some("\'if\'"), Some("\'in\'"), Some("\'is\'"), Some("\'on\'"), Some("\'or\'"), Some("\'u8\'"), Some("\'|=\'"), Some("\'||\'"), Some("\'!\'"), None, Some("\'#\'"), Some("\'%\'"), Some("\'&\'"), Some("\'*\'"), Some("\'+\'"), Some("\',\'"), Some("\'-\'"), Some("\'.\'"), Some("\'/\'"), Some("\';\'"), Some("\'<\'"), Some("\'=\'"), Some("\'>\'"), Some("\'?\'"), Some("\'^\'"), Some("\'_\'"), Some("\'|\'"), Some("\'~\'"), Some("\'record\'"), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, Some("\'\u{feff}\'"), None, Some("\'$\"\'"), None, None, None, None, Some("\':\'"), Some("\'(\'"), Some("\')\'"), Some("\'[\'"), Some("\']\'"), None, None, Some("\'\"\"\'")], - &[None, Some("INTERPOLATED_TEXT"), Some("XML_TEXT_LIT"), Some("KW___REFVALUE"), Some("KW_DESCENDING"), Some("KW_STACKALLOC"), Some("KW___ARGLIST"), Some("KW___MAKEREF"), Some("KW___REFTYPE"), Some("KW_ASCENDING"), Some("KW_EXTENSION"), Some("KW_INTERFACE"), Some("KW_NAMESPACE"), Some("KW_PROTECTED"), Some("KW_UNCHECKED"), Some("KW_UNMANAGED"), Some("KW_ABSTRACT"), Some("KW_CONTINUE"), Some("KW_DELEGATE"), Some("KW_EXPLICIT"), Some("KW_IMPLICIT"), Some("KW_INTERNAL"), Some("KW_OPERATOR"), Some("KW_OVERRIDE"), Some("KW_READONLY"), Some("KW_REQUIRED"), Some("KW_VOLATILE"), Some("KW_CHECKED"), Some("KW_DECIMAL"), Some("KW_DEFAULT"), Some("KW_FINALLY"), Some("KW_FOREACH"), Some("KW_MANAGED"), Some("KW_ORDERBY"), Some("KW_PARTIAL"), Some("KW_PRIVATE"), Some("KW_VIRTUAL"), Some("KW_ALLOWS"), Some("KW_CLOSED"), Some("KW_DOUBLE"), Some("KW_EQUALS"), Some("KW_EXTERN"), Some("KW_GLOBAL"), Some("KW_OBJECT"), Some("KW_PARAMS"), Some("KW_PUBLIC"), Some("KW_REMOVE"), Some("KW_RETURN"), Some("KW_SCOPED"), Some("KW_SEALED"), Some("KW_SELECT"), Some("KW_SIZEOF"), Some("KW_STATIC"), Some("KW_STRING"), Some("KW_STRUCT"), Some("KW_SWITCH"), Some("KW_TYPEOF"), Some("KW_UNSAFE"), Some("KW_USHORT"), Some("KW_ALIAS"), Some("KW_ASYNC"), Some("KW_AWAIT"), Some("KW_BREAK"), Some("KW_CATCH"), Some("KW_CLASS"), Some("KW_CONST"), Some("KW_EVENT"), Some("KW_FALSE"), Some("KW_FIELD"), Some("KW_FIXED"), Some("KW_FLOAT"), Some("KW_GROUP"), Some("KW_SBYTE"), Some("KW_SHORT"), Some("KW_THROW"), Some("KW_ULONG"), Some("KW_UNION"), Some("KW_USING"), Some("KW_WHERE"), Some("KW_WHILE"), Some("KW_YIELD"), Some("KW_BASE"), Some("KW_BOOL"), Some("KW_BYTE"), Some("KW_CASE"), Some("KW_CHAR"), Some("KW_ELSE"), Some("KW_ENUM"), Some("KW_FILE"), Some("KW_FROM"), Some("KW_GOTO"), Some("KW_INIT"), Some("KW_INTO"), Some("KW_JOIN"), Some("KW_LOCK"), Some("KW_LONG"), Some("KW_NULL"), Some("KW_SAFE"), Some("KW_THIS"), Some("KW_TRUE"), Some("KW_UINT"), Some("KW_VOID"), Some("KW_WHEN"), Some("KW_WITH"), Some("TRIPLE_DQUOTE"), Some("LT_LT_EQ"), Some("QUESTION_QUESTION_EQ"), Some("KW_ADD"), Some("KW_AND"), Some("KW_FOR"), Some("KW_GET"), Some("KW_INT"), Some("KW_LET"), Some("KW_NEW"), Some("KW_NOT"), Some("KW_OUT"), Some("KW_REF"), Some("KW_SET"), Some("KW_TRY"), Some("KW_VAR"), Some("NE"), Some("PERCENT_EQ"), Some("AMP_AMP"), Some("AMP_EQ"), Some("STAR_EQ"), Some("PLUS_PLUS"), Some("PLUS_EQ"), Some("MINUS_MINUS"), Some("MINUS_EQ"), Some("MINUS_GT"), Some("DOT_DOT"), Some("SLASH_EQ"), Some("SLASH_GT"), Some("COLON_COLON"), Some("LT_SLASH"), Some("LT_LT"), Some("LE"), Some("EQ_EQ"), Some("ARROW"), Some("GE"), Some("QUESTION_QUESTION"), Some("KW_U8"), Some("ESCAPED_QUOTE"), Some("ESCAPED_BACKSLASH"), Some("CARET_EQ"), Some("KW_AS"), Some("KW_BY"), Some("KW_DO"), Some("KW_IF"), Some("KW_IN"), Some("KW_IS"), Some("KW_ON"), Some("KW_OR"), Some("KW_U8_LOWER"), Some("PIPE_EQ"), Some("PIPE_PIPE"), Some("BANG"), Some("DQUOTE"), Some("HASH"), Some("PERCENT"), Some("AMP"), Some("STAR"), Some("PLUS"), Some("COMMA"), Some("MINUS"), Some("DOT"), Some("SLASH"), Some("SEMICOLON"), Some("LT"), Some("EQ"), Some("GT"), Some("QUESTION"), Some("CARET"), Some("KW__"), Some("PIPE"), Some("TILDE"), Some("KW_RECORD"), Some("IDENTIFIER"), Some("DEC_INT_LIT"), Some("HEX_INT_LIT"), Some("BIN_INT_LIT"), Some("REAL_LIT"), Some("CHAR_LIT"), Some("STRING_LIT"), Some("VERBATIM_STRING_LIT"), Some("SL_RAW_STRING_LIT"), Some("ML_RAW_STRING_LIT"), Some("SINGLE_LINE_DOC_COMMENT"), Some("DELIMITED_DOC_COMMENT"), Some("SINGLE_LINE_COMMENT"), Some("DELIMITED_COMMENT"), Some("WHITESPACES"), Some("BYTE_ORDER_MARK"), Some("DIRECTIVE_LINE"), Some("INTERP_START"), Some("INTERP_VERBATIM_START"), Some("INTERP_RAW_START"), Some("LBRACE"), Some("RBRACE"), Some("COLON"), Some("LPAREN"), Some("RPAREN"), Some("LBRACKET"), Some("RBRACKET"), Some("INTERP_ESCAPED_OPEN"), Some("INTERP_ESCAPED_CLOSE"), Some("INTERP_V_ESCAPED_QUOTE")], - &[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &["DEFAULT_TOKEN_CHANNEL", "HIDDEN", "COMMENTS_CHANNEL", "DIRECTIVE"], - &["DEFAULT_MODE", "INTERPOLATION", "INTERPOLATION_VERBATIM", "INTERPOLATION_RAW", "INTERPOLATION_RAW_2", "INTERPOLATION_FORMAT", "INTERPOLATION_RAW_4", "INTERPOLATION_RAW_2_4"], - &[4, 0, 206, 2460, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 2, 202, 7, 202, 2, 203, 7, 203, 2, 204, 7, 204, 2, 205, 7, 205, 2, 206, 7, 206, 2, 207, 7, 207, 2, 208, 7, 208, 2, 209, 7, 209, 2, 210, 7, 210, 2, 211, 7, 211, 2, 212, 7, 212, 2, 213, 7, 213, 2, 214, 7, 214, 2, 215, 7, 215, 2, 216, 7, 216, 2, 217, 7, 217, 2, 218, 7, 218, 2, 219, 7, 219, 2, 220, 7, 220, 2, 221, 7, 221, 2, 222, 7, 222, 2, 223, 7, 223, 2, 224, 7, 224, 2, 225, 7, 225, 2, 226, 7, 226, 2, 227, 7, 227, 2, 228, 7, 228, 2, 229, 7, 229, 2, 230, 7, 230, 2, 231, 7, 231, 2, 232, 7, 232, 2, 233, 7, 233, 2, 234, 7, 234, 2, 235, 7, 235, 2, 236, 7, 236, 2, 237, 7, 237, 2, 238, 7, 238, 2, 239, 7, 239, 2, 240, 7, 240, 2, 241, 7, 241, 2, 242, 7, 242, 2, 243, 7, 243, 2, 244, 7, 244, 2, 245, 7, 245, 2, 246, 7, 246, 2, 247, 7, 247, 2, 248, 7, 248, 2, 249, 7, 249, 2, 250, 7, 250, 2, 251, 7, 251, 2, 252, 7, 252, 2, 253, 7, 253, 2, 254, 7, 254, 2, 255, 7, 255, 2, 256, 7, 256, 2, 257, 7, 257, 2, 258, 7, 258, 2, 259, 7, 259, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 154, 1, 154, 1, 155, 1, 155, 1, 156, 1, 156, 1, 157, 1, 157, 1, 158, 1, 158, 1, 159, 1, 159, 1, 160, 1, 160, 1, 161, 1, 161, 1, 162, 1, 162, 1, 163, 1, 163, 1, 164, 1, 164, 1, 165, 1, 165, 1, 166, 1, 166, 1, 167, 1, 167, 1, 168, 1, 168, 1, 169, 1, 169, 1, 170, 1, 170, 1, 171, 1, 171, 1, 172, 1, 172, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 174, 3, 174, 1460, 8, 174, 1, 174, 1, 174, 3, 174, 1464, 8, 174, 1, 174, 1, 174, 5, 174, 1468, 8, 174, 10, 174, 12, 174, 1471, 9, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 3, 175, 1480, 8, 175, 1, 176, 1, 176, 5, 176, 1484, 8, 176, 10, 176, 12, 176, 1487, 9, 176, 1, 176, 5, 176, 1490, 8, 176, 10, 176, 12, 176, 1493, 9, 176, 1, 176, 3, 176, 1496, 8, 176, 1, 177, 1, 177, 1, 177, 1, 177, 5, 177, 1502, 8, 177, 10, 177, 12, 177, 1505, 9, 177, 1, 177, 5, 177, 1508, 8, 177, 10, 177, 12, 177, 1511, 9, 177, 1, 177, 3, 177, 1514, 8, 177, 1, 178, 1, 178, 1, 178, 1, 178, 5, 178, 1520, 8, 178, 10, 178, 12, 178, 1523, 9, 178, 1, 178, 5, 178, 1526, 8, 178, 10, 178, 12, 178, 1529, 9, 178, 1, 178, 3, 178, 1532, 8, 178, 1, 179, 1, 179, 3, 179, 1536, 8, 179, 1, 179, 1, 179, 3, 179, 1540, 8, 179, 3, 179, 1542, 8, 179, 1, 180, 1, 180, 5, 180, 1546, 8, 180, 10, 180, 12, 180, 1549, 9, 180, 1, 180, 1, 180, 1, 180, 5, 180, 1554, 8, 180, 10, 180, 12, 180, 1557, 9, 180, 1, 180, 3, 180, 1560, 8, 180, 1, 180, 3, 180, 1563, 8, 180, 1, 180, 1, 180, 1, 180, 5, 180, 1568, 8, 180, 10, 180, 12, 180, 1571, 9, 180, 1, 180, 3, 180, 1574, 8, 180, 1, 180, 3, 180, 1577, 8, 180, 1, 180, 1, 180, 5, 180, 1581, 8, 180, 10, 180, 12, 180, 1584, 9, 180, 1, 180, 1, 180, 3, 180, 1588, 8, 180, 1, 180, 1, 180, 5, 180, 1592, 8, 180, 10, 180, 12, 180, 1595, 9, 180, 1, 180, 3, 180, 1598, 8, 180, 1, 181, 1, 181, 3, 181, 1602, 8, 181, 1, 181, 1, 181, 5, 181, 1606, 8, 181, 10, 181, 12, 181, 1609, 9, 181, 1, 182, 1, 182, 1, 182, 3, 182, 1614, 8, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 3, 183, 1628, 8, 183, 1, 183, 3, 183, 1631, 8, 183, 1, 183, 3, 183, 1634, 8, 183, 1, 183, 3, 183, 1637, 8, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 5, 185, 1647, 8, 185, 10, 185, 12, 185, 1650, 9, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 5, 186, 1660, 8, 186, 10, 186, 12, 186, 1663, 9, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1677, 8, 187, 10, 187, 12, 187, 1680, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1692, 8, 187, 10, 187, 12, 187, 1695, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1706, 8, 187, 10, 187, 12, 187, 1709, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1720, 8, 187, 10, 187, 12, 187, 1723, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1733, 8, 187, 10, 187, 12, 187, 1736, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1746, 8, 187, 10, 187, 12, 187, 1749, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1758, 8, 187, 10, 187, 12, 187, 1761, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1770, 8, 187, 10, 187, 12, 187, 1773, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1781, 8, 187, 10, 187, 12, 187, 1784, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1792, 8, 187, 10, 187, 12, 187, 1795, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1802, 8, 187, 10, 187, 12, 187, 1805, 9, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 5, 187, 1812, 8, 187, 10, 187, 12, 187, 1815, 9, 187, 3, 187, 1817, 8, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1829, 8, 188, 10, 188, 12, 188, 1832, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1844, 8, 188, 10, 188, 12, 188, 1847, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1858, 8, 188, 10, 188, 12, 188, 1861, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1872, 8, 188, 10, 188, 12, 188, 1875, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1885, 8, 188, 10, 188, 12, 188, 1888, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1898, 8, 188, 10, 188, 12, 188, 1901, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1910, 8, 188, 10, 188, 12, 188, 1913, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1922, 8, 188, 10, 188, 12, 188, 1925, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1933, 8, 188, 10, 188, 12, 188, 1936, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1944, 8, 188, 10, 188, 12, 188, 1947, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1954, 8, 188, 10, 188, 12, 188, 1957, 9, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 5, 188, 1964, 8, 188, 10, 188, 12, 188, 1967, 9, 188, 3, 188, 1969, 8, 188, 1, 189, 1, 189, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 5, 190, 1978, 8, 190, 10, 190, 12, 190, 1981, 9, 190, 1, 190, 1, 190, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 5, 191, 1990, 8, 191, 10, 191, 12, 191, 1993, 9, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 192, 1, 192, 1, 192, 1, 192, 5, 192, 2004, 8, 192, 10, 192, 12, 192, 2007, 9, 192, 1, 192, 1, 192, 1, 193, 1, 193, 1, 193, 1, 193, 5, 193, 2015, 8, 193, 10, 193, 12, 193, 2018, 9, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 194, 1, 194, 4, 194, 2027, 8, 194, 11, 194, 12, 194, 2028, 1, 194, 1, 194, 1, 195, 1, 195, 1, 195, 1, 195, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 5, 196, 2042, 8, 196, 10, 196, 12, 196, 2045, 9, 196, 1, 196, 1, 196, 3, 196, 2049, 8, 196, 3, 196, 2051, 8, 196, 1, 196, 1, 196, 1, 197, 1, 197, 5, 197, 2057, 8, 197, 10, 197, 12, 197, 2060, 9, 197, 1, 197, 1, 197, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 3, 199, 2075, 8, 199, 1, 199, 1, 199, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 201, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 202, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 203, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 204, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 205, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 206, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 208, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 209, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 210, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 211, 1, 212, 1, 212, 1, 212, 1, 212, 1, 212, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 213, 1, 214, 1, 214, 1, 215, 1, 215, 1, 216, 1, 216, 1, 217, 1, 217, 1, 218, 1, 218, 1, 219, 1, 219, 1, 220, 1, 220, 1, 221, 1, 221, 1, 221, 1, 221, 1, 221, 1, 222, 1, 222, 1, 222, 1, 222, 1, 222, 1, 223, 1, 223, 1, 223, 1, 223, 1, 224, 4, 224, 2208, 8, 224, 11, 224, 12, 224, 2209, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 225, 1, 226, 1, 226, 1, 226, 1, 226, 1, 226, 1, 227, 1, 227, 1, 227, 1, 227, 1, 227, 1, 228, 1, 228, 1, 228, 1, 228, 1, 228, 1, 229, 1, 229, 1, 229, 1, 229, 1, 229, 1, 230, 4, 230, 2239, 8, 230, 11, 230, 12, 230, 2240, 1, 230, 1, 230, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 231, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 233, 1, 233, 1, 233, 1, 233, 1, 233, 1, 234, 1, 234, 1, 234, 1, 234, 1, 234, 1, 235, 1, 235, 1, 235, 1, 235, 1, 235, 5, 235, 2271, 8, 235, 10, 235, 12, 235, 2274, 9, 235, 1, 235, 1, 235, 1, 235, 1, 236, 1, 236, 3, 236, 2281, 8, 236, 1, 236, 1, 236, 1, 237, 4, 237, 2286, 8, 237, 11, 237, 12, 237, 2287, 1, 237, 1, 237, 1, 238, 1, 238, 1, 238, 1, 238, 1, 238, 1, 238, 1, 239, 1, 239, 1, 239, 1, 239, 1, 239, 1, 239, 1, 239, 1, 239, 1, 240, 1, 240, 1, 240, 1, 240, 1, 240, 5, 240, 2311, 8, 240, 10, 240, 12, 240, 2314, 9, 240, 1, 240, 1, 240, 1, 240, 1, 241, 1, 241, 3, 241, 2321, 8, 241, 1, 241, 1, 241, 1, 242, 4, 242, 2326, 8, 242, 11, 242, 12, 242, 2327, 1, 242, 1, 242, 1, 243, 1, 243, 1, 243, 1, 243, 1, 244, 1, 244, 1, 244, 1, 244, 1, 245, 1, 245, 1, 245, 1, 245, 1, 245, 1, 245, 4, 245, 2346, 8, 245, 11, 245, 12, 245, 2347, 1, 245, 1, 245, 1, 246, 1, 246, 1, 246, 1, 246, 1, 246, 1, 246, 1, 246, 1, 246, 1, 246, 1, 246, 1, 247, 1, 247, 1, 247, 1, 247, 1, 247, 1, 247, 1, 247, 1, 248, 1, 248, 1, 248, 1, 248, 1, 248, 1, 249, 1, 249, 1, 249, 1, 249, 1, 249, 1, 250, 1, 250, 1, 250, 1, 250, 1, 250, 1, 250, 5, 250, 2385, 8, 250, 10, 250, 12, 250, 2388, 9, 250, 1, 250, 1, 250, 1, 250, 1, 251, 1, 251, 3, 251, 2395, 8, 251, 1, 251, 3, 251, 2398, 8, 251, 1, 251, 1, 251, 1, 252, 4, 252, 2403, 8, 252, 11, 252, 12, 252, 2404, 1, 252, 1, 252, 1, 253, 1, 253, 1, 253, 1, 253, 1, 253, 1, 253, 1, 254, 1, 254, 1, 254, 1, 254, 1, 254, 1, 254, 1, 254, 1, 254, 1, 255, 1, 255, 1, 255, 1, 255, 1, 255, 1, 255, 5, 255, 2429, 8, 255, 10, 255, 12, 255, 2432, 9, 255, 1, 255, 1, 255, 1, 255, 1, 256, 1, 256, 3, 256, 2439, 8, 256, 1, 256, 3, 256, 2442, 8, 256, 1, 256, 1, 256, 1, 257, 4, 257, 2447, 8, 257, 11, 257, 12, 257, 2448, 1, 257, 1, 257, 1, 258, 1, 258, 1, 258, 1, 258, 1, 259, 1, 259, 1, 259, 1, 259, 14, 1678, 1707, 1734, 1759, 1782, 1803, 1830, 1859, 1886, 1911, 1934, 1955, 1991, 2016, 0, 260, 8, 3, 10, 4, 12, 5, 14, 6, 16, 7, 18, 8, 20, 9, 22, 10, 24, 11, 26, 12, 28, 13, 30, 14, 32, 15, 34, 16, 36, 17, 38, 18, 40, 19, 42, 20, 44, 21, 46, 22, 48, 23, 50, 24, 52, 25, 54, 26, 56, 27, 58, 28, 60, 29, 62, 30, 64, 31, 66, 32, 68, 33, 70, 34, 72, 35, 74, 36, 76, 37, 78, 38, 80, 39, 82, 40, 84, 41, 86, 42, 88, 43, 90, 44, 92, 45, 94, 46, 96, 47, 98, 48, 100, 49, 102, 50, 104, 51, 106, 52, 108, 53, 110, 54, 112, 55, 114, 56, 116, 57, 118, 58, 120, 59, 122, 60, 124, 61, 126, 62, 128, 63, 130, 64, 132, 65, 134, 66, 136, 67, 138, 68, 140, 69, 142, 70, 144, 71, 146, 72, 148, 73, 150, 74, 152, 75, 154, 76, 156, 77, 158, 78, 160, 79, 162, 80, 164, 81, 166, 82, 168, 83, 170, 84, 172, 85, 174, 86, 176, 87, 178, 88, 180, 89, 182, 90, 184, 91, 186, 92, 188, 93, 190, 94, 192, 95, 194, 96, 196, 97, 198, 98, 200, 99, 202, 100, 204, 101, 206, 102, 208, 103, 210, 104, 212, 105, 214, 106, 216, 107, 218, 108, 220, 109, 222, 110, 224, 111, 226, 112, 228, 113, 230, 114, 232, 115, 234, 116, 236, 117, 238, 118, 240, 119, 242, 120, 244, 121, 246, 122, 248, 123, 250, 124, 252, 125, 254, 126, 256, 127, 258, 128, 260, 129, 262, 130, 264, 131, 266, 132, 268, 133, 270, 134, 272, 135, 274, 136, 276, 137, 278, 138, 280, 139, 282, 140, 284, 141, 286, 142, 288, 143, 290, 144, 292, 145, 294, 146, 296, 147, 298, 148, 300, 149, 302, 150, 304, 151, 306, 152, 308, 153, 310, 154, 312, 155, 314, 156, 316, 157, 318, 158, 320, 159, 322, 160, 324, 161, 326, 162, 328, 163, 330, 164, 332, 165, 334, 166, 336, 167, 338, 168, 340, 169, 342, 170, 344, 171, 346, 172, 348, 173, 350, 174, 352, 175, 354, 176, 356, 177, 358, 0, 360, 178, 362, 179, 364, 180, 366, 0, 368, 181, 370, 0, 372, 182, 374, 0, 376, 0, 378, 183, 380, 184, 382, 185, 384, 186, 386, 0, 388, 187, 390, 188, 392, 189, 394, 190, 396, 191, 398, 192, 400, 193, 402, 0, 404, 194, 406, 195, 408, 0, 410, 0, 412, 0, 414, 196, 416, 0, 418, 0, 420, 0, 422, 0, 424, 0, 426, 0, 428, 0, 430, 0, 432, 0, 434, 0, 436, 197, 438, 198, 440, 199, 442, 200, 444, 201, 446, 202, 448, 203, 450, 204, 452, 205, 454, 0, 456, 1, 458, 0, 460, 0, 462, 0, 464, 0, 466, 206, 468, 0, 470, 0, 472, 0, 474, 0, 476, 0, 478, 0, 480, 0, 482, 0, 484, 0, 486, 0, 488, 0, 490, 0, 492, 0, 494, 0, 496, 0, 498, 0, 500, 0, 502, 0, 504, 0, 506, 0, 508, 0, 510, 0, 512, 0, 514, 0, 516, 0, 518, 0, 520, 0, 522, 0, 524, 0, 526, 0, 8, 0, 1, 2, 3, 4, 5, 6, 7, 27, 688, 0, 65, 90, 95, 95, 97, 122, 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 895, 895, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1327, 1329, 1366, 1369, 1369, 1376, 1416, 1488, 1514, 1519, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2144, 2154, 2160, 2183, 2185, 2191, 2208, 2249, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2432, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2556, 2556, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2809, 2809, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3129, 3133, 3133, 3160, 3162, 3164, 3165, 3168, 3169, 3200, 3200, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3292, 3294, 3296, 3297, 3313, 3314, 3332, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3412, 3414, 3423, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5880, 5888, 5905, 5919, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6264, 6272, 6276, 6279, 6312, 6314, 6314, 6320, 6389, 6400, 6430, 6480, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6988, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7296, 7306, 7312, 7354, 7357, 7359, 7401, 7404, 7406, 7411, 7413, 7414, 7418, 7418, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12591, 12593, 12686, 12704, 12735, 12784, 12799, 13312, 19903, 19968, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42653, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42972, 42993, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43261, 43262, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43488, 43492, 43494, 43503, 43514, 43518, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43646, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, 43868, 43881, 43888, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66335, 66349, 66378, 66384, 66421, 66432, 66461, 66464, 66499, 66504, 66511, 66513, 66517, 66560, 66717, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 66928, 66938, 66940, 66954, 66956, 66962, 66964, 66965, 66967, 66977, 66979, 66993, 66995, 67001, 67003, 67004, 67008, 67059, 67072, 67382, 67392, 67413, 67424, 67431, 67456, 67461, 67463, 67504, 67506, 67514, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, 67808, 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67904, 67929, 67968, 68023, 68030, 68031, 68096, 68096, 68112, 68115, 68117, 68119, 68121, 68149, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68324, 68352, 68405, 68416, 68437, 68448, 68466, 68480, 68497, 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68899, 68938, 68965, 68975, 68997, 69248, 69289, 69296, 69297, 69314, 69319, 69376, 69404, 69415, 69415, 69424, 69445, 69488, 69505, 69552, 69572, 69600, 69622, 69635, 69687, 69745, 69746, 69749, 69749, 69763, 69807, 69840, 69864, 69891, 69926, 69956, 69956, 69959, 69959, 69968, 70002, 70006, 70006, 70019, 70066, 70081, 70084, 70106, 70106, 70108, 70108, 70144, 70161, 70163, 70187, 70207, 70208, 70272, 70278, 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70366, 70405, 70412, 70415, 70416, 70419, 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70461, 70461, 70480, 70480, 70493, 70497, 70528, 70537, 70539, 70539, 70542, 70542, 70544, 70581, 70583, 70583, 70609, 70609, 70611, 70611, 70656, 70708, 70727, 70730, 70751, 70753, 70784, 70831, 70852, 70853, 70855, 70855, 71040, 71086, 71128, 71131, 71168, 71215, 71236, 71236, 71296, 71338, 71352, 71352, 71424, 71450, 71488, 71494, 71680, 71723, 71840, 71903, 71935, 71942, 71945, 71945, 71948, 71955, 71957, 71958, 71960, 71983, 71999, 71999, 72001, 72001, 72096, 72103, 72106, 72144, 72161, 72161, 72163, 72163, 72192, 72192, 72203, 72242, 72250, 72250, 72272, 72272, 72284, 72329, 72349, 72349, 72368, 72440, 72640, 72672, 72704, 72712, 72714, 72750, 72768, 72768, 72818, 72847, 72960, 72966, 72968, 72969, 72971, 73008, 73030, 73030, 73056, 73061, 73063, 73064, 73066, 73097, 73112, 73112, 73136, 73179, 73440, 73458, 73474, 73474, 73476, 73488, 73490, 73523, 73648, 73648, 73728, 74649, 74752, 74862, 74880, 75075, 77712, 77808, 77824, 78895, 78913, 78918, 78944, 82938, 82944, 83526, 90368, 90397, 92160, 92728, 92736, 92766, 92784, 92862, 92880, 92909, 92928, 92975, 92992, 92995, 93027, 93047, 93053, 93071, 93504, 93548, 93760, 93823, 93856, 93880, 93883, 93907, 93952, 94026, 94032, 94032, 94099, 94111, 94176, 94177, 94179, 94179, 94194, 94198, 94208, 101589, 101631, 101662, 101760, 101874, 110576, 110579, 110581, 110587, 110589, 110590, 110592, 110882, 110898, 110898, 110928, 110930, 110933, 110933, 110948, 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 119808, 119892, 119894, 119964, 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144, 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686, 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, 122624, 122654, 122661, 122666, 122928, 122989, 123136, 123180, 123191, 123197, 123214, 123214, 123536, 123565, 123584, 123627, 124112, 124139, 124368, 124397, 124400, 124400, 124608, 124638, 124640, 124642, 124644, 124645, 124647, 124653, 124656, 124660, 124670, 124671, 124896, 124902, 124904, 124907, 124909, 124910, 124912, 124926, 124928, 125124, 125184, 125251, 125259, 125259, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516, 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, 126543, 126545, 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, 126562, 126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, 126619, 126625, 126627, 126629, 126633, 126635, 126651, 131072, 173791, 173824, 178205, 178208, 183981, 183984, 191456, 191472, 192093, 194560, 195101, 196608, 201546, 201552, 210041, 811, 0, 48, 57, 65, 90, 95, 95, 97, 122, 170, 170, 173, 173, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 895, 895, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1327, 1329, 1366, 1369, 1369, 1376, 1416, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1519, 1522, 1536, 1541, 1552, 1562, 1564, 1564, 1568, 1641, 1646, 1747, 1749, 1757, 1759, 1768, 1770, 1788, 1791, 1791, 1807, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2045, 2045, 2048, 2093, 2112, 2139, 2144, 2154, 2160, 2183, 2185, 2193, 2199, 2403, 2406, 2415, 2417, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2556, 2556, 2558, 2558, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2809, 2815, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2901, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3072, 3084, 3086, 3088, 3090, 3112, 3114, 3129, 3132, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3162, 3164, 3165, 3168, 3171, 3174, 3183, 3200, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3292, 3294, 3296, 3299, 3302, 3311, 3313, 3315, 3328, 3340, 3342, 3344, 3346, 3396, 3398, 3400, 3402, 3406, 3412, 3415, 3423, 3427, 3430, 3439, 3450, 3455, 3457, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3558, 3567, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3773, 3776, 3780, 3782, 3782, 3784, 3790, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5880, 5888, 5909, 5919, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6169, 6176, 6264, 6272, 6314, 6320, 6389, 6400, 6430, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6832, 6845, 6847, 6877, 6880, 6891, 6912, 6988, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7296, 7306, 7312, 7354, 7357, 7359, 7376, 7378, 7380, 7418, 7424, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8203, 8207, 8234, 8238, 8255, 8256, 8276, 8276, 8288, 8292, 8294, 8303, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12591, 12593, 12686, 12704, 12735, 12784, 12799, 13312, 19903, 19968, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42737, 42775, 42783, 42786, 42888, 42891, 42972, 42993, 43047, 43052, 43052, 43072, 43123, 43136, 43205, 43216, 43225, 43232, 43255, 43259, 43259, 43261, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43488, 43518, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, 43868, 43881, 43888, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65071, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65279, 65279, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, 65529, 65531, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, 65856, 65908, 66045, 66045, 66176, 66204, 66208, 66256, 66272, 66272, 66304, 66335, 66349, 66378, 66384, 66426, 66432, 66461, 66464, 66499, 66504, 66511, 66513, 66517, 66560, 66717, 66720, 66729, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 66928, 66938, 66940, 66954, 66956, 66962, 66964, 66965, 66967, 66977, 66979, 66993, 66995, 67001, 67003, 67004, 67008, 67059, 67072, 67382, 67392, 67413, 67424, 67431, 67456, 67461, 67463, 67504, 67506, 67514, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, 67808, 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67904, 67929, 67968, 68023, 68030, 68031, 68096, 68099, 68101, 68102, 68108, 68115, 68117, 68119, 68121, 68149, 68152, 68154, 68159, 68159, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68326, 68352, 68405, 68416, 68437, 68448, 68466, 68480, 68497, 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68903, 68912, 68921, 68928, 68965, 68969, 68973, 68975, 68997, 69248, 69289, 69291, 69292, 69296, 69297, 69314, 69319, 69370, 69404, 69415, 69415, 69424, 69456, 69488, 69509, 69552, 69572, 69600, 69622, 69632, 69702, 69734, 69749, 69759, 69818, 69821, 69821, 69826, 69826, 69837, 69837, 69840, 69864, 69872, 69881, 69888, 69940, 69942, 69951, 69956, 69959, 69968, 70003, 70006, 70006, 70016, 70084, 70089, 70092, 70094, 70106, 70108, 70108, 70144, 70161, 70163, 70199, 70206, 70209, 70272, 70278, 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70378, 70384, 70393, 70400, 70403, 70405, 70412, 70415, 70416, 70419, 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70459, 70468, 70471, 70472, 70475, 70477, 70480, 70480, 70487, 70487, 70493, 70499, 70502, 70508, 70512, 70516, 70528, 70537, 70539, 70539, 70542, 70542, 70544, 70581, 70583, 70592, 70594, 70594, 70597, 70597, 70599, 70602, 70604, 70611, 70625, 70626, 70656, 70730, 70736, 70745, 70750, 70753, 70784, 70853, 70855, 70855, 70864, 70873, 71040, 71093, 71096, 71104, 71128, 71133, 71168, 71232, 71236, 71236, 71248, 71257, 71296, 71352, 71360, 71369, 71376, 71395, 71424, 71450, 71453, 71467, 71472, 71481, 71488, 71494, 71680, 71738, 71840, 71913, 71935, 71942, 71945, 71945, 71948, 71955, 71957, 71958, 71960, 71989, 71991, 71992, 71995, 72003, 72016, 72025, 72096, 72103, 72106, 72151, 72154, 72161, 72163, 72164, 72192, 72254, 72263, 72263, 72272, 72345, 72349, 72349, 72368, 72440, 72544, 72551, 72640, 72672, 72688, 72697, 72704, 72712, 72714, 72758, 72760, 72768, 72784, 72793, 72818, 72847, 72850, 72871, 72873, 72886, 72960, 72966, 72968, 72969, 72971, 73014, 73018, 73018, 73020, 73021, 73023, 73031, 73040, 73049, 73056, 73061, 73063, 73064, 73066, 73102, 73104, 73105, 73107, 73112, 73120, 73129, 73136, 73179, 73184, 73193, 73440, 73462, 73472, 73488, 73490, 73530, 73534, 73538, 73552, 73562, 73648, 73648, 73728, 74649, 74752, 74862, 74880, 75075, 77712, 77808, 77824, 78933, 78944, 82938, 82944, 83526, 90368, 90425, 92160, 92728, 92736, 92766, 92768, 92777, 92784, 92862, 92864, 92873, 92880, 92909, 92912, 92916, 92928, 92982, 92992, 92995, 93008, 93017, 93027, 93047, 93053, 93071, 93504, 93548, 93552, 93561, 93760, 93823, 93856, 93880, 93883, 93907, 93952, 94026, 94031, 94087, 94095, 94111, 94176, 94177, 94179, 94180, 94192, 94198, 94208, 101589, 101631, 101662, 101760, 101874, 110576, 110579, 110581, 110587, 110589, 110590, 110592, 110882, 110898, 110898, 110928, 110930, 110933, 110933, 110948, 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 113821, 113822, 113824, 113827, 118000, 118009, 118528, 118573, 118576, 118598, 119141, 119145, 119149, 119170, 119173, 119179, 119210, 119213, 119362, 119364, 119808, 119892, 119894, 119964, 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144, 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686, 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, 120782, 120831, 121344, 121398, 121403, 121452, 121461, 121461, 121476, 121476, 121499, 121503, 121505, 121519, 122624, 122654, 122661, 122666, 122880, 122886, 122888, 122904, 122907, 122913, 122915, 122916, 122918, 122922, 122928, 122989, 123023, 123023, 123136, 123180, 123184, 123197, 123200, 123209, 123214, 123214, 123536, 123566, 123584, 123641, 124112, 124153, 124368, 124410, 124608, 124638, 124640, 124661, 124670, 124671, 124896, 124902, 124904, 124907, 124909, 124910, 124912, 124926, 124928, 125124, 125136, 125142, 125184, 125259, 125264, 125273, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516, 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, 126543, 126545, 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, 126562, 126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, 126619, 126625, 126627, 126629, 126633, 126635, 126651, 130032, 130041, 131072, 173791, 173824, 178205, 178208, 183981, 183984, 191456, 191472, 192093, 194560, 195101, 196608, 201546, 201552, 210041, 917505, 917505, 917536, 917631, 917760, 917999, 1, 0, 48, 57, 2, 0, 88, 88, 120, 120, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 66, 66, 98, 98, 1, 0, 48, 49, 2, 0, 85, 85, 117, 117, 2, 0, 76, 76, 108, 108, 2, 0, 48, 57, 95, 95, 6, 0, 68, 68, 70, 70, 77, 77, 100, 100, 102, 102, 109, 109, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 10, 0, 34, 34, 39, 39, 48, 48, 92, 92, 97, 98, 102, 102, 110, 110, 114, 114, 116, 116, 118, 118, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 1, 0, 34, 34, 2, 0, 10, 10, 13, 13, 4, 0, 10, 10, 13, 13, 133, 133, 8232, 8233, 3, 0, 9, 9, 12, 12, 32, 32, 5, 0, 10, 10, 13, 13, 47, 47, 133, 133, 8232, 8233, 6, 0, 10, 10, 13, 13, 42, 42, 47, 47, 133, 133, 8232, 8233, 4, 1, 10, 10, 13, 13, 133, 133, 8232, 8233, 5, 0, 10, 10, 13, 13, 34, 34, 133, 133, 8232, 8233, 8, 0, 10, 10, 13, 13, 34, 34, 92, 92, 123, 123, 125, 125, 133, 133, 8232, 8233, 3, 0, 34, 34, 123, 123, 125, 125, 3, 0, 34, 34, 92, 92, 125, 125, 2554, 0, 8, 1, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 0, 68, 1, 0, 0, 0, 0, 70, 1, 0, 0, 0, 0, 72, 1, 0, 0, 0, 0, 74, 1, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 78, 1, 0, 0, 0, 0, 80, 1, 0, 0, 0, 0, 82, 1, 0, 0, 0, 0, 84, 1, 0, 0, 0, 0, 86, 1, 0, 0, 0, 0, 88, 1, 0, 0, 0, 0, 90, 1, 0, 0, 0, 0, 92, 1, 0, 0, 0, 0, 94, 1, 0, 0, 0, 0, 96, 1, 0, 0, 0, 0, 98, 1, 0, 0, 0, 0, 100, 1, 0, 0, 0, 0, 102, 1, 0, 0, 0, 0, 104, 1, 0, 0, 0, 0, 106, 1, 0, 0, 0, 0, 108, 1, 0, 0, 0, 0, 110, 1, 0, 0, 0, 0, 112, 1, 0, 0, 0, 0, 114, 1, 0, 0, 0, 0, 116, 1, 0, 0, 0, 0, 118, 1, 0, 0, 0, 0, 120, 1, 0, 0, 0, 0, 122, 1, 0, 0, 0, 0, 124, 1, 0, 0, 0, 0, 126, 1, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 130, 1, 0, 0, 0, 0, 132, 1, 0, 0, 0, 0, 134, 1, 0, 0, 0, 0, 136, 1, 0, 0, 0, 0, 138, 1, 0, 0, 0, 0, 140, 1, 0, 0, 0, 0, 142, 1, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 146, 1, 0, 0, 0, 0, 148, 1, 0, 0, 0, 0, 150, 1, 0, 0, 0, 0, 152, 1, 0, 0, 0, 0, 154, 1, 0, 0, 0, 0, 156, 1, 0, 0, 0, 0, 158, 1, 0, 0, 0, 0, 160, 1, 0, 0, 0, 0, 162, 1, 0, 0, 0, 0, 164, 1, 0, 0, 0, 0, 166, 1, 0, 0, 0, 0, 168, 1, 0, 0, 0, 0, 170, 1, 0, 0, 0, 0, 172, 1, 0, 0, 0, 0, 174, 1, 0, 0, 0, 0, 176, 1, 0, 0, 0, 0, 178, 1, 0, 0, 0, 0, 180, 1, 0, 0, 0, 0, 182, 1, 0, 0, 0, 0, 184, 1, 0, 0, 0, 0, 186, 1, 0, 0, 0, 0, 188, 1, 0, 0, 0, 0, 190, 1, 0, 0, 0, 0, 192, 1, 0, 0, 0, 0, 194, 1, 0, 0, 0, 0, 196, 1, 0, 0, 0, 0, 198, 1, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 202, 1, 0, 0, 0, 0, 204, 1, 0, 0, 0, 0, 206, 1, 0, 0, 0, 0, 208, 1, 0, 0, 0, 0, 210, 1, 0, 0, 0, 0, 212, 1, 0, 0, 0, 0, 214, 1, 0, 0, 0, 0, 216, 1, 0, 0, 0, 0, 218, 1, 0, 0, 0, 0, 220, 1, 0, 0, 0, 0, 222, 1, 0, 0, 0, 0, 224, 1, 0, 0, 0, 0, 226, 1, 0, 0, 0, 0, 228, 1, 0, 0, 0, 0, 230, 1, 0, 0, 0, 0, 232, 1, 0, 0, 0, 0, 234, 1, 0, 0, 0, 0, 236, 1, 0, 0, 0, 0, 238, 1, 0, 0, 0, 0, 240, 1, 0, 0, 0, 0, 242, 1, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 246, 1, 0, 0, 0, 0, 248, 1, 0, 0, 0, 0, 250, 1, 0, 0, 0, 0, 252, 1, 0, 0, 0, 0, 254, 1, 0, 0, 0, 0, 256, 1, 0, 0, 0, 0, 258, 1, 0, 0, 0, 0, 260, 1, 0, 0, 0, 0, 262, 1, 0, 0, 0, 0, 264, 1, 0, 0, 0, 0, 266, 1, 0, 0, 0, 0, 268, 1, 0, 0, 0, 0, 270, 1, 0, 0, 0, 0, 272, 1, 0, 0, 0, 0, 274, 1, 0, 0, 0, 0, 276, 1, 0, 0, 0, 0, 278, 1, 0, 0, 0, 0, 280, 1, 0, 0, 0, 0, 282, 1, 0, 0, 0, 0, 284, 1, 0, 0, 0, 0, 286, 1, 0, 0, 0, 0, 288, 1, 0, 0, 0, 0, 290, 1, 0, 0, 0, 0, 292, 1, 0, 0, 0, 0, 294, 1, 0, 0, 0, 0, 296, 1, 0, 0, 0, 0, 298, 1, 0, 0, 0, 0, 300, 1, 0, 0, 0, 0, 302, 1, 0, 0, 0, 0, 304, 1, 0, 0, 0, 0, 306, 1, 0, 0, 0, 0, 308, 1, 0, 0, 0, 0, 310, 1, 0, 0, 0, 0, 312, 1, 0, 0, 0, 0, 314, 1, 0, 0, 0, 0, 316, 1, 0, 0, 0, 0, 318, 1, 0, 0, 0, 0, 320, 1, 0, 0, 0, 0, 322, 1, 0, 0, 0, 0, 324, 1, 0, 0, 0, 0, 326, 1, 0, 0, 0, 0, 328, 1, 0, 0, 0, 0, 330, 1, 0, 0, 0, 0, 332, 1, 0, 0, 0, 0, 334, 1, 0, 0, 0, 0, 336, 1, 0, 0, 0, 0, 338, 1, 0, 0, 0, 0, 340, 1, 0, 0, 0, 0, 342, 1, 0, 0, 0, 0, 344, 1, 0, 0, 0, 0, 346, 1, 0, 0, 0, 0, 348, 1, 0, 0, 0, 0, 350, 1, 0, 0, 0, 0, 352, 1, 0, 0, 0, 0, 354, 1, 0, 0, 0, 0, 356, 1, 0, 0, 0, 0, 360, 1, 0, 0, 0, 0, 362, 1, 0, 0, 0, 0, 364, 1, 0, 0, 0, 0, 368, 1, 0, 0, 0, 0, 372, 1, 0, 0, 0, 0, 378, 1, 0, 0, 0, 0, 380, 1, 0, 0, 0, 0, 382, 1, 0, 0, 0, 0, 384, 1, 0, 0, 0, 0, 388, 1, 0, 0, 0, 0, 390, 1, 0, 0, 0, 0, 392, 1, 0, 0, 0, 0, 394, 1, 0, 0, 0, 0, 396, 1, 0, 0, 0, 0, 398, 1, 0, 0, 0, 0, 400, 1, 0, 0, 0, 0, 404, 1, 0, 0, 0, 0, 406, 1, 0, 0, 0, 0, 408, 1, 0, 0, 0, 0, 410, 1, 0, 0, 0, 0, 412, 1, 0, 0, 0, 0, 414, 1, 0, 0, 0, 0, 416, 1, 0, 0, 0, 0, 418, 1, 0, 0, 0, 0, 420, 1, 0, 0, 0, 0, 422, 1, 0, 0, 0, 0, 424, 1, 0, 0, 0, 0, 426, 1, 0, 0, 0, 0, 428, 1, 0, 0, 0, 0, 430, 1, 0, 0, 0, 0, 432, 1, 0, 0, 0, 0, 434, 1, 0, 0, 0, 0, 436, 1, 0, 0, 0, 0, 438, 1, 0, 0, 0, 0, 440, 1, 0, 0, 0, 0, 442, 1, 0, 0, 0, 0, 444, 1, 0, 0, 0, 0, 446, 1, 0, 0, 0, 0, 448, 1, 0, 0, 0, 1, 450, 1, 0, 0, 0, 1, 452, 1, 0, 0, 0, 1, 454, 1, 0, 0, 0, 1, 456, 1, 0, 0, 0, 1, 458, 1, 0, 0, 0, 1, 460, 1, 0, 0, 0, 2, 462, 1, 0, 0, 0, 2, 464, 1, 0, 0, 0, 2, 466, 1, 0, 0, 0, 2, 468, 1, 0, 0, 0, 2, 470, 1, 0, 0, 0, 2, 472, 1, 0, 0, 0, 3, 474, 1, 0, 0, 0, 3, 476, 1, 0, 0, 0, 3, 478, 1, 0, 0, 0, 3, 480, 1, 0, 0, 0, 3, 482, 1, 0, 0, 0, 3, 484, 1, 0, 0, 0, 4, 486, 1, 0, 0, 0, 4, 488, 1, 0, 0, 0, 4, 490, 1, 0, 0, 0, 4, 492, 1, 0, 0, 0, 4, 494, 1, 0, 0, 0, 4, 496, 1, 0, 0, 0, 5, 498, 1, 0, 0, 0, 5, 500, 1, 0, 0, 0, 5, 502, 1, 0, 0, 0, 6, 504, 1, 0, 0, 0, 6, 506, 1, 0, 0, 0, 6, 508, 1, 0, 0, 0, 6, 510, 1, 0, 0, 0, 6, 512, 1, 0, 0, 0, 6, 514, 1, 0, 0, 0, 7, 516, 1, 0, 0, 0, 7, 518, 1, 0, 0, 0, 7, 520, 1, 0, 0, 0, 7, 522, 1, 0, 0, 0, 7, 524, 1, 0, 0, 0, 7, 526, 1, 0, 0, 0, 8, 528, 1, 0, 0, 0, 10, 539, 1, 0, 0, 0, 12, 550, 1, 0, 0, 0, 14, 561, 1, 0, 0, 0, 16, 571, 1, 0, 0, 0, 18, 581, 1, 0, 0, 0, 20, 591, 1, 0, 0, 0, 22, 601, 1, 0, 0, 0, 24, 611, 1, 0, 0, 0, 26, 621, 1, 0, 0, 0, 28, 631, 1, 0, 0, 0, 30, 641, 1, 0, 0, 0, 32, 651, 1, 0, 0, 0, 34, 661, 1, 0, 0, 0, 36, 670, 1, 0, 0, 0, 38, 679, 1, 0, 0, 0, 40, 688, 1, 0, 0, 0, 42, 697, 1, 0, 0, 0, 44, 706, 1, 0, 0, 0, 46, 715, 1, 0, 0, 0, 48, 724, 1, 0, 0, 0, 50, 733, 1, 0, 0, 0, 52, 742, 1, 0, 0, 0, 54, 751, 1, 0, 0, 0, 56, 760, 1, 0, 0, 0, 58, 768, 1, 0, 0, 0, 60, 776, 1, 0, 0, 0, 62, 784, 1, 0, 0, 0, 64, 792, 1, 0, 0, 0, 66, 800, 1, 0, 0, 0, 68, 808, 1, 0, 0, 0, 70, 816, 1, 0, 0, 0, 72, 824, 1, 0, 0, 0, 74, 832, 1, 0, 0, 0, 76, 840, 1, 0, 0, 0, 78, 847, 1, 0, 0, 0, 80, 854, 1, 0, 0, 0, 82, 861, 1, 0, 0, 0, 84, 868, 1, 0, 0, 0, 86, 875, 1, 0, 0, 0, 88, 882, 1, 0, 0, 0, 90, 889, 1, 0, 0, 0, 92, 896, 1, 0, 0, 0, 94, 903, 1, 0, 0, 0, 96, 910, 1, 0, 0, 0, 98, 917, 1, 0, 0, 0, 100, 924, 1, 0, 0, 0, 102, 931, 1, 0, 0, 0, 104, 938, 1, 0, 0, 0, 106, 945, 1, 0, 0, 0, 108, 952, 1, 0, 0, 0, 110, 959, 1, 0, 0, 0, 112, 966, 1, 0, 0, 0, 114, 973, 1, 0, 0, 0, 116, 980, 1, 0, 0, 0, 118, 987, 1, 0, 0, 0, 120, 994, 1, 0, 0, 0, 122, 1000, 1, 0, 0, 0, 124, 1006, 1, 0, 0, 0, 126, 1012, 1, 0, 0, 0, 128, 1018, 1, 0, 0, 0, 130, 1024, 1, 0, 0, 0, 132, 1030, 1, 0, 0, 0, 134, 1036, 1, 0, 0, 0, 136, 1042, 1, 0, 0, 0, 138, 1048, 1, 0, 0, 0, 140, 1054, 1, 0, 0, 0, 142, 1060, 1, 0, 0, 0, 144, 1066, 1, 0, 0, 0, 146, 1072, 1, 0, 0, 0, 148, 1078, 1, 0, 0, 0, 150, 1084, 1, 0, 0, 0, 152, 1090, 1, 0, 0, 0, 154, 1096, 1, 0, 0, 0, 156, 1102, 1, 0, 0, 0, 158, 1108, 1, 0, 0, 0, 160, 1114, 1, 0, 0, 0, 162, 1120, 1, 0, 0, 0, 164, 1126, 1, 0, 0, 0, 166, 1131, 1, 0, 0, 0, 168, 1136, 1, 0, 0, 0, 170, 1141, 1, 0, 0, 0, 172, 1146, 1, 0, 0, 0, 174, 1151, 1, 0, 0, 0, 176, 1156, 1, 0, 0, 0, 178, 1161, 1, 0, 0, 0, 180, 1166, 1, 0, 0, 0, 182, 1171, 1, 0, 0, 0, 184, 1176, 1, 0, 0, 0, 186, 1181, 1, 0, 0, 0, 188, 1186, 1, 0, 0, 0, 190, 1191, 1, 0, 0, 0, 192, 1196, 1, 0, 0, 0, 194, 1201, 1, 0, 0, 0, 196, 1206, 1, 0, 0, 0, 198, 1211, 1, 0, 0, 0, 200, 1216, 1, 0, 0, 0, 202, 1221, 1, 0, 0, 0, 204, 1226, 1, 0, 0, 0, 206, 1231, 1, 0, 0, 0, 208, 1236, 1, 0, 0, 0, 210, 1241, 1, 0, 0, 0, 212, 1245, 1, 0, 0, 0, 214, 1249, 1, 0, 0, 0, 216, 1253, 1, 0, 0, 0, 218, 1257, 1, 0, 0, 0, 220, 1261, 1, 0, 0, 0, 222, 1265, 1, 0, 0, 0, 224, 1269, 1, 0, 0, 0, 226, 1273, 1, 0, 0, 0, 228, 1277, 1, 0, 0, 0, 230, 1281, 1, 0, 0, 0, 232, 1285, 1, 0, 0, 0, 234, 1289, 1, 0, 0, 0, 236, 1293, 1, 0, 0, 0, 238, 1297, 1, 0, 0, 0, 240, 1301, 1, 0, 0, 0, 242, 1305, 1, 0, 0, 0, 244, 1308, 1, 0, 0, 0, 246, 1311, 1, 0, 0, 0, 248, 1314, 1, 0, 0, 0, 250, 1317, 1, 0, 0, 0, 252, 1320, 1, 0, 0, 0, 254, 1323, 1, 0, 0, 0, 256, 1326, 1, 0, 0, 0, 258, 1329, 1, 0, 0, 0, 260, 1332, 1, 0, 0, 0, 262, 1335, 1, 0, 0, 0, 264, 1338, 1, 0, 0, 0, 266, 1341, 1, 0, 0, 0, 268, 1344, 1, 0, 0, 0, 270, 1347, 1, 0, 0, 0, 272, 1350, 1, 0, 0, 0, 274, 1353, 1, 0, 0, 0, 276, 1356, 1, 0, 0, 0, 278, 1359, 1, 0, 0, 0, 280, 1362, 1, 0, 0, 0, 282, 1365, 1, 0, 0, 0, 284, 1368, 1, 0, 0, 0, 286, 1371, 1, 0, 0, 0, 288, 1373, 1, 0, 0, 0, 290, 1375, 1, 0, 0, 0, 292, 1378, 1, 0, 0, 0, 294, 1381, 1, 0, 0, 0, 296, 1384, 1, 0, 0, 0, 298, 1387, 1, 0, 0, 0, 300, 1390, 1, 0, 0, 0, 302, 1393, 1, 0, 0, 0, 304, 1396, 1, 0, 0, 0, 306, 1399, 1, 0, 0, 0, 308, 1402, 1, 0, 0, 0, 310, 1405, 1, 0, 0, 0, 312, 1408, 1, 0, 0, 0, 314, 1411, 1, 0, 0, 0, 316, 1413, 1, 0, 0, 0, 318, 1415, 1, 0, 0, 0, 320, 1417, 1, 0, 0, 0, 322, 1419, 1, 0, 0, 0, 324, 1421, 1, 0, 0, 0, 326, 1423, 1, 0, 0, 0, 328, 1425, 1, 0, 0, 0, 330, 1427, 1, 0, 0, 0, 332, 1429, 1, 0, 0, 0, 334, 1431, 1, 0, 0, 0, 336, 1433, 1, 0, 0, 0, 338, 1435, 1, 0, 0, 0, 340, 1437, 1, 0, 0, 0, 342, 1439, 1, 0, 0, 0, 344, 1441, 1, 0, 0, 0, 346, 1443, 1, 0, 0, 0, 348, 1445, 1, 0, 0, 0, 350, 1447, 1, 0, 0, 0, 352, 1449, 1, 0, 0, 0, 354, 1451, 1, 0, 0, 0, 356, 1459, 1, 0, 0, 0, 358, 1472, 1, 0, 0, 0, 360, 1481, 1, 0, 0, 0, 362, 1497, 1, 0, 0, 0, 364, 1515, 1, 0, 0, 0, 366, 1541, 1, 0, 0, 0, 368, 1597, 1, 0, 0, 0, 370, 1599, 1, 0, 0, 0, 372, 1610, 1, 0, 0, 0, 374, 1617, 1, 0, 0, 0, 376, 1638, 1, 0, 0, 0, 378, 1643, 1, 0, 0, 0, 380, 1653, 1, 0, 0, 0, 382, 1816, 1, 0, 0, 0, 384, 1968, 1, 0, 0, 0, 386, 1970, 1, 0, 0, 0, 388, 1972, 1, 0, 0, 0, 390, 1984, 1, 0, 0, 0, 392, 1999, 1, 0, 0, 0, 394, 2010, 1, 0, 0, 0, 396, 2026, 1, 0, 0, 0, 398, 2032, 1, 0, 0, 0, 400, 2036, 1, 0, 0, 0, 402, 2054, 1, 0, 0, 0, 404, 2063, 1, 0, 0, 0, 406, 2074, 1, 0, 0, 0, 408, 2078, 1, 0, 0, 0, 410, 2089, 1, 0, 0, 0, 412, 2099, 1, 0, 0, 0, 414, 2108, 1, 0, 0, 0, 416, 2115, 1, 0, 0, 0, 418, 2121, 1, 0, 0, 0, 420, 2127, 1, 0, 0, 0, 422, 2133, 1, 0, 0, 0, 424, 2139, 1, 0, 0, 0, 426, 2145, 1, 0, 0, 0, 428, 2154, 1, 0, 0, 0, 430, 2161, 1, 0, 0, 0, 432, 2167, 1, 0, 0, 0, 434, 2172, 1, 0, 0, 0, 436, 2178, 1, 0, 0, 0, 438, 2180, 1, 0, 0, 0, 440, 2182, 1, 0, 0, 0, 442, 2184, 1, 0, 0, 0, 444, 2186, 1, 0, 0, 0, 446, 2188, 1, 0, 0, 0, 448, 2190, 1, 0, 0, 0, 450, 2192, 1, 0, 0, 0, 452, 2197, 1, 0, 0, 0, 454, 2202, 1, 0, 0, 0, 456, 2207, 1, 0, 0, 0, 458, 2211, 1, 0, 0, 0, 460, 2217, 1, 0, 0, 0, 462, 2222, 1, 0, 0, 0, 464, 2227, 1, 0, 0, 0, 466, 2232, 1, 0, 0, 0, 468, 2238, 1, 0, 0, 0, 470, 2244, 1, 0, 0, 0, 472, 2250, 1, 0, 0, 0, 474, 2255, 1, 0, 0, 0, 476, 2260, 1, 0, 0, 0, 478, 2265, 1, 0, 0, 0, 480, 2278, 1, 0, 0, 0, 482, 2285, 1, 0, 0, 0, 484, 2291, 1, 0, 0, 0, 486, 2297, 1, 0, 0, 0, 488, 2305, 1, 0, 0, 0, 490, 2318, 1, 0, 0, 0, 492, 2325, 1, 0, 0, 0, 494, 2331, 1, 0, 0, 0, 496, 2335, 1, 0, 0, 0, 498, 2345, 1, 0, 0, 0, 500, 2351, 1, 0, 0, 0, 502, 2361, 1, 0, 0, 0, 504, 2368, 1, 0, 0, 0, 506, 2373, 1, 0, 0, 0, 508, 2378, 1, 0, 0, 0, 510, 2392, 1, 0, 0, 0, 512, 2402, 1, 0, 0, 0, 514, 2408, 1, 0, 0, 0, 516, 2414, 1, 0, 0, 0, 518, 2422, 1, 0, 0, 0, 520, 2436, 1, 0, 0, 0, 522, 2446, 1, 0, 0, 0, 524, 2452, 1, 0, 0, 0, 526, 2456, 1, 0, 0, 0, 528, 529, 5, 95, 0, 0, 529, 530, 5, 95, 0, 0, 530, 531, 5, 114, 0, 0, 531, 532, 5, 101, 0, 0, 532, 533, 5, 102, 0, 0, 533, 534, 5, 118, 0, 0, 534, 535, 5, 97, 0, 0, 535, 536, 5, 108, 0, 0, 536, 537, 5, 117, 0, 0, 537, 538, 5, 101, 0, 0, 538, 9, 1, 0, 0, 0, 539, 540, 5, 100, 0, 0, 540, 541, 5, 101, 0, 0, 541, 542, 5, 115, 0, 0, 542, 543, 5, 99, 0, 0, 543, 544, 5, 101, 0, 0, 544, 545, 5, 110, 0, 0, 545, 546, 5, 100, 0, 0, 546, 547, 5, 105, 0, 0, 547, 548, 5, 110, 0, 0, 548, 549, 5, 103, 0, 0, 549, 11, 1, 0, 0, 0, 550, 551, 5, 115, 0, 0, 551, 552, 5, 116, 0, 0, 552, 553, 5, 97, 0, 0, 553, 554, 5, 99, 0, 0, 554, 555, 5, 107, 0, 0, 555, 556, 5, 97, 0, 0, 556, 557, 5, 108, 0, 0, 557, 558, 5, 108, 0, 0, 558, 559, 5, 111, 0, 0, 559, 560, 5, 99, 0, 0, 560, 13, 1, 0, 0, 0, 561, 562, 5, 95, 0, 0, 562, 563, 5, 95, 0, 0, 563, 564, 5, 97, 0, 0, 564, 565, 5, 114, 0, 0, 565, 566, 5, 103, 0, 0, 566, 567, 5, 108, 0, 0, 567, 568, 5, 105, 0, 0, 568, 569, 5, 115, 0, 0, 569, 570, 5, 116, 0, 0, 570, 15, 1, 0, 0, 0, 571, 572, 5, 95, 0, 0, 572, 573, 5, 95, 0, 0, 573, 574, 5, 109, 0, 0, 574, 575, 5, 97, 0, 0, 575, 576, 5, 107, 0, 0, 576, 577, 5, 101, 0, 0, 577, 578, 5, 114, 0, 0, 578, 579, 5, 101, 0, 0, 579, 580, 5, 102, 0, 0, 580, 17, 1, 0, 0, 0, 581, 582, 5, 95, 0, 0, 582, 583, 5, 95, 0, 0, 583, 584, 5, 114, 0, 0, 584, 585, 5, 101, 0, 0, 585, 586, 5, 102, 0, 0, 586, 587, 5, 116, 0, 0, 587, 588, 5, 121, 0, 0, 588, 589, 5, 112, 0, 0, 589, 590, 5, 101, 0, 0, 590, 19, 1, 0, 0, 0, 591, 592, 5, 97, 0, 0, 592, 593, 5, 115, 0, 0, 593, 594, 5, 99, 0, 0, 594, 595, 5, 101, 0, 0, 595, 596, 5, 110, 0, 0, 596, 597, 5, 100, 0, 0, 597, 598, 5, 105, 0, 0, 598, 599, 5, 110, 0, 0, 599, 600, 5, 103, 0, 0, 600, 21, 1, 0, 0, 0, 601, 602, 5, 101, 0, 0, 602, 603, 5, 120, 0, 0, 603, 604, 5, 116, 0, 0, 604, 605, 5, 101, 0, 0, 605, 606, 5, 110, 0, 0, 606, 607, 5, 115, 0, 0, 607, 608, 5, 105, 0, 0, 608, 609, 5, 111, 0, 0, 609, 610, 5, 110, 0, 0, 610, 23, 1, 0, 0, 0, 611, 612, 5, 105, 0, 0, 612, 613, 5, 110, 0, 0, 613, 614, 5, 116, 0, 0, 614, 615, 5, 101, 0, 0, 615, 616, 5, 114, 0, 0, 616, 617, 5, 102, 0, 0, 617, 618, 5, 97, 0, 0, 618, 619, 5, 99, 0, 0, 619, 620, 5, 101, 0, 0, 620, 25, 1, 0, 0, 0, 621, 622, 5, 110, 0, 0, 622, 623, 5, 97, 0, 0, 623, 624, 5, 109, 0, 0, 624, 625, 5, 101, 0, 0, 625, 626, 5, 115, 0, 0, 626, 627, 5, 112, 0, 0, 627, 628, 5, 97, 0, 0, 628, 629, 5, 99, 0, 0, 629, 630, 5, 101, 0, 0, 630, 27, 1, 0, 0, 0, 631, 632, 5, 112, 0, 0, 632, 633, 5, 114, 0, 0, 633, 634, 5, 111, 0, 0, 634, 635, 5, 116, 0, 0, 635, 636, 5, 101, 0, 0, 636, 637, 5, 99, 0, 0, 637, 638, 5, 116, 0, 0, 638, 639, 5, 101, 0, 0, 639, 640, 5, 100, 0, 0, 640, 29, 1, 0, 0, 0, 641, 642, 5, 117, 0, 0, 642, 643, 5, 110, 0, 0, 643, 644, 5, 99, 0, 0, 644, 645, 5, 104, 0, 0, 645, 646, 5, 101, 0, 0, 646, 647, 5, 99, 0, 0, 647, 648, 5, 107, 0, 0, 648, 649, 5, 101, 0, 0, 649, 650, 5, 100, 0, 0, 650, 31, 1, 0, 0, 0, 651, 652, 5, 117, 0, 0, 652, 653, 5, 110, 0, 0, 653, 654, 5, 109, 0, 0, 654, 655, 5, 97, 0, 0, 655, 656, 5, 110, 0, 0, 656, 657, 5, 97, 0, 0, 657, 658, 5, 103, 0, 0, 658, 659, 5, 101, 0, 0, 659, 660, 5, 100, 0, 0, 660, 33, 1, 0, 0, 0, 661, 662, 5, 97, 0, 0, 662, 663, 5, 98, 0, 0, 663, 664, 5, 115, 0, 0, 664, 665, 5, 116, 0, 0, 665, 666, 5, 114, 0, 0, 666, 667, 5, 97, 0, 0, 667, 668, 5, 99, 0, 0, 668, 669, 5, 116, 0, 0, 669, 35, 1, 0, 0, 0, 670, 671, 5, 99, 0, 0, 671, 672, 5, 111, 0, 0, 672, 673, 5, 110, 0, 0, 673, 674, 5, 116, 0, 0, 674, 675, 5, 105, 0, 0, 675, 676, 5, 110, 0, 0, 676, 677, 5, 117, 0, 0, 677, 678, 5, 101, 0, 0, 678, 37, 1, 0, 0, 0, 679, 680, 5, 100, 0, 0, 680, 681, 5, 101, 0, 0, 681, 682, 5, 108, 0, 0, 682, 683, 5, 101, 0, 0, 683, 684, 5, 103, 0, 0, 684, 685, 5, 97, 0, 0, 685, 686, 5, 116, 0, 0, 686, 687, 5, 101, 0, 0, 687, 39, 1, 0, 0, 0, 688, 689, 5, 101, 0, 0, 689, 690, 5, 120, 0, 0, 690, 691, 5, 112, 0, 0, 691, 692, 5, 108, 0, 0, 692, 693, 5, 105, 0, 0, 693, 694, 5, 99, 0, 0, 694, 695, 5, 105, 0, 0, 695, 696, 5, 116, 0, 0, 696, 41, 1, 0, 0, 0, 697, 698, 5, 105, 0, 0, 698, 699, 5, 109, 0, 0, 699, 700, 5, 112, 0, 0, 700, 701, 5, 108, 0, 0, 701, 702, 5, 105, 0, 0, 702, 703, 5, 99, 0, 0, 703, 704, 5, 105, 0, 0, 704, 705, 5, 116, 0, 0, 705, 43, 1, 0, 0, 0, 706, 707, 5, 105, 0, 0, 707, 708, 5, 110, 0, 0, 708, 709, 5, 116, 0, 0, 709, 710, 5, 101, 0, 0, 710, 711, 5, 114, 0, 0, 711, 712, 5, 110, 0, 0, 712, 713, 5, 97, 0, 0, 713, 714, 5, 108, 0, 0, 714, 45, 1, 0, 0, 0, 715, 716, 5, 111, 0, 0, 716, 717, 5, 112, 0, 0, 717, 718, 5, 101, 0, 0, 718, 719, 5, 114, 0, 0, 719, 720, 5, 97, 0, 0, 720, 721, 5, 116, 0, 0, 721, 722, 5, 111, 0, 0, 722, 723, 5, 114, 0, 0, 723, 47, 1, 0, 0, 0, 724, 725, 5, 111, 0, 0, 725, 726, 5, 118, 0, 0, 726, 727, 5, 101, 0, 0, 727, 728, 5, 114, 0, 0, 728, 729, 5, 114, 0, 0, 729, 730, 5, 105, 0, 0, 730, 731, 5, 100, 0, 0, 731, 732, 5, 101, 0, 0, 732, 49, 1, 0, 0, 0, 733, 734, 5, 114, 0, 0, 734, 735, 5, 101, 0, 0, 735, 736, 5, 97, 0, 0, 736, 737, 5, 100, 0, 0, 737, 738, 5, 111, 0, 0, 738, 739, 5, 110, 0, 0, 739, 740, 5, 108, 0, 0, 740, 741, 5, 121, 0, 0, 741, 51, 1, 0, 0, 0, 742, 743, 5, 114, 0, 0, 743, 744, 5, 101, 0, 0, 744, 745, 5, 113, 0, 0, 745, 746, 5, 117, 0, 0, 746, 747, 5, 105, 0, 0, 747, 748, 5, 114, 0, 0, 748, 749, 5, 101, 0, 0, 749, 750, 5, 100, 0, 0, 750, 53, 1, 0, 0, 0, 751, 752, 5, 118, 0, 0, 752, 753, 5, 111, 0, 0, 753, 754, 5, 108, 0, 0, 754, 755, 5, 97, 0, 0, 755, 756, 5, 116, 0, 0, 756, 757, 5, 105, 0, 0, 757, 758, 5, 108, 0, 0, 758, 759, 5, 101, 0, 0, 759, 55, 1, 0, 0, 0, 760, 761, 5, 99, 0, 0, 761, 762, 5, 104, 0, 0, 762, 763, 5, 101, 0, 0, 763, 764, 5, 99, 0, 0, 764, 765, 5, 107, 0, 0, 765, 766, 5, 101, 0, 0, 766, 767, 5, 100, 0, 0, 767, 57, 1, 0, 0, 0, 768, 769, 5, 100, 0, 0, 769, 770, 5, 101, 0, 0, 770, 771, 5, 99, 0, 0, 771, 772, 5, 105, 0, 0, 772, 773, 5, 109, 0, 0, 773, 774, 5, 97, 0, 0, 774, 775, 5, 108, 0, 0, 775, 59, 1, 0, 0, 0, 776, 777, 5, 100, 0, 0, 777, 778, 5, 101, 0, 0, 778, 779, 5, 102, 0, 0, 779, 780, 5, 97, 0, 0, 780, 781, 5, 117, 0, 0, 781, 782, 5, 108, 0, 0, 782, 783, 5, 116, 0, 0, 783, 61, 1, 0, 0, 0, 784, 785, 5, 102, 0, 0, 785, 786, 5, 105, 0, 0, 786, 787, 5, 110, 0, 0, 787, 788, 5, 97, 0, 0, 788, 789, 5, 108, 0, 0, 789, 790, 5, 108, 0, 0, 790, 791, 5, 121, 0, 0, 791, 63, 1, 0, 0, 0, 792, 793, 5, 102, 0, 0, 793, 794, 5, 111, 0, 0, 794, 795, 5, 114, 0, 0, 795, 796, 5, 101, 0, 0, 796, 797, 5, 97, 0, 0, 797, 798, 5, 99, 0, 0, 798, 799, 5, 104, 0, 0, 799, 65, 1, 0, 0, 0, 800, 801, 5, 109, 0, 0, 801, 802, 5, 97, 0, 0, 802, 803, 5, 110, 0, 0, 803, 804, 5, 97, 0, 0, 804, 805, 5, 103, 0, 0, 805, 806, 5, 101, 0, 0, 806, 807, 5, 100, 0, 0, 807, 67, 1, 0, 0, 0, 808, 809, 5, 111, 0, 0, 809, 810, 5, 114, 0, 0, 810, 811, 5, 100, 0, 0, 811, 812, 5, 101, 0, 0, 812, 813, 5, 114, 0, 0, 813, 814, 5, 98, 0, 0, 814, 815, 5, 121, 0, 0, 815, 69, 1, 0, 0, 0, 816, 817, 5, 112, 0, 0, 817, 818, 5, 97, 0, 0, 818, 819, 5, 114, 0, 0, 819, 820, 5, 116, 0, 0, 820, 821, 5, 105, 0, 0, 821, 822, 5, 97, 0, 0, 822, 823, 5, 108, 0, 0, 823, 71, 1, 0, 0, 0, 824, 825, 5, 112, 0, 0, 825, 826, 5, 114, 0, 0, 826, 827, 5, 105, 0, 0, 827, 828, 5, 118, 0, 0, 828, 829, 5, 97, 0, 0, 829, 830, 5, 116, 0, 0, 830, 831, 5, 101, 0, 0, 831, 73, 1, 0, 0, 0, 832, 833, 5, 118, 0, 0, 833, 834, 5, 105, 0, 0, 834, 835, 5, 114, 0, 0, 835, 836, 5, 116, 0, 0, 836, 837, 5, 117, 0, 0, 837, 838, 5, 97, 0, 0, 838, 839, 5, 108, 0, 0, 839, 75, 1, 0, 0, 0, 840, 841, 5, 97, 0, 0, 841, 842, 5, 108, 0, 0, 842, 843, 5, 108, 0, 0, 843, 844, 5, 111, 0, 0, 844, 845, 5, 119, 0, 0, 845, 846, 5, 115, 0, 0, 846, 77, 1, 0, 0, 0, 847, 848, 5, 99, 0, 0, 848, 849, 5, 108, 0, 0, 849, 850, 5, 111, 0, 0, 850, 851, 5, 115, 0, 0, 851, 852, 5, 101, 0, 0, 852, 853, 5, 100, 0, 0, 853, 79, 1, 0, 0, 0, 854, 855, 5, 100, 0, 0, 855, 856, 5, 111, 0, 0, 856, 857, 5, 117, 0, 0, 857, 858, 5, 98, 0, 0, 858, 859, 5, 108, 0, 0, 859, 860, 5, 101, 0, 0, 860, 81, 1, 0, 0, 0, 861, 862, 5, 101, 0, 0, 862, 863, 5, 113, 0, 0, 863, 864, 5, 117, 0, 0, 864, 865, 5, 97, 0, 0, 865, 866, 5, 108, 0, 0, 866, 867, 5, 115, 0, 0, 867, 83, 1, 0, 0, 0, 868, 869, 5, 101, 0, 0, 869, 870, 5, 120, 0, 0, 870, 871, 5, 116, 0, 0, 871, 872, 5, 101, 0, 0, 872, 873, 5, 114, 0, 0, 873, 874, 5, 110, 0, 0, 874, 85, 1, 0, 0, 0, 875, 876, 5, 103, 0, 0, 876, 877, 5, 108, 0, 0, 877, 878, 5, 111, 0, 0, 878, 879, 5, 98, 0, 0, 879, 880, 5, 97, 0, 0, 880, 881, 5, 108, 0, 0, 881, 87, 1, 0, 0, 0, 882, 883, 5, 111, 0, 0, 883, 884, 5, 98, 0, 0, 884, 885, 5, 106, 0, 0, 885, 886, 5, 101, 0, 0, 886, 887, 5, 99, 0, 0, 887, 888, 5, 116, 0, 0, 888, 89, 1, 0, 0, 0, 889, 890, 5, 112, 0, 0, 890, 891, 5, 97, 0, 0, 891, 892, 5, 114, 0, 0, 892, 893, 5, 97, 0, 0, 893, 894, 5, 109, 0, 0, 894, 895, 5, 115, 0, 0, 895, 91, 1, 0, 0, 0, 896, 897, 5, 112, 0, 0, 897, 898, 5, 117, 0, 0, 898, 899, 5, 98, 0, 0, 899, 900, 5, 108, 0, 0, 900, 901, 5, 105, 0, 0, 901, 902, 5, 99, 0, 0, 902, 93, 1, 0, 0, 0, 903, 904, 5, 114, 0, 0, 904, 905, 5, 101, 0, 0, 905, 906, 5, 109, 0, 0, 906, 907, 5, 111, 0, 0, 907, 908, 5, 118, 0, 0, 908, 909, 5, 101, 0, 0, 909, 95, 1, 0, 0, 0, 910, 911, 5, 114, 0, 0, 911, 912, 5, 101, 0, 0, 912, 913, 5, 116, 0, 0, 913, 914, 5, 117, 0, 0, 914, 915, 5, 114, 0, 0, 915, 916, 5, 110, 0, 0, 916, 97, 1, 0, 0, 0, 917, 918, 5, 115, 0, 0, 918, 919, 5, 99, 0, 0, 919, 920, 5, 111, 0, 0, 920, 921, 5, 112, 0, 0, 921, 922, 5, 101, 0, 0, 922, 923, 5, 100, 0, 0, 923, 99, 1, 0, 0, 0, 924, 925, 5, 115, 0, 0, 925, 926, 5, 101, 0, 0, 926, 927, 5, 97, 0, 0, 927, 928, 5, 108, 0, 0, 928, 929, 5, 101, 0, 0, 929, 930, 5, 100, 0, 0, 930, 101, 1, 0, 0, 0, 931, 932, 5, 115, 0, 0, 932, 933, 5, 101, 0, 0, 933, 934, 5, 108, 0, 0, 934, 935, 5, 101, 0, 0, 935, 936, 5, 99, 0, 0, 936, 937, 5, 116, 0, 0, 937, 103, 1, 0, 0, 0, 938, 939, 5, 115, 0, 0, 939, 940, 5, 105, 0, 0, 940, 941, 5, 122, 0, 0, 941, 942, 5, 101, 0, 0, 942, 943, 5, 111, 0, 0, 943, 944, 5, 102, 0, 0, 944, 105, 1, 0, 0, 0, 945, 946, 5, 115, 0, 0, 946, 947, 5, 116, 0, 0, 947, 948, 5, 97, 0, 0, 948, 949, 5, 116, 0, 0, 949, 950, 5, 105, 0, 0, 950, 951, 5, 99, 0, 0, 951, 107, 1, 0, 0, 0, 952, 953, 5, 115, 0, 0, 953, 954, 5, 116, 0, 0, 954, 955, 5, 114, 0, 0, 955, 956, 5, 105, 0, 0, 956, 957, 5, 110, 0, 0, 957, 958, 5, 103, 0, 0, 958, 109, 1, 0, 0, 0, 959, 960, 5, 115, 0, 0, 960, 961, 5, 116, 0, 0, 961, 962, 5, 114, 0, 0, 962, 963, 5, 117, 0, 0, 963, 964, 5, 99, 0, 0, 964, 965, 5, 116, 0, 0, 965, 111, 1, 0, 0, 0, 966, 967, 5, 115, 0, 0, 967, 968, 5, 119, 0, 0, 968, 969, 5, 105, 0, 0, 969, 970, 5, 116, 0, 0, 970, 971, 5, 99, 0, 0, 971, 972, 5, 104, 0, 0, 972, 113, 1, 0, 0, 0, 973, 974, 5, 116, 0, 0, 974, 975, 5, 121, 0, 0, 975, 976, 5, 112, 0, 0, 976, 977, 5, 101, 0, 0, 977, 978, 5, 111, 0, 0, 978, 979, 5, 102, 0, 0, 979, 115, 1, 0, 0, 0, 980, 981, 5, 117, 0, 0, 981, 982, 5, 110, 0, 0, 982, 983, 5, 115, 0, 0, 983, 984, 5, 97, 0, 0, 984, 985, 5, 102, 0, 0, 985, 986, 5, 101, 0, 0, 986, 117, 1, 0, 0, 0, 987, 988, 5, 117, 0, 0, 988, 989, 5, 115, 0, 0, 989, 990, 5, 104, 0, 0, 990, 991, 5, 111, 0, 0, 991, 992, 5, 114, 0, 0, 992, 993, 5, 116, 0, 0, 993, 119, 1, 0, 0, 0, 994, 995, 5, 97, 0, 0, 995, 996, 5, 108, 0, 0, 996, 997, 5, 105, 0, 0, 997, 998, 5, 97, 0, 0, 998, 999, 5, 115, 0, 0, 999, 121, 1, 0, 0, 0, 1000, 1001, 5, 97, 0, 0, 1001, 1002, 5, 115, 0, 0, 1002, 1003, 5, 121, 0, 0, 1003, 1004, 5, 110, 0, 0, 1004, 1005, 5, 99, 0, 0, 1005, 123, 1, 0, 0, 0, 1006, 1007, 5, 97, 0, 0, 1007, 1008, 5, 119, 0, 0, 1008, 1009, 5, 97, 0, 0, 1009, 1010, 5, 105, 0, 0, 1010, 1011, 5, 116, 0, 0, 1011, 125, 1, 0, 0, 0, 1012, 1013, 5, 98, 0, 0, 1013, 1014, 5, 114, 0, 0, 1014, 1015, 5, 101, 0, 0, 1015, 1016, 5, 97, 0, 0, 1016, 1017, 5, 107, 0, 0, 1017, 127, 1, 0, 0, 0, 1018, 1019, 5, 99, 0, 0, 1019, 1020, 5, 97, 0, 0, 1020, 1021, 5, 116, 0, 0, 1021, 1022, 5, 99, 0, 0, 1022, 1023, 5, 104, 0, 0, 1023, 129, 1, 0, 0, 0, 1024, 1025, 5, 99, 0, 0, 1025, 1026, 5, 108, 0, 0, 1026, 1027, 5, 97, 0, 0, 1027, 1028, 5, 115, 0, 0, 1028, 1029, 5, 115, 0, 0, 1029, 131, 1, 0, 0, 0, 1030, 1031, 5, 99, 0, 0, 1031, 1032, 5, 111, 0, 0, 1032, 1033, 5, 110, 0, 0, 1033, 1034, 5, 115, 0, 0, 1034, 1035, 5, 116, 0, 0, 1035, 133, 1, 0, 0, 0, 1036, 1037, 5, 101, 0, 0, 1037, 1038, 5, 118, 0, 0, 1038, 1039, 5, 101, 0, 0, 1039, 1040, 5, 110, 0, 0, 1040, 1041, 5, 116, 0, 0, 1041, 135, 1, 0, 0, 0, 1042, 1043, 5, 102, 0, 0, 1043, 1044, 5, 97, 0, 0, 1044, 1045, 5, 108, 0, 0, 1045, 1046, 5, 115, 0, 0, 1046, 1047, 5, 101, 0, 0, 1047, 137, 1, 0, 0, 0, 1048, 1049, 5, 102, 0, 0, 1049, 1050, 5, 105, 0, 0, 1050, 1051, 5, 101, 0, 0, 1051, 1052, 5, 108, 0, 0, 1052, 1053, 5, 100, 0, 0, 1053, 139, 1, 0, 0, 0, 1054, 1055, 5, 102, 0, 0, 1055, 1056, 5, 105, 0, 0, 1056, 1057, 5, 120, 0, 0, 1057, 1058, 5, 101, 0, 0, 1058, 1059, 5, 100, 0, 0, 1059, 141, 1, 0, 0, 0, 1060, 1061, 5, 102, 0, 0, 1061, 1062, 5, 108, 0, 0, 1062, 1063, 5, 111, 0, 0, 1063, 1064, 5, 97, 0, 0, 1064, 1065, 5, 116, 0, 0, 1065, 143, 1, 0, 0, 0, 1066, 1067, 5, 103, 0, 0, 1067, 1068, 5, 114, 0, 0, 1068, 1069, 5, 111, 0, 0, 1069, 1070, 5, 117, 0, 0, 1070, 1071, 5, 112, 0, 0, 1071, 145, 1, 0, 0, 0, 1072, 1073, 5, 115, 0, 0, 1073, 1074, 5, 98, 0, 0, 1074, 1075, 5, 121, 0, 0, 1075, 1076, 5, 116, 0, 0, 1076, 1077, 5, 101, 0, 0, 1077, 147, 1, 0, 0, 0, 1078, 1079, 5, 115, 0, 0, 1079, 1080, 5, 104, 0, 0, 1080, 1081, 5, 111, 0, 0, 1081, 1082, 5, 114, 0, 0, 1082, 1083, 5, 116, 0, 0, 1083, 149, 1, 0, 0, 0, 1084, 1085, 5, 116, 0, 0, 1085, 1086, 5, 104, 0, 0, 1086, 1087, 5, 114, 0, 0, 1087, 1088, 5, 111, 0, 0, 1088, 1089, 5, 119, 0, 0, 1089, 151, 1, 0, 0, 0, 1090, 1091, 5, 117, 0, 0, 1091, 1092, 5, 108, 0, 0, 1092, 1093, 5, 111, 0, 0, 1093, 1094, 5, 110, 0, 0, 1094, 1095, 5, 103, 0, 0, 1095, 153, 1, 0, 0, 0, 1096, 1097, 5, 117, 0, 0, 1097, 1098, 5, 110, 0, 0, 1098, 1099, 5, 105, 0, 0, 1099, 1100, 5, 111, 0, 0, 1100, 1101, 5, 110, 0, 0, 1101, 155, 1, 0, 0, 0, 1102, 1103, 5, 117, 0, 0, 1103, 1104, 5, 115, 0, 0, 1104, 1105, 5, 105, 0, 0, 1105, 1106, 5, 110, 0, 0, 1106, 1107, 5, 103, 0, 0, 1107, 157, 1, 0, 0, 0, 1108, 1109, 5, 119, 0, 0, 1109, 1110, 5, 104, 0, 0, 1110, 1111, 5, 101, 0, 0, 1111, 1112, 5, 114, 0, 0, 1112, 1113, 5, 101, 0, 0, 1113, 159, 1, 0, 0, 0, 1114, 1115, 5, 119, 0, 0, 1115, 1116, 5, 104, 0, 0, 1116, 1117, 5, 105, 0, 0, 1117, 1118, 5, 108, 0, 0, 1118, 1119, 5, 101, 0, 0, 1119, 161, 1, 0, 0, 0, 1120, 1121, 5, 121, 0, 0, 1121, 1122, 5, 105, 0, 0, 1122, 1123, 5, 101, 0, 0, 1123, 1124, 5, 108, 0, 0, 1124, 1125, 5, 100, 0, 0, 1125, 163, 1, 0, 0, 0, 1126, 1127, 5, 98, 0, 0, 1127, 1128, 5, 97, 0, 0, 1128, 1129, 5, 115, 0, 0, 1129, 1130, 5, 101, 0, 0, 1130, 165, 1, 0, 0, 0, 1131, 1132, 5, 98, 0, 0, 1132, 1133, 5, 111, 0, 0, 1133, 1134, 5, 111, 0, 0, 1134, 1135, 5, 108, 0, 0, 1135, 167, 1, 0, 0, 0, 1136, 1137, 5, 98, 0, 0, 1137, 1138, 5, 121, 0, 0, 1138, 1139, 5, 116, 0, 0, 1139, 1140, 5, 101, 0, 0, 1140, 169, 1, 0, 0, 0, 1141, 1142, 5, 99, 0, 0, 1142, 1143, 5, 97, 0, 0, 1143, 1144, 5, 115, 0, 0, 1144, 1145, 5, 101, 0, 0, 1145, 171, 1, 0, 0, 0, 1146, 1147, 5, 99, 0, 0, 1147, 1148, 5, 104, 0, 0, 1148, 1149, 5, 97, 0, 0, 1149, 1150, 5, 114, 0, 0, 1150, 173, 1, 0, 0, 0, 1151, 1152, 5, 101, 0, 0, 1152, 1153, 5, 108, 0, 0, 1153, 1154, 5, 115, 0, 0, 1154, 1155, 5, 101, 0, 0, 1155, 175, 1, 0, 0, 0, 1156, 1157, 5, 101, 0, 0, 1157, 1158, 5, 110, 0, 0, 1158, 1159, 5, 117, 0, 0, 1159, 1160, 5, 109, 0, 0, 1160, 177, 1, 0, 0, 0, 1161, 1162, 5, 102, 0, 0, 1162, 1163, 5, 105, 0, 0, 1163, 1164, 5, 108, 0, 0, 1164, 1165, 5, 101, 0, 0, 1165, 179, 1, 0, 0, 0, 1166, 1167, 5, 102, 0, 0, 1167, 1168, 5, 114, 0, 0, 1168, 1169, 5, 111, 0, 0, 1169, 1170, 5, 109, 0, 0, 1170, 181, 1, 0, 0, 0, 1171, 1172, 5, 103, 0, 0, 1172, 1173, 5, 111, 0, 0, 1173, 1174, 5, 116, 0, 0, 1174, 1175, 5, 111, 0, 0, 1175, 183, 1, 0, 0, 0, 1176, 1177, 5, 105, 0, 0, 1177, 1178, 5, 110, 0, 0, 1178, 1179, 5, 105, 0, 0, 1179, 1180, 5, 116, 0, 0, 1180, 185, 1, 0, 0, 0, 1181, 1182, 5, 105, 0, 0, 1182, 1183, 5, 110, 0, 0, 1183, 1184, 5, 116, 0, 0, 1184, 1185, 5, 111, 0, 0, 1185, 187, 1, 0, 0, 0, 1186, 1187, 5, 106, 0, 0, 1187, 1188, 5, 111, 0, 0, 1188, 1189, 5, 105, 0, 0, 1189, 1190, 5, 110, 0, 0, 1190, 189, 1, 0, 0, 0, 1191, 1192, 5, 108, 0, 0, 1192, 1193, 5, 111, 0, 0, 1193, 1194, 5, 99, 0, 0, 1194, 1195, 5, 107, 0, 0, 1195, 191, 1, 0, 0, 0, 1196, 1197, 5, 108, 0, 0, 1197, 1198, 5, 111, 0, 0, 1198, 1199, 5, 110, 0, 0, 1199, 1200, 5, 103, 0, 0, 1200, 193, 1, 0, 0, 0, 1201, 1202, 5, 110, 0, 0, 1202, 1203, 5, 117, 0, 0, 1203, 1204, 5, 108, 0, 0, 1204, 1205, 5, 108, 0, 0, 1205, 195, 1, 0, 0, 0, 1206, 1207, 5, 115, 0, 0, 1207, 1208, 5, 97, 0, 0, 1208, 1209, 5, 102, 0, 0, 1209, 1210, 5, 101, 0, 0, 1210, 197, 1, 0, 0, 0, 1211, 1212, 5, 116, 0, 0, 1212, 1213, 5, 104, 0, 0, 1213, 1214, 5, 105, 0, 0, 1214, 1215, 5, 115, 0, 0, 1215, 199, 1, 0, 0, 0, 1216, 1217, 5, 116, 0, 0, 1217, 1218, 5, 114, 0, 0, 1218, 1219, 5, 117, 0, 0, 1219, 1220, 5, 101, 0, 0, 1220, 201, 1, 0, 0, 0, 1221, 1222, 5, 117, 0, 0, 1222, 1223, 5, 105, 0, 0, 1223, 1224, 5, 110, 0, 0, 1224, 1225, 5, 116, 0, 0, 1225, 203, 1, 0, 0, 0, 1226, 1227, 5, 118, 0, 0, 1227, 1228, 5, 111, 0, 0, 1228, 1229, 5, 105, 0, 0, 1229, 1230, 5, 100, 0, 0, 1230, 205, 1, 0, 0, 0, 1231, 1232, 5, 119, 0, 0, 1232, 1233, 5, 104, 0, 0, 1233, 1234, 5, 101, 0, 0, 1234, 1235, 5, 110, 0, 0, 1235, 207, 1, 0, 0, 0, 1236, 1237, 5, 119, 0, 0, 1237, 1238, 5, 105, 0, 0, 1238, 1239, 5, 116, 0, 0, 1239, 1240, 5, 104, 0, 0, 1240, 209, 1, 0, 0, 0, 1241, 1242, 5, 34, 0, 0, 1242, 1243, 5, 34, 0, 0, 1243, 1244, 5, 34, 0, 0, 1244, 211, 1, 0, 0, 0, 1245, 1246, 5, 60, 0, 0, 1246, 1247, 5, 60, 0, 0, 1247, 1248, 5, 61, 0, 0, 1248, 213, 1, 0, 0, 0, 1249, 1250, 5, 63, 0, 0, 1250, 1251, 5, 63, 0, 0, 1251, 1252, 5, 61, 0, 0, 1252, 215, 1, 0, 0, 0, 1253, 1254, 5, 97, 0, 0, 1254, 1255, 5, 100, 0, 0, 1255, 1256, 5, 100, 0, 0, 1256, 217, 1, 0, 0, 0, 1257, 1258, 5, 97, 0, 0, 1258, 1259, 5, 110, 0, 0, 1259, 1260, 5, 100, 0, 0, 1260, 219, 1, 0, 0, 0, 1261, 1262, 5, 102, 0, 0, 1262, 1263, 5, 111, 0, 0, 1263, 1264, 5, 114, 0, 0, 1264, 221, 1, 0, 0, 0, 1265, 1266, 5, 103, 0, 0, 1266, 1267, 5, 101, 0, 0, 1267, 1268, 5, 116, 0, 0, 1268, 223, 1, 0, 0, 0, 1269, 1270, 5, 105, 0, 0, 1270, 1271, 5, 110, 0, 0, 1271, 1272, 5, 116, 0, 0, 1272, 225, 1, 0, 0, 0, 1273, 1274, 5, 108, 0, 0, 1274, 1275, 5, 101, 0, 0, 1275, 1276, 5, 116, 0, 0, 1276, 227, 1, 0, 0, 0, 1277, 1278, 5, 110, 0, 0, 1278, 1279, 5, 101, 0, 0, 1279, 1280, 5, 119, 0, 0, 1280, 229, 1, 0, 0, 0, 1281, 1282, 5, 110, 0, 0, 1282, 1283, 5, 111, 0, 0, 1283, 1284, 5, 116, 0, 0, 1284, 231, 1, 0, 0, 0, 1285, 1286, 5, 111, 0, 0, 1286, 1287, 5, 117, 0, 0, 1287, 1288, 5, 116, 0, 0, 1288, 233, 1, 0, 0, 0, 1289, 1290, 5, 114, 0, 0, 1290, 1291, 5, 101, 0, 0, 1291, 1292, 5, 102, 0, 0, 1292, 235, 1, 0, 0, 0, 1293, 1294, 5, 115, 0, 0, 1294, 1295, 5, 101, 0, 0, 1295, 1296, 5, 116, 0, 0, 1296, 237, 1, 0, 0, 0, 1297, 1298, 5, 116, 0, 0, 1298, 1299, 5, 114, 0, 0, 1299, 1300, 5, 121, 0, 0, 1300, 239, 1, 0, 0, 0, 1301, 1302, 5, 118, 0, 0, 1302, 1303, 5, 97, 0, 0, 1303, 1304, 5, 114, 0, 0, 1304, 241, 1, 0, 0, 0, 1305, 1306, 5, 33, 0, 0, 1306, 1307, 5, 61, 0, 0, 1307, 243, 1, 0, 0, 0, 1308, 1309, 5, 37, 0, 0, 1309, 1310, 5, 61, 0, 0, 1310, 245, 1, 0, 0, 0, 1311, 1312, 5, 38, 0, 0, 1312, 1313, 5, 38, 0, 0, 1313, 247, 1, 0, 0, 0, 1314, 1315, 5, 38, 0, 0, 1315, 1316, 5, 61, 0, 0, 1316, 249, 1, 0, 0, 0, 1317, 1318, 5, 42, 0, 0, 1318, 1319, 5, 61, 0, 0, 1319, 251, 1, 0, 0, 0, 1320, 1321, 5, 43, 0, 0, 1321, 1322, 5, 43, 0, 0, 1322, 253, 1, 0, 0, 0, 1323, 1324, 5, 43, 0, 0, 1324, 1325, 5, 61, 0, 0, 1325, 255, 1, 0, 0, 0, 1326, 1327, 5, 45, 0, 0, 1327, 1328, 5, 45, 0, 0, 1328, 257, 1, 0, 0, 0, 1329, 1330, 5, 45, 0, 0, 1330, 1331, 5, 61, 0, 0, 1331, 259, 1, 0, 0, 0, 1332, 1333, 5, 45, 0, 0, 1333, 1334, 5, 62, 0, 0, 1334, 261, 1, 0, 0, 0, 1335, 1336, 5, 46, 0, 0, 1336, 1337, 5, 46, 0, 0, 1337, 263, 1, 0, 0, 0, 1338, 1339, 5, 47, 0, 0, 1339, 1340, 5, 61, 0, 0, 1340, 265, 1, 0, 0, 0, 1341, 1342, 5, 47, 0, 0, 1342, 1343, 5, 62, 0, 0, 1343, 267, 1, 0, 0, 0, 1344, 1345, 5, 58, 0, 0, 1345, 1346, 5, 58, 0, 0, 1346, 269, 1, 0, 0, 0, 1347, 1348, 5, 60, 0, 0, 1348, 1349, 5, 47, 0, 0, 1349, 271, 1, 0, 0, 0, 1350, 1351, 5, 60, 0, 0, 1351, 1352, 5, 60, 0, 0, 1352, 273, 1, 0, 0, 0, 1353, 1354, 5, 60, 0, 0, 1354, 1355, 5, 61, 0, 0, 1355, 275, 1, 0, 0, 0, 1356, 1357, 5, 61, 0, 0, 1357, 1358, 5, 61, 0, 0, 1358, 277, 1, 0, 0, 0, 1359, 1360, 5, 61, 0, 0, 1360, 1361, 5, 62, 0, 0, 1361, 279, 1, 0, 0, 0, 1362, 1363, 5, 62, 0, 0, 1363, 1364, 5, 61, 0, 0, 1364, 281, 1, 0, 0, 0, 1365, 1366, 5, 63, 0, 0, 1366, 1367, 5, 63, 0, 0, 1367, 283, 1, 0, 0, 0, 1368, 1369, 5, 85, 0, 0, 1369, 1370, 5, 56, 0, 0, 1370, 285, 1, 0, 0, 0, 1371, 1372, 5, 39, 0, 0, 1372, 287, 1, 0, 0, 0, 1373, 1374, 5, 92, 0, 0, 1374, 289, 1, 0, 0, 0, 1375, 1376, 5, 94, 0, 0, 1376, 1377, 5, 61, 0, 0, 1377, 291, 1, 0, 0, 0, 1378, 1379, 5, 97, 0, 0, 1379, 1380, 5, 115, 0, 0, 1380, 293, 1, 0, 0, 0, 1381, 1382, 5, 98, 0, 0, 1382, 1383, 5, 121, 0, 0, 1383, 295, 1, 0, 0, 0, 1384, 1385, 5, 100, 0, 0, 1385, 1386, 5, 111, 0, 0, 1386, 297, 1, 0, 0, 0, 1387, 1388, 5, 105, 0, 0, 1388, 1389, 5, 102, 0, 0, 1389, 299, 1, 0, 0, 0, 1390, 1391, 5, 105, 0, 0, 1391, 1392, 5, 110, 0, 0, 1392, 301, 1, 0, 0, 0, 1393, 1394, 5, 105, 0, 0, 1394, 1395, 5, 115, 0, 0, 1395, 303, 1, 0, 0, 0, 1396, 1397, 5, 111, 0, 0, 1397, 1398, 5, 110, 0, 0, 1398, 305, 1, 0, 0, 0, 1399, 1400, 5, 111, 0, 0, 1400, 1401, 5, 114, 0, 0, 1401, 307, 1, 0, 0, 0, 1402, 1403, 5, 117, 0, 0, 1403, 1404, 5, 56, 0, 0, 1404, 309, 1, 0, 0, 0, 1405, 1406, 5, 124, 0, 0, 1406, 1407, 5, 61, 0, 0, 1407, 311, 1, 0, 0, 0, 1408, 1409, 5, 124, 0, 0, 1409, 1410, 5, 124, 0, 0, 1410, 313, 1, 0, 0, 0, 1411, 1412, 5, 33, 0, 0, 1412, 315, 1, 0, 0, 0, 1413, 1414, 5, 34, 0, 0, 1414, 317, 1, 0, 0, 0, 1415, 1416, 5, 35, 0, 0, 1416, 319, 1, 0, 0, 0, 1417, 1418, 5, 37, 0, 0, 1418, 321, 1, 0, 0, 0, 1419, 1420, 5, 38, 0, 0, 1420, 323, 1, 0, 0, 0, 1421, 1422, 5, 42, 0, 0, 1422, 325, 1, 0, 0, 0, 1423, 1424, 5, 43, 0, 0, 1424, 327, 1, 0, 0, 0, 1425, 1426, 5, 44, 0, 0, 1426, 329, 1, 0, 0, 0, 1427, 1428, 5, 45, 0, 0, 1428, 331, 1, 0, 0, 0, 1429, 1430, 5, 46, 0, 0, 1430, 333, 1, 0, 0, 0, 1431, 1432, 5, 47, 0, 0, 1432, 335, 1, 0, 0, 0, 1433, 1434, 5, 59, 0, 0, 1434, 337, 1, 0, 0, 0, 1435, 1436, 5, 60, 0, 0, 1436, 339, 1, 0, 0, 0, 1437, 1438, 5, 61, 0, 0, 1438, 341, 1, 0, 0, 0, 1439, 1440, 5, 62, 0, 0, 1440, 343, 1, 0, 0, 0, 1441, 1442, 5, 63, 0, 0, 1442, 345, 1, 0, 0, 0, 1443, 1444, 5, 94, 0, 0, 1444, 347, 1, 0, 0, 0, 1445, 1446, 5, 95, 0, 0, 1446, 349, 1, 0, 0, 0, 1447, 1448, 5, 124, 0, 0, 1448, 351, 1, 0, 0, 0, 1449, 1450, 5, 126, 0, 0, 1450, 353, 1, 0, 0, 0, 1451, 1452, 5, 114, 0, 0, 1452, 1453, 5, 101, 0, 0, 1453, 1454, 5, 99, 0, 0, 1454, 1455, 5, 111, 0, 0, 1455, 1456, 5, 114, 0, 0, 1456, 1457, 5, 100, 0, 0, 1457, 355, 1, 0, 0, 0, 1458, 1460, 5, 64, 0, 0, 1459, 1458, 1, 0, 0, 0, 1459, 1460, 1, 0, 0, 0, 1460, 1463, 1, 0, 0, 0, 1461, 1464, 7, 0, 0, 0, 1462, 1464, 3, 358, 175, 0, 1463, 1461, 1, 0, 0, 0, 1463, 1462, 1, 0, 0, 0, 1464, 1469, 1, 0, 0, 0, 1465, 1468, 7, 1, 0, 0, 1466, 1468, 3, 358, 175, 0, 1467, 1465, 1, 0, 0, 0, 1467, 1466, 1, 0, 0, 0, 1468, 1471, 1, 0, 0, 0, 1469, 1467, 1, 0, 0, 0, 1469, 1470, 1, 0, 0, 0, 1470, 357, 1, 0, 0, 0, 1471, 1469, 1, 0, 0, 0, 1472, 1479, 5, 92, 0, 0, 1473, 1474, 5, 117, 0, 0, 1474, 1480, 3, 376, 184, 0, 1475, 1476, 5, 85, 0, 0, 1476, 1477, 3, 376, 184, 0, 1477, 1478, 3, 376, 184, 0, 1478, 1480, 1, 0, 0, 0, 1479, 1473, 1, 0, 0, 0, 1479, 1475, 1, 0, 0, 0, 1480, 359, 1, 0, 0, 0, 1481, 1491, 7, 2, 0, 0, 1482, 1484, 5, 95, 0, 0, 1483, 1482, 1, 0, 0, 0, 1484, 1487, 1, 0, 0, 0, 1485, 1483, 1, 0, 0, 0, 1485, 1486, 1, 0, 0, 0, 1486, 1488, 1, 0, 0, 0, 1487, 1485, 1, 0, 0, 0, 1488, 1490, 7, 2, 0, 0, 1489, 1485, 1, 0, 0, 0, 1490, 1493, 1, 0, 0, 0, 1491, 1489, 1, 0, 0, 0, 1491, 1492, 1, 0, 0, 0, 1492, 1495, 1, 0, 0, 0, 1493, 1491, 1, 0, 0, 0, 1494, 1496, 3, 366, 179, 0, 1495, 1494, 1, 0, 0, 0, 1495, 1496, 1, 0, 0, 0, 1496, 361, 1, 0, 0, 0, 1497, 1498, 5, 48, 0, 0, 1498, 1499, 7, 3, 0, 0, 1499, 1509, 7, 4, 0, 0, 1500, 1502, 5, 95, 0, 0, 1501, 1500, 1, 0, 0, 0, 1502, 1505, 1, 0, 0, 0, 1503, 1501, 1, 0, 0, 0, 1503, 1504, 1, 0, 0, 0, 1504, 1506, 1, 0, 0, 0, 1505, 1503, 1, 0, 0, 0, 1506, 1508, 7, 4, 0, 0, 1507, 1503, 1, 0, 0, 0, 1508, 1511, 1, 0, 0, 0, 1509, 1507, 1, 0, 0, 0, 1509, 1510, 1, 0, 0, 0, 1510, 1513, 1, 0, 0, 0, 1511, 1509, 1, 0, 0, 0, 1512, 1514, 3, 366, 179, 0, 1513, 1512, 1, 0, 0, 0, 1513, 1514, 1, 0, 0, 0, 1514, 363, 1, 0, 0, 0, 1515, 1516, 5, 48, 0, 0, 1516, 1517, 7, 5, 0, 0, 1517, 1527, 7, 6, 0, 0, 1518, 1520, 5, 95, 0, 0, 1519, 1518, 1, 0, 0, 0, 1520, 1523, 1, 0, 0, 0, 1521, 1519, 1, 0, 0, 0, 1521, 1522, 1, 0, 0, 0, 1522, 1524, 1, 0, 0, 0, 1523, 1521, 1, 0, 0, 0, 1524, 1526, 7, 6, 0, 0, 1525, 1521, 1, 0, 0, 0, 1526, 1529, 1, 0, 0, 0, 1527, 1525, 1, 0, 0, 0, 1527, 1528, 1, 0, 0, 0, 1528, 1531, 1, 0, 0, 0, 1529, 1527, 1, 0, 0, 0, 1530, 1532, 3, 366, 179, 0, 1531, 1530, 1, 0, 0, 0, 1531, 1532, 1, 0, 0, 0, 1532, 365, 1, 0, 0, 0, 1533, 1535, 7, 7, 0, 0, 1534, 1536, 7, 8, 0, 0, 1535, 1534, 1, 0, 0, 0, 1535, 1536, 1, 0, 0, 0, 1536, 1542, 1, 0, 0, 0, 1537, 1539, 7, 8, 0, 0, 1538, 1540, 7, 7, 0, 0, 1539, 1538, 1, 0, 0, 0, 1539, 1540, 1, 0, 0, 0, 1540, 1542, 1, 0, 0, 0, 1541, 1533, 1, 0, 0, 0, 1541, 1537, 1, 0, 0, 0, 1542, 367, 1, 0, 0, 0, 1543, 1547, 7, 2, 0, 0, 1544, 1546, 7, 9, 0, 0, 1545, 1544, 1, 0, 0, 0, 1546, 1549, 1, 0, 0, 0, 1547, 1545, 1, 0, 0, 0, 1547, 1548, 1, 0, 0, 0, 1548, 1550, 1, 0, 0, 0, 1549, 1547, 1, 0, 0, 0, 1550, 1551, 5, 46, 0, 0, 1551, 1555, 7, 2, 0, 0, 1552, 1554, 7, 9, 0, 0, 1553, 1552, 1, 0, 0, 0, 1554, 1557, 1, 0, 0, 0, 1555, 1553, 1, 0, 0, 0, 1555, 1556, 1, 0, 0, 0, 1556, 1559, 1, 0, 0, 0, 1557, 1555, 1, 0, 0, 0, 1558, 1560, 3, 370, 181, 0, 1559, 1558, 1, 0, 0, 0, 1559, 1560, 1, 0, 0, 0, 1560, 1562, 1, 0, 0, 0, 1561, 1563, 7, 10, 0, 0, 1562, 1561, 1, 0, 0, 0, 1562, 1563, 1, 0, 0, 0, 1563, 1598, 1, 0, 0, 0, 1564, 1565, 5, 46, 0, 0, 1565, 1569, 7, 2, 0, 0, 1566, 1568, 7, 9, 0, 0, 1567, 1566, 1, 0, 0, 0, 1568, 1571, 1, 0, 0, 0, 1569, 1567, 1, 0, 0, 0, 1569, 1570, 1, 0, 0, 0, 1570, 1573, 1, 0, 0, 0, 1571, 1569, 1, 0, 0, 0, 1572, 1574, 3, 370, 181, 0, 1573, 1572, 1, 0, 0, 0, 1573, 1574, 1, 0, 0, 0, 1574, 1576, 1, 0, 0, 0, 1575, 1577, 7, 10, 0, 0, 1576, 1575, 1, 0, 0, 0, 1576, 1577, 1, 0, 0, 0, 1577, 1598, 1, 0, 0, 0, 1578, 1582, 7, 2, 0, 0, 1579, 1581, 7, 9, 0, 0, 1580, 1579, 1, 0, 0, 0, 1581, 1584, 1, 0, 0, 0, 1582, 1580, 1, 0, 0, 0, 1582, 1583, 1, 0, 0, 0, 1583, 1585, 1, 0, 0, 0, 1584, 1582, 1, 0, 0, 0, 1585, 1587, 3, 370, 181, 0, 1586, 1588, 7, 10, 0, 0, 1587, 1586, 1, 0, 0, 0, 1587, 1588, 1, 0, 0, 0, 1588, 1598, 1, 0, 0, 0, 1589, 1593, 7, 2, 0, 0, 1590, 1592, 7, 9, 0, 0, 1591, 1590, 1, 0, 0, 0, 1592, 1595, 1, 0, 0, 0, 1593, 1591, 1, 0, 0, 0, 1593, 1594, 1, 0, 0, 0, 1594, 1596, 1, 0, 0, 0, 1595, 1593, 1, 0, 0, 0, 1596, 1598, 7, 10, 0, 0, 1597, 1543, 1, 0, 0, 0, 1597, 1564, 1, 0, 0, 0, 1597, 1578, 1, 0, 0, 0, 1597, 1589, 1, 0, 0, 0, 1598, 369, 1, 0, 0, 0, 1599, 1601, 7, 11, 0, 0, 1600, 1602, 7, 12, 0, 0, 1601, 1600, 1, 0, 0, 0, 1601, 1602, 1, 0, 0, 0, 1602, 1603, 1, 0, 0, 0, 1603, 1607, 7, 2, 0, 0, 1604, 1606, 7, 9, 0, 0, 1605, 1604, 1, 0, 0, 0, 1606, 1609, 1, 0, 0, 0, 1607, 1605, 1, 0, 0, 0, 1607, 1608, 1, 0, 0, 0, 1608, 371, 1, 0, 0, 0, 1609, 1607, 1, 0, 0, 0, 1610, 1613, 5, 39, 0, 0, 1611, 1614, 3, 374, 183, 0, 1612, 1614, 8, 13, 0, 0, 1613, 1611, 1, 0, 0, 0, 1613, 1612, 1, 0, 0, 0, 1614, 1615, 1, 0, 0, 0, 1615, 1616, 5, 39, 0, 0, 1616, 373, 1, 0, 0, 0, 1617, 1636, 5, 92, 0, 0, 1618, 1619, 5, 117, 0, 0, 1619, 1637, 3, 376, 184, 0, 1620, 1621, 5, 85, 0, 0, 1621, 1622, 3, 376, 184, 0, 1622, 1623, 3, 376, 184, 0, 1623, 1637, 1, 0, 0, 0, 1624, 1625, 5, 120, 0, 0, 1625, 1627, 7, 4, 0, 0, 1626, 1628, 7, 4, 0, 0, 1627, 1626, 1, 0, 0, 0, 1627, 1628, 1, 0, 0, 0, 1628, 1630, 1, 0, 0, 0, 1629, 1631, 7, 4, 0, 0, 1630, 1629, 1, 0, 0, 0, 1630, 1631, 1, 0, 0, 0, 1631, 1633, 1, 0, 0, 0, 1632, 1634, 7, 4, 0, 0, 1633, 1632, 1, 0, 0, 0, 1633, 1634, 1, 0, 0, 0, 1634, 1637, 1, 0, 0, 0, 1635, 1637, 7, 14, 0, 0, 1636, 1618, 1, 0, 0, 0, 1636, 1620, 1, 0, 0, 0, 1636, 1624, 1, 0, 0, 0, 1636, 1635, 1, 0, 0, 0, 1637, 375, 1, 0, 0, 0, 1638, 1639, 7, 4, 0, 0, 1639, 1640, 7, 4, 0, 0, 1640, 1641, 7, 4, 0, 0, 1641, 1642, 7, 4, 0, 0, 1642, 377, 1, 0, 0, 0, 1643, 1648, 5, 34, 0, 0, 1644, 1647, 3, 374, 183, 0, 1645, 1647, 8, 15, 0, 0, 1646, 1644, 1, 0, 0, 0, 1646, 1645, 1, 0, 0, 0, 1647, 1650, 1, 0, 0, 0, 1648, 1646, 1, 0, 0, 0, 1648, 1649, 1, 0, 0, 0, 1649, 1651, 1, 0, 0, 0, 1650, 1648, 1, 0, 0, 0, 1651, 1652, 5, 34, 0, 0, 1652, 379, 1, 0, 0, 0, 1653, 1654, 5, 64, 0, 0, 1654, 1655, 5, 34, 0, 0, 1655, 1661, 1, 0, 0, 0, 1656, 1657, 5, 34, 0, 0, 1657, 1660, 5, 34, 0, 0, 1658, 1660, 8, 16, 0, 0, 1659, 1656, 1, 0, 0, 0, 1659, 1658, 1, 0, 0, 0, 1660, 1663, 1, 0, 0, 0, 1661, 1659, 1, 0, 0, 0, 1661, 1662, 1, 0, 0, 0, 1662, 1664, 1, 0, 0, 0, 1663, 1661, 1, 0, 0, 0, 1664, 1665, 5, 34, 0, 0, 1665, 381, 1, 0, 0, 0, 1666, 1667, 5, 34, 0, 0, 1667, 1668, 5, 34, 0, 0, 1668, 1669, 5, 34, 0, 0, 1669, 1670, 5, 34, 0, 0, 1670, 1671, 5, 34, 0, 0, 1671, 1672, 5, 34, 0, 0, 1672, 1673, 5, 34, 0, 0, 1673, 1674, 5, 34, 0, 0, 1674, 1678, 1, 0, 0, 0, 1675, 1677, 8, 17, 0, 0, 1676, 1675, 1, 0, 0, 0, 1677, 1680, 1, 0, 0, 0, 1678, 1679, 1, 0, 0, 0, 1678, 1676, 1, 0, 0, 0, 1679, 1681, 1, 0, 0, 0, 1680, 1678, 1, 0, 0, 0, 1681, 1682, 5, 34, 0, 0, 1682, 1683, 5, 34, 0, 0, 1683, 1684, 5, 34, 0, 0, 1684, 1685, 5, 34, 0, 0, 1685, 1686, 5, 34, 0, 0, 1686, 1687, 5, 34, 0, 0, 1687, 1688, 5, 34, 0, 0, 1688, 1689, 5, 34, 0, 0, 1689, 1693, 1, 0, 0, 0, 1690, 1692, 5, 34, 0, 0, 1691, 1690, 1, 0, 0, 0, 1692, 1695, 1, 0, 0, 0, 1693, 1691, 1, 0, 0, 0, 1693, 1694, 1, 0, 0, 0, 1694, 1817, 1, 0, 0, 0, 1695, 1693, 1, 0, 0, 0, 1696, 1697, 5, 34, 0, 0, 1697, 1698, 5, 34, 0, 0, 1698, 1699, 5, 34, 0, 0, 1699, 1700, 5, 34, 0, 0, 1700, 1701, 5, 34, 0, 0, 1701, 1702, 5, 34, 0, 0, 1702, 1703, 5, 34, 0, 0, 1703, 1707, 1, 0, 0, 0, 1704, 1706, 8, 17, 0, 0, 1705, 1704, 1, 0, 0, 0, 1706, 1709, 1, 0, 0, 0, 1707, 1708, 1, 0, 0, 0, 1707, 1705, 1, 0, 0, 0, 1708, 1710, 1, 0, 0, 0, 1709, 1707, 1, 0, 0, 0, 1710, 1711, 5, 34, 0, 0, 1711, 1712, 5, 34, 0, 0, 1712, 1713, 5, 34, 0, 0, 1713, 1714, 5, 34, 0, 0, 1714, 1715, 5, 34, 0, 0, 1715, 1716, 5, 34, 0, 0, 1716, 1717, 5, 34, 0, 0, 1717, 1721, 1, 0, 0, 0, 1718, 1720, 5, 34, 0, 0, 1719, 1718, 1, 0, 0, 0, 1720, 1723, 1, 0, 0, 0, 1721, 1719, 1, 0, 0, 0, 1721, 1722, 1, 0, 0, 0, 1722, 1817, 1, 0, 0, 0, 1723, 1721, 1, 0, 0, 0, 1724, 1725, 5, 34, 0, 0, 1725, 1726, 5, 34, 0, 0, 1726, 1727, 5, 34, 0, 0, 1727, 1728, 5, 34, 0, 0, 1728, 1729, 5, 34, 0, 0, 1729, 1730, 5, 34, 0, 0, 1730, 1734, 1, 0, 0, 0, 1731, 1733, 8, 17, 0, 0, 1732, 1731, 1, 0, 0, 0, 1733, 1736, 1, 0, 0, 0, 1734, 1735, 1, 0, 0, 0, 1734, 1732, 1, 0, 0, 0, 1735, 1737, 1, 0, 0, 0, 1736, 1734, 1, 0, 0, 0, 1737, 1738, 5, 34, 0, 0, 1738, 1739, 5, 34, 0, 0, 1739, 1740, 5, 34, 0, 0, 1740, 1741, 5, 34, 0, 0, 1741, 1742, 5, 34, 0, 0, 1742, 1743, 5, 34, 0, 0, 1743, 1747, 1, 0, 0, 0, 1744, 1746, 5, 34, 0, 0, 1745, 1744, 1, 0, 0, 0, 1746, 1749, 1, 0, 0, 0, 1747, 1745, 1, 0, 0, 0, 1747, 1748, 1, 0, 0, 0, 1748, 1817, 1, 0, 0, 0, 1749, 1747, 1, 0, 0, 0, 1750, 1751, 5, 34, 0, 0, 1751, 1752, 5, 34, 0, 0, 1752, 1753, 5, 34, 0, 0, 1753, 1754, 5, 34, 0, 0, 1754, 1755, 5, 34, 0, 0, 1755, 1759, 1, 0, 0, 0, 1756, 1758, 8, 17, 0, 0, 1757, 1756, 1, 0, 0, 0, 1758, 1761, 1, 0, 0, 0, 1759, 1760, 1, 0, 0, 0, 1759, 1757, 1, 0, 0, 0, 1760, 1762, 1, 0, 0, 0, 1761, 1759, 1, 0, 0, 0, 1762, 1763, 5, 34, 0, 0, 1763, 1764, 5, 34, 0, 0, 1764, 1765, 5, 34, 0, 0, 1765, 1766, 5, 34, 0, 0, 1766, 1767, 5, 34, 0, 0, 1767, 1771, 1, 0, 0, 0, 1768, 1770, 5, 34, 0, 0, 1769, 1768, 1, 0, 0, 0, 1770, 1773, 1, 0, 0, 0, 1771, 1769, 1, 0, 0, 0, 1771, 1772, 1, 0, 0, 0, 1772, 1817, 1, 0, 0, 0, 1773, 1771, 1, 0, 0, 0, 1774, 1775, 5, 34, 0, 0, 1775, 1776, 5, 34, 0, 0, 1776, 1777, 5, 34, 0, 0, 1777, 1778, 5, 34, 0, 0, 1778, 1782, 1, 0, 0, 0, 1779, 1781, 8, 17, 0, 0, 1780, 1779, 1, 0, 0, 0, 1781, 1784, 1, 0, 0, 0, 1782, 1783, 1, 0, 0, 0, 1782, 1780, 1, 0, 0, 0, 1783, 1785, 1, 0, 0, 0, 1784, 1782, 1, 0, 0, 0, 1785, 1786, 5, 34, 0, 0, 1786, 1787, 5, 34, 0, 0, 1787, 1788, 5, 34, 0, 0, 1788, 1789, 5, 34, 0, 0, 1789, 1793, 1, 0, 0, 0, 1790, 1792, 5, 34, 0, 0, 1791, 1790, 1, 0, 0, 0, 1792, 1795, 1, 0, 0, 0, 1793, 1791, 1, 0, 0, 0, 1793, 1794, 1, 0, 0, 0, 1794, 1817, 1, 0, 0, 0, 1795, 1793, 1, 0, 0, 0, 1796, 1797, 5, 34, 0, 0, 1797, 1798, 5, 34, 0, 0, 1798, 1799, 5, 34, 0, 0, 1799, 1803, 1, 0, 0, 0, 1800, 1802, 8, 17, 0, 0, 1801, 1800, 1, 0, 0, 0, 1802, 1805, 1, 0, 0, 0, 1803, 1804, 1, 0, 0, 0, 1803, 1801, 1, 0, 0, 0, 1804, 1806, 1, 0, 0, 0, 1805, 1803, 1, 0, 0, 0, 1806, 1807, 5, 34, 0, 0, 1807, 1808, 5, 34, 0, 0, 1808, 1809, 5, 34, 0, 0, 1809, 1813, 1, 0, 0, 0, 1810, 1812, 5, 34, 0, 0, 1811, 1810, 1, 0, 0, 0, 1812, 1815, 1, 0, 0, 0, 1813, 1811, 1, 0, 0, 0, 1813, 1814, 1, 0, 0, 0, 1814, 1817, 1, 0, 0, 0, 1815, 1813, 1, 0, 0, 0, 1816, 1666, 1, 0, 0, 0, 1816, 1696, 1, 0, 0, 0, 1816, 1724, 1, 0, 0, 0, 1816, 1750, 1, 0, 0, 0, 1816, 1774, 1, 0, 0, 0, 1816, 1796, 1, 0, 0, 0, 1817, 383, 1, 0, 0, 0, 1818, 1819, 5, 34, 0, 0, 1819, 1820, 5, 34, 0, 0, 1820, 1821, 5, 34, 0, 0, 1821, 1822, 5, 34, 0, 0, 1822, 1823, 5, 34, 0, 0, 1823, 1824, 5, 34, 0, 0, 1824, 1825, 5, 34, 0, 0, 1825, 1826, 5, 34, 0, 0, 1826, 1830, 1, 0, 0, 0, 1827, 1829, 9, 0, 0, 0, 1828, 1827, 1, 0, 0, 0, 1829, 1832, 1, 0, 0, 0, 1830, 1831, 1, 0, 0, 0, 1830, 1828, 1, 0, 0, 0, 1831, 1833, 1, 0, 0, 0, 1832, 1830, 1, 0, 0, 0, 1833, 1834, 5, 34, 0, 0, 1834, 1835, 5, 34, 0, 0, 1835, 1836, 5, 34, 0, 0, 1836, 1837, 5, 34, 0, 0, 1837, 1838, 5, 34, 0, 0, 1838, 1839, 5, 34, 0, 0, 1839, 1840, 5, 34, 0, 0, 1840, 1841, 5, 34, 0, 0, 1841, 1845, 1, 0, 0, 0, 1842, 1844, 5, 34, 0, 0, 1843, 1842, 1, 0, 0, 0, 1844, 1847, 1, 0, 0, 0, 1845, 1843, 1, 0, 0, 0, 1845, 1846, 1, 0, 0, 0, 1846, 1969, 1, 0, 0, 0, 1847, 1845, 1, 0, 0, 0, 1848, 1849, 5, 34, 0, 0, 1849, 1850, 5, 34, 0, 0, 1850, 1851, 5, 34, 0, 0, 1851, 1852, 5, 34, 0, 0, 1852, 1853, 5, 34, 0, 0, 1853, 1854, 5, 34, 0, 0, 1854, 1855, 5, 34, 0, 0, 1855, 1859, 1, 0, 0, 0, 1856, 1858, 9, 0, 0, 0, 1857, 1856, 1, 0, 0, 0, 1858, 1861, 1, 0, 0, 0, 1859, 1860, 1, 0, 0, 0, 1859, 1857, 1, 0, 0, 0, 1860, 1862, 1, 0, 0, 0, 1861, 1859, 1, 0, 0, 0, 1862, 1863, 5, 34, 0, 0, 1863, 1864, 5, 34, 0, 0, 1864, 1865, 5, 34, 0, 0, 1865, 1866, 5, 34, 0, 0, 1866, 1867, 5, 34, 0, 0, 1867, 1868, 5, 34, 0, 0, 1868, 1869, 5, 34, 0, 0, 1869, 1873, 1, 0, 0, 0, 1870, 1872, 5, 34, 0, 0, 1871, 1870, 1, 0, 0, 0, 1872, 1875, 1, 0, 0, 0, 1873, 1871, 1, 0, 0, 0, 1873, 1874, 1, 0, 0, 0, 1874, 1969, 1, 0, 0, 0, 1875, 1873, 1, 0, 0, 0, 1876, 1877, 5, 34, 0, 0, 1877, 1878, 5, 34, 0, 0, 1878, 1879, 5, 34, 0, 0, 1879, 1880, 5, 34, 0, 0, 1880, 1881, 5, 34, 0, 0, 1881, 1882, 5, 34, 0, 0, 1882, 1886, 1, 0, 0, 0, 1883, 1885, 9, 0, 0, 0, 1884, 1883, 1, 0, 0, 0, 1885, 1888, 1, 0, 0, 0, 1886, 1887, 1, 0, 0, 0, 1886, 1884, 1, 0, 0, 0, 1887, 1889, 1, 0, 0, 0, 1888, 1886, 1, 0, 0, 0, 1889, 1890, 5, 34, 0, 0, 1890, 1891, 5, 34, 0, 0, 1891, 1892, 5, 34, 0, 0, 1892, 1893, 5, 34, 0, 0, 1893, 1894, 5, 34, 0, 0, 1894, 1895, 5, 34, 0, 0, 1895, 1899, 1, 0, 0, 0, 1896, 1898, 5, 34, 0, 0, 1897, 1896, 1, 0, 0, 0, 1898, 1901, 1, 0, 0, 0, 1899, 1897, 1, 0, 0, 0, 1899, 1900, 1, 0, 0, 0, 1900, 1969, 1, 0, 0, 0, 1901, 1899, 1, 0, 0, 0, 1902, 1903, 5, 34, 0, 0, 1903, 1904, 5, 34, 0, 0, 1904, 1905, 5, 34, 0, 0, 1905, 1906, 5, 34, 0, 0, 1906, 1907, 5, 34, 0, 0, 1907, 1911, 1, 0, 0, 0, 1908, 1910, 9, 0, 0, 0, 1909, 1908, 1, 0, 0, 0, 1910, 1913, 1, 0, 0, 0, 1911, 1912, 1, 0, 0, 0, 1911, 1909, 1, 0, 0, 0, 1912, 1914, 1, 0, 0, 0, 1913, 1911, 1, 0, 0, 0, 1914, 1915, 5, 34, 0, 0, 1915, 1916, 5, 34, 0, 0, 1916, 1917, 5, 34, 0, 0, 1917, 1918, 5, 34, 0, 0, 1918, 1919, 5, 34, 0, 0, 1919, 1923, 1, 0, 0, 0, 1920, 1922, 5, 34, 0, 0, 1921, 1920, 1, 0, 0, 0, 1922, 1925, 1, 0, 0, 0, 1923, 1921, 1, 0, 0, 0, 1923, 1924, 1, 0, 0, 0, 1924, 1969, 1, 0, 0, 0, 1925, 1923, 1, 0, 0, 0, 1926, 1927, 5, 34, 0, 0, 1927, 1928, 5, 34, 0, 0, 1928, 1929, 5, 34, 0, 0, 1929, 1930, 5, 34, 0, 0, 1930, 1934, 1, 0, 0, 0, 1931, 1933, 9, 0, 0, 0, 1932, 1931, 1, 0, 0, 0, 1933, 1936, 1, 0, 0, 0, 1934, 1935, 1, 0, 0, 0, 1934, 1932, 1, 0, 0, 0, 1935, 1937, 1, 0, 0, 0, 1936, 1934, 1, 0, 0, 0, 1937, 1938, 5, 34, 0, 0, 1938, 1939, 5, 34, 0, 0, 1939, 1940, 5, 34, 0, 0, 1940, 1941, 5, 34, 0, 0, 1941, 1945, 1, 0, 0, 0, 1942, 1944, 5, 34, 0, 0, 1943, 1942, 1, 0, 0, 0, 1944, 1947, 1, 0, 0, 0, 1945, 1943, 1, 0, 0, 0, 1945, 1946, 1, 0, 0, 0, 1946, 1969, 1, 0, 0, 0, 1947, 1945, 1, 0, 0, 0, 1948, 1949, 5, 34, 0, 0, 1949, 1950, 5, 34, 0, 0, 1950, 1951, 5, 34, 0, 0, 1951, 1955, 1, 0, 0, 0, 1952, 1954, 9, 0, 0, 0, 1953, 1952, 1, 0, 0, 0, 1954, 1957, 1, 0, 0, 0, 1955, 1956, 1, 0, 0, 0, 1955, 1953, 1, 0, 0, 0, 1956, 1958, 1, 0, 0, 0, 1957, 1955, 1, 0, 0, 0, 1958, 1959, 5, 34, 0, 0, 1959, 1960, 5, 34, 0, 0, 1960, 1961, 5, 34, 0, 0, 1961, 1965, 1, 0, 0, 0, 1962, 1964, 5, 34, 0, 0, 1963, 1962, 1, 0, 0, 0, 1964, 1967, 1, 0, 0, 0, 1965, 1963, 1, 0, 0, 0, 1965, 1966, 1, 0, 0, 0, 1966, 1969, 1, 0, 0, 0, 1967, 1965, 1, 0, 0, 0, 1968, 1818, 1, 0, 0, 0, 1968, 1848, 1, 0, 0, 0, 1968, 1876, 1, 0, 0, 0, 1968, 1902, 1, 0, 0, 0, 1968, 1926, 1, 0, 0, 0, 1968, 1948, 1, 0, 0, 0, 1969, 385, 1, 0, 0, 0, 1970, 1971, 7, 18, 0, 0, 1971, 387, 1, 0, 0, 0, 1972, 1973, 5, 47, 0, 0, 1973, 1974, 5, 47, 0, 0, 1974, 1975, 5, 47, 0, 0, 1975, 1979, 1, 0, 0, 0, 1976, 1978, 8, 18, 0, 0, 1977, 1976, 1, 0, 0, 0, 1978, 1981, 1, 0, 0, 0, 1979, 1977, 1, 0, 0, 0, 1979, 1980, 1, 0, 0, 0, 1980, 1982, 1, 0, 0, 0, 1981, 1979, 1, 0, 0, 0, 1982, 1983, 6, 190, 0, 0, 1983, 389, 1, 0, 0, 0, 1984, 1985, 5, 47, 0, 0, 1985, 1986, 5, 42, 0, 0, 1986, 1987, 5, 42, 0, 0, 1987, 1991, 1, 0, 0, 0, 1988, 1990, 9, 0, 0, 0, 1989, 1988, 1, 0, 0, 0, 1990, 1993, 1, 0, 0, 0, 1991, 1992, 1, 0, 0, 0, 1991, 1989, 1, 0, 0, 0, 1992, 1994, 1, 0, 0, 0, 1993, 1991, 1, 0, 0, 0, 1994, 1995, 5, 42, 0, 0, 1995, 1996, 5, 47, 0, 0, 1996, 1997, 1, 0, 0, 0, 1997, 1998, 6, 191, 0, 0, 1998, 391, 1, 0, 0, 0, 1999, 2000, 5, 47, 0, 0, 2000, 2001, 5, 47, 0, 0, 2001, 2005, 1, 0, 0, 0, 2002, 2004, 8, 18, 0, 0, 2003, 2002, 1, 0, 0, 0, 2004, 2007, 1, 0, 0, 0, 2005, 2003, 1, 0, 0, 0, 2005, 2006, 1, 0, 0, 0, 2006, 2008, 1, 0, 0, 0, 2007, 2005, 1, 0, 0, 0, 2008, 2009, 6, 192, 0, 0, 2009, 393, 1, 0, 0, 0, 2010, 2011, 5, 47, 0, 0, 2011, 2012, 5, 42, 0, 0, 2012, 2016, 1, 0, 0, 0, 2013, 2015, 9, 0, 0, 0, 2014, 2013, 1, 0, 0, 0, 2015, 2018, 1, 0, 0, 0, 2016, 2017, 1, 0, 0, 0, 2016, 2014, 1, 0, 0, 0, 2017, 2019, 1, 0, 0, 0, 2018, 2016, 1, 0, 0, 0, 2019, 2020, 5, 42, 0, 0, 2020, 2021, 5, 47, 0, 0, 2021, 2022, 1, 0, 0, 0, 2022, 2023, 6, 193, 0, 0, 2023, 395, 1, 0, 0, 0, 2024, 2027, 7, 19, 0, 0, 2025, 2027, 3, 386, 189, 0, 2026, 2024, 1, 0, 0, 0, 2026, 2025, 1, 0, 0, 0, 2027, 2028, 1, 0, 0, 0, 2028, 2026, 1, 0, 0, 0, 2028, 2029, 1, 0, 0, 0, 2029, 2030, 1, 0, 0, 0, 2030, 2031, 6, 194, 1, 0, 2031, 397, 1, 0, 0, 0, 2032, 2033, 5, 65279, 0, 0, 2033, 2034, 1, 0, 0, 0, 2034, 2035, 6, 195, 2, 0, 2035, 399, 1, 0, 0, 0, 2036, 2043, 5, 35, 0, 0, 2037, 2042, 3, 402, 197, 0, 2038, 2042, 8, 20, 0, 0, 2039, 2040, 5, 47, 0, 0, 2040, 2042, 8, 21, 0, 0, 2041, 2037, 1, 0, 0, 0, 2041, 2038, 1, 0, 0, 0, 2041, 2039, 1, 0, 0, 0, 2042, 2045, 1, 0, 0, 0, 2043, 2041, 1, 0, 0, 0, 2043, 2044, 1, 0, 0, 0, 2044, 2050, 1, 0, 0, 0, 2045, 2043, 1, 0, 0, 0, 2046, 2048, 5, 47, 0, 0, 2047, 2049, 7, 22, 0, 0, 2048, 2047, 1, 0, 0, 0, 2049, 2051, 1, 0, 0, 0, 2050, 2046, 1, 0, 0, 0, 2050, 2051, 1, 0, 0, 0, 2051, 2052, 1, 0, 0, 0, 2052, 2053, 6, 196, 3, 0, 2053, 401, 1, 0, 0, 0, 2054, 2058, 5, 34, 0, 0, 2055, 2057, 8, 23, 0, 0, 2056, 2055, 1, 0, 0, 0, 2057, 2060, 1, 0, 0, 0, 2058, 2056, 1, 0, 0, 0, 2058, 2059, 1, 0, 0, 0, 2059, 2061, 1, 0, 0, 0, 2060, 2058, 1, 0, 0, 0, 2061, 2062, 5, 34, 0, 0, 2062, 403, 1, 0, 0, 0, 2063, 2064, 5, 36, 0, 0, 2064, 2065, 5, 34, 0, 0, 2065, 2066, 1, 0, 0, 0, 2066, 2067, 6, 198, 4, 0, 2067, 405, 1, 0, 0, 0, 2068, 2069, 5, 36, 0, 0, 2069, 2070, 5, 64, 0, 0, 2070, 2075, 5, 34, 0, 0, 2071, 2072, 5, 64, 0, 0, 2072, 2073, 5, 36, 0, 0, 2073, 2075, 5, 34, 0, 0, 2074, 2068, 1, 0, 0, 0, 2074, 2071, 1, 0, 0, 0, 2075, 2076, 1, 0, 0, 0, 2076, 2077, 6, 199, 5, 0, 2077, 407, 1, 0, 0, 0, 2078, 2079, 5, 36, 0, 0, 2079, 2080, 5, 36, 0, 0, 2080, 2081, 1, 0, 0, 0, 2081, 2082, 5, 34, 0, 0, 2082, 2083, 5, 34, 0, 0, 2083, 2084, 5, 34, 0, 0, 2084, 2085, 5, 34, 0, 0, 2085, 2086, 1, 0, 0, 0, 2086, 2087, 6, 200, 6, 0, 2087, 2088, 6, 200, 7, 0, 2088, 409, 1, 0, 0, 0, 2089, 2090, 5, 36, 0, 0, 2090, 2091, 5, 36, 0, 0, 2091, 2092, 1, 0, 0, 0, 2092, 2093, 5, 34, 0, 0, 2093, 2094, 5, 34, 0, 0, 2094, 2095, 5, 34, 0, 0, 2095, 2096, 1, 0, 0, 0, 2096, 2097, 6, 201, 6, 0, 2097, 2098, 6, 201, 8, 0, 2098, 411, 1, 0, 0, 0, 2099, 2100, 5, 36, 0, 0, 2100, 2101, 5, 34, 0, 0, 2101, 2102, 5, 34, 0, 0, 2102, 2103, 5, 34, 0, 0, 2103, 2104, 5, 34, 0, 0, 2104, 2105, 1, 0, 0, 0, 2105, 2106, 6, 202, 6, 0, 2106, 2107, 6, 202, 9, 0, 2107, 413, 1, 0, 0, 0, 2108, 2109, 5, 36, 0, 0, 2109, 2110, 5, 34, 0, 0, 2110, 2111, 5, 34, 0, 0, 2111, 2112, 5, 34, 0, 0, 2112, 2113, 1, 0, 0, 0, 2113, 2114, 6, 203, 10, 0, 2114, 415, 1, 0, 0, 0, 2115, 2116, 4, 204, 0, 0, 2116, 2117, 5, 125, 0, 0, 2117, 2118, 6, 204, 11, 0, 2118, 2119, 1, 0, 0, 0, 2119, 2120, 6, 204, 12, 0, 2120, 417, 1, 0, 0, 0, 2121, 2122, 4, 205, 1, 0, 2122, 2123, 5, 40, 0, 0, 2123, 2124, 6, 205, 13, 0, 2124, 2125, 1, 0, 0, 0, 2125, 2126, 6, 205, 14, 0, 2126, 419, 1, 0, 0, 0, 2127, 2128, 4, 206, 2, 0, 2128, 2129, 5, 41, 0, 0, 2129, 2130, 6, 206, 15, 0, 2130, 2131, 1, 0, 0, 0, 2131, 2132, 6, 206, 16, 0, 2132, 421, 1, 0, 0, 0, 2133, 2134, 4, 207, 3, 0, 2134, 2135, 5, 91, 0, 0, 2135, 2136, 6, 207, 17, 0, 2136, 2137, 1, 0, 0, 0, 2137, 2138, 6, 207, 18, 0, 2138, 423, 1, 0, 0, 0, 2139, 2140, 4, 208, 4, 0, 2140, 2141, 5, 93, 0, 0, 2141, 2142, 6, 208, 19, 0, 2142, 2143, 1, 0, 0, 0, 2143, 2144, 6, 208, 20, 0, 2144, 425, 1, 0, 0, 0, 2145, 2146, 4, 209, 5, 0, 2146, 2147, 5, 125, 0, 0, 2147, 2148, 5, 125, 0, 0, 2148, 2149, 1, 0, 0, 0, 2149, 2150, 6, 209, 21, 0, 2150, 2151, 1, 0, 0, 0, 2151, 2152, 6, 209, 12, 0, 2152, 2153, 6, 209, 22, 0, 2153, 427, 1, 0, 0, 0, 2154, 2155, 4, 210, 6, 0, 2155, 2156, 5, 125, 0, 0, 2156, 2157, 6, 210, 23, 0, 2157, 2158, 1, 0, 0, 0, 2158, 2159, 6, 210, 12, 0, 2159, 2160, 6, 210, 22, 0, 2160, 429, 1, 0, 0, 0, 2161, 2162, 4, 211, 7, 0, 2162, 2163, 5, 123, 0, 0, 2163, 2164, 6, 211, 24, 0, 2164, 2165, 1, 0, 0, 0, 2165, 2166, 6, 211, 25, 0, 2166, 431, 1, 0, 0, 0, 2167, 2168, 4, 212, 8, 0, 2168, 2169, 5, 58, 0, 0, 2169, 2170, 1, 0, 0, 0, 2170, 2171, 6, 212, 26, 0, 2171, 433, 1, 0, 0, 0, 2172, 2173, 4, 213, 9, 0, 2173, 2174, 5, 58, 0, 0, 2174, 2175, 1, 0, 0, 0, 2175, 2176, 6, 213, 26, 0, 2176, 2177, 6, 213, 27, 0, 2177, 435, 1, 0, 0, 0, 2178, 2179, 5, 123, 0, 0, 2179, 437, 1, 0, 0, 0, 2180, 2181, 5, 125, 0, 0, 2181, 439, 1, 0, 0, 0, 2182, 2183, 5, 58, 0, 0, 2183, 441, 1, 0, 0, 0, 2184, 2185, 5, 40, 0, 0, 2185, 443, 1, 0, 0, 0, 2186, 2187, 5, 41, 0, 0, 2187, 445, 1, 0, 0, 0, 2188, 2189, 5, 91, 0, 0, 2189, 447, 1, 0, 0, 0, 2190, 2191, 5, 93, 0, 0, 2191, 449, 1, 0, 0, 0, 2192, 2193, 5, 123, 0, 0, 2193, 2194, 5, 123, 0, 0, 2194, 2195, 1, 0, 0, 0, 2195, 2196, 6, 221, 28, 0, 2196, 451, 1, 0, 0, 0, 2197, 2198, 5, 125, 0, 0, 2198, 2199, 5, 125, 0, 0, 2199, 2200, 1, 0, 0, 0, 2200, 2201, 6, 222, 28, 0, 2201, 453, 1, 0, 0, 0, 2202, 2203, 3, 374, 183, 0, 2203, 2204, 1, 0, 0, 0, 2204, 2205, 6, 223, 28, 0, 2205, 455, 1, 0, 0, 0, 2206, 2208, 8, 24, 0, 0, 2207, 2206, 1, 0, 0, 0, 2208, 2209, 1, 0, 0, 0, 2209, 2207, 1, 0, 0, 0, 2209, 2210, 1, 0, 0, 0, 2210, 457, 1, 0, 0, 0, 2211, 2212, 5, 123, 0, 0, 2212, 2213, 6, 225, 29, 0, 2213, 2214, 1, 0, 0, 0, 2214, 2215, 6, 225, 25, 0, 2215, 2216, 6, 225, 30, 0, 2216, 459, 1, 0, 0, 0, 2217, 2218, 5, 34, 0, 0, 2218, 2219, 1, 0, 0, 0, 2219, 2220, 6, 226, 31, 0, 2220, 2221, 6, 226, 22, 0, 2221, 461, 1, 0, 0, 0, 2222, 2223, 5, 123, 0, 0, 2223, 2224, 5, 123, 0, 0, 2224, 2225, 1, 0, 0, 0, 2225, 2226, 6, 227, 28, 0, 2226, 463, 1, 0, 0, 0, 2227, 2228, 5, 125, 0, 0, 2228, 2229, 5, 125, 0, 0, 2229, 2230, 1, 0, 0, 0, 2230, 2231, 6, 228, 28, 0, 2231, 465, 1, 0, 0, 0, 2232, 2233, 5, 34, 0, 0, 2233, 2234, 5, 34, 0, 0, 2234, 2235, 1, 0, 0, 0, 2235, 2236, 6, 229, 28, 0, 2236, 467, 1, 0, 0, 0, 2237, 2239, 8, 25, 0, 0, 2238, 2237, 1, 0, 0, 0, 2239, 2240, 1, 0, 0, 0, 2240, 2238, 1, 0, 0, 0, 2240, 2241, 1, 0, 0, 0, 2241, 2242, 1, 0, 0, 0, 2242, 2243, 6, 230, 28, 0, 2243, 469, 1, 0, 0, 0, 2244, 2245, 5, 123, 0, 0, 2245, 2246, 6, 231, 32, 0, 2246, 2247, 1, 0, 0, 0, 2247, 2248, 6, 231, 25, 0, 2248, 2249, 6, 231, 30, 0, 2249, 471, 1, 0, 0, 0, 2250, 2251, 5, 34, 0, 0, 2251, 2252, 1, 0, 0, 0, 2252, 2253, 6, 232, 31, 0, 2253, 2254, 6, 232, 22, 0, 2254, 473, 1, 0, 0, 0, 2255, 2256, 5, 123, 0, 0, 2256, 2257, 5, 123, 0, 0, 2257, 2258, 1, 0, 0, 0, 2258, 2259, 6, 233, 28, 0, 2259, 475, 1, 0, 0, 0, 2260, 2261, 5, 125, 0, 0, 2261, 2262, 5, 125, 0, 0, 2262, 2263, 1, 0, 0, 0, 2263, 2264, 6, 234, 28, 0, 2264, 477, 1, 0, 0, 0, 2265, 2266, 5, 34, 0, 0, 2266, 2267, 5, 34, 0, 0, 2267, 2268, 5, 34, 0, 0, 2268, 2272, 1, 0, 0, 0, 2269, 2271, 5, 34, 0, 0, 2270, 2269, 1, 0, 0, 0, 2271, 2274, 1, 0, 0, 0, 2272, 2270, 1, 0, 0, 0, 2272, 2273, 1, 0, 0, 0, 2273, 2275, 1, 0, 0, 0, 2274, 2272, 1, 0, 0, 0, 2275, 2276, 6, 235, 33, 0, 2276, 2277, 6, 235, 22, 0, 2277, 479, 1, 0, 0, 0, 2278, 2280, 5, 34, 0, 0, 2279, 2281, 5, 34, 0, 0, 2280, 2279, 1, 0, 0, 0, 2280, 2281, 1, 0, 0, 0, 2281, 2282, 1, 0, 0, 0, 2282, 2283, 6, 236, 28, 0, 2283, 481, 1, 0, 0, 0, 2284, 2286, 8, 25, 0, 0, 2285, 2284, 1, 0, 0, 0, 2286, 2287, 1, 0, 0, 0, 2287, 2285, 1, 0, 0, 0, 2287, 2288, 1, 0, 0, 0, 2288, 2289, 1, 0, 0, 0, 2289, 2290, 6, 237, 28, 0, 2290, 483, 1, 0, 0, 0, 2291, 2292, 5, 123, 0, 0, 2292, 2293, 6, 238, 34, 0, 2293, 2294, 1, 0, 0, 0, 2294, 2295, 6, 238, 25, 0, 2295, 2296, 6, 238, 30, 0, 2296, 485, 1, 0, 0, 0, 2297, 2298, 5, 123, 0, 0, 2298, 2299, 5, 123, 0, 0, 2299, 2300, 1, 0, 0, 0, 2300, 2301, 6, 239, 35, 0, 2301, 2302, 1, 0, 0, 0, 2302, 2303, 6, 239, 25, 0, 2303, 2304, 6, 239, 30, 0, 2304, 487, 1, 0, 0, 0, 2305, 2306, 5, 34, 0, 0, 2306, 2307, 5, 34, 0, 0, 2307, 2308, 5, 34, 0, 0, 2308, 2312, 1, 0, 0, 0, 2309, 2311, 5, 34, 0, 0, 2310, 2309, 1, 0, 0, 0, 2311, 2314, 1, 0, 0, 0, 2312, 2310, 1, 0, 0, 0, 2312, 2313, 1, 0, 0, 0, 2313, 2315, 1, 0, 0, 0, 2314, 2312, 1, 0, 0, 0, 2315, 2316, 6, 240, 33, 0, 2316, 2317, 6, 240, 22, 0, 2317, 489, 1, 0, 0, 0, 2318, 2320, 5, 34, 0, 0, 2319, 2321, 5, 34, 0, 0, 2320, 2319, 1, 0, 0, 0, 2320, 2321, 1, 0, 0, 0, 2321, 2322, 1, 0, 0, 0, 2322, 2323, 6, 241, 28, 0, 2323, 491, 1, 0, 0, 0, 2324, 2326, 8, 25, 0, 0, 2325, 2324, 1, 0, 0, 0, 2326, 2327, 1, 0, 0, 0, 2327, 2325, 1, 0, 0, 0, 2327, 2328, 1, 0, 0, 0, 2328, 2329, 1, 0, 0, 0, 2329, 2330, 6, 242, 28, 0, 2330, 493, 1, 0, 0, 0, 2331, 2332, 5, 123, 0, 0, 2332, 2333, 1, 0, 0, 0, 2333, 2334, 6, 243, 28, 0, 2334, 495, 1, 0, 0, 0, 2335, 2336, 5, 125, 0, 0, 2336, 2337, 1, 0, 0, 0, 2337, 2338, 6, 244, 28, 0, 2338, 497, 1, 0, 0, 0, 2339, 2340, 5, 92, 0, 0, 2340, 2346, 5, 34, 0, 0, 2341, 2342, 5, 34, 0, 0, 2342, 2346, 5, 34, 0, 0, 2343, 2346, 5, 92, 0, 0, 2344, 2346, 8, 26, 0, 0, 2345, 2339, 1, 0, 0, 0, 2345, 2341, 1, 0, 0, 0, 2345, 2343, 1, 0, 0, 0, 2345, 2344, 1, 0, 0, 0, 2346, 2347, 1, 0, 0, 0, 2347, 2345, 1, 0, 0, 0, 2347, 2348, 1, 0, 0, 0, 2348, 2349, 1, 0, 0, 0, 2349, 2350, 6, 245, 28, 0, 2350, 499, 1, 0, 0, 0, 2351, 2352, 4, 246, 10, 0, 2352, 2353, 5, 125, 0, 0, 2353, 2354, 5, 125, 0, 0, 2354, 2355, 1, 0, 0, 0, 2355, 2356, 6, 246, 36, 0, 2356, 2357, 1, 0, 0, 0, 2357, 2358, 6, 246, 12, 0, 2358, 2359, 6, 246, 22, 0, 2359, 2360, 6, 246, 22, 0, 2360, 501, 1, 0, 0, 0, 2361, 2362, 5, 125, 0, 0, 2362, 2363, 6, 247, 37, 0, 2363, 2364, 1, 0, 0, 0, 2364, 2365, 6, 247, 12, 0, 2365, 2366, 6, 247, 22, 0, 2366, 2367, 6, 247, 22, 0, 2367, 503, 1, 0, 0, 0, 2368, 2369, 5, 123, 0, 0, 2369, 2370, 5, 123, 0, 0, 2370, 2371, 1, 0, 0, 0, 2371, 2372, 6, 248, 28, 0, 2372, 505, 1, 0, 0, 0, 2373, 2374, 5, 125, 0, 0, 2374, 2375, 5, 125, 0, 0, 2375, 2376, 1, 0, 0, 0, 2376, 2377, 6, 249, 28, 0, 2377, 507, 1, 0, 0, 0, 2378, 2379, 5, 34, 0, 0, 2379, 2380, 5, 34, 0, 0, 2380, 2381, 5, 34, 0, 0, 2381, 2382, 5, 34, 0, 0, 2382, 2386, 1, 0, 0, 0, 2383, 2385, 5, 34, 0, 0, 2384, 2383, 1, 0, 0, 0, 2385, 2388, 1, 0, 0, 0, 2386, 2384, 1, 0, 0, 0, 2386, 2387, 1, 0, 0, 0, 2387, 2389, 1, 0, 0, 0, 2388, 2386, 1, 0, 0, 0, 2389, 2390, 6, 250, 33, 0, 2390, 2391, 6, 250, 22, 0, 2391, 509, 1, 0, 0, 0, 2392, 2394, 5, 34, 0, 0, 2393, 2395, 5, 34, 0, 0, 2394, 2393, 1, 0, 0, 0, 2394, 2395, 1, 0, 0, 0, 2395, 2397, 1, 0, 0, 0, 2396, 2398, 5, 34, 0, 0, 2397, 2396, 1, 0, 0, 0, 2397, 2398, 1, 0, 0, 0, 2398, 2399, 1, 0, 0, 0, 2399, 2400, 6, 251, 28, 0, 2400, 511, 1, 0, 0, 0, 2401, 2403, 8, 25, 0, 0, 2402, 2401, 1, 0, 0, 0, 2403, 2404, 1, 0, 0, 0, 2404, 2402, 1, 0, 0, 0, 2404, 2405, 1, 0, 0, 0, 2405, 2406, 1, 0, 0, 0, 2406, 2407, 6, 252, 28, 0, 2407, 513, 1, 0, 0, 0, 2408, 2409, 5, 123, 0, 0, 2409, 2410, 6, 253, 38, 0, 2410, 2411, 1, 0, 0, 0, 2411, 2412, 6, 253, 25, 0, 2412, 2413, 6, 253, 30, 0, 2413, 515, 1, 0, 0, 0, 2414, 2415, 5, 123, 0, 0, 2415, 2416, 5, 123, 0, 0, 2416, 2417, 1, 0, 0, 0, 2417, 2418, 6, 254, 39, 0, 2418, 2419, 1, 0, 0, 0, 2419, 2420, 6, 254, 25, 0, 2420, 2421, 6, 254, 30, 0, 2421, 517, 1, 0, 0, 0, 2422, 2423, 5, 34, 0, 0, 2423, 2424, 5, 34, 0, 0, 2424, 2425, 5, 34, 0, 0, 2425, 2426, 5, 34, 0, 0, 2426, 2430, 1, 0, 0, 0, 2427, 2429, 5, 34, 0, 0, 2428, 2427, 1, 0, 0, 0, 2429, 2432, 1, 0, 0, 0, 2430, 2428, 1, 0, 0, 0, 2430, 2431, 1, 0, 0, 0, 2431, 2433, 1, 0, 0, 0, 2432, 2430, 1, 0, 0, 0, 2433, 2434, 6, 255, 33, 0, 2434, 2435, 6, 255, 22, 0, 2435, 519, 1, 0, 0, 0, 2436, 2438, 5, 34, 0, 0, 2437, 2439, 5, 34, 0, 0, 2438, 2437, 1, 0, 0, 0, 2438, 2439, 1, 0, 0, 0, 2439, 2441, 1, 0, 0, 0, 2440, 2442, 5, 34, 0, 0, 2441, 2440, 1, 0, 0, 0, 2441, 2442, 1, 0, 0, 0, 2442, 2443, 1, 0, 0, 0, 2443, 2444, 6, 256, 28, 0, 2444, 521, 1, 0, 0, 0, 2445, 2447, 8, 25, 0, 0, 2446, 2445, 1, 0, 0, 0, 2447, 2448, 1, 0, 0, 0, 2448, 2446, 1, 0, 0, 0, 2448, 2449, 1, 0, 0, 0, 2449, 2450, 1, 0, 0, 0, 2450, 2451, 6, 257, 28, 0, 2451, 523, 1, 0, 0, 0, 2452, 2453, 5, 123, 0, 0, 2453, 2454, 1, 0, 0, 0, 2454, 2455, 6, 258, 28, 0, 2455, 525, 1, 0, 0, 0, 2456, 2457, 5, 125, 0, 0, 2457, 2458, 1, 0, 0, 0, 2458, 2459, 6, 259, 28, 0, 2459, 527, 1, 0, 0, 0, 103, 0, 1, 2, 3, 4, 5, 6, 7, 1459, 1463, 1467, 1469, 1479, 1485, 1491, 1495, 1503, 1509, 1513, 1521, 1527, 1531, 1535, 1539, 1541, 1547, 1555, 1559, 1562, 1569, 1573, 1576, 1582, 1587, 1593, 1597, 1601, 1607, 1613, 1627, 1630, 1633, 1636, 1646, 1648, 1659, 1661, 1678, 1693, 1707, 1721, 1734, 1747, 1759, 1771, 1782, 1793, 1803, 1813, 1816, 1830, 1845, 1859, 1873, 1886, 1899, 1911, 1923, 1934, 1945, 1955, 1965, 1968, 1979, 1991, 2005, 2016, 2026, 2028, 2041, 2043, 2048, 2050, 2058, 2074, 2209, 2240, 2272, 2280, 2287, 2312, 2320, 2327, 2345, 2347, 2386, 2394, 2397, 2404, 2430, 2438, 2441, 2448, 40, 0, 2, 0, 0, 1, 0, 6, 0, 0, 0, 3, 0, 5, 1, 0, 5, 2, 0, 7, 196, 0, 5, 7, 0, 5, 4, 0, 5, 6, 0, 5, 3, 0, 1, 204, 0, 7, 198, 0, 1, 205, 1, 7, 200, 0, 1, 206, 2, 7, 201, 0, 1, 207, 3, 7, 202, 0, 1, 208, 4, 7, 203, 0, 1, 209, 5, 4, 0, 0, 1, 210, 6, 1, 211, 7, 7, 197, 0, 7, 199, 0, 5, 5, 0, 7, 1, 0, 1, 225, 8, 5, 0, 0, 7, 157, 0, 1, 231, 9, 7, 104, 0, 1, 238, 10, 1, 239, 11, 1, 246, 12, 1, 247, 13, 1, 253, 14, 1, 254, 15], -); - -pub fn metadata() -> &'static GrammarMetadata { - &METADATA -} - -pub fn rule_names() -> &'static [&'static str] { - METADATA.rule_names() -} - -pub use antlr4_runtime::generated::{lex, lex_stream}; - - -static ATN_CELL: OnceLock = OnceLock::new(); - -/// Deserializes and caches the grammar ATN for all lexer instances. -fn atn() -> &'static LexerAtn { - ATN_CELL.get_or_init(|| { - let serialized = metadata().serialized_atn(); - AtnDeserializer::new(&serialized) - .deserialize() - .expect("generated lexer contains a valid ANTLR serialized ATN") - }) -} - -static LEXER_DFA_DATA: &[u32] = &[1280852999,8,4294967295,0,21,29,38,4294967295,46,56,65,0,0,65535,4294967295,1,0,65535,0,2,1,65535,1,3,1,65535,4294967295,4,1,65535,2,5,1,65535,4294967295,2,1,65535,3,6,1,65535,4294967295,7,1,65535,4294967295,8,1,65535,4294967295,2,1,65535,4,2,1,65535,5,9,1,65535,4294967295,10,1,65535,4294967295,11,1,65535,6,12,1,65535,4294967295,13,1,65535,4294967295,14,1,65535,7,15,1,65535,4294967295,16,1,65535,4294967295,16,1,65535,8,17,2,65535,4294967295,18,2,65535,9,19,1,65535,10,20,1,65535,11,21,1,65535,4294967295,2,1,65535,12,2,1,65535,13,2,1,65535,14,22,3,65535,4294967295,23,3,65535,15,24,1,65535,16,25,1,65535,17,26,1,65535,4294967295,27,1,65535,18,2,1,65535,19,2,1,65535,20,27,1,65535,21,28,4,65535,4294967295,29,4,65535,22,30,1,65535,23,31,1,65535,24,2,1,65535,25,32,1,65535,26,2,1,65535,27,32,1,65535,28,33,5,65535,4294967295,34,5,65535,29,35,1,65535,30,36,1,65535,31,37,1,65535,4294967295,38,1,65535,32,2,1,65535,33,2,1,65535,34,39,1,65535,35,39,1,65535,36,40,6,65535,4294967295,41,6,65535,37,42,1,65535,38,43,1,65535,39,2,1,65535,40,44,1,65535,41,2,1,65535,42,45,1,65535,43,45,1,65535,44,65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2105221636,0,0,0,0,0,0,0,2105221636,0,0,0,0,0,0,261,8738,0,0,2105221636,0,0,0,0,0,261,8738,0,0,2105221636,0,0,0,0,0,0,0,261,8738,0,0,2105221636,0,0,0,0,0,0,261,8738,0,46,65537,65537,65537,65537,65537,131071,4294901761,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65538,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65539,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,262145,327681,65537,65537,65537,65537,65537,65537,131071,4294901761,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,131071,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,131071,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,65537,4294901761,4294901761,65537,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901766,4294967295,458751,4294967295,4294967295,4294967295,4294967295,4294901766,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,524287,4294967295,4294967295,4294967295,4294901766,4294967295,458751,4294901766,4294967295,4294901766,4294967295,4294967295,4294967295,4294901766,4294967295,4294901766,524294,4294901766,4294901769,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,720895,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,786431,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,786444,786444,786444,786444,786444,4294967295,4294967295,4294967295,851967,786444,786444,4294901772,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,851967,786444,786444,4294901772,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,851981,851981,851981,851981,851981,4294967295,4294967295,4294967295,917503,851981,851981,4294901773,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,917503,851981,851981,4294901773,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,917518,917518,917518,917518,917518,4294967295,4294967295,4294967295,983039,917518,917518,4294901774,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,983039,917518,917518,4294901774,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,983055,983055,983055,983055,983055,4294967295,4294967295,4294967295,1048575,983055,983055,4294901775,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1048575,983055,983055,4294901775,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1048592,1048592,1048592,1048592,1048592,4294967295,4294967295,4294967295,1114111,1048592,1048592,4294901776,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1114111,1048592,1048592,4294901776,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1114129,1114129,1114129,1114129,1114129,4294967295,4294967295,4294967295,1179647,1114129,1114129,4294901777,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1179647,1114129,1114129,4294901777,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1179666,1179666,1179666,1179666,1179666,4294967295,4294967295,4294967295,1245183,1179666,1179666,4294901778,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1245183,1179666,1179666,4294901778,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1245203,1245203,1245203,1245203,1245203,4294967295,4294967295,4294967295,1310719,1245203,1245203,4294901779,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1310719,1245203,1245203,4294901779,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1310740,1310740,1310740,1310740,1310740,4294967295,4294967295,4294967295,1376255,1310740,1310740,4294901780,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1376255,1310740,1310740,4294901780,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,524296,524296,524296,524296,524296,4294967295,4294967295,4294967295,589823,524296,524296,4294901768,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,589823,524296,524296,4294901768,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,393222,393222,393222,393222,393222,4294967295,4294967295,4294967295,458751,393222,393222,4294901766,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,458751,393222,393222,4294901766,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441815,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1572886,1638422,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1507327,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,1441814,4294901782,4294901782,1441814,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901786,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1835007,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,1900543,4294967295,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966111,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,2097182,2162718,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,2031615,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,1966110,4294901790,4294901790,1966110,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901794,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2359295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2424831,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901797,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555944,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2687015,2752551,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2621439,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,2555943,4294901799,4294901799,2555943,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901803,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2949119,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901805,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080240,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3211311,3276847,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3145727,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,3080239,4294901807,4294901807,3080239,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901811,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3473407,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3538943,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901814,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901815,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735610,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3866681,3932217,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3801087,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,3735609,4294901817,4294901817,3735609,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901821,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4128767,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901823,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901824,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7,3,128,132,1,134,8231,1,8234,1114111,1,0,1,128,1114111,22,1,128,1114111,30,1,128,1114111,39,1,128,1114111,47,1,128,1114111,57,45,224,0,0,226,0,2,31,226,0,22,226,0,225,0,3,29,225,0,25,225,0,30,225,0,223,0,1,28,223,0,221,0,1,28,221,0,222,0,1,28,222,0,223,0,1,28,223,0,223,0,1,28,223,0,223,0,1,28,223,0,230,0,1,28,230,0,232,0,2,31,232,0,22,232,0,231,0,3,32,231,0,25,231,0,30,231,0,229,0,1,28,229,0,227,0,1,28,227,0,228,0,1,28,228,0,237,0,1,28,237,0,236,0,1,28,236,0,238,0,3,34,238,0,25,238,0,30,238,0,236,0,1,28,236,0,233,0,1,28,233,0,234,0,1,28,234,0,235,0,2,33,235,0,22,235,0,242,0,1,28,242,0,241,0,1,28,241,0,243,0,1,28,243,0,244,0,1,28,244,0,241,0,1,28,241,0,239,0,3,35,239,0,25,239,0,30,239,0,240,0,2,33,240,0,22,240,0,252,0,1,28,252,0,251,0,1,28,251,0,253,0,3,38,253,0,25,253,0,30,253,0,251,0,1,28,251,0,248,0,1,28,248,0,249,0,1,28,249,0,251,0,1,28,251,0,250,0,2,33,250,0,22,250,0,257,0,1,28,257,0,256,0,1,28,256,0,258,0,1,28,258,0,259,0,1,28,259,0,256,0,1,28,256,0,254,0,3,39,254,0,25,254,0,30,254,0,256,0,1,28,256,0,255,0,2,33,255,0,22,255,0,65,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,0]; - -static LEXER_DFA_CELL: OnceLock = OnceLock::new(); - -/// Ahead-of-time lexer DFA tables compiled by antlr4-rust-gen, embedded so -/// runtime startup only deserializes them. Rebuilt from the ATN instead when -/// the embedded stream comes from a different runtime version. -fn lexer_dfa() -> &'static CompiledLexerDfa { - LEXER_DFA_CELL.get_or_init(|| { - CompiledLexerDfa::from_serialized(LEXER_DFA_DATA) - .unwrap_or_else(|| CompiledLexerDfa::compile(atn())) - }) -} - -fn lexer_semantics() -> &'static antlr4_runtime::LexerSemantics { - static SEMANTICS_CELL: OnceLock = OnceLock::new(); - SEMANTICS_CELL.get_or_init(|| { - let mut ir = antlr4_runtime::semir::SemIr::new(); - let mut predicates = Vec::new(); - let mut actions = Vec::new(); - let __member_expr_0 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_expr_1 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_0)); - let __member_expr_2 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_1)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 204, pred_index: 0, expr: __member_expr_2 }); - let __member_expr_3 = ir.expr(antlr4_runtime::semir::PExpr::MemberLen(0)); - let __member_expr_4 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_3)); - let __member_expr_5 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_4)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 205, pred_index: 1, expr: __member_expr_5 }); - let __member_expr_6 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_expr_7 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_6)); - let __member_expr_8 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_7)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 206, pred_index: 2, expr: __member_expr_8 }); - let __member_expr_9 = ir.expr(antlr4_runtime::semir::PExpr::MemberLen(0)); - let __member_expr_10 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_9)); - let __member_expr_11 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_10)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 207, pred_index: 3, expr: __member_expr_11 }); - let __member_expr_12 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_expr_13 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_12)); - let __member_expr_14 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_13)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 208, pred_index: 4, expr: __member_expr_14 }); - let __member_expr_15 = ir.expr(antlr4_runtime::semir::PExpr::MemberTop(1)); - let __member_expr_16 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_15)); - let __member_expr_17 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_16)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 209, pred_index: 5, expr: __member_expr_17 }); - let __member_expr_18 = ir.expr(antlr4_runtime::semir::PExpr::MemberLen(0)); - let __member_expr_19 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_18)); - let __member_expr_20 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_19)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 210, pred_index: 6, expr: __member_expr_20 }); - let __member_expr_21 = ir.expr(antlr4_runtime::semir::PExpr::MemberLen(0)); - let __member_expr_22 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_21)); - let __member_expr_23 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_22)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 211, pred_index: 7, expr: __member_expr_23 }); - let __member_expr_24 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_expr_25 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_24)); - let __member_expr_26 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_25)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 212, pred_index: 8, expr: __member_expr_26 }); - let __member_expr_27 = ir.expr(antlr4_runtime::semir::PExpr::MemberLen(0)); - let __member_expr_28 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_27)); - let __member_expr_29 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_28)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 213, pred_index: 9, expr: __member_expr_29 }); - let __member_expr_30 = ir.expr(antlr4_runtime::semir::PExpr::MemberTop(1)); - let __member_expr_31 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_30)); - let __member_expr_32 = ir.expr(antlr4_runtime::semir::PExpr::Not(__member_expr_31)); - predicates.push(antlr4_runtime::LexerSemanticPredicate { rule_index: 246, pred_index: 10, expr: __member_expr_32 }); - let __member_expr_33 = ir.expr(antlr4_runtime::semir::PExpr::Int(-1)); - let __member_stmt_34 = ir.stmt(antlr4_runtime::semir::AStmt::AddMember(0, __member_expr_33)); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 204, action_index: 0, stmt: __member_stmt_34 }); - let __member_expr_35 = ir.expr(antlr4_runtime::semir::PExpr::Int(1)); - let __member_stmt_36 = ir.stmt(antlr4_runtime::semir::AStmt::AddMember(0, __member_expr_35)); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 205, action_index: 1, stmt: __member_stmt_36 }); - let __member_expr_37 = ir.expr(antlr4_runtime::semir::PExpr::Int(-1)); - let __member_stmt_38 = ir.stmt(antlr4_runtime::semir::AStmt::AddMember(0, __member_expr_37)); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 206, action_index: 2, stmt: __member_stmt_38 }); - let __member_expr_39 = ir.expr(antlr4_runtime::semir::PExpr::Int(1)); - let __member_stmt_40 = ir.stmt(antlr4_runtime::semir::AStmt::AddMember(0, __member_expr_39)); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 207, action_index: 3, stmt: __member_stmt_40 }); - let __member_expr_41 = ir.expr(antlr4_runtime::semir::PExpr::Int(-1)); - let __member_stmt_42 = ir.stmt(antlr4_runtime::semir::AStmt::AddMember(0, __member_expr_41)); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 208, action_index: 4, stmt: __member_stmt_42 }); - let __member_expr_43 = ir.expr(antlr4_runtime::semir::PExpr::MemberTop(0)); - let __member_stmt_44 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_43)); - let __member_stmt_45 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(0)); - let __member_stmt_46 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(1)); - let __member_stmt_47 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_44, __member_stmt_45, __member_stmt_46].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 209, action_index: 5, stmt: __member_stmt_47 }); - let __member_expr_48 = ir.expr(antlr4_runtime::semir::PExpr::MemberTop(0)); - let __member_stmt_49 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_48)); - let __member_stmt_50 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(0)); - let __member_stmt_51 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(1)); - let __member_stmt_52 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_49, __member_stmt_50, __member_stmt_51].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 210, action_index: 6, stmt: __member_stmt_52 }); - let __member_expr_53 = ir.expr(antlr4_runtime::semir::PExpr::Int(1)); - let __member_stmt_54 = ir.stmt(antlr4_runtime::semir::AStmt::AddMember(0, __member_expr_53)); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 211, action_index: 7, stmt: __member_stmt_54 }); - let __member_expr_55 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_stmt_56 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(0, __member_expr_55)); - let __member_expr_57 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_58 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(1, __member_expr_57)); - let __member_expr_59 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_60 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_59)); - let __member_stmt_61 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_56, __member_stmt_58, __member_stmt_60].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 225, action_index: 8, stmt: __member_stmt_61 }); - let __member_expr_62 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_stmt_63 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(0, __member_expr_62)); - let __member_expr_64 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_65 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(1, __member_expr_64)); - let __member_expr_66 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_67 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_66)); - let __member_stmt_68 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_63, __member_stmt_65, __member_stmt_67].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 231, action_index: 9, stmt: __member_stmt_68 }); - let __member_expr_69 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_stmt_70 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(0, __member_expr_69)); - let __member_expr_71 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_72 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(1, __member_expr_71)); - let __member_expr_73 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_74 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_73)); - let __member_stmt_75 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_70, __member_stmt_72, __member_stmt_74].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 238, action_index: 10, stmt: __member_stmt_75 }); - let __member_expr_76 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_stmt_77 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(0, __member_expr_76)); - let __member_expr_78 = ir.expr(antlr4_runtime::semir::PExpr::Int(1)); - let __member_stmt_79 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(1, __member_expr_78)); - let __member_expr_80 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_81 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_80)); - let __member_stmt_82 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_77, __member_stmt_79, __member_stmt_81].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 239, action_index: 11, stmt: __member_stmt_82 }); - let __member_expr_83 = ir.expr(antlr4_runtime::semir::PExpr::MemberTop(0)); - let __member_stmt_84 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_83)); - let __member_stmt_85 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(0)); - let __member_stmt_86 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(1)); - let __member_stmt_87 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_84, __member_stmt_85, __member_stmt_86].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 246, action_index: 12, stmt: __member_stmt_87 }); - let __member_expr_88 = ir.expr(antlr4_runtime::semir::PExpr::MemberTop(0)); - let __member_stmt_89 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_88)); - let __member_stmt_90 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(0)); - let __member_stmt_91 = ir.stmt(antlr4_runtime::semir::AStmt::PopMember(1)); - let __member_stmt_92 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_89, __member_stmt_90, __member_stmt_91].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 247, action_index: 13, stmt: __member_stmt_92 }); - let __member_expr_93 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_stmt_94 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(0, __member_expr_93)); - let __member_expr_95 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_96 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(1, __member_expr_95)); - let __member_expr_97 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_98 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_97)); - let __member_stmt_99 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_94, __member_stmt_96, __member_stmt_98].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 253, action_index: 14, stmt: __member_stmt_99 }); - let __member_expr_100 = ir.expr(antlr4_runtime::semir::PExpr::Member(0)); - let __member_stmt_101 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(0, __member_expr_100)); - let __member_expr_102 = ir.expr(antlr4_runtime::semir::PExpr::Int(1)); - let __member_stmt_103 = ir.stmt(antlr4_runtime::semir::AStmt::PushMember(1, __member_expr_102)); - let __member_expr_104 = ir.expr(antlr4_runtime::semir::PExpr::Int(0)); - let __member_stmt_105 = ir.stmt(antlr4_runtime::semir::AStmt::SetMember(0, __member_expr_104)); - let __member_stmt_106 = ir.stmt(antlr4_runtime::semir::AStmt::Seq([__member_stmt_101, __member_stmt_103, __member_stmt_105].into())); - actions.push(antlr4_runtime::LexerSemanticAction { rule_index: 254, action_index: 15, stmt: __member_stmt_106 }); - antlr4_runtime::LexerSemantics { ir, predicates, actions } - }) -} - -#[derive(Clone, Debug)] -pub struct CSharpLexer -where - I: CharStream, - H: antlr4_runtime::SemanticHooks, -{ - base: BaseLexer, - hooks: H, -} - -impl CSharpLexer -where - I: CharStream, -{ - pub fn new(input: I) -> Self { - Self::with_hooks(input, antlr4_runtime::NoSemanticHooks) - } -} - -impl CSharpLexer -where - I: CharStream, - H: antlr4_runtime::SemanticHooks, -{ - pub fn with_hooks(input: I, hooks: H) -> Self { - let grammar_metadata = metadata(); - let data = grammar_metadata.recognizer_data(); - Self { base: BaseLexer::new(input, data).with_shared_dfa(atn()), hooks } - } - - fn run_action(_base: &mut BaseLexer, action: antlr4_runtime::LexerCustomAction) -> bool { - match (action.rule_index(), action.action_index()) { - (204, 0) => { let _ = lexer_semantics().exec_action(_base, action); true } - (205, 1) => { let _ = lexer_semantics().exec_action(_base, action); true } - (206, 2) => { let _ = lexer_semantics().exec_action(_base, action); true } - (207, 3) => { let _ = lexer_semantics().exec_action(_base, action); true } - (208, 4) => { let _ = lexer_semantics().exec_action(_base, action); true } - (209, 5) => { let _ = lexer_semantics().exec_action(_base, action); true } - (210, 6) => { let _ = lexer_semantics().exec_action(_base, action); true } - (211, 7) => { let _ = lexer_semantics().exec_action(_base, action); true } - (225, 8) => { let _ = lexer_semantics().exec_action(_base, action); true } - (231, 9) => { let _ = lexer_semantics().exec_action(_base, action); true } - (238, 10) => { let _ = lexer_semantics().exec_action(_base, action); true } - (239, 11) => { let _ = lexer_semantics().exec_action(_base, action); true } - (246, 12) => { let _ = lexer_semantics().exec_action(_base, action); true } - (247, 13) => { let _ = lexer_semantics().exec_action(_base, action); true } - (253, 14) => { let _ = lexer_semantics().exec_action(_base, action); true } - (254, 15) => { let _ = lexer_semantics().exec_action(_base, action); true } - _ => false, - } - } - - fn run_predicate(_base: &BaseLexer, predicate: antlr4_runtime::LexerPredicate) -> Option { - match (predicate.rule_index(), predicate.pred_index()) { - (204, 0) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (205, 1) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (206, 2) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (207, 3) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (208, 4) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (209, 5) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (210, 6) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (211, 7) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (212, 8) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (213, 9) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - (246, 10) => { Some(lexer_semantics().eval_predicate(_base, predicate).unwrap_or(false)) } - _ => Some(true), - } - } - -} - - - -antlr4_runtime::__antlr4_rust_lexer_facade! { - type: CSharpLexer, - fields: { - base: base, - hooks: hooks, - }, - metadata: metadata, - next_token(lexer, sink) { - if H::ENABLES_LEXER_LIFECYCLE { - antlr4_runtime::atn::lexer::next_token_compiled_with_semantic_dispatch(&mut lexer.base, sink, atn(), lexer_dfa(), &mut lexer.hooks, Self::run_action, Self::run_predicate, antlr4_runtime::UnknownSemanticPolicy::Error, |_, _, _| {}) - } else { - antlr4_runtime::atn::lexer::next_token_compiled_with_hooks(&mut lexer.base, sink, atn(), lexer_dfa(), |base, action| { let _ = Self::run_action(base, action); }, |base, predicate| Self::run_predicate(base, predicate).unwrap_or(true), |_, _, _| {}) - } - } -} -} - -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -pub use self::__antlr4_rust_generated::*; diff --git a/crates/mehen-csharp-parser/src/generated/c_sharp_parser.rs b/crates/mehen-csharp-parser/src/generated/c_sharp_parser.rs deleted file mode 100644 index 0357da3a..00000000 --- a/crates/mehen-csharp-parser/src/generated/c_sharp_parser.rs +++ /dev/null @@ -1,27137 +0,0 @@ -// @generated by antlr-rust-codegen v0.33.1 - do not edit -// project: https://github.com/ophi-dev/antlr-rust-runtime -antlr4_runtime::__antlr4_rust_require_codegen_api!(14, "0.33.1"); -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -#[rustfmt::skip] -mod __antlr4_rust_generated { - -use antlr4_runtime::token::TokenSource; -use antlr4_runtime::token_stream::CommonTokenStream; -use antlr4_runtime::atn::parser_atn::ParserAtn; -use antlr4_runtime::generated::GeneratedRuleError; -use antlr4_runtime::{BaseParser, GrammarMetadata, Parser, Recognizer}; -use std::sync::OnceLock; -#[allow(unused_imports)] -use std::io::Write as _; -#[allow(unused_imports)] -use antlr4_runtime::{java_style_list, PredictionMode, BailErrorStrategy, TerminalNodeView as RuntimeTerminalNode, ErrorNodeView as RuntimeErrorNode, RuleNodeView, AsRuleNode, FromRuleNode, MissingChildError, Token as _}; -pub use antlr4_runtime::generated::{ErrorNode, StoredTreeContext, TerminalNode, __GeneratedInput, __GeneratedTokenView}; -#[allow(unused_imports)] -use antlr4_runtime::generated::{__ActiveParserContext, __FromActiveRuleContext, __GeneratedRuleContext, __RecoveryContextState, __active_context_view, __active_context_view_with_attrs, __context_children, __labeled_token_children, __labeled_token_children_matching, __rule_children, __terminal_children, __token_children, __token_children_matching, __write_invocation_states}; - - -pub const EOF: i32 = antlr4_runtime::TOKEN_EOF; -pub const INTERPOLATED_TEXT: i32 = 1; -pub const XML_TEXT_LIT: i32 = 2; -pub const KW_REFVALUE: i32 = 3; -pub const KW_DESCENDING: i32 = 4; -pub const KW_STACKALLOC: i32 = 5; -pub const KW_ARGLIST: i32 = 6; -pub const KW_MAKEREF: i32 = 7; -pub const KW_REFTYPE: i32 = 8; -pub const KW_ASCENDING: i32 = 9; -pub const KW_EXTENSION: i32 = 10; -pub const KW_INTERFACE: i32 = 11; -pub const KW_NAMESPACE: i32 = 12; -pub const KW_PROTECTED: i32 = 13; -pub const KW_UNCHECKED: i32 = 14; -pub const KW_UNMANAGED: i32 = 15; -pub const KW_ABSTRACT: i32 = 16; -pub const KW_CONTINUE: i32 = 17; -pub const KW_DELEGATE: i32 = 18; -pub const KW_EXPLICIT: i32 = 19; -pub const KW_IMPLICIT: i32 = 20; -pub const KW_INTERNAL: i32 = 21; -pub const KW_OPERATOR: i32 = 22; -pub const KW_OVERRIDE: i32 = 23; -pub const KW_READONLY: i32 = 24; -pub const KW_REQUIRED: i32 = 25; -pub const KW_VOLATILE: i32 = 26; -pub const KW_CHECKED: i32 = 27; -pub const KW_DECIMAL: i32 = 28; -pub const KW_DEFAULT: i32 = 29; -pub const KW_FINALLY: i32 = 30; -pub const KW_FOREACH: i32 = 31; -pub const KW_MANAGED: i32 = 32; -pub const KW_ORDERBY: i32 = 33; -pub const KW_PARTIAL: i32 = 34; -pub const KW_PRIVATE: i32 = 35; -pub const KW_VIRTUAL: i32 = 36; -pub const KW_ALLOWS: i32 = 37; -pub const KW_CLOSED: i32 = 38; -pub const KW_DOUBLE: i32 = 39; -pub const KW_EQUALS: i32 = 40; -pub const KW_EXTERN: i32 = 41; -pub const KW_GLOBAL: i32 = 42; -pub const KW_OBJECT: i32 = 43; -pub const KW_PARAMS: i32 = 44; -pub const KW_PUBLIC: i32 = 45; -pub const KW_REMOVE: i32 = 46; -pub const KW_RETURN: i32 = 47; -pub const KW_SCOPED: i32 = 48; -pub const KW_SEALED: i32 = 49; -pub const KW_SELECT: i32 = 50; -pub const KW_SIZEOF: i32 = 51; -pub const KW_STATIC: i32 = 52; -pub const KW_STRING: i32 = 53; -pub const KW_STRUCT: i32 = 54; -pub const KW_SWITCH: i32 = 55; -pub const KW_TYPEOF: i32 = 56; -pub const KW_UNSAFE: i32 = 57; -pub const KW_USHORT: i32 = 58; -pub const KW_ALIAS: i32 = 59; -pub const KW_ASYNC: i32 = 60; -pub const KW_AWAIT: i32 = 61; -pub const KW_BREAK: i32 = 62; -pub const KW_CATCH: i32 = 63; -pub const KW_CLASS: i32 = 64; -pub const KW_CONST: i32 = 65; -pub const KW_EVENT: i32 = 66; -pub const KW_FALSE: i32 = 67; -pub const KW_FIELD: i32 = 68; -pub const KW_FIXED: i32 = 69; -pub const KW_FLOAT: i32 = 70; -pub const KW_GROUP: i32 = 71; -pub const KW_SBYTE: i32 = 72; -pub const KW_SHORT: i32 = 73; -pub const KW_THROW: i32 = 74; -pub const KW_ULONG: i32 = 75; -pub const KW_UNION: i32 = 76; -pub const KW_USING: i32 = 77; -pub const KW_WHERE: i32 = 78; -pub const KW_WHILE: i32 = 79; -pub const KW_YIELD: i32 = 80; -pub const KW_BASE: i32 = 81; -pub const KW_BOOL: i32 = 82; -pub const KW_BYTE: i32 = 83; -pub const KW_CASE: i32 = 84; -pub const KW_CHAR: i32 = 85; -pub const KW_ELSE: i32 = 86; -pub const KW_ENUM: i32 = 87; -pub const KW_FILE: i32 = 88; -pub const KW_FROM: i32 = 89; -pub const KW_GOTO: i32 = 90; -pub const KW_INIT: i32 = 91; -pub const KW_INTO: i32 = 92; -pub const KW_JOIN: i32 = 93; -pub const KW_LOCK: i32 = 94; -pub const KW_LONG: i32 = 95; -pub const KW_NULL: i32 = 96; -pub const KW_SAFE: i32 = 97; -pub const KW_THIS: i32 = 98; -pub const KW_TRUE: i32 = 99; -pub const KW_UINT: i32 = 100; -pub const KW_VOID: i32 = 101; -pub const KW_WHEN: i32 = 102; -pub const KW_WITH: i32 = 103; -pub const TRIPLE_DQUOTE: i32 = 104; -pub const LT_LT_EQ: i32 = 105; -pub const QUESTION_QUESTION_EQ: i32 = 106; -pub const KW_ADD: i32 = 107; -pub const KW_AND: i32 = 108; -pub const KW_FOR: i32 = 109; -pub const KW_GET: i32 = 110; -pub const KW_INT: i32 = 111; -pub const KW_LET: i32 = 112; -pub const KW_NEW: i32 = 113; -pub const KW_NOT: i32 = 114; -pub const KW_OUT: i32 = 115; -pub const KW_REF: i32 = 116; -pub const KW_SET: i32 = 117; -pub const KW_TRY: i32 = 118; -pub const KW_VAR: i32 = 119; -pub const NE: i32 = 120; -pub const PERCENT_EQ: i32 = 121; -pub const AMP_AMP: i32 = 122; -pub const AMP_EQ: i32 = 123; -pub const STAR_EQ: i32 = 124; -pub const PLUS_PLUS: i32 = 125; -pub const PLUS_EQ: i32 = 126; -pub const MINUS_MINUS: i32 = 127; -pub const MINUS_EQ: i32 = 128; -pub const MINUS_GT: i32 = 129; -pub const DOT_DOT: i32 = 130; -pub const SLASH_EQ: i32 = 131; -pub const SLASH_GT: i32 = 132; -pub const COLON_COLON: i32 = 133; -pub const LT_SLASH: i32 = 134; -pub const LT_LT: i32 = 135; -pub const LE: i32 = 136; -pub const EQ_EQ: i32 = 137; -pub const ARROW: i32 = 138; -pub const GE: i32 = 139; -pub const QUESTION_QUESTION: i32 = 140; -pub const KW_U8: i32 = 141; -pub const ESCAPED_QUOTE: i32 = 142; -pub const ESCAPED_BACKSLASH: i32 = 143; -pub const CARET_EQ: i32 = 144; -pub const KW_AS: i32 = 145; -pub const KW_BY: i32 = 146; -pub const KW_DO: i32 = 147; -pub const KW_IF: i32 = 148; -pub const KW_IN: i32 = 149; -pub const KW_IS: i32 = 150; -pub const KW_ON: i32 = 151; -pub const KW_OR: i32 = 152; -pub const KW_U8_LOWER: i32 = 153; -pub const PIPE_EQ: i32 = 154; -pub const PIPE_PIPE: i32 = 155; -pub const BANG: i32 = 156; -pub const DQUOTE: i32 = 157; -pub const HASH: i32 = 158; -pub const PERCENT: i32 = 159; -pub const AMP: i32 = 160; -pub const STAR: i32 = 161; -pub const PLUS: i32 = 162; -pub const COMMA: i32 = 163; -pub const MINUS: i32 = 164; -pub const DOT: i32 = 165; -pub const SLASH: i32 = 166; -pub const SEMICOLON: i32 = 167; -pub const LT: i32 = 168; -pub const EQ: i32 = 169; -pub const GT: i32 = 170; -pub const QUESTION: i32 = 171; -pub const CARET: i32 = 172; -pub const KW: i32 = 173; -pub const PIPE: i32 = 174; -pub const TILDE: i32 = 175; -pub const KW_RECORD: i32 = 176; -pub const IDENTIFIER: i32 = 177; -pub const DEC_INT_LIT: i32 = 178; -pub const HEX_INT_LIT: i32 = 179; -pub const BIN_INT_LIT: i32 = 180; -pub const REAL_LIT: i32 = 181; -pub const CHAR_LIT: i32 = 182; -pub const STRING_LIT: i32 = 183; -pub const VERBATIM_STRING_LIT: i32 = 184; -pub const SL_RAW_STRING_LIT: i32 = 185; -pub const ML_RAW_STRING_LIT: i32 = 186; -pub const SINGLE_LINE_DOC_COMMENT: i32 = 187; -pub const DELIMITED_DOC_COMMENT: i32 = 188; -pub const SINGLE_LINE_COMMENT: i32 = 189; -pub const DELIMITED_COMMENT: i32 = 190; -pub const WHITESPACES: i32 = 191; -pub const BYTE_ORDER_MARK: i32 = 192; -pub const DIRECTIVE_LINE: i32 = 193; -pub const INTERP_START: i32 = 194; -pub const INTERP_VERBATIM_START: i32 = 195; -pub const INTERP_RAW_START: i32 = 196; -pub const LBRACE: i32 = 197; -pub const RBRACE: i32 = 198; -pub const COLON: i32 = 199; -pub const LPAREN: i32 = 200; -pub const RPAREN: i32 = 201; -pub const LBRACKET: i32 = 202; -pub const RBRACKET: i32 = 203; -pub const INTERP_ESCAPED_OPEN: i32 = 204; -pub const INTERP_ESCAPED_CLOSE: i32 = 205; -pub const INTERP_V_ESCAPED_QUOTE: i32 = 206; - -pub const RULE_COMPILATION_UNIT: usize = 0; -pub const RULE_EXTERN_ALIAS_DIRECTIVE: usize = 1; -pub const RULE_USING_DIRECTIVE: usize = 2; -pub const RULE_NAME_EQUALS: usize = 3; -pub const RULE_IDENTIFIER_NAME: usize = 4; -pub const RULE_ATTRIBUTE_LIST: usize = 5; -pub const RULE_ATTRIBUTE_TARGET_SPECIFIER: usize = 6; -pub const RULE_ATTRIBUTE: usize = 7; -pub const RULE_NAME: usize = 8; -pub const RULE_ALIAS_QUALIFIED_NAME: usize = 9; -pub const RULE_SIMPLE_NAME: usize = 10; -pub const RULE_GENERIC_NAME: usize = 11; -pub const RULE_TYPE_ARGUMENT_LIST: usize = 12; -pub const RULE_ATTRIBUTE_ARGUMENT_LIST: usize = 13; -pub const RULE_ATTRIBUTE_ARGUMENT: usize = 14; -pub const RULE_NAME_COLON: usize = 15; -pub const RULE_MEMBER_DECLARATION: usize = 16; -pub const RULE_BASE_FIELD_DECLARATION: usize = 17; -pub const RULE_EVENT_FIELD_DECLARATION: usize = 18; -pub const RULE_MODIFIER: usize = 19; -pub const RULE_VARIABLE_DECLARATION: usize = 20; -pub const RULE_VARIABLE_DECLARATOR: usize = 21; -pub const RULE_BRACKETED_ARGUMENT_LIST: usize = 22; -pub const RULE_ARGUMENT: usize = 23; -pub const RULE_EQUALS_VALUE_CLAUSE: usize = 24; -pub const RULE_FIELD_DECLARATION: usize = 25; -pub const RULE_BASE_METHOD_DECLARATION: usize = 26; -pub const RULE_CONSTRUCTOR_DECLARATION: usize = 27; -pub const RULE_PARAMETER_LIST: usize = 28; -pub const RULE_PARAMETER: usize = 29; -pub const RULE_CONSTRUCTOR_INITIALIZER: usize = 30; -pub const RULE_ARGUMENT_LIST: usize = 31; -pub const RULE_BLOCK: usize = 32; -pub const RULE_ARROW_EXPRESSION_CLAUSE: usize = 33; -pub const RULE_CONVERSION_OPERATOR_DECLARATION: usize = 34; -pub const RULE_EXPLICIT_INTERFACE_SPECIFIER: usize = 35; -pub const RULE_DESTRUCTOR_DECLARATION: usize = 36; -pub const RULE_METHOD_DECLARATION: usize = 37; -pub const RULE_TYPE_PARAMETER_LIST: usize = 38; -pub const RULE_TYPE_PARAMETER: usize = 39; -pub const RULE_TYPE_PARAMETER_CONSTRAINT_CLAUSE: usize = 40; -pub const RULE_TYPE_PARAMETER_CONSTRAINT: usize = 41; -pub const RULE_ALLOWS_CONSTRAINT_CLAUSE: usize = 42; -pub const RULE_ALLOWS_CONSTRAINT: usize = 43; -pub const RULE_REF_STRUCT_CONSTRAINT: usize = 44; -pub const RULE_CLASS_OR_STRUCT_CONSTRAINT: usize = 45; -pub const RULE_CONSTRUCTOR_CONSTRAINT: usize = 46; -pub const RULE_DEFAULT_CONSTRAINT: usize = 47; -pub const RULE_TYPE_CONSTRAINT: usize = 48; -pub const RULE_OPERATOR_DECLARATION: usize = 49; -pub const RULE_BASE_NAMESPACE_DECLARATION: usize = 50; -pub const RULE_FILE_SCOPED_NAMESPACE_DECLARATION: usize = 51; -pub const RULE_NAMESPACE_DECLARATION: usize = 52; -pub const RULE_BASE_PROPERTY_DECLARATION: usize = 53; -pub const RULE_EVENT_DECLARATION: usize = 54; -pub const RULE_ACCESSOR_LIST: usize = 55; -pub const RULE_ACCESSOR_DECLARATION: usize = 56; -pub const RULE_INDEXER_DECLARATION: usize = 57; -pub const RULE_BRACKETED_PARAMETER_LIST: usize = 58; -pub const RULE_PROPERTY_DECLARATION: usize = 59; -pub const RULE_BASE_TYPE_DECLARATION: usize = 60; -pub const RULE_ENUM_DECLARATION: usize = 61; -pub const RULE_BASE_LIST: usize = 62; -pub const RULE_BASE_TYPE: usize = 63; -pub const RULE_PRIMARY_CONSTRUCTOR_BASE_TYPE: usize = 64; -pub const RULE_SIMPLE_BASE_TYPE: usize = 65; -pub const RULE_ENUM_MEMBER_DECLARATION: usize = 66; -pub const RULE_TYPE_DECLARATION: usize = 67; -pub const RULE_CLASS_DECLARATION: usize = 68; -pub const RULE_EXTENSION_BLOCK_DECLARATION: usize = 69; -pub const RULE_INTERFACE_DECLARATION: usize = 70; -pub const RULE_RECORD_DECLARATION: usize = 71; -pub const RULE_STRUCT_DECLARATION: usize = 72; -pub const RULE_UNION_DECLARATION: usize = 73; -pub const RULE_DELEGATE_DECLARATION: usize = 74; -pub const RULE_GLOBAL_STATEMENT: usize = 75; -pub const RULE_TYPE: usize = 76; -pub const RULE_ARRAY_TYPE: usize = 77; -pub const RULE_ARRAY_RANK_SPECIFIER: usize = 78; -pub const RULE_FUNCTION_POINTER_TYPE: usize = 79; -pub const RULE_FUNCTION_POINTER_CALLING_CONVENTION: usize = 80; -pub const RULE_FUNCTION_POINTER_UNMANAGED_CALLING_CONVENTION_LIST: usize = 81; -pub const RULE_FUNCTION_POINTER_UNMANAGED_CALLING_CONVENTION: usize = 82; -pub const RULE_FUNCTION_POINTER_PARAMETER_LIST: usize = 83; -pub const RULE_FUNCTION_POINTER_PARAMETER: usize = 84; -pub const RULE_PREDEFINED_TYPE: usize = 85; -pub const RULE_REF_TYPE: usize = 86; -pub const RULE_SCOPED_TYPE: usize = 87; -pub const RULE_TUPLE_TYPE: usize = 88; -pub const RULE_TUPLE_ELEMENT: usize = 89; -pub const RULE_STATEMENT: usize = 90; -pub const RULE_BREAK_STATEMENT: usize = 91; -pub const RULE_CHECKED_STATEMENT: usize = 92; -pub const RULE_COMMON_FOR_EACH_STATEMENT: usize = 93; -pub const RULE_FOR_EACH_STATEMENT: usize = 94; -pub const RULE_FOR_EACH_VARIABLE_STATEMENT: usize = 95; -pub const RULE_CONTINUE_STATEMENT: usize = 96; -pub const RULE_DO_STATEMENT: usize = 97; -pub const RULE_EMPTY_STATEMENT: usize = 98; -pub const RULE_EXPRESSION_STATEMENT: usize = 99; -pub const RULE_FIXED_STATEMENT: usize = 100; -pub const RULE_FOR_STATEMENT: usize = 101; -pub const RULE_GOTO_STATEMENT: usize = 102; -pub const RULE_IF_STATEMENT: usize = 103; -pub const RULE_ELSE_CLAUSE: usize = 104; -pub const RULE_LABELED_STATEMENT: usize = 105; -pub const RULE_LOCAL_DECLARATION_STATEMENT: usize = 106; -pub const RULE_LOCAL_FUNCTION_STATEMENT: usize = 107; -pub const RULE_LOCK_STATEMENT: usize = 108; -pub const RULE_RETURN_STATEMENT: usize = 109; -pub const RULE_SWITCH_STATEMENT: usize = 110; -pub const RULE_SWITCH_SECTION: usize = 111; -pub const RULE_SWITCH_LABEL: usize = 112; -pub const RULE_CASE_PATTERN_SWITCH_LABEL: usize = 113; -pub const RULE_PATTERN: usize = 114; -pub const RULE_CONSTANT_PATTERN: usize = 115; -pub const RULE_DECLARATION_PATTERN: usize = 116; -pub const RULE_VARIABLE_DESIGNATION: usize = 117; -pub const RULE_DISCARD_DESIGNATION: usize = 118; -pub const RULE_PARENTHESIZED_VARIABLE_DESIGNATION: usize = 119; -pub const RULE_SINGLE_VARIABLE_DESIGNATION: usize = 120; -pub const RULE_DISCARD_PATTERN: usize = 121; -pub const RULE_LIST_PATTERN: usize = 122; -pub const RULE_PARENTHESIZED_PATTERN: usize = 123; -pub const RULE_RECURSIVE_PATTERN: usize = 124; -pub const RULE_POSITIONAL_PATTERN_CLAUSE: usize = 125; -pub const RULE_SUBPATTERN: usize = 126; -pub const RULE_BASE_EXPRESSION_COLON: usize = 127; -pub const RULE_EXPRESSION_COLON: usize = 128; -pub const RULE_PROPERTY_PATTERN_CLAUSE: usize = 129; -pub const RULE_RELATIONAL_PATTERN: usize = 130; -pub const RULE_SLICE_PATTERN: usize = 131; -pub const RULE_TYPE_PATTERN: usize = 132; -pub const RULE_UNARY_PATTERN: usize = 133; -pub const RULE_VAR_PATTERN: usize = 134; -pub const RULE_WHEN_CLAUSE: usize = 135; -pub const RULE_CASE_SWITCH_LABEL: usize = 136; -pub const RULE_DEFAULT_SWITCH_LABEL: usize = 137; -pub const RULE_THROW_STATEMENT: usize = 138; -pub const RULE_TRY_STATEMENT: usize = 139; -pub const RULE_CATCH_CLAUSE: usize = 140; -pub const RULE_CATCH_DECLARATION: usize = 141; -pub const RULE_CATCH_FILTER_CLAUSE: usize = 142; -pub const RULE_FINALLY_CLAUSE: usize = 143; -pub const RULE_UNSAFE_STATEMENT: usize = 144; -pub const RULE_USING_STATEMENT: usize = 145; -pub const RULE_WHILE_STATEMENT: usize = 146; -pub const RULE_YIELD_STATEMENT: usize = 147; -pub const RULE_EXPRESSION: usize = 148; -pub const RULE_ANONYMOUS_FUNCTION_EXPRESSION: usize = 149; -pub const RULE_ANONYMOUS_METHOD_EXPRESSION: usize = 150; -pub const RULE_LAMBDA_EXPRESSION: usize = 151; -pub const RULE_PARENTHESIZED_LAMBDA_EXPRESSION: usize = 152; -pub const RULE_SIMPLE_LAMBDA_EXPRESSION: usize = 153; -pub const RULE_ANONYMOUS_OBJECT_CREATION_EXPRESSION: usize = 154; -pub const RULE_ANONYMOUS_OBJECT_MEMBER_DECLARATOR: usize = 155; -pub const RULE_ARRAY_CREATION_EXPRESSION: usize = 156; -pub const RULE_INITIALIZER_EXPRESSION: usize = 157; -pub const RULE_AWAIT_EXPRESSION: usize = 158; -pub const RULE_BASE_OBJECT_CREATION_EXPRESSION: usize = 159; -pub const RULE_IMPLICIT_OBJECT_CREATION_EXPRESSION: usize = 160; -pub const RULE_OBJECT_CREATION_EXPRESSION: usize = 161; -pub const RULE_CAST_EXPRESSION: usize = 162; -pub const RULE_CHECKED_EXPRESSION: usize = 163; -pub const RULE_COLLECTION_EXPRESSION: usize = 164; -pub const RULE_COLLECTION_ELEMENT: usize = 165; -pub const RULE_EXPRESSION_ELEMENT: usize = 166; -pub const RULE_SPREAD_ELEMENT: usize = 167; -pub const RULE_WITH_ELEMENT: usize = 168; -pub const RULE_DECLARATION_EXPRESSION: usize = 169; -pub const RULE_DEFAULT_EXPRESSION: usize = 170; -pub const RULE_ELEMENT_BINDING_EXPRESSION: usize = 171; -pub const RULE_FIELD_EXPRESSION: usize = 172; -pub const RULE_IMPLICIT_ARRAY_CREATION_EXPRESSION: usize = 173; -pub const RULE_IMPLICIT_ELEMENT_ACCESS: usize = 174; -pub const RULE_IMPLICIT_STACK_ALLOC_ARRAY_CREATION_EXPRESSION: usize = 175; -pub const RULE_INSTANCE_EXPRESSION: usize = 176; -pub const RULE_BASE_EXPRESSION: usize = 177; -pub const RULE_THIS_EXPRESSION: usize = 178; -pub const RULE_INTERPOLATED_STRING_EXPRESSION: usize = 179; -pub const RULE_INTERPOLATED_STRING_CONTENT: usize = 180; -pub const RULE_INTERPOLATED_STRING_TEXT: usize = 181; -pub const RULE_INTERPOLATION: usize = 182; -pub const RULE_INTERPOLATION_ALIGNMENT_CLAUSE: usize = 183; -pub const RULE_INTERPOLATION_FORMAT_CLAUSE: usize = 184; -pub const RULE_INTERPOLATED_MULTI_LINE_RAW_STRING_START_TOKEN: usize = 185; -pub const RULE_INTERPOLATED_RAW_STRING_END_TOKEN: usize = 186; -pub const RULE_INTERPOLATED_SINGLE_LINE_RAW_STRING_START_TOKEN: usize = 187; -pub const RULE_LITERAL_EXPRESSION: usize = 188; -pub const RULE_UTF8_MULTI_LINE_RAW_STRING_LITERAL_TOKEN: usize = 189; -pub const RULE_UTF8_SINGLE_LINE_RAW_STRING_LITERAL_TOKEN: usize = 190; -pub const RULE_UTF8_STRING_LITERAL_TOKEN: usize = 191; -pub const RULE_MAKE_REF_EXPRESSION: usize = 192; -pub const RULE_MEMBER_BINDING_EXPRESSION: usize = 193; -pub const RULE_PARENTHESIZED_EXPRESSION: usize = 194; -pub const RULE_PREFIX_UNARY_EXPRESSION: usize = 195; -pub const RULE_QUERY_EXPRESSION: usize = 196; -pub const RULE_FROM_CLAUSE: usize = 197; -pub const RULE_QUERY_BODY: usize = 198; -pub const RULE_QUERY_CLAUSE: usize = 199; -pub const RULE_JOIN_CLAUSE: usize = 200; -pub const RULE_JOIN_INTO_CLAUSE: usize = 201; -pub const RULE_LET_CLAUSE: usize = 202; -pub const RULE_ORDER_BY_CLAUSE: usize = 203; -pub const RULE_ORDERING: usize = 204; -pub const RULE_WHERE_CLAUSE: usize = 205; -pub const RULE_SELECT_OR_GROUP_CLAUSE: usize = 206; -pub const RULE_GROUP_CLAUSE: usize = 207; -pub const RULE_SELECT_CLAUSE: usize = 208; -pub const RULE_QUERY_CONTINUATION: usize = 209; -pub const RULE_REF_EXPRESSION: usize = 210; -pub const RULE_REF_TYPE_EXPRESSION: usize = 211; -pub const RULE_REF_VALUE_EXPRESSION: usize = 212; -pub const RULE_SIZE_OF_EXPRESSION: usize = 213; -pub const RULE_STACK_ALLOC_ARRAY_CREATION_EXPRESSION: usize = 214; -pub const RULE_SWITCH_EXPRESSION_ARM: usize = 215; -pub const RULE_THROW_EXPRESSION: usize = 216; -pub const RULE_TUPLE_EXPRESSION: usize = 217; -pub const RULE_TYPE_OF_EXPRESSION: usize = 218; -pub const RULE_UNSAFE_EXPRESSION: usize = 219; -pub const RULE_SYNTAX_TOKEN: usize = 220; -pub const RULE_IDENTIFIER_TOKEN: usize = 221; -pub const RULE_KEYWORD: usize = 222; -pub const RULE_NUMERIC_LITERAL_TOKEN: usize = 223; -pub const RULE_INTEGER_LITERAL_TOKEN: usize = 224; -pub const RULE_DECIMAL_INTEGER_LITERAL_TOKEN: usize = 225; -pub const RULE_HEXADECIMAL_INTEGER_LITERAL_TOKEN: usize = 226; -pub const RULE_REAL_LITERAL_TOKEN: usize = 227; -pub const RULE_CHARACTER_LITERAL_TOKEN: usize = 228; -pub const RULE_STRING_LITERAL_TOKEN: usize = 229; -pub const RULE_REGULAR_STRING_LITERAL_TOKEN: usize = 230; -pub const RULE_VERBATIM_STRING_LITERAL_TOKEN: usize = 231; -pub const RULE_OPERATOR_TOKEN: usize = 232; -pub const RULE_PUNCTUATION_TOKEN: usize = 233; -pub const RULE_INTERPOLATED_STRING_TEXT_TOKEN: usize = 234; -pub const RULE_MULTI_LINE_RAW_STRING_LITERAL_TOKEN: usize = 235; -pub const RULE_SINGLE_LINE_RAW_STRING_LITERAL_TOKEN: usize = 236; -pub const RULE_RECORD_KEYWORD: usize = 237; -pub const RULE_RIGHT_SHIFT: usize = 238; -pub const RULE_UNSIGNED_RIGHT_SHIFT: usize = 239; -pub const RULE_RIGHT_SHIFT_ASSIGNMENT: usize = 240; -pub const RULE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: usize = 241; -pub const RULE_LOCAL_VARIABLE_DECLARATION: usize = 242; -pub const RULE_LOCAL_VARIABLE_DECLARATOR: usize = 243; - -pub static METADATA: GrammarMetadata = GrammarMetadata::new( - "CSharpParser", - &["compilation_unit", "extern_alias_directive", "using_directive", "name_equals", "identifier_name", "attribute_list", "attribute_target_specifier", "attribute", "name", "alias_qualified_name", "simple_name", "generic_name", "type_argument_list", "attribute_argument_list", "attribute_argument", "name_colon", "member_declaration", "base_field_declaration", "event_field_declaration", "modifier", "variable_declaration", "variable_declarator", "bracketed_argument_list", "argument", "equals_value_clause", "field_declaration", "base_method_declaration", "constructor_declaration", "parameter_list", "parameter", "constructor_initializer", "argument_list", "block", "arrow_expression_clause", "conversion_operator_declaration", "explicit_interface_specifier", "destructor_declaration", "method_declaration", "type_parameter_list", "type_parameter", "type_parameter_constraint_clause", "type_parameter_constraint", "allows_constraint_clause", "allows_constraint", "ref_struct_constraint", "class_or_struct_constraint", "constructor_constraint", "default_constraint", "type_constraint", "operator_declaration", "base_namespace_declaration", "file_scoped_namespace_declaration", "namespace_declaration", "base_property_declaration", "event_declaration", "accessor_list", "accessor_declaration", "indexer_declaration", "bracketed_parameter_list", "property_declaration", "base_type_declaration", "enum_declaration", "base_list", "base_type", "primary_constructor_base_type", "simple_base_type", "enum_member_declaration", "type_declaration", "class_declaration", "extension_block_declaration", "interface_declaration", "record_declaration", "struct_declaration", "union_declaration", "delegate_declaration", "global_statement", "type", "array_type", "array_rank_specifier", "function_pointer_type", "function_pointer_calling_convention", "function_pointer_unmanaged_calling_convention_list", "function_pointer_unmanaged_calling_convention", "function_pointer_parameter_list", "function_pointer_parameter", "predefined_type", "ref_type", "scoped_type", "tuple_type", "tuple_element", "statement", "break_statement", "checked_statement", "common_for_each_statement", "for_each_statement", "for_each_variable_statement", "continue_statement", "do_statement", "empty_statement", "expression_statement", "fixed_statement", "for_statement", "goto_statement", "if_statement", "else_clause", "labeled_statement", "local_declaration_statement", "local_function_statement", "lock_statement", "return_statement", "switch_statement", "switch_section", "switch_label", "case_pattern_switch_label", "pattern", "constant_pattern", "declaration_pattern", "variable_designation", "discard_designation", "parenthesized_variable_designation", "single_variable_designation", "discard_pattern", "list_pattern", "parenthesized_pattern", "recursive_pattern", "positional_pattern_clause", "subpattern", "base_expression_colon", "expression_colon", "property_pattern_clause", "relational_pattern", "slice_pattern", "type_pattern", "unary_pattern", "var_pattern", "when_clause", "case_switch_label", "default_switch_label", "throw_statement", "try_statement", "catch_clause", "catch_declaration", "catch_filter_clause", "finally_clause", "unsafe_statement", "using_statement", "while_statement", "yield_statement", "expression", "anonymous_function_expression", "anonymous_method_expression", "lambda_expression", "parenthesized_lambda_expression", "simple_lambda_expression", "anonymous_object_creation_expression", "anonymous_object_member_declarator", "array_creation_expression", "initializer_expression", "await_expression", "base_object_creation_expression", "implicit_object_creation_expression", "object_creation_expression", "cast_expression", "checked_expression", "collection_expression", "collection_element", "expression_element", "spread_element", "with_element", "declaration_expression", "default_expression", "element_binding_expression", "field_expression", "implicit_array_creation_expression", "implicit_element_access", "implicit_stack_alloc_array_creation_expression", "instance_expression", "base_expression", "this_expression", "interpolated_string_expression", "interpolated_string_content", "interpolated_string_text", "interpolation", "interpolation_alignment_clause", "interpolation_format_clause", "interpolated_multi_line_raw_string_start_token", "interpolated_raw_string_end_token", "interpolated_single_line_raw_string_start_token", "literal_expression", "utf8_multi_line_raw_string_literal_token", "utf8_single_line_raw_string_literal_token", "utf8_string_literal_token", "make_ref_expression", "member_binding_expression", "parenthesized_expression", "prefix_unary_expression", "query_expression", "from_clause", "query_body", "query_clause", "join_clause", "join_into_clause", "let_clause", "order_by_clause", "ordering", "where_clause", "select_or_group_clause", "group_clause", "select_clause", "query_continuation", "ref_expression", "ref_type_expression", "ref_value_expression", "size_of_expression", "stack_alloc_array_creation_expression", "switch_expression_arm", "throw_expression", "tuple_expression", "type_of_expression", "unsafe_expression", "syntax_token", "identifier_token", "keyword", "numeric_literal_token", "integer_literal_token", "decimal_integer_literal_token", "hexadecimal_integer_literal_token", "real_literal_token", "character_literal_token", "string_literal_token", "regular_string_literal_token", "verbatim_string_literal_token", "operator_token", "punctuation_token", "interpolated_string_text_token", "multi_line_raw_string_literal_token", "single_line_raw_string_literal_token", "record_keyword", "right_shift", "unsigned_right_shift", "right_shift_assignment", "unsigned_right_shift_assignment", "local_variable_declaration", "local_variable_declarator"], - &[None, None, None, Some("\'__refvalue\'"), Some("\'descending\'"), Some("\'stackalloc\'"), Some("\'__arglist\'"), Some("\'__makeref\'"), Some("\'__reftype\'"), Some("\'ascending\'"), Some("\'extension\'"), Some("\'interface\'"), Some("\'namespace\'"), Some("\'protected\'"), Some("\'unchecked\'"), Some("\'unmanaged\'"), Some("\'abstract\'"), Some("\'continue\'"), Some("\'delegate\'"), Some("\'explicit\'"), Some("\'implicit\'"), Some("\'internal\'"), Some("\'operator\'"), Some("\'override\'"), Some("\'readonly\'"), Some("\'required\'"), Some("\'volatile\'"), Some("\'checked\'"), Some("\'decimal\'"), Some("\'default\'"), Some("\'finally\'"), Some("\'foreach\'"), Some("\'managed\'"), Some("\'orderby\'"), Some("\'partial\'"), Some("\'private\'"), Some("\'virtual\'"), Some("\'allows\'"), Some("\'closed\'"), Some("\'double\'"), Some("\'equals\'"), Some("\'extern\'"), Some("\'global\'"), Some("\'object\'"), Some("\'params\'"), Some("\'public\'"), Some("\'remove\'"), Some("\'return\'"), Some("\'scoped\'"), Some("\'sealed\'"), Some("\'select\'"), Some("\'sizeof\'"), Some("\'static\'"), Some("\'string\'"), Some("\'struct\'"), Some("\'switch\'"), Some("\'typeof\'"), Some("\'unsafe\'"), Some("\'ushort\'"), Some("\'alias\'"), Some("\'async\'"), Some("\'await\'"), Some("\'break\'"), Some("\'catch\'"), Some("\'class\'"), Some("\'const\'"), Some("\'event\'"), Some("\'false\'"), Some("\'field\'"), Some("\'fixed\'"), Some("\'float\'"), Some("\'group\'"), Some("\'sbyte\'"), Some("\'short\'"), Some("\'throw\'"), Some("\'ulong\'"), Some("\'union\'"), Some("\'using\'"), Some("\'where\'"), Some("\'while\'"), Some("\'yield\'"), Some("\'base\'"), Some("\'bool\'"), Some("\'byte\'"), Some("\'case\'"), Some("\'char\'"), Some("\'else\'"), Some("\'enum\'"), Some("\'file\'"), Some("\'from\'"), Some("\'goto\'"), Some("\'init\'"), Some("\'into\'"), Some("\'join\'"), Some("\'lock\'"), Some("\'long\'"), Some("\'null\'"), Some("\'safe\'"), Some("\'this\'"), Some("\'true\'"), Some("\'uint\'"), Some("\'void\'"), Some("\'when\'"), Some("\'with\'"), Some("\'\"\"\"\'"), Some("\'<<=\'"), Some("\'??=\'"), Some("\'add\'"), Some("\'and\'"), Some("\'for\'"), Some("\'get\'"), Some("\'int\'"), Some("\'let\'"), Some("\'new\'"), Some("\'not\'"), Some("\'out\'"), Some("\'ref\'"), Some("\'set\'"), Some("\'try\'"), Some("\'var\'"), Some("\'!=\'"), Some("\'%=\'"), Some("\'&&\'"), Some("\'&=\'"), Some("\'*=\'"), Some("\'++\'"), Some("\'+=\'"), Some("\'--\'"), Some("\'-=\'"), Some("\'->\'"), Some("\'..\'"), Some("\'/=\'"), Some("\'/>\'"), Some("\'::\'"), Some("\'\'"), Some("\'>=\'"), Some("\'??\'"), Some("\'U8\'"), Some("\'\\\'\'"), Some("\'\\\\\'"), Some("\'^=\'"), Some("\'as\'"), Some("\'by\'"), Some("\'do\'"), Some("\'if\'"), Some("\'in\'"), Some("\'is\'"), Some("\'on\'"), Some("\'or\'"), Some("\'u8\'"), Some("\'|=\'"), Some("\'||\'"), Some("\'!\'"), None, Some("\'#\'"), Some("\'%\'"), Some("\'&\'"), Some("\'*\'"), Some("\'+\'"), Some("\',\'"), Some("\'-\'"), Some("\'.\'"), Some("\'/\'"), Some("\';\'"), Some("\'<\'"), Some("\'=\'"), Some("\'>\'"), Some("\'?\'"), Some("\'^\'"), Some("\'_\'"), Some("\'|\'"), Some("\'~\'"), Some("\'record\'"), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, Some("\'\u{feff}\'"), None, Some("\'$\"\'"), None, None, None, None, Some("\':\'"), Some("\'(\'"), Some("\')\'"), Some("\'[\'"), Some("\']\'"), None, None, Some("\'\"\"\'")], - &[None, Some("INTERPOLATED_TEXT"), Some("XML_TEXT_LIT"), Some("KW___REFVALUE"), Some("KW_DESCENDING"), Some("KW_STACKALLOC"), Some("KW___ARGLIST"), Some("KW___MAKEREF"), Some("KW___REFTYPE"), Some("KW_ASCENDING"), Some("KW_EXTENSION"), Some("KW_INTERFACE"), Some("KW_NAMESPACE"), Some("KW_PROTECTED"), Some("KW_UNCHECKED"), Some("KW_UNMANAGED"), Some("KW_ABSTRACT"), Some("KW_CONTINUE"), Some("KW_DELEGATE"), Some("KW_EXPLICIT"), Some("KW_IMPLICIT"), Some("KW_INTERNAL"), Some("KW_OPERATOR"), Some("KW_OVERRIDE"), Some("KW_READONLY"), Some("KW_REQUIRED"), Some("KW_VOLATILE"), Some("KW_CHECKED"), Some("KW_DECIMAL"), Some("KW_DEFAULT"), Some("KW_FINALLY"), Some("KW_FOREACH"), Some("KW_MANAGED"), Some("KW_ORDERBY"), Some("KW_PARTIAL"), Some("KW_PRIVATE"), Some("KW_VIRTUAL"), Some("KW_ALLOWS"), Some("KW_CLOSED"), Some("KW_DOUBLE"), Some("KW_EQUALS"), Some("KW_EXTERN"), Some("KW_GLOBAL"), Some("KW_OBJECT"), Some("KW_PARAMS"), Some("KW_PUBLIC"), Some("KW_REMOVE"), Some("KW_RETURN"), Some("KW_SCOPED"), Some("KW_SEALED"), Some("KW_SELECT"), Some("KW_SIZEOF"), Some("KW_STATIC"), Some("KW_STRING"), Some("KW_STRUCT"), Some("KW_SWITCH"), Some("KW_TYPEOF"), Some("KW_UNSAFE"), Some("KW_USHORT"), Some("KW_ALIAS"), Some("KW_ASYNC"), Some("KW_AWAIT"), Some("KW_BREAK"), Some("KW_CATCH"), Some("KW_CLASS"), Some("KW_CONST"), Some("KW_EVENT"), Some("KW_FALSE"), Some("KW_FIELD"), Some("KW_FIXED"), Some("KW_FLOAT"), Some("KW_GROUP"), Some("KW_SBYTE"), Some("KW_SHORT"), Some("KW_THROW"), Some("KW_ULONG"), Some("KW_UNION"), Some("KW_USING"), Some("KW_WHERE"), Some("KW_WHILE"), Some("KW_YIELD"), Some("KW_BASE"), Some("KW_BOOL"), Some("KW_BYTE"), Some("KW_CASE"), Some("KW_CHAR"), Some("KW_ELSE"), Some("KW_ENUM"), Some("KW_FILE"), Some("KW_FROM"), Some("KW_GOTO"), Some("KW_INIT"), Some("KW_INTO"), Some("KW_JOIN"), Some("KW_LOCK"), Some("KW_LONG"), Some("KW_NULL"), Some("KW_SAFE"), Some("KW_THIS"), Some("KW_TRUE"), Some("KW_UINT"), Some("KW_VOID"), Some("KW_WHEN"), Some("KW_WITH"), Some("TRIPLE_DQUOTE"), Some("LT_LT_EQ"), Some("QUESTION_QUESTION_EQ"), Some("KW_ADD"), Some("KW_AND"), Some("KW_FOR"), Some("KW_GET"), Some("KW_INT"), Some("KW_LET"), Some("KW_NEW"), Some("KW_NOT"), Some("KW_OUT"), Some("KW_REF"), Some("KW_SET"), Some("KW_TRY"), Some("KW_VAR"), Some("NE"), Some("PERCENT_EQ"), Some("AMP_AMP"), Some("AMP_EQ"), Some("STAR_EQ"), Some("PLUS_PLUS"), Some("PLUS_EQ"), Some("MINUS_MINUS"), Some("MINUS_EQ"), Some("MINUS_GT"), Some("DOT_DOT"), Some("SLASH_EQ"), Some("SLASH_GT"), Some("COLON_COLON"), Some("LT_SLASH"), Some("LT_LT"), Some("LE"), Some("EQ_EQ"), Some("ARROW"), Some("GE"), Some("QUESTION_QUESTION"), Some("KW_U8"), Some("ESCAPED_QUOTE"), Some("ESCAPED_BACKSLASH"), Some("CARET_EQ"), Some("KW_AS"), Some("KW_BY"), Some("KW_DO"), Some("KW_IF"), Some("KW_IN"), Some("KW_IS"), Some("KW_ON"), Some("KW_OR"), Some("KW_U8_LOWER"), Some("PIPE_EQ"), Some("PIPE_PIPE"), Some("BANG"), Some("DQUOTE"), Some("HASH"), Some("PERCENT"), Some("AMP"), Some("STAR"), Some("PLUS"), Some("COMMA"), Some("MINUS"), Some("DOT"), Some("SLASH"), Some("SEMICOLON"), Some("LT"), Some("EQ"), Some("GT"), Some("QUESTION"), Some("CARET"), Some("KW__"), Some("PIPE"), Some("TILDE"), Some("KW_RECORD"), Some("IDENTIFIER"), Some("DEC_INT_LIT"), Some("HEX_INT_LIT"), Some("BIN_INT_LIT"), Some("REAL_LIT"), Some("CHAR_LIT"), Some("STRING_LIT"), Some("VERBATIM_STRING_LIT"), Some("SL_RAW_STRING_LIT"), Some("ML_RAW_STRING_LIT"), Some("SINGLE_LINE_DOC_COMMENT"), Some("DELIMITED_DOC_COMMENT"), Some("SINGLE_LINE_COMMENT"), Some("DELIMITED_COMMENT"), Some("WHITESPACES"), Some("BYTE_ORDER_MARK"), Some("DIRECTIVE_LINE"), Some("INTERP_START"), Some("INTERP_VERBATIM_START"), Some("INTERP_RAW_START"), Some("LBRACE"), Some("RBRACE"), Some("COLON"), Some("LPAREN"), Some("RPAREN"), Some("LBRACKET"), Some("RBRACKET"), Some("INTERP_ESCAPED_OPEN"), Some("INTERP_ESCAPED_CLOSE"), Some("INTERP_V_ESCAPED_QUOTE")], - &[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &[], - &[], - &[], -); - -pub fn metadata() -> &'static GrammarMetadata { - &METADATA -} - -pub fn rule_names() -> &'static [&'static str] { - METADATA.rule_names() -} - -fn parser_semantics() -> &'static antlr4_runtime::ParserSemantics { - static SEMANTICS_CELL: OnceLock = OnceLock::new(); - SEMANTICS_CELL.get_or_init(|| { - let mut ir = antlr4_runtime::semir::SemIr::new(); - let mut predicates = Vec::new(); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::TokenIndexAdjacent); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 238, pred_index: 17, expr: __expr, failure_message: None }); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::TokenIndexAdjacent); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 239, pred_index: 18, expr: __expr, failure_message: None }); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::TokenIndexAdjacent); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 239, pred_index: 19, expr: __expr, failure_message: None }); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::TokenIndexAdjacent); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 240, pred_index: 20, expr: __expr, failure_message: None }); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::TokenIndexAdjacent); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 241, pred_index: 21, expr: __expr, failure_message: None }); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::TokenIndexAdjacent); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 241, pred_index: 22, expr: __expr, failure_message: None }); - - let actions = Vec::new(); - antlr4_runtime::ParserSemantics { ir, predicates, actions } - }) -} - - - -/// Marker carried by generated contexts whose required-child -/// invariants were checked after a syntax-clean parse, and grammar brand of -/// this module's validated tree and rule-node types. -/// -/// This marker stays module-local (unlike the runtime-owned support items) -/// so rustc can prove it never implements the runtime's -/// `__RecoveryContextState`, keeping the recovery-oriented and validated -/// accessor impls coherent — and so the runtime's branded validated types -/// stay nominally distinct per grammar. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct ValidatedTreeContext { - __private: (), -} - -/// A completed, syntax-clean parse tree whose generated child cardinalities -/// have been structurally validated. -/// -/// Alias of the runtime's grammar-agnostic `antlr4_runtime::ValidatedTree` -/// branded with this module's [`ValidatedTreeContext`] marker, so validated -/// trees of different grammars remain distinct types. -pub type CSharpValidatedTree = antlr4_runtime::ValidatedTree; - -/// A rule node borrowed from a [`CSharpValidatedTree`]. -/// -/// Alias of the runtime's `antlr4_runtime::ValidatedRuleNode` branded with -/// this module's [`ValidatedTreeContext`] marker. -pub type ValidatedRuleNode<'a> = antlr4_runtime::ValidatedRuleNode<'a, ValidatedTreeContext>; - -pub use antlr4_runtime::FromValidatedRuleNode; - -/// Failure to recognize or validate a strict generated parse. -/// -/// Alias of the grammar-agnostic `antlr4_runtime::ValidationError`; unlike -/// the branded tree types, the validation errors of every generated parser -/// are deliberately one shared type. -pub type CSharpValidationError = antlr4_runtime::ValidationError; - -#[allow(dead_code)] -fn __context_kind(context: RuleNodeView<'_>) -> usize { - context.rule_index() -} - -#[allow(dead_code)] -fn __active_context_kind( - context: &antlr4_runtime::ParserRuleContext, - _storage: &antlr4_runtime::ParseTreeStorage, - _tokens: &antlr4_runtime::TokenStore, -) -> usize { - context.rule_index() -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CompilationUnitContext { - rule_index: 0, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CompilationUnitContext { - rule extern_alias_directive_children: many(ExternAliasDirectiveContext[1]), - rule using_directive_children: many(UsingDirectiveContext[2]), - rule attribute_list_children: many(AttributeListContext[5]), - rule member_declaration_children: many(MemberDeclarationContext[16]), - token eof_token: required(-1, "EOF"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExternAliasDirectiveContext { - rule_index: 1, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExternAliasDirectiveContext { - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_extern_token: required(41, "KW_EXTERN"), - token kw_alias_token: required(59, "KW_ALIAS"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UsingDirectiveContext { - rule_index: 2, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UsingDirectiveContext { - rule name_equals: optional(NameEqualsContext[3]), - rule r#type: required(TypeContext[76], "type"), - token kw_global_token: optional(42), - token kw_static_token: optional(52), - token kw_unsafe_token: optional(57), - token kw_using_token: required(77, "KW_USING"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NameEqualsContext { - rule_index: 3, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NameEqualsContext { - rule identifier_name: required(IdentifierNameContext[4], "identifier_name"), - token eq_token: required(169, "EQ"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IdentifierNameContext { - rule_index: 4, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IdentifierNameContext { - rule identifier_token: optional(IdentifierTokenContext[221]), - token kw_global_token: optional(42), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AttributeListContext { - rule_index: 5, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AttributeListContext { - rule attribute_target_specifier: optional(AttributeTargetSpecifierContext[6]), - rule attribute_children: many(AttributeContext[7]), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AttributeTargetSpecifierContext { - rule_index: 6, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AttributeTargetSpecifierContext { - rule syntax_token: required(SyntaxTokenContext[220], "syntax_token"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AttributeContext { - rule_index: 7, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AttributeContext { - rule name: required(NameContext[8], "name"), - rule attribute_argument_list: optional(AttributeArgumentListContext[13]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NameContext { - rule_index: 8, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NameContext { - rule name: optional(NameContext[8]), - rule alias_qualified_name: optional(AliasQualifiedNameContext[9]), - rule simple_name: optional(SimpleNameContext[10]), - token dot_token: optional(165), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AliasQualifiedNameContext { - rule_index: 9, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AliasQualifiedNameContext { - rule identifier_name: required(IdentifierNameContext[4], "identifier_name"), - rule simple_name: required(SimpleNameContext[10], "simple_name"), - token colon_colon_token: required(133, "COLON_COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SimpleNameContext { - rule_index: 10, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SimpleNameContext { - rule identifier_name: optional(IdentifierNameContext[4]), - rule generic_name: optional(GenericNameContext[11]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GenericNameContext { - rule_index: 11, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GenericNameContext { - rule type_argument_list: required(TypeArgumentListContext[12], "type_argument_list"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeArgumentListContext { - rule_index: 12, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeArgumentListContext { - rule type_children: many(TypeContext[76]), - token comma_tokens: many(163), - token lt_token: required(168, "LT"), - token gt_token: required(170, "GT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AttributeArgumentListContext { - rule_index: 13, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AttributeArgumentListContext { - rule attribute_argument_children: many(AttributeArgumentContext[14]), - token comma_tokens: many(163), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AttributeArgumentContext { - rule_index: 14, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AttributeArgumentContext { - rule name_equals: optional(NameEqualsContext[3]), - rule name_colon: optional(NameColonContext[15]), - rule expression: required(ExpressionContext[148], "expression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NameColonContext { - rule_index: 15, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NameColonContext { - rule identifier_name: required(IdentifierNameContext[4], "identifier_name"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MemberDeclarationContext { - rule_index: 16, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MemberDeclarationContext { - rule base_field_declaration: optional(BaseFieldDeclarationContext[17]), - rule base_method_declaration: optional(BaseMethodDeclarationContext[26]), - rule base_namespace_declaration: optional(BaseNamespaceDeclarationContext[50]), - rule base_property_declaration: optional(BasePropertyDeclarationContext[53]), - rule base_type_declaration: optional(BaseTypeDeclarationContext[60]), - rule enum_member_declaration: optional(EnumMemberDeclarationContext[66]), - rule extension_block_declaration: optional(ExtensionBlockDeclarationContext[69]), - rule record_declaration: optional(RecordDeclarationContext[71]), - rule union_declaration: optional(UnionDeclarationContext[73]), - rule delegate_declaration: optional(DelegateDeclarationContext[74]), - rule global_statement: optional(GlobalStatementContext[75]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseFieldDeclarationContext { - rule_index: 17, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseFieldDeclarationContext { - rule event_field_declaration: optional(EventFieldDeclarationContext[18]), - rule field_declaration: optional(FieldDeclarationContext[25]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EventFieldDeclarationContext { - rule_index: 18, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EventFieldDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule variable_declaration: required(VariableDeclarationContext[20], "variable_declaration"), - token kw_event_token: required(66, "KW_EVENT"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ModifierContext { - rule_index: 19, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ModifierContext { - token kw_protected_token: optional(13), - token kw_abstract_token: optional(16), - token kw_internal_token: optional(21), - token kw_override_token: optional(23), - token kw_readonly_token: optional(24), - token kw_required_token: optional(25), - token kw_volatile_token: optional(26), - token kw_partial_token: optional(34), - token kw_private_token: optional(35), - token kw_virtual_token: optional(36), - token kw_closed_token: optional(38), - token kw_extern_token: optional(41), - token kw_public_token: optional(45), - token kw_scoped_token: optional(48), - token kw_sealed_token: optional(49), - token kw_static_token: optional(52), - token kw_unsafe_token: optional(57), - token kw_async_token: optional(60), - token kw_const_token: optional(65), - token kw_fixed_token: optional(69), - token kw_file_token: optional(88), - token kw_safe_token: optional(97), - token kw_new_token: optional(113), - token kw_ref_token: optional(116), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableDeclarationContext { - rule_index: 20, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableDeclarationContext { - rule variable_declarator_children: many(VariableDeclaratorContext[21]), - rule r#type: required(TypeContext[76], "type"), - token comma_tokens: many(163), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableDeclaratorContext { - rule_index: 21, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableDeclaratorContext { - rule bracketed_argument_list: optional(BracketedArgumentListContext[22]), - rule equals_value_clause: optional(EqualsValueClauseContext[24]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BracketedArgumentListContext { - rule_index: 22, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BracketedArgumentListContext { - rule argument_children: many(ArgumentContext[23]), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArgumentContext { - rule_index: 23, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArgumentContext { - rule name_colon: optional(NameColonContext[15]), - rule expression: required(ExpressionContext[148], "expression"), - token kw_out_token: optional(115), - token kw_ref_token: optional(116), - token kw_in_token: optional(149), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EqualsValueClauseContext { - rule_index: 24, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EqualsValueClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - token eq_token: required(169, "EQ"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FieldDeclarationContext { - rule_index: 25, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FieldDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule variable_declaration: required(VariableDeclarationContext[20], "variable_declaration"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseMethodDeclarationContext { - rule_index: 26, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseMethodDeclarationContext { - rule constructor_declaration: optional(ConstructorDeclarationContext[27]), - rule conversion_operator_declaration: optional(ConversionOperatorDeclarationContext[34]), - rule destructor_declaration: optional(DestructorDeclarationContext[36]), - rule method_declaration: optional(MethodDeclarationContext[37]), - rule operator_declaration: optional(OperatorDeclarationContext[49]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstructorDeclarationContext { - rule_index: 27, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstructorDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule constructor_initializer: optional(ConstructorInitializerContext[30]), - rule block: optional(BlockContext[32]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParameterListContext { - rule_index: 28, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParameterListContext { - rule parameter_children: many(ParameterContext[29]), - token comma_tokens: many(163), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParameterContext { - rule_index: 29, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParameterContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule equals_value_clause: optional(EqualsValueClauseContext[24]), - rule r#type: optional(TypeContext[76]), - rule identifier_token: optional(IdentifierTokenContext[221]), - token kw_arglist_token: optional(6), - token kw_params_tokens: many(44), - token kw_this_tokens: many(98), - token kw_out_tokens: many(115), - token kw_in_tokens: many(149), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstructorInitializerContext { - rule_index: 30, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstructorInitializerContext { - rule argument_list: required(ArgumentListContext[31], "argument_list"), - token kw_base_token: optional(81), - token kw_this_token: optional(98), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArgumentListContext { - rule_index: 31, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArgumentListContext { - rule argument_children: many(ArgumentContext[23]), - token comma_tokens: many(163), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BlockContext { - rule_index: 32, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BlockContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule statement_children: many(StatementContext[90]), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArrowExpressionClauseContext { - rule_index: 33, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArrowExpressionClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - token arrow_token: required(138, "ARROW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConversionOperatorDeclarationContext { - rule_index: 34, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConversionOperatorDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule block: optional(BlockContext[32]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule explicit_interface_specifier: optional(ExplicitInterfaceSpecifierContext[35]), - rule r#type: required(TypeContext[76], "type"), - token kw_explicit_token: optional(19), - token kw_implicit_token: optional(20), - token kw_operator_token: required(22, "KW_OPERATOR"), - token kw_checked_token: optional(27), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExplicitInterfaceSpecifierContext { - rule_index: 35, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExplicitInterfaceSpecifierContext { - rule name: required(NameContext[8], "name"), - token dot_token: required(165, "DOT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DestructorDeclarationContext { - rule_index: 36, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DestructorDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule block: optional(BlockContext[32]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token semicolon_token: optional(167), - token tilde_token: required(175, "TILDE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MethodDeclarationContext { - rule_index: 37, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MethodDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule block: optional(BlockContext[32]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule explicit_interface_specifier: optional(ExplicitInterfaceSpecifierContext[35]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule r#type: required(TypeContext[76], "type"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterListContext { - rule_index: 38, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterListContext { - rule type_parameter_children: many(TypeParameterContext[39]), - token comma_tokens: many(163), - token lt_token: required(168, "LT"), - token gt_token: required(170, "GT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterContext { - rule_index: 39, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_out_token: optional(115), - token kw_in_token: optional(149), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterConstraintClauseContext { - rule_index: 40, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterConstraintClauseContext { - rule identifier_name: required(IdentifierNameContext[4], "identifier_name"), - rule type_parameter_constraint_children: many(TypeParameterConstraintContext[41]), - token kw_where_token: required(78, "KW_WHERE"), - token comma_tokens: many(163), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterConstraintContext { - rule_index: 41, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterConstraintContext { - rule allows_constraint_clause: optional(AllowsConstraintClauseContext[42]), - rule class_or_struct_constraint: optional(ClassOrStructConstraintContext[45]), - rule constructor_constraint: optional(ConstructorConstraintContext[46]), - rule default_constraint: optional(DefaultConstraintContext[47]), - rule type_constraint: optional(TypeConstraintContext[48]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AllowsConstraintClauseContext { - rule_index: 42, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AllowsConstraintClauseContext { - rule allows_constraint_children: many(AllowsConstraintContext[43]), - token kw_allows_token: required(37, "KW_ALLOWS"), - token comma_tokens: many(163), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AllowsConstraintContext { - rule_index: 43, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AllowsConstraintContext { - rule ref_struct_constraint: required(RefStructConstraintContext[44], "ref_struct_constraint"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RefStructConstraintContext { - rule_index: 44, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RefStructConstraintContext { - token kw_struct_token: required(54, "KW_STRUCT"), - token kw_ref_token: required(116, "KW_REF"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassOrStructConstraintContext { - rule_index: 45, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassOrStructConstraintContext { - token kw_struct_token: optional(54), - token kw_class_token: optional(64), - token question_token: optional(171), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstructorConstraintContext { - rule_index: 46, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstructorConstraintContext { - token kw_new_token: required(113, "KW_NEW"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DefaultConstraintContext { - rule_index: 47, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DefaultConstraintContext { - token kw_default_token: required(29, "KW_DEFAULT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeConstraintContext { - rule_index: 48, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeConstraintContext { - rule r#type: required(TypeContext[76], "type"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct OperatorDeclarationContext { - rule_index: 49, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - OperatorDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule block: optional(BlockContext[32]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule explicit_interface_specifier: optional(ExplicitInterfaceSpecifierContext[35]), - rule r#type: required(TypeContext[76], "type"), - rule right_shift: optional(RightShiftContext[238]), - rule unsigned_right_shift: optional(UnsignedRightShiftContext[239]), - rule right_shift_assignment: optional(RightShiftAssignmentContext[240]), - rule unsigned_right_shift_assignment: optional(UnsignedRightShiftAssignmentContext[241]), - token kw_operator_token: required(22, "KW_OPERATOR"), - token kw_checked_token: optional(27), - token kw_false_token: optional(67), - token kw_true_token: optional(99), - token lt_lt_eq_token: optional(105), - token ne_token: optional(120), - token percent_eq_token: optional(121), - token amp_eq_token: optional(123), - token star_eq_token: optional(124), - token plus_plus_token: optional(125), - token plus_eq_token: optional(126), - token minus_minus_token: optional(127), - token minus_eq_token: optional(128), - token slash_eq_token: optional(131), - token lt_lt_token: optional(135), - token le_token: optional(136), - token eq_eq_token: optional(137), - token ge_token: optional(139), - token caret_eq_token: optional(144), - token kw_is_token: optional(150), - token pipe_eq_token: optional(154), - token bang_token: optional(156), - token percent_token: optional(159), - token amp_token: optional(160), - token star_token: optional(161), - token plus_token: optional(162), - token minus_token: optional(164), - token slash_token: optional(166), - token semicolon_token: optional(167), - token lt_token: optional(168), - token gt_token: optional(170), - token caret_token: optional(172), - token pipe_token: optional(174), - token tilde_token: optional(175), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseNamespaceDeclarationContext { - rule_index: 50, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseNamespaceDeclarationContext { - rule file_scoped_namespace_declaration: optional(FileScopedNamespaceDeclarationContext[51]), - rule namespace_declaration: optional(NamespaceDeclarationContext[52]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FileScopedNamespaceDeclarationContext { - rule_index: 51, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FileScopedNamespaceDeclarationContext { - rule extern_alias_directive_children: many(ExternAliasDirectiveContext[1]), - rule using_directive_children: many(UsingDirectiveContext[2]), - rule attribute_list_children: many(AttributeListContext[5]), - rule name: required(NameContext[8], "name"), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - token kw_namespace_token: required(12, "KW_NAMESPACE"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NamespaceDeclarationContext { - rule_index: 52, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NamespaceDeclarationContext { - rule extern_alias_directive_children: many(ExternAliasDirectiveContext[1]), - rule using_directive_children: many(UsingDirectiveContext[2]), - rule attribute_list_children: many(AttributeListContext[5]), - rule name: required(NameContext[8], "name"), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - token kw_namespace_token: required(12, "KW_NAMESPACE"), - token semicolon_token: optional(167), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BasePropertyDeclarationContext { - rule_index: 53, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BasePropertyDeclarationContext { - rule event_declaration: optional(EventDeclarationContext[54]), - rule indexer_declaration: optional(IndexerDeclarationContext[57]), - rule property_declaration: optional(PropertyDeclarationContext[59]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EventDeclarationContext { - rule_index: 54, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EventDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule explicit_interface_specifier: optional(ExplicitInterfaceSpecifierContext[35]), - rule accessor_list: optional(AccessorListContext[55]), - rule r#type: required(TypeContext[76], "type"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_event_token: required(66, "KW_EVENT"), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AccessorListContext { - rule_index: 55, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AccessorListContext { - rule accessor_declaration_children: many(AccessorDeclarationContext[56]), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AccessorDeclarationContext { - rule_index: 56, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AccessorDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule block: optional(BlockContext[32]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - token kw_remove_token: optional(46), - token kw_init_token: optional(91), - token kw_add_token: optional(107), - token kw_get_token: optional(110), - token kw_set_token: optional(117), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IndexerDeclarationContext { - rule_index: 57, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IndexerDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule explicit_interface_specifier: optional(ExplicitInterfaceSpecifierContext[35]), - rule accessor_list: optional(AccessorListContext[55]), - rule bracketed_parameter_list: required(BracketedParameterListContext[58], "bracketed_parameter_list"), - rule r#type: required(TypeContext[76], "type"), - token kw_this_token: required(98, "KW_THIS"), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BracketedParameterListContext { - rule_index: 58, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BracketedParameterListContext { - rule parameter_children: many(ParameterContext[29]), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PropertyDeclarationContext { - rule_index: 59, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PropertyDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule equals_value_clause: optional(EqualsValueClauseContext[24]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule explicit_interface_specifier: optional(ExplicitInterfaceSpecifierContext[35]), - rule accessor_list: optional(AccessorListContext[55]), - rule r#type: required(TypeContext[76], "type"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseTypeDeclarationContext { - rule_index: 60, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseTypeDeclarationContext { - rule enum_declaration: optional(EnumDeclarationContext[61]), - rule type_declaration: optional(TypeDeclarationContext[67]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumDeclarationContext { - rule_index: 61, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule base_list: optional(BaseListContext[62]), - rule enum_member_declaration_children: many(EnumMemberDeclarationContext[66]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_enum_token: required(87, "KW_ENUM"), - token comma_tokens: many(163), - token semicolon_token: optional(167), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseListContext { - rule_index: 62, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseListContext { - rule base_type_children: many(BaseTypeContext[63]), - token comma_tokens: many(163), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseTypeContext { - rule_index: 63, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseTypeContext { - rule primary_constructor_base_type: optional(PrimaryConstructorBaseTypeContext[64]), - rule simple_base_type: optional(SimpleBaseTypeContext[65]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrimaryConstructorBaseTypeContext { - rule_index: 64, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrimaryConstructorBaseTypeContext { - rule argument_list: required(ArgumentListContext[31], "argument_list"), - rule r#type: required(TypeContext[76], "type"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SimpleBaseTypeContext { - rule_index: 65, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SimpleBaseTypeContext { - rule r#type: required(TypeContext[76], "type"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumMemberDeclarationContext { - rule_index: 66, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumMemberDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule equals_value_clause: optional(EqualsValueClauseContext[24]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeDeclarationContext { - rule_index: 67, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeDeclarationContext { - rule class_declaration: optional(ClassDeclarationContext[68]), - rule extension_block_declaration: optional(ExtensionBlockDeclarationContext[69]), - rule interface_declaration: optional(InterfaceDeclarationContext[70]), - rule record_declaration: optional(RecordDeclarationContext[71]), - rule struct_declaration: optional(StructDeclarationContext[72]), - rule union_declaration: optional(UnionDeclarationContext[73]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassDeclarationContext { - rule_index: 68, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: optional(ParameterListContext[28]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule base_list: optional(BaseListContext[62]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_class_token: required(64, "KW_CLASS"), - token semicolon_token: optional(167), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExtensionBlockDeclarationContext { - rule_index: 69, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExtensionBlockDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: optional(ParameterListContext[28]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - token kw_extension_token: required(10, "KW_EXTENSION"), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceDeclarationContext { - rule_index: 70, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: optional(ParameterListContext[28]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule base_list: optional(BaseListContext[62]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_interface_token: required(11, "KW_INTERFACE"), - token semicolon_token: optional(167), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecordDeclarationContext { - rule_index: 71, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecordDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: optional(ParameterListContext[28]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule base_list: optional(BaseListContext[62]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - rule record_keyword: required(RecordKeywordContext[237], "record_keyword"), - token kw_struct_token: optional(54), - token kw_class_token: optional(64), - token semicolon_token: optional(167), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StructDeclarationContext { - rule_index: 72, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StructDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: optional(ParameterListContext[28]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule base_list: optional(BaseListContext[62]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_struct_token: required(54, "KW_STRUCT"), - token semicolon_token: optional(167), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnionDeclarationContext { - rule_index: 73, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnionDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule member_declaration_children: many(MemberDeclarationContext[16]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: optional(ParameterListContext[28]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule base_list: optional(BaseListContext[62]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_union_token: required(76, "KW_UNION"), - token semicolon_token: optional(167), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DelegateDeclarationContext { - rule_index: 74, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DelegateDeclarationContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule r#type: required(TypeContext[76], "type"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_delegate_token: required(18, "KW_DELEGATE"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GlobalStatementContext { - rule_index: 75, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GlobalStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule statement: required(StatementContext[90], "statement"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeContext { - rule_index: 76, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeContext { - rule name: optional(NameContext[8]), - rule r#type: optional(TypeContext[76]), - rule array_rank_specifier_children: many(ArrayRankSpecifierContext[78]), - rule function_pointer_type: optional(FunctionPointerTypeContext[79]), - rule predefined_type: optional(PredefinedTypeContext[85]), - rule ref_type: optional(RefTypeContext[86]), - rule scoped_type: optional(ScopedTypeContext[87]), - rule tuple_type: optional(TupleTypeContext[88]), - token star_token: optional(161), - token question_token: optional(171), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArrayTypeContext { - rule_index: 77, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArrayTypeContext { - rule r#type: required(TypeContext[76], "type"), - rule array_rank_specifier_children: many(ArrayRankSpecifierContext[78]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArrayRankSpecifierContext { - rule_index: 78, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArrayRankSpecifierContext { - rule expression_children: many(ExpressionContext[148]), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionPointerTypeContext { - rule_index: 79, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionPointerTypeContext { - rule function_pointer_calling_convention: optional(FunctionPointerCallingConventionContext[80]), - rule function_pointer_parameter_list: required(FunctionPointerParameterListContext[83], "function_pointer_parameter_list"), - token kw_delegate_token: required(18, "KW_DELEGATE"), - token star_token: required(161, "STAR"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionPointerCallingConventionContext { - rule_index: 80, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionPointerCallingConventionContext { - rule function_pointer_unmanaged_calling_convention_list: optional(FunctionPointerUnmanagedCallingConventionListContext[81]), - token kw_unmanaged_token: optional(15), - token kw_managed_token: optional(32), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionPointerUnmanagedCallingConventionListContext { - rule_index: 81, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionPointerUnmanagedCallingConventionListContext { - rule function_pointer_unmanaged_calling_convention_children: many(FunctionPointerUnmanagedCallingConventionContext[82]), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionPointerUnmanagedCallingConventionContext { - rule_index: 82, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionPointerUnmanagedCallingConventionContext { - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionPointerParameterListContext { - rule_index: 83, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionPointerParameterListContext { - rule function_pointer_parameter_children: many(FunctionPointerParameterContext[84]), - token comma_tokens: many(163), - token lt_token: required(168, "LT"), - token gt_token: required(170, "GT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionPointerParameterContext { - rule_index: 84, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionPointerParameterContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule r#type: required(TypeContext[76], "type"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PredefinedTypeContext { - rule_index: 85, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PredefinedTypeContext { - token kw_decimal_token: optional(28), - token kw_double_token: optional(39), - token kw_object_token: optional(43), - token kw_string_token: optional(53), - token kw_ushort_token: optional(58), - token kw_float_token: optional(70), - token kw_sbyte_token: optional(72), - token kw_short_token: optional(73), - token kw_ulong_token: optional(75), - token kw_bool_token: optional(82), - token kw_byte_token: optional(83), - token kw_char_token: optional(85), - token kw_long_token: optional(95), - token kw_uint_token: optional(100), - token kw_void_token: optional(101), - token kw_int_token: optional(111), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RefTypeContext { - rule_index: 86, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RefTypeContext { - rule r#type: required(TypeContext[76], "type"), - token kw_readonly_token: optional(24), - token kw_ref_token: required(116, "KW_REF"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ScopedTypeContext { - rule_index: 87, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ScopedTypeContext { - rule r#type: required(TypeContext[76], "type"), - token kw_scoped_token: required(48, "KW_SCOPED"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TupleTypeContext { - rule_index: 88, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TupleTypeContext { - rule tuple_element_children: many(TupleElementContext[89]), - token comma_tokens: many(163), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TupleElementContext { - rule_index: 89, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TupleElementContext { - rule r#type: required(TypeContext[76], "type"), - rule identifier_token: optional(IdentifierTokenContext[221]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StatementContext { - rule_index: 90, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StatementContext { - rule block: optional(BlockContext[32]), - rule break_statement: optional(BreakStatementContext[91]), - rule checked_statement: optional(CheckedStatementContext[92]), - rule common_for_each_statement: optional(CommonForEachStatementContext[93]), - rule continue_statement: optional(ContinueStatementContext[96]), - rule do_statement: optional(DoStatementContext[97]), - rule empty_statement: optional(EmptyStatementContext[98]), - rule expression_statement: optional(ExpressionStatementContext[99]), - rule fixed_statement: optional(FixedStatementContext[100]), - rule for_statement: optional(ForStatementContext[101]), - rule goto_statement: optional(GotoStatementContext[102]), - rule if_statement: optional(IfStatementContext[103]), - rule labeled_statement: optional(LabeledStatementContext[105]), - rule local_declaration_statement: optional(LocalDeclarationStatementContext[106]), - rule local_function_statement: optional(LocalFunctionStatementContext[107]), - rule lock_statement: optional(LockStatementContext[108]), - rule return_statement: optional(ReturnStatementContext[109]), - rule switch_statement: optional(SwitchStatementContext[110]), - rule throw_statement: optional(ThrowStatementContext[138]), - rule try_statement: optional(TryStatementContext[139]), - rule unsafe_statement: optional(UnsafeStatementContext[144]), - rule using_statement: optional(UsingStatementContext[145]), - rule while_statement: optional(WhileStatementContext[146]), - rule yield_statement: optional(YieldStatementContext[147]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BreakStatementContext { - rule_index: 91, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BreakStatementContext { - rule identifier_name: optional(IdentifierNameContext[4]), - rule attribute_list_children: many(AttributeListContext[5]), - token kw_break_token: required(62, "KW_BREAK"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CheckedStatementContext { - rule_index: 92, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CheckedStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule block: required(BlockContext[32], "block"), - token kw_unchecked_token: optional(14), - token kw_checked_token: optional(27), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CommonForEachStatementContext { - rule_index: 93, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CommonForEachStatementContext { - rule for_each_statement: optional(ForEachStatementContext[94]), - rule for_each_variable_statement: optional(ForEachVariableStatementContext[95]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ForEachStatementContext { - rule_index: 94, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ForEachStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule r#type: required(TypeContext[76], "type"), - rule statement: required(StatementContext[90], "statement"), - rule expression: required(ExpressionContext[148], "expression"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_foreach_token: required(31, "KW_FOREACH"), - token kw_await_token: optional(61), - token kw_in_token: required(149, "KW_IN"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ForEachVariableStatementContext { - rule_index: 95, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ForEachVariableStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule statement: required(StatementContext[90], "statement"), - rule expression_children: many(ExpressionContext[148]), - token kw_foreach_token: required(31, "KW_FOREACH"), - token kw_await_token: optional(61), - token kw_in_token: required(149, "KW_IN"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ContinueStatementContext { - rule_index: 96, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ContinueStatementContext { - rule identifier_name: optional(IdentifierNameContext[4]), - rule attribute_list_children: many(AttributeListContext[5]), - token kw_continue_token: required(17, "KW_CONTINUE"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DoStatementContext { - rule_index: 97, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DoStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule statement: required(StatementContext[90], "statement"), - rule expression: required(ExpressionContext[148], "expression"), - token kw_while_token: required(79, "KW_WHILE"), - token kw_do_token: required(147, "KW_DO"), - token semicolon_token: required(167, "SEMICOLON"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EmptyStatementContext { - rule_index: 98, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EmptyStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionStatementContext { - rule_index: 99, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule expression: required(ExpressionContext[148], "expression"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FixedStatementContext { - rule_index: 100, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FixedStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule variable_declaration: required(VariableDeclarationContext[20], "variable_declaration"), - rule statement: required(StatementContext[90], "statement"), - token kw_fixed_token: required(69, "KW_FIXED"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ForStatementContext { - rule_index: 101, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ForStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule variable_declaration: optional(VariableDeclarationContext[20]), - rule statement: required(StatementContext[90], "statement"), - rule expression_children: many(ExpressionContext[148]), - token kw_for_token: required(109, "KW_FOR"), - token comma_tokens: many(163), - token semicolon_tokens: many(167), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GotoStatementContext { - rule_index: 102, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GotoStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule expression: optional(ExpressionContext[148]), - token kw_default_token: optional(29), - token kw_case_token: optional(84), - token kw_goto_token: required(90, "KW_GOTO"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IfStatementContext { - rule_index: 103, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IfStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule statement: required(StatementContext[90], "statement"), - rule else_clause: optional(ElseClauseContext[104]), - rule expression: required(ExpressionContext[148], "expression"), - token kw_if_token: required(148, "KW_IF"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ElseClauseContext { - rule_index: 104, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ElseClauseContext { - rule statement: required(StatementContext[90], "statement"), - token kw_else_token: required(86, "KW_ELSE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LabeledStatementContext { - rule_index: 105, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LabeledStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule statement: required(StatementContext[90], "statement"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LocalDeclarationStatementContext { - rule_index: 106, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LocalDeclarationStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule local_variable_declaration: required(LocalVariableDeclarationContext[242], "local_variable_declaration"), - token kw_await_token: optional(61), - token kw_using_token: optional(77), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LocalFunctionStatementContext { - rule_index: 107, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LocalFunctionStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule block: optional(BlockContext[32]), - rule arrow_expression_clause: optional(ArrowExpressionClauseContext[33]), - rule type_parameter_list: optional(TypeParameterListContext[38]), - rule type_parameter_constraint_clause_children: many(TypeParameterConstraintClauseContext[40]), - rule r#type: required(TypeContext[76], "type"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token semicolon_token: optional(167), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LockStatementContext { - rule_index: 108, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LockStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule statement: required(StatementContext[90], "statement"), - rule expression: required(ExpressionContext[148], "expression"), - token kw_lock_token: required(94, "KW_LOCK"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ReturnStatementContext { - rule_index: 109, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ReturnStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule expression: optional(ExpressionContext[148]), - token kw_return_token: required(47, "KW_RETURN"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchStatementContext { - rule_index: 110, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule switch_section_children: many(SwitchSectionContext[111]), - rule expression: required(ExpressionContext[148], "expression"), - token kw_switch_token: required(55, "KW_SWITCH"), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchSectionContext { - rule_index: 111, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchSectionContext { - rule statement_children: many(StatementContext[90]), - rule switch_label_children: many(SwitchLabelContext[112]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchLabelContext { - rule_index: 112, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchLabelContext { - rule case_pattern_switch_label: optional(CasePatternSwitchLabelContext[113]), - rule case_switch_label: optional(CaseSwitchLabelContext[136]), - rule default_switch_label: optional(DefaultSwitchLabelContext[137]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CasePatternSwitchLabelContext { - rule_index: 113, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CasePatternSwitchLabelContext { - rule pattern: required(PatternContext[114], "pattern"), - rule when_clause: optional(WhenClauseContext[135]), - token kw_case_token: required(84, "KW_CASE"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PatternContext { - rule_index: 114, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PatternContext { - rule pattern_children: many(PatternContext[114]), - rule constant_pattern: optional(ConstantPatternContext[115]), - rule declaration_pattern: optional(DeclarationPatternContext[116]), - rule discard_pattern: optional(DiscardPatternContext[121]), - rule list_pattern: optional(ListPatternContext[122]), - rule parenthesized_pattern: optional(ParenthesizedPatternContext[123]), - rule recursive_pattern: optional(RecursivePatternContext[124]), - rule relational_pattern: optional(RelationalPatternContext[130]), - rule slice_pattern: optional(SlicePatternContext[131]), - rule type_pattern: optional(TypePatternContext[132]), - rule unary_pattern: optional(UnaryPatternContext[133]), - rule var_pattern: optional(VarPatternContext[134]), - token kw_and_token: optional(108), - token kw_or_token: optional(152), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstantPatternContext { - rule_index: 115, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstantPatternContext { - rule expression: required(ExpressionContext[148], "expression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DeclarationPatternContext { - rule_index: 116, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DeclarationPatternContext { - rule r#type: required(TypeContext[76], "type"), - rule variable_designation: required(VariableDesignationContext[117], "variable_designation"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableDesignationContext { - rule_index: 117, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableDesignationContext { - rule discard_designation: optional(DiscardDesignationContext[118]), - rule parenthesized_variable_designation: optional(ParenthesizedVariableDesignationContext[119]), - rule single_variable_designation: optional(SingleVariableDesignationContext[120]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DiscardDesignationContext { - rule_index: 118, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DiscardDesignationContext { - token kw_token: required(173, "KW__"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedVariableDesignationContext { - rule_index: 119, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedVariableDesignationContext { - rule variable_designation_children: many(VariableDesignationContext[117]), - token comma_tokens: many(163), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SingleVariableDesignationContext { - rule_index: 120, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SingleVariableDesignationContext { - token kw_descending_token: optional(4), - token kw_ascending_token: optional(9), - token kw_extension_token: optional(10), - token kw_unmanaged_token: optional(15), - token kw_required_token: optional(25), - token kw_managed_token: optional(32), - token kw_orderby_token: optional(33), - token kw_partial_token: optional(34), - token kw_allows_token: optional(37), - token kw_closed_token: optional(38), - token kw_equals_token: optional(40), - token kw_global_token: optional(42), - token kw_remove_token: optional(46), - token kw_scoped_token: optional(48), - token kw_select_token: optional(50), - token kw_alias_token: optional(59), - token kw_async_token: optional(60), - token kw_await_token: optional(61), - token kw_field_token: optional(68), - token kw_group_token: optional(71), - token kw_union_token: optional(76), - token kw_where_token: optional(78), - token kw_yield_token: optional(80), - token kw_file_token: optional(88), - token kw_from_token: optional(89), - token kw_init_token: optional(91), - token kw_into_token: optional(92), - token kw_join_token: optional(93), - token kw_safe_token: optional(97), - token kw_when_token: optional(102), - token kw_with_token: optional(103), - token kw_add_token: optional(107), - token kw_get_token: optional(110), - token kw_let_token: optional(112), - token kw_set_token: optional(117), - token kw_var_token: optional(119), - token kw_u8_token: optional(141), - token kw_by_token: optional(146), - token kw_on_token: optional(151), - token kw_u8_lower_token: optional(153), - token kw_token: optional(173), - token kw_record_token: optional(176), - token identifier_token: optional(177), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DiscardPatternContext { - rule_index: 121, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DiscardPatternContext { - token kw_token: required(173, "KW__"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ListPatternContext { - rule_index: 122, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ListPatternContext { - rule pattern_children: many(PatternContext[114]), - rule variable_designation: optional(VariableDesignationContext[117]), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedPatternContext { - rule_index: 123, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedPatternContext { - rule pattern: required(PatternContext[114], "pattern"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecursivePatternContext { - rule_index: 124, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecursivePatternContext { - rule r#type: optional(TypeContext[76]), - rule variable_designation: optional(VariableDesignationContext[117]), - rule positional_pattern_clause: optional(PositionalPatternClauseContext[125]), - rule property_pattern_clause: optional(PropertyPatternClauseContext[129]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PositionalPatternClauseContext { - rule_index: 125, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PositionalPatternClauseContext { - rule subpattern_children: many(SubpatternContext[126]), - token comma_tokens: many(163), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SubpatternContext { - rule_index: 126, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SubpatternContext { - rule pattern: required(PatternContext[114], "pattern"), - rule base_expression_colon: optional(BaseExpressionColonContext[127]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseExpressionColonContext { - rule_index: 127, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseExpressionColonContext { - rule name_colon: optional(NameColonContext[15]), - rule expression_colon: optional(ExpressionColonContext[128]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionColonContext { - rule_index: 128, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionColonContext { - rule expression: required(ExpressionContext[148], "expression"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PropertyPatternClauseContext { - rule_index: 129, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PropertyPatternClauseContext { - rule subpattern_children: many(SubpatternContext[126]), - token comma_tokens: many(163), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RelationalPatternContext { - rule_index: 130, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RelationalPatternContext { - rule expression: required(ExpressionContext[148], "expression"), - token ne_token: optional(120), - token le_token: optional(136), - token eq_eq_token: optional(137), - token ge_token: optional(139), - token lt_token: optional(168), - token gt_token: optional(170), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SlicePatternContext { - rule_index: 131, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SlicePatternContext { - rule pattern: optional(PatternContext[114]), - token dot_dot_token: required(130, "DOT_DOT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypePatternContext { - rule_index: 132, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypePatternContext { - rule r#type: required(TypeContext[76], "type"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnaryPatternContext { - rule_index: 133, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnaryPatternContext { - rule pattern: required(PatternContext[114], "pattern"), - token kw_not_token: required(114, "KW_NOT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VarPatternContext { - rule_index: 134, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VarPatternContext { - rule variable_designation: required(VariableDesignationContext[117], "variable_designation"), - token kw_var_token: required(119, "KW_VAR"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhenClauseContext { - rule_index: 135, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhenClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_when_token: required(102, "KW_WHEN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CaseSwitchLabelContext { - rule_index: 136, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CaseSwitchLabelContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_case_token: required(84, "KW_CASE"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DefaultSwitchLabelContext { - rule_index: 137, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DefaultSwitchLabelContext { - token kw_default_token: required(29, "KW_DEFAULT"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ThrowStatementContext { - rule_index: 138, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ThrowStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule expression: optional(ExpressionContext[148]), - token kw_throw_token: required(74, "KW_THROW"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TryStatementContext { - rule_index: 139, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TryStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule block: required(BlockContext[32], "block"), - rule catch_clause_children: many(CatchClauseContext[140]), - rule finally_clause: optional(FinallyClauseContext[143]), - token kw_try_token: required(118, "KW_TRY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CatchClauseContext { - rule_index: 140, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CatchClauseContext { - rule block: required(BlockContext[32], "block"), - rule catch_declaration: optional(CatchDeclarationContext[141]), - rule catch_filter_clause: optional(CatchFilterClauseContext[142]), - token kw_catch_token: required(63, "KW_CATCH"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CatchDeclarationContext { - rule_index: 141, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CatchDeclarationContext { - rule r#type: required(TypeContext[76], "type"), - rule identifier_token: optional(IdentifierTokenContext[221]), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CatchFilterClauseContext { - rule_index: 142, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CatchFilterClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_when_token: required(102, "KW_WHEN"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FinallyClauseContext { - rule_index: 143, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FinallyClauseContext { - rule block: required(BlockContext[32], "block"), - token kw_finally_token: required(30, "KW_FINALLY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnsafeStatementContext { - rule_index: 144, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnsafeStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule block: required(BlockContext[32], "block"), - token kw_unsafe_token: required(57, "KW_UNSAFE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UsingStatementContext { - rule_index: 145, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UsingStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule variable_declaration: optional(VariableDeclarationContext[20]), - rule statement: required(StatementContext[90], "statement"), - rule expression: optional(ExpressionContext[148]), - token kw_await_token: optional(61), - token kw_using_token: required(77, "KW_USING"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhileStatementContext { - rule_index: 146, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhileStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule statement: required(StatementContext[90], "statement"), - rule expression: required(ExpressionContext[148], "expression"), - token kw_while_token: required(79, "KW_WHILE"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct YieldStatementContext { - rule_index: 147, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - YieldStatementContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule expression: optional(ExpressionContext[148]), - token kw_return_token: optional(47), - token kw_break_token: optional(62), - token kw_yield_token: required(80, "KW_YIELD"), - token semicolon_token: required(167, "SEMICOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionContext { - rule_index: 148, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionContext { - rule simple_name: optional(SimpleNameContext[10]), - rule bracketed_argument_list: optional(BracketedArgumentListContext[22]), - rule argument_list: optional(ArgumentListContext[31]), - rule r#type: optional(TypeContext[76]), - rule pattern: optional(PatternContext[114]), - rule expression_children: many(ExpressionContext[148]), - rule anonymous_function_expression: optional(AnonymousFunctionExpressionContext[149]), - rule anonymous_object_creation_expression: optional(AnonymousObjectCreationExpressionContext[154]), - rule array_creation_expression: optional(ArrayCreationExpressionContext[156]), - rule initializer_expression: optional(InitializerExpressionContext[157]), - rule await_expression: optional(AwaitExpressionContext[158]), - rule base_object_creation_expression: optional(BaseObjectCreationExpressionContext[159]), - rule cast_expression: optional(CastExpressionContext[162]), - rule checked_expression: optional(CheckedExpressionContext[163]), - rule collection_expression: optional(CollectionExpressionContext[164]), - rule declaration_expression: optional(DeclarationExpressionContext[169]), - rule default_expression: optional(DefaultExpressionContext[170]), - rule element_binding_expression: optional(ElementBindingExpressionContext[171]), - rule field_expression: optional(FieldExpressionContext[172]), - rule implicit_array_creation_expression: optional(ImplicitArrayCreationExpressionContext[173]), - rule implicit_element_access: optional(ImplicitElementAccessContext[174]), - rule implicit_stack_alloc_array_creation_expression: optional(ImplicitStackAllocArrayCreationExpressionContext[175]), - rule instance_expression: optional(InstanceExpressionContext[176]), - rule interpolated_string_expression: optional(InterpolatedStringExpressionContext[179]), - rule literal_expression: optional(LiteralExpressionContext[188]), - rule make_ref_expression: optional(MakeRefExpressionContext[192]), - rule member_binding_expression: optional(MemberBindingExpressionContext[193]), - rule parenthesized_expression: optional(ParenthesizedExpressionContext[194]), - rule prefix_unary_expression: optional(PrefixUnaryExpressionContext[195]), - rule query_expression: optional(QueryExpressionContext[196]), - rule ref_expression: optional(RefExpressionContext[210]), - rule ref_type_expression: optional(RefTypeExpressionContext[211]), - rule ref_value_expression: optional(RefValueExpressionContext[212]), - rule size_of_expression: optional(SizeOfExpressionContext[213]), - rule stack_alloc_array_creation_expression: optional(StackAllocArrayCreationExpressionContext[214]), - rule switch_expression_arm_children: many(SwitchExpressionArmContext[215]), - rule throw_expression: optional(ThrowExpressionContext[216]), - rule tuple_expression: optional(TupleExpressionContext[217]), - rule type_of_expression: optional(TypeOfExpressionContext[218]), - rule unsafe_expression: optional(UnsafeExpressionContext[219]), - rule right_shift: optional(RightShiftContext[238]), - rule unsigned_right_shift: optional(UnsignedRightShiftContext[239]), - rule right_shift_assignment: optional(RightShiftAssignmentContext[240]), - rule unsigned_right_shift_assignment: optional(UnsignedRightShiftAssignmentContext[241]), - token kw_switch_token: optional(55), - token kw_with_token: optional(103), - token lt_lt_eq_token: optional(105), - token question_question_eq_token: optional(106), - token ne_token: optional(120), - token percent_eq_token: optional(121), - token amp_amp_token: optional(122), - token amp_eq_token: optional(123), - token star_eq_token: optional(124), - token plus_plus_token: optional(125), - token plus_eq_token: optional(126), - token minus_minus_token: optional(127), - token minus_eq_token: optional(128), - token minus_gt_token: optional(129), - token dot_dot_token: optional(130), - token slash_eq_token: optional(131), - token lt_lt_token: optional(135), - token le_token: optional(136), - token eq_eq_token: optional(137), - token ge_token: optional(139), - token question_question_token: optional(140), - token caret_eq_token: optional(144), - token kw_as_token: optional(145), - token kw_is_token: optional(150), - token pipe_eq_token: optional(154), - token pipe_pipe_token: optional(155), - token bang_token: optional(156), - token percent_token: optional(159), - token amp_token: optional(160), - token star_token: optional(161), - token plus_token: optional(162), - token comma_tokens: many(163), - token minus_token: optional(164), - token dot_token: optional(165), - token slash_token: optional(166), - token lt_token: optional(168), - token eq_token: optional(169), - token gt_token: optional(170), - token question_token: optional(171), - token caret_token: optional(172), - token pipe_token: optional(174), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - token colon_token: optional(199), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnonymousFunctionExpressionContext { - rule_index: 149, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnonymousFunctionExpressionContext { - rule anonymous_method_expression: optional(AnonymousMethodExpressionContext[150]), - rule lambda_expression: optional(LambdaExpressionContext[151]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnonymousMethodExpressionContext { - rule_index: 150, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnonymousMethodExpressionContext { - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: optional(ParameterListContext[28]), - rule block: required(BlockContext[32], "block"), - rule expression: optional(ExpressionContext[148]), - token kw_delegate_token: required(18, "KW_DELEGATE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaExpressionContext { - rule_index: 151, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaExpressionContext { - rule parenthesized_lambda_expression: optional(ParenthesizedLambdaExpressionContext[152]), - rule simple_lambda_expression: optional(SimpleLambdaExpressionContext[153]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedLambdaExpressionContext { - rule_index: 152, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedLambdaExpressionContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule parameter_list: required(ParameterListContext[28], "parameter_list"), - rule block: optional(BlockContext[32]), - rule r#type: optional(TypeContext[76]), - rule expression: optional(ExpressionContext[148]), - token arrow_token: required(138, "ARROW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SimpleLambdaExpressionContext { - rule_index: 153, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SimpleLambdaExpressionContext { - rule attribute_list_children: many(AttributeListContext[5]), - rule modifier_children: many(ModifierContext[19]), - rule block: optional(BlockContext[32]), - rule expression: optional(ExpressionContext[148]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token arrow_token: required(138, "ARROW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnonymousObjectCreationExpressionContext { - rule_index: 154, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnonymousObjectCreationExpressionContext { - rule anonymous_object_member_declarator_children: many(AnonymousObjectMemberDeclaratorContext[155]), - token kw_new_token: required(113, "KW_NEW"), - token comma_tokens: many(163), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnonymousObjectMemberDeclaratorContext { - rule_index: 155, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnonymousObjectMemberDeclaratorContext { - rule name_equals: optional(NameEqualsContext[3]), - rule expression: required(ExpressionContext[148], "expression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArrayCreationExpressionContext { - rule_index: 156, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArrayCreationExpressionContext { - rule array_type: required(ArrayTypeContext[77], "array_type"), - rule initializer_expression: optional(InitializerExpressionContext[157]), - token kw_new_token: required(113, "KW_NEW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InitializerExpressionContext { - rule_index: 157, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InitializerExpressionContext { - rule expression_children: many(ExpressionContext[148]), - token comma_tokens: many(163), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AwaitExpressionContext { - rule_index: 158, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AwaitExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_await_token: required(61, "KW_AWAIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseObjectCreationExpressionContext { - rule_index: 159, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseObjectCreationExpressionContext { - rule implicit_object_creation_expression: optional(ImplicitObjectCreationExpressionContext[160]), - rule object_creation_expression: optional(ObjectCreationExpressionContext[161]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImplicitObjectCreationExpressionContext { - rule_index: 160, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImplicitObjectCreationExpressionContext { - rule argument_list: required(ArgumentListContext[31], "argument_list"), - rule initializer_expression: optional(InitializerExpressionContext[157]), - token kw_new_token: required(113, "KW_NEW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ObjectCreationExpressionContext { - rule_index: 161, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ObjectCreationExpressionContext { - rule argument_list: optional(ArgumentListContext[31]), - rule r#type: required(TypeContext[76], "type"), - rule initializer_expression: optional(InitializerExpressionContext[157]), - token kw_new_token: required(113, "KW_NEW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CastExpressionContext { - rule_index: 162, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CastExpressionContext { - rule r#type: required(TypeContext[76], "type"), - rule expression: required(ExpressionContext[148], "expression"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CheckedExpressionContext { - rule_index: 163, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CheckedExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_unchecked_token: optional(14), - token kw_checked_token: optional(27), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CollectionExpressionContext { - rule_index: 164, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CollectionExpressionContext { - rule collection_element_children: many(CollectionElementContext[165]), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CollectionElementContext { - rule_index: 165, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CollectionElementContext { - rule expression_element: optional(ExpressionElementContext[166]), - rule spread_element: optional(SpreadElementContext[167]), - rule with_element: optional(WithElementContext[168]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionElementContext { - rule_index: 166, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionElementContext { - rule expression: required(ExpressionContext[148], "expression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SpreadElementContext { - rule_index: 167, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SpreadElementContext { - rule expression: required(ExpressionContext[148], "expression"), - token dot_dot_token: required(130, "DOT_DOT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WithElementContext { - rule_index: 168, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WithElementContext { - rule argument_list: required(ArgumentListContext[31], "argument_list"), - token kw_with_token: required(103, "KW_WITH"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DeclarationExpressionContext { - rule_index: 169, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DeclarationExpressionContext { - rule r#type: required(TypeContext[76], "type"), - rule variable_designation: required(VariableDesignationContext[117], "variable_designation"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DefaultExpressionContext { - rule_index: 170, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DefaultExpressionContext { - rule r#type: required(TypeContext[76], "type"), - token kw_default_token: required(29, "KW_DEFAULT"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ElementBindingExpressionContext { - rule_index: 171, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ElementBindingExpressionContext { - rule bracketed_argument_list: required(BracketedArgumentListContext[22], "bracketed_argument_list"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FieldExpressionContext { - rule_index: 172, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FieldExpressionContext { - token kw_field_token: required(68, "KW_FIELD"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImplicitArrayCreationExpressionContext { - rule_index: 173, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImplicitArrayCreationExpressionContext { - rule initializer_expression: required(InitializerExpressionContext[157], "initializer_expression"), - token kw_new_token: required(113, "KW_NEW"), - token comma_tokens: many(163), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImplicitElementAccessContext { - rule_index: 174, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImplicitElementAccessContext { - rule bracketed_argument_list: required(BracketedArgumentListContext[22], "bracketed_argument_list"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImplicitStackAllocArrayCreationExpressionContext { - rule_index: 175, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImplicitStackAllocArrayCreationExpressionContext { - rule initializer_expression: required(InitializerExpressionContext[157], "initializer_expression"), - token kw_stackalloc_token: required(5, "KW_STACKALLOC"), - token lbracket_token: required(202, "LBRACKET"), - token rbracket_token: required(203, "RBRACKET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InstanceExpressionContext { - rule_index: 176, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InstanceExpressionContext { - rule base_expression: optional(BaseExpressionContext[177]), - rule this_expression: optional(ThisExpressionContext[178]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BaseExpressionContext { - rule_index: 177, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BaseExpressionContext { - token kw_base_token: required(81, "KW_BASE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ThisExpressionContext { - rule_index: 178, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ThisExpressionContext { - token kw_this_token: required(98, "KW_THIS"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolatedStringExpressionContext { - rule_index: 179, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolatedStringExpressionContext { - rule interpolated_string_content_children: many(InterpolatedStringContentContext[180]), - rule interpolated_multi_line_raw_string_start_token: optional(InterpolatedMultiLineRawStringStartTokenContext[185]), - rule interpolated_raw_string_end_token: optional(InterpolatedRawStringEndTokenContext[186]), - rule interpolated_single_line_raw_string_start_token: optional(InterpolatedSingleLineRawStringStartTokenContext[187]), - token dquote_token: optional(157), - token interp_start_token: optional(194), - token interp_verbatim_start_token: optional(195), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolatedStringContentContext { - rule_index: 180, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolatedStringContentContext { - rule interpolated_string_text: optional(InterpolatedStringTextContext[181]), - rule interpolation: optional(InterpolationContext[182]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolatedStringTextContext { - rule_index: 181, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolatedStringTextContext { - rule interpolated_string_text_token: required(InterpolatedStringTextTokenContext[234], "interpolated_string_text_token"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolationContext { - rule_index: 182, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolationContext { - rule expression: required(ExpressionContext[148], "expression"), - rule interpolation_alignment_clause: optional(InterpolationAlignmentClauseContext[183]), - rule interpolation_format_clause: optional(InterpolationFormatClauseContext[184]), - token lbrace_token: required(197, "LBRACE"), - token rbrace_token: required(198, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolationAlignmentClauseContext { - rule_index: 183, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolationAlignmentClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - token comma_token: required(163, "COMMA"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolationFormatClauseContext { - rule_index: 184, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolationFormatClauseContext { - rule interpolated_string_text_token: required(InterpolatedStringTextTokenContext[234], "interpolated_string_text_token"), - token colon_token: required(199, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolatedMultiLineRawStringStartTokenContext { - rule_index: 185, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolatedMultiLineRawStringStartTokenContext { - token interp_raw_start_token: required(196, "INTERP_RAW_START"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolatedRawStringEndTokenContext { - rule_index: 186, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolatedRawStringEndTokenContext { - token triple_dquote_token: required(104, "TRIPLE_DQUOTE"), - token dquote_tokens: many(157), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolatedSingleLineRawStringStartTokenContext { - rule_index: 187, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolatedSingleLineRawStringStartTokenContext { - token interp_raw_start_token: required(196, "INTERP_RAW_START"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LiteralExpressionContext { - rule_index: 188, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LiteralExpressionContext { - rule utf8_multi_line_raw_string_literal_token: optional(Utf8MultiLineRawStringLiteralTokenContext[189]), - rule utf8_single_line_raw_string_literal_token: optional(Utf8SingleLineRawStringLiteralTokenContext[190]), - rule utf8_string_literal_token: optional(Utf8StringLiteralTokenContext[191]), - rule numeric_literal_token: optional(NumericLiteralTokenContext[223]), - rule character_literal_token: optional(CharacterLiteralTokenContext[228]), - rule string_literal_token: optional(StringLiteralTokenContext[229]), - rule multi_line_raw_string_literal_token: optional(MultiLineRawStringLiteralTokenContext[235]), - rule single_line_raw_string_literal_token: optional(SingleLineRawStringLiteralTokenContext[236]), - token kw_arglist_token: optional(6), - token kw_default_token: optional(29), - token kw_false_token: optional(67), - token kw_null_token: optional(96), - token kw_true_token: optional(99), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct Utf8MultiLineRawStringLiteralTokenContext { - rule_index: 189, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - Utf8MultiLineRawStringLiteralTokenContext { - rule multi_line_raw_string_literal_token: required(MultiLineRawStringLiteralTokenContext[235], "multi_line_raw_string_literal_token"), - token kw_u8_token: optional(141), - token kw_u8_lower_token: optional(153), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct Utf8SingleLineRawStringLiteralTokenContext { - rule_index: 190, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - Utf8SingleLineRawStringLiteralTokenContext { - rule single_line_raw_string_literal_token: required(SingleLineRawStringLiteralTokenContext[236], "single_line_raw_string_literal_token"), - token kw_u8_token: optional(141), - token kw_u8_lower_token: optional(153), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct Utf8StringLiteralTokenContext { - rule_index: 191, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - Utf8StringLiteralTokenContext { - rule string_literal_token: required(StringLiteralTokenContext[229], "string_literal_token"), - token kw_u8_token: optional(141), - token kw_u8_lower_token: optional(153), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MakeRefExpressionContext { - rule_index: 192, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MakeRefExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_makeref_token: required(7, "KW___MAKEREF"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MemberBindingExpressionContext { - rule_index: 193, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MemberBindingExpressionContext { - rule simple_name: required(SimpleNameContext[10], "simple_name"), - token dot_token: required(165, "DOT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedExpressionContext { - rule_index: 194, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrefixUnaryExpressionContext { - rule_index: 195, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrefixUnaryExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token plus_plus_token: optional(125), - token minus_minus_token: optional(127), - token bang_token: optional(156), - token amp_token: optional(160), - token star_token: optional(161), - token plus_token: optional(162), - token minus_token: optional(164), - token caret_token: optional(172), - token tilde_token: optional(175), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct QueryExpressionContext { - rule_index: 196, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - QueryExpressionContext { - rule from_clause: required(FromClauseContext[197], "from_clause"), - rule query_body: required(QueryBodyContext[198], "query_body"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FromClauseContext { - rule_index: 197, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FromClauseContext { - rule r#type: optional(TypeContext[76]), - rule expression: required(ExpressionContext[148], "expression"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_from_token: required(89, "KW_FROM"), - token kw_in_token: required(149, "KW_IN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct QueryBodyContext { - rule_index: 198, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - QueryBodyContext { - rule query_clause_children: many(QueryClauseContext[199]), - rule select_or_group_clause: required(SelectOrGroupClauseContext[206], "select_or_group_clause"), - rule query_continuation: optional(QueryContinuationContext[209]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct QueryClauseContext { - rule_index: 199, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - QueryClauseContext { - rule from_clause: optional(FromClauseContext[197]), - rule join_clause: optional(JoinClauseContext[200]), - rule let_clause: optional(LetClauseContext[202]), - rule order_by_clause: optional(OrderByClauseContext[203]), - rule where_clause: optional(WhereClauseContext[205]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct JoinClauseContext { - rule_index: 200, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - JoinClauseContext { - rule r#type: optional(TypeContext[76]), - rule expression_children: many(ExpressionContext[148]), - rule join_into_clause: optional(JoinIntoClauseContext[201]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_equals_token: required(40, "KW_EQUALS"), - token kw_join_token: required(93, "KW_JOIN"), - token kw_in_token: required(149, "KW_IN"), - token kw_on_token: required(151, "KW_ON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct JoinIntoClauseContext { - rule_index: 201, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - JoinIntoClauseContext { - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_into_token: required(92, "KW_INTO"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LetClauseContext { - rule_index: 202, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LetClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_let_token: required(112, "KW_LET"), - token eq_token: required(169, "EQ"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct OrderByClauseContext { - rule_index: 203, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - OrderByClauseContext { - rule ordering_children: many(OrderingContext[204]), - token kw_orderby_token: required(33, "KW_ORDERBY"), - token comma_tokens: many(163), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct OrderingContext { - rule_index: 204, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - OrderingContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_descending_token: optional(4), - token kw_ascending_token: optional(9), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhereClauseContext { - rule_index: 205, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhereClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_where_token: required(78, "KW_WHERE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SelectOrGroupClauseContext { - rule_index: 206, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SelectOrGroupClauseContext { - rule group_clause: optional(GroupClauseContext[207]), - rule select_clause: optional(SelectClauseContext[208]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GroupClauseContext { - rule_index: 207, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GroupClauseContext { - rule expression_children: many(ExpressionContext[148]), - token kw_group_token: required(71, "KW_GROUP"), - token kw_by_token: required(146, "KW_BY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SelectClauseContext { - rule_index: 208, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SelectClauseContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_select_token: required(50, "KW_SELECT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct QueryContinuationContext { - rule_index: 209, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - QueryContinuationContext { - rule query_body: required(QueryBodyContext[198], "query_body"), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - token kw_into_token: required(92, "KW_INTO"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RefExpressionContext { - rule_index: 210, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RefExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_ref_token: required(116, "KW_REF"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RefTypeExpressionContext { - rule_index: 211, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RefTypeExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_reftype_token: required(8, "KW___REFTYPE"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RefValueExpressionContext { - rule_index: 212, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RefValueExpressionContext { - rule r#type: required(TypeContext[76], "type"), - rule expression: required(ExpressionContext[148], "expression"), - token kw_refvalue_token: required(3, "KW___REFVALUE"), - token comma_token: required(163, "COMMA"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SizeOfExpressionContext { - rule_index: 213, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SizeOfExpressionContext { - rule r#type: required(TypeContext[76], "type"), - token kw_sizeof_token: required(51, "KW_SIZEOF"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StackAllocArrayCreationExpressionContext { - rule_index: 214, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StackAllocArrayCreationExpressionContext { - rule r#type: required(TypeContext[76], "type"), - rule initializer_expression: optional(InitializerExpressionContext[157]), - token kw_stackalloc_token: required(5, "KW_STACKALLOC"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchExpressionArmContext { - rule_index: 215, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchExpressionArmContext { - rule pattern: required(PatternContext[114], "pattern"), - rule when_clause: optional(WhenClauseContext[135]), - rule expression: required(ExpressionContext[148], "expression"), - token arrow_token: required(138, "ARROW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ThrowExpressionContext { - rule_index: 216, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ThrowExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_throw_token: required(74, "KW_THROW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TupleExpressionContext { - rule_index: 217, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TupleExpressionContext { - rule argument_children: many(ArgumentContext[23]), - token comma_tokens: many(163), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeOfExpressionContext { - rule_index: 218, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeOfExpressionContext { - rule r#type: required(TypeContext[76], "type"), - token kw_typeof_token: required(56, "KW_TYPEOF"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnsafeExpressionContext { - rule_index: 219, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnsafeExpressionContext { - rule expression: required(ExpressionContext[148], "expression"), - token kw_unsafe_token: required(57, "KW_UNSAFE"), - token lparen_token: required(200, "LPAREN"), - token rparen_token: required(201, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SyntaxTokenContext { - rule_index: 220, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SyntaxTokenContext { - rule identifier_token: optional(IdentifierTokenContext[221]), - rule keyword: optional(KeywordContext[222]), - rule numeric_literal_token: optional(NumericLiteralTokenContext[223]), - rule character_literal_token: optional(CharacterLiteralTokenContext[228]), - rule string_literal_token: optional(StringLiteralTokenContext[229]), - rule operator_token: optional(OperatorTokenContext[232]), - rule punctuation_token: optional(PunctuationTokenContext[233]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IdentifierTokenContext { - rule_index: 221, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IdentifierTokenContext { - token kw_descending_token: optional(4), - token kw_ascending_token: optional(9), - token kw_extension_token: optional(10), - token kw_unmanaged_token: optional(15), - token kw_required_token: optional(25), - token kw_managed_token: optional(32), - token kw_orderby_token: optional(33), - token kw_partial_token: optional(34), - token kw_allows_token: optional(37), - token kw_closed_token: optional(38), - token kw_equals_token: optional(40), - token kw_global_token: optional(42), - token kw_remove_token: optional(46), - token kw_scoped_token: optional(48), - token kw_select_token: optional(50), - token kw_alias_token: optional(59), - token kw_async_token: optional(60), - token kw_await_token: optional(61), - token kw_field_token: optional(68), - token kw_group_token: optional(71), - token kw_union_token: optional(76), - token kw_where_token: optional(78), - token kw_yield_token: optional(80), - token kw_file_token: optional(88), - token kw_from_token: optional(89), - token kw_init_token: optional(91), - token kw_into_token: optional(92), - token kw_join_token: optional(93), - token kw_safe_token: optional(97), - token kw_when_token: optional(102), - token kw_with_token: optional(103), - token kw_add_token: optional(107), - token kw_and_token: optional(108), - token kw_get_token: optional(110), - token kw_let_token: optional(112), - token kw_not_token: optional(114), - token kw_set_token: optional(117), - token kw_var_token: optional(119), - token kw_u8_token: optional(141), - token kw_by_token: optional(146), - token kw_on_token: optional(151), - token kw_or_token: optional(152), - token kw_u8_lower_token: optional(153), - token kw_token: optional(173), - token kw_record_token: optional(176), - token identifier_token: optional(177), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct KeywordContext { - rule_index: 222, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - KeywordContext { - rule modifier: optional(ModifierContext[19]), - token kw_refvalue_token: optional(3), - token kw_stackalloc_token: optional(5), - token kw_arglist_token: optional(6), - token kw_makeref_token: optional(7), - token kw_reftype_token: optional(8), - token kw_interface_token: optional(11), - token kw_namespace_token: optional(12), - token kw_unchecked_token: optional(14), - token kw_continue_token: optional(17), - token kw_delegate_token: optional(18), - token kw_explicit_token: optional(19), - token kw_implicit_token: optional(20), - token kw_operator_token: optional(22), - token kw_checked_token: optional(27), - token kw_decimal_token: optional(28), - token kw_default_token: optional(29), - token kw_finally_token: optional(30), - token kw_foreach_token: optional(31), - token kw_double_token: optional(39), - token kw_object_token: optional(43), - token kw_params_token: optional(44), - token kw_return_token: optional(47), - token kw_sizeof_token: optional(51), - token kw_string_token: optional(53), - token kw_struct_token: optional(54), - token kw_switch_token: optional(55), - token kw_typeof_token: optional(56), - token kw_ushort_token: optional(58), - token kw_break_token: optional(62), - token kw_catch_token: optional(63), - token kw_class_token: optional(64), - token kw_event_token: optional(66), - token kw_false_token: optional(67), - token kw_float_token: optional(70), - token kw_sbyte_token: optional(72), - token kw_short_token: optional(73), - token kw_throw_token: optional(74), - token kw_ulong_token: optional(75), - token kw_using_token: optional(77), - token kw_while_token: optional(79), - token kw_base_token: optional(81), - token kw_bool_token: optional(82), - token kw_byte_token: optional(83), - token kw_case_token: optional(84), - token kw_char_token: optional(85), - token kw_else_token: optional(86), - token kw_enum_token: optional(87), - token kw_goto_token: optional(90), - token kw_lock_token: optional(94), - token kw_long_token: optional(95), - token kw_null_token: optional(96), - token kw_this_token: optional(98), - token kw_true_token: optional(99), - token kw_uint_token: optional(100), - token kw_void_token: optional(101), - token kw_for_token: optional(109), - token kw_int_token: optional(111), - token kw_out_token: optional(115), - token kw_try_token: optional(118), - token kw_as_token: optional(145), - token kw_do_token: optional(147), - token kw_if_token: optional(148), - token kw_in_token: optional(149), - token kw_is_token: optional(150), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NumericLiteralTokenContext { - rule_index: 223, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NumericLiteralTokenContext { - rule integer_literal_token: optional(IntegerLiteralTokenContext[224]), - rule real_literal_token: optional(RealLiteralTokenContext[227]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IntegerLiteralTokenContext { - rule_index: 224, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IntegerLiteralTokenContext { - rule decimal_integer_literal_token: optional(DecimalIntegerLiteralTokenContext[225]), - rule hexadecimal_integer_literal_token: optional(HexadecimalIntegerLiteralTokenContext[226]), - token bin_int_lit_token: optional(180), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DecimalIntegerLiteralTokenContext { - rule_index: 225, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DecimalIntegerLiteralTokenContext { - token dec_int_lit_token: required(178, "DEC_INT_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct HexadecimalIntegerLiteralTokenContext { - rule_index: 226, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - HexadecimalIntegerLiteralTokenContext { - token hex_int_lit_token: required(179, "HEX_INT_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RealLiteralTokenContext { - rule_index: 227, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RealLiteralTokenContext { - token real_lit_token: required(181, "REAL_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CharacterLiteralTokenContext { - rule_index: 228, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CharacterLiteralTokenContext { - token char_lit_token: required(182, "CHAR_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StringLiteralTokenContext { - rule_index: 229, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StringLiteralTokenContext { - rule regular_string_literal_token: optional(RegularStringLiteralTokenContext[230]), - rule verbatim_string_literal_token: optional(VerbatimStringLiteralTokenContext[231]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RegularStringLiteralTokenContext { - rule_index: 230, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RegularStringLiteralTokenContext { - token string_lit_token: required(183, "STRING_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VerbatimStringLiteralTokenContext { - rule_index: 231, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VerbatimStringLiteralTokenContext { - token verbatim_string_lit_token: required(184, "VERBATIM_STRING_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct OperatorTokenContext { - rule_index: 232, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - OperatorTokenContext { - rule right_shift: optional(RightShiftContext[238]), - rule unsigned_right_shift: optional(UnsignedRightShiftContext[239]), - rule right_shift_assignment: optional(RightShiftAssignmentContext[240]), - rule unsigned_right_shift_assignment: optional(UnsignedRightShiftAssignmentContext[241]), - token lt_lt_eq_token: optional(105), - token question_question_eq_token: optional(106), - token ne_token: optional(120), - token percent_eq_token: optional(121), - token amp_amp_token: optional(122), - token amp_eq_token: optional(123), - token star_eq_token: optional(124), - token plus_plus_token: optional(125), - token plus_eq_token: optional(126), - token minus_minus_token: optional(127), - token minus_eq_token: optional(128), - token slash_eq_token: optional(131), - token lt_lt_token: optional(135), - token le_token: optional(136), - token eq_eq_token: optional(137), - token ge_token: optional(139), - token question_question_token: optional(140), - token caret_eq_token: optional(144), - token kw_as_token: optional(145), - token kw_is_token: optional(150), - token pipe_eq_token: optional(154), - token pipe_pipe_token: optional(155), - token bang_token: optional(156), - token percent_token: optional(159), - token amp_token: optional(160), - token star_token: optional(161), - token plus_token: optional(162), - token minus_token: optional(164), - token slash_token: optional(166), - token lt_token: optional(168), - token eq_token: optional(169), - token gt_token: optional(170), - token caret_token: optional(172), - token pipe_token: optional(174), - token tilde_token: optional(175), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PunctuationTokenContext { - rule_index: 233, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PunctuationTokenContext { - token minus_gt_token: optional(129), - token dot_dot_token: optional(130), - token slash_gt_token: optional(132), - token colon_colon_token: optional(133), - token lt_slash_token: optional(134), - token arrow_token: optional(138), - token escaped_quote_token: optional(142), - token escaped_backslash_token: optional(143), - token dquote_token: optional(157), - token hash_token: optional(158), - token comma_token: optional(163), - token dot_token: optional(165), - token semicolon_token: optional(167), - token question_token: optional(171), - token lbrace_token: optional(197), - token rbrace_token: optional(198), - token colon_token: optional(199), - token lparen_token: optional(200), - token rparen_token: optional(201), - token lbracket_token: optional(202), - token rbracket_token: optional(203), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterpolatedStringTextTokenContext { - rule_index: 234, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterpolatedStringTextTokenContext { - token interpolated_text_token: required(1, "INTERPOLATED_TEXT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiLineRawStringLiteralTokenContext { - rule_index: 235, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiLineRawStringLiteralTokenContext { - token ml_raw_string_lit_token: required(186, "ML_RAW_STRING_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SingleLineRawStringLiteralTokenContext { - rule_index: 236, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SingleLineRawStringLiteralTokenContext { - token sl_raw_string_lit_token: required(185, "SL_RAW_STRING_LIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecordKeywordContext { - rule_index: 237, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecordKeywordContext { - token kw_record_token: required(176, "KW_RECORD"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RightShiftContext { - rule_index: 238, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RightShiftContext { - token gt_tokens: many(170), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnsignedRightShiftContext { - rule_index: 239, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnsignedRightShiftContext { - token gt_tokens: many(170), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RightShiftAssignmentContext { - rule_index: 240, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RightShiftAssignmentContext { - token ge_token: required(139, "GE"), - token gt_token: required(170, "GT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnsignedRightShiftAssignmentContext { - rule_index: 241, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnsignedRightShiftAssignmentContext { - token ge_token: required(139, "GE"), - token gt_tokens: many(170), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LocalVariableDeclarationContext { - rule_index: 242, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LocalVariableDeclarationContext { - rule r#type: required(TypeContext[76], "type"), - rule local_variable_declarator_children: many(LocalVariableDeclaratorContext[243]), - token comma_tokens: many(163), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LocalVariableDeclaratorContext { - rule_index: 243, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LocalVariableDeclaratorContext { - rule equals_value_clause: optional(EqualsValueClauseContext[24]), - rule identifier_token: required(IdentifierTokenContext[221], "identifier_token"), - } -} - -/// Checks generated required-child invariants without changing the -/// recovery-oriented tree's type. -/// -/// Strict parsing calls this after proving that lexer and parser syntax-error -/// counts are both zero. It is public so structural runtime/codegen invariant -/// failures can be diagnosed independently. -pub fn validate_tree_structure( - parsed: &antlr4_runtime::ParsedFile, -) -> Result<(), CSharpValidationError> { - let tree = parsed.tree(); - if tree.as_rule().is_none() { - return Err(CSharpValidationError::InvalidRoot); - } - for node in tree.descendants() { - match node.kind() { - antlr4_runtime::NodeKind::Terminal => {} - antlr4_runtime::NodeKind::Error => { - let symbol = node - .as_error() - .expect("error node kind checked") - .symbol(); - return Err(CSharpValidationError::RecoveredErrorNode { - line: symbol.line(), - column: symbol.column(), - text: symbol.text_or_empty().to_owned(), - }); - } - antlr4_runtime::NodeKind::Rule => { - let context = node.as_rule().expect("rule node kind checked"); - match __context_kind(context) { - 0 => { - let context = CompilationUnitContext::__from_listener_node(context, None); - context.eof_token()?; - }, - 1 => { - let context = ExternAliasDirectiveContext::__from_listener_node(context, None); - context.identifier_token()?; - context.kw_extern_token()?; - context.kw_alias_token()?; - context.semicolon_token()?; - }, - 2 => { - let context = UsingDirectiveContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_using_token()?; - context.semicolon_token()?; - }, - 3 => { - let context = NameEqualsContext::__from_listener_node(context, None); - context.identifier_name()?; - context.eq_token()?; - }, - 4 => { - }, - 5 => { - let context = AttributeListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.attribute_children().count(), 1, "AttributeListContext", "attribute")?; - context.lbracket_token()?; - context.rbracket_token()?; - }, - 6 => { - let context = AttributeTargetSpecifierContext::__from_listener_node(context, None); - context.syntax_token()?; - context.colon_token()?; - }, - 7 => { - let context = AttributeContext::__from_listener_node(context, None); - context.name()?; - }, - 8 => { - }, - 9 => { - let context = AliasQualifiedNameContext::__from_listener_node(context, None); - context.identifier_name()?; - context.simple_name()?; - context.colon_colon_token()?; - }, - 10 => { - }, - 11 => { - let context = GenericNameContext::__from_listener_node(context, None); - context.type_argument_list()?; - context.identifier_token()?; - }, - 12 => { - let context = TypeArgumentListContext::__from_listener_node(context, None); - context.lt_token()?; - context.gt_token()?; - }, - 13 => { - let context = AttributeArgumentListContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 14 => { - let context = AttributeArgumentContext::__from_listener_node(context, None); - context.expression()?; - }, - 15 => { - let context = NameColonContext::__from_listener_node(context, None); - context.identifier_name()?; - context.colon_token()?; - }, - 16 => { - }, - 17 => { - }, - 18 => { - let context = EventFieldDeclarationContext::__from_listener_node(context, None); - context.variable_declaration()?; - context.kw_event_token()?; - context.semicolon_token()?; - }, - 19 => { - }, - 20 => { - let context = VariableDeclarationContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.variable_declarator_children().count(), 1, "VariableDeclarationContext", "variable_declarator")?; - context.r#type()?; - }, - 21 => { - let context = VariableDeclaratorContext::__from_listener_node(context, None); - context.identifier_token()?; - }, - 22 => { - let context = BracketedArgumentListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.argument_children().count(), 1, "BracketedArgumentListContext", "argument")?; - context.lbracket_token()?; - context.rbracket_token()?; - }, - 23 => { - let context = ArgumentContext::__from_listener_node(context, None); - context.expression()?; - }, - 24 => { - let context = EqualsValueClauseContext::__from_listener_node(context, None); - context.expression()?; - context.eq_token()?; - }, - 25 => { - let context = FieldDeclarationContext::__from_listener_node(context, None); - context.variable_declaration()?; - context.semicolon_token()?; - }, - 26 => { - }, - 27 => { - let context = ConstructorDeclarationContext::__from_listener_node(context, None); - context.parameter_list()?; - context.identifier_token()?; - }, - 28 => { - let context = ParameterListContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 29 => { - }, - 30 => { - let context = ConstructorInitializerContext::__from_listener_node(context, None); - context.argument_list()?; - context.colon_token()?; - }, - 31 => { - let context = ArgumentListContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 32 => { - let context = BlockContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 33 => { - let context = ArrowExpressionClauseContext::__from_listener_node(context, None); - context.expression()?; - context.arrow_token()?; - }, - 34 => { - let context = ConversionOperatorDeclarationContext::__from_listener_node(context, None); - context.parameter_list()?; - context.r#type()?; - context.kw_operator_token()?; - }, - 35 => { - let context = ExplicitInterfaceSpecifierContext::__from_listener_node(context, None); - context.name()?; - context.dot_token()?; - }, - 36 => { - let context = DestructorDeclarationContext::__from_listener_node(context, None); - context.parameter_list()?; - context.identifier_token()?; - context.tilde_token()?; - }, - 37 => { - let context = MethodDeclarationContext::__from_listener_node(context, None); - context.parameter_list()?; - context.r#type()?; - context.identifier_token()?; - }, - 38 => { - let context = TypeParameterListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_parameter_children().count(), 1, "TypeParameterListContext", "type_parameter")?; - context.lt_token()?; - context.gt_token()?; - }, - 39 => { - let context = TypeParameterContext::__from_listener_node(context, None); - context.identifier_token()?; - }, - 40 => { - let context = TypeParameterConstraintClauseContext::__from_listener_node(context, None); - context.identifier_name()?; - antlr4_runtime::require_min_count(context.type_parameter_constraint_children().count(), 1, "TypeParameterConstraintClauseContext", "type_parameter_constraint")?; - context.kw_where_token()?; - context.colon_token()?; - }, - 41 => { - }, - 42 => { - let context = AllowsConstraintClauseContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.allows_constraint_children().count(), 1, "AllowsConstraintClauseContext", "allows_constraint")?; - context.kw_allows_token()?; - }, - 43 => { - let context = AllowsConstraintContext::__from_listener_node(context, None); - context.ref_struct_constraint()?; - }, - 44 => { - let context = RefStructConstraintContext::__from_listener_node(context, None); - context.kw_struct_token()?; - context.kw_ref_token()?; - }, - 45 => { - }, - 46 => { - let context = ConstructorConstraintContext::__from_listener_node(context, None); - context.kw_new_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 47 => { - let context = DefaultConstraintContext::__from_listener_node(context, None); - context.kw_default_token()?; - }, - 48 => { - let context = TypeConstraintContext::__from_listener_node(context, None); - context.r#type()?; - }, - 49 => { - let context = OperatorDeclarationContext::__from_listener_node(context, None); - context.parameter_list()?; - context.r#type()?; - context.kw_operator_token()?; - }, - 50 => { - }, - 51 => { - let context = FileScopedNamespaceDeclarationContext::__from_listener_node(context, None); - context.name()?; - context.kw_namespace_token()?; - context.semicolon_token()?; - }, - 52 => { - let context = NamespaceDeclarationContext::__from_listener_node(context, None); - context.name()?; - context.kw_namespace_token()?; - context.lbrace_token()?; - context.rbrace_token()?; - }, - 53 => { - }, - 54 => { - let context = EventDeclarationContext::__from_listener_node(context, None); - context.r#type()?; - context.identifier_token()?; - context.kw_event_token()?; - }, - 55 => { - let context = AccessorListContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 56 => { - }, - 57 => { - let context = IndexerDeclarationContext::__from_listener_node(context, None); - context.bracketed_parameter_list()?; - context.r#type()?; - context.kw_this_token()?; - }, - 58 => { - let context = BracketedParameterListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.parameter_children().count(), 1, "BracketedParameterListContext", "parameter")?; - context.lbracket_token()?; - context.rbracket_token()?; - }, - 59 => { - let context = PropertyDeclarationContext::__from_listener_node(context, None); - context.r#type()?; - context.identifier_token()?; - }, - 60 => { - }, - 61 => { - let context = EnumDeclarationContext::__from_listener_node(context, None); - context.identifier_token()?; - context.kw_enum_token()?; - }, - 62 => { - let context = BaseListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.base_type_children().count(), 1, "BaseListContext", "base_type")?; - context.colon_token()?; - }, - 63 => { - }, - 64 => { - let context = PrimaryConstructorBaseTypeContext::__from_listener_node(context, None); - context.argument_list()?; - context.r#type()?; - }, - 65 => { - let context = SimpleBaseTypeContext::__from_listener_node(context, None); - context.r#type()?; - }, - 66 => { - let context = EnumMemberDeclarationContext::__from_listener_node(context, None); - context.identifier_token()?; - }, - 67 => { - }, - 68 => { - let context = ClassDeclarationContext::__from_listener_node(context, None); - context.identifier_token()?; - context.kw_class_token()?; - }, - 69 => { - let context = ExtensionBlockDeclarationContext::__from_listener_node(context, None); - context.kw_extension_token()?; - context.lbrace_token()?; - context.rbrace_token()?; - }, - 70 => { - let context = InterfaceDeclarationContext::__from_listener_node(context, None); - context.identifier_token()?; - context.kw_interface_token()?; - }, - 71 => { - let context = RecordDeclarationContext::__from_listener_node(context, None); - context.identifier_token()?; - context.record_keyword()?; - }, - 72 => { - let context = StructDeclarationContext::__from_listener_node(context, None); - context.identifier_token()?; - context.kw_struct_token()?; - }, - 73 => { - let context = UnionDeclarationContext::__from_listener_node(context, None); - context.identifier_token()?; - context.kw_union_token()?; - }, - 74 => { - let context = DelegateDeclarationContext::__from_listener_node(context, None); - context.parameter_list()?; - context.r#type()?; - context.identifier_token()?; - context.kw_delegate_token()?; - context.semicolon_token()?; - }, - 75 => { - let context = GlobalStatementContext::__from_listener_node(context, None); - context.statement()?; - }, - 76 => { - }, - 77 => { - let context = ArrayTypeContext::__from_listener_node(context, None); - context.r#type()?; - antlr4_runtime::require_min_count(context.array_rank_specifier_children().count(), 1, "ArrayTypeContext", "array_rank_specifier")?; - }, - 78 => { - let context = ArrayRankSpecifierContext::__from_listener_node(context, None); - context.lbracket_token()?; - context.rbracket_token()?; - }, - 79 => { - let context = FunctionPointerTypeContext::__from_listener_node(context, None); - context.function_pointer_parameter_list()?; - context.kw_delegate_token()?; - context.star_token()?; - }, - 80 => { - }, - 81 => { - let context = FunctionPointerUnmanagedCallingConventionListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.function_pointer_unmanaged_calling_convention_children().count(), 1, "FunctionPointerUnmanagedCallingConventionListContext", "function_pointer_unmanaged_calling_convention")?; - context.lbracket_token()?; - context.rbracket_token()?; - }, - 82 => { - let context = FunctionPointerUnmanagedCallingConventionContext::__from_listener_node(context, None); - context.identifier_token()?; - }, - 83 => { - let context = FunctionPointerParameterListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.function_pointer_parameter_children().count(), 1, "FunctionPointerParameterListContext", "function_pointer_parameter")?; - context.lt_token()?; - context.gt_token()?; - }, - 84 => { - let context = FunctionPointerParameterContext::__from_listener_node(context, None); - context.r#type()?; - }, - 85 => { - }, - 86 => { - let context = RefTypeContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_ref_token()?; - }, - 87 => { - let context = ScopedTypeContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_scoped_token()?; - }, - 88 => { - let context = TupleTypeContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.tuple_element_children().count(), 2, "TupleTypeContext", "tuple_element")?; - antlr4_runtime::require_min_count(context.comma_tokens().count(), 1, "TupleTypeContext", "COMMA")?; - context.lparen_token()?; - context.rparen_token()?; - }, - 89 => { - let context = TupleElementContext::__from_listener_node(context, None); - context.r#type()?; - }, - 90 => { - }, - 91 => { - let context = BreakStatementContext::__from_listener_node(context, None); - context.kw_break_token()?; - context.semicolon_token()?; - }, - 92 => { - let context = CheckedStatementContext::__from_listener_node(context, None); - context.block()?; - }, - 93 => { - }, - 94 => { - let context = ForEachStatementContext::__from_listener_node(context, None); - context.r#type()?; - context.statement()?; - context.expression()?; - context.identifier_token()?; - context.kw_foreach_token()?; - context.kw_in_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 95 => { - let context = ForEachVariableStatementContext::__from_listener_node(context, None); - context.statement()?; - antlr4_runtime::require_min_count(context.expression_children().count(), 2, "ForEachVariableStatementContext", "expression")?; - context.kw_foreach_token()?; - context.kw_in_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 96 => { - let context = ContinueStatementContext::__from_listener_node(context, None); - context.kw_continue_token()?; - context.semicolon_token()?; - }, - 97 => { - let context = DoStatementContext::__from_listener_node(context, None); - context.statement()?; - context.expression()?; - context.kw_while_token()?; - context.kw_do_token()?; - context.semicolon_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 98 => { - let context = EmptyStatementContext::__from_listener_node(context, None); - context.semicolon_token()?; - }, - 99 => { - let context = ExpressionStatementContext::__from_listener_node(context, None); - context.expression()?; - context.semicolon_token()?; - }, - 100 => { - let context = FixedStatementContext::__from_listener_node(context, None); - context.variable_declaration()?; - context.statement()?; - context.kw_fixed_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 101 => { - let context = ForStatementContext::__from_listener_node(context, None); - context.statement()?; - context.kw_for_token()?; - antlr4_runtime::require_min_count(context.semicolon_tokens().count(), 2, "ForStatementContext", "SEMICOLON")?; - context.lparen_token()?; - context.rparen_token()?; - }, - 102 => { - let context = GotoStatementContext::__from_listener_node(context, None); - context.kw_goto_token()?; - context.semicolon_token()?; - }, - 103 => { - let context = IfStatementContext::__from_listener_node(context, None); - context.statement()?; - context.expression()?; - context.kw_if_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 104 => { - let context = ElseClauseContext::__from_listener_node(context, None); - context.statement()?; - context.kw_else_token()?; - }, - 105 => { - let context = LabeledStatementContext::__from_listener_node(context, None); - context.statement()?; - context.identifier_token()?; - context.colon_token()?; - }, - 106 => { - let context = LocalDeclarationStatementContext::__from_listener_node(context, None); - context.local_variable_declaration()?; - context.semicolon_token()?; - }, - 107 => { - let context = LocalFunctionStatementContext::__from_listener_node(context, None); - context.parameter_list()?; - context.r#type()?; - context.identifier_token()?; - }, - 108 => { - let context = LockStatementContext::__from_listener_node(context, None); - context.statement()?; - context.expression()?; - context.kw_lock_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 109 => { - let context = ReturnStatementContext::__from_listener_node(context, None); - context.kw_return_token()?; - context.semicolon_token()?; - }, - 110 => { - let context = SwitchStatementContext::__from_listener_node(context, None); - context.expression()?; - context.kw_switch_token()?; - context.lbrace_token()?; - context.rbrace_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 111 => { - let context = SwitchSectionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.statement_children().count(), 1, "SwitchSectionContext", "statement")?; - antlr4_runtime::require_min_count(context.switch_label_children().count(), 1, "SwitchSectionContext", "switch_label")?; - }, - 112 => { - }, - 113 => { - let context = CasePatternSwitchLabelContext::__from_listener_node(context, None); - context.pattern()?; - context.kw_case_token()?; - context.colon_token()?; - }, - 114 => { - }, - 115 => { - let context = ConstantPatternContext::__from_listener_node(context, None); - context.expression()?; - }, - 116 => { - let context = DeclarationPatternContext::__from_listener_node(context, None); - context.r#type()?; - context.variable_designation()?; - }, - 117 => { - }, - 118 => { - let context = DiscardDesignationContext::__from_listener_node(context, None); - context.kw_token()?; - }, - 119 => { - let context = ParenthesizedVariableDesignationContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 120 => { - }, - 121 => { - let context = DiscardPatternContext::__from_listener_node(context, None); - context.kw_token()?; - }, - 122 => { - let context = ListPatternContext::__from_listener_node(context, None); - context.lbracket_token()?; - context.rbracket_token()?; - }, - 123 => { - let context = ParenthesizedPatternContext::__from_listener_node(context, None); - context.pattern()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 124 => { - }, - 125 => { - let context = PositionalPatternClauseContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 126 => { - let context = SubpatternContext::__from_listener_node(context, None); - context.pattern()?; - }, - 127 => { - }, - 128 => { - let context = ExpressionColonContext::__from_listener_node(context, None); - context.expression()?; - context.colon_token()?; - }, - 129 => { - let context = PropertyPatternClauseContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 130 => { - let context = RelationalPatternContext::__from_listener_node(context, None); - context.expression()?; - }, - 131 => { - let context = SlicePatternContext::__from_listener_node(context, None); - context.dot_dot_token()?; - }, - 132 => { - let context = TypePatternContext::__from_listener_node(context, None); - context.r#type()?; - }, - 133 => { - let context = UnaryPatternContext::__from_listener_node(context, None); - context.pattern()?; - context.kw_not_token()?; - }, - 134 => { - let context = VarPatternContext::__from_listener_node(context, None); - context.variable_designation()?; - context.kw_var_token()?; - }, - 135 => { - let context = WhenClauseContext::__from_listener_node(context, None); - context.expression()?; - context.kw_when_token()?; - }, - 136 => { - let context = CaseSwitchLabelContext::__from_listener_node(context, None); - context.expression()?; - context.kw_case_token()?; - context.colon_token()?; - }, - 137 => { - let context = DefaultSwitchLabelContext::__from_listener_node(context, None); - context.kw_default_token()?; - context.colon_token()?; - }, - 138 => { - let context = ThrowStatementContext::__from_listener_node(context, None); - context.kw_throw_token()?; - context.semicolon_token()?; - }, - 139 => { - let context = TryStatementContext::__from_listener_node(context, None); - context.block()?; - context.kw_try_token()?; - }, - 140 => { - let context = CatchClauseContext::__from_listener_node(context, None); - context.block()?; - context.kw_catch_token()?; - }, - 141 => { - let context = CatchDeclarationContext::__from_listener_node(context, None); - context.r#type()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 142 => { - let context = CatchFilterClauseContext::__from_listener_node(context, None); - context.expression()?; - context.kw_when_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 143 => { - let context = FinallyClauseContext::__from_listener_node(context, None); - context.block()?; - context.kw_finally_token()?; - }, - 144 => { - let context = UnsafeStatementContext::__from_listener_node(context, None); - context.block()?; - context.kw_unsafe_token()?; - }, - 145 => { - let context = UsingStatementContext::__from_listener_node(context, None); - context.statement()?; - context.kw_using_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 146 => { - let context = WhileStatementContext::__from_listener_node(context, None); - context.statement()?; - context.expression()?; - context.kw_while_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 147 => { - let context = YieldStatementContext::__from_listener_node(context, None); - context.kw_yield_token()?; - context.semicolon_token()?; - }, - 148 => { - }, - 149 => { - }, - 150 => { - let context = AnonymousMethodExpressionContext::__from_listener_node(context, None); - context.block()?; - context.kw_delegate_token()?; - }, - 151 => { - }, - 152 => { - let context = ParenthesizedLambdaExpressionContext::__from_listener_node(context, None); - context.parameter_list()?; - context.arrow_token()?; - }, - 153 => { - let context = SimpleLambdaExpressionContext::__from_listener_node(context, None); - context.identifier_token()?; - context.arrow_token()?; - }, - 154 => { - let context = AnonymousObjectCreationExpressionContext::__from_listener_node(context, None); - context.kw_new_token()?; - context.lbrace_token()?; - context.rbrace_token()?; - }, - 155 => { - let context = AnonymousObjectMemberDeclaratorContext::__from_listener_node(context, None); - context.expression()?; - }, - 156 => { - let context = ArrayCreationExpressionContext::__from_listener_node(context, None); - context.array_type()?; - context.kw_new_token()?; - }, - 157 => { - let context = InitializerExpressionContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 158 => { - let context = AwaitExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.kw_await_token()?; - }, - 159 => { - }, - 160 => { - let context = ImplicitObjectCreationExpressionContext::__from_listener_node(context, None); - context.argument_list()?; - context.kw_new_token()?; - }, - 161 => { - let context = ObjectCreationExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_new_token()?; - }, - 162 => { - let context = CastExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 163 => { - let context = CheckedExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 164 => { - let context = CollectionExpressionContext::__from_listener_node(context, None); - context.lbracket_token()?; - context.rbracket_token()?; - }, - 165 => { - }, - 166 => { - let context = ExpressionElementContext::__from_listener_node(context, None); - context.expression()?; - }, - 167 => { - let context = SpreadElementContext::__from_listener_node(context, None); - context.expression()?; - context.dot_dot_token()?; - }, - 168 => { - let context = WithElementContext::__from_listener_node(context, None); - context.argument_list()?; - context.kw_with_token()?; - }, - 169 => { - let context = DeclarationExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.variable_designation()?; - }, - 170 => { - let context = DefaultExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_default_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 171 => { - let context = ElementBindingExpressionContext::__from_listener_node(context, None); - context.bracketed_argument_list()?; - }, - 172 => { - let context = FieldExpressionContext::__from_listener_node(context, None); - context.kw_field_token()?; - }, - 173 => { - let context = ImplicitArrayCreationExpressionContext::__from_listener_node(context, None); - context.initializer_expression()?; - context.kw_new_token()?; - context.lbracket_token()?; - context.rbracket_token()?; - }, - 174 => { - let context = ImplicitElementAccessContext::__from_listener_node(context, None); - context.bracketed_argument_list()?; - }, - 175 => { - let context = ImplicitStackAllocArrayCreationExpressionContext::__from_listener_node(context, None); - context.initializer_expression()?; - context.kw_stackalloc_token()?; - context.lbracket_token()?; - context.rbracket_token()?; - }, - 176 => { - }, - 177 => { - let context = BaseExpressionContext::__from_listener_node(context, None); - context.kw_base_token()?; - }, - 178 => { - let context = ThisExpressionContext::__from_listener_node(context, None); - context.kw_this_token()?; - }, - 179 => { - }, - 180 => { - }, - 181 => { - let context = InterpolatedStringTextContext::__from_listener_node(context, None); - context.interpolated_string_text_token()?; - }, - 182 => { - let context = InterpolationContext::__from_listener_node(context, None); - context.expression()?; - context.lbrace_token()?; - context.rbrace_token()?; - }, - 183 => { - let context = InterpolationAlignmentClauseContext::__from_listener_node(context, None); - context.expression()?; - context.comma_token()?; - }, - 184 => { - let context = InterpolationFormatClauseContext::__from_listener_node(context, None); - context.interpolated_string_text_token()?; - context.colon_token()?; - }, - 185 => { - let context = InterpolatedMultiLineRawStringStartTokenContext::__from_listener_node(context, None); - context.interp_raw_start_token()?; - }, - 186 => { - let context = InterpolatedRawStringEndTokenContext::__from_listener_node(context, None); - context.triple_dquote_token()?; - }, - 187 => { - let context = InterpolatedSingleLineRawStringStartTokenContext::__from_listener_node(context, None); - context.interp_raw_start_token()?; - }, - 188 => { - }, - 189 => { - let context = Utf8MultiLineRawStringLiteralTokenContext::__from_listener_node(context, None); - context.multi_line_raw_string_literal_token()?; - }, - 190 => { - let context = Utf8SingleLineRawStringLiteralTokenContext::__from_listener_node(context, None); - context.single_line_raw_string_literal_token()?; - }, - 191 => { - let context = Utf8StringLiteralTokenContext::__from_listener_node(context, None); - context.string_literal_token()?; - }, - 192 => { - let context = MakeRefExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.kw_makeref_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 193 => { - let context = MemberBindingExpressionContext::__from_listener_node(context, None); - context.simple_name()?; - context.dot_token()?; - }, - 194 => { - let context = ParenthesizedExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 195 => { - let context = PrefixUnaryExpressionContext::__from_listener_node(context, None); - context.expression()?; - }, - 196 => { - let context = QueryExpressionContext::__from_listener_node(context, None); - context.from_clause()?; - context.query_body()?; - }, - 197 => { - let context = FromClauseContext::__from_listener_node(context, None); - context.expression()?; - context.identifier_token()?; - context.kw_from_token()?; - context.kw_in_token()?; - }, - 198 => { - let context = QueryBodyContext::__from_listener_node(context, None); - context.select_or_group_clause()?; - }, - 199 => { - }, - 200 => { - let context = JoinClauseContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.expression_children().count(), 3, "JoinClauseContext", "expression")?; - context.identifier_token()?; - context.kw_equals_token()?; - context.kw_join_token()?; - context.kw_in_token()?; - context.kw_on_token()?; - }, - 201 => { - let context = JoinIntoClauseContext::__from_listener_node(context, None); - context.identifier_token()?; - context.kw_into_token()?; - }, - 202 => { - let context = LetClauseContext::__from_listener_node(context, None); - context.expression()?; - context.identifier_token()?; - context.kw_let_token()?; - context.eq_token()?; - }, - 203 => { - let context = OrderByClauseContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.ordering_children().count(), 1, "OrderByClauseContext", "ordering")?; - context.kw_orderby_token()?; - }, - 204 => { - let context = OrderingContext::__from_listener_node(context, None); - context.expression()?; - }, - 205 => { - let context = WhereClauseContext::__from_listener_node(context, None); - context.expression()?; - context.kw_where_token()?; - }, - 206 => { - }, - 207 => { - let context = GroupClauseContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.expression_children().count(), 2, "GroupClauseContext", "expression")?; - context.kw_group_token()?; - context.kw_by_token()?; - }, - 208 => { - let context = SelectClauseContext::__from_listener_node(context, None); - context.expression()?; - context.kw_select_token()?; - }, - 209 => { - let context = QueryContinuationContext::__from_listener_node(context, None); - context.query_body()?; - context.identifier_token()?; - context.kw_into_token()?; - }, - 210 => { - let context = RefExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.kw_ref_token()?; - }, - 211 => { - let context = RefTypeExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.kw_reftype_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 212 => { - let context = RefValueExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.expression()?; - context.kw_refvalue_token()?; - context.comma_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 213 => { - let context = SizeOfExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_sizeof_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 214 => { - let context = StackAllocArrayCreationExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_stackalloc_token()?; - }, - 215 => { - let context = SwitchExpressionArmContext::__from_listener_node(context, None); - context.pattern()?; - context.expression()?; - context.arrow_token()?; - }, - 216 => { - let context = ThrowExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.kw_throw_token()?; - }, - 217 => { - let context = TupleExpressionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.argument_children().count(), 2, "TupleExpressionContext", "argument")?; - antlr4_runtime::require_min_count(context.comma_tokens().count(), 1, "TupleExpressionContext", "COMMA")?; - context.lparen_token()?; - context.rparen_token()?; - }, - 218 => { - let context = TypeOfExpressionContext::__from_listener_node(context, None); - context.r#type()?; - context.kw_typeof_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 219 => { - let context = UnsafeExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.kw_unsafe_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 220 => { - }, - 221 => { - }, - 222 => { - }, - 223 => { - }, - 224 => { - }, - 225 => { - let context = DecimalIntegerLiteralTokenContext::__from_listener_node(context, None); - context.dec_int_lit_token()?; - }, - 226 => { - let context = HexadecimalIntegerLiteralTokenContext::__from_listener_node(context, None); - context.hex_int_lit_token()?; - }, - 227 => { - let context = RealLiteralTokenContext::__from_listener_node(context, None); - context.real_lit_token()?; - }, - 228 => { - let context = CharacterLiteralTokenContext::__from_listener_node(context, None); - context.char_lit_token()?; - }, - 229 => { - }, - 230 => { - let context = RegularStringLiteralTokenContext::__from_listener_node(context, None); - context.string_lit_token()?; - }, - 231 => { - let context = VerbatimStringLiteralTokenContext::__from_listener_node(context, None); - context.verbatim_string_lit_token()?; - }, - 232 => { - }, - 233 => { - }, - 234 => { - let context = InterpolatedStringTextTokenContext::__from_listener_node(context, None); - context.interpolated_text_token()?; - }, - 235 => { - let context = MultiLineRawStringLiteralTokenContext::__from_listener_node(context, None); - context.ml_raw_string_lit_token()?; - }, - 236 => { - let context = SingleLineRawStringLiteralTokenContext::__from_listener_node(context, None); - context.sl_raw_string_lit_token()?; - }, - 237 => { - let context = RecordKeywordContext::__from_listener_node(context, None); - context.kw_record_token()?; - }, - 238 => { - let context = RightShiftContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.gt_tokens().count(), 2, "RightShiftContext", "GT")?; - }, - 239 => { - let context = UnsignedRightShiftContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.gt_tokens().count(), 3, "UnsignedRightShiftContext", "GT")?; - }, - 240 => { - let context = RightShiftAssignmentContext::__from_listener_node(context, None); - context.ge_token()?; - context.gt_token()?; - }, - 241 => { - let context = UnsignedRightShiftAssignmentContext::__from_listener_node(context, None); - context.ge_token()?; - antlr4_runtime::require_min_count(context.gt_tokens().count(), 2, "UnsignedRightShiftAssignmentContext", "GT")?; - }, - 242 => { - let context = LocalVariableDeclarationContext::__from_listener_node(context, None); - context.r#type()?; - antlr4_runtime::require_min_count(context.local_variable_declarator_children().count(), 1, "LocalVariableDeclarationContext", "local_variable_declarator")?; - }, - 243 => { - let context = LocalVariableDeclaratorContext::__from_listener_node(context, None); - context.identifier_token()?; - }, - _ => { - return Err(CSharpValidationError::UnknownRule { - rule_index: context.rule_index(), - }); - } - } - } - } - } - Ok(()) -} - -#[allow(dead_code, unused_variables)] -pub trait CSharpListener { - fn walk(&mut self, tree: antlr4_runtime::Node<'_>) -> Result<(), E> - where - Self: Sized, - { - CSharpTreeWalker::walk(self, tree) - } - - fn enter_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), E> { Ok(()) } - fn exit_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), E> { Ok(()) } - - fn enter_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn exit_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn enter_extern_alias_directive(&mut self, _ctx: &ExternAliasDirectiveContext) -> Result<(), E> { Ok(()) } - fn exit_extern_alias_directive(&mut self, _ctx: &ExternAliasDirectiveContext) -> Result<(), E> { Ok(()) } - fn enter_using_directive(&mut self, _ctx: &UsingDirectiveContext) -> Result<(), E> { Ok(()) } - fn exit_using_directive(&mut self, _ctx: &UsingDirectiveContext) -> Result<(), E> { Ok(()) } - fn enter_name_equals(&mut self, _ctx: &NameEqualsContext) -> Result<(), E> { Ok(()) } - fn exit_name_equals(&mut self, _ctx: &NameEqualsContext) -> Result<(), E> { Ok(()) } - fn enter_identifier_name(&mut self, _ctx: &IdentifierNameContext) -> Result<(), E> { Ok(()) } - fn exit_identifier_name(&mut self, _ctx: &IdentifierNameContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_list(&mut self, _ctx: &AttributeListContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_list(&mut self, _ctx: &AttributeListContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_target_specifier(&mut self, _ctx: &AttributeTargetSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_target_specifier(&mut self, _ctx: &AttributeTargetSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_attribute(&mut self, _ctx: &AttributeContext) -> Result<(), E> { Ok(()) } - fn exit_attribute(&mut self, _ctx: &AttributeContext) -> Result<(), E> { Ok(()) } - fn enter_name(&mut self, _ctx: &NameContext) -> Result<(), E> { Ok(()) } - fn exit_name(&mut self, _ctx: &NameContext) -> Result<(), E> { Ok(()) } - fn enter_alias_qualified_name(&mut self, _ctx: &AliasQualifiedNameContext) -> Result<(), E> { Ok(()) } - fn exit_alias_qualified_name(&mut self, _ctx: &AliasQualifiedNameContext) -> Result<(), E> { Ok(()) } - fn enter_simple_name(&mut self, _ctx: &SimpleNameContext) -> Result<(), E> { Ok(()) } - fn exit_simple_name(&mut self, _ctx: &SimpleNameContext) -> Result<(), E> { Ok(()) } - fn enter_generic_name(&mut self, _ctx: &GenericNameContext) -> Result<(), E> { Ok(()) } - fn exit_generic_name(&mut self, _ctx: &GenericNameContext) -> Result<(), E> { Ok(()) } - fn enter_type_argument_list(&mut self, _ctx: &TypeArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_type_argument_list(&mut self, _ctx: &TypeArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_argument_list(&mut self, _ctx: &AttributeArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_argument_list(&mut self, _ctx: &AttributeArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_argument(&mut self, _ctx: &AttributeArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_argument(&mut self, _ctx: &AttributeArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_name_colon(&mut self, _ctx: &NameColonContext) -> Result<(), E> { Ok(()) } - fn exit_name_colon(&mut self, _ctx: &NameColonContext) -> Result<(), E> { Ok(()) } - fn enter_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_field_declaration(&mut self, _ctx: &BaseFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_field_declaration(&mut self, _ctx: &BaseFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_event_field_declaration(&mut self, _ctx: &EventFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_event_field_declaration(&mut self, _ctx: &EventFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn exit_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_bracketed_argument_list(&mut self, _ctx: &BracketedArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_bracketed_argument_list(&mut self, _ctx: &BracketedArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_argument(&mut self, _ctx: &ArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_argument(&mut self, _ctx: &ArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_equals_value_clause(&mut self, _ctx: &EqualsValueClauseContext) -> Result<(), E> { Ok(()) } - fn exit_equals_value_clause(&mut self, _ctx: &EqualsValueClauseContext) -> Result<(), E> { Ok(()) } - fn enter_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_method_declaration(&mut self, _ctx: &BaseMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_method_declaration(&mut self, _ctx: &BaseMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_list(&mut self, _ctx: &ParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_list(&mut self, _ctx: &ParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn exit_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_initializer(&mut self, _ctx: &ConstructorInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_initializer(&mut self, _ctx: &ConstructorInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_argument_list(&mut self, _ctx: &ArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_argument_list(&mut self, _ctx: &ArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn exit_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn enter_arrow_expression_clause(&mut self, _ctx: &ArrowExpressionClauseContext) -> Result<(), E> { Ok(()) } - fn exit_arrow_expression_clause(&mut self, _ctx: &ArrowExpressionClauseContext) -> Result<(), E> { Ok(()) } - fn enter_conversion_operator_declaration(&mut self, _ctx: &ConversionOperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_conversion_operator_declaration(&mut self, _ctx: &ConversionOperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_interface_specifier(&mut self, _ctx: &ExplicitInterfaceSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_interface_specifier(&mut self, _ctx: &ExplicitInterfaceSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_destructor_declaration(&mut self, _ctx: &DestructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_destructor_declaration(&mut self, _ctx: &DestructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_list(&mut self, _ctx: &TypeParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_list(&mut self, _ctx: &TypeParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_constraint_clause(&mut self, _ctx: &TypeParameterConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_constraint_clause(&mut self, _ctx: &TypeParameterConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_constraint(&mut self, _ctx: &TypeParameterConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_constraint(&mut self, _ctx: &TypeParameterConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_allows_constraint_clause(&mut self, _ctx: &AllowsConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn exit_allows_constraint_clause(&mut self, _ctx: &AllowsConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn enter_allows_constraint(&mut self, _ctx: &AllowsConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_allows_constraint(&mut self, _ctx: &AllowsConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_ref_struct_constraint(&mut self, _ctx: &RefStructConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_ref_struct_constraint(&mut self, _ctx: &RefStructConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_class_or_struct_constraint(&mut self, _ctx: &ClassOrStructConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_class_or_struct_constraint(&mut self, _ctx: &ClassOrStructConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_constraint(&mut self, _ctx: &ConstructorConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_constraint(&mut self, _ctx: &ConstructorConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_default_constraint(&mut self, _ctx: &DefaultConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_default_constraint(&mut self, _ctx: &DefaultConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_operator_declaration(&mut self, _ctx: &OperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_operator_declaration(&mut self, _ctx: &OperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_namespace_declaration(&mut self, _ctx: &BaseNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_namespace_declaration(&mut self, _ctx: &BaseNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_file_scoped_namespace_declaration(&mut self, _ctx: &FileScopedNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_file_scoped_namespace_declaration(&mut self, _ctx: &FileScopedNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_namespace_declaration(&mut self, _ctx: &NamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_namespace_declaration(&mut self, _ctx: &NamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_property_declaration(&mut self, _ctx: &BasePropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_property_declaration(&mut self, _ctx: &BasePropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_event_declaration(&mut self, _ctx: &EventDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_event_declaration(&mut self, _ctx: &EventDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_accessor_list(&mut self, _ctx: &AccessorListContext) -> Result<(), E> { Ok(()) } - fn exit_accessor_list(&mut self, _ctx: &AccessorListContext) -> Result<(), E> { Ok(()) } - fn enter_accessor_declaration(&mut self, _ctx: &AccessorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_accessor_declaration(&mut self, _ctx: &AccessorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_indexer_declaration(&mut self, _ctx: &IndexerDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_indexer_declaration(&mut self, _ctx: &IndexerDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_bracketed_parameter_list(&mut self, _ctx: &BracketedParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_bracketed_parameter_list(&mut self, _ctx: &BracketedParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_type_declaration(&mut self, _ctx: &BaseTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_type_declaration(&mut self, _ctx: &BaseTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_list(&mut self, _ctx: &BaseListContext) -> Result<(), E> { Ok(()) } - fn exit_base_list(&mut self, _ctx: &BaseListContext) -> Result<(), E> { Ok(()) } - fn enter_base_type(&mut self, _ctx: &BaseTypeContext) -> Result<(), E> { Ok(()) } - fn exit_base_type(&mut self, _ctx: &BaseTypeContext) -> Result<(), E> { Ok(()) } - fn enter_primary_constructor_base_type(&mut self, _ctx: &PrimaryConstructorBaseTypeContext) -> Result<(), E> { Ok(()) } - fn exit_primary_constructor_base_type(&mut self, _ctx: &PrimaryConstructorBaseTypeContext) -> Result<(), E> { Ok(()) } - fn enter_simple_base_type(&mut self, _ctx: &SimpleBaseTypeContext) -> Result<(), E> { Ok(()) } - fn exit_simple_base_type(&mut self, _ctx: &SimpleBaseTypeContext) -> Result<(), E> { Ok(()) } - fn enter_enum_member_declaration(&mut self, _ctx: &EnumMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_enum_member_declaration(&mut self, _ctx: &EnumMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_extension_block_declaration(&mut self, _ctx: &ExtensionBlockDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_extension_block_declaration(&mut self, _ctx: &ExtensionBlockDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_struct_declaration(&mut self, _ctx: &StructDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_struct_declaration(&mut self, _ctx: &StructDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_union_declaration(&mut self, _ctx: &UnionDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_union_declaration(&mut self, _ctx: &UnionDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_delegate_declaration(&mut self, _ctx: &DelegateDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_delegate_declaration(&mut self, _ctx: &DelegateDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_global_statement(&mut self, _ctx: &GlobalStatementContext) -> Result<(), E> { Ok(()) } - fn exit_global_statement(&mut self, _ctx: &GlobalStatementContext) -> Result<(), E> { Ok(()) } - fn enter_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn exit_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn enter_array_type(&mut self, _ctx: &ArrayTypeContext) -> Result<(), E> { Ok(()) } - fn exit_array_type(&mut self, _ctx: &ArrayTypeContext) -> Result<(), E> { Ok(()) } - fn enter_array_rank_specifier(&mut self, _ctx: &ArrayRankSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_array_rank_specifier(&mut self, _ctx: &ArrayRankSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_type(&mut self, _ctx: &FunctionPointerTypeContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_type(&mut self, _ctx: &FunctionPointerTypeContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_calling_convention(&mut self, _ctx: &FunctionPointerCallingConventionContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_calling_convention(&mut self, _ctx: &FunctionPointerCallingConventionContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_unmanaged_calling_convention_list(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionListContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_unmanaged_calling_convention_list(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionListContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_unmanaged_calling_convention(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_unmanaged_calling_convention(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_parameter_list(&mut self, _ctx: &FunctionPointerParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_parameter_list(&mut self, _ctx: &FunctionPointerParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_parameter(&mut self, _ctx: &FunctionPointerParameterContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_parameter(&mut self, _ctx: &FunctionPointerParameterContext) -> Result<(), E> { Ok(()) } - fn enter_predefined_type(&mut self, _ctx: &PredefinedTypeContext) -> Result<(), E> { Ok(()) } - fn exit_predefined_type(&mut self, _ctx: &PredefinedTypeContext) -> Result<(), E> { Ok(()) } - fn enter_ref_type(&mut self, _ctx: &RefTypeContext) -> Result<(), E> { Ok(()) } - fn exit_ref_type(&mut self, _ctx: &RefTypeContext) -> Result<(), E> { Ok(()) } - fn enter_scoped_type(&mut self, _ctx: &ScopedTypeContext) -> Result<(), E> { Ok(()) } - fn exit_scoped_type(&mut self, _ctx: &ScopedTypeContext) -> Result<(), E> { Ok(()) } - fn enter_tuple_type(&mut self, _ctx: &TupleTypeContext) -> Result<(), E> { Ok(()) } - fn exit_tuple_type(&mut self, _ctx: &TupleTypeContext) -> Result<(), E> { Ok(()) } - fn enter_tuple_element(&mut self, _ctx: &TupleElementContext) -> Result<(), E> { Ok(()) } - fn exit_tuple_element(&mut self, _ctx: &TupleElementContext) -> Result<(), E> { Ok(()) } - fn enter_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn exit_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn enter_break_statement(&mut self, _ctx: &BreakStatementContext) -> Result<(), E> { Ok(()) } - fn exit_break_statement(&mut self, _ctx: &BreakStatementContext) -> Result<(), E> { Ok(()) } - fn enter_checked_statement(&mut self, _ctx: &CheckedStatementContext) -> Result<(), E> { Ok(()) } - fn exit_checked_statement(&mut self, _ctx: &CheckedStatementContext) -> Result<(), E> { Ok(()) } - fn enter_common_for_each_statement(&mut self, _ctx: &CommonForEachStatementContext) -> Result<(), E> { Ok(()) } - fn exit_common_for_each_statement(&mut self, _ctx: &CommonForEachStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_each_statement(&mut self, _ctx: &ForEachStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_each_statement(&mut self, _ctx: &ForEachStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_each_variable_statement(&mut self, _ctx: &ForEachVariableStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_each_variable_statement(&mut self, _ctx: &ForEachVariableStatementContext) -> Result<(), E> { Ok(()) } - fn enter_continue_statement(&mut self, _ctx: &ContinueStatementContext) -> Result<(), E> { Ok(()) } - fn exit_continue_statement(&mut self, _ctx: &ContinueStatementContext) -> Result<(), E> { Ok(()) } - fn enter_do_statement(&mut self, _ctx: &DoStatementContext) -> Result<(), E> { Ok(()) } - fn exit_do_statement(&mut self, _ctx: &DoStatementContext) -> Result<(), E> { Ok(()) } - fn enter_empty_statement(&mut self, _ctx: &EmptyStatementContext) -> Result<(), E> { Ok(()) } - fn exit_empty_statement(&mut self, _ctx: &EmptyStatementContext) -> Result<(), E> { Ok(()) } - fn enter_expression_statement(&mut self, _ctx: &ExpressionStatementContext) -> Result<(), E> { Ok(()) } - fn exit_expression_statement(&mut self, _ctx: &ExpressionStatementContext) -> Result<(), E> { Ok(()) } - fn enter_fixed_statement(&mut self, _ctx: &FixedStatementContext) -> Result<(), E> { Ok(()) } - fn exit_fixed_statement(&mut self, _ctx: &FixedStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn enter_goto_statement(&mut self, _ctx: &GotoStatementContext) -> Result<(), E> { Ok(()) } - fn exit_goto_statement(&mut self, _ctx: &GotoStatementContext) -> Result<(), E> { Ok(()) } - fn enter_if_statement(&mut self, _ctx: &IfStatementContext) -> Result<(), E> { Ok(()) } - fn exit_if_statement(&mut self, _ctx: &IfStatementContext) -> Result<(), E> { Ok(()) } - fn enter_else_clause(&mut self, _ctx: &ElseClauseContext) -> Result<(), E> { Ok(()) } - fn exit_else_clause(&mut self, _ctx: &ElseClauseContext) -> Result<(), E> { Ok(()) } - fn enter_labeled_statement(&mut self, _ctx: &LabeledStatementContext) -> Result<(), E> { Ok(()) } - fn exit_labeled_statement(&mut self, _ctx: &LabeledStatementContext) -> Result<(), E> { Ok(()) } - fn enter_local_declaration_statement(&mut self, _ctx: &LocalDeclarationStatementContext) -> Result<(), E> { Ok(()) } - fn exit_local_declaration_statement(&mut self, _ctx: &LocalDeclarationStatementContext) -> Result<(), E> { Ok(()) } - fn enter_local_function_statement(&mut self, _ctx: &LocalFunctionStatementContext) -> Result<(), E> { Ok(()) } - fn exit_local_function_statement(&mut self, _ctx: &LocalFunctionStatementContext) -> Result<(), E> { Ok(()) } - fn enter_lock_statement(&mut self, _ctx: &LockStatementContext) -> Result<(), E> { Ok(()) } - fn exit_lock_statement(&mut self, _ctx: &LockStatementContext) -> Result<(), E> { Ok(()) } - fn enter_return_statement(&mut self, _ctx: &ReturnStatementContext) -> Result<(), E> { Ok(()) } - fn exit_return_statement(&mut self, _ctx: &ReturnStatementContext) -> Result<(), E> { Ok(()) } - fn enter_switch_statement(&mut self, _ctx: &SwitchStatementContext) -> Result<(), E> { Ok(()) } - fn exit_switch_statement(&mut self, _ctx: &SwitchStatementContext) -> Result<(), E> { Ok(()) } - fn enter_switch_section(&mut self, _ctx: &SwitchSectionContext) -> Result<(), E> { Ok(()) } - fn exit_switch_section(&mut self, _ctx: &SwitchSectionContext) -> Result<(), E> { Ok(()) } - fn enter_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_case_pattern_switch_label(&mut self, _ctx: &CasePatternSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_case_pattern_switch_label(&mut self, _ctx: &CasePatternSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn exit_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn enter_constant_pattern(&mut self, _ctx: &ConstantPatternContext) -> Result<(), E> { Ok(()) } - fn exit_constant_pattern(&mut self, _ctx: &ConstantPatternContext) -> Result<(), E> { Ok(()) } - fn enter_declaration_pattern(&mut self, _ctx: &DeclarationPatternContext) -> Result<(), E> { Ok(()) } - fn exit_declaration_pattern(&mut self, _ctx: &DeclarationPatternContext) -> Result<(), E> { Ok(()) } - fn enter_variable_designation(&mut self, _ctx: &VariableDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_variable_designation(&mut self, _ctx: &VariableDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_discard_designation(&mut self, _ctx: &DiscardDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_discard_designation(&mut self, _ctx: &DiscardDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_variable_designation(&mut self, _ctx: &ParenthesizedVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_variable_designation(&mut self, _ctx: &ParenthesizedVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_single_variable_designation(&mut self, _ctx: &SingleVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_single_variable_designation(&mut self, _ctx: &SingleVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_discard_pattern(&mut self, _ctx: &DiscardPatternContext) -> Result<(), E> { Ok(()) } - fn exit_discard_pattern(&mut self, _ctx: &DiscardPatternContext) -> Result<(), E> { Ok(()) } - fn enter_list_pattern(&mut self, _ctx: &ListPatternContext) -> Result<(), E> { Ok(()) } - fn exit_list_pattern(&mut self, _ctx: &ListPatternContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_pattern(&mut self, _ctx: &ParenthesizedPatternContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_pattern(&mut self, _ctx: &ParenthesizedPatternContext) -> Result<(), E> { Ok(()) } - fn enter_recursive_pattern(&mut self, _ctx: &RecursivePatternContext) -> Result<(), E> { Ok(()) } - fn exit_recursive_pattern(&mut self, _ctx: &RecursivePatternContext) -> Result<(), E> { Ok(()) } - fn enter_positional_pattern_clause(&mut self, _ctx: &PositionalPatternClauseContext) -> Result<(), E> { Ok(()) } - fn exit_positional_pattern_clause(&mut self, _ctx: &PositionalPatternClauseContext) -> Result<(), E> { Ok(()) } - fn enter_subpattern(&mut self, _ctx: &SubpatternContext) -> Result<(), E> { Ok(()) } - fn exit_subpattern(&mut self, _ctx: &SubpatternContext) -> Result<(), E> { Ok(()) } - fn enter_base_expression_colon(&mut self, _ctx: &BaseExpressionColonContext) -> Result<(), E> { Ok(()) } - fn exit_base_expression_colon(&mut self, _ctx: &BaseExpressionColonContext) -> Result<(), E> { Ok(()) } - fn enter_expression_colon(&mut self, _ctx: &ExpressionColonContext) -> Result<(), E> { Ok(()) } - fn exit_expression_colon(&mut self, _ctx: &ExpressionColonContext) -> Result<(), E> { Ok(()) } - fn enter_property_pattern_clause(&mut self, _ctx: &PropertyPatternClauseContext) -> Result<(), E> { Ok(()) } - fn exit_property_pattern_clause(&mut self, _ctx: &PropertyPatternClauseContext) -> Result<(), E> { Ok(()) } - fn enter_relational_pattern(&mut self, _ctx: &RelationalPatternContext) -> Result<(), E> { Ok(()) } - fn exit_relational_pattern(&mut self, _ctx: &RelationalPatternContext) -> Result<(), E> { Ok(()) } - fn enter_slice_pattern(&mut self, _ctx: &SlicePatternContext) -> Result<(), E> { Ok(()) } - fn exit_slice_pattern(&mut self, _ctx: &SlicePatternContext) -> Result<(), E> { Ok(()) } - fn enter_type_pattern(&mut self, _ctx: &TypePatternContext) -> Result<(), E> { Ok(()) } - fn exit_type_pattern(&mut self, _ctx: &TypePatternContext) -> Result<(), E> { Ok(()) } - fn enter_unary_pattern(&mut self, _ctx: &UnaryPatternContext) -> Result<(), E> { Ok(()) } - fn exit_unary_pattern(&mut self, _ctx: &UnaryPatternContext) -> Result<(), E> { Ok(()) } - fn enter_var_pattern(&mut self, _ctx: &VarPatternContext) -> Result<(), E> { Ok(()) } - fn exit_var_pattern(&mut self, _ctx: &VarPatternContext) -> Result<(), E> { Ok(()) } - fn enter_when_clause(&mut self, _ctx: &WhenClauseContext) -> Result<(), E> { Ok(()) } - fn exit_when_clause(&mut self, _ctx: &WhenClauseContext) -> Result<(), E> { Ok(()) } - fn enter_case_switch_label(&mut self, _ctx: &CaseSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_case_switch_label(&mut self, _ctx: &CaseSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_default_switch_label(&mut self, _ctx: &DefaultSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_default_switch_label(&mut self, _ctx: &DefaultSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_throw_statement(&mut self, _ctx: &ThrowStatementContext) -> Result<(), E> { Ok(()) } - fn exit_throw_statement(&mut self, _ctx: &ThrowStatementContext) -> Result<(), E> { Ok(()) } - fn enter_try_statement(&mut self, _ctx: &TryStatementContext) -> Result<(), E> { Ok(()) } - fn exit_try_statement(&mut self, _ctx: &TryStatementContext) -> Result<(), E> { Ok(()) } - fn enter_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn exit_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn enter_catch_declaration(&mut self, _ctx: &CatchDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_catch_declaration(&mut self, _ctx: &CatchDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_catch_filter_clause(&mut self, _ctx: &CatchFilterClauseContext) -> Result<(), E> { Ok(()) } - fn exit_catch_filter_clause(&mut self, _ctx: &CatchFilterClauseContext) -> Result<(), E> { Ok(()) } - fn enter_finally_clause(&mut self, _ctx: &FinallyClauseContext) -> Result<(), E> { Ok(()) } - fn exit_finally_clause(&mut self, _ctx: &FinallyClauseContext) -> Result<(), E> { Ok(()) } - fn enter_unsafe_statement(&mut self, _ctx: &UnsafeStatementContext) -> Result<(), E> { Ok(()) } - fn exit_unsafe_statement(&mut self, _ctx: &UnsafeStatementContext) -> Result<(), E> { Ok(()) } - fn enter_using_statement(&mut self, _ctx: &UsingStatementContext) -> Result<(), E> { Ok(()) } - fn exit_using_statement(&mut self, _ctx: &UsingStatementContext) -> Result<(), E> { Ok(()) } - fn enter_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn exit_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn enter_yield_statement(&mut self, _ctx: &YieldStatementContext) -> Result<(), E> { Ok(()) } - fn exit_yield_statement(&mut self, _ctx: &YieldStatementContext) -> Result<(), E> { Ok(()) } - fn enter_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_function_expression(&mut self, _ctx: &AnonymousFunctionExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_function_expression(&mut self, _ctx: &AnonymousFunctionExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_method_expression(&mut self, _ctx: &AnonymousMethodExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_method_expression(&mut self, _ctx: &AnonymousMethodExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_lambda_expression(&mut self, _ctx: &ParenthesizedLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_lambda_expression(&mut self, _ctx: &ParenthesizedLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_simple_lambda_expression(&mut self, _ctx: &SimpleLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_simple_lambda_expression(&mut self, _ctx: &SimpleLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_object_creation_expression(&mut self, _ctx: &AnonymousObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_object_creation_expression(&mut self, _ctx: &AnonymousObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_object_member_declarator(&mut self, _ctx: &AnonymousObjectMemberDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_object_member_declarator(&mut self, _ctx: &AnonymousObjectMemberDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_array_creation_expression(&mut self, _ctx: &ArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_array_creation_expression(&mut self, _ctx: &ArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_initializer_expression(&mut self, _ctx: &InitializerExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_initializer_expression(&mut self, _ctx: &InitializerExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_await_expression(&mut self, _ctx: &AwaitExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_await_expression(&mut self, _ctx: &AwaitExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_base_object_creation_expression(&mut self, _ctx: &BaseObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_base_object_creation_expression(&mut self, _ctx: &BaseObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_object_creation_expression(&mut self, _ctx: &ImplicitObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_object_creation_expression(&mut self, _ctx: &ImplicitObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_object_creation_expression(&mut self, _ctx: &ObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_object_creation_expression(&mut self, _ctx: &ObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_cast_expression(&mut self, _ctx: &CastExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_cast_expression(&mut self, _ctx: &CastExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_checked_expression(&mut self, _ctx: &CheckedExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_checked_expression(&mut self, _ctx: &CheckedExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_collection_expression(&mut self, _ctx: &CollectionExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_collection_expression(&mut self, _ctx: &CollectionExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_collection_element(&mut self, _ctx: &CollectionElementContext) -> Result<(), E> { Ok(()) } - fn exit_collection_element(&mut self, _ctx: &CollectionElementContext) -> Result<(), E> { Ok(()) } - fn enter_expression_element(&mut self, _ctx: &ExpressionElementContext) -> Result<(), E> { Ok(()) } - fn exit_expression_element(&mut self, _ctx: &ExpressionElementContext) -> Result<(), E> { Ok(()) } - fn enter_spread_element(&mut self, _ctx: &SpreadElementContext) -> Result<(), E> { Ok(()) } - fn exit_spread_element(&mut self, _ctx: &SpreadElementContext) -> Result<(), E> { Ok(()) } - fn enter_with_element(&mut self, _ctx: &WithElementContext) -> Result<(), E> { Ok(()) } - fn exit_with_element(&mut self, _ctx: &WithElementContext) -> Result<(), E> { Ok(()) } - fn enter_declaration_expression(&mut self, _ctx: &DeclarationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_declaration_expression(&mut self, _ctx: &DeclarationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_default_expression(&mut self, _ctx: &DefaultExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_default_expression(&mut self, _ctx: &DefaultExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_element_binding_expression(&mut self, _ctx: &ElementBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_element_binding_expression(&mut self, _ctx: &ElementBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_field_expression(&mut self, _ctx: &FieldExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_field_expression(&mut self, _ctx: &FieldExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_array_creation_expression(&mut self, _ctx: &ImplicitArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_array_creation_expression(&mut self, _ctx: &ImplicitArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_element_access(&mut self, _ctx: &ImplicitElementAccessContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_element_access(&mut self, _ctx: &ImplicitElementAccessContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_stack_alloc_array_creation_expression(&mut self, _ctx: &ImplicitStackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_stack_alloc_array_creation_expression(&mut self, _ctx: &ImplicitStackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_instance_expression(&mut self, _ctx: &InstanceExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_instance_expression(&mut self, _ctx: &InstanceExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_base_expression(&mut self, _ctx: &BaseExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_base_expression(&mut self, _ctx: &BaseExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_expression(&mut self, _ctx: &InterpolatedStringExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_expression(&mut self, _ctx: &InterpolatedStringExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_content(&mut self, _ctx: &InterpolatedStringContentContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_content(&mut self, _ctx: &InterpolatedStringContentContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_text(&mut self, _ctx: &InterpolatedStringTextContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_text(&mut self, _ctx: &InterpolatedStringTextContext) -> Result<(), E> { Ok(()) } - fn enter_interpolation(&mut self, _ctx: &InterpolationContext) -> Result<(), E> { Ok(()) } - fn exit_interpolation(&mut self, _ctx: &InterpolationContext) -> Result<(), E> { Ok(()) } - fn enter_interpolation_alignment_clause(&mut self, _ctx: &InterpolationAlignmentClauseContext) -> Result<(), E> { Ok(()) } - fn exit_interpolation_alignment_clause(&mut self, _ctx: &InterpolationAlignmentClauseContext) -> Result<(), E> { Ok(()) } - fn enter_interpolation_format_clause(&mut self, _ctx: &InterpolationFormatClauseContext) -> Result<(), E> { Ok(()) } - fn exit_interpolation_format_clause(&mut self, _ctx: &InterpolationFormatClauseContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_multi_line_raw_string_start_token(&mut self, _ctx: &InterpolatedMultiLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_multi_line_raw_string_start_token(&mut self, _ctx: &InterpolatedMultiLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_raw_string_end_token(&mut self, _ctx: &InterpolatedRawStringEndTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_raw_string_end_token(&mut self, _ctx: &InterpolatedRawStringEndTokenContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_single_line_raw_string_start_token(&mut self, _ctx: &InterpolatedSingleLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_single_line_raw_string_start_token(&mut self, _ctx: &InterpolatedSingleLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn enter_literal_expression(&mut self, _ctx: &LiteralExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_literal_expression(&mut self, _ctx: &LiteralExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_utf8_multi_line_raw_string_literal_token(&mut self, _ctx: &Utf8MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_utf8_multi_line_raw_string_literal_token(&mut self, _ctx: &Utf8MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_utf8_single_line_raw_string_literal_token(&mut self, _ctx: &Utf8SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_utf8_single_line_raw_string_literal_token(&mut self, _ctx: &Utf8SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_utf8_string_literal_token(&mut self, _ctx: &Utf8StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_utf8_string_literal_token(&mut self, _ctx: &Utf8StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_make_ref_expression(&mut self, _ctx: &MakeRefExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_make_ref_expression(&mut self, _ctx: &MakeRefExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_member_binding_expression(&mut self, _ctx: &MemberBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_member_binding_expression(&mut self, _ctx: &MemberBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_query_expression(&mut self, _ctx: &QueryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_query_expression(&mut self, _ctx: &QueryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_from_clause(&mut self, _ctx: &FromClauseContext) -> Result<(), E> { Ok(()) } - fn exit_from_clause(&mut self, _ctx: &FromClauseContext) -> Result<(), E> { Ok(()) } - fn enter_query_body(&mut self, _ctx: &QueryBodyContext) -> Result<(), E> { Ok(()) } - fn exit_query_body(&mut self, _ctx: &QueryBodyContext) -> Result<(), E> { Ok(()) } - fn enter_query_clause(&mut self, _ctx: &QueryClauseContext) -> Result<(), E> { Ok(()) } - fn exit_query_clause(&mut self, _ctx: &QueryClauseContext) -> Result<(), E> { Ok(()) } - fn enter_join_clause(&mut self, _ctx: &JoinClauseContext) -> Result<(), E> { Ok(()) } - fn exit_join_clause(&mut self, _ctx: &JoinClauseContext) -> Result<(), E> { Ok(()) } - fn enter_join_into_clause(&mut self, _ctx: &JoinIntoClauseContext) -> Result<(), E> { Ok(()) } - fn exit_join_into_clause(&mut self, _ctx: &JoinIntoClauseContext) -> Result<(), E> { Ok(()) } - fn enter_let_clause(&mut self, _ctx: &LetClauseContext) -> Result<(), E> { Ok(()) } - fn exit_let_clause(&mut self, _ctx: &LetClauseContext) -> Result<(), E> { Ok(()) } - fn enter_order_by_clause(&mut self, _ctx: &OrderByClauseContext) -> Result<(), E> { Ok(()) } - fn exit_order_by_clause(&mut self, _ctx: &OrderByClauseContext) -> Result<(), E> { Ok(()) } - fn enter_ordering(&mut self, _ctx: &OrderingContext) -> Result<(), E> { Ok(()) } - fn exit_ordering(&mut self, _ctx: &OrderingContext) -> Result<(), E> { Ok(()) } - fn enter_where_clause(&mut self, _ctx: &WhereClauseContext) -> Result<(), E> { Ok(()) } - fn exit_where_clause(&mut self, _ctx: &WhereClauseContext) -> Result<(), E> { Ok(()) } - fn enter_select_or_group_clause(&mut self, _ctx: &SelectOrGroupClauseContext) -> Result<(), E> { Ok(()) } - fn exit_select_or_group_clause(&mut self, _ctx: &SelectOrGroupClauseContext) -> Result<(), E> { Ok(()) } - fn enter_group_clause(&mut self, _ctx: &GroupClauseContext) -> Result<(), E> { Ok(()) } - fn exit_group_clause(&mut self, _ctx: &GroupClauseContext) -> Result<(), E> { Ok(()) } - fn enter_select_clause(&mut self, _ctx: &SelectClauseContext) -> Result<(), E> { Ok(()) } - fn exit_select_clause(&mut self, _ctx: &SelectClauseContext) -> Result<(), E> { Ok(()) } - fn enter_query_continuation(&mut self, _ctx: &QueryContinuationContext) -> Result<(), E> { Ok(()) } - fn exit_query_continuation(&mut self, _ctx: &QueryContinuationContext) -> Result<(), E> { Ok(()) } - fn enter_ref_expression(&mut self, _ctx: &RefExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_ref_expression(&mut self, _ctx: &RefExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_ref_type_expression(&mut self, _ctx: &RefTypeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_ref_type_expression(&mut self, _ctx: &RefTypeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_ref_value_expression(&mut self, _ctx: &RefValueExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_ref_value_expression(&mut self, _ctx: &RefValueExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_size_of_expression(&mut self, _ctx: &SizeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_size_of_expression(&mut self, _ctx: &SizeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_stack_alloc_array_creation_expression(&mut self, _ctx: &StackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_stack_alloc_array_creation_expression(&mut self, _ctx: &StackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_switch_expression_arm(&mut self, _ctx: &SwitchExpressionArmContext) -> Result<(), E> { Ok(()) } - fn exit_switch_expression_arm(&mut self, _ctx: &SwitchExpressionArmContext) -> Result<(), E> { Ok(()) } - fn enter_throw_expression(&mut self, _ctx: &ThrowExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_throw_expression(&mut self, _ctx: &ThrowExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_tuple_expression(&mut self, _ctx: &TupleExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_tuple_expression(&mut self, _ctx: &TupleExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_type_of_expression(&mut self, _ctx: &TypeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_type_of_expression(&mut self, _ctx: &TypeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_unsafe_expression(&mut self, _ctx: &UnsafeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_unsafe_expression(&mut self, _ctx: &UnsafeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_syntax_token(&mut self, _ctx: &SyntaxTokenContext) -> Result<(), E> { Ok(()) } - fn exit_syntax_token(&mut self, _ctx: &SyntaxTokenContext) -> Result<(), E> { Ok(()) } - fn enter_identifier_token(&mut self, _ctx: &IdentifierTokenContext) -> Result<(), E> { Ok(()) } - fn exit_identifier_token(&mut self, _ctx: &IdentifierTokenContext) -> Result<(), E> { Ok(()) } - fn enter_keyword(&mut self, _ctx: &KeywordContext) -> Result<(), E> { Ok(()) } - fn exit_keyword(&mut self, _ctx: &KeywordContext) -> Result<(), E> { Ok(()) } - fn enter_numeric_literal_token(&mut self, _ctx: &NumericLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_numeric_literal_token(&mut self, _ctx: &NumericLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_integer_literal_token(&mut self, _ctx: &IntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_integer_literal_token(&mut self, _ctx: &IntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_decimal_integer_literal_token(&mut self, _ctx: &DecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_decimal_integer_literal_token(&mut self, _ctx: &DecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_hexadecimal_integer_literal_token(&mut self, _ctx: &HexadecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_hexadecimal_integer_literal_token(&mut self, _ctx: &HexadecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_real_literal_token(&mut self, _ctx: &RealLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_real_literal_token(&mut self, _ctx: &RealLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_character_literal_token(&mut self, _ctx: &CharacterLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_character_literal_token(&mut self, _ctx: &CharacterLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_string_literal_token(&mut self, _ctx: &StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_string_literal_token(&mut self, _ctx: &StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_regular_string_literal_token(&mut self, _ctx: &RegularStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_regular_string_literal_token(&mut self, _ctx: &RegularStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_verbatim_string_literal_token(&mut self, _ctx: &VerbatimStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_verbatim_string_literal_token(&mut self, _ctx: &VerbatimStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_operator_token(&mut self, _ctx: &OperatorTokenContext) -> Result<(), E> { Ok(()) } - fn exit_operator_token(&mut self, _ctx: &OperatorTokenContext) -> Result<(), E> { Ok(()) } - fn enter_punctuation_token(&mut self, _ctx: &PunctuationTokenContext) -> Result<(), E> { Ok(()) } - fn exit_punctuation_token(&mut self, _ctx: &PunctuationTokenContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_text_token(&mut self, _ctx: &InterpolatedStringTextTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_text_token(&mut self, _ctx: &InterpolatedStringTextTokenContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_raw_string_literal_token(&mut self, _ctx: &MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_raw_string_literal_token(&mut self, _ctx: &MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_single_line_raw_string_literal_token(&mut self, _ctx: &SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_single_line_raw_string_literal_token(&mut self, _ctx: &SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_record_keyword(&mut self, _ctx: &RecordKeywordContext) -> Result<(), E> { Ok(()) } - fn exit_record_keyword(&mut self, _ctx: &RecordKeywordContext) -> Result<(), E> { Ok(()) } - fn enter_right_shift(&mut self, _ctx: &RightShiftContext) -> Result<(), E> { Ok(()) } - fn exit_right_shift(&mut self, _ctx: &RightShiftContext) -> Result<(), E> { Ok(()) } - fn enter_unsigned_right_shift(&mut self, _ctx: &UnsignedRightShiftContext) -> Result<(), E> { Ok(()) } - fn exit_unsigned_right_shift(&mut self, _ctx: &UnsignedRightShiftContext) -> Result<(), E> { Ok(()) } - fn enter_right_shift_assignment(&mut self, _ctx: &RightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn exit_right_shift_assignment(&mut self, _ctx: &RightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn enter_unsigned_right_shift_assignment(&mut self, _ctx: &UnsignedRightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn exit_unsigned_right_shift_assignment(&mut self, _ctx: &UnsignedRightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn enter_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_local_variable_declarator(&mut self, _ctx: &LocalVariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_local_variable_declarator(&mut self, _ctx: &LocalVariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), E> { Ok(()) } - fn visit_error_node(&mut self, _node: &ErrorNode) -> Result<(), E> { Ok(()) } - fn output(&mut self) -> std::io::Stdout { std::io::stdout() } -} - -antlr4_runtime::__antlr4_rust_generated_walk_callbacks! { - callbacks: __CSharpTreeWalkerCallbacks, - listener: CSharpListener, - enter: |listener, context, invocation_states| { - listener.enter_every_rule(context)?; - match __context_kind(context) { - 0 => listener.enter_compilation_unit(&CompilationUnitContext::__from_listener_node(context, invocation_states))?, - 1 => listener.enter_extern_alias_directive(&ExternAliasDirectiveContext::__from_listener_node(context, invocation_states))?, - 2 => listener.enter_using_directive(&UsingDirectiveContext::__from_listener_node(context, invocation_states))?, - 3 => listener.enter_name_equals(&NameEqualsContext::__from_listener_node(context, invocation_states))?, - 4 => listener.enter_identifier_name(&IdentifierNameContext::__from_listener_node(context, invocation_states))?, - 5 => listener.enter_attribute_list(&AttributeListContext::__from_listener_node(context, invocation_states))?, - 6 => listener.enter_attribute_target_specifier(&AttributeTargetSpecifierContext::__from_listener_node(context, invocation_states))?, - 7 => listener.enter_attribute(&AttributeContext::__from_listener_node(context, invocation_states))?, - 8 => listener.enter_name(&NameContext::__from_listener_node(context, invocation_states))?, - 9 => listener.enter_alias_qualified_name(&AliasQualifiedNameContext::__from_listener_node(context, invocation_states))?, - 10 => listener.enter_simple_name(&SimpleNameContext::__from_listener_node(context, invocation_states))?, - 11 => listener.enter_generic_name(&GenericNameContext::__from_listener_node(context, invocation_states))?, - 12 => listener.enter_type_argument_list(&TypeArgumentListContext::__from_listener_node(context, invocation_states))?, - 13 => listener.enter_attribute_argument_list(&AttributeArgumentListContext::__from_listener_node(context, invocation_states))?, - 14 => listener.enter_attribute_argument(&AttributeArgumentContext::__from_listener_node(context, invocation_states))?, - 15 => listener.enter_name_colon(&NameColonContext::__from_listener_node(context, invocation_states))?, - 16 => listener.enter_member_declaration(&MemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 17 => listener.enter_base_field_declaration(&BaseFieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 18 => listener.enter_event_field_declaration(&EventFieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 19 => listener.enter_modifier(&ModifierContext::__from_listener_node(context, invocation_states))?, - 20 => listener.enter_variable_declaration(&VariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 21 => listener.enter_variable_declarator(&VariableDeclaratorContext::__from_listener_node(context, invocation_states))?, - 22 => listener.enter_bracketed_argument_list(&BracketedArgumentListContext::__from_listener_node(context, invocation_states))?, - 23 => listener.enter_argument(&ArgumentContext::__from_listener_node(context, invocation_states))?, - 24 => listener.enter_equals_value_clause(&EqualsValueClauseContext::__from_listener_node(context, invocation_states))?, - 25 => listener.enter_field_declaration(&FieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 26 => listener.enter_base_method_declaration(&BaseMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 27 => listener.enter_constructor_declaration(&ConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 28 => listener.enter_parameter_list(&ParameterListContext::__from_listener_node(context, invocation_states))?, - 29 => listener.enter_parameter(&ParameterContext::__from_listener_node(context, invocation_states))?, - 30 => listener.enter_constructor_initializer(&ConstructorInitializerContext::__from_listener_node(context, invocation_states))?, - 31 => listener.enter_argument_list(&ArgumentListContext::__from_listener_node(context, invocation_states))?, - 32 => listener.enter_block(&BlockContext::__from_listener_node(context, invocation_states))?, - 33 => listener.enter_arrow_expression_clause(&ArrowExpressionClauseContext::__from_listener_node(context, invocation_states))?, - 34 => listener.enter_conversion_operator_declaration(&ConversionOperatorDeclarationContext::__from_listener_node(context, invocation_states))?, - 35 => listener.enter_explicit_interface_specifier(&ExplicitInterfaceSpecifierContext::__from_listener_node(context, invocation_states))?, - 36 => listener.enter_destructor_declaration(&DestructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 37 => listener.enter_method_declaration(&MethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 38 => listener.enter_type_parameter_list(&TypeParameterListContext::__from_listener_node(context, invocation_states))?, - 39 => listener.enter_type_parameter(&TypeParameterContext::__from_listener_node(context, invocation_states))?, - 40 => listener.enter_type_parameter_constraint_clause(&TypeParameterConstraintClauseContext::__from_listener_node(context, invocation_states))?, - 41 => listener.enter_type_parameter_constraint(&TypeParameterConstraintContext::__from_listener_node(context, invocation_states))?, - 42 => listener.enter_allows_constraint_clause(&AllowsConstraintClauseContext::__from_listener_node(context, invocation_states))?, - 43 => listener.enter_allows_constraint(&AllowsConstraintContext::__from_listener_node(context, invocation_states))?, - 44 => listener.enter_ref_struct_constraint(&RefStructConstraintContext::__from_listener_node(context, invocation_states))?, - 45 => listener.enter_class_or_struct_constraint(&ClassOrStructConstraintContext::__from_listener_node(context, invocation_states))?, - 46 => listener.enter_constructor_constraint(&ConstructorConstraintContext::__from_listener_node(context, invocation_states))?, - 47 => listener.enter_default_constraint(&DefaultConstraintContext::__from_listener_node(context, invocation_states))?, - 48 => listener.enter_type_constraint(&TypeConstraintContext::__from_listener_node(context, invocation_states))?, - 49 => listener.enter_operator_declaration(&OperatorDeclarationContext::__from_listener_node(context, invocation_states))?, - 50 => listener.enter_base_namespace_declaration(&BaseNamespaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 51 => listener.enter_file_scoped_namespace_declaration(&FileScopedNamespaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 52 => listener.enter_namespace_declaration(&NamespaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 53 => listener.enter_base_property_declaration(&BasePropertyDeclarationContext::__from_listener_node(context, invocation_states))?, - 54 => listener.enter_event_declaration(&EventDeclarationContext::__from_listener_node(context, invocation_states))?, - 55 => listener.enter_accessor_list(&AccessorListContext::__from_listener_node(context, invocation_states))?, - 56 => listener.enter_accessor_declaration(&AccessorDeclarationContext::__from_listener_node(context, invocation_states))?, - 57 => listener.enter_indexer_declaration(&IndexerDeclarationContext::__from_listener_node(context, invocation_states))?, - 58 => listener.enter_bracketed_parameter_list(&BracketedParameterListContext::__from_listener_node(context, invocation_states))?, - 59 => listener.enter_property_declaration(&PropertyDeclarationContext::__from_listener_node(context, invocation_states))?, - 60 => listener.enter_base_type_declaration(&BaseTypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 61 => listener.enter_enum_declaration(&EnumDeclarationContext::__from_listener_node(context, invocation_states))?, - 62 => listener.enter_base_list(&BaseListContext::__from_listener_node(context, invocation_states))?, - 63 => listener.enter_base_type(&BaseTypeContext::__from_listener_node(context, invocation_states))?, - 64 => listener.enter_primary_constructor_base_type(&PrimaryConstructorBaseTypeContext::__from_listener_node(context, invocation_states))?, - 65 => listener.enter_simple_base_type(&SimpleBaseTypeContext::__from_listener_node(context, invocation_states))?, - 66 => listener.enter_enum_member_declaration(&EnumMemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 67 => listener.enter_type_declaration(&TypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 68 => listener.enter_class_declaration(&ClassDeclarationContext::__from_listener_node(context, invocation_states))?, - 69 => listener.enter_extension_block_declaration(&ExtensionBlockDeclarationContext::__from_listener_node(context, invocation_states))?, - 70 => listener.enter_interface_declaration(&InterfaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 71 => listener.enter_record_declaration(&RecordDeclarationContext::__from_listener_node(context, invocation_states))?, - 72 => listener.enter_struct_declaration(&StructDeclarationContext::__from_listener_node(context, invocation_states))?, - 73 => listener.enter_union_declaration(&UnionDeclarationContext::__from_listener_node(context, invocation_states))?, - 74 => listener.enter_delegate_declaration(&DelegateDeclarationContext::__from_listener_node(context, invocation_states))?, - 75 => listener.enter_global_statement(&GlobalStatementContext::__from_listener_node(context, invocation_states))?, - 76 => listener.enter_type(&TypeContext::__from_listener_node(context, invocation_states))?, - 77 => listener.enter_array_type(&ArrayTypeContext::__from_listener_node(context, invocation_states))?, - 78 => listener.enter_array_rank_specifier(&ArrayRankSpecifierContext::__from_listener_node(context, invocation_states))?, - 79 => listener.enter_function_pointer_type(&FunctionPointerTypeContext::__from_listener_node(context, invocation_states))?, - 80 => listener.enter_function_pointer_calling_convention(&FunctionPointerCallingConventionContext::__from_listener_node(context, invocation_states))?, - 81 => listener.enter_function_pointer_unmanaged_calling_convention_list(&FunctionPointerUnmanagedCallingConventionListContext::__from_listener_node(context, invocation_states))?, - 82 => listener.enter_function_pointer_unmanaged_calling_convention(&FunctionPointerUnmanagedCallingConventionContext::__from_listener_node(context, invocation_states))?, - 83 => listener.enter_function_pointer_parameter_list(&FunctionPointerParameterListContext::__from_listener_node(context, invocation_states))?, - 84 => listener.enter_function_pointer_parameter(&FunctionPointerParameterContext::__from_listener_node(context, invocation_states))?, - 85 => listener.enter_predefined_type(&PredefinedTypeContext::__from_listener_node(context, invocation_states))?, - 86 => listener.enter_ref_type(&RefTypeContext::__from_listener_node(context, invocation_states))?, - 87 => listener.enter_scoped_type(&ScopedTypeContext::__from_listener_node(context, invocation_states))?, - 88 => listener.enter_tuple_type(&TupleTypeContext::__from_listener_node(context, invocation_states))?, - 89 => listener.enter_tuple_element(&TupleElementContext::__from_listener_node(context, invocation_states))?, - 90 => listener.enter_statement(&StatementContext::__from_listener_node(context, invocation_states))?, - 91 => listener.enter_break_statement(&BreakStatementContext::__from_listener_node(context, invocation_states))?, - 92 => listener.enter_checked_statement(&CheckedStatementContext::__from_listener_node(context, invocation_states))?, - 93 => listener.enter_common_for_each_statement(&CommonForEachStatementContext::__from_listener_node(context, invocation_states))?, - 94 => listener.enter_for_each_statement(&ForEachStatementContext::__from_listener_node(context, invocation_states))?, - 95 => listener.enter_for_each_variable_statement(&ForEachVariableStatementContext::__from_listener_node(context, invocation_states))?, - 96 => listener.enter_continue_statement(&ContinueStatementContext::__from_listener_node(context, invocation_states))?, - 97 => listener.enter_do_statement(&DoStatementContext::__from_listener_node(context, invocation_states))?, - 98 => listener.enter_empty_statement(&EmptyStatementContext::__from_listener_node(context, invocation_states))?, - 99 => listener.enter_expression_statement(&ExpressionStatementContext::__from_listener_node(context, invocation_states))?, - 100 => listener.enter_fixed_statement(&FixedStatementContext::__from_listener_node(context, invocation_states))?, - 101 => listener.enter_for_statement(&ForStatementContext::__from_listener_node(context, invocation_states))?, - 102 => listener.enter_goto_statement(&GotoStatementContext::__from_listener_node(context, invocation_states))?, - 103 => listener.enter_if_statement(&IfStatementContext::__from_listener_node(context, invocation_states))?, - 104 => listener.enter_else_clause(&ElseClauseContext::__from_listener_node(context, invocation_states))?, - 105 => listener.enter_labeled_statement(&LabeledStatementContext::__from_listener_node(context, invocation_states))?, - 106 => listener.enter_local_declaration_statement(&LocalDeclarationStatementContext::__from_listener_node(context, invocation_states))?, - 107 => listener.enter_local_function_statement(&LocalFunctionStatementContext::__from_listener_node(context, invocation_states))?, - 108 => listener.enter_lock_statement(&LockStatementContext::__from_listener_node(context, invocation_states))?, - 109 => listener.enter_return_statement(&ReturnStatementContext::__from_listener_node(context, invocation_states))?, - 110 => listener.enter_switch_statement(&SwitchStatementContext::__from_listener_node(context, invocation_states))?, - 111 => listener.enter_switch_section(&SwitchSectionContext::__from_listener_node(context, invocation_states))?, - 112 => listener.enter_switch_label(&SwitchLabelContext::__from_listener_node(context, invocation_states))?, - 113 => listener.enter_case_pattern_switch_label(&CasePatternSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 114 => listener.enter_pattern(&PatternContext::__from_listener_node(context, invocation_states))?, - 115 => listener.enter_constant_pattern(&ConstantPatternContext::__from_listener_node(context, invocation_states))?, - 116 => listener.enter_declaration_pattern(&DeclarationPatternContext::__from_listener_node(context, invocation_states))?, - 117 => listener.enter_variable_designation(&VariableDesignationContext::__from_listener_node(context, invocation_states))?, - 118 => listener.enter_discard_designation(&DiscardDesignationContext::__from_listener_node(context, invocation_states))?, - 119 => listener.enter_parenthesized_variable_designation(&ParenthesizedVariableDesignationContext::__from_listener_node(context, invocation_states))?, - 120 => listener.enter_single_variable_designation(&SingleVariableDesignationContext::__from_listener_node(context, invocation_states))?, - 121 => listener.enter_discard_pattern(&DiscardPatternContext::__from_listener_node(context, invocation_states))?, - 122 => listener.enter_list_pattern(&ListPatternContext::__from_listener_node(context, invocation_states))?, - 123 => listener.enter_parenthesized_pattern(&ParenthesizedPatternContext::__from_listener_node(context, invocation_states))?, - 124 => listener.enter_recursive_pattern(&RecursivePatternContext::__from_listener_node(context, invocation_states))?, - 125 => listener.enter_positional_pattern_clause(&PositionalPatternClauseContext::__from_listener_node(context, invocation_states))?, - 126 => listener.enter_subpattern(&SubpatternContext::__from_listener_node(context, invocation_states))?, - 127 => listener.enter_base_expression_colon(&BaseExpressionColonContext::__from_listener_node(context, invocation_states))?, - 128 => listener.enter_expression_colon(&ExpressionColonContext::__from_listener_node(context, invocation_states))?, - 129 => listener.enter_property_pattern_clause(&PropertyPatternClauseContext::__from_listener_node(context, invocation_states))?, - 130 => listener.enter_relational_pattern(&RelationalPatternContext::__from_listener_node(context, invocation_states))?, - 131 => listener.enter_slice_pattern(&SlicePatternContext::__from_listener_node(context, invocation_states))?, - 132 => listener.enter_type_pattern(&TypePatternContext::__from_listener_node(context, invocation_states))?, - 133 => listener.enter_unary_pattern(&UnaryPatternContext::__from_listener_node(context, invocation_states))?, - 134 => listener.enter_var_pattern(&VarPatternContext::__from_listener_node(context, invocation_states))?, - 135 => listener.enter_when_clause(&WhenClauseContext::__from_listener_node(context, invocation_states))?, - 136 => listener.enter_case_switch_label(&CaseSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 137 => listener.enter_default_switch_label(&DefaultSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 138 => listener.enter_throw_statement(&ThrowStatementContext::__from_listener_node(context, invocation_states))?, - 139 => listener.enter_try_statement(&TryStatementContext::__from_listener_node(context, invocation_states))?, - 140 => listener.enter_catch_clause(&CatchClauseContext::__from_listener_node(context, invocation_states))?, - 141 => listener.enter_catch_declaration(&CatchDeclarationContext::__from_listener_node(context, invocation_states))?, - 142 => listener.enter_catch_filter_clause(&CatchFilterClauseContext::__from_listener_node(context, invocation_states))?, - 143 => listener.enter_finally_clause(&FinallyClauseContext::__from_listener_node(context, invocation_states))?, - 144 => listener.enter_unsafe_statement(&UnsafeStatementContext::__from_listener_node(context, invocation_states))?, - 145 => listener.enter_using_statement(&UsingStatementContext::__from_listener_node(context, invocation_states))?, - 146 => listener.enter_while_statement(&WhileStatementContext::__from_listener_node(context, invocation_states))?, - 147 => listener.enter_yield_statement(&YieldStatementContext::__from_listener_node(context, invocation_states))?, - 148 => listener.enter_expression(&ExpressionContext::__from_listener_node(context, invocation_states))?, - 149 => listener.enter_anonymous_function_expression(&AnonymousFunctionExpressionContext::__from_listener_node(context, invocation_states))?, - 150 => listener.enter_anonymous_method_expression(&AnonymousMethodExpressionContext::__from_listener_node(context, invocation_states))?, - 151 => listener.enter_lambda_expression(&LambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 152 => listener.enter_parenthesized_lambda_expression(&ParenthesizedLambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 153 => listener.enter_simple_lambda_expression(&SimpleLambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 154 => listener.enter_anonymous_object_creation_expression(&AnonymousObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 155 => listener.enter_anonymous_object_member_declarator(&AnonymousObjectMemberDeclaratorContext::__from_listener_node(context, invocation_states))?, - 156 => listener.enter_array_creation_expression(&ArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 157 => listener.enter_initializer_expression(&InitializerExpressionContext::__from_listener_node(context, invocation_states))?, - 158 => listener.enter_await_expression(&AwaitExpressionContext::__from_listener_node(context, invocation_states))?, - 159 => listener.enter_base_object_creation_expression(&BaseObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 160 => listener.enter_implicit_object_creation_expression(&ImplicitObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 161 => listener.enter_object_creation_expression(&ObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 162 => listener.enter_cast_expression(&CastExpressionContext::__from_listener_node(context, invocation_states))?, - 163 => listener.enter_checked_expression(&CheckedExpressionContext::__from_listener_node(context, invocation_states))?, - 164 => listener.enter_collection_expression(&CollectionExpressionContext::__from_listener_node(context, invocation_states))?, - 165 => listener.enter_collection_element(&CollectionElementContext::__from_listener_node(context, invocation_states))?, - 166 => listener.enter_expression_element(&ExpressionElementContext::__from_listener_node(context, invocation_states))?, - 167 => listener.enter_spread_element(&SpreadElementContext::__from_listener_node(context, invocation_states))?, - 168 => listener.enter_with_element(&WithElementContext::__from_listener_node(context, invocation_states))?, - 169 => listener.enter_declaration_expression(&DeclarationExpressionContext::__from_listener_node(context, invocation_states))?, - 170 => listener.enter_default_expression(&DefaultExpressionContext::__from_listener_node(context, invocation_states))?, - 171 => listener.enter_element_binding_expression(&ElementBindingExpressionContext::__from_listener_node(context, invocation_states))?, - 172 => listener.enter_field_expression(&FieldExpressionContext::__from_listener_node(context, invocation_states))?, - 173 => listener.enter_implicit_array_creation_expression(&ImplicitArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 174 => listener.enter_implicit_element_access(&ImplicitElementAccessContext::__from_listener_node(context, invocation_states))?, - 175 => listener.enter_implicit_stack_alloc_array_creation_expression(&ImplicitStackAllocArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 176 => listener.enter_instance_expression(&InstanceExpressionContext::__from_listener_node(context, invocation_states))?, - 177 => listener.enter_base_expression(&BaseExpressionContext::__from_listener_node(context, invocation_states))?, - 178 => listener.enter_this_expression(&ThisExpressionContext::__from_listener_node(context, invocation_states))?, - 179 => listener.enter_interpolated_string_expression(&InterpolatedStringExpressionContext::__from_listener_node(context, invocation_states))?, - 180 => listener.enter_interpolated_string_content(&InterpolatedStringContentContext::__from_listener_node(context, invocation_states))?, - 181 => listener.enter_interpolated_string_text(&InterpolatedStringTextContext::__from_listener_node(context, invocation_states))?, - 182 => listener.enter_interpolation(&InterpolationContext::__from_listener_node(context, invocation_states))?, - 183 => listener.enter_interpolation_alignment_clause(&InterpolationAlignmentClauseContext::__from_listener_node(context, invocation_states))?, - 184 => listener.enter_interpolation_format_clause(&InterpolationFormatClauseContext::__from_listener_node(context, invocation_states))?, - 185 => listener.enter_interpolated_multi_line_raw_string_start_token(&InterpolatedMultiLineRawStringStartTokenContext::__from_listener_node(context, invocation_states))?, - 186 => listener.enter_interpolated_raw_string_end_token(&InterpolatedRawStringEndTokenContext::__from_listener_node(context, invocation_states))?, - 187 => listener.enter_interpolated_single_line_raw_string_start_token(&InterpolatedSingleLineRawStringStartTokenContext::__from_listener_node(context, invocation_states))?, - 188 => listener.enter_literal_expression(&LiteralExpressionContext::__from_listener_node(context, invocation_states))?, - 189 => listener.enter_utf8_multi_line_raw_string_literal_token(&Utf8MultiLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 190 => listener.enter_utf8_single_line_raw_string_literal_token(&Utf8SingleLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 191 => listener.enter_utf8_string_literal_token(&Utf8StringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 192 => listener.enter_make_ref_expression(&MakeRefExpressionContext::__from_listener_node(context, invocation_states))?, - 193 => listener.enter_member_binding_expression(&MemberBindingExpressionContext::__from_listener_node(context, invocation_states))?, - 194 => listener.enter_parenthesized_expression(&ParenthesizedExpressionContext::__from_listener_node(context, invocation_states))?, - 195 => listener.enter_prefix_unary_expression(&PrefixUnaryExpressionContext::__from_listener_node(context, invocation_states))?, - 196 => listener.enter_query_expression(&QueryExpressionContext::__from_listener_node(context, invocation_states))?, - 197 => listener.enter_from_clause(&FromClauseContext::__from_listener_node(context, invocation_states))?, - 198 => listener.enter_query_body(&QueryBodyContext::__from_listener_node(context, invocation_states))?, - 199 => listener.enter_query_clause(&QueryClauseContext::__from_listener_node(context, invocation_states))?, - 200 => listener.enter_join_clause(&JoinClauseContext::__from_listener_node(context, invocation_states))?, - 201 => listener.enter_join_into_clause(&JoinIntoClauseContext::__from_listener_node(context, invocation_states))?, - 202 => listener.enter_let_clause(&LetClauseContext::__from_listener_node(context, invocation_states))?, - 203 => listener.enter_order_by_clause(&OrderByClauseContext::__from_listener_node(context, invocation_states))?, - 204 => listener.enter_ordering(&OrderingContext::__from_listener_node(context, invocation_states))?, - 205 => listener.enter_where_clause(&WhereClauseContext::__from_listener_node(context, invocation_states))?, - 206 => listener.enter_select_or_group_clause(&SelectOrGroupClauseContext::__from_listener_node(context, invocation_states))?, - 207 => listener.enter_group_clause(&GroupClauseContext::__from_listener_node(context, invocation_states))?, - 208 => listener.enter_select_clause(&SelectClauseContext::__from_listener_node(context, invocation_states))?, - 209 => listener.enter_query_continuation(&QueryContinuationContext::__from_listener_node(context, invocation_states))?, - 210 => listener.enter_ref_expression(&RefExpressionContext::__from_listener_node(context, invocation_states))?, - 211 => listener.enter_ref_type_expression(&RefTypeExpressionContext::__from_listener_node(context, invocation_states))?, - 212 => listener.enter_ref_value_expression(&RefValueExpressionContext::__from_listener_node(context, invocation_states))?, - 213 => listener.enter_size_of_expression(&SizeOfExpressionContext::__from_listener_node(context, invocation_states))?, - 214 => listener.enter_stack_alloc_array_creation_expression(&StackAllocArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 215 => listener.enter_switch_expression_arm(&SwitchExpressionArmContext::__from_listener_node(context, invocation_states))?, - 216 => listener.enter_throw_expression(&ThrowExpressionContext::__from_listener_node(context, invocation_states))?, - 217 => listener.enter_tuple_expression(&TupleExpressionContext::__from_listener_node(context, invocation_states))?, - 218 => listener.enter_type_of_expression(&TypeOfExpressionContext::__from_listener_node(context, invocation_states))?, - 219 => listener.enter_unsafe_expression(&UnsafeExpressionContext::__from_listener_node(context, invocation_states))?, - 220 => listener.enter_syntax_token(&SyntaxTokenContext::__from_listener_node(context, invocation_states))?, - 221 => listener.enter_identifier_token(&IdentifierTokenContext::__from_listener_node(context, invocation_states))?, - 222 => listener.enter_keyword(&KeywordContext::__from_listener_node(context, invocation_states))?, - 223 => listener.enter_numeric_literal_token(&NumericLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 224 => listener.enter_integer_literal_token(&IntegerLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 225 => listener.enter_decimal_integer_literal_token(&DecimalIntegerLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 226 => listener.enter_hexadecimal_integer_literal_token(&HexadecimalIntegerLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 227 => listener.enter_real_literal_token(&RealLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 228 => listener.enter_character_literal_token(&CharacterLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 229 => listener.enter_string_literal_token(&StringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 230 => listener.enter_regular_string_literal_token(&RegularStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 231 => listener.enter_verbatim_string_literal_token(&VerbatimStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 232 => listener.enter_operator_token(&OperatorTokenContext::__from_listener_node(context, invocation_states))?, - 233 => listener.enter_punctuation_token(&PunctuationTokenContext::__from_listener_node(context, invocation_states))?, - 234 => listener.enter_interpolated_string_text_token(&InterpolatedStringTextTokenContext::__from_listener_node(context, invocation_states))?, - 235 => listener.enter_multi_line_raw_string_literal_token(&MultiLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 236 => listener.enter_single_line_raw_string_literal_token(&SingleLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 237 => listener.enter_record_keyword(&RecordKeywordContext::__from_listener_node(context, invocation_states))?, - 238 => listener.enter_right_shift(&RightShiftContext::__from_listener_node(context, invocation_states))?, - 239 => listener.enter_unsigned_right_shift(&UnsignedRightShiftContext::__from_listener_node(context, invocation_states))?, - 240 => listener.enter_right_shift_assignment(&RightShiftAssignmentContext::__from_listener_node(context, invocation_states))?, - 241 => listener.enter_unsigned_right_shift_assignment(&UnsignedRightShiftAssignmentContext::__from_listener_node(context, invocation_states))?, - 242 => listener.enter_local_variable_declaration(&LocalVariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 243 => listener.enter_local_variable_declarator(&LocalVariableDeclaratorContext::__from_listener_node(context, invocation_states))?, - _ => {} - } - Ok(()) - }, - exit: |listener, context, invocation_states| { - match __context_kind(context) { - 0 => listener.exit_compilation_unit(&CompilationUnitContext::__from_listener_node(context, invocation_states))?, - 1 => listener.exit_extern_alias_directive(&ExternAliasDirectiveContext::__from_listener_node(context, invocation_states))?, - 2 => listener.exit_using_directive(&UsingDirectiveContext::__from_listener_node(context, invocation_states))?, - 3 => listener.exit_name_equals(&NameEqualsContext::__from_listener_node(context, invocation_states))?, - 4 => listener.exit_identifier_name(&IdentifierNameContext::__from_listener_node(context, invocation_states))?, - 5 => listener.exit_attribute_list(&AttributeListContext::__from_listener_node(context, invocation_states))?, - 6 => listener.exit_attribute_target_specifier(&AttributeTargetSpecifierContext::__from_listener_node(context, invocation_states))?, - 7 => listener.exit_attribute(&AttributeContext::__from_listener_node(context, invocation_states))?, - 8 => listener.exit_name(&NameContext::__from_listener_node(context, invocation_states))?, - 9 => listener.exit_alias_qualified_name(&AliasQualifiedNameContext::__from_listener_node(context, invocation_states))?, - 10 => listener.exit_simple_name(&SimpleNameContext::__from_listener_node(context, invocation_states))?, - 11 => listener.exit_generic_name(&GenericNameContext::__from_listener_node(context, invocation_states))?, - 12 => listener.exit_type_argument_list(&TypeArgumentListContext::__from_listener_node(context, invocation_states))?, - 13 => listener.exit_attribute_argument_list(&AttributeArgumentListContext::__from_listener_node(context, invocation_states))?, - 14 => listener.exit_attribute_argument(&AttributeArgumentContext::__from_listener_node(context, invocation_states))?, - 15 => listener.exit_name_colon(&NameColonContext::__from_listener_node(context, invocation_states))?, - 16 => listener.exit_member_declaration(&MemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 17 => listener.exit_base_field_declaration(&BaseFieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 18 => listener.exit_event_field_declaration(&EventFieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 19 => listener.exit_modifier(&ModifierContext::__from_listener_node(context, invocation_states))?, - 20 => listener.exit_variable_declaration(&VariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 21 => listener.exit_variable_declarator(&VariableDeclaratorContext::__from_listener_node(context, invocation_states))?, - 22 => listener.exit_bracketed_argument_list(&BracketedArgumentListContext::__from_listener_node(context, invocation_states))?, - 23 => listener.exit_argument(&ArgumentContext::__from_listener_node(context, invocation_states))?, - 24 => listener.exit_equals_value_clause(&EqualsValueClauseContext::__from_listener_node(context, invocation_states))?, - 25 => listener.exit_field_declaration(&FieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 26 => listener.exit_base_method_declaration(&BaseMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 27 => listener.exit_constructor_declaration(&ConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 28 => listener.exit_parameter_list(&ParameterListContext::__from_listener_node(context, invocation_states))?, - 29 => listener.exit_parameter(&ParameterContext::__from_listener_node(context, invocation_states))?, - 30 => listener.exit_constructor_initializer(&ConstructorInitializerContext::__from_listener_node(context, invocation_states))?, - 31 => listener.exit_argument_list(&ArgumentListContext::__from_listener_node(context, invocation_states))?, - 32 => listener.exit_block(&BlockContext::__from_listener_node(context, invocation_states))?, - 33 => listener.exit_arrow_expression_clause(&ArrowExpressionClauseContext::__from_listener_node(context, invocation_states))?, - 34 => listener.exit_conversion_operator_declaration(&ConversionOperatorDeclarationContext::__from_listener_node(context, invocation_states))?, - 35 => listener.exit_explicit_interface_specifier(&ExplicitInterfaceSpecifierContext::__from_listener_node(context, invocation_states))?, - 36 => listener.exit_destructor_declaration(&DestructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 37 => listener.exit_method_declaration(&MethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 38 => listener.exit_type_parameter_list(&TypeParameterListContext::__from_listener_node(context, invocation_states))?, - 39 => listener.exit_type_parameter(&TypeParameterContext::__from_listener_node(context, invocation_states))?, - 40 => listener.exit_type_parameter_constraint_clause(&TypeParameterConstraintClauseContext::__from_listener_node(context, invocation_states))?, - 41 => listener.exit_type_parameter_constraint(&TypeParameterConstraintContext::__from_listener_node(context, invocation_states))?, - 42 => listener.exit_allows_constraint_clause(&AllowsConstraintClauseContext::__from_listener_node(context, invocation_states))?, - 43 => listener.exit_allows_constraint(&AllowsConstraintContext::__from_listener_node(context, invocation_states))?, - 44 => listener.exit_ref_struct_constraint(&RefStructConstraintContext::__from_listener_node(context, invocation_states))?, - 45 => listener.exit_class_or_struct_constraint(&ClassOrStructConstraintContext::__from_listener_node(context, invocation_states))?, - 46 => listener.exit_constructor_constraint(&ConstructorConstraintContext::__from_listener_node(context, invocation_states))?, - 47 => listener.exit_default_constraint(&DefaultConstraintContext::__from_listener_node(context, invocation_states))?, - 48 => listener.exit_type_constraint(&TypeConstraintContext::__from_listener_node(context, invocation_states))?, - 49 => listener.exit_operator_declaration(&OperatorDeclarationContext::__from_listener_node(context, invocation_states))?, - 50 => listener.exit_base_namespace_declaration(&BaseNamespaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 51 => listener.exit_file_scoped_namespace_declaration(&FileScopedNamespaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 52 => listener.exit_namespace_declaration(&NamespaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 53 => listener.exit_base_property_declaration(&BasePropertyDeclarationContext::__from_listener_node(context, invocation_states))?, - 54 => listener.exit_event_declaration(&EventDeclarationContext::__from_listener_node(context, invocation_states))?, - 55 => listener.exit_accessor_list(&AccessorListContext::__from_listener_node(context, invocation_states))?, - 56 => listener.exit_accessor_declaration(&AccessorDeclarationContext::__from_listener_node(context, invocation_states))?, - 57 => listener.exit_indexer_declaration(&IndexerDeclarationContext::__from_listener_node(context, invocation_states))?, - 58 => listener.exit_bracketed_parameter_list(&BracketedParameterListContext::__from_listener_node(context, invocation_states))?, - 59 => listener.exit_property_declaration(&PropertyDeclarationContext::__from_listener_node(context, invocation_states))?, - 60 => listener.exit_base_type_declaration(&BaseTypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 61 => listener.exit_enum_declaration(&EnumDeclarationContext::__from_listener_node(context, invocation_states))?, - 62 => listener.exit_base_list(&BaseListContext::__from_listener_node(context, invocation_states))?, - 63 => listener.exit_base_type(&BaseTypeContext::__from_listener_node(context, invocation_states))?, - 64 => listener.exit_primary_constructor_base_type(&PrimaryConstructorBaseTypeContext::__from_listener_node(context, invocation_states))?, - 65 => listener.exit_simple_base_type(&SimpleBaseTypeContext::__from_listener_node(context, invocation_states))?, - 66 => listener.exit_enum_member_declaration(&EnumMemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 67 => listener.exit_type_declaration(&TypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 68 => listener.exit_class_declaration(&ClassDeclarationContext::__from_listener_node(context, invocation_states))?, - 69 => listener.exit_extension_block_declaration(&ExtensionBlockDeclarationContext::__from_listener_node(context, invocation_states))?, - 70 => listener.exit_interface_declaration(&InterfaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 71 => listener.exit_record_declaration(&RecordDeclarationContext::__from_listener_node(context, invocation_states))?, - 72 => listener.exit_struct_declaration(&StructDeclarationContext::__from_listener_node(context, invocation_states))?, - 73 => listener.exit_union_declaration(&UnionDeclarationContext::__from_listener_node(context, invocation_states))?, - 74 => listener.exit_delegate_declaration(&DelegateDeclarationContext::__from_listener_node(context, invocation_states))?, - 75 => listener.exit_global_statement(&GlobalStatementContext::__from_listener_node(context, invocation_states))?, - 76 => listener.exit_type(&TypeContext::__from_listener_node(context, invocation_states))?, - 77 => listener.exit_array_type(&ArrayTypeContext::__from_listener_node(context, invocation_states))?, - 78 => listener.exit_array_rank_specifier(&ArrayRankSpecifierContext::__from_listener_node(context, invocation_states))?, - 79 => listener.exit_function_pointer_type(&FunctionPointerTypeContext::__from_listener_node(context, invocation_states))?, - 80 => listener.exit_function_pointer_calling_convention(&FunctionPointerCallingConventionContext::__from_listener_node(context, invocation_states))?, - 81 => listener.exit_function_pointer_unmanaged_calling_convention_list(&FunctionPointerUnmanagedCallingConventionListContext::__from_listener_node(context, invocation_states))?, - 82 => listener.exit_function_pointer_unmanaged_calling_convention(&FunctionPointerUnmanagedCallingConventionContext::__from_listener_node(context, invocation_states))?, - 83 => listener.exit_function_pointer_parameter_list(&FunctionPointerParameterListContext::__from_listener_node(context, invocation_states))?, - 84 => listener.exit_function_pointer_parameter(&FunctionPointerParameterContext::__from_listener_node(context, invocation_states))?, - 85 => listener.exit_predefined_type(&PredefinedTypeContext::__from_listener_node(context, invocation_states))?, - 86 => listener.exit_ref_type(&RefTypeContext::__from_listener_node(context, invocation_states))?, - 87 => listener.exit_scoped_type(&ScopedTypeContext::__from_listener_node(context, invocation_states))?, - 88 => listener.exit_tuple_type(&TupleTypeContext::__from_listener_node(context, invocation_states))?, - 89 => listener.exit_tuple_element(&TupleElementContext::__from_listener_node(context, invocation_states))?, - 90 => listener.exit_statement(&StatementContext::__from_listener_node(context, invocation_states))?, - 91 => listener.exit_break_statement(&BreakStatementContext::__from_listener_node(context, invocation_states))?, - 92 => listener.exit_checked_statement(&CheckedStatementContext::__from_listener_node(context, invocation_states))?, - 93 => listener.exit_common_for_each_statement(&CommonForEachStatementContext::__from_listener_node(context, invocation_states))?, - 94 => listener.exit_for_each_statement(&ForEachStatementContext::__from_listener_node(context, invocation_states))?, - 95 => listener.exit_for_each_variable_statement(&ForEachVariableStatementContext::__from_listener_node(context, invocation_states))?, - 96 => listener.exit_continue_statement(&ContinueStatementContext::__from_listener_node(context, invocation_states))?, - 97 => listener.exit_do_statement(&DoStatementContext::__from_listener_node(context, invocation_states))?, - 98 => listener.exit_empty_statement(&EmptyStatementContext::__from_listener_node(context, invocation_states))?, - 99 => listener.exit_expression_statement(&ExpressionStatementContext::__from_listener_node(context, invocation_states))?, - 100 => listener.exit_fixed_statement(&FixedStatementContext::__from_listener_node(context, invocation_states))?, - 101 => listener.exit_for_statement(&ForStatementContext::__from_listener_node(context, invocation_states))?, - 102 => listener.exit_goto_statement(&GotoStatementContext::__from_listener_node(context, invocation_states))?, - 103 => listener.exit_if_statement(&IfStatementContext::__from_listener_node(context, invocation_states))?, - 104 => listener.exit_else_clause(&ElseClauseContext::__from_listener_node(context, invocation_states))?, - 105 => listener.exit_labeled_statement(&LabeledStatementContext::__from_listener_node(context, invocation_states))?, - 106 => listener.exit_local_declaration_statement(&LocalDeclarationStatementContext::__from_listener_node(context, invocation_states))?, - 107 => listener.exit_local_function_statement(&LocalFunctionStatementContext::__from_listener_node(context, invocation_states))?, - 108 => listener.exit_lock_statement(&LockStatementContext::__from_listener_node(context, invocation_states))?, - 109 => listener.exit_return_statement(&ReturnStatementContext::__from_listener_node(context, invocation_states))?, - 110 => listener.exit_switch_statement(&SwitchStatementContext::__from_listener_node(context, invocation_states))?, - 111 => listener.exit_switch_section(&SwitchSectionContext::__from_listener_node(context, invocation_states))?, - 112 => listener.exit_switch_label(&SwitchLabelContext::__from_listener_node(context, invocation_states))?, - 113 => listener.exit_case_pattern_switch_label(&CasePatternSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 114 => listener.exit_pattern(&PatternContext::__from_listener_node(context, invocation_states))?, - 115 => listener.exit_constant_pattern(&ConstantPatternContext::__from_listener_node(context, invocation_states))?, - 116 => listener.exit_declaration_pattern(&DeclarationPatternContext::__from_listener_node(context, invocation_states))?, - 117 => listener.exit_variable_designation(&VariableDesignationContext::__from_listener_node(context, invocation_states))?, - 118 => listener.exit_discard_designation(&DiscardDesignationContext::__from_listener_node(context, invocation_states))?, - 119 => listener.exit_parenthesized_variable_designation(&ParenthesizedVariableDesignationContext::__from_listener_node(context, invocation_states))?, - 120 => listener.exit_single_variable_designation(&SingleVariableDesignationContext::__from_listener_node(context, invocation_states))?, - 121 => listener.exit_discard_pattern(&DiscardPatternContext::__from_listener_node(context, invocation_states))?, - 122 => listener.exit_list_pattern(&ListPatternContext::__from_listener_node(context, invocation_states))?, - 123 => listener.exit_parenthesized_pattern(&ParenthesizedPatternContext::__from_listener_node(context, invocation_states))?, - 124 => listener.exit_recursive_pattern(&RecursivePatternContext::__from_listener_node(context, invocation_states))?, - 125 => listener.exit_positional_pattern_clause(&PositionalPatternClauseContext::__from_listener_node(context, invocation_states))?, - 126 => listener.exit_subpattern(&SubpatternContext::__from_listener_node(context, invocation_states))?, - 127 => listener.exit_base_expression_colon(&BaseExpressionColonContext::__from_listener_node(context, invocation_states))?, - 128 => listener.exit_expression_colon(&ExpressionColonContext::__from_listener_node(context, invocation_states))?, - 129 => listener.exit_property_pattern_clause(&PropertyPatternClauseContext::__from_listener_node(context, invocation_states))?, - 130 => listener.exit_relational_pattern(&RelationalPatternContext::__from_listener_node(context, invocation_states))?, - 131 => listener.exit_slice_pattern(&SlicePatternContext::__from_listener_node(context, invocation_states))?, - 132 => listener.exit_type_pattern(&TypePatternContext::__from_listener_node(context, invocation_states))?, - 133 => listener.exit_unary_pattern(&UnaryPatternContext::__from_listener_node(context, invocation_states))?, - 134 => listener.exit_var_pattern(&VarPatternContext::__from_listener_node(context, invocation_states))?, - 135 => listener.exit_when_clause(&WhenClauseContext::__from_listener_node(context, invocation_states))?, - 136 => listener.exit_case_switch_label(&CaseSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 137 => listener.exit_default_switch_label(&DefaultSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 138 => listener.exit_throw_statement(&ThrowStatementContext::__from_listener_node(context, invocation_states))?, - 139 => listener.exit_try_statement(&TryStatementContext::__from_listener_node(context, invocation_states))?, - 140 => listener.exit_catch_clause(&CatchClauseContext::__from_listener_node(context, invocation_states))?, - 141 => listener.exit_catch_declaration(&CatchDeclarationContext::__from_listener_node(context, invocation_states))?, - 142 => listener.exit_catch_filter_clause(&CatchFilterClauseContext::__from_listener_node(context, invocation_states))?, - 143 => listener.exit_finally_clause(&FinallyClauseContext::__from_listener_node(context, invocation_states))?, - 144 => listener.exit_unsafe_statement(&UnsafeStatementContext::__from_listener_node(context, invocation_states))?, - 145 => listener.exit_using_statement(&UsingStatementContext::__from_listener_node(context, invocation_states))?, - 146 => listener.exit_while_statement(&WhileStatementContext::__from_listener_node(context, invocation_states))?, - 147 => listener.exit_yield_statement(&YieldStatementContext::__from_listener_node(context, invocation_states))?, - 148 => listener.exit_expression(&ExpressionContext::__from_listener_node(context, invocation_states))?, - 149 => listener.exit_anonymous_function_expression(&AnonymousFunctionExpressionContext::__from_listener_node(context, invocation_states))?, - 150 => listener.exit_anonymous_method_expression(&AnonymousMethodExpressionContext::__from_listener_node(context, invocation_states))?, - 151 => listener.exit_lambda_expression(&LambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 152 => listener.exit_parenthesized_lambda_expression(&ParenthesizedLambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 153 => listener.exit_simple_lambda_expression(&SimpleLambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 154 => listener.exit_anonymous_object_creation_expression(&AnonymousObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 155 => listener.exit_anonymous_object_member_declarator(&AnonymousObjectMemberDeclaratorContext::__from_listener_node(context, invocation_states))?, - 156 => listener.exit_array_creation_expression(&ArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 157 => listener.exit_initializer_expression(&InitializerExpressionContext::__from_listener_node(context, invocation_states))?, - 158 => listener.exit_await_expression(&AwaitExpressionContext::__from_listener_node(context, invocation_states))?, - 159 => listener.exit_base_object_creation_expression(&BaseObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 160 => listener.exit_implicit_object_creation_expression(&ImplicitObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 161 => listener.exit_object_creation_expression(&ObjectCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 162 => listener.exit_cast_expression(&CastExpressionContext::__from_listener_node(context, invocation_states))?, - 163 => listener.exit_checked_expression(&CheckedExpressionContext::__from_listener_node(context, invocation_states))?, - 164 => listener.exit_collection_expression(&CollectionExpressionContext::__from_listener_node(context, invocation_states))?, - 165 => listener.exit_collection_element(&CollectionElementContext::__from_listener_node(context, invocation_states))?, - 166 => listener.exit_expression_element(&ExpressionElementContext::__from_listener_node(context, invocation_states))?, - 167 => listener.exit_spread_element(&SpreadElementContext::__from_listener_node(context, invocation_states))?, - 168 => listener.exit_with_element(&WithElementContext::__from_listener_node(context, invocation_states))?, - 169 => listener.exit_declaration_expression(&DeclarationExpressionContext::__from_listener_node(context, invocation_states))?, - 170 => listener.exit_default_expression(&DefaultExpressionContext::__from_listener_node(context, invocation_states))?, - 171 => listener.exit_element_binding_expression(&ElementBindingExpressionContext::__from_listener_node(context, invocation_states))?, - 172 => listener.exit_field_expression(&FieldExpressionContext::__from_listener_node(context, invocation_states))?, - 173 => listener.exit_implicit_array_creation_expression(&ImplicitArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 174 => listener.exit_implicit_element_access(&ImplicitElementAccessContext::__from_listener_node(context, invocation_states))?, - 175 => listener.exit_implicit_stack_alloc_array_creation_expression(&ImplicitStackAllocArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 176 => listener.exit_instance_expression(&InstanceExpressionContext::__from_listener_node(context, invocation_states))?, - 177 => listener.exit_base_expression(&BaseExpressionContext::__from_listener_node(context, invocation_states))?, - 178 => listener.exit_this_expression(&ThisExpressionContext::__from_listener_node(context, invocation_states))?, - 179 => listener.exit_interpolated_string_expression(&InterpolatedStringExpressionContext::__from_listener_node(context, invocation_states))?, - 180 => listener.exit_interpolated_string_content(&InterpolatedStringContentContext::__from_listener_node(context, invocation_states))?, - 181 => listener.exit_interpolated_string_text(&InterpolatedStringTextContext::__from_listener_node(context, invocation_states))?, - 182 => listener.exit_interpolation(&InterpolationContext::__from_listener_node(context, invocation_states))?, - 183 => listener.exit_interpolation_alignment_clause(&InterpolationAlignmentClauseContext::__from_listener_node(context, invocation_states))?, - 184 => listener.exit_interpolation_format_clause(&InterpolationFormatClauseContext::__from_listener_node(context, invocation_states))?, - 185 => listener.exit_interpolated_multi_line_raw_string_start_token(&InterpolatedMultiLineRawStringStartTokenContext::__from_listener_node(context, invocation_states))?, - 186 => listener.exit_interpolated_raw_string_end_token(&InterpolatedRawStringEndTokenContext::__from_listener_node(context, invocation_states))?, - 187 => listener.exit_interpolated_single_line_raw_string_start_token(&InterpolatedSingleLineRawStringStartTokenContext::__from_listener_node(context, invocation_states))?, - 188 => listener.exit_literal_expression(&LiteralExpressionContext::__from_listener_node(context, invocation_states))?, - 189 => listener.exit_utf8_multi_line_raw_string_literal_token(&Utf8MultiLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 190 => listener.exit_utf8_single_line_raw_string_literal_token(&Utf8SingleLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 191 => listener.exit_utf8_string_literal_token(&Utf8StringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 192 => listener.exit_make_ref_expression(&MakeRefExpressionContext::__from_listener_node(context, invocation_states))?, - 193 => listener.exit_member_binding_expression(&MemberBindingExpressionContext::__from_listener_node(context, invocation_states))?, - 194 => listener.exit_parenthesized_expression(&ParenthesizedExpressionContext::__from_listener_node(context, invocation_states))?, - 195 => listener.exit_prefix_unary_expression(&PrefixUnaryExpressionContext::__from_listener_node(context, invocation_states))?, - 196 => listener.exit_query_expression(&QueryExpressionContext::__from_listener_node(context, invocation_states))?, - 197 => listener.exit_from_clause(&FromClauseContext::__from_listener_node(context, invocation_states))?, - 198 => listener.exit_query_body(&QueryBodyContext::__from_listener_node(context, invocation_states))?, - 199 => listener.exit_query_clause(&QueryClauseContext::__from_listener_node(context, invocation_states))?, - 200 => listener.exit_join_clause(&JoinClauseContext::__from_listener_node(context, invocation_states))?, - 201 => listener.exit_join_into_clause(&JoinIntoClauseContext::__from_listener_node(context, invocation_states))?, - 202 => listener.exit_let_clause(&LetClauseContext::__from_listener_node(context, invocation_states))?, - 203 => listener.exit_order_by_clause(&OrderByClauseContext::__from_listener_node(context, invocation_states))?, - 204 => listener.exit_ordering(&OrderingContext::__from_listener_node(context, invocation_states))?, - 205 => listener.exit_where_clause(&WhereClauseContext::__from_listener_node(context, invocation_states))?, - 206 => listener.exit_select_or_group_clause(&SelectOrGroupClauseContext::__from_listener_node(context, invocation_states))?, - 207 => listener.exit_group_clause(&GroupClauseContext::__from_listener_node(context, invocation_states))?, - 208 => listener.exit_select_clause(&SelectClauseContext::__from_listener_node(context, invocation_states))?, - 209 => listener.exit_query_continuation(&QueryContinuationContext::__from_listener_node(context, invocation_states))?, - 210 => listener.exit_ref_expression(&RefExpressionContext::__from_listener_node(context, invocation_states))?, - 211 => listener.exit_ref_type_expression(&RefTypeExpressionContext::__from_listener_node(context, invocation_states))?, - 212 => listener.exit_ref_value_expression(&RefValueExpressionContext::__from_listener_node(context, invocation_states))?, - 213 => listener.exit_size_of_expression(&SizeOfExpressionContext::__from_listener_node(context, invocation_states))?, - 214 => listener.exit_stack_alloc_array_creation_expression(&StackAllocArrayCreationExpressionContext::__from_listener_node(context, invocation_states))?, - 215 => listener.exit_switch_expression_arm(&SwitchExpressionArmContext::__from_listener_node(context, invocation_states))?, - 216 => listener.exit_throw_expression(&ThrowExpressionContext::__from_listener_node(context, invocation_states))?, - 217 => listener.exit_tuple_expression(&TupleExpressionContext::__from_listener_node(context, invocation_states))?, - 218 => listener.exit_type_of_expression(&TypeOfExpressionContext::__from_listener_node(context, invocation_states))?, - 219 => listener.exit_unsafe_expression(&UnsafeExpressionContext::__from_listener_node(context, invocation_states))?, - 220 => listener.exit_syntax_token(&SyntaxTokenContext::__from_listener_node(context, invocation_states))?, - 221 => listener.exit_identifier_token(&IdentifierTokenContext::__from_listener_node(context, invocation_states))?, - 222 => listener.exit_keyword(&KeywordContext::__from_listener_node(context, invocation_states))?, - 223 => listener.exit_numeric_literal_token(&NumericLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 224 => listener.exit_integer_literal_token(&IntegerLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 225 => listener.exit_decimal_integer_literal_token(&DecimalIntegerLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 226 => listener.exit_hexadecimal_integer_literal_token(&HexadecimalIntegerLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 227 => listener.exit_real_literal_token(&RealLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 228 => listener.exit_character_literal_token(&CharacterLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 229 => listener.exit_string_literal_token(&StringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 230 => listener.exit_regular_string_literal_token(&RegularStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 231 => listener.exit_verbatim_string_literal_token(&VerbatimStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 232 => listener.exit_operator_token(&OperatorTokenContext::__from_listener_node(context, invocation_states))?, - 233 => listener.exit_punctuation_token(&PunctuationTokenContext::__from_listener_node(context, invocation_states))?, - 234 => listener.exit_interpolated_string_text_token(&InterpolatedStringTextTokenContext::__from_listener_node(context, invocation_states))?, - 235 => listener.exit_multi_line_raw_string_literal_token(&MultiLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 236 => listener.exit_single_line_raw_string_literal_token(&SingleLineRawStringLiteralTokenContext::__from_listener_node(context, invocation_states))?, - 237 => listener.exit_record_keyword(&RecordKeywordContext::__from_listener_node(context, invocation_states))?, - 238 => listener.exit_right_shift(&RightShiftContext::__from_listener_node(context, invocation_states))?, - 239 => listener.exit_unsigned_right_shift(&UnsignedRightShiftContext::__from_listener_node(context, invocation_states))?, - 240 => listener.exit_right_shift_assignment(&RightShiftAssignmentContext::__from_listener_node(context, invocation_states))?, - 241 => listener.exit_unsigned_right_shift_assignment(&UnsignedRightShiftAssignmentContext::__from_listener_node(context, invocation_states))?, - 242 => listener.exit_local_variable_declaration(&LocalVariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 243 => listener.exit_local_variable_declarator(&LocalVariableDeclaratorContext::__from_listener_node(context, invocation_states))?, - _ => {} - } - listener.exit_every_rule(context) - }, - terminal: |listener, node| { - listener.visit_terminal(&TerminalNode::new(node)) - }, - error: |listener, node| { - listener.visit_error_node(&ErrorNode::new(node)) - }, -} - -#[allow(dead_code)] -pub struct CSharpTreeWalker; - -#[allow(dead_code)] -impl CSharpTreeWalker { - pub fn walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - ) -> Result<(), E> { - Self::__walk(listener, tree, None) - } - - pub fn walk_with_invocation_states>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - parent_invocation_states: Vec, - ) -> Result<(), E> { - Self::__walk(listener, tree, Some(parent_invocation_states)) - } - - fn __walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - invocation_states: Option>, - ) -> Result<(), E> { - let mut callbacks = __CSharpTreeWalkerCallbacks(listener); - antlr4_runtime::generated::walk_generated(tree, invocation_states, &mut callbacks) - } -} - -pub type ParseTreeWalker = CSharpTreeWalker; - -#[allow(dead_code, unused_variables)] -pub trait CSharpValidatedListener { - fn walk(&mut self, tree: ValidatedRuleNode<'_>) -> Result<(), E> - where - Self: Sized, - { - CSharpValidatedTreeWalker::walk(self, tree) - } - - fn enter_every_rule(&mut self, _ctx: ValidatedRuleNode<'_>) -> Result<(), E> { Ok(()) } - fn exit_every_rule(&mut self, _ctx: ValidatedRuleNode<'_>) -> Result<(), E> { Ok(()) } - - fn enter_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn exit_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn enter_extern_alias_directive(&mut self, _ctx: &ExternAliasDirectiveContext) -> Result<(), E> { Ok(()) } - fn exit_extern_alias_directive(&mut self, _ctx: &ExternAliasDirectiveContext) -> Result<(), E> { Ok(()) } - fn enter_using_directive(&mut self, _ctx: &UsingDirectiveContext) -> Result<(), E> { Ok(()) } - fn exit_using_directive(&mut self, _ctx: &UsingDirectiveContext) -> Result<(), E> { Ok(()) } - fn enter_name_equals(&mut self, _ctx: &NameEqualsContext) -> Result<(), E> { Ok(()) } - fn exit_name_equals(&mut self, _ctx: &NameEqualsContext) -> Result<(), E> { Ok(()) } - fn enter_identifier_name(&mut self, _ctx: &IdentifierNameContext) -> Result<(), E> { Ok(()) } - fn exit_identifier_name(&mut self, _ctx: &IdentifierNameContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_list(&mut self, _ctx: &AttributeListContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_list(&mut self, _ctx: &AttributeListContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_target_specifier(&mut self, _ctx: &AttributeTargetSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_target_specifier(&mut self, _ctx: &AttributeTargetSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_attribute(&mut self, _ctx: &AttributeContext) -> Result<(), E> { Ok(()) } - fn exit_attribute(&mut self, _ctx: &AttributeContext) -> Result<(), E> { Ok(()) } - fn enter_name(&mut self, _ctx: &NameContext) -> Result<(), E> { Ok(()) } - fn exit_name(&mut self, _ctx: &NameContext) -> Result<(), E> { Ok(()) } - fn enter_alias_qualified_name(&mut self, _ctx: &AliasQualifiedNameContext) -> Result<(), E> { Ok(()) } - fn exit_alias_qualified_name(&mut self, _ctx: &AliasQualifiedNameContext) -> Result<(), E> { Ok(()) } - fn enter_simple_name(&mut self, _ctx: &SimpleNameContext) -> Result<(), E> { Ok(()) } - fn exit_simple_name(&mut self, _ctx: &SimpleNameContext) -> Result<(), E> { Ok(()) } - fn enter_generic_name(&mut self, _ctx: &GenericNameContext) -> Result<(), E> { Ok(()) } - fn exit_generic_name(&mut self, _ctx: &GenericNameContext) -> Result<(), E> { Ok(()) } - fn enter_type_argument_list(&mut self, _ctx: &TypeArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_type_argument_list(&mut self, _ctx: &TypeArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_argument_list(&mut self, _ctx: &AttributeArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_argument_list(&mut self, _ctx: &AttributeArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_attribute_argument(&mut self, _ctx: &AttributeArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_attribute_argument(&mut self, _ctx: &AttributeArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_name_colon(&mut self, _ctx: &NameColonContext) -> Result<(), E> { Ok(()) } - fn exit_name_colon(&mut self, _ctx: &NameColonContext) -> Result<(), E> { Ok(()) } - fn enter_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_field_declaration(&mut self, _ctx: &BaseFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_field_declaration(&mut self, _ctx: &BaseFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_event_field_declaration(&mut self, _ctx: &EventFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_event_field_declaration(&mut self, _ctx: &EventFieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn exit_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_bracketed_argument_list(&mut self, _ctx: &BracketedArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_bracketed_argument_list(&mut self, _ctx: &BracketedArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_argument(&mut self, _ctx: &ArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_argument(&mut self, _ctx: &ArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_equals_value_clause(&mut self, _ctx: &EqualsValueClauseContext) -> Result<(), E> { Ok(()) } - fn exit_equals_value_clause(&mut self, _ctx: &EqualsValueClauseContext) -> Result<(), E> { Ok(()) } - fn enter_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_method_declaration(&mut self, _ctx: &BaseMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_method_declaration(&mut self, _ctx: &BaseMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_list(&mut self, _ctx: &ParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_list(&mut self, _ctx: &ParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn exit_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_initializer(&mut self, _ctx: &ConstructorInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_initializer(&mut self, _ctx: &ConstructorInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_argument_list(&mut self, _ctx: &ArgumentListContext) -> Result<(), E> { Ok(()) } - fn exit_argument_list(&mut self, _ctx: &ArgumentListContext) -> Result<(), E> { Ok(()) } - fn enter_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn exit_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn enter_arrow_expression_clause(&mut self, _ctx: &ArrowExpressionClauseContext) -> Result<(), E> { Ok(()) } - fn exit_arrow_expression_clause(&mut self, _ctx: &ArrowExpressionClauseContext) -> Result<(), E> { Ok(()) } - fn enter_conversion_operator_declaration(&mut self, _ctx: &ConversionOperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_conversion_operator_declaration(&mut self, _ctx: &ConversionOperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_interface_specifier(&mut self, _ctx: &ExplicitInterfaceSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_interface_specifier(&mut self, _ctx: &ExplicitInterfaceSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_destructor_declaration(&mut self, _ctx: &DestructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_destructor_declaration(&mut self, _ctx: &DestructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_list(&mut self, _ctx: &TypeParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_list(&mut self, _ctx: &TypeParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_constraint_clause(&mut self, _ctx: &TypeParameterConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_constraint_clause(&mut self, _ctx: &TypeParameterConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_constraint(&mut self, _ctx: &TypeParameterConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_constraint(&mut self, _ctx: &TypeParameterConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_allows_constraint_clause(&mut self, _ctx: &AllowsConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn exit_allows_constraint_clause(&mut self, _ctx: &AllowsConstraintClauseContext) -> Result<(), E> { Ok(()) } - fn enter_allows_constraint(&mut self, _ctx: &AllowsConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_allows_constraint(&mut self, _ctx: &AllowsConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_ref_struct_constraint(&mut self, _ctx: &RefStructConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_ref_struct_constraint(&mut self, _ctx: &RefStructConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_class_or_struct_constraint(&mut self, _ctx: &ClassOrStructConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_class_or_struct_constraint(&mut self, _ctx: &ClassOrStructConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_constraint(&mut self, _ctx: &ConstructorConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_constraint(&mut self, _ctx: &ConstructorConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_default_constraint(&mut self, _ctx: &DefaultConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_default_constraint(&mut self, _ctx: &DefaultConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_operator_declaration(&mut self, _ctx: &OperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_operator_declaration(&mut self, _ctx: &OperatorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_namespace_declaration(&mut self, _ctx: &BaseNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_namespace_declaration(&mut self, _ctx: &BaseNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_file_scoped_namespace_declaration(&mut self, _ctx: &FileScopedNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_file_scoped_namespace_declaration(&mut self, _ctx: &FileScopedNamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_namespace_declaration(&mut self, _ctx: &NamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_namespace_declaration(&mut self, _ctx: &NamespaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_property_declaration(&mut self, _ctx: &BasePropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_property_declaration(&mut self, _ctx: &BasePropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_event_declaration(&mut self, _ctx: &EventDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_event_declaration(&mut self, _ctx: &EventDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_accessor_list(&mut self, _ctx: &AccessorListContext) -> Result<(), E> { Ok(()) } - fn exit_accessor_list(&mut self, _ctx: &AccessorListContext) -> Result<(), E> { Ok(()) } - fn enter_accessor_declaration(&mut self, _ctx: &AccessorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_accessor_declaration(&mut self, _ctx: &AccessorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_indexer_declaration(&mut self, _ctx: &IndexerDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_indexer_declaration(&mut self, _ctx: &IndexerDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_bracketed_parameter_list(&mut self, _ctx: &BracketedParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_bracketed_parameter_list(&mut self, _ctx: &BracketedParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_type_declaration(&mut self, _ctx: &BaseTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_base_type_declaration(&mut self, _ctx: &BaseTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_base_list(&mut self, _ctx: &BaseListContext) -> Result<(), E> { Ok(()) } - fn exit_base_list(&mut self, _ctx: &BaseListContext) -> Result<(), E> { Ok(()) } - fn enter_base_type(&mut self, _ctx: &BaseTypeContext) -> Result<(), E> { Ok(()) } - fn exit_base_type(&mut self, _ctx: &BaseTypeContext) -> Result<(), E> { Ok(()) } - fn enter_primary_constructor_base_type(&mut self, _ctx: &PrimaryConstructorBaseTypeContext) -> Result<(), E> { Ok(()) } - fn exit_primary_constructor_base_type(&mut self, _ctx: &PrimaryConstructorBaseTypeContext) -> Result<(), E> { Ok(()) } - fn enter_simple_base_type(&mut self, _ctx: &SimpleBaseTypeContext) -> Result<(), E> { Ok(()) } - fn exit_simple_base_type(&mut self, _ctx: &SimpleBaseTypeContext) -> Result<(), E> { Ok(()) } - fn enter_enum_member_declaration(&mut self, _ctx: &EnumMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_enum_member_declaration(&mut self, _ctx: &EnumMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_extension_block_declaration(&mut self, _ctx: &ExtensionBlockDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_extension_block_declaration(&mut self, _ctx: &ExtensionBlockDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_struct_declaration(&mut self, _ctx: &StructDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_struct_declaration(&mut self, _ctx: &StructDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_union_declaration(&mut self, _ctx: &UnionDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_union_declaration(&mut self, _ctx: &UnionDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_delegate_declaration(&mut self, _ctx: &DelegateDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_delegate_declaration(&mut self, _ctx: &DelegateDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_global_statement(&mut self, _ctx: &GlobalStatementContext) -> Result<(), E> { Ok(()) } - fn exit_global_statement(&mut self, _ctx: &GlobalStatementContext) -> Result<(), E> { Ok(()) } - fn enter_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn exit_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn enter_array_type(&mut self, _ctx: &ArrayTypeContext) -> Result<(), E> { Ok(()) } - fn exit_array_type(&mut self, _ctx: &ArrayTypeContext) -> Result<(), E> { Ok(()) } - fn enter_array_rank_specifier(&mut self, _ctx: &ArrayRankSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_array_rank_specifier(&mut self, _ctx: &ArrayRankSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_type(&mut self, _ctx: &FunctionPointerTypeContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_type(&mut self, _ctx: &FunctionPointerTypeContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_calling_convention(&mut self, _ctx: &FunctionPointerCallingConventionContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_calling_convention(&mut self, _ctx: &FunctionPointerCallingConventionContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_unmanaged_calling_convention_list(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionListContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_unmanaged_calling_convention_list(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionListContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_unmanaged_calling_convention(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_unmanaged_calling_convention(&mut self, _ctx: &FunctionPointerUnmanagedCallingConventionContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_parameter_list(&mut self, _ctx: &FunctionPointerParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_parameter_list(&mut self, _ctx: &FunctionPointerParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_function_pointer_parameter(&mut self, _ctx: &FunctionPointerParameterContext) -> Result<(), E> { Ok(()) } - fn exit_function_pointer_parameter(&mut self, _ctx: &FunctionPointerParameterContext) -> Result<(), E> { Ok(()) } - fn enter_predefined_type(&mut self, _ctx: &PredefinedTypeContext) -> Result<(), E> { Ok(()) } - fn exit_predefined_type(&mut self, _ctx: &PredefinedTypeContext) -> Result<(), E> { Ok(()) } - fn enter_ref_type(&mut self, _ctx: &RefTypeContext) -> Result<(), E> { Ok(()) } - fn exit_ref_type(&mut self, _ctx: &RefTypeContext) -> Result<(), E> { Ok(()) } - fn enter_scoped_type(&mut self, _ctx: &ScopedTypeContext) -> Result<(), E> { Ok(()) } - fn exit_scoped_type(&mut self, _ctx: &ScopedTypeContext) -> Result<(), E> { Ok(()) } - fn enter_tuple_type(&mut self, _ctx: &TupleTypeContext) -> Result<(), E> { Ok(()) } - fn exit_tuple_type(&mut self, _ctx: &TupleTypeContext) -> Result<(), E> { Ok(()) } - fn enter_tuple_element(&mut self, _ctx: &TupleElementContext) -> Result<(), E> { Ok(()) } - fn exit_tuple_element(&mut self, _ctx: &TupleElementContext) -> Result<(), E> { Ok(()) } - fn enter_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn exit_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn enter_break_statement(&mut self, _ctx: &BreakStatementContext) -> Result<(), E> { Ok(()) } - fn exit_break_statement(&mut self, _ctx: &BreakStatementContext) -> Result<(), E> { Ok(()) } - fn enter_checked_statement(&mut self, _ctx: &CheckedStatementContext) -> Result<(), E> { Ok(()) } - fn exit_checked_statement(&mut self, _ctx: &CheckedStatementContext) -> Result<(), E> { Ok(()) } - fn enter_common_for_each_statement(&mut self, _ctx: &CommonForEachStatementContext) -> Result<(), E> { Ok(()) } - fn exit_common_for_each_statement(&mut self, _ctx: &CommonForEachStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_each_statement(&mut self, _ctx: &ForEachStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_each_statement(&mut self, _ctx: &ForEachStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_each_variable_statement(&mut self, _ctx: &ForEachVariableStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_each_variable_statement(&mut self, _ctx: &ForEachVariableStatementContext) -> Result<(), E> { Ok(()) } - fn enter_continue_statement(&mut self, _ctx: &ContinueStatementContext) -> Result<(), E> { Ok(()) } - fn exit_continue_statement(&mut self, _ctx: &ContinueStatementContext) -> Result<(), E> { Ok(()) } - fn enter_do_statement(&mut self, _ctx: &DoStatementContext) -> Result<(), E> { Ok(()) } - fn exit_do_statement(&mut self, _ctx: &DoStatementContext) -> Result<(), E> { Ok(()) } - fn enter_empty_statement(&mut self, _ctx: &EmptyStatementContext) -> Result<(), E> { Ok(()) } - fn exit_empty_statement(&mut self, _ctx: &EmptyStatementContext) -> Result<(), E> { Ok(()) } - fn enter_expression_statement(&mut self, _ctx: &ExpressionStatementContext) -> Result<(), E> { Ok(()) } - fn exit_expression_statement(&mut self, _ctx: &ExpressionStatementContext) -> Result<(), E> { Ok(()) } - fn enter_fixed_statement(&mut self, _ctx: &FixedStatementContext) -> Result<(), E> { Ok(()) } - fn exit_fixed_statement(&mut self, _ctx: &FixedStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn enter_goto_statement(&mut self, _ctx: &GotoStatementContext) -> Result<(), E> { Ok(()) } - fn exit_goto_statement(&mut self, _ctx: &GotoStatementContext) -> Result<(), E> { Ok(()) } - fn enter_if_statement(&mut self, _ctx: &IfStatementContext) -> Result<(), E> { Ok(()) } - fn exit_if_statement(&mut self, _ctx: &IfStatementContext) -> Result<(), E> { Ok(()) } - fn enter_else_clause(&mut self, _ctx: &ElseClauseContext) -> Result<(), E> { Ok(()) } - fn exit_else_clause(&mut self, _ctx: &ElseClauseContext) -> Result<(), E> { Ok(()) } - fn enter_labeled_statement(&mut self, _ctx: &LabeledStatementContext) -> Result<(), E> { Ok(()) } - fn exit_labeled_statement(&mut self, _ctx: &LabeledStatementContext) -> Result<(), E> { Ok(()) } - fn enter_local_declaration_statement(&mut self, _ctx: &LocalDeclarationStatementContext) -> Result<(), E> { Ok(()) } - fn exit_local_declaration_statement(&mut self, _ctx: &LocalDeclarationStatementContext) -> Result<(), E> { Ok(()) } - fn enter_local_function_statement(&mut self, _ctx: &LocalFunctionStatementContext) -> Result<(), E> { Ok(()) } - fn exit_local_function_statement(&mut self, _ctx: &LocalFunctionStatementContext) -> Result<(), E> { Ok(()) } - fn enter_lock_statement(&mut self, _ctx: &LockStatementContext) -> Result<(), E> { Ok(()) } - fn exit_lock_statement(&mut self, _ctx: &LockStatementContext) -> Result<(), E> { Ok(()) } - fn enter_return_statement(&mut self, _ctx: &ReturnStatementContext) -> Result<(), E> { Ok(()) } - fn exit_return_statement(&mut self, _ctx: &ReturnStatementContext) -> Result<(), E> { Ok(()) } - fn enter_switch_statement(&mut self, _ctx: &SwitchStatementContext) -> Result<(), E> { Ok(()) } - fn exit_switch_statement(&mut self, _ctx: &SwitchStatementContext) -> Result<(), E> { Ok(()) } - fn enter_switch_section(&mut self, _ctx: &SwitchSectionContext) -> Result<(), E> { Ok(()) } - fn exit_switch_section(&mut self, _ctx: &SwitchSectionContext) -> Result<(), E> { Ok(()) } - fn enter_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_case_pattern_switch_label(&mut self, _ctx: &CasePatternSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_case_pattern_switch_label(&mut self, _ctx: &CasePatternSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn exit_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn enter_constant_pattern(&mut self, _ctx: &ConstantPatternContext) -> Result<(), E> { Ok(()) } - fn exit_constant_pattern(&mut self, _ctx: &ConstantPatternContext) -> Result<(), E> { Ok(()) } - fn enter_declaration_pattern(&mut self, _ctx: &DeclarationPatternContext) -> Result<(), E> { Ok(()) } - fn exit_declaration_pattern(&mut self, _ctx: &DeclarationPatternContext) -> Result<(), E> { Ok(()) } - fn enter_variable_designation(&mut self, _ctx: &VariableDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_variable_designation(&mut self, _ctx: &VariableDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_discard_designation(&mut self, _ctx: &DiscardDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_discard_designation(&mut self, _ctx: &DiscardDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_variable_designation(&mut self, _ctx: &ParenthesizedVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_variable_designation(&mut self, _ctx: &ParenthesizedVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_single_variable_designation(&mut self, _ctx: &SingleVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn exit_single_variable_designation(&mut self, _ctx: &SingleVariableDesignationContext) -> Result<(), E> { Ok(()) } - fn enter_discard_pattern(&mut self, _ctx: &DiscardPatternContext) -> Result<(), E> { Ok(()) } - fn exit_discard_pattern(&mut self, _ctx: &DiscardPatternContext) -> Result<(), E> { Ok(()) } - fn enter_list_pattern(&mut self, _ctx: &ListPatternContext) -> Result<(), E> { Ok(()) } - fn exit_list_pattern(&mut self, _ctx: &ListPatternContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_pattern(&mut self, _ctx: &ParenthesizedPatternContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_pattern(&mut self, _ctx: &ParenthesizedPatternContext) -> Result<(), E> { Ok(()) } - fn enter_recursive_pattern(&mut self, _ctx: &RecursivePatternContext) -> Result<(), E> { Ok(()) } - fn exit_recursive_pattern(&mut self, _ctx: &RecursivePatternContext) -> Result<(), E> { Ok(()) } - fn enter_positional_pattern_clause(&mut self, _ctx: &PositionalPatternClauseContext) -> Result<(), E> { Ok(()) } - fn exit_positional_pattern_clause(&mut self, _ctx: &PositionalPatternClauseContext) -> Result<(), E> { Ok(()) } - fn enter_subpattern(&mut self, _ctx: &SubpatternContext) -> Result<(), E> { Ok(()) } - fn exit_subpattern(&mut self, _ctx: &SubpatternContext) -> Result<(), E> { Ok(()) } - fn enter_base_expression_colon(&mut self, _ctx: &BaseExpressionColonContext) -> Result<(), E> { Ok(()) } - fn exit_base_expression_colon(&mut self, _ctx: &BaseExpressionColonContext) -> Result<(), E> { Ok(()) } - fn enter_expression_colon(&mut self, _ctx: &ExpressionColonContext) -> Result<(), E> { Ok(()) } - fn exit_expression_colon(&mut self, _ctx: &ExpressionColonContext) -> Result<(), E> { Ok(()) } - fn enter_property_pattern_clause(&mut self, _ctx: &PropertyPatternClauseContext) -> Result<(), E> { Ok(()) } - fn exit_property_pattern_clause(&mut self, _ctx: &PropertyPatternClauseContext) -> Result<(), E> { Ok(()) } - fn enter_relational_pattern(&mut self, _ctx: &RelationalPatternContext) -> Result<(), E> { Ok(()) } - fn exit_relational_pattern(&mut self, _ctx: &RelationalPatternContext) -> Result<(), E> { Ok(()) } - fn enter_slice_pattern(&mut self, _ctx: &SlicePatternContext) -> Result<(), E> { Ok(()) } - fn exit_slice_pattern(&mut self, _ctx: &SlicePatternContext) -> Result<(), E> { Ok(()) } - fn enter_type_pattern(&mut self, _ctx: &TypePatternContext) -> Result<(), E> { Ok(()) } - fn exit_type_pattern(&mut self, _ctx: &TypePatternContext) -> Result<(), E> { Ok(()) } - fn enter_unary_pattern(&mut self, _ctx: &UnaryPatternContext) -> Result<(), E> { Ok(()) } - fn exit_unary_pattern(&mut self, _ctx: &UnaryPatternContext) -> Result<(), E> { Ok(()) } - fn enter_var_pattern(&mut self, _ctx: &VarPatternContext) -> Result<(), E> { Ok(()) } - fn exit_var_pattern(&mut self, _ctx: &VarPatternContext) -> Result<(), E> { Ok(()) } - fn enter_when_clause(&mut self, _ctx: &WhenClauseContext) -> Result<(), E> { Ok(()) } - fn exit_when_clause(&mut self, _ctx: &WhenClauseContext) -> Result<(), E> { Ok(()) } - fn enter_case_switch_label(&mut self, _ctx: &CaseSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_case_switch_label(&mut self, _ctx: &CaseSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_default_switch_label(&mut self, _ctx: &DefaultSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_default_switch_label(&mut self, _ctx: &DefaultSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_throw_statement(&mut self, _ctx: &ThrowStatementContext) -> Result<(), E> { Ok(()) } - fn exit_throw_statement(&mut self, _ctx: &ThrowStatementContext) -> Result<(), E> { Ok(()) } - fn enter_try_statement(&mut self, _ctx: &TryStatementContext) -> Result<(), E> { Ok(()) } - fn exit_try_statement(&mut self, _ctx: &TryStatementContext) -> Result<(), E> { Ok(()) } - fn enter_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn exit_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn enter_catch_declaration(&mut self, _ctx: &CatchDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_catch_declaration(&mut self, _ctx: &CatchDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_catch_filter_clause(&mut self, _ctx: &CatchFilterClauseContext) -> Result<(), E> { Ok(()) } - fn exit_catch_filter_clause(&mut self, _ctx: &CatchFilterClauseContext) -> Result<(), E> { Ok(()) } - fn enter_finally_clause(&mut self, _ctx: &FinallyClauseContext) -> Result<(), E> { Ok(()) } - fn exit_finally_clause(&mut self, _ctx: &FinallyClauseContext) -> Result<(), E> { Ok(()) } - fn enter_unsafe_statement(&mut self, _ctx: &UnsafeStatementContext) -> Result<(), E> { Ok(()) } - fn exit_unsafe_statement(&mut self, _ctx: &UnsafeStatementContext) -> Result<(), E> { Ok(()) } - fn enter_using_statement(&mut self, _ctx: &UsingStatementContext) -> Result<(), E> { Ok(()) } - fn exit_using_statement(&mut self, _ctx: &UsingStatementContext) -> Result<(), E> { Ok(()) } - fn enter_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn exit_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn enter_yield_statement(&mut self, _ctx: &YieldStatementContext) -> Result<(), E> { Ok(()) } - fn exit_yield_statement(&mut self, _ctx: &YieldStatementContext) -> Result<(), E> { Ok(()) } - fn enter_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_function_expression(&mut self, _ctx: &AnonymousFunctionExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_function_expression(&mut self, _ctx: &AnonymousFunctionExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_method_expression(&mut self, _ctx: &AnonymousMethodExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_method_expression(&mut self, _ctx: &AnonymousMethodExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_lambda_expression(&mut self, _ctx: &ParenthesizedLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_lambda_expression(&mut self, _ctx: &ParenthesizedLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_simple_lambda_expression(&mut self, _ctx: &SimpleLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_simple_lambda_expression(&mut self, _ctx: &SimpleLambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_object_creation_expression(&mut self, _ctx: &AnonymousObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_object_creation_expression(&mut self, _ctx: &AnonymousObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_object_member_declarator(&mut self, _ctx: &AnonymousObjectMemberDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_object_member_declarator(&mut self, _ctx: &AnonymousObjectMemberDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_array_creation_expression(&mut self, _ctx: &ArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_array_creation_expression(&mut self, _ctx: &ArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_initializer_expression(&mut self, _ctx: &InitializerExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_initializer_expression(&mut self, _ctx: &InitializerExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_await_expression(&mut self, _ctx: &AwaitExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_await_expression(&mut self, _ctx: &AwaitExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_base_object_creation_expression(&mut self, _ctx: &BaseObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_base_object_creation_expression(&mut self, _ctx: &BaseObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_object_creation_expression(&mut self, _ctx: &ImplicitObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_object_creation_expression(&mut self, _ctx: &ImplicitObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_object_creation_expression(&mut self, _ctx: &ObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_object_creation_expression(&mut self, _ctx: &ObjectCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_cast_expression(&mut self, _ctx: &CastExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_cast_expression(&mut self, _ctx: &CastExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_checked_expression(&mut self, _ctx: &CheckedExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_checked_expression(&mut self, _ctx: &CheckedExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_collection_expression(&mut self, _ctx: &CollectionExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_collection_expression(&mut self, _ctx: &CollectionExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_collection_element(&mut self, _ctx: &CollectionElementContext) -> Result<(), E> { Ok(()) } - fn exit_collection_element(&mut self, _ctx: &CollectionElementContext) -> Result<(), E> { Ok(()) } - fn enter_expression_element(&mut self, _ctx: &ExpressionElementContext) -> Result<(), E> { Ok(()) } - fn exit_expression_element(&mut self, _ctx: &ExpressionElementContext) -> Result<(), E> { Ok(()) } - fn enter_spread_element(&mut self, _ctx: &SpreadElementContext) -> Result<(), E> { Ok(()) } - fn exit_spread_element(&mut self, _ctx: &SpreadElementContext) -> Result<(), E> { Ok(()) } - fn enter_with_element(&mut self, _ctx: &WithElementContext) -> Result<(), E> { Ok(()) } - fn exit_with_element(&mut self, _ctx: &WithElementContext) -> Result<(), E> { Ok(()) } - fn enter_declaration_expression(&mut self, _ctx: &DeclarationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_declaration_expression(&mut self, _ctx: &DeclarationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_default_expression(&mut self, _ctx: &DefaultExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_default_expression(&mut self, _ctx: &DefaultExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_element_binding_expression(&mut self, _ctx: &ElementBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_element_binding_expression(&mut self, _ctx: &ElementBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_field_expression(&mut self, _ctx: &FieldExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_field_expression(&mut self, _ctx: &FieldExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_array_creation_expression(&mut self, _ctx: &ImplicitArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_array_creation_expression(&mut self, _ctx: &ImplicitArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_element_access(&mut self, _ctx: &ImplicitElementAccessContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_element_access(&mut self, _ctx: &ImplicitElementAccessContext) -> Result<(), E> { Ok(()) } - fn enter_implicit_stack_alloc_array_creation_expression(&mut self, _ctx: &ImplicitStackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_implicit_stack_alloc_array_creation_expression(&mut self, _ctx: &ImplicitStackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_instance_expression(&mut self, _ctx: &InstanceExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_instance_expression(&mut self, _ctx: &InstanceExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_base_expression(&mut self, _ctx: &BaseExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_base_expression(&mut self, _ctx: &BaseExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_expression(&mut self, _ctx: &InterpolatedStringExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_expression(&mut self, _ctx: &InterpolatedStringExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_content(&mut self, _ctx: &InterpolatedStringContentContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_content(&mut self, _ctx: &InterpolatedStringContentContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_text(&mut self, _ctx: &InterpolatedStringTextContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_text(&mut self, _ctx: &InterpolatedStringTextContext) -> Result<(), E> { Ok(()) } - fn enter_interpolation(&mut self, _ctx: &InterpolationContext) -> Result<(), E> { Ok(()) } - fn exit_interpolation(&mut self, _ctx: &InterpolationContext) -> Result<(), E> { Ok(()) } - fn enter_interpolation_alignment_clause(&mut self, _ctx: &InterpolationAlignmentClauseContext) -> Result<(), E> { Ok(()) } - fn exit_interpolation_alignment_clause(&mut self, _ctx: &InterpolationAlignmentClauseContext) -> Result<(), E> { Ok(()) } - fn enter_interpolation_format_clause(&mut self, _ctx: &InterpolationFormatClauseContext) -> Result<(), E> { Ok(()) } - fn exit_interpolation_format_clause(&mut self, _ctx: &InterpolationFormatClauseContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_multi_line_raw_string_start_token(&mut self, _ctx: &InterpolatedMultiLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_multi_line_raw_string_start_token(&mut self, _ctx: &InterpolatedMultiLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_raw_string_end_token(&mut self, _ctx: &InterpolatedRawStringEndTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_raw_string_end_token(&mut self, _ctx: &InterpolatedRawStringEndTokenContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_single_line_raw_string_start_token(&mut self, _ctx: &InterpolatedSingleLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_single_line_raw_string_start_token(&mut self, _ctx: &InterpolatedSingleLineRawStringStartTokenContext) -> Result<(), E> { Ok(()) } - fn enter_literal_expression(&mut self, _ctx: &LiteralExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_literal_expression(&mut self, _ctx: &LiteralExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_utf8_multi_line_raw_string_literal_token(&mut self, _ctx: &Utf8MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_utf8_multi_line_raw_string_literal_token(&mut self, _ctx: &Utf8MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_utf8_single_line_raw_string_literal_token(&mut self, _ctx: &Utf8SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_utf8_single_line_raw_string_literal_token(&mut self, _ctx: &Utf8SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_utf8_string_literal_token(&mut self, _ctx: &Utf8StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_utf8_string_literal_token(&mut self, _ctx: &Utf8StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_make_ref_expression(&mut self, _ctx: &MakeRefExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_make_ref_expression(&mut self, _ctx: &MakeRefExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_member_binding_expression(&mut self, _ctx: &MemberBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_member_binding_expression(&mut self, _ctx: &MemberBindingExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_query_expression(&mut self, _ctx: &QueryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_query_expression(&mut self, _ctx: &QueryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_from_clause(&mut self, _ctx: &FromClauseContext) -> Result<(), E> { Ok(()) } - fn exit_from_clause(&mut self, _ctx: &FromClauseContext) -> Result<(), E> { Ok(()) } - fn enter_query_body(&mut self, _ctx: &QueryBodyContext) -> Result<(), E> { Ok(()) } - fn exit_query_body(&mut self, _ctx: &QueryBodyContext) -> Result<(), E> { Ok(()) } - fn enter_query_clause(&mut self, _ctx: &QueryClauseContext) -> Result<(), E> { Ok(()) } - fn exit_query_clause(&mut self, _ctx: &QueryClauseContext) -> Result<(), E> { Ok(()) } - fn enter_join_clause(&mut self, _ctx: &JoinClauseContext) -> Result<(), E> { Ok(()) } - fn exit_join_clause(&mut self, _ctx: &JoinClauseContext) -> Result<(), E> { Ok(()) } - fn enter_join_into_clause(&mut self, _ctx: &JoinIntoClauseContext) -> Result<(), E> { Ok(()) } - fn exit_join_into_clause(&mut self, _ctx: &JoinIntoClauseContext) -> Result<(), E> { Ok(()) } - fn enter_let_clause(&mut self, _ctx: &LetClauseContext) -> Result<(), E> { Ok(()) } - fn exit_let_clause(&mut self, _ctx: &LetClauseContext) -> Result<(), E> { Ok(()) } - fn enter_order_by_clause(&mut self, _ctx: &OrderByClauseContext) -> Result<(), E> { Ok(()) } - fn exit_order_by_clause(&mut self, _ctx: &OrderByClauseContext) -> Result<(), E> { Ok(()) } - fn enter_ordering(&mut self, _ctx: &OrderingContext) -> Result<(), E> { Ok(()) } - fn exit_ordering(&mut self, _ctx: &OrderingContext) -> Result<(), E> { Ok(()) } - fn enter_where_clause(&mut self, _ctx: &WhereClauseContext) -> Result<(), E> { Ok(()) } - fn exit_where_clause(&mut self, _ctx: &WhereClauseContext) -> Result<(), E> { Ok(()) } - fn enter_select_or_group_clause(&mut self, _ctx: &SelectOrGroupClauseContext) -> Result<(), E> { Ok(()) } - fn exit_select_or_group_clause(&mut self, _ctx: &SelectOrGroupClauseContext) -> Result<(), E> { Ok(()) } - fn enter_group_clause(&mut self, _ctx: &GroupClauseContext) -> Result<(), E> { Ok(()) } - fn exit_group_clause(&mut self, _ctx: &GroupClauseContext) -> Result<(), E> { Ok(()) } - fn enter_select_clause(&mut self, _ctx: &SelectClauseContext) -> Result<(), E> { Ok(()) } - fn exit_select_clause(&mut self, _ctx: &SelectClauseContext) -> Result<(), E> { Ok(()) } - fn enter_query_continuation(&mut self, _ctx: &QueryContinuationContext) -> Result<(), E> { Ok(()) } - fn exit_query_continuation(&mut self, _ctx: &QueryContinuationContext) -> Result<(), E> { Ok(()) } - fn enter_ref_expression(&mut self, _ctx: &RefExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_ref_expression(&mut self, _ctx: &RefExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_ref_type_expression(&mut self, _ctx: &RefTypeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_ref_type_expression(&mut self, _ctx: &RefTypeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_ref_value_expression(&mut self, _ctx: &RefValueExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_ref_value_expression(&mut self, _ctx: &RefValueExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_size_of_expression(&mut self, _ctx: &SizeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_size_of_expression(&mut self, _ctx: &SizeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_stack_alloc_array_creation_expression(&mut self, _ctx: &StackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_stack_alloc_array_creation_expression(&mut self, _ctx: &StackAllocArrayCreationExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_switch_expression_arm(&mut self, _ctx: &SwitchExpressionArmContext) -> Result<(), E> { Ok(()) } - fn exit_switch_expression_arm(&mut self, _ctx: &SwitchExpressionArmContext) -> Result<(), E> { Ok(()) } - fn enter_throw_expression(&mut self, _ctx: &ThrowExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_throw_expression(&mut self, _ctx: &ThrowExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_tuple_expression(&mut self, _ctx: &TupleExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_tuple_expression(&mut self, _ctx: &TupleExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_type_of_expression(&mut self, _ctx: &TypeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_type_of_expression(&mut self, _ctx: &TypeOfExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_unsafe_expression(&mut self, _ctx: &UnsafeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_unsafe_expression(&mut self, _ctx: &UnsafeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_syntax_token(&mut self, _ctx: &SyntaxTokenContext) -> Result<(), E> { Ok(()) } - fn exit_syntax_token(&mut self, _ctx: &SyntaxTokenContext) -> Result<(), E> { Ok(()) } - fn enter_identifier_token(&mut self, _ctx: &IdentifierTokenContext) -> Result<(), E> { Ok(()) } - fn exit_identifier_token(&mut self, _ctx: &IdentifierTokenContext) -> Result<(), E> { Ok(()) } - fn enter_keyword(&mut self, _ctx: &KeywordContext) -> Result<(), E> { Ok(()) } - fn exit_keyword(&mut self, _ctx: &KeywordContext) -> Result<(), E> { Ok(()) } - fn enter_numeric_literal_token(&mut self, _ctx: &NumericLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_numeric_literal_token(&mut self, _ctx: &NumericLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_integer_literal_token(&mut self, _ctx: &IntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_integer_literal_token(&mut self, _ctx: &IntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_decimal_integer_literal_token(&mut self, _ctx: &DecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_decimal_integer_literal_token(&mut self, _ctx: &DecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_hexadecimal_integer_literal_token(&mut self, _ctx: &HexadecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_hexadecimal_integer_literal_token(&mut self, _ctx: &HexadecimalIntegerLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_real_literal_token(&mut self, _ctx: &RealLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_real_literal_token(&mut self, _ctx: &RealLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_character_literal_token(&mut self, _ctx: &CharacterLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_character_literal_token(&mut self, _ctx: &CharacterLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_string_literal_token(&mut self, _ctx: &StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_string_literal_token(&mut self, _ctx: &StringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_regular_string_literal_token(&mut self, _ctx: &RegularStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_regular_string_literal_token(&mut self, _ctx: &RegularStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_verbatim_string_literal_token(&mut self, _ctx: &VerbatimStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_verbatim_string_literal_token(&mut self, _ctx: &VerbatimStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_operator_token(&mut self, _ctx: &OperatorTokenContext) -> Result<(), E> { Ok(()) } - fn exit_operator_token(&mut self, _ctx: &OperatorTokenContext) -> Result<(), E> { Ok(()) } - fn enter_punctuation_token(&mut self, _ctx: &PunctuationTokenContext) -> Result<(), E> { Ok(()) } - fn exit_punctuation_token(&mut self, _ctx: &PunctuationTokenContext) -> Result<(), E> { Ok(()) } - fn enter_interpolated_string_text_token(&mut self, _ctx: &InterpolatedStringTextTokenContext) -> Result<(), E> { Ok(()) } - fn exit_interpolated_string_text_token(&mut self, _ctx: &InterpolatedStringTextTokenContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_raw_string_literal_token(&mut self, _ctx: &MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_raw_string_literal_token(&mut self, _ctx: &MultiLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_single_line_raw_string_literal_token(&mut self, _ctx: &SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn exit_single_line_raw_string_literal_token(&mut self, _ctx: &SingleLineRawStringLiteralTokenContext) -> Result<(), E> { Ok(()) } - fn enter_record_keyword(&mut self, _ctx: &RecordKeywordContext) -> Result<(), E> { Ok(()) } - fn exit_record_keyword(&mut self, _ctx: &RecordKeywordContext) -> Result<(), E> { Ok(()) } - fn enter_right_shift(&mut self, _ctx: &RightShiftContext) -> Result<(), E> { Ok(()) } - fn exit_right_shift(&mut self, _ctx: &RightShiftContext) -> Result<(), E> { Ok(()) } - fn enter_unsigned_right_shift(&mut self, _ctx: &UnsignedRightShiftContext) -> Result<(), E> { Ok(()) } - fn exit_unsigned_right_shift(&mut self, _ctx: &UnsignedRightShiftContext) -> Result<(), E> { Ok(()) } - fn enter_right_shift_assignment(&mut self, _ctx: &RightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn exit_right_shift_assignment(&mut self, _ctx: &RightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn enter_unsigned_right_shift_assignment(&mut self, _ctx: &UnsignedRightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn exit_unsigned_right_shift_assignment(&mut self, _ctx: &UnsignedRightShiftAssignmentContext) -> Result<(), E> { Ok(()) } - fn enter_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_local_variable_declarator(&mut self, _ctx: &LocalVariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_local_variable_declarator(&mut self, _ctx: &LocalVariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), E> { Ok(()) } - fn output(&mut self) -> std::io::Stdout { std::io::stdout() } -} - -antlr4_runtime::__antlr4_rust_generated_walk_callbacks! { - callbacks: __CSharpValidatedTreeWalkerCallbacks, - listener: CSharpValidatedListener, - enter: |listener, context, invocation_states| { - listener.enter_every_rule(ValidatedRuleNode::__new(context))?; - match __context_kind(context) { - 0 => listener.enter_compilation_unit(&CompilationUnitContext::::__from_validated_listener_node(context, invocation_states))?, - 1 => listener.enter_extern_alias_directive(&ExternAliasDirectiveContext::::__from_validated_listener_node(context, invocation_states))?, - 2 => listener.enter_using_directive(&UsingDirectiveContext::::__from_validated_listener_node(context, invocation_states))?, - 3 => listener.enter_name_equals(&NameEqualsContext::::__from_validated_listener_node(context, invocation_states))?, - 4 => listener.enter_identifier_name(&IdentifierNameContext::::__from_validated_listener_node(context, invocation_states))?, - 5 => listener.enter_attribute_list(&AttributeListContext::::__from_validated_listener_node(context, invocation_states))?, - 6 => listener.enter_attribute_target_specifier(&AttributeTargetSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 7 => listener.enter_attribute(&AttributeContext::::__from_validated_listener_node(context, invocation_states))?, - 8 => listener.enter_name(&NameContext::::__from_validated_listener_node(context, invocation_states))?, - 9 => listener.enter_alias_qualified_name(&AliasQualifiedNameContext::::__from_validated_listener_node(context, invocation_states))?, - 10 => listener.enter_simple_name(&SimpleNameContext::::__from_validated_listener_node(context, invocation_states))?, - 11 => listener.enter_generic_name(&GenericNameContext::::__from_validated_listener_node(context, invocation_states))?, - 12 => listener.enter_type_argument_list(&TypeArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 13 => listener.enter_attribute_argument_list(&AttributeArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 14 => listener.enter_attribute_argument(&AttributeArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 15 => listener.enter_name_colon(&NameColonContext::::__from_validated_listener_node(context, invocation_states))?, - 16 => listener.enter_member_declaration(&MemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 17 => listener.enter_base_field_declaration(&BaseFieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 18 => listener.enter_event_field_declaration(&EventFieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 19 => listener.enter_modifier(&ModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 20 => listener.enter_variable_declaration(&VariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 21 => listener.enter_variable_declarator(&VariableDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 22 => listener.enter_bracketed_argument_list(&BracketedArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 23 => listener.enter_argument(&ArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 24 => listener.enter_equals_value_clause(&EqualsValueClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 25 => listener.enter_field_declaration(&FieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 26 => listener.enter_base_method_declaration(&BaseMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 27 => listener.enter_constructor_declaration(&ConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 28 => listener.enter_parameter_list(&ParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 29 => listener.enter_parameter(&ParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 30 => listener.enter_constructor_initializer(&ConstructorInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 31 => listener.enter_argument_list(&ArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 32 => listener.enter_block(&BlockContext::::__from_validated_listener_node(context, invocation_states))?, - 33 => listener.enter_arrow_expression_clause(&ArrowExpressionClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 34 => listener.enter_conversion_operator_declaration(&ConversionOperatorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 35 => listener.enter_explicit_interface_specifier(&ExplicitInterfaceSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 36 => listener.enter_destructor_declaration(&DestructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 37 => listener.enter_method_declaration(&MethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 38 => listener.enter_type_parameter_list(&TypeParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 39 => listener.enter_type_parameter(&TypeParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 40 => listener.enter_type_parameter_constraint_clause(&TypeParameterConstraintClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 41 => listener.enter_type_parameter_constraint(&TypeParameterConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 42 => listener.enter_allows_constraint_clause(&AllowsConstraintClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 43 => listener.enter_allows_constraint(&AllowsConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 44 => listener.enter_ref_struct_constraint(&RefStructConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 45 => listener.enter_class_or_struct_constraint(&ClassOrStructConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 46 => listener.enter_constructor_constraint(&ConstructorConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 47 => listener.enter_default_constraint(&DefaultConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 48 => listener.enter_type_constraint(&TypeConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 49 => listener.enter_operator_declaration(&OperatorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 50 => listener.enter_base_namespace_declaration(&BaseNamespaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 51 => listener.enter_file_scoped_namespace_declaration(&FileScopedNamespaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 52 => listener.enter_namespace_declaration(&NamespaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 53 => listener.enter_base_property_declaration(&BasePropertyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 54 => listener.enter_event_declaration(&EventDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 55 => listener.enter_accessor_list(&AccessorListContext::::__from_validated_listener_node(context, invocation_states))?, - 56 => listener.enter_accessor_declaration(&AccessorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 57 => listener.enter_indexer_declaration(&IndexerDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 58 => listener.enter_bracketed_parameter_list(&BracketedParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 59 => listener.enter_property_declaration(&PropertyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 60 => listener.enter_base_type_declaration(&BaseTypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 61 => listener.enter_enum_declaration(&EnumDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 62 => listener.enter_base_list(&BaseListContext::::__from_validated_listener_node(context, invocation_states))?, - 63 => listener.enter_base_type(&BaseTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 64 => listener.enter_primary_constructor_base_type(&PrimaryConstructorBaseTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 65 => listener.enter_simple_base_type(&SimpleBaseTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 66 => listener.enter_enum_member_declaration(&EnumMemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 67 => listener.enter_type_declaration(&TypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 68 => listener.enter_class_declaration(&ClassDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 69 => listener.enter_extension_block_declaration(&ExtensionBlockDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 70 => listener.enter_interface_declaration(&InterfaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 71 => listener.enter_record_declaration(&RecordDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 72 => listener.enter_struct_declaration(&StructDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 73 => listener.enter_union_declaration(&UnionDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 74 => listener.enter_delegate_declaration(&DelegateDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 75 => listener.enter_global_statement(&GlobalStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 76 => listener.enter_type(&TypeContext::::__from_validated_listener_node(context, invocation_states))?, - 77 => listener.enter_array_type(&ArrayTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 78 => listener.enter_array_rank_specifier(&ArrayRankSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 79 => listener.enter_function_pointer_type(&FunctionPointerTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 80 => listener.enter_function_pointer_calling_convention(&FunctionPointerCallingConventionContext::::__from_validated_listener_node(context, invocation_states))?, - 81 => listener.enter_function_pointer_unmanaged_calling_convention_list(&FunctionPointerUnmanagedCallingConventionListContext::::__from_validated_listener_node(context, invocation_states))?, - 82 => listener.enter_function_pointer_unmanaged_calling_convention(&FunctionPointerUnmanagedCallingConventionContext::::__from_validated_listener_node(context, invocation_states))?, - 83 => listener.enter_function_pointer_parameter_list(&FunctionPointerParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 84 => listener.enter_function_pointer_parameter(&FunctionPointerParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 85 => listener.enter_predefined_type(&PredefinedTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 86 => listener.enter_ref_type(&RefTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 87 => listener.enter_scoped_type(&ScopedTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 88 => listener.enter_tuple_type(&TupleTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 89 => listener.enter_tuple_element(&TupleElementContext::::__from_validated_listener_node(context, invocation_states))?, - 90 => listener.enter_statement(&StatementContext::::__from_validated_listener_node(context, invocation_states))?, - 91 => listener.enter_break_statement(&BreakStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 92 => listener.enter_checked_statement(&CheckedStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 93 => listener.enter_common_for_each_statement(&CommonForEachStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 94 => listener.enter_for_each_statement(&ForEachStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 95 => listener.enter_for_each_variable_statement(&ForEachVariableStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 96 => listener.enter_continue_statement(&ContinueStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 97 => listener.enter_do_statement(&DoStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 98 => listener.enter_empty_statement(&EmptyStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 99 => listener.enter_expression_statement(&ExpressionStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 100 => listener.enter_fixed_statement(&FixedStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 101 => listener.enter_for_statement(&ForStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 102 => listener.enter_goto_statement(&GotoStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 103 => listener.enter_if_statement(&IfStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 104 => listener.enter_else_clause(&ElseClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 105 => listener.enter_labeled_statement(&LabeledStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 106 => listener.enter_local_declaration_statement(&LocalDeclarationStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 107 => listener.enter_local_function_statement(&LocalFunctionStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 108 => listener.enter_lock_statement(&LockStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 109 => listener.enter_return_statement(&ReturnStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 110 => listener.enter_switch_statement(&SwitchStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 111 => listener.enter_switch_section(&SwitchSectionContext::::__from_validated_listener_node(context, invocation_states))?, - 112 => listener.enter_switch_label(&SwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 113 => listener.enter_case_pattern_switch_label(&CasePatternSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 114 => listener.enter_pattern(&PatternContext::::__from_validated_listener_node(context, invocation_states))?, - 115 => listener.enter_constant_pattern(&ConstantPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 116 => listener.enter_declaration_pattern(&DeclarationPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 117 => listener.enter_variable_designation(&VariableDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 118 => listener.enter_discard_designation(&DiscardDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 119 => listener.enter_parenthesized_variable_designation(&ParenthesizedVariableDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 120 => listener.enter_single_variable_designation(&SingleVariableDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 121 => listener.enter_discard_pattern(&DiscardPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 122 => listener.enter_list_pattern(&ListPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 123 => listener.enter_parenthesized_pattern(&ParenthesizedPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 124 => listener.enter_recursive_pattern(&RecursivePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 125 => listener.enter_positional_pattern_clause(&PositionalPatternClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 126 => listener.enter_subpattern(&SubpatternContext::::__from_validated_listener_node(context, invocation_states))?, - 127 => listener.enter_base_expression_colon(&BaseExpressionColonContext::::__from_validated_listener_node(context, invocation_states))?, - 128 => listener.enter_expression_colon(&ExpressionColonContext::::__from_validated_listener_node(context, invocation_states))?, - 129 => listener.enter_property_pattern_clause(&PropertyPatternClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 130 => listener.enter_relational_pattern(&RelationalPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 131 => listener.enter_slice_pattern(&SlicePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 132 => listener.enter_type_pattern(&TypePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 133 => listener.enter_unary_pattern(&UnaryPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 134 => listener.enter_var_pattern(&VarPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 135 => listener.enter_when_clause(&WhenClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 136 => listener.enter_case_switch_label(&CaseSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 137 => listener.enter_default_switch_label(&DefaultSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 138 => listener.enter_throw_statement(&ThrowStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 139 => listener.enter_try_statement(&TryStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 140 => listener.enter_catch_clause(&CatchClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 141 => listener.enter_catch_declaration(&CatchDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 142 => listener.enter_catch_filter_clause(&CatchFilterClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 143 => listener.enter_finally_clause(&FinallyClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 144 => listener.enter_unsafe_statement(&UnsafeStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 145 => listener.enter_using_statement(&UsingStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 146 => listener.enter_while_statement(&WhileStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 147 => listener.enter_yield_statement(&YieldStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 148 => listener.enter_expression(&ExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 149 => listener.enter_anonymous_function_expression(&AnonymousFunctionExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 150 => listener.enter_anonymous_method_expression(&AnonymousMethodExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 151 => listener.enter_lambda_expression(&LambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 152 => listener.enter_parenthesized_lambda_expression(&ParenthesizedLambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 153 => listener.enter_simple_lambda_expression(&SimpleLambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 154 => listener.enter_anonymous_object_creation_expression(&AnonymousObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 155 => listener.enter_anonymous_object_member_declarator(&AnonymousObjectMemberDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 156 => listener.enter_array_creation_expression(&ArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 157 => listener.enter_initializer_expression(&InitializerExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 158 => listener.enter_await_expression(&AwaitExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 159 => listener.enter_base_object_creation_expression(&BaseObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 160 => listener.enter_implicit_object_creation_expression(&ImplicitObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 161 => listener.enter_object_creation_expression(&ObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 162 => listener.enter_cast_expression(&CastExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 163 => listener.enter_checked_expression(&CheckedExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 164 => listener.enter_collection_expression(&CollectionExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 165 => listener.enter_collection_element(&CollectionElementContext::::__from_validated_listener_node(context, invocation_states))?, - 166 => listener.enter_expression_element(&ExpressionElementContext::::__from_validated_listener_node(context, invocation_states))?, - 167 => listener.enter_spread_element(&SpreadElementContext::::__from_validated_listener_node(context, invocation_states))?, - 168 => listener.enter_with_element(&WithElementContext::::__from_validated_listener_node(context, invocation_states))?, - 169 => listener.enter_declaration_expression(&DeclarationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 170 => listener.enter_default_expression(&DefaultExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 171 => listener.enter_element_binding_expression(&ElementBindingExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 172 => listener.enter_field_expression(&FieldExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 173 => listener.enter_implicit_array_creation_expression(&ImplicitArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 174 => listener.enter_implicit_element_access(&ImplicitElementAccessContext::::__from_validated_listener_node(context, invocation_states))?, - 175 => listener.enter_implicit_stack_alloc_array_creation_expression(&ImplicitStackAllocArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 176 => listener.enter_instance_expression(&InstanceExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 177 => listener.enter_base_expression(&BaseExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 178 => listener.enter_this_expression(&ThisExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 179 => listener.enter_interpolated_string_expression(&InterpolatedStringExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 180 => listener.enter_interpolated_string_content(&InterpolatedStringContentContext::::__from_validated_listener_node(context, invocation_states))?, - 181 => listener.enter_interpolated_string_text(&InterpolatedStringTextContext::::__from_validated_listener_node(context, invocation_states))?, - 182 => listener.enter_interpolation(&InterpolationContext::::__from_validated_listener_node(context, invocation_states))?, - 183 => listener.enter_interpolation_alignment_clause(&InterpolationAlignmentClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 184 => listener.enter_interpolation_format_clause(&InterpolationFormatClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 185 => listener.enter_interpolated_multi_line_raw_string_start_token(&InterpolatedMultiLineRawStringStartTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 186 => listener.enter_interpolated_raw_string_end_token(&InterpolatedRawStringEndTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 187 => listener.enter_interpolated_single_line_raw_string_start_token(&InterpolatedSingleLineRawStringStartTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 188 => listener.enter_literal_expression(&LiteralExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 189 => listener.enter_utf8_multi_line_raw_string_literal_token(&Utf8MultiLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 190 => listener.enter_utf8_single_line_raw_string_literal_token(&Utf8SingleLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 191 => listener.enter_utf8_string_literal_token(&Utf8StringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 192 => listener.enter_make_ref_expression(&MakeRefExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 193 => listener.enter_member_binding_expression(&MemberBindingExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 194 => listener.enter_parenthesized_expression(&ParenthesizedExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 195 => listener.enter_prefix_unary_expression(&PrefixUnaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 196 => listener.enter_query_expression(&QueryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 197 => listener.enter_from_clause(&FromClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 198 => listener.enter_query_body(&QueryBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 199 => listener.enter_query_clause(&QueryClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 200 => listener.enter_join_clause(&JoinClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 201 => listener.enter_join_into_clause(&JoinIntoClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 202 => listener.enter_let_clause(&LetClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 203 => listener.enter_order_by_clause(&OrderByClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 204 => listener.enter_ordering(&OrderingContext::::__from_validated_listener_node(context, invocation_states))?, - 205 => listener.enter_where_clause(&WhereClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 206 => listener.enter_select_or_group_clause(&SelectOrGroupClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 207 => listener.enter_group_clause(&GroupClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 208 => listener.enter_select_clause(&SelectClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 209 => listener.enter_query_continuation(&QueryContinuationContext::::__from_validated_listener_node(context, invocation_states))?, - 210 => listener.enter_ref_expression(&RefExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 211 => listener.enter_ref_type_expression(&RefTypeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 212 => listener.enter_ref_value_expression(&RefValueExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 213 => listener.enter_size_of_expression(&SizeOfExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 214 => listener.enter_stack_alloc_array_creation_expression(&StackAllocArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 215 => listener.enter_switch_expression_arm(&SwitchExpressionArmContext::::__from_validated_listener_node(context, invocation_states))?, - 216 => listener.enter_throw_expression(&ThrowExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 217 => listener.enter_tuple_expression(&TupleExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 218 => listener.enter_type_of_expression(&TypeOfExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 219 => listener.enter_unsafe_expression(&UnsafeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 220 => listener.enter_syntax_token(&SyntaxTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 221 => listener.enter_identifier_token(&IdentifierTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 222 => listener.enter_keyword(&KeywordContext::::__from_validated_listener_node(context, invocation_states))?, - 223 => listener.enter_numeric_literal_token(&NumericLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 224 => listener.enter_integer_literal_token(&IntegerLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 225 => listener.enter_decimal_integer_literal_token(&DecimalIntegerLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 226 => listener.enter_hexadecimal_integer_literal_token(&HexadecimalIntegerLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 227 => listener.enter_real_literal_token(&RealLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 228 => listener.enter_character_literal_token(&CharacterLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 229 => listener.enter_string_literal_token(&StringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 230 => listener.enter_regular_string_literal_token(&RegularStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 231 => listener.enter_verbatim_string_literal_token(&VerbatimStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 232 => listener.enter_operator_token(&OperatorTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 233 => listener.enter_punctuation_token(&PunctuationTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 234 => listener.enter_interpolated_string_text_token(&InterpolatedStringTextTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 235 => listener.enter_multi_line_raw_string_literal_token(&MultiLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 236 => listener.enter_single_line_raw_string_literal_token(&SingleLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 237 => listener.enter_record_keyword(&RecordKeywordContext::::__from_validated_listener_node(context, invocation_states))?, - 238 => listener.enter_right_shift(&RightShiftContext::::__from_validated_listener_node(context, invocation_states))?, - 239 => listener.enter_unsigned_right_shift(&UnsignedRightShiftContext::::__from_validated_listener_node(context, invocation_states))?, - 240 => listener.enter_right_shift_assignment(&RightShiftAssignmentContext::::__from_validated_listener_node(context, invocation_states))?, - 241 => listener.enter_unsigned_right_shift_assignment(&UnsignedRightShiftAssignmentContext::::__from_validated_listener_node(context, invocation_states))?, - 242 => listener.enter_local_variable_declaration(&LocalVariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 243 => listener.enter_local_variable_declarator(&LocalVariableDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - _ => {} - } - Ok(()) - }, - exit: |listener, context, invocation_states| { - match __context_kind(context) { - 0 => listener.exit_compilation_unit(&CompilationUnitContext::::__from_validated_listener_node(context, invocation_states))?, - 1 => listener.exit_extern_alias_directive(&ExternAliasDirectiveContext::::__from_validated_listener_node(context, invocation_states))?, - 2 => listener.exit_using_directive(&UsingDirectiveContext::::__from_validated_listener_node(context, invocation_states))?, - 3 => listener.exit_name_equals(&NameEqualsContext::::__from_validated_listener_node(context, invocation_states))?, - 4 => listener.exit_identifier_name(&IdentifierNameContext::::__from_validated_listener_node(context, invocation_states))?, - 5 => listener.exit_attribute_list(&AttributeListContext::::__from_validated_listener_node(context, invocation_states))?, - 6 => listener.exit_attribute_target_specifier(&AttributeTargetSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 7 => listener.exit_attribute(&AttributeContext::::__from_validated_listener_node(context, invocation_states))?, - 8 => listener.exit_name(&NameContext::::__from_validated_listener_node(context, invocation_states))?, - 9 => listener.exit_alias_qualified_name(&AliasQualifiedNameContext::::__from_validated_listener_node(context, invocation_states))?, - 10 => listener.exit_simple_name(&SimpleNameContext::::__from_validated_listener_node(context, invocation_states))?, - 11 => listener.exit_generic_name(&GenericNameContext::::__from_validated_listener_node(context, invocation_states))?, - 12 => listener.exit_type_argument_list(&TypeArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 13 => listener.exit_attribute_argument_list(&AttributeArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 14 => listener.exit_attribute_argument(&AttributeArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 15 => listener.exit_name_colon(&NameColonContext::::__from_validated_listener_node(context, invocation_states))?, - 16 => listener.exit_member_declaration(&MemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 17 => listener.exit_base_field_declaration(&BaseFieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 18 => listener.exit_event_field_declaration(&EventFieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 19 => listener.exit_modifier(&ModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 20 => listener.exit_variable_declaration(&VariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 21 => listener.exit_variable_declarator(&VariableDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 22 => listener.exit_bracketed_argument_list(&BracketedArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 23 => listener.exit_argument(&ArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 24 => listener.exit_equals_value_clause(&EqualsValueClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 25 => listener.exit_field_declaration(&FieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 26 => listener.exit_base_method_declaration(&BaseMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 27 => listener.exit_constructor_declaration(&ConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 28 => listener.exit_parameter_list(&ParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 29 => listener.exit_parameter(&ParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 30 => listener.exit_constructor_initializer(&ConstructorInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 31 => listener.exit_argument_list(&ArgumentListContext::::__from_validated_listener_node(context, invocation_states))?, - 32 => listener.exit_block(&BlockContext::::__from_validated_listener_node(context, invocation_states))?, - 33 => listener.exit_arrow_expression_clause(&ArrowExpressionClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 34 => listener.exit_conversion_operator_declaration(&ConversionOperatorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 35 => listener.exit_explicit_interface_specifier(&ExplicitInterfaceSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 36 => listener.exit_destructor_declaration(&DestructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 37 => listener.exit_method_declaration(&MethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 38 => listener.exit_type_parameter_list(&TypeParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 39 => listener.exit_type_parameter(&TypeParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 40 => listener.exit_type_parameter_constraint_clause(&TypeParameterConstraintClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 41 => listener.exit_type_parameter_constraint(&TypeParameterConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 42 => listener.exit_allows_constraint_clause(&AllowsConstraintClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 43 => listener.exit_allows_constraint(&AllowsConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 44 => listener.exit_ref_struct_constraint(&RefStructConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 45 => listener.exit_class_or_struct_constraint(&ClassOrStructConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 46 => listener.exit_constructor_constraint(&ConstructorConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 47 => listener.exit_default_constraint(&DefaultConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 48 => listener.exit_type_constraint(&TypeConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 49 => listener.exit_operator_declaration(&OperatorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 50 => listener.exit_base_namespace_declaration(&BaseNamespaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 51 => listener.exit_file_scoped_namespace_declaration(&FileScopedNamespaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 52 => listener.exit_namespace_declaration(&NamespaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 53 => listener.exit_base_property_declaration(&BasePropertyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 54 => listener.exit_event_declaration(&EventDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 55 => listener.exit_accessor_list(&AccessorListContext::::__from_validated_listener_node(context, invocation_states))?, - 56 => listener.exit_accessor_declaration(&AccessorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 57 => listener.exit_indexer_declaration(&IndexerDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 58 => listener.exit_bracketed_parameter_list(&BracketedParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 59 => listener.exit_property_declaration(&PropertyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 60 => listener.exit_base_type_declaration(&BaseTypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 61 => listener.exit_enum_declaration(&EnumDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 62 => listener.exit_base_list(&BaseListContext::::__from_validated_listener_node(context, invocation_states))?, - 63 => listener.exit_base_type(&BaseTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 64 => listener.exit_primary_constructor_base_type(&PrimaryConstructorBaseTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 65 => listener.exit_simple_base_type(&SimpleBaseTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 66 => listener.exit_enum_member_declaration(&EnumMemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 67 => listener.exit_type_declaration(&TypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 68 => listener.exit_class_declaration(&ClassDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 69 => listener.exit_extension_block_declaration(&ExtensionBlockDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 70 => listener.exit_interface_declaration(&InterfaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 71 => listener.exit_record_declaration(&RecordDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 72 => listener.exit_struct_declaration(&StructDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 73 => listener.exit_union_declaration(&UnionDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 74 => listener.exit_delegate_declaration(&DelegateDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 75 => listener.exit_global_statement(&GlobalStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 76 => listener.exit_type(&TypeContext::::__from_validated_listener_node(context, invocation_states))?, - 77 => listener.exit_array_type(&ArrayTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 78 => listener.exit_array_rank_specifier(&ArrayRankSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 79 => listener.exit_function_pointer_type(&FunctionPointerTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 80 => listener.exit_function_pointer_calling_convention(&FunctionPointerCallingConventionContext::::__from_validated_listener_node(context, invocation_states))?, - 81 => listener.exit_function_pointer_unmanaged_calling_convention_list(&FunctionPointerUnmanagedCallingConventionListContext::::__from_validated_listener_node(context, invocation_states))?, - 82 => listener.exit_function_pointer_unmanaged_calling_convention(&FunctionPointerUnmanagedCallingConventionContext::::__from_validated_listener_node(context, invocation_states))?, - 83 => listener.exit_function_pointer_parameter_list(&FunctionPointerParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 84 => listener.exit_function_pointer_parameter(&FunctionPointerParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 85 => listener.exit_predefined_type(&PredefinedTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 86 => listener.exit_ref_type(&RefTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 87 => listener.exit_scoped_type(&ScopedTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 88 => listener.exit_tuple_type(&TupleTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 89 => listener.exit_tuple_element(&TupleElementContext::::__from_validated_listener_node(context, invocation_states))?, - 90 => listener.exit_statement(&StatementContext::::__from_validated_listener_node(context, invocation_states))?, - 91 => listener.exit_break_statement(&BreakStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 92 => listener.exit_checked_statement(&CheckedStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 93 => listener.exit_common_for_each_statement(&CommonForEachStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 94 => listener.exit_for_each_statement(&ForEachStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 95 => listener.exit_for_each_variable_statement(&ForEachVariableStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 96 => listener.exit_continue_statement(&ContinueStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 97 => listener.exit_do_statement(&DoStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 98 => listener.exit_empty_statement(&EmptyStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 99 => listener.exit_expression_statement(&ExpressionStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 100 => listener.exit_fixed_statement(&FixedStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 101 => listener.exit_for_statement(&ForStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 102 => listener.exit_goto_statement(&GotoStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 103 => listener.exit_if_statement(&IfStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 104 => listener.exit_else_clause(&ElseClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 105 => listener.exit_labeled_statement(&LabeledStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 106 => listener.exit_local_declaration_statement(&LocalDeclarationStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 107 => listener.exit_local_function_statement(&LocalFunctionStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 108 => listener.exit_lock_statement(&LockStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 109 => listener.exit_return_statement(&ReturnStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 110 => listener.exit_switch_statement(&SwitchStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 111 => listener.exit_switch_section(&SwitchSectionContext::::__from_validated_listener_node(context, invocation_states))?, - 112 => listener.exit_switch_label(&SwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 113 => listener.exit_case_pattern_switch_label(&CasePatternSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 114 => listener.exit_pattern(&PatternContext::::__from_validated_listener_node(context, invocation_states))?, - 115 => listener.exit_constant_pattern(&ConstantPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 116 => listener.exit_declaration_pattern(&DeclarationPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 117 => listener.exit_variable_designation(&VariableDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 118 => listener.exit_discard_designation(&DiscardDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 119 => listener.exit_parenthesized_variable_designation(&ParenthesizedVariableDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 120 => listener.exit_single_variable_designation(&SingleVariableDesignationContext::::__from_validated_listener_node(context, invocation_states))?, - 121 => listener.exit_discard_pattern(&DiscardPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 122 => listener.exit_list_pattern(&ListPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 123 => listener.exit_parenthesized_pattern(&ParenthesizedPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 124 => listener.exit_recursive_pattern(&RecursivePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 125 => listener.exit_positional_pattern_clause(&PositionalPatternClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 126 => listener.exit_subpattern(&SubpatternContext::::__from_validated_listener_node(context, invocation_states))?, - 127 => listener.exit_base_expression_colon(&BaseExpressionColonContext::::__from_validated_listener_node(context, invocation_states))?, - 128 => listener.exit_expression_colon(&ExpressionColonContext::::__from_validated_listener_node(context, invocation_states))?, - 129 => listener.exit_property_pattern_clause(&PropertyPatternClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 130 => listener.exit_relational_pattern(&RelationalPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 131 => listener.exit_slice_pattern(&SlicePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 132 => listener.exit_type_pattern(&TypePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 133 => listener.exit_unary_pattern(&UnaryPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 134 => listener.exit_var_pattern(&VarPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 135 => listener.exit_when_clause(&WhenClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 136 => listener.exit_case_switch_label(&CaseSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 137 => listener.exit_default_switch_label(&DefaultSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 138 => listener.exit_throw_statement(&ThrowStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 139 => listener.exit_try_statement(&TryStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 140 => listener.exit_catch_clause(&CatchClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 141 => listener.exit_catch_declaration(&CatchDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 142 => listener.exit_catch_filter_clause(&CatchFilterClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 143 => listener.exit_finally_clause(&FinallyClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 144 => listener.exit_unsafe_statement(&UnsafeStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 145 => listener.exit_using_statement(&UsingStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 146 => listener.exit_while_statement(&WhileStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 147 => listener.exit_yield_statement(&YieldStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 148 => listener.exit_expression(&ExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 149 => listener.exit_anonymous_function_expression(&AnonymousFunctionExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 150 => listener.exit_anonymous_method_expression(&AnonymousMethodExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 151 => listener.exit_lambda_expression(&LambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 152 => listener.exit_parenthesized_lambda_expression(&ParenthesizedLambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 153 => listener.exit_simple_lambda_expression(&SimpleLambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 154 => listener.exit_anonymous_object_creation_expression(&AnonymousObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 155 => listener.exit_anonymous_object_member_declarator(&AnonymousObjectMemberDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 156 => listener.exit_array_creation_expression(&ArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 157 => listener.exit_initializer_expression(&InitializerExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 158 => listener.exit_await_expression(&AwaitExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 159 => listener.exit_base_object_creation_expression(&BaseObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 160 => listener.exit_implicit_object_creation_expression(&ImplicitObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 161 => listener.exit_object_creation_expression(&ObjectCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 162 => listener.exit_cast_expression(&CastExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 163 => listener.exit_checked_expression(&CheckedExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 164 => listener.exit_collection_expression(&CollectionExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 165 => listener.exit_collection_element(&CollectionElementContext::::__from_validated_listener_node(context, invocation_states))?, - 166 => listener.exit_expression_element(&ExpressionElementContext::::__from_validated_listener_node(context, invocation_states))?, - 167 => listener.exit_spread_element(&SpreadElementContext::::__from_validated_listener_node(context, invocation_states))?, - 168 => listener.exit_with_element(&WithElementContext::::__from_validated_listener_node(context, invocation_states))?, - 169 => listener.exit_declaration_expression(&DeclarationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 170 => listener.exit_default_expression(&DefaultExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 171 => listener.exit_element_binding_expression(&ElementBindingExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 172 => listener.exit_field_expression(&FieldExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 173 => listener.exit_implicit_array_creation_expression(&ImplicitArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 174 => listener.exit_implicit_element_access(&ImplicitElementAccessContext::::__from_validated_listener_node(context, invocation_states))?, - 175 => listener.exit_implicit_stack_alloc_array_creation_expression(&ImplicitStackAllocArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 176 => listener.exit_instance_expression(&InstanceExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 177 => listener.exit_base_expression(&BaseExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 178 => listener.exit_this_expression(&ThisExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 179 => listener.exit_interpolated_string_expression(&InterpolatedStringExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 180 => listener.exit_interpolated_string_content(&InterpolatedStringContentContext::::__from_validated_listener_node(context, invocation_states))?, - 181 => listener.exit_interpolated_string_text(&InterpolatedStringTextContext::::__from_validated_listener_node(context, invocation_states))?, - 182 => listener.exit_interpolation(&InterpolationContext::::__from_validated_listener_node(context, invocation_states))?, - 183 => listener.exit_interpolation_alignment_clause(&InterpolationAlignmentClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 184 => listener.exit_interpolation_format_clause(&InterpolationFormatClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 185 => listener.exit_interpolated_multi_line_raw_string_start_token(&InterpolatedMultiLineRawStringStartTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 186 => listener.exit_interpolated_raw_string_end_token(&InterpolatedRawStringEndTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 187 => listener.exit_interpolated_single_line_raw_string_start_token(&InterpolatedSingleLineRawStringStartTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 188 => listener.exit_literal_expression(&LiteralExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 189 => listener.exit_utf8_multi_line_raw_string_literal_token(&Utf8MultiLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 190 => listener.exit_utf8_single_line_raw_string_literal_token(&Utf8SingleLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 191 => listener.exit_utf8_string_literal_token(&Utf8StringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 192 => listener.exit_make_ref_expression(&MakeRefExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 193 => listener.exit_member_binding_expression(&MemberBindingExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 194 => listener.exit_parenthesized_expression(&ParenthesizedExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 195 => listener.exit_prefix_unary_expression(&PrefixUnaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 196 => listener.exit_query_expression(&QueryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 197 => listener.exit_from_clause(&FromClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 198 => listener.exit_query_body(&QueryBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 199 => listener.exit_query_clause(&QueryClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 200 => listener.exit_join_clause(&JoinClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 201 => listener.exit_join_into_clause(&JoinIntoClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 202 => listener.exit_let_clause(&LetClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 203 => listener.exit_order_by_clause(&OrderByClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 204 => listener.exit_ordering(&OrderingContext::::__from_validated_listener_node(context, invocation_states))?, - 205 => listener.exit_where_clause(&WhereClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 206 => listener.exit_select_or_group_clause(&SelectOrGroupClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 207 => listener.exit_group_clause(&GroupClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 208 => listener.exit_select_clause(&SelectClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 209 => listener.exit_query_continuation(&QueryContinuationContext::::__from_validated_listener_node(context, invocation_states))?, - 210 => listener.exit_ref_expression(&RefExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 211 => listener.exit_ref_type_expression(&RefTypeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 212 => listener.exit_ref_value_expression(&RefValueExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 213 => listener.exit_size_of_expression(&SizeOfExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 214 => listener.exit_stack_alloc_array_creation_expression(&StackAllocArrayCreationExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 215 => listener.exit_switch_expression_arm(&SwitchExpressionArmContext::::__from_validated_listener_node(context, invocation_states))?, - 216 => listener.exit_throw_expression(&ThrowExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 217 => listener.exit_tuple_expression(&TupleExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 218 => listener.exit_type_of_expression(&TypeOfExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 219 => listener.exit_unsafe_expression(&UnsafeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 220 => listener.exit_syntax_token(&SyntaxTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 221 => listener.exit_identifier_token(&IdentifierTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 222 => listener.exit_keyword(&KeywordContext::::__from_validated_listener_node(context, invocation_states))?, - 223 => listener.exit_numeric_literal_token(&NumericLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 224 => listener.exit_integer_literal_token(&IntegerLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 225 => listener.exit_decimal_integer_literal_token(&DecimalIntegerLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 226 => listener.exit_hexadecimal_integer_literal_token(&HexadecimalIntegerLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 227 => listener.exit_real_literal_token(&RealLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 228 => listener.exit_character_literal_token(&CharacterLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 229 => listener.exit_string_literal_token(&StringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 230 => listener.exit_regular_string_literal_token(&RegularStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 231 => listener.exit_verbatim_string_literal_token(&VerbatimStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 232 => listener.exit_operator_token(&OperatorTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 233 => listener.exit_punctuation_token(&PunctuationTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 234 => listener.exit_interpolated_string_text_token(&InterpolatedStringTextTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 235 => listener.exit_multi_line_raw_string_literal_token(&MultiLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 236 => listener.exit_single_line_raw_string_literal_token(&SingleLineRawStringLiteralTokenContext::::__from_validated_listener_node(context, invocation_states))?, - 237 => listener.exit_record_keyword(&RecordKeywordContext::::__from_validated_listener_node(context, invocation_states))?, - 238 => listener.exit_right_shift(&RightShiftContext::::__from_validated_listener_node(context, invocation_states))?, - 239 => listener.exit_unsigned_right_shift(&UnsignedRightShiftContext::::__from_validated_listener_node(context, invocation_states))?, - 240 => listener.exit_right_shift_assignment(&RightShiftAssignmentContext::::__from_validated_listener_node(context, invocation_states))?, - 241 => listener.exit_unsigned_right_shift_assignment(&UnsignedRightShiftAssignmentContext::::__from_validated_listener_node(context, invocation_states))?, - 242 => listener.exit_local_variable_declaration(&LocalVariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 243 => listener.exit_local_variable_declarator(&LocalVariableDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - _ => {} - } - listener.exit_every_rule(ValidatedRuleNode::__new(context)) - }, - terminal: |listener, node| { - listener.visit_terminal(&TerminalNode::new(node)) - }, - error: |_listener, _node| { - unreachable!("validated parse tree contains an error node") - }, -} - -#[allow(dead_code)] -pub struct CSharpValidatedTreeWalker; - -#[allow(dead_code)] -impl CSharpValidatedTreeWalker { - pub fn walk>( - listener: &mut T, - tree: ValidatedRuleNode<'_>, - ) -> Result<(), E> { - Self::__walk(listener, tree.node(), None) - } - - pub fn walk_with_invocation_states>( - listener: &mut T, - tree: ValidatedRuleNode<'_>, - parent_invocation_states: Vec, - ) -> Result<(), E> { - Self::__walk(listener, tree.node(), Some(parent_invocation_states)) - } - - fn __walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - invocation_states: Option>, - ) -> Result<(), E> { - let mut callbacks = __CSharpValidatedTreeWalkerCallbacks(listener); - antlr4_runtime::generated::walk_generated(tree, invocation_states, &mut callbacks) - } -} - -pub type ValidatedParseTreeWalker = CSharpValidatedTreeWalker; - - - -static PARSER_ATN_DATA: &[u32] = &[1346458702, 3, 16909060, 29, 206, 3140, 4233, 19, 136, 362, 244, 29, 21980, 22009, 21165, 43174, 95, 43269, 272, 43607, 362, 43969, 244, 44213, 244, 44457, 33, 43541, 66, 2, 0, 8, 0, 1, 4294967295, 4294967295, 7, 0, 16, 1, 0, 4294967295, 4294967295, 2, 1, 8, 1, 1, 4294967295, 4294967295, 7, 1, 24, 2, 3, 4294967295, 4294967295, 2, 2, 8, 5, 1, 4294967295, 4294967295, 7, 2, 24, 6, 3, 4294967295, 4294967295, 2, 3, 8, 9, 1, 4294967295, 4294967295, 7, 3, 24, 10, 3, 4294967295, 4294967295, 2, 4, 8, 13, 1, 4294967295, 4294967295, 7, 4, 24, 14, 7, 4294967295, 4294967295, 2, 5, 8, 21, 1, 4294967295, 4294967295, 7, 5, 24, 22, 54, 4294967295, 4294967295, 2, 6, 8, 76, 1, 4294967295, 4294967295, 7, 6, 24, 77, 1, 4294967295, 4294967295, 2, 7, 8, 78, 1, 4294967295, 4294967295, 7, 7, 24, 79, 2, 4294967295, 4294967295, 2, 8, 12, 81, 1, 4294967295, 4294967295, 7, 8, 24, 82, 5, 4294967295, 4294967295, 2, 9, 8, 87, 1, 4294967295, 4294967295, 7, 9, 24, 88, 1, 4294967295, 4294967295, 2, 10, 8, 89, 1, 4294967295, 4294967295, 7, 10, 24, 90, 5, 4294967295, 4294967295, 2, 11, 8, 95, 1, 4294967295, 4294967295, 7, 11, 24, 96, 1, 4294967295, 4294967295, 2, 12, 8, 97, 1, 4294967295, 4294967295, 7, 12, 24, 98, 1, 4294967295, 4294967295, 2, 13, 8, 99, 1, 4294967295, 4294967295, 7, 13, 24, 100, 1, 4294967295, 4294967295, 2, 14, 8, 101, 1, 4294967295, 4294967295, 7, 14, 24, 102, 2, 4294967295, 4294967295, 2, 15, 8, 104, 1, 4294967295, 4294967295, 7, 15, 24, 105, 3, 4294967295, 4294967295, 2, 16, 8, 108, 1, 4294967295, 4294967295, 7, 16, 24, 109, 9, 4294967295, 4294967295, 2, 17, 8, 118, 1, 4294967295, 4294967295, 7, 17, 24, 119, 1, 4294967295, 4294967295, 2, 18, 8, 120, 1, 4294967295, 4294967295, 7, 18, 24, 121, 1, 4294967295, 4294967295, 2, 19, 8, 122, 1, 4294967295, 4294967295, 7, 19, 24, 123, 31, 4294967295, 4294967295, 2, 20, 8, 154, 1, 4294967295, 4294967295, 7, 20, 24, 155, 5, 4294967295, 4294967295, 2, 21, 8, 160, 1, 4294967295, 4294967295, 7, 21, 24, 161, 2, 4294967295, 4294967295, 2, 22, 8, 163, 1, 4294967295, 4294967295, 7, 22, 24, 164, 4, 4294967295, 4294967295, 2, 23, 8, 168, 1, 4294967295, 4294967295, 7, 23, 24, 169, 6, 4294967295, 4294967295, 2, 24, 8, 175, 1, 4294967295, 4294967295, 7, 24, 24, 176, 6, 4294967295, 4294967295, 2, 25, 8, 182, 1, 4294967295, 4294967295, 7, 25, 24, 183, 1, 4294967295, 4294967295, 2, 26, 8, 184, 1, 4294967295, 4294967295, 7, 26, 24, 185, 1, 4294967295, 4294967295, 2, 27, 8, 186, 1, 4294967295, 4294967295, 7, 27, 24, 187, 1, 4294967295, 4294967295, 2, 28, 8, 188, 1, 4294967295, 4294967295, 7, 28, 24, 189, 15, 4294967295, 4294967295, 2, 29, 8, 204, 1, 4294967295, 4294967295, 7, 29, 24, 205, 4, 4294967295, 4294967295, 2, 30, 8, 209, 1, 4294967295, 4294967295, 7, 30, 24, 210, 1, 4294967295, 4294967295, 2, 31, 8, 211, 1, 4294967295, 4294967295, 7, 31, 24, 212, 6, 4294967295, 4294967295, 2, 32, 8, 218, 1, 4294967295, 4294967295, 7, 32, 24, 219, 16, 4294967295, 4294967295, 2, 33, 8, 235, 1, 4294967295, 4294967295, 7, 33, 24, 236, 9, 4294967295, 4294967295, 2, 34, 8, 245, 1, 4294967295, 4294967295, 7, 34, 24, 246, 1, 4294967295, 4294967295, 2, 35, 8, 247, 1, 4294967295, 4294967295, 7, 35, 24, 248, 6, 4294967295, 4294967295, 2, 36, 8, 254, 1, 4294967295, 4294967295, 7, 36, 24, 255, 1, 4294967295, 4294967295, 2, 37, 8, 256, 1, 4294967295, 4294967295, 7, 37, 24, 257, 1, 4294967295, 4294967295, 2, 38, 8, 258, 1, 4294967295, 4294967295, 7, 38, 24, 259, 9, 4294967295, 4294967295, 2, 39, 8, 268, 1, 4294967295, 4294967295, 7, 39, 24, 269, 2, 4294967295, 4294967295, 2, 40, 8, 271, 1, 4294967295, 4294967295, 7, 40, 24, 272, 9, 4294967295, 4294967295, 2, 41, 8, 281, 1, 4294967295, 4294967295, 7, 41, 24, 282, 2, 4294967295, 4294967295, 2, 42, 8, 284, 1, 4294967295, 4294967295, 7, 42, 24, 285, 1, 4294967295, 4294967295, 2, 43, 8, 286, 1, 4294967295, 4294967295, 7, 43, 24, 287, 2, 4294967295, 4294967295, 2, 44, 8, 289, 1, 4294967295, 4294967295, 7, 44, 24, 290, 1, 4294967295, 4294967295, 2, 45, 8, 291, 1, 4294967295, 4294967295, 7, 45, 24, 292, 1, 4294967295, 4294967295, 2, 46, 8, 293, 1, 4294967295, 4294967295, 7, 46, 24, 294, 1, 4294967295, 4294967295, 2, 47, 8, 295, 1, 4294967295, 4294967295, 7, 47, 24, 296, 1, 4294967295, 4294967295, 2, 48, 8, 297, 1, 4294967295, 4294967295, 7, 48, 24, 298, 1, 4294967295, 4294967295, 2, 49, 8, 299, 1, 4294967295, 4294967295, 7, 49, 24, 300, 1, 4294967295, 4294967295, 2, 50, 8, 301, 1, 4294967295, 4294967295, 7, 50, 24, 302, 1, 4294967295, 4294967295, 2, 51, 8, 303, 1, 4294967295, 4294967295, 7, 51, 24, 304, 1, 4294967295, 4294967295, 2, 52, 8, 305, 1, 4294967295, 4294967295, 7, 52, 24, 306, 1, 4294967295, 4294967295, 2, 53, 8, 307, 1, 4294967295, 4294967295, 7, 53, 24, 308, 1, 4294967295, 4294967295, 2, 54, 8, 309, 1, 4294967295, 4294967295, 7, 54, 24, 310, 1, 4294967295, 4294967295, 2, 55, 8, 311, 1, 4294967295, 4294967295, 7, 55, 24, 312, 3, 4294967295, 4294967295, 2, 56, 8, 315, 1, 4294967295, 4294967295, 7, 56, 24, 316, 1, 4294967295, 4294967295, 2, 57, 8, 317, 1, 4294967295, 4294967295, 7, 57, 24, 318, 1, 4294967295, 4294967295, 2, 58, 8, 319, 1, 4294967295, 4294967295, 7, 58, 24, 320, 1, 4294967295, 4294967295, 2, 59, 8, 321, 1, 4294967295, 4294967295, 7, 59, 24, 322, 1, 4294967295, 4294967295, 2, 60, 8, 323, 1, 4294967295, 4294967295, 7, 60, 24, 324, 1, 4294967295, 4294967295, 2, 61, 8, 325, 1, 4294967295, 4294967295, 7, 61, 24, 326, 1, 4294967295, 4294967295, 2, 62, 8, 327, 1, 4294967295, 4294967295, 7, 62, 24, 328, 6, 4294967295, 4294967295, 2, 63, 8, 334, 1, 4294967295, 4294967295, 7, 63, 24, 335, 2, 4294967295, 4294967295, 2, 64, 8, 337, 1, 4294967295, 4294967295, 7, 64, 24, 338, 1, 4294967295, 4294967295, 2, 65, 8, 339, 1, 4294967295, 4294967295, 7, 65, 24, 340, 1, 4294967295, 4294967295, 2, 66, 8, 341, 1, 4294967295, 4294967295, 7, 66, 24, 342, 3, 4294967295, 4294967295, 2, 67, 8, 345, 1, 4294967295, 4294967295, 7, 67, 24, 346, 1, 4294967295, 4294967295, 2, 68, 8, 347, 1, 4294967295, 4294967295, 7, 68, 24, 348, 1, 4294967295, 4294967295, 2, 69, 8, 349, 1, 4294967295, 4294967295, 7, 69, 24, 350, 2, 4294967295, 4294967295, 2, 70, 8, 352, 1, 4294967295, 4294967295, 7, 70, 24, 353, 1, 4294967295, 4294967295, 2, 71, 8, 354, 1, 4294967295, 4294967295, 7, 71, 24, 355, 2, 4294967295, 4294967295, 2, 72, 8, 357, 1, 4294967295, 4294967295, 7, 72, 24, 358, 1, 4294967295, 4294967295, 2, 73, 8, 359, 1, 4294967295, 4294967295, 7, 73, 24, 360, 2, 4294967295, 4294967295, 2, 74, 8, 362, 1, 4294967295, 4294967295, 7, 74, 24, 363, 1, 4294967295, 4294967295, 2, 75, 8, 364, 1, 4294967295, 4294967295, 7, 75, 24, 365, 1, 4294967295, 4294967295, 2, 76, 12, 366, 1, 4294967295, 4294967295, 7, 76, 24, 367, 39, 4294967295, 4294967295, 2, 77, 8, 406, 1, 4294967295, 4294967295, 7, 77, 24, 407, 1, 4294967295, 4294967295, 2, 78, 8, 408, 1, 4294967295, 4294967295, 7, 78, 24, 409, 2, 4294967295, 4294967295, 2, 79, 8, 411, 1, 4294967295, 4294967295, 7, 79, 24, 412, 1, 4294967295, 4294967295, 2, 80, 8, 413, 1, 4294967295, 4294967295, 7, 80, 24, 414, 1, 4294967295, 4294967295, 2, 81, 8, 415, 1, 4294967295, 4294967295, 7, 81, 24, 416, 2, 4294967295, 4294967295, 2, 82, 8, 418, 1, 4294967295, 4294967295, 7, 82, 24, 419, 2, 4294967295, 4294967295, 2, 83, 8, 421, 1, 4294967295, 4294967295, 7, 83, 24, 422, 1, 4294967295, 4294967295, 2, 84, 8, 423, 1, 4294967295, 4294967295, 7, 84, 24, 424, 2, 4294967295, 4294967295, 2, 85, 8, 426, 1, 4294967295, 4294967295, 7, 85, 24, 427, 1, 4294967295, 4294967295, 2, 86, 8, 428, 1, 4294967295, 4294967295, 7, 86, 24, 429, 1, 4294967295, 4294967295, 2, 87, 8, 430, 1, 4294967295, 4294967295, 7, 87, 24, 431, 1, 4294967295, 4294967295, 2, 88, 8, 432, 1, 4294967295, 4294967295, 7, 88, 24, 433, 1, 4294967295, 4294967295, 2, 89, 8, 434, 1, 4294967295, 4294967295, 7, 89, 24, 435, 2, 4294967295, 4294967295, 2, 90, 8, 437, 1, 4294967295, 4294967295, 7, 90, 24, 438, 14, 4294967295, 4294967295, 2, 91, 8, 452, 1, 4294967295, 4294967295, 7, 91, 24, 453, 1, 4294967295, 4294967295, 2, 92, 8, 454, 1, 4294967295, 4294967295, 7, 92, 24, 455, 1, 4294967295, 4294967295, 2, 93, 8, 456, 1, 4294967295, 4294967295, 7, 93, 24, 457, 1, 4294967295, 4294967295, 2, 94, 8, 458, 1, 4294967295, 4294967295, 7, 94, 24, 459, 1, 4294967295, 4294967295, 2, 95, 8, 460, 1, 4294967295, 4294967295, 7, 95, 24, 461, 1, 4294967295, 4294967295, 2, 96, 8, 462, 1, 4294967295, 4294967295, 7, 96, 24, 463, 1, 4294967295, 4294967295, 2, 97, 8, 464, 1, 4294967295, 4294967295, 7, 97, 24, 465, 1, 4294967295, 4294967295, 2, 98, 8, 466, 1, 4294967295, 4294967295, 7, 98, 24, 467, 1, 4294967295, 4294967295, 2, 99, 8, 468, 1, 4294967295, 4294967295, 7, 99, 24, 469, 1, 4294967295, 4294967295, 2, 100, 8, 470, 1, 4294967295, 4294967295, 7, 100, 24, 471, 1, 4294967295, 4294967295, 2, 101, 8, 472, 1, 4294967295, 4294967295, 7, 101, 24, 473, 1, 4294967295, 4294967295, 2, 102, 8, 474, 1, 4294967295, 4294967295, 7, 102, 24, 475, 1, 4294967295, 4294967295, 2, 103, 8, 476, 1, 4294967295, 4294967295, 7, 103, 24, 477, 1, 4294967295, 4294967295, 2, 104, 8, 478, 1, 4294967295, 4294967295, 7, 104, 24, 479, 1, 4294967295, 4294967295, 2, 105, 8, 480, 1, 4294967295, 4294967295, 7, 105, 24, 481, 1, 4294967295, 4294967295, 2, 106, 8, 482, 1, 4294967295, 4294967295, 7, 106, 24, 483, 1, 4294967295, 4294967295, 2, 107, 8, 484, 1, 4294967295, 4294967295, 7, 107, 24, 485, 1, 4294967295, 4294967295, 2, 108, 8, 486, 1, 4294967295, 4294967295, 7, 108, 24, 487, 1, 4294967295, 4294967295, 2, 109, 8, 488, 1, 4294967295, 4294967295, 7, 109, 24, 489, 1, 4294967295, 4294967295, 2, 110, 8, 490, 1, 4294967295, 4294967295, 7, 110, 24, 491, 1, 4294967295, 4294967295, 2, 111, 8, 492, 1, 4294967295, 4294967295, 7, 111, 24, 493, 1, 4294967295, 4294967295, 2, 112, 8, 494, 1, 4294967295, 4294967295, 7, 112, 24, 495, 1, 4294967295, 4294967295, 2, 113, 8, 496, 1, 4294967295, 4294967295, 7, 113, 24, 497, 1, 4294967295, 4294967295, 2, 114, 12, 498, 1, 4294967295, 4294967295, 7, 114, 24, 499, 10, 4294967295, 4294967295, 2, 115, 8, 509, 1, 4294967295, 4294967295, 7, 115, 24, 510, 1, 4294967295, 4294967295, 2, 116, 8, 511, 1, 4294967295, 4294967295, 7, 116, 24, 512, 1, 4294967295, 4294967295, 2, 117, 8, 513, 1, 4294967295, 4294967295, 7, 117, 24, 514, 7, 4294967295, 4294967295, 2, 118, 8, 521, 1, 4294967295, 4294967295, 7, 118, 24, 522, 1, 4294967295, 4294967295, 2, 119, 8, 523, 1, 4294967295, 4294967295, 7, 119, 24, 524, 1, 4294967295, 4294967295, 2, 120, 8, 525, 1, 4294967295, 4294967295, 7, 120, 24, 526, 1, 4294967295, 4294967295, 2, 121, 8, 527, 1, 4294967295, 4294967295, 7, 121, 24, 528, 1, 4294967295, 4294967295, 2, 122, 8, 529, 1, 4294967295, 4294967295, 7, 122, 24, 530, 1, 4294967295, 4294967295, 2, 123, 8, 531, 1, 4294967295, 4294967295, 7, 123, 24, 532, 1, 4294967295, 4294967295, 2, 124, 8, 533, 1, 4294967295, 4294967295, 7, 124, 24, 534, 1, 4294967295, 4294967295, 2, 125, 8, 535, 1, 4294967295, 4294967295, 7, 125, 24, 536, 1, 4294967295, 4294967295, 2, 126, 8, 537, 1, 4294967295, 4294967295, 7, 126, 24, 538, 4, 4294967295, 4294967295, 2, 127, 8, 542, 1, 4294967295, 4294967295, 7, 127, 24, 543, 1, 4294967295, 4294967295, 2, 128, 8, 544, 1, 4294967295, 4294967295, 7, 128, 24, 545, 1, 4294967295, 4294967295, 2, 129, 8, 546, 1, 4294967295, 4294967295, 7, 129, 24, 547, 1, 4294967295, 4294967295, 2, 130, 8, 548, 1, 4294967295, 4294967295, 7, 130, 24, 549, 1, 4294967295, 4294967295, 2, 131, 8, 550, 1, 4294967295, 4294967295, 7, 131, 24, 551, 1, 4294967295, 4294967295, 2, 132, 8, 552, 1, 4294967295, 4294967295, 7, 132, 24, 553, 1, 4294967295, 4294967295, 2, 133, 8, 554, 1, 4294967295, 4294967295, 7, 133, 24, 555, 1, 4294967295, 4294967295, 2, 134, 8, 556, 1, 4294967295, 4294967295, 7, 134, 24, 557, 1, 4294967295, 4294967295, 2, 135, 8, 558, 1, 4294967295, 4294967295, 7, 135, 24, 559, 2, 4294967295, 4294967295, 2, 136, 8, 561, 1, 4294967295, 4294967295, 7, 136, 24, 562, 1, 4294967295, 4294967295, 2, 137, 8, 563, 1, 4294967295, 4294967295, 7, 137, 24, 564, 1, 4294967295, 4294967295, 2, 138, 8, 565, 1, 4294967295, 4294967295, 7, 138, 24, 566, 1, 4294967295, 4294967295, 2, 139, 8, 567, 1, 4294967295, 4294967295, 7, 139, 24, 568, 1, 4294967295, 4294967295, 2, 140, 8, 569, 1, 4294967295, 4294967295, 7, 140, 24, 570, 1, 4294967295, 4294967295, 2, 141, 8, 571, 1, 4294967295, 4294967295, 7, 141, 24, 572, 1, 4294967295, 4294967295, 2, 142, 8, 573, 1, 4294967295, 4294967295, 7, 142, 24, 574, 1, 4294967295, 4294967295, 2, 143, 8, 575, 1, 4294967295, 4294967295, 7, 143, 24, 576, 1, 4294967295, 4294967295, 2, 144, 8, 577, 1, 4294967295, 4294967295, 7, 144, 24, 578, 1, 4294967295, 4294967295, 2, 145, 8, 579, 1, 4294967295, 4294967295, 7, 145, 24, 580, 1, 4294967295, 4294967295, 2, 146, 8, 581, 1, 4294967295, 4294967295, 7, 146, 24, 582, 1, 4294967295, 4294967295, 2, 147, 8, 583, 1, 4294967295, 4294967295, 7, 147, 24, 584, 1, 4294967295, 4294967295, 2, 148, 12, 585, 1, 4294967295, 4294967295, 7, 148, 24, 586, 69, 4294967295, 4294967295, 2, 149, 8, 655, 1, 4294967295, 4294967295, 7, 149, 24, 656, 1, 4294967295, 4294967295, 2, 150, 8, 657, 1, 4294967295, 4294967295, 7, 150, 24, 658, 1, 4294967295, 4294967295, 2, 151, 8, 659, 1, 4294967295, 4294967295, 7, 151, 24, 660, 1, 4294967295, 4294967295, 2, 152, 8, 661, 1, 4294967295, 4294967295, 7, 152, 24, 662, 1, 4294967295, 4294967295, 2, 153, 8, 663, 1, 4294967295, 4294967295, 7, 153, 24, 664, 1, 4294967295, 4294967295, 2, 154, 8, 665, 1, 4294967295, 4294967295, 7, 154, 24, 666, 1, 4294967295, 4294967295, 2, 155, 8, 667, 1, 4294967295, 4294967295, 7, 155, 24, 668, 2, 4294967295, 4294967295, 2, 156, 8, 670, 1, 4294967295, 4294967295, 7, 156, 24, 671, 1, 4294967295, 4294967295, 2, 157, 8, 672, 1, 4294967295, 4294967295, 7, 157, 24, 673, 8, 4294967295, 4294967295, 2, 158, 8, 681, 1, 4294967295, 4294967295, 7, 158, 24, 682, 1, 4294967295, 4294967295, 2, 159, 8, 683, 1, 4294967295, 4294967295, 7, 159, 24, 684, 1, 4294967295, 4294967295, 2, 160, 8, 685, 1, 4294967295, 4294967295, 7, 160, 24, 686, 1, 4294967295, 4294967295, 2, 161, 8, 687, 1, 4294967295, 4294967295, 7, 161, 24, 688, 1, 4294967295, 4294967295, 2, 162, 8, 689, 1, 4294967295, 4294967295, 7, 162, 24, 690, 1, 4294967295, 4294967295, 2, 163, 8, 691, 1, 4294967295, 4294967295, 7, 163, 24, 692, 1, 4294967295, 4294967295, 2, 164, 8, 693, 1, 4294967295, 4294967295, 7, 164, 24, 694, 1, 4294967295, 4294967295, 2, 165, 8, 695, 1, 4294967295, 4294967295, 7, 165, 24, 696, 2, 4294967295, 4294967295, 2, 166, 8, 698, 1, 4294967295, 4294967295, 7, 166, 24, 699, 1, 4294967295, 4294967295, 2, 167, 8, 700, 1, 4294967295, 4294967295, 7, 167, 24, 701, 1, 4294967295, 4294967295, 2, 168, 8, 702, 1, 4294967295, 4294967295, 7, 168, 24, 703, 1, 4294967295, 4294967295, 2, 169, 8, 704, 1, 4294967295, 4294967295, 7, 169, 24, 705, 1, 4294967295, 4294967295, 2, 170, 8, 706, 1, 4294967295, 4294967295, 7, 170, 24, 707, 1, 4294967295, 4294967295, 2, 171, 8, 708, 1, 4294967295, 4294967295, 7, 171, 24, 709, 1, 4294967295, 4294967295, 2, 172, 8, 710, 1, 4294967295, 4294967295, 7, 172, 24, 711, 1, 4294967295, 4294967295, 2, 173, 8, 712, 1, 4294967295, 4294967295, 7, 173, 24, 713, 1, 4294967295, 4294967295, 2, 174, 8, 714, 1, 4294967295, 4294967295, 7, 174, 24, 715, 1, 4294967295, 4294967295, 2, 175, 8, 716, 1, 4294967295, 4294967295, 7, 175, 24, 717, 1, 4294967295, 4294967295, 2, 176, 8, 718, 1, 4294967295, 4294967295, 7, 176, 24, 719, 1, 4294967295, 4294967295, 2, 177, 8, 720, 1, 4294967295, 4294967295, 7, 177, 24, 721, 1, 4294967295, 4294967295, 2, 178, 8, 722, 1, 4294967295, 4294967295, 7, 178, 24, 723, 1, 4294967295, 4294967295, 2, 179, 8, 724, 1, 4294967295, 4294967295, 7, 179, 24, 725, 1, 4294967295, 4294967295, 2, 180, 8, 726, 1, 4294967295, 4294967295, 7, 180, 24, 727, 4, 4294967295, 4294967295, 2, 181, 8, 731, 1, 4294967295, 4294967295, 7, 181, 24, 732, 1, 4294967295, 4294967295, 2, 182, 8, 733, 1, 4294967295, 4294967295, 7, 182, 24, 734, 1, 4294967295, 4294967295, 2, 183, 8, 735, 1, 4294967295, 4294967295, 7, 183, 24, 736, 1, 4294967295, 4294967295, 2, 184, 8, 737, 1, 4294967295, 4294967295, 7, 184, 24, 738, 1, 4294967295, 4294967295, 2, 185, 8, 739, 1, 4294967295, 4294967295, 7, 185, 24, 740, 1, 4294967295, 4294967295, 2, 186, 8, 741, 1, 4294967295, 4294967295, 7, 186, 24, 742, 2, 4294967295, 4294967295, 2, 187, 8, 744, 1, 4294967295, 4294967295, 7, 187, 24, 745, 1, 4294967295, 4294967295, 2, 188, 8, 746, 1, 4294967295, 4294967295, 7, 188, 24, 747, 1, 4294967295, 4294967295, 2, 189, 8, 748, 1, 4294967295, 4294967295, 7, 189, 24, 749, 1, 4294967295, 4294967295, 2, 190, 8, 750, 1, 4294967295, 4294967295, 7, 190, 24, 751, 1, 4294967295, 4294967295, 2, 191, 8, 752, 1, 4294967295, 4294967295, 7, 191, 24, 753, 1, 4294967295, 4294967295, 2, 192, 8, 754, 1, 4294967295, 4294967295, 7, 192, 24, 755, 1, 4294967295, 4294967295, 2, 193, 8, 756, 1, 4294967295, 4294967295, 7, 193, 24, 757, 1, 4294967295, 4294967295, 2, 194, 8, 758, 1, 4294967295, 4294967295, 7, 194, 24, 759, 1, 4294967295, 4294967295, 2, 195, 8, 760, 1, 4294967295, 4294967295, 7, 195, 24, 761, 1, 4294967295, 4294967295, 2, 196, 8, 762, 1, 4294967295, 4294967295, 7, 196, 24, 763, 1, 4294967295, 4294967295, 2, 197, 8, 764, 1, 4294967295, 4294967295, 7, 197, 24, 765, 2, 4294967295, 4294967295, 2, 198, 8, 767, 1, 4294967295, 4294967295, 7, 198, 24, 768, 2, 4294967295, 4294967295, 2, 199, 8, 770, 1, 4294967295, 4294967295, 7, 199, 24, 771, 1, 4294967295, 4294967295, 2, 200, 8, 772, 1, 4294967295, 4294967295, 7, 200, 24, 773, 1, 4294967295, 4294967295, 2, 201, 8, 774, 1, 4294967295, 4294967295, 7, 201, 24, 775, 1, 4294967295, 4294967295, 2, 202, 8, 776, 1, 4294967295, 4294967295, 7, 202, 24, 777, 1, 4294967295, 4294967295, 2, 203, 8, 778, 1, 4294967295, 4294967295, 7, 203, 24, 779, 1, 4294967295, 4294967295, 2, 204, 8, 780, 1, 4294967295, 4294967295, 7, 204, 24, 781, 2, 4294967295, 4294967295, 2, 205, 8, 783, 1, 4294967295, 4294967295, 7, 205, 24, 784, 1, 4294967295, 4294967295, 2, 206, 8, 785, 1, 4294967295, 4294967295, 7, 206, 24, 786, 1, 4294967295, 4294967295, 2, 207, 8, 787, 1, 4294967295, 4294967295, 7, 207, 24, 788, 1, 4294967295, 4294967295, 2, 208, 8, 789, 1, 4294967295, 4294967295, 7, 208, 24, 790, 1, 4294967295, 4294967295, 2, 209, 8, 791, 1, 4294967295, 4294967295, 7, 209, 24, 792, 1, 4294967295, 4294967295, 2, 210, 8, 793, 1, 4294967295, 4294967295, 7, 210, 24, 794, 1, 4294967295, 4294967295, 2, 211, 8, 795, 1, 4294967295, 4294967295, 7, 211, 24, 796, 1, 4294967295, 4294967295, 2, 212, 8, 797, 1, 4294967295, 4294967295, 7, 212, 24, 798, 1, 4294967295, 4294967295, 2, 213, 8, 799, 1, 4294967295, 4294967295, 7, 213, 24, 800, 1, 4294967295, 4294967295, 2, 214, 8, 801, 1, 4294967295, 4294967295, 7, 214, 24, 802, 1, 4294967295, 4294967295, 2, 215, 8, 803, 1, 4294967295, 4294967295, 7, 215, 24, 804, 2, 4294967295, 4294967295, 2, 216, 8, 806, 1, 4294967295, 4294967295, 7, 216, 24, 807, 1, 4294967295, 4294967295, 2, 217, 8, 808, 1, 4294967295, 4294967295, 7, 217, 24, 809, 1, 4294967295, 4294967295, 2, 218, 8, 810, 1, 4294967295, 4294967295, 7, 218, 24, 811, 1, 4294967295, 4294967295, 2, 219, 8, 812, 1, 4294967295, 4294967295, 7, 219, 24, 813, 1, 4294967295, 4294967295, 2, 220, 8, 814, 1, 4294967295, 4294967295, 7, 220, 24, 815, 1, 4294967295, 4294967295, 2, 221, 8, 816, 1, 4294967295, 4294967295, 7, 221, 24, 817, 33, 4294967295, 4294967295, 2, 222, 8, 850, 1, 4294967295, 4294967295, 7, 222, 24, 851, 1, 4294967295, 4294967295, 2, 223, 8, 852, 1, 4294967295, 4294967295, 7, 223, 24, 853, 2, 4294967295, 4294967295, 2, 224, 8, 855, 1, 4294967295, 4294967295, 7, 224, 24, 856, 1, 4294967295, 4294967295, 2, 225, 8, 857, 1, 4294967295, 4294967295, 7, 225, 24, 858, 1, 4294967295, 4294967295, 2, 226, 8, 859, 1, 4294967295, 4294967295, 7, 226, 24, 860, 1, 4294967295, 4294967295, 2, 227, 8, 861, 1, 4294967295, 4294967295, 7, 227, 24, 862, 1, 4294967295, 4294967295, 2, 228, 8, 863, 1, 4294967295, 4294967295, 7, 228, 24, 864, 2, 4294967295, 4294967295, 2, 229, 8, 866, 1, 4294967295, 4294967295, 7, 229, 24, 867, 3, 4294967295, 4294967295, 2, 230, 8, 870, 1, 4294967295, 4294967295, 7, 230, 24, 871, 1, 4294967295, 4294967295, 2, 231, 8, 872, 1, 4294967295, 4294967295, 7, 231, 24, 873, 1, 4294967295, 4294967295, 2, 232, 8, 874, 1, 4294967295, 4294967295, 7, 232, 24, 875, 1, 4294967295, 4294967295, 2, 233, 8, 876, 1, 4294967295, 4294967295, 7, 233, 24, 877, 1, 4294967295, 4294967295, 2, 234, 8, 878, 1, 4294967295, 4294967295, 7, 234, 24, 879, 2, 4294967295, 4294967295, 2, 235, 8, 881, 1, 4294967295, 4294967295, 7, 235, 24, 882, 2, 4294967295, 4294967295, 2, 236, 8, 884, 1, 4294967295, 4294967295, 7, 236, 24, 885, 2, 4294967295, 4294967295, 2, 237, 8, 887, 1, 4294967295, 4294967295, 7, 237, 24, 888, 1, 4294967295, 4294967295, 2, 238, 8, 889, 1, 4294967295, 4294967295, 7, 238, 24, 890, 3, 4294967295, 4294967295, 2, 239, 8, 893, 1, 4294967295, 4294967295, 7, 239, 24, 894, 3, 4294967295, 4294967295, 2, 240, 8, 897, 1, 4294967295, 4294967295, 7, 240, 24, 898, 3, 4294967295, 4294967295, 2, 241, 8, 901, 1, 4294967295, 4294967295, 7, 241, 24, 902, 3, 4294967295, 4294967295, 2, 242, 8, 905, 1, 4294967295, 4294967295, 7, 242, 24, 906, 1, 4294967295, 4294967295, 2, 243, 8, 907, 1, 4294967295, 4294967295, 7, 243, 24, 908, 2, 4294967295, 4294967295, 1, 0, 8, 910, 1, 4294967295, 4294967295, 5, 0, 8, 911, 1, 490, 4294967295, 8, 0, 8, 912, 1, 4294967295, 4294967295, 10, 0, 8, 913, 2, 4294967295, 4294967295, 12, 0, 8, 915, 1, 4294967295, 493, 9, 0, 8, 916, 1, 4294967295, 4294967295, 1, 0, 8, 917, 1, 4294967295, 4294967295, 5, 0, 8, 918, 1, 496, 4294967295, 8, 0, 8, 919, 1, 4294967295, 4294967295, 10, 0, 8, 920, 2, 4294967295, 4294967295, 12, 0, 8, 922, 1, 4294967295, 499, 9, 0, 8, 923, 1, 4294967295, 4294967295, 1, 0, 8, 924, 1, 4294967295, 4294967295, 5, 0, 8, 925, 1, 502, 4294967295, 8, 0, 8, 926, 1, 4294967295, 4294967295, 10, 0, 8, 927, 2, 4294967295, 4294967295, 12, 0, 8, 929, 1, 4294967295, 505, 9, 0, 8, 930, 1, 4294967295, 4294967295, 1, 0, 8, 931, 1, 4294967295, 4294967295, 5, 0, 8, 932, 1, 508, 4294967295, 8, 0, 8, 933, 1, 4294967295, 4294967295, 10, 0, 8, 934, 2, 4294967295, 4294967295, 12, 0, 8, 936, 1, 4294967295, 511, 9, 0, 8, 937, 1, 4294967295, 4294967295, 1, 0, 32, 938, 1, 4294967295, 4294967295, 1, 0, 8, 939, 1, 4294967295, 4294967295, 1, 1, 32, 940, 1, 4294967295, 4294967295, 1, 1, 32, 941, 1, 4294967295, 4294967295, 1, 1, 8, 942, 1, 4294967295, 4294967295, 1, 1, 32, 943, 1, 4294967295, 4294967295, 1, 1, 8, 944, 1, 4294967295, 4294967295, 1, 2, 32, 945, 1, 4294967295, 4294967295, 3, 2, 8, 946, 2, 521, 4294967295, 8, 2, 8, 948, 1, 4294967295, 4294967295, 1, 2, 32, 949, 1, 4294967295, 4294967295, 1, 2, 32, 950, 1, 4294967295, 4294967295, 1, 2, 32, 951, 1, 4294967295, 4294967295, 3, 2, 8, 952, 2, 526, 4294967295, 8, 2, 8, 954, 1, 4294967295, 4294967295, 1, 2, 8, 955, 1, 4294967295, 4294967295, 3, 2, 8, 956, 3, 529, 4294967295, 8, 2, 8, 959, 1, 4294967295, 4294967295, 1, 2, 8, 960, 1, 4294967295, 4294967295, 1, 2, 32, 961, 1, 4294967295, 4294967295, 1, 2, 8, 962, 1, 4294967295, 4294967295, 1, 3, 8, 963, 1, 4294967295, 4294967295, 1, 3, 32, 964, 1, 4294967295, 4294967295, 1, 3, 8, 965, 1, 4294967295, 4294967295, 1, 4, 32, 966, 1, 4294967295, 4294967295, 1, 4, 8, 967, 1, 4294967295, 4294967295, 3, 4, 8, 968, 2, 539, 4294967295, 8, 4, 8, 970, 1, 4294967295, 4294967295, 1, 5, 32, 971, 1, 4294967295, 4294967295, 1, 5, 8, 972, 1, 4294967295, 4294967295, 3, 5, 8, 973, 2, 543, 4294967295, 8, 5, 8, 975, 1, 4294967295, 4294967295, 1, 5, 8, 976, 1, 4294967295, 4294967295, 1, 5, 32, 977, 1, 4294967295, 4294967295, 1, 5, 8, 978, 1, 4294967295, 4294967295, 5, 5, 8, 979, 1, 548, 4294967295, 8, 5, 8, 980, 1, 4294967295, 4294967295, 10, 5, 8, 981, 2, 4294967295, 4294967295, 12, 5, 8, 983, 1, 4294967295, 551, 9, 5, 8, 984, 1, 4294967295, 4294967295, 1, 5, 32, 985, 1, 4294967295, 4294967295, 1, 5, 8, 986, 1, 4294967295, 4294967295, 1, 6, 8, 987, 1, 4294967295, 4294967295, 1, 6, 32, 988, 1, 4294967295, 4294967295, 1, 6, 8, 989, 1, 4294967295, 4294967295, 1, 7, 8, 990, 1, 4294967295, 4294967295, 1, 7, 8, 991, 1, 4294967295, 4294967295, 3, 7, 8, 992, 2, 560, 4294967295, 8, 7, 8, 994, 1, 4294967295, 4294967295, 1, 8, 72, 995, 1, 4294967295, 4294967295, 1, 8, 8, 996, 1, 4294967295, 4294967295, 1, 8, 8, 997, 1, 4294967295, 4294967295, 3, 8, 8, 998, 2, 565, 4294967295, 8, 8, 8, 1000, 1, 4294967295, 4294967295, 1, 8, 72, 1001, 1, 4294967295, 4294967295, 1, 8, 32, 1002, 1, 4294967295, 4294967295, 1, 8, 8, 1003, 1, 4294967295, 4294967295, 5, 8, 8, 1004, 1, 570, 4294967295, 8, 8, 8, 1005, 1, 4294967295, 4294967295, 10, 8, 10, 1006, 2, 4294967295, 4294967295, 12, 8, 8, 1008, 1, 4294967295, 573, 9, 8, 8, 1009, 1, 4294967295, 4294967295, 1, 9, 8, 1010, 1, 4294967295, 4294967295, 1, 9, 32, 1011, 1, 4294967295, 4294967295, 1, 9, 8, 1012, 1, 4294967295, 4294967295, 1, 9, 8, 1013, 1, 4294967295, 4294967295, 1, 10, 8, 1014, 1, 4294967295, 4294967295, 1, 10, 8, 1015, 1, 4294967295, 4294967295, 3, 10, 8, 1016, 2, 581, 4294967295, 8, 10, 8, 1018, 1, 4294967295, 4294967295, 1, 11, 8, 1019, 1, 4294967295, 4294967295, 1, 11, 8, 1020, 1, 4294967295, 4294967295, 1, 11, 8, 1021, 1, 4294967295, 4294967295, 1, 12, 32, 1022, 1, 4294967295, 4294967295, 1, 12, 8, 1023, 1, 4294967295, 4294967295, 3, 12, 8, 1024, 2, 588, 4294967295, 8, 12, 8, 1026, 1, 4294967295, 4294967295, 1, 12, 32, 1027, 1, 4294967295, 4294967295, 1, 12, 8, 1028, 1, 4294967295, 4294967295, 3, 12, 8, 1029, 2, 592, 4294967295, 8, 12, 8, 1031, 1, 4294967295, 4294967295, 5, 12, 8, 1032, 1, 594, 4294967295, 8, 12, 8, 1033, 1, 4294967295, 4294967295, 10, 12, 8, 1034, 2, 4294967295, 4294967295, 12, 12, 8, 1036, 1, 4294967295, 597, 9, 12, 8, 1037, 1, 4294967295, 4294967295, 3, 12, 8, 1038, 2, 599, 4294967295, 8, 12, 8, 1040, 1, 4294967295, 4294967295, 1, 12, 32, 1041, 1, 4294967295, 4294967295, 1, 12, 8, 1042, 1, 4294967295, 4294967295, 1, 13, 32, 1043, 1, 4294967295, 4294967295, 1, 13, 8, 1044, 1, 4294967295, 4294967295, 1, 13, 32, 1045, 1, 4294967295, 4294967295, 1, 13, 8, 1046, 1, 4294967295, 4294967295, 5, 13, 8, 1047, 1, 607, 4294967295, 8, 13, 8, 1048, 1, 4294967295, 4294967295, 10, 13, 8, 1049, 2, 4294967295, 4294967295, 12, 13, 8, 1051, 1, 4294967295, 610, 9, 13, 8, 1052, 1, 4294967295, 4294967295, 3, 13, 8, 1053, 2, 612, 4294967295, 8, 13, 8, 1055, 1, 4294967295, 4294967295, 1, 13, 32, 1056, 1, 4294967295, 4294967295, 1, 13, 8, 1057, 1, 4294967295, 4294967295, 1, 14, 8, 1058, 1, 4294967295, 4294967295, 3, 14, 8, 1059, 2, 617, 4294967295, 8, 14, 8, 1061, 1, 4294967295, 4294967295, 1, 14, 8, 1062, 1, 4294967295, 4294967295, 3, 14, 8, 1063, 2, 620, 4294967295, 8, 14, 8, 1065, 1, 4294967295, 4294967295, 3, 14, 8, 1066, 2, 622, 4294967295, 8, 14, 8, 1068, 1, 4294967295, 4294967295, 1, 14, 8, 1069, 1, 4294967295, 4294967295, 1, 14, 8, 1070, 1, 4294967295, 4294967295, 1, 15, 8, 1071, 1, 4294967295, 4294967295, 1, 15, 32, 1072, 1, 4294967295, 4294967295, 1, 15, 8, 1073, 1, 4294967295, 4294967295, 1, 16, 8, 1074, 1, 4294967295, 4294967295, 1, 16, 8, 1075, 1, 4294967295, 4294967295, 1, 16, 8, 1076, 1, 4294967295, 4294967295, 1, 16, 8, 1077, 1, 4294967295, 4294967295, 1, 16, 8, 1078, 1, 4294967295, 4294967295, 1, 16, 8, 1079, 1, 4294967295, 4294967295, 1, 16, 8, 1080, 1, 4294967295, 4294967295, 1, 16, 8, 1081, 1, 4294967295, 4294967295, 1, 16, 8, 1082, 1, 4294967295, 4294967295, 1, 16, 8, 1083, 1, 4294967295, 4294967295, 1, 16, 8, 1084, 1, 4294967295, 4294967295, 3, 16, 8, 1085, 11, 640, 4294967295, 8, 16, 8, 1096, 1, 4294967295, 4294967295, 1, 17, 8, 1097, 1, 4294967295, 4294967295, 1, 17, 8, 1098, 1, 4294967295, 4294967295, 3, 17, 8, 1099, 2, 644, 4294967295, 8, 17, 8, 1101, 1, 4294967295, 4294967295, 1, 18, 8, 1102, 1, 4294967295, 4294967295, 5, 18, 8, 1103, 1, 647, 4294967295, 8, 18, 8, 1104, 1, 4294967295, 4294967295, 10, 18, 8, 1105, 2, 4294967295, 4294967295, 12, 18, 8, 1107, 1, 4294967295, 650, 9, 18, 8, 1108, 1, 4294967295, 4294967295, 1, 18, 8, 1109, 1, 4294967295, 4294967295, 5, 18, 8, 1110, 1, 653, 4294967295, 8, 18, 8, 1111, 1, 4294967295, 4294967295, 10, 18, 8, 1112, 2, 4294967295, 4294967295, 12, 18, 8, 1114, 1, 4294967295, 656, 9, 18, 8, 1115, 1, 4294967295, 4294967295, 1, 18, 32, 1116, 1, 4294967295, 4294967295, 1, 18, 8, 1117, 1, 4294967295, 4294967295, 1, 18, 32, 1118, 1, 4294967295, 4294967295, 1, 18, 8, 1119, 1, 4294967295, 4294967295, 1, 19, 32, 1120, 1, 4294967295, 4294967295, 1, 19, 8, 1121, 1, 4294967295, 4294967295, 1, 20, 8, 1122, 1, 4294967295, 4294967295, 1, 20, 8, 1123, 1, 4294967295, 4294967295, 1, 20, 32, 1124, 1, 4294967295, 4294967295, 1, 20, 8, 1125, 1, 4294967295, 4294967295, 5, 20, 8, 1126, 1, 668, 4294967295, 8, 20, 8, 1127, 1, 4294967295, 4294967295, 10, 20, 8, 1128, 2, 4294967295, 4294967295, 12, 20, 8, 1130, 1, 4294967295, 671, 9, 20, 8, 1131, 1, 4294967295, 4294967295, 1, 21, 8, 1132, 1, 4294967295, 4294967295, 1, 21, 8, 1133, 1, 4294967295, 4294967295, 3, 21, 8, 1134, 2, 675, 4294967295, 8, 21, 8, 1136, 1, 4294967295, 4294967295, 1, 21, 8, 1137, 1, 4294967295, 4294967295, 3, 21, 8, 1138, 2, 678, 4294967295, 8, 21, 8, 1140, 1, 4294967295, 4294967295, 1, 22, 32, 1141, 1, 4294967295, 4294967295, 1, 22, 8, 1142, 1, 4294967295, 4294967295, 1, 22, 32, 1143, 1, 4294967295, 4294967295, 1, 22, 8, 1144, 1, 4294967295, 4294967295, 5, 22, 8, 1145, 1, 684, 4294967295, 8, 22, 8, 1146, 1, 4294967295, 4294967295, 10, 22, 8, 1147, 2, 4294967295, 4294967295, 12, 22, 8, 1149, 1, 4294967295, 687, 9, 22, 8, 1150, 1, 4294967295, 4294967295, 1, 22, 32, 1151, 1, 4294967295, 4294967295, 1, 22, 8, 1152, 1, 4294967295, 4294967295, 1, 23, 8, 1153, 1, 4294967295, 4294967295, 3, 23, 8, 1154, 2, 692, 4294967295, 8, 23, 8, 1156, 1, 4294967295, 4294967295, 1, 23, 32, 1157, 1, 4294967295, 4294967295, 3, 23, 8, 1158, 2, 695, 4294967295, 8, 23, 8, 1160, 1, 4294967295, 4294967295, 1, 23, 8, 1161, 1, 4294967295, 4294967295, 1, 23, 8, 1162, 1, 4294967295, 4294967295, 1, 24, 32, 1163, 1, 4294967295, 4294967295, 1, 24, 8, 1164, 1, 4294967295, 4294967295, 1, 24, 8, 1165, 1, 4294967295, 4294967295, 1, 25, 8, 1166, 1, 4294967295, 4294967295, 5, 25, 8, 1167, 1, 703, 4294967295, 8, 25, 8, 1168, 1, 4294967295, 4294967295, 10, 25, 8, 1169, 2, 4294967295, 4294967295, 12, 25, 8, 1171, 1, 4294967295, 706, 9, 25, 8, 1172, 1, 4294967295, 4294967295, 1, 25, 8, 1173, 1, 4294967295, 4294967295, 5, 25, 8, 1174, 1, 709, 4294967295, 8, 25, 8, 1175, 1, 4294967295, 4294967295, 10, 25, 8, 1176, 2, 4294967295, 4294967295, 12, 25, 8, 1178, 1, 4294967295, 712, 9, 25, 8, 1179, 1, 4294967295, 4294967295, 1, 25, 8, 1180, 1, 4294967295, 4294967295, 1, 25, 32, 1181, 1, 4294967295, 4294967295, 1, 25, 8, 1182, 1, 4294967295, 4294967295, 1, 26, 8, 1183, 1, 4294967295, 4294967295, 1, 26, 8, 1184, 1, 4294967295, 4294967295, 1, 26, 8, 1185, 1, 4294967295, 4294967295, 1, 26, 8, 1186, 1, 4294967295, 4294967295, 1, 26, 8, 1187, 1, 4294967295, 4294967295, 3, 26, 8, 1188, 5, 722, 4294967295, 8, 26, 8, 1193, 1, 4294967295, 4294967295, 1, 27, 8, 1194, 1, 4294967295, 4294967295, 5, 27, 8, 1195, 1, 725, 4294967295, 8, 27, 8, 1196, 1, 4294967295, 4294967295, 10, 27, 8, 1197, 2, 4294967295, 4294967295, 12, 27, 8, 1199, 1, 4294967295, 728, 9, 27, 8, 1200, 1, 4294967295, 4294967295, 1, 27, 8, 1201, 1, 4294967295, 4294967295, 5, 27, 8, 1202, 1, 731, 4294967295, 8, 27, 8, 1203, 1, 4294967295, 4294967295, 10, 27, 8, 1204, 2, 4294967295, 4294967295, 12, 27, 8, 1206, 1, 4294967295, 734, 9, 27, 8, 1207, 1, 4294967295, 4294967295, 1, 27, 8, 1208, 1, 4294967295, 4294967295, 1, 27, 8, 1209, 1, 4294967295, 4294967295, 1, 27, 8, 1210, 1, 4294967295, 4294967295, 3, 27, 8, 1211, 2, 739, 4294967295, 8, 27, 8, 1213, 1, 4294967295, 4294967295, 1, 27, 8, 1214, 1, 4294967295, 4294967295, 1, 27, 8, 1215, 1, 4294967295, 4294967295, 1, 27, 32, 1216, 1, 4294967295, 4294967295, 1, 27, 8, 1217, 1, 4294967295, 4294967295, 1, 27, 32, 1218, 1, 4294967295, 4294967295, 3, 27, 8, 1219, 3, 746, 4294967295, 8, 27, 8, 1222, 1, 4294967295, 4294967295, 1, 28, 32, 1223, 1, 4294967295, 4294967295, 1, 28, 8, 1224, 1, 4294967295, 4294967295, 1, 28, 32, 1225, 1, 4294967295, 4294967295, 1, 28, 8, 1226, 1, 4294967295, 4294967295, 5, 28, 8, 1227, 1, 752, 4294967295, 8, 28, 8, 1228, 1, 4294967295, 4294967295, 10, 28, 8, 1229, 2, 4294967295, 4294967295, 12, 28, 8, 1231, 1, 4294967295, 755, 9, 28, 8, 1232, 1, 4294967295, 4294967295, 3, 28, 8, 1233, 2, 757, 4294967295, 8, 28, 8, 1235, 1, 4294967295, 4294967295, 1, 28, 32, 1236, 1, 4294967295, 4294967295, 1, 28, 8, 1237, 1, 4294967295, 4294967295, 1, 29, 8, 1238, 1, 4294967295, 4294967295, 5, 29, 8, 1239, 1, 762, 4294967295, 8, 29, 8, 1240, 1, 4294967295, 4294967295, 10, 29, 8, 1241, 2, 4294967295, 4294967295, 12, 29, 8, 1243, 1, 4294967295, 765, 9, 29, 8, 1244, 1, 4294967295, 4294967295, 1, 29, 8, 1245, 1, 4294967295, 4294967295, 1, 29, 32, 1246, 1, 4294967295, 4294967295, 1, 29, 32, 1247, 1, 4294967295, 4294967295, 1, 29, 32, 1248, 1, 4294967295, 4294967295, 1, 29, 32, 1249, 1, 4294967295, 4294967295, 5, 29, 8, 1250, 5, 772, 4294967295, 8, 29, 8, 1255, 1, 4294967295, 4294967295, 10, 29, 8, 1256, 2, 4294967295, 4294967295, 12, 29, 8, 1258, 1, 4294967295, 775, 9, 29, 8, 1259, 1, 4294967295, 4294967295, 1, 29, 8, 1260, 1, 4294967295, 4294967295, 3, 29, 8, 1261, 2, 778, 4294967295, 8, 29, 8, 1263, 1, 4294967295, 4294967295, 1, 29, 8, 1264, 1, 4294967295, 4294967295, 1, 29, 32, 1265, 1, 4294967295, 4294967295, 3, 29, 8, 1266, 3, 782, 4294967295, 8, 29, 8, 1269, 1, 4294967295, 4294967295, 1, 29, 8, 1270, 1, 4294967295, 4294967295, 3, 29, 8, 1271, 2, 785, 4294967295, 8, 29, 8, 1273, 1, 4294967295, 4294967295, 1, 30, 32, 1274, 1, 4294967295, 4294967295, 1, 30, 32, 1275, 1, 4294967295, 4294967295, 1, 30, 8, 1276, 1, 4294967295, 4294967295, 1, 30, 8, 1277, 1, 4294967295, 4294967295, 1, 31, 32, 1278, 1, 4294967295, 4294967295, 1, 31, 8, 1279, 1, 4294967295, 4294967295, 1, 31, 32, 1280, 1, 4294967295, 4294967295, 1, 31, 8, 1281, 1, 4294967295, 4294967295, 5, 31, 8, 1282, 1, 795, 4294967295, 8, 31, 8, 1283, 1, 4294967295, 4294967295, 10, 31, 8, 1284, 2, 4294967295, 4294967295, 12, 31, 8, 1286, 1, 4294967295, 798, 9, 31, 8, 1287, 1, 4294967295, 4294967295, 3, 31, 8, 1288, 2, 800, 4294967295, 8, 31, 8, 1290, 1, 4294967295, 4294967295, 1, 31, 32, 1291, 1, 4294967295, 4294967295, 1, 31, 8, 1292, 1, 4294967295, 4294967295, 1, 32, 8, 1293, 1, 4294967295, 4294967295, 5, 32, 8, 1294, 1, 805, 4294967295, 8, 32, 8, 1295, 1, 4294967295, 4294967295, 10, 32, 8, 1296, 2, 4294967295, 4294967295, 12, 32, 8, 1298, 1, 4294967295, 808, 9, 32, 8, 1299, 1, 4294967295, 4294967295, 1, 32, 32, 1300, 1, 4294967295, 4294967295, 1, 32, 8, 1301, 1, 4294967295, 4294967295, 5, 32, 8, 1302, 1, 812, 4294967295, 8, 32, 8, 1303, 1, 4294967295, 4294967295, 10, 32, 8, 1304, 2, 4294967295, 4294967295, 12, 32, 8, 1306, 1, 4294967295, 815, 9, 32, 8, 1307, 1, 4294967295, 4294967295, 1, 32, 32, 1308, 1, 4294967295, 4294967295, 1, 32, 8, 1309, 1, 4294967295, 4294967295, 1, 33, 32, 1310, 1, 4294967295, 4294967295, 1, 33, 8, 1311, 1, 4294967295, 4294967295, 1, 33, 8, 1312, 1, 4294967295, 4294967295, 1, 34, 8, 1313, 1, 4294967295, 4294967295, 5, 34, 8, 1314, 1, 823, 4294967295, 8, 34, 8, 1315, 1, 4294967295, 4294967295, 10, 34, 8, 1316, 2, 4294967295, 4294967295, 12, 34, 8, 1318, 1, 4294967295, 826, 9, 34, 8, 1319, 1, 4294967295, 4294967295, 1, 34, 8, 1320, 1, 4294967295, 4294967295, 5, 34, 8, 1321, 1, 829, 4294967295, 8, 34, 8, 1322, 1, 4294967295, 4294967295, 10, 34, 8, 1323, 2, 4294967295, 4294967295, 12, 34, 8, 1325, 1, 4294967295, 832, 9, 34, 8, 1326, 1, 4294967295, 4294967295, 1, 34, 32, 1327, 1, 4294967295, 4294967295, 1, 34, 8, 1328, 1, 4294967295, 4294967295, 3, 34, 8, 1329, 2, 836, 4294967295, 8, 34, 8, 1331, 1, 4294967295, 4294967295, 1, 34, 32, 1332, 1, 4294967295, 4294967295, 1, 34, 32, 1333, 1, 4294967295, 4294967295, 3, 34, 8, 1334, 2, 840, 4294967295, 8, 34, 8, 1336, 1, 4294967295, 4294967295, 1, 34, 8, 1337, 1, 4294967295, 4294967295, 1, 34, 8, 1338, 1, 4294967295, 4294967295, 1, 34, 8, 1339, 1, 4294967295, 4294967295, 1, 34, 8, 1340, 1, 4294967295, 4294967295, 1, 34, 32, 1341, 1, 4294967295, 4294967295, 1, 34, 8, 1342, 1, 4294967295, 4294967295, 1, 34, 32, 1343, 1, 4294967295, 4294967295, 3, 34, 8, 1344, 3, 849, 4294967295, 8, 34, 8, 1347, 1, 4294967295, 4294967295, 1, 35, 8, 1348, 1, 4294967295, 4294967295, 1, 35, 32, 1349, 1, 4294967295, 4294967295, 1, 35, 8, 1350, 1, 4294967295, 4294967295, 1, 36, 8, 1351, 1, 4294967295, 4294967295, 5, 36, 8, 1352, 1, 855, 4294967295, 8, 36, 8, 1353, 1, 4294967295, 4294967295, 10, 36, 8, 1354, 2, 4294967295, 4294967295, 12, 36, 8, 1356, 1, 4294967295, 858, 9, 36, 8, 1357, 1, 4294967295, 4294967295, 1, 36, 8, 1358, 1, 4294967295, 4294967295, 5, 36, 8, 1359, 1, 861, 4294967295, 8, 36, 8, 1360, 1, 4294967295, 4294967295, 10, 36, 8, 1361, 2, 4294967295, 4294967295, 12, 36, 8, 1363, 1, 4294967295, 864, 9, 36, 8, 1364, 1, 4294967295, 4294967295, 1, 36, 32, 1365, 1, 4294967295, 4294967295, 1, 36, 8, 1366, 1, 4294967295, 4294967295, 1, 36, 8, 1367, 1, 4294967295, 4294967295, 1, 36, 8, 1368, 1, 4294967295, 4294967295, 1, 36, 8, 1369, 1, 4294967295, 4294967295, 1, 36, 32, 1370, 1, 4294967295, 4294967295, 1, 36, 8, 1371, 1, 4294967295, 4294967295, 1, 36, 32, 1372, 1, 4294967295, 4294967295, 3, 36, 8, 1373, 3, 874, 4294967295, 8, 36, 8, 1376, 1, 4294967295, 4294967295, 1, 37, 8, 1377, 1, 4294967295, 4294967295, 5, 37, 8, 1378, 1, 877, 4294967295, 8, 37, 8, 1379, 1, 4294967295, 4294967295, 10, 37, 8, 1380, 2, 4294967295, 4294967295, 12, 37, 8, 1382, 1, 4294967295, 880, 9, 37, 8, 1383, 1, 4294967295, 4294967295, 1, 37, 8, 1384, 1, 4294967295, 4294967295, 5, 37, 8, 1385, 1, 883, 4294967295, 8, 37, 8, 1386, 1, 4294967295, 4294967295, 10, 37, 8, 1387, 2, 4294967295, 4294967295, 12, 37, 8, 1389, 1, 4294967295, 886, 9, 37, 8, 1390, 1, 4294967295, 4294967295, 1, 37, 8, 1391, 1, 4294967295, 4294967295, 1, 37, 8, 1392, 1, 4294967295, 4294967295, 3, 37, 8, 1393, 2, 890, 4294967295, 8, 37, 8, 1395, 1, 4294967295, 4294967295, 1, 37, 8, 1396, 1, 4294967295, 4294967295, 1, 37, 8, 1397, 1, 4294967295, 4294967295, 3, 37, 8, 1398, 2, 894, 4294967295, 8, 37, 8, 1400, 1, 4294967295, 4294967295, 1, 37, 8, 1401, 1, 4294967295, 4294967295, 1, 37, 8, 1402, 1, 4294967295, 4294967295, 5, 37, 8, 1403, 1, 898, 4294967295, 8, 37, 8, 1404, 1, 4294967295, 4294967295, 10, 37, 8, 1405, 2, 4294967295, 4294967295, 12, 37, 8, 1407, 1, 4294967295, 901, 9, 37, 8, 1408, 1, 4294967295, 4294967295, 1, 37, 8, 1409, 1, 4294967295, 4294967295, 1, 37, 8, 1410, 1, 4294967295, 4294967295, 1, 37, 32, 1411, 1, 4294967295, 4294967295, 1, 37, 8, 1412, 1, 4294967295, 4294967295, 1, 37, 32, 1413, 1, 4294967295, 4294967295, 3, 37, 8, 1414, 3, 908, 4294967295, 8, 37, 8, 1417, 1, 4294967295, 4294967295, 1, 38, 32, 1418, 1, 4294967295, 4294967295, 1, 38, 8, 1419, 1, 4294967295, 4294967295, 1, 38, 32, 1420, 1, 4294967295, 4294967295, 1, 38, 8, 1421, 1, 4294967295, 4294967295, 5, 38, 8, 1422, 1, 914, 4294967295, 8, 38, 8, 1423, 1, 4294967295, 4294967295, 10, 38, 8, 1424, 2, 4294967295, 4294967295, 12, 38, 8, 1426, 1, 4294967295, 917, 9, 38, 8, 1427, 1, 4294967295, 4294967295, 1, 38, 32, 1428, 1, 4294967295, 4294967295, 1, 38, 8, 1429, 1, 4294967295, 4294967295, 1, 39, 8, 1430, 1, 4294967295, 4294967295, 5, 39, 8, 1431, 1, 922, 4294967295, 8, 39, 8, 1432, 1, 4294967295, 4294967295, 10, 39, 8, 1433, 2, 4294967295, 4294967295, 12, 39, 8, 1435, 1, 4294967295, 925, 9, 39, 8, 1436, 1, 4294967295, 4294967295, 1, 39, 32, 1437, 1, 4294967295, 4294967295, 3, 39, 8, 1438, 2, 928, 4294967295, 8, 39, 8, 1440, 1, 4294967295, 4294967295, 1, 39, 8, 1441, 1, 4294967295, 4294967295, 1, 39, 8, 1442, 1, 4294967295, 4294967295, 1, 40, 32, 1443, 1, 4294967295, 4294967295, 1, 40, 8, 1444, 1, 4294967295, 4294967295, 1, 40, 32, 1445, 1, 4294967295, 4294967295, 1, 40, 8, 1446, 1, 4294967295, 4294967295, 1, 40, 32, 1447, 1, 4294967295, 4294967295, 1, 40, 8, 1448, 1, 4294967295, 4294967295, 5, 40, 8, 1449, 1, 938, 4294967295, 8, 40, 8, 1450, 1, 4294967295, 4294967295, 10, 40, 8, 1451, 2, 4294967295, 4294967295, 12, 40, 8, 1453, 1, 4294967295, 941, 9, 40, 8, 1454, 1, 4294967295, 4294967295, 1, 41, 8, 1455, 1, 4294967295, 4294967295, 1, 41, 8, 1456, 1, 4294967295, 4294967295, 1, 41, 8, 1457, 1, 4294967295, 4294967295, 1, 41, 8, 1458, 1, 4294967295, 4294967295, 1, 41, 8, 1459, 1, 4294967295, 4294967295, 3, 41, 8, 1460, 5, 948, 4294967295, 8, 41, 8, 1465, 1, 4294967295, 4294967295, 1, 42, 32, 1466, 1, 4294967295, 4294967295, 1, 42, 8, 1467, 1, 4294967295, 4294967295, 1, 42, 32, 1468, 1, 4294967295, 4294967295, 1, 42, 8, 1469, 1, 4294967295, 4294967295, 5, 42, 8, 1470, 1, 954, 4294967295, 8, 42, 8, 1471, 1, 4294967295, 4294967295, 10, 42, 8, 1472, 2, 4294967295, 4294967295, 12, 42, 8, 1474, 1, 4294967295, 957, 9, 42, 8, 1475, 1, 4294967295, 4294967295, 1, 43, 8, 1476, 1, 4294967295, 4294967295, 1, 43, 8, 1477, 1, 4294967295, 4294967295, 1, 44, 32, 1478, 1, 4294967295, 4294967295, 1, 44, 32, 1479, 1, 4294967295, 4294967295, 1, 44, 8, 1480, 1, 4294967295, 4294967295, 1, 45, 32, 1481, 1, 4294967295, 4294967295, 1, 45, 32, 1482, 1, 4294967295, 4294967295, 3, 45, 8, 1483, 2, 966, 4294967295, 8, 45, 8, 1485, 1, 4294967295, 4294967295, 1, 45, 32, 1486, 1, 4294967295, 4294967295, 1, 45, 32, 1487, 1, 4294967295, 4294967295, 3, 45, 8, 1488, 2, 970, 4294967295, 8, 45, 8, 1490, 1, 4294967295, 4294967295, 3, 45, 8, 1491, 2, 972, 4294967295, 8, 45, 8, 1493, 1, 4294967295, 4294967295, 1, 46, 32, 1494, 1, 4294967295, 4294967295, 1, 46, 32, 1495, 1, 4294967295, 4294967295, 1, 46, 32, 1496, 1, 4294967295, 4294967295, 1, 46, 8, 1497, 1, 4294967295, 4294967295, 1, 47, 32, 1498, 1, 4294967295, 4294967295, 1, 47, 8, 1499, 1, 4294967295, 4294967295, 1, 48, 8, 1500, 1, 4294967295, 4294967295, 1, 48, 8, 1501, 1, 4294967295, 4294967295, 1, 49, 8, 1502, 1, 4294967295, 4294967295, 5, 49, 8, 1503, 1, 983, 4294967295, 8, 49, 8, 1504, 1, 4294967295, 4294967295, 10, 49, 8, 1505, 2, 4294967295, 4294967295, 12, 49, 8, 1507, 1, 4294967295, 986, 9, 49, 8, 1508, 1, 4294967295, 4294967295, 1, 49, 8, 1509, 1, 4294967295, 4294967295, 5, 49, 8, 1510, 1, 989, 4294967295, 8, 49, 8, 1511, 1, 4294967295, 4294967295, 10, 49, 8, 1512, 2, 4294967295, 4294967295, 12, 49, 8, 1514, 1, 4294967295, 992, 9, 49, 8, 1515, 1, 4294967295, 4294967295, 1, 49, 8, 1516, 1, 4294967295, 4294967295, 1, 49, 8, 1517, 1, 4294967295, 4294967295, 3, 49, 8, 1518, 2, 996, 4294967295, 8, 49, 8, 1520, 1, 4294967295, 4294967295, 1, 49, 32, 1521, 1, 4294967295, 4294967295, 1, 49, 32, 1522, 1, 4294967295, 4294967295, 3, 49, 8, 1523, 2, 1000, 4294967295, 8, 49, 8, 1525, 1, 4294967295, 4294967295, 1, 49, 32, 1526, 1, 4294967295, 4294967295, 1, 49, 32, 1527, 1, 4294967295, 4294967295, 1, 49, 32, 1528, 1, 4294967295, 4294967295, 1, 49, 32, 1529, 1, 4294967295, 4294967295, 1, 49, 32, 1530, 1, 4294967295, 4294967295, 1, 49, 32, 1531, 1, 4294967295, 4294967295, 1, 49, 32, 1532, 1, 4294967295, 4294967295, 1, 49, 32, 1533, 1, 4294967295, 4294967295, 1, 49, 32, 1534, 1, 4294967295, 4294967295, 1, 49, 32, 1535, 1, 4294967295, 4294967295, 1, 49, 8, 1536, 1, 4294967295, 4294967295, 1, 49, 8, 1537, 1, 4294967295, 4294967295, 1, 49, 32, 1538, 1, 4294967295, 4294967295, 1, 49, 32, 1539, 1, 4294967295, 4294967295, 1, 49, 32, 1540, 1, 4294967295, 4294967295, 1, 49, 32, 1541, 1, 4294967295, 4294967295, 1, 49, 32, 1542, 1, 4294967295, 4294967295, 1, 49, 32, 1543, 1, 4294967295, 4294967295, 1, 49, 32, 1544, 1, 4294967295, 4294967295, 1, 49, 32, 1545, 1, 4294967295, 4294967295, 1, 49, 32, 1546, 1, 4294967295, 4294967295, 1, 49, 32, 1547, 1, 4294967295, 4294967295, 1, 49, 32, 1548, 1, 4294967295, 4294967295, 1, 49, 32, 1549, 1, 4294967295, 4294967295, 1, 49, 32, 1550, 1, 4294967295, 4294967295, 1, 49, 32, 1551, 1, 4294967295, 4294967295, 1, 49, 32, 1552, 1, 4294967295, 4294967295, 1, 49, 32, 1553, 1, 4294967295, 4294967295, 1, 49, 32, 1554, 1, 4294967295, 4294967295, 1, 49, 32, 1555, 1, 4294967295, 4294967295, 1, 49, 32, 1556, 1, 4294967295, 4294967295, 1, 49, 32, 1557, 1, 4294967295, 4294967295, 1, 49, 32, 1558, 1, 4294967295, 4294967295, 1, 49, 8, 1559, 1, 4294967295, 4294967295, 1, 49, 8, 1560, 1, 4294967295, 4294967295, 3, 49, 8, 1561, 35, 1037, 4294967295, 8, 49, 8, 1596, 1, 4294967295, 4294967295, 1, 49, 8, 1597, 1, 4294967295, 4294967295, 1, 49, 8, 1598, 1, 4294967295, 4294967295, 1, 49, 8, 1599, 1, 4294967295, 4294967295, 1, 49, 32, 1600, 1, 4294967295, 4294967295, 1, 49, 8, 1601, 1, 4294967295, 4294967295, 1, 49, 32, 1602, 1, 4294967295, 4294967295, 3, 49, 8, 1603, 3, 1045, 4294967295, 8, 49, 8, 1606, 1, 4294967295, 4294967295, 1, 50, 8, 1607, 1, 4294967295, 4294967295, 1, 50, 8, 1608, 1, 4294967295, 4294967295, 3, 50, 8, 1609, 2, 1049, 4294967295, 8, 50, 8, 1611, 1, 4294967295, 4294967295, 1, 51, 8, 1612, 1, 4294967295, 4294967295, 5, 51, 8, 1613, 1, 1052, 4294967295, 8, 51, 8, 1614, 1, 4294967295, 4294967295, 10, 51, 8, 1615, 2, 4294967295, 4294967295, 12, 51, 8, 1617, 1, 4294967295, 1055, 9, 51, 8, 1618, 1, 4294967295, 4294967295, 1, 51, 8, 1619, 1, 4294967295, 4294967295, 5, 51, 8, 1620, 1, 1058, 4294967295, 8, 51, 8, 1621, 1, 4294967295, 4294967295, 10, 51, 8, 1622, 2, 4294967295, 4294967295, 12, 51, 8, 1624, 1, 4294967295, 1061, 9, 51, 8, 1625, 1, 4294967295, 4294967295, 1, 51, 32, 1626, 1, 4294967295, 4294967295, 1, 51, 8, 1627, 1, 4294967295, 4294967295, 1, 51, 32, 1628, 1, 4294967295, 4294967295, 1, 51, 8, 1629, 1, 4294967295, 4294967295, 5, 51, 8, 1630, 1, 1067, 4294967295, 8, 51, 8, 1631, 1, 4294967295, 4294967295, 10, 51, 8, 1632, 2, 4294967295, 4294967295, 12, 51, 8, 1634, 1, 4294967295, 1070, 9, 51, 8, 1635, 1, 4294967295, 4294967295, 1, 51, 8, 1636, 1, 4294967295, 4294967295, 5, 51, 8, 1637, 1, 1073, 4294967295, 8, 51, 8, 1638, 1, 4294967295, 4294967295, 10, 51, 8, 1639, 2, 4294967295, 4294967295, 12, 51, 8, 1641, 1, 4294967295, 1076, 9, 51, 8, 1642, 1, 4294967295, 4294967295, 1, 51, 8, 1643, 1, 4294967295, 4294967295, 5, 51, 8, 1644, 1, 1079, 4294967295, 8, 51, 8, 1645, 1, 4294967295, 4294967295, 10, 51, 8, 1646, 2, 4294967295, 4294967295, 12, 51, 8, 1648, 1, 4294967295, 1082, 9, 51, 8, 1649, 1, 4294967295, 4294967295, 1, 52, 8, 1650, 1, 4294967295, 4294967295, 5, 52, 8, 1651, 1, 1085, 4294967295, 8, 52, 8, 1652, 1, 4294967295, 4294967295, 10, 52, 8, 1653, 2, 4294967295, 4294967295, 12, 52, 8, 1655, 1, 4294967295, 1088, 9, 52, 8, 1656, 1, 4294967295, 4294967295, 1, 52, 8, 1657, 1, 4294967295, 4294967295, 5, 52, 8, 1658, 1, 1091, 4294967295, 8, 52, 8, 1659, 1, 4294967295, 4294967295, 10, 52, 8, 1660, 2, 4294967295, 4294967295, 12, 52, 8, 1662, 1, 4294967295, 1094, 9, 52, 8, 1663, 1, 4294967295, 4294967295, 1, 52, 32, 1664, 1, 4294967295, 4294967295, 1, 52, 8, 1665, 1, 4294967295, 4294967295, 1, 52, 32, 1666, 1, 4294967295, 4294967295, 1, 52, 8, 1667, 1, 4294967295, 4294967295, 5, 52, 8, 1668, 1, 1100, 4294967295, 8, 52, 8, 1669, 1, 4294967295, 4294967295, 10, 52, 8, 1670, 2, 4294967295, 4294967295, 12, 52, 8, 1672, 1, 4294967295, 1103, 9, 52, 8, 1673, 1, 4294967295, 4294967295, 1, 52, 8, 1674, 1, 4294967295, 4294967295, 5, 52, 8, 1675, 1, 1106, 4294967295, 8, 52, 8, 1676, 1, 4294967295, 4294967295, 10, 52, 8, 1677, 2, 4294967295, 4294967295, 12, 52, 8, 1679, 1, 4294967295, 1109, 9, 52, 8, 1680, 1, 4294967295, 4294967295, 1, 52, 8, 1681, 1, 4294967295, 4294967295, 5, 52, 8, 1682, 1, 1112, 4294967295, 8, 52, 8, 1683, 1, 4294967295, 4294967295, 10, 52, 8, 1684, 2, 4294967295, 4294967295, 12, 52, 8, 1686, 1, 4294967295, 1115, 9, 52, 8, 1687, 1, 4294967295, 4294967295, 1, 52, 32, 1688, 1, 4294967295, 4294967295, 1, 52, 32, 1689, 1, 4294967295, 4294967295, 3, 52, 8, 1690, 2, 1119, 4294967295, 8, 52, 8, 1692, 1, 4294967295, 4294967295, 1, 53, 8, 1693, 1, 4294967295, 4294967295, 1, 53, 8, 1694, 1, 4294967295, 4294967295, 1, 53, 8, 1695, 1, 4294967295, 4294967295, 3, 53, 8, 1696, 3, 1124, 4294967295, 8, 53, 8, 1699, 1, 4294967295, 4294967295, 1, 54, 8, 1700, 1, 4294967295, 4294967295, 5, 54, 8, 1701, 1, 1127, 4294967295, 8, 54, 8, 1702, 1, 4294967295, 4294967295, 10, 54, 8, 1703, 2, 4294967295, 4294967295, 12, 54, 8, 1705, 1, 4294967295, 1130, 9, 54, 8, 1706, 1, 4294967295, 4294967295, 1, 54, 8, 1707, 1, 4294967295, 4294967295, 5, 54, 8, 1708, 1, 1133, 4294967295, 8, 54, 8, 1709, 1, 4294967295, 4294967295, 10, 54, 8, 1710, 2, 4294967295, 4294967295, 12, 54, 8, 1712, 1, 4294967295, 1136, 9, 54, 8, 1713, 1, 4294967295, 4294967295, 1, 54, 32, 1714, 1, 4294967295, 4294967295, 1, 54, 8, 1715, 1, 4294967295, 4294967295, 1, 54, 8, 1716, 1, 4294967295, 4294967295, 3, 54, 8, 1717, 2, 1141, 4294967295, 8, 54, 8, 1719, 1, 4294967295, 4294967295, 1, 54, 8, 1720, 1, 4294967295, 4294967295, 1, 54, 8, 1721, 1, 4294967295, 4294967295, 1, 54, 32, 1722, 1, 4294967295, 4294967295, 3, 54, 8, 1723, 2, 1146, 4294967295, 8, 54, 8, 1725, 1, 4294967295, 4294967295, 1, 55, 32, 1726, 1, 4294967295, 4294967295, 1, 55, 8, 1727, 1, 4294967295, 4294967295, 5, 55, 8, 1728, 1, 1150, 4294967295, 8, 55, 8, 1729, 1, 4294967295, 4294967295, 10, 55, 8, 1730, 2, 4294967295, 4294967295, 12, 55, 8, 1732, 1, 4294967295, 1153, 9, 55, 8, 1733, 1, 4294967295, 4294967295, 1, 55, 32, 1734, 1, 4294967295, 4294967295, 1, 55, 8, 1735, 1, 4294967295, 4294967295, 1, 56, 8, 1736, 1, 4294967295, 4294967295, 5, 56, 8, 1737, 1, 1158, 4294967295, 8, 56, 8, 1738, 1, 4294967295, 4294967295, 10, 56, 8, 1739, 2, 4294967295, 4294967295, 12, 56, 8, 1741, 1, 4294967295, 1161, 9, 56, 8, 1742, 1, 4294967295, 4294967295, 1, 56, 8, 1743, 1, 4294967295, 4294967295, 5, 56, 8, 1744, 1, 1164, 4294967295, 8, 56, 8, 1745, 1, 4294967295, 4294967295, 10, 56, 8, 1746, 2, 4294967295, 4294967295, 12, 56, 8, 1748, 1, 4294967295, 1167, 9, 56, 8, 1749, 1, 4294967295, 4294967295, 1, 56, 32, 1750, 1, 4294967295, 4294967295, 1, 56, 8, 1751, 1, 4294967295, 4294967295, 1, 56, 8, 1752, 1, 4294967295, 4294967295, 1, 56, 32, 1753, 1, 4294967295, 4294967295, 1, 56, 8, 1754, 1, 4294967295, 4294967295, 1, 56, 32, 1755, 1, 4294967295, 4294967295, 3, 56, 8, 1756, 3, 1175, 4294967295, 8, 56, 8, 1759, 1, 4294967295, 4294967295, 1, 57, 8, 1760, 1, 4294967295, 4294967295, 5, 57, 8, 1761, 1, 1178, 4294967295, 8, 57, 8, 1762, 1, 4294967295, 4294967295, 10, 57, 8, 1763, 2, 4294967295, 4294967295, 12, 57, 8, 1765, 1, 4294967295, 1181, 9, 57, 8, 1766, 1, 4294967295, 4294967295, 1, 57, 8, 1767, 1, 4294967295, 4294967295, 5, 57, 8, 1768, 1, 1184, 4294967295, 8, 57, 8, 1769, 1, 4294967295, 4294967295, 10, 57, 8, 1770, 2, 4294967295, 4294967295, 12, 57, 8, 1772, 1, 4294967295, 1187, 9, 57, 8, 1773, 1, 4294967295, 4294967295, 1, 57, 8, 1774, 1, 4294967295, 4294967295, 1, 57, 8, 1775, 1, 4294967295, 4294967295, 3, 57, 8, 1776, 2, 1191, 4294967295, 8, 57, 8, 1778, 1, 4294967295, 4294967295, 1, 57, 32, 1779, 1, 4294967295, 4294967295, 1, 57, 8, 1780, 1, 4294967295, 4294967295, 1, 57, 8, 1781, 1, 4294967295, 4294967295, 1, 57, 8, 1782, 1, 4294967295, 4294967295, 1, 57, 32, 1783, 1, 4294967295, 4294967295, 1, 57, 8, 1784, 1, 4294967295, 4294967295, 3, 57, 8, 1785, 2, 1199, 4294967295, 8, 57, 8, 1787, 1, 4294967295, 4294967295, 1, 58, 32, 1788, 1, 4294967295, 4294967295, 1, 58, 8, 1789, 1, 4294967295, 4294967295, 1, 58, 32, 1790, 1, 4294967295, 4294967295, 1, 58, 8, 1791, 1, 4294967295, 4294967295, 5, 58, 8, 1792, 1, 1205, 4294967295, 8, 58, 8, 1793, 1, 4294967295, 4294967295, 10, 58, 8, 1794, 2, 4294967295, 4294967295, 12, 58, 8, 1796, 1, 4294967295, 1208, 9, 58, 8, 1797, 1, 4294967295, 4294967295, 1, 58, 32, 1798, 1, 4294967295, 4294967295, 1, 58, 8, 1799, 1, 4294967295, 4294967295, 1, 59, 8, 1800, 1, 4294967295, 4294967295, 5, 59, 8, 1801, 1, 1213, 4294967295, 8, 59, 8, 1802, 1, 4294967295, 4294967295, 10, 59, 8, 1803, 2, 4294967295, 4294967295, 12, 59, 8, 1805, 1, 4294967295, 1216, 9, 59, 8, 1806, 1, 4294967295, 4294967295, 1, 59, 8, 1807, 1, 4294967295, 4294967295, 5, 59, 8, 1808, 1, 1219, 4294967295, 8, 59, 8, 1809, 1, 4294967295, 4294967295, 10, 59, 8, 1810, 2, 4294967295, 4294967295, 12, 59, 8, 1812, 1, 4294967295, 1222, 9, 59, 8, 1813, 1, 4294967295, 4294967295, 1, 59, 8, 1814, 1, 4294967295, 4294967295, 1, 59, 8, 1815, 1, 4294967295, 4294967295, 3, 59, 8, 1816, 2, 1226, 4294967295, 8, 59, 8, 1818, 1, 4294967295, 4294967295, 1, 59, 8, 1819, 1, 4294967295, 4294967295, 1, 59, 8, 1820, 1, 4294967295, 4294967295, 1, 59, 8, 1821, 1, 4294967295, 4294967295, 1, 59, 32, 1822, 1, 4294967295, 4294967295, 1, 59, 8, 1823, 1, 4294967295, 4294967295, 3, 59, 8, 1824, 2, 1233, 4294967295, 8, 59, 8, 1826, 1, 4294967295, 4294967295, 1, 59, 8, 1827, 1, 4294967295, 4294967295, 1, 59, 8, 1828, 1, 4294967295, 4294967295, 3, 59, 8, 1829, 2, 1237, 4294967295, 8, 59, 8, 1831, 1, 4294967295, 4294967295, 1, 59, 32, 1832, 1, 4294967295, 4294967295, 1, 59, 8, 1833, 1, 4294967295, 4294967295, 3, 59, 8, 1834, 2, 1241, 4294967295, 8, 59, 8, 1836, 1, 4294967295, 4294967295, 1, 60, 8, 1837, 1, 4294967295, 4294967295, 1, 60, 8, 1838, 1, 4294967295, 4294967295, 3, 60, 8, 1839, 2, 1245, 4294967295, 8, 60, 8, 1841, 1, 4294967295, 4294967295, 1, 61, 8, 1842, 1, 4294967295, 4294967295, 5, 61, 8, 1843, 1, 1248, 4294967295, 8, 61, 8, 1844, 1, 4294967295, 4294967295, 10, 61, 8, 1845, 2, 4294967295, 4294967295, 12, 61, 8, 1847, 1, 4294967295, 1251, 9, 61, 8, 1848, 1, 4294967295, 4294967295, 1, 61, 8, 1849, 1, 4294967295, 4294967295, 5, 61, 8, 1850, 1, 1254, 4294967295, 8, 61, 8, 1851, 1, 4294967295, 4294967295, 10, 61, 8, 1852, 2, 4294967295, 4294967295, 12, 61, 8, 1854, 1, 4294967295, 1257, 9, 61, 8, 1855, 1, 4294967295, 4294967295, 1, 61, 32, 1856, 1, 4294967295, 4294967295, 1, 61, 8, 1857, 1, 4294967295, 4294967295, 1, 61, 8, 1858, 1, 4294967295, 4294967295, 3, 61, 8, 1859, 2, 1262, 4294967295, 8, 61, 8, 1861, 1, 4294967295, 4294967295, 1, 61, 32, 1862, 1, 4294967295, 4294967295, 1, 61, 8, 1863, 1, 4294967295, 4294967295, 1, 61, 32, 1864, 1, 4294967295, 4294967295, 1, 61, 8, 1865, 1, 4294967295, 4294967295, 5, 61, 8, 1866, 1, 1268, 4294967295, 8, 61, 8, 1867, 1, 4294967295, 4294967295, 10, 61, 8, 1868, 2, 4294967295, 4294967295, 12, 61, 8, 1870, 1, 4294967295, 1271, 9, 61, 8, 1871, 1, 4294967295, 4294967295, 1, 61, 32, 1872, 1, 4294967295, 4294967295, 3, 61, 8, 1873, 2, 1274, 4294967295, 8, 61, 8, 1875, 1, 4294967295, 4294967295, 3, 61, 8, 1876, 2, 1276, 4294967295, 8, 61, 8, 1878, 1, 4294967295, 4294967295, 1, 61, 32, 1879, 1, 4294967295, 4294967295, 3, 61, 8, 1880, 2, 1279, 4294967295, 8, 61, 8, 1882, 1, 4294967295, 4294967295, 1, 61, 32, 1883, 1, 4294967295, 4294967295, 3, 61, 8, 1884, 2, 1282, 4294967295, 8, 61, 8, 1886, 1, 4294967295, 4294967295, 1, 62, 32, 1887, 1, 4294967295, 4294967295, 1, 62, 8, 1888, 1, 4294967295, 4294967295, 1, 62, 32, 1889, 1, 4294967295, 4294967295, 1, 62, 8, 1890, 1, 4294967295, 4294967295, 5, 62, 8, 1891, 1, 1288, 4294967295, 8, 62, 8, 1892, 1, 4294967295, 4294967295, 10, 62, 8, 1893, 2, 4294967295, 4294967295, 12, 62, 8, 1895, 1, 4294967295, 1291, 9, 62, 8, 1896, 1, 4294967295, 4294967295, 1, 63, 8, 1897, 1, 4294967295, 4294967295, 1, 63, 8, 1898, 1, 4294967295, 4294967295, 3, 63, 8, 1899, 2, 1295, 4294967295, 8, 63, 8, 1901, 1, 4294967295, 4294967295, 1, 64, 8, 1902, 1, 4294967295, 4294967295, 1, 64, 8, 1903, 1, 4294967295, 4294967295, 1, 64, 8, 1904, 1, 4294967295, 4294967295, 1, 65, 8, 1905, 1, 4294967295, 4294967295, 1, 65, 8, 1906, 1, 4294967295, 4294967295, 1, 66, 8, 1907, 1, 4294967295, 4294967295, 5, 66, 8, 1908, 1, 1303, 4294967295, 8, 66, 8, 1909, 1, 4294967295, 4294967295, 10, 66, 8, 1910, 2, 4294967295, 4294967295, 12, 66, 8, 1912, 1, 4294967295, 1306, 9, 66, 8, 1913, 1, 4294967295, 4294967295, 1, 66, 8, 1914, 1, 4294967295, 4294967295, 5, 66, 8, 1915, 1, 1309, 4294967295, 8, 66, 8, 1916, 1, 4294967295, 4294967295, 10, 66, 8, 1917, 2, 4294967295, 4294967295, 12, 66, 8, 1919, 1, 4294967295, 1312, 9, 66, 8, 1920, 1, 4294967295, 4294967295, 1, 66, 8, 1921, 1, 4294967295, 4294967295, 1, 66, 8, 1922, 1, 4294967295, 4294967295, 3, 66, 8, 1923, 2, 1316, 4294967295, 8, 66, 8, 1925, 1, 4294967295, 4294967295, 1, 67, 8, 1926, 1, 4294967295, 4294967295, 1, 67, 8, 1927, 1, 4294967295, 4294967295, 1, 67, 8, 1928, 1, 4294967295, 4294967295, 1, 67, 8, 1929, 1, 4294967295, 4294967295, 1, 67, 8, 1930, 1, 4294967295, 4294967295, 1, 67, 8, 1931, 1, 4294967295, 4294967295, 3, 67, 8, 1932, 6, 1324, 4294967295, 8, 67, 8, 1938, 1, 4294967295, 4294967295, 1, 68, 8, 1939, 1, 4294967295, 4294967295, 5, 68, 8, 1940, 1, 1327, 4294967295, 8, 68, 8, 1941, 1, 4294967295, 4294967295, 10, 68, 8, 1942, 2, 4294967295, 4294967295, 12, 68, 8, 1944, 1, 4294967295, 1330, 9, 68, 8, 1945, 1, 4294967295, 4294967295, 1, 68, 8, 1946, 1, 4294967295, 4294967295, 5, 68, 8, 1947, 1, 1333, 4294967295, 8, 68, 8, 1948, 1, 4294967295, 4294967295, 10, 68, 8, 1949, 2, 4294967295, 4294967295, 12, 68, 8, 1951, 1, 4294967295, 1336, 9, 68, 8, 1952, 1, 4294967295, 4294967295, 1, 68, 32, 1953, 1, 4294967295, 4294967295, 1, 68, 8, 1954, 1, 4294967295, 4294967295, 1, 68, 8, 1955, 1, 4294967295, 4294967295, 3, 68, 8, 1956, 2, 1341, 4294967295, 8, 68, 8, 1958, 1, 4294967295, 4294967295, 1, 68, 8, 1959, 1, 4294967295, 4294967295, 3, 68, 8, 1960, 2, 1344, 4294967295, 8, 68, 8, 1962, 1, 4294967295, 4294967295, 1, 68, 8, 1963, 1, 4294967295, 4294967295, 3, 68, 8, 1964, 2, 1347, 4294967295, 8, 68, 8, 1966, 1, 4294967295, 4294967295, 1, 68, 8, 1967, 1, 4294967295, 4294967295, 5, 68, 8, 1968, 1, 1350, 4294967295, 8, 68, 8, 1969, 1, 4294967295, 4294967295, 10, 68, 8, 1970, 2, 4294967295, 4294967295, 12, 68, 8, 1972, 1, 4294967295, 1353, 9, 68, 8, 1973, 1, 4294967295, 4294967295, 1, 68, 32, 1974, 1, 4294967295, 4294967295, 1, 68, 8, 1975, 1, 4294967295, 4294967295, 5, 68, 8, 1976, 1, 1357, 4294967295, 8, 68, 8, 1977, 1, 4294967295, 4294967295, 10, 68, 8, 1978, 2, 4294967295, 4294967295, 12, 68, 8, 1980, 1, 4294967295, 1360, 9, 68, 8, 1981, 1, 4294967295, 4294967295, 1, 68, 32, 1982, 1, 4294967295, 4294967295, 3, 68, 8, 1983, 2, 1363, 4294967295, 8, 68, 8, 1985, 1, 4294967295, 4294967295, 1, 68, 32, 1986, 1, 4294967295, 4294967295, 3, 68, 8, 1987, 2, 1366, 4294967295, 8, 68, 8, 1989, 1, 4294967295, 4294967295, 1, 69, 8, 1990, 1, 4294967295, 4294967295, 5, 69, 8, 1991, 1, 1369, 4294967295, 8, 69, 8, 1992, 1, 4294967295, 4294967295, 10, 69, 8, 1993, 2, 4294967295, 4294967295, 12, 69, 8, 1995, 1, 4294967295, 1372, 9, 69, 8, 1996, 1, 4294967295, 4294967295, 1, 69, 8, 1997, 1, 4294967295, 4294967295, 5, 69, 8, 1998, 1, 1375, 4294967295, 8, 69, 8, 1999, 1, 4294967295, 4294967295, 10, 69, 8, 2000, 2, 4294967295, 4294967295, 12, 69, 8, 2002, 1, 4294967295, 1378, 9, 69, 8, 2003, 1, 4294967295, 4294967295, 1, 69, 32, 2004, 1, 4294967295, 4294967295, 1, 69, 8, 2005, 1, 4294967295, 4294967295, 3, 69, 8, 2006, 2, 1382, 4294967295, 8, 69, 8, 2008, 1, 4294967295, 4294967295, 1, 69, 8, 2009, 1, 4294967295, 4294967295, 3, 69, 8, 2010, 2, 1385, 4294967295, 8, 69, 8, 2012, 1, 4294967295, 4294967295, 1, 69, 8, 2013, 1, 4294967295, 4294967295, 5, 69, 8, 2014, 1, 1388, 4294967295, 8, 69, 8, 2015, 1, 4294967295, 4294967295, 10, 69, 8, 2016, 2, 4294967295, 4294967295, 12, 69, 8, 2018, 1, 4294967295, 1391, 9, 69, 8, 2019, 1, 4294967295, 4294967295, 1, 69, 32, 2020, 1, 4294967295, 4294967295, 1, 69, 8, 2021, 1, 4294967295, 4294967295, 5, 69, 8, 2022, 1, 1395, 4294967295, 8, 69, 8, 2023, 1, 4294967295, 4294967295, 10, 69, 8, 2024, 2, 4294967295, 4294967295, 12, 69, 8, 2026, 1, 4294967295, 1398, 9, 69, 8, 2027, 1, 4294967295, 4294967295, 1, 69, 32, 2028, 1, 4294967295, 4294967295, 1, 69, 8, 2029, 1, 4294967295, 4294967295, 1, 70, 8, 2030, 1, 4294967295, 4294967295, 5, 70, 8, 2031, 1, 1403, 4294967295, 8, 70, 8, 2032, 1, 4294967295, 4294967295, 10, 70, 8, 2033, 2, 4294967295, 4294967295, 12, 70, 8, 2035, 1, 4294967295, 1406, 9, 70, 8, 2036, 1, 4294967295, 4294967295, 1, 70, 8, 2037, 1, 4294967295, 4294967295, 5, 70, 8, 2038, 1, 1409, 4294967295, 8, 70, 8, 2039, 1, 4294967295, 4294967295, 10, 70, 8, 2040, 2, 4294967295, 4294967295, 12, 70, 8, 2042, 1, 4294967295, 1412, 9, 70, 8, 2043, 1, 4294967295, 4294967295, 1, 70, 32, 2044, 1, 4294967295, 4294967295, 1, 70, 8, 2045, 1, 4294967295, 4294967295, 1, 70, 8, 2046, 1, 4294967295, 4294967295, 3, 70, 8, 2047, 2, 1417, 4294967295, 8, 70, 8, 2049, 1, 4294967295, 4294967295, 1, 70, 8, 2050, 1, 4294967295, 4294967295, 3, 70, 8, 2051, 2, 1420, 4294967295, 8, 70, 8, 2053, 1, 4294967295, 4294967295, 1, 70, 8, 2054, 1, 4294967295, 4294967295, 3, 70, 8, 2055, 2, 1423, 4294967295, 8, 70, 8, 2057, 1, 4294967295, 4294967295, 1, 70, 8, 2058, 1, 4294967295, 4294967295, 5, 70, 8, 2059, 1, 1426, 4294967295, 8, 70, 8, 2060, 1, 4294967295, 4294967295, 10, 70, 8, 2061, 2, 4294967295, 4294967295, 12, 70, 8, 2063, 1, 4294967295, 1429, 9, 70, 8, 2064, 1, 4294967295, 4294967295, 1, 70, 32, 2065, 1, 4294967295, 4294967295, 1, 70, 8, 2066, 1, 4294967295, 4294967295, 5, 70, 8, 2067, 1, 1433, 4294967295, 8, 70, 8, 2068, 1, 4294967295, 4294967295, 10, 70, 8, 2069, 2, 4294967295, 4294967295, 12, 70, 8, 2071, 1, 4294967295, 1436, 9, 70, 8, 2072, 1, 4294967295, 4294967295, 1, 70, 32, 2073, 1, 4294967295, 4294967295, 3, 70, 8, 2074, 2, 1439, 4294967295, 8, 70, 8, 2076, 1, 4294967295, 4294967295, 1, 70, 32, 2077, 1, 4294967295, 4294967295, 3, 70, 8, 2078, 2, 1442, 4294967295, 8, 70, 8, 2080, 1, 4294967295, 4294967295, 1, 71, 8, 2081, 1, 4294967295, 4294967295, 5, 71, 8, 2082, 1, 1445, 4294967295, 8, 71, 8, 2083, 1, 4294967295, 4294967295, 10, 71, 8, 2084, 2, 4294967295, 4294967295, 12, 71, 8, 2086, 1, 4294967295, 1448, 9, 71, 8, 2087, 1, 4294967295, 4294967295, 1, 71, 8, 2088, 1, 4294967295, 4294967295, 5, 71, 8, 2089, 1, 1451, 4294967295, 8, 71, 8, 2090, 1, 4294967295, 4294967295, 10, 71, 8, 2091, 2, 4294967295, 4294967295, 12, 71, 8, 2093, 1, 4294967295, 1454, 9, 71, 8, 2094, 1, 4294967295, 4294967295, 1, 71, 8, 2095, 1, 4294967295, 4294967295, 1, 71, 32, 2096, 1, 4294967295, 4294967295, 3, 71, 8, 2097, 2, 1458, 4294967295, 8, 71, 8, 2099, 1, 4294967295, 4294967295, 1, 71, 8, 2100, 1, 4294967295, 4294967295, 1, 71, 8, 2101, 1, 4294967295, 4294967295, 3, 71, 8, 2102, 2, 1462, 4294967295, 8, 71, 8, 2104, 1, 4294967295, 4294967295, 1, 71, 8, 2105, 1, 4294967295, 4294967295, 3, 71, 8, 2106, 2, 1465, 4294967295, 8, 71, 8, 2108, 1, 4294967295, 4294967295, 1, 71, 8, 2109, 1, 4294967295, 4294967295, 3, 71, 8, 2110, 2, 1468, 4294967295, 8, 71, 8, 2112, 1, 4294967295, 4294967295, 1, 71, 8, 2113, 1, 4294967295, 4294967295, 5, 71, 8, 2114, 1, 1471, 4294967295, 8, 71, 8, 2115, 1, 4294967295, 4294967295, 10, 71, 8, 2116, 2, 4294967295, 4294967295, 12, 71, 8, 2118, 1, 4294967295, 1474, 9, 71, 8, 2119, 1, 4294967295, 4294967295, 1, 71, 32, 2120, 1, 4294967295, 4294967295, 1, 71, 8, 2121, 1, 4294967295, 4294967295, 5, 71, 8, 2122, 1, 1478, 4294967295, 8, 71, 8, 2123, 1, 4294967295, 4294967295, 10, 71, 8, 2124, 2, 4294967295, 4294967295, 12, 71, 8, 2126, 1, 4294967295, 1481, 9, 71, 8, 2127, 1, 4294967295, 4294967295, 1, 71, 32, 2128, 1, 4294967295, 4294967295, 3, 71, 8, 2129, 2, 1484, 4294967295, 8, 71, 8, 2131, 1, 4294967295, 4294967295, 1, 71, 32, 2132, 1, 4294967295, 4294967295, 3, 71, 8, 2133, 2, 1487, 4294967295, 8, 71, 8, 2135, 1, 4294967295, 4294967295, 1, 72, 8, 2136, 1, 4294967295, 4294967295, 5, 72, 8, 2137, 1, 1490, 4294967295, 8, 72, 8, 2138, 1, 4294967295, 4294967295, 10, 72, 8, 2139, 2, 4294967295, 4294967295, 12, 72, 8, 2141, 1, 4294967295, 1493, 9, 72, 8, 2142, 1, 4294967295, 4294967295, 1, 72, 8, 2143, 1, 4294967295, 4294967295, 5, 72, 8, 2144, 1, 1496, 4294967295, 8, 72, 8, 2145, 1, 4294967295, 4294967295, 10, 72, 8, 2146, 2, 4294967295, 4294967295, 12, 72, 8, 2148, 1, 4294967295, 1499, 9, 72, 8, 2149, 1, 4294967295, 4294967295, 1, 72, 32, 2150, 1, 4294967295, 4294967295, 1, 72, 8, 2151, 1, 4294967295, 4294967295, 1, 72, 8, 2152, 1, 4294967295, 4294967295, 3, 72, 8, 2153, 2, 1504, 4294967295, 8, 72, 8, 2155, 1, 4294967295, 4294967295, 1, 72, 8, 2156, 1, 4294967295, 4294967295, 3, 72, 8, 2157, 2, 1507, 4294967295, 8, 72, 8, 2159, 1, 4294967295, 4294967295, 1, 72, 8, 2160, 1, 4294967295, 4294967295, 3, 72, 8, 2161, 2, 1510, 4294967295, 8, 72, 8, 2163, 1, 4294967295, 4294967295, 1, 72, 8, 2164, 1, 4294967295, 4294967295, 5, 72, 8, 2165, 1, 1513, 4294967295, 8, 72, 8, 2166, 1, 4294967295, 4294967295, 10, 72, 8, 2167, 2, 4294967295, 4294967295, 12, 72, 8, 2169, 1, 4294967295, 1516, 9, 72, 8, 2170, 1, 4294967295, 4294967295, 1, 72, 32, 2171, 1, 4294967295, 4294967295, 1, 72, 8, 2172, 1, 4294967295, 4294967295, 5, 72, 8, 2173, 1, 1520, 4294967295, 8, 72, 8, 2174, 1, 4294967295, 4294967295, 10, 72, 8, 2175, 2, 4294967295, 4294967295, 12, 72, 8, 2177, 1, 4294967295, 1523, 9, 72, 8, 2178, 1, 4294967295, 4294967295, 1, 72, 32, 2179, 1, 4294967295, 4294967295, 3, 72, 8, 2180, 2, 1526, 4294967295, 8, 72, 8, 2182, 1, 4294967295, 4294967295, 1, 72, 32, 2183, 1, 4294967295, 4294967295, 3, 72, 8, 2184, 2, 1529, 4294967295, 8, 72, 8, 2186, 1, 4294967295, 4294967295, 1, 73, 8, 2187, 1, 4294967295, 4294967295, 5, 73, 8, 2188, 1, 1532, 4294967295, 8, 73, 8, 2189, 1, 4294967295, 4294967295, 10, 73, 8, 2190, 2, 4294967295, 4294967295, 12, 73, 8, 2192, 1, 4294967295, 1535, 9, 73, 8, 2193, 1, 4294967295, 4294967295, 1, 73, 8, 2194, 1, 4294967295, 4294967295, 5, 73, 8, 2195, 1, 1538, 4294967295, 8, 73, 8, 2196, 1, 4294967295, 4294967295, 10, 73, 8, 2197, 2, 4294967295, 4294967295, 12, 73, 8, 2199, 1, 4294967295, 1541, 9, 73, 8, 2200, 1, 4294967295, 4294967295, 1, 73, 32, 2201, 1, 4294967295, 4294967295, 1, 73, 8, 2202, 1, 4294967295, 4294967295, 1, 73, 8, 2203, 1, 4294967295, 4294967295, 3, 73, 8, 2204, 2, 1546, 4294967295, 8, 73, 8, 2206, 1, 4294967295, 4294967295, 1, 73, 8, 2207, 1, 4294967295, 4294967295, 3, 73, 8, 2208, 2, 1549, 4294967295, 8, 73, 8, 2210, 1, 4294967295, 4294967295, 1, 73, 8, 2211, 1, 4294967295, 4294967295, 3, 73, 8, 2212, 2, 1552, 4294967295, 8, 73, 8, 2214, 1, 4294967295, 4294967295, 1, 73, 8, 2215, 1, 4294967295, 4294967295, 5, 73, 8, 2216, 1, 1555, 4294967295, 8, 73, 8, 2217, 1, 4294967295, 4294967295, 10, 73, 8, 2218, 2, 4294967295, 4294967295, 12, 73, 8, 2220, 1, 4294967295, 1558, 9, 73, 8, 2221, 1, 4294967295, 4294967295, 1, 73, 32, 2222, 1, 4294967295, 4294967295, 1, 73, 8, 2223, 1, 4294967295, 4294967295, 5, 73, 8, 2224, 1, 1562, 4294967295, 8, 73, 8, 2225, 1, 4294967295, 4294967295, 10, 73, 8, 2226, 2, 4294967295, 4294967295, 12, 73, 8, 2228, 1, 4294967295, 1565, 9, 73, 8, 2229, 1, 4294967295, 4294967295, 1, 73, 32, 2230, 1, 4294967295, 4294967295, 3, 73, 8, 2231, 2, 1568, 4294967295, 8, 73, 8, 2233, 1, 4294967295, 4294967295, 1, 73, 32, 2234, 1, 4294967295, 4294967295, 3, 73, 8, 2235, 2, 1571, 4294967295, 8, 73, 8, 2237, 1, 4294967295, 4294967295, 1, 74, 8, 2238, 1, 4294967295, 4294967295, 5, 74, 8, 2239, 1, 1574, 4294967295, 8, 74, 8, 2240, 1, 4294967295, 4294967295, 10, 74, 8, 2241, 2, 4294967295, 4294967295, 12, 74, 8, 2243, 1, 4294967295, 1577, 9, 74, 8, 2244, 1, 4294967295, 4294967295, 1, 74, 8, 2245, 1, 4294967295, 4294967295, 5, 74, 8, 2246, 1, 1580, 4294967295, 8, 74, 8, 2247, 1, 4294967295, 4294967295, 10, 74, 8, 2248, 2, 4294967295, 4294967295, 12, 74, 8, 2250, 1, 4294967295, 1583, 9, 74, 8, 2251, 1, 4294967295, 4294967295, 1, 74, 32, 2252, 1, 4294967295, 4294967295, 1, 74, 8, 2253, 1, 4294967295, 4294967295, 1, 74, 8, 2254, 1, 4294967295, 4294967295, 1, 74, 8, 2255, 1, 4294967295, 4294967295, 3, 74, 8, 2256, 2, 1589, 4294967295, 8, 74, 8, 2258, 1, 4294967295, 4294967295, 1, 74, 8, 2259, 1, 4294967295, 4294967295, 1, 74, 8, 2260, 1, 4294967295, 4294967295, 5, 74, 8, 2261, 1, 1593, 4294967295, 8, 74, 8, 2262, 1, 4294967295, 4294967295, 10, 74, 8, 2263, 2, 4294967295, 4294967295, 12, 74, 8, 2265, 1, 4294967295, 1596, 9, 74, 8, 2266, 1, 4294967295, 4294967295, 1, 74, 32, 2267, 1, 4294967295, 4294967295, 1, 74, 8, 2268, 1, 4294967295, 4294967295, 1, 75, 8, 2269, 1, 4294967295, 4294967295, 5, 75, 8, 2270, 1, 1601, 4294967295, 8, 75, 8, 2271, 1, 4294967295, 4294967295, 10, 75, 8, 2272, 2, 4294967295, 4294967295, 12, 75, 8, 2274, 1, 4294967295, 1604, 9, 75, 8, 2275, 1, 4294967295, 4294967295, 1, 75, 8, 2276, 1, 4294967295, 4294967295, 5, 75, 8, 2277, 1, 1607, 4294967295, 8, 75, 8, 2278, 1, 4294967295, 4294967295, 10, 75, 8, 2279, 2, 4294967295, 4294967295, 12, 75, 8, 2281, 1, 4294967295, 1610, 9, 75, 8, 2282, 1, 4294967295, 4294967295, 1, 75, 8, 2283, 1, 4294967295, 4294967295, 1, 75, 8, 2284, 1, 4294967295, 4294967295, 1, 76, 72, 2285, 1, 4294967295, 4294967295, 1, 76, 8, 2286, 1, 4294967295, 4294967295, 1, 76, 8, 2287, 1, 4294967295, 4294967295, 1, 76, 8, 2288, 1, 4294967295, 4294967295, 1, 76, 8, 2289, 1, 4294967295, 4294967295, 1, 76, 8, 2290, 1, 4294967295, 4294967295, 1, 76, 8, 2291, 1, 4294967295, 4294967295, 3, 76, 8, 2292, 6, 1621, 4294967295, 8, 76, 8, 2298, 1, 4294967295, 4294967295, 1, 76, 72, 2299, 1, 4294967295, 4294967295, 1, 76, 8, 2300, 1, 4294967295, 4294967295, 4, 76, 8, 2301, 1, 1625, 4294967295, 8, 76, 8, 2302, 1, 4294967295, 4294967295, 11, 76, 8, 2303, 2, 4294967295, 4294967295, 12, 76, 8, 2305, 1, 4294967295, 1626, 1, 76, 72, 2306, 1, 4294967295, 4294967295, 1, 76, 32, 2307, 1, 4294967295, 4294967295, 1, 76, 72, 2308, 1, 4294967295, 4294967295, 1, 76, 32, 2309, 1, 4294967295, 4294967295, 5, 76, 8, 2310, 3, 1633, 4294967295, 8, 76, 8, 2313, 1, 4294967295, 4294967295, 10, 76, 10, 2314, 2, 4294967295, 4294967295, 12, 76, 8, 2316, 1, 4294967295, 1636, 9, 76, 8, 2317, 1, 4294967295, 4294967295, 1, 77, 8, 2318, 1, 4294967295, 4294967295, 1, 77, 8, 2319, 1, 4294967295, 4294967295, 4, 77, 8, 2320, 1, 1640, 4294967295, 8, 77, 8, 2321, 1, 4294967295, 4294967295, 11, 77, 8, 2322, 2, 4294967295, 4294967295, 12, 77, 8, 2324, 1, 4294967295, 1641, 1, 78, 32, 2325, 1, 4294967295, 4294967295, 1, 78, 8, 2326, 1, 4294967295, 4294967295, 3, 78, 8, 2327, 2, 1646, 4294967295, 8, 78, 8, 2329, 1, 4294967295, 4294967295, 1, 78, 32, 2330, 1, 4294967295, 4294967295, 1, 78, 8, 2331, 1, 4294967295, 4294967295, 3, 78, 8, 2332, 2, 1650, 4294967295, 8, 78, 8, 2334, 1, 4294967295, 4294967295, 5, 78, 8, 2335, 1, 1652, 4294967295, 8, 78, 8, 2336, 1, 4294967295, 4294967295, 10, 78, 8, 2337, 2, 4294967295, 4294967295, 12, 78, 8, 2339, 1, 4294967295, 1655, 9, 78, 8, 2340, 1, 4294967295, 4294967295, 3, 78, 8, 2341, 2, 1657, 4294967295, 8, 78, 8, 2343, 1, 4294967295, 4294967295, 1, 78, 32, 2344, 1, 4294967295, 4294967295, 1, 78, 8, 2345, 1, 4294967295, 4294967295, 1, 79, 32, 2346, 1, 4294967295, 4294967295, 1, 79, 32, 2347, 1, 4294967295, 4294967295, 1, 79, 8, 2348, 1, 4294967295, 4294967295, 3, 79, 8, 2349, 2, 1664, 4294967295, 8, 79, 8, 2351, 1, 4294967295, 4294967295, 1, 79, 8, 2352, 1, 4294967295, 4294967295, 1, 79, 8, 2353, 1, 4294967295, 4294967295, 1, 80, 32, 2354, 1, 4294967295, 4294967295, 1, 80, 8, 2355, 1, 4294967295, 4294967295, 3, 80, 8, 2356, 2, 1670, 4294967295, 8, 80, 8, 2358, 1, 4294967295, 4294967295, 1, 80, 32, 2359, 1, 4294967295, 4294967295, 1, 80, 8, 2360, 1, 4294967295, 4294967295, 3, 80, 8, 2361, 2, 1674, 4294967295, 8, 80, 8, 2363, 1, 4294967295, 4294967295, 3, 80, 8, 2364, 2, 1676, 4294967295, 8, 80, 8, 2366, 1, 4294967295, 4294967295, 1, 81, 32, 2367, 1, 4294967295, 4294967295, 1, 81, 8, 2368, 1, 4294967295, 4294967295, 1, 81, 32, 2369, 1, 4294967295, 4294967295, 1, 81, 8, 2370, 1, 4294967295, 4294967295, 5, 81, 8, 2371, 1, 1682, 4294967295, 8, 81, 8, 2372, 1, 4294967295, 4294967295, 10, 81, 8, 2373, 2, 4294967295, 4294967295, 12, 81, 8, 2375, 1, 4294967295, 1685, 9, 81, 8, 2376, 1, 4294967295, 4294967295, 1, 81, 32, 2377, 1, 4294967295, 4294967295, 1, 81, 8, 2378, 1, 4294967295, 4294967295, 1, 82, 8, 2379, 1, 4294967295, 4294967295, 1, 82, 8, 2380, 1, 4294967295, 4294967295, 1, 83, 32, 2381, 1, 4294967295, 4294967295, 1, 83, 8, 2382, 1, 4294967295, 4294967295, 1, 83, 32, 2383, 1, 4294967295, 4294967295, 1, 83, 8, 2384, 1, 4294967295, 4294967295, 5, 83, 8, 2385, 1, 1695, 4294967295, 8, 83, 8, 2386, 1, 4294967295, 4294967295, 10, 83, 8, 2387, 2, 4294967295, 4294967295, 12, 83, 8, 2389, 1, 4294967295, 1698, 9, 83, 8, 2390, 1, 4294967295, 4294967295, 1, 83, 32, 2391, 1, 4294967295, 4294967295, 1, 83, 8, 2392, 1, 4294967295, 4294967295, 1, 84, 8, 2393, 1, 4294967295, 4294967295, 5, 84, 8, 2394, 1, 1703, 4294967295, 8, 84, 8, 2395, 1, 4294967295, 4294967295, 10, 84, 8, 2396, 2, 4294967295, 4294967295, 12, 84, 8, 2398, 1, 4294967295, 1706, 9, 84, 8, 2399, 1, 4294967295, 4294967295, 1, 84, 8, 2400, 1, 4294967295, 4294967295, 5, 84, 8, 2401, 1, 1709, 4294967295, 8, 84, 8, 2402, 1, 4294967295, 4294967295, 10, 84, 8, 2403, 2, 4294967295, 4294967295, 12, 84, 8, 2405, 1, 4294967295, 1712, 9, 84, 8, 2406, 1, 4294967295, 4294967295, 1, 84, 8, 2407, 1, 4294967295, 4294967295, 1, 84, 8, 2408, 1, 4294967295, 4294967295, 1, 85, 32, 2409, 1, 4294967295, 4294967295, 1, 85, 8, 2410, 1, 4294967295, 4294967295, 1, 86, 32, 2411, 1, 4294967295, 4294967295, 1, 86, 32, 2412, 1, 4294967295, 4294967295, 3, 86, 8, 2413, 2, 1720, 4294967295, 8, 86, 8, 2415, 1, 4294967295, 4294967295, 1, 86, 8, 2416, 1, 4294967295, 4294967295, 1, 86, 8, 2417, 1, 4294967295, 4294967295, 1, 87, 32, 2418, 1, 4294967295, 4294967295, 1, 87, 8, 2419, 1, 4294967295, 4294967295, 1, 87, 8, 2420, 1, 4294967295, 4294967295, 1, 88, 32, 2421, 1, 4294967295, 4294967295, 1, 88, 8, 2422, 1, 4294967295, 4294967295, 1, 88, 32, 2423, 1, 4294967295, 4294967295, 1, 88, 8, 2424, 1, 4294967295, 4294967295, 4, 88, 8, 2425, 1, 1731, 4294967295, 8, 88, 8, 2426, 1, 4294967295, 4294967295, 11, 88, 8, 2427, 2, 4294967295, 4294967295, 12, 88, 8, 2429, 1, 4294967295, 1732, 1, 88, 32, 2430, 1, 4294967295, 4294967295, 1, 88, 8, 2431, 1, 4294967295, 4294967295, 1, 89, 8, 2432, 1, 4294967295, 4294967295, 1, 89, 8, 2433, 1, 4294967295, 4294967295, 3, 89, 8, 2434, 2, 1739, 4294967295, 8, 89, 8, 2436, 1, 4294967295, 4294967295, 1, 90, 8, 2437, 1, 4294967295, 4294967295, 1, 90, 8, 2438, 1, 4294967295, 4294967295, 1, 90, 8, 2439, 1, 4294967295, 4294967295, 1, 90, 8, 2440, 1, 4294967295, 4294967295, 1, 90, 8, 2441, 1, 4294967295, 4294967295, 1, 90, 8, 2442, 1, 4294967295, 4294967295, 1, 90, 8, 2443, 1, 4294967295, 4294967295, 1, 90, 8, 2444, 1, 4294967295, 4294967295, 1, 90, 8, 2445, 1, 4294967295, 4294967295, 1, 90, 8, 2446, 1, 4294967295, 4294967295, 1, 90, 8, 2447, 1, 4294967295, 4294967295, 1, 90, 8, 2448, 1, 4294967295, 4294967295, 1, 90, 8, 2449, 1, 4294967295, 4294967295, 1, 90, 8, 2450, 1, 4294967295, 4294967295, 1, 90, 8, 2451, 1, 4294967295, 4294967295, 1, 90, 8, 2452, 1, 4294967295, 4294967295, 1, 90, 8, 2453, 1, 4294967295, 4294967295, 1, 90, 8, 2454, 1, 4294967295, 4294967295, 1, 90, 8, 2455, 1, 4294967295, 4294967295, 1, 90, 8, 2456, 1, 4294967295, 4294967295, 1, 90, 8, 2457, 1, 4294967295, 4294967295, 1, 90, 8, 2458, 1, 4294967295, 4294967295, 1, 90, 8, 2459, 1, 4294967295, 4294967295, 1, 90, 8, 2460, 1, 4294967295, 4294967295, 3, 90, 8, 2461, 24, 1765, 4294967295, 8, 90, 8, 2485, 1, 4294967295, 4294967295, 1, 91, 8, 2486, 1, 4294967295, 4294967295, 5, 91, 8, 2487, 1, 1768, 4294967295, 8, 91, 8, 2488, 1, 4294967295, 4294967295, 10, 91, 8, 2489, 2, 4294967295, 4294967295, 12, 91, 8, 2491, 1, 4294967295, 1771, 9, 91, 8, 2492, 1, 4294967295, 4294967295, 1, 91, 32, 2493, 1, 4294967295, 4294967295, 1, 91, 8, 2494, 1, 4294967295, 4294967295, 3, 91, 8, 2495, 2, 1775, 4294967295, 8, 91, 8, 2497, 1, 4294967295, 4294967295, 1, 91, 32, 2498, 1, 4294967295, 4294967295, 1, 91, 8, 2499, 1, 4294967295, 4294967295, 1, 92, 8, 2500, 1, 4294967295, 4294967295, 5, 92, 8, 2501, 1, 1780, 4294967295, 8, 92, 8, 2502, 1, 4294967295, 4294967295, 10, 92, 8, 2503, 2, 4294967295, 4294967295, 12, 92, 8, 2505, 1, 4294967295, 1783, 9, 92, 8, 2506, 1, 4294967295, 4294967295, 1, 92, 32, 2507, 1, 4294967295, 4294967295, 1, 92, 8, 2508, 1, 4294967295, 4294967295, 1, 92, 8, 2509, 1, 4294967295, 4294967295, 1, 93, 8, 2510, 1, 4294967295, 4294967295, 1, 93, 8, 2511, 1, 4294967295, 4294967295, 3, 93, 8, 2512, 2, 1790, 4294967295, 8, 93, 8, 2514, 1, 4294967295, 4294967295, 1, 94, 8, 2515, 1, 4294967295, 4294967295, 5, 94, 8, 2516, 1, 1793, 4294967295, 8, 94, 8, 2517, 1, 4294967295, 4294967295, 10, 94, 8, 2518, 2, 4294967295, 4294967295, 12, 94, 8, 2520, 1, 4294967295, 1796, 9, 94, 8, 2521, 1, 4294967295, 4294967295, 1, 94, 32, 2522, 1, 4294967295, 4294967295, 3, 94, 8, 2523, 2, 1799, 4294967295, 8, 94, 8, 2525, 1, 4294967295, 4294967295, 1, 94, 32, 2526, 1, 4294967295, 4294967295, 1, 94, 32, 2527, 1, 4294967295, 4294967295, 1, 94, 8, 2528, 1, 4294967295, 4294967295, 1, 94, 8, 2529, 1, 4294967295, 4294967295, 1, 94, 32, 2530, 1, 4294967295, 4294967295, 1, 94, 8, 2531, 1, 4294967295, 4294967295, 1, 94, 32, 2532, 1, 4294967295, 4294967295, 1, 94, 8, 2533, 1, 4294967295, 4294967295, 1, 94, 8, 2534, 1, 4294967295, 4294967295, 1, 95, 8, 2535, 1, 4294967295, 4294967295, 5, 95, 8, 2536, 1, 1811, 4294967295, 8, 95, 8, 2537, 1, 4294967295, 4294967295, 10, 95, 8, 2538, 2, 4294967295, 4294967295, 12, 95, 8, 2540, 1, 4294967295, 1814, 9, 95, 8, 2541, 1, 4294967295, 4294967295, 1, 95, 32, 2542, 1, 4294967295, 4294967295, 3, 95, 8, 2543, 2, 1817, 4294967295, 8, 95, 8, 2545, 1, 4294967295, 4294967295, 1, 95, 32, 2546, 1, 4294967295, 4294967295, 1, 95, 32, 2547, 1, 4294967295, 4294967295, 1, 95, 8, 2548, 1, 4294967295, 4294967295, 1, 95, 32, 2549, 1, 4294967295, 4294967295, 1, 95, 8, 2550, 1, 4294967295, 4294967295, 1, 95, 32, 2551, 1, 4294967295, 4294967295, 1, 95, 8, 2552, 1, 4294967295, 4294967295, 1, 95, 8, 2553, 1, 4294967295, 4294967295, 1, 96, 8, 2554, 1, 4294967295, 4294967295, 5, 96, 8, 2555, 1, 1828, 4294967295, 8, 96, 8, 2556, 1, 4294967295, 4294967295, 10, 96, 8, 2557, 2, 4294967295, 4294967295, 12, 96, 8, 2559, 1, 4294967295, 1831, 9, 96, 8, 2560, 1, 4294967295, 4294967295, 1, 96, 32, 2561, 1, 4294967295, 4294967295, 1, 96, 8, 2562, 1, 4294967295, 4294967295, 3, 96, 8, 2563, 2, 1835, 4294967295, 8, 96, 8, 2565, 1, 4294967295, 4294967295, 1, 96, 32, 2566, 1, 4294967295, 4294967295, 1, 96, 8, 2567, 1, 4294967295, 4294967295, 1, 97, 8, 2568, 1, 4294967295, 4294967295, 5, 97, 8, 2569, 1, 1840, 4294967295, 8, 97, 8, 2570, 1, 4294967295, 4294967295, 10, 97, 8, 2571, 2, 4294967295, 4294967295, 12, 97, 8, 2573, 1, 4294967295, 1843, 9, 97, 8, 2574, 1, 4294967295, 4294967295, 1, 97, 32, 2575, 1, 4294967295, 4294967295, 1, 97, 8, 2576, 1, 4294967295, 4294967295, 1, 97, 32, 2577, 1, 4294967295, 4294967295, 1, 97, 32, 2578, 1, 4294967295, 4294967295, 1, 97, 8, 2579, 1, 4294967295, 4294967295, 1, 97, 32, 2580, 1, 4294967295, 4294967295, 1, 97, 32, 2581, 1, 4294967295, 4294967295, 1, 97, 8, 2582, 1, 4294967295, 4294967295, 1, 98, 8, 2583, 1, 4294967295, 4294967295, 5, 98, 8, 2584, 1, 1854, 4294967295, 8, 98, 8, 2585, 1, 4294967295, 4294967295, 10, 98, 8, 2586, 2, 4294967295, 4294967295, 12, 98, 8, 2588, 1, 4294967295, 1857, 9, 98, 8, 2589, 1, 4294967295, 4294967295, 1, 98, 32, 2590, 1, 4294967295, 4294967295, 1, 98, 8, 2591, 1, 4294967295, 4294967295, 1, 99, 8, 2592, 1, 4294967295, 4294967295, 5, 99, 8, 2593, 1, 1862, 4294967295, 8, 99, 8, 2594, 1, 4294967295, 4294967295, 10, 99, 8, 2595, 2, 4294967295, 4294967295, 12, 99, 8, 2597, 1, 4294967295, 1865, 9, 99, 8, 2598, 1, 4294967295, 4294967295, 1, 99, 8, 2599, 1, 4294967295, 4294967295, 1, 99, 32, 2600, 1, 4294967295, 4294967295, 1, 99, 8, 2601, 1, 4294967295, 4294967295, 1, 100, 8, 2602, 1, 4294967295, 4294967295, 5, 100, 8, 2603, 1, 1871, 4294967295, 8, 100, 8, 2604, 1, 4294967295, 4294967295, 10, 100, 8, 2605, 2, 4294967295, 4294967295, 12, 100, 8, 2607, 1, 4294967295, 1874, 9, 100, 8, 2608, 1, 4294967295, 4294967295, 1, 100, 32, 2609, 1, 4294967295, 4294967295, 1, 100, 32, 2610, 1, 4294967295, 4294967295, 1, 100, 8, 2611, 1, 4294967295, 4294967295, 1, 100, 32, 2612, 1, 4294967295, 4294967295, 1, 100, 8, 2613, 1, 4294967295, 4294967295, 1, 100, 8, 2614, 1, 4294967295, 4294967295, 1, 101, 8, 2615, 1, 4294967295, 4294967295, 5, 101, 8, 2616, 1, 1883, 4294967295, 8, 101, 8, 2617, 1, 4294967295, 4294967295, 10, 101, 8, 2618, 2, 4294967295, 4294967295, 12, 101, 8, 2620, 1, 4294967295, 1886, 9, 101, 8, 2621, 1, 4294967295, 4294967295, 1, 101, 32, 2622, 1, 4294967295, 4294967295, 1, 101, 32, 2623, 1, 4294967295, 4294967295, 1, 101, 8, 2624, 1, 4294967295, 4294967295, 3, 101, 8, 2625, 2, 1891, 4294967295, 8, 101, 8, 2627, 1, 4294967295, 4294967295, 1, 101, 8, 2628, 1, 4294967295, 4294967295, 1, 101, 32, 2629, 1, 4294967295, 4294967295, 1, 101, 8, 2630, 1, 4294967295, 4294967295, 5, 101, 8, 2631, 1, 1896, 4294967295, 8, 101, 8, 2632, 1, 4294967295, 4294967295, 10, 101, 8, 2633, 2, 4294967295, 4294967295, 12, 101, 8, 2635, 1, 4294967295, 1899, 9, 101, 8, 2636, 1, 4294967295, 4294967295, 3, 101, 8, 2637, 2, 1901, 4294967295, 8, 101, 8, 2639, 1, 4294967295, 4294967295, 3, 101, 8, 2640, 2, 1903, 4294967295, 8, 101, 8, 2642, 1, 4294967295, 4294967295, 1, 101, 32, 2643, 1, 4294967295, 4294967295, 1, 101, 8, 2644, 1, 4294967295, 4294967295, 3, 101, 8, 2645, 2, 1907, 4294967295, 8, 101, 8, 2647, 1, 4294967295, 4294967295, 1, 101, 32, 2648, 1, 4294967295, 4294967295, 1, 101, 8, 2649, 1, 4294967295, 4294967295, 1, 101, 32, 2650, 1, 4294967295, 4294967295, 1, 101, 8, 2651, 1, 4294967295, 4294967295, 5, 101, 8, 2652, 1, 1913, 4294967295, 8, 101, 8, 2653, 1, 4294967295, 4294967295, 10, 101, 8, 2654, 2, 4294967295, 4294967295, 12, 101, 8, 2656, 1, 4294967295, 1916, 9, 101, 8, 2657, 1, 4294967295, 4294967295, 3, 101, 8, 2658, 2, 1918, 4294967295, 8, 101, 8, 2660, 1, 4294967295, 4294967295, 1, 101, 32, 2661, 1, 4294967295, 4294967295, 1, 101, 8, 2662, 1, 4294967295, 4294967295, 1, 101, 8, 2663, 1, 4294967295, 4294967295, 1, 102, 8, 2664, 1, 4294967295, 4294967295, 5, 102, 8, 2665, 1, 1924, 4294967295, 8, 102, 8, 2666, 1, 4294967295, 4294967295, 10, 102, 8, 2667, 2, 4294967295, 4294967295, 12, 102, 8, 2669, 1, 4294967295, 1927, 9, 102, 8, 2670, 1, 4294967295, 4294967295, 1, 102, 32, 2671, 1, 4294967295, 4294967295, 1, 102, 32, 2672, 1, 4294967295, 4294967295, 3, 102, 8, 2673, 2, 1931, 4294967295, 8, 102, 8, 2675, 1, 4294967295, 4294967295, 1, 102, 8, 2676, 1, 4294967295, 4294967295, 3, 102, 8, 2677, 2, 1934, 4294967295, 8, 102, 8, 2679, 1, 4294967295, 4294967295, 1, 102, 32, 2680, 1, 4294967295, 4294967295, 1, 102, 8, 2681, 1, 4294967295, 4294967295, 1, 103, 8, 2682, 1, 4294967295, 4294967295, 5, 103, 8, 2683, 1, 1939, 4294967295, 8, 103, 8, 2684, 1, 4294967295, 4294967295, 10, 103, 8, 2685, 2, 4294967295, 4294967295, 12, 103, 8, 2687, 1, 4294967295, 1942, 9, 103, 8, 2688, 1, 4294967295, 4294967295, 1, 103, 32, 2689, 1, 4294967295, 4294967295, 1, 103, 32, 2690, 1, 4294967295, 4294967295, 1, 103, 8, 2691, 1, 4294967295, 4294967295, 1, 103, 32, 2692, 1, 4294967295, 4294967295, 1, 103, 8, 2693, 1, 4294967295, 4294967295, 1, 103, 8, 2694, 1, 4294967295, 4294967295, 3, 103, 8, 2695, 2, 1950, 4294967295, 8, 103, 8, 2697, 1, 4294967295, 4294967295, 1, 104, 32, 2698, 1, 4294967295, 4294967295, 1, 104, 8, 2699, 1, 4294967295, 4294967295, 1, 104, 8, 2700, 1, 4294967295, 4294967295, 1, 105, 8, 2701, 1, 4294967295, 4294967295, 5, 105, 8, 2702, 1, 1956, 4294967295, 8, 105, 8, 2703, 1, 4294967295, 4294967295, 10, 105, 8, 2704, 2, 4294967295, 4294967295, 12, 105, 8, 2706, 1, 4294967295, 1959, 9, 105, 8, 2707, 1, 4294967295, 4294967295, 1, 105, 8, 2708, 1, 4294967295, 4294967295, 1, 105, 32, 2709, 1, 4294967295, 4294967295, 1, 105, 8, 2710, 1, 4294967295, 4294967295, 1, 105, 8, 2711, 1, 4294967295, 4294967295, 1, 106, 8, 2712, 1, 4294967295, 4294967295, 5, 106, 8, 2713, 1, 1966, 4294967295, 8, 106, 8, 2714, 1, 4294967295, 4294967295, 10, 106, 8, 2715, 2, 4294967295, 4294967295, 12, 106, 8, 2717, 1, 4294967295, 1969, 9, 106, 8, 2718, 1, 4294967295, 4294967295, 1, 106, 32, 2719, 1, 4294967295, 4294967295, 3, 106, 8, 2720, 2, 1972, 4294967295, 8, 106, 8, 2722, 1, 4294967295, 4294967295, 1, 106, 32, 2723, 1, 4294967295, 4294967295, 3, 106, 8, 2724, 2, 1975, 4294967295, 8, 106, 8, 2726, 1, 4294967295, 4294967295, 1, 106, 8, 2727, 1, 4294967295, 4294967295, 5, 106, 8, 2728, 1, 1978, 4294967295, 8, 106, 8, 2729, 1, 4294967295, 4294967295, 10, 106, 8, 2730, 2, 4294967295, 4294967295, 12, 106, 8, 2732, 1, 4294967295, 1981, 9, 106, 8, 2733, 1, 4294967295, 4294967295, 1, 106, 8, 2734, 1, 4294967295, 4294967295, 1, 106, 32, 2735, 1, 4294967295, 4294967295, 1, 106, 8, 2736, 1, 4294967295, 4294967295, 1, 107, 8, 2737, 1, 4294967295, 4294967295, 5, 107, 8, 2738, 1, 1987, 4294967295, 8, 107, 8, 2739, 1, 4294967295, 4294967295, 10, 107, 8, 2740, 2, 4294967295, 4294967295, 12, 107, 8, 2742, 1, 4294967295, 1990, 9, 107, 8, 2743, 1, 4294967295, 4294967295, 1, 107, 8, 2744, 1, 4294967295, 4294967295, 5, 107, 8, 2745, 1, 1993, 4294967295, 8, 107, 8, 2746, 1, 4294967295, 4294967295, 10, 107, 8, 2747, 2, 4294967295, 4294967295, 12, 107, 8, 2749, 1, 4294967295, 1996, 9, 107, 8, 2750, 1, 4294967295, 4294967295, 1, 107, 8, 2751, 1, 4294967295, 4294967295, 1, 107, 8, 2752, 1, 4294967295, 4294967295, 1, 107, 8, 2753, 1, 4294967295, 4294967295, 3, 107, 8, 2754, 2, 2001, 4294967295, 8, 107, 8, 2756, 1, 4294967295, 4294967295, 1, 107, 8, 2757, 1, 4294967295, 4294967295, 1, 107, 8, 2758, 1, 4294967295, 4294967295, 5, 107, 8, 2759, 1, 2005, 4294967295, 8, 107, 8, 2760, 1, 4294967295, 4294967295, 10, 107, 8, 2761, 2, 4294967295, 4294967295, 12, 107, 8, 2763, 1, 4294967295, 2008, 9, 107, 8, 2764, 1, 4294967295, 4294967295, 1, 107, 8, 2765, 1, 4294967295, 4294967295, 1, 107, 8, 2766, 1, 4294967295, 4294967295, 1, 107, 32, 2767, 1, 4294967295, 4294967295, 1, 107, 8, 2768, 1, 4294967295, 4294967295, 3, 107, 8, 2769, 2, 2014, 4294967295, 8, 107, 8, 2771, 1, 4294967295, 4294967295, 1, 108, 8, 2772, 1, 4294967295, 4294967295, 5, 108, 8, 2773, 1, 2017, 4294967295, 8, 108, 8, 2774, 1, 4294967295, 4294967295, 10, 108, 8, 2775, 2, 4294967295, 4294967295, 12, 108, 8, 2777, 1, 4294967295, 2020, 9, 108, 8, 2778, 1, 4294967295, 4294967295, 1, 108, 32, 2779, 1, 4294967295, 4294967295, 1, 108, 32, 2780, 1, 4294967295, 4294967295, 1, 108, 8, 2781, 1, 4294967295, 4294967295, 1, 108, 32, 2782, 1, 4294967295, 4294967295, 1, 108, 8, 2783, 1, 4294967295, 4294967295, 1, 108, 8, 2784, 1, 4294967295, 4294967295, 1, 109, 8, 2785, 1, 4294967295, 4294967295, 5, 109, 8, 2786, 1, 2029, 4294967295, 8, 109, 8, 2787, 1, 4294967295, 4294967295, 10, 109, 8, 2788, 2, 4294967295, 4294967295, 12, 109, 8, 2790, 1, 4294967295, 2032, 9, 109, 8, 2791, 1, 4294967295, 4294967295, 1, 109, 32, 2792, 1, 4294967295, 4294967295, 1, 109, 8, 2793, 1, 4294967295, 4294967295, 3, 109, 8, 2794, 2, 2036, 4294967295, 8, 109, 8, 2796, 1, 4294967295, 4294967295, 1, 109, 32, 2797, 1, 4294967295, 4294967295, 1, 109, 8, 2798, 1, 4294967295, 4294967295, 1, 110, 8, 2799, 1, 4294967295, 4294967295, 5, 110, 8, 2800, 1, 2041, 4294967295, 8, 110, 8, 2801, 1, 4294967295, 4294967295, 10, 110, 8, 2802, 2, 4294967295, 4294967295, 12, 110, 8, 2804, 1, 4294967295, 2044, 9, 110, 8, 2805, 1, 4294967295, 4294967295, 1, 110, 32, 2806, 1, 4294967295, 4294967295, 1, 110, 32, 2807, 1, 4294967295, 4294967295, 1, 110, 8, 2808, 1, 4294967295, 4294967295, 1, 110, 32, 2809, 1, 4294967295, 4294967295, 1, 110, 32, 2810, 1, 4294967295, 4294967295, 1, 110, 8, 2811, 1, 4294967295, 4294967295, 5, 110, 8, 2812, 1, 2052, 4294967295, 8, 110, 8, 2813, 1, 4294967295, 4294967295, 10, 110, 8, 2814, 2, 4294967295, 4294967295, 12, 110, 8, 2816, 1, 4294967295, 2055, 9, 110, 8, 2817, 1, 4294967295, 4294967295, 1, 110, 32, 2818, 1, 4294967295, 4294967295, 1, 110, 8, 2819, 1, 4294967295, 4294967295, 1, 111, 8, 2820, 1, 4294967295, 4294967295, 4, 111, 8, 2821, 1, 2060, 4294967295, 8, 111, 8, 2822, 1, 4294967295, 4294967295, 11, 111, 8, 2823, 2, 4294967295, 4294967295, 12, 111, 8, 2825, 1, 4294967295, 2061, 1, 111, 8, 2826, 1, 4294967295, 4294967295, 4, 111, 8, 2827, 1, 2065, 4294967295, 8, 111, 8, 2828, 1, 4294967295, 4294967295, 11, 111, 8, 2829, 2, 4294967295, 4294967295, 12, 111, 8, 2831, 1, 4294967295, 2066, 1, 112, 8, 2832, 1, 4294967295, 4294967295, 1, 112, 8, 2833, 1, 4294967295, 4294967295, 1, 112, 8, 2834, 1, 4294967295, 4294967295, 3, 112, 8, 2835, 3, 2072, 4294967295, 8, 112, 8, 2838, 1, 4294967295, 4294967295, 1, 113, 32, 2839, 1, 4294967295, 4294967295, 1, 113, 8, 2840, 1, 4294967295, 4294967295, 1, 113, 8, 2841, 1, 4294967295, 4294967295, 3, 113, 8, 2842, 2, 2077, 4294967295, 8, 113, 8, 2844, 1, 4294967295, 4294967295, 1, 113, 32, 2845, 1, 4294967295, 4294967295, 1, 113, 8, 2846, 1, 4294967295, 4294967295, 1, 114, 72, 2847, 1, 4294967295, 4294967295, 1, 114, 8, 2848, 1, 4294967295, 4294967295, 1, 114, 8, 2849, 1, 4294967295, 4294967295, 1, 114, 8, 2850, 1, 4294967295, 4294967295, 1, 114, 8, 2851, 1, 4294967295, 4294967295, 1, 114, 8, 2852, 1, 4294967295, 4294967295, 1, 114, 8, 2853, 1, 4294967295, 4294967295, 1, 114, 8, 2854, 1, 4294967295, 4294967295, 1, 114, 8, 2855, 1, 4294967295, 4294967295, 1, 114, 8, 2856, 1, 4294967295, 4294967295, 1, 114, 8, 2857, 1, 4294967295, 4294967295, 1, 114, 8, 2858, 1, 4294967295, 4294967295, 3, 114, 8, 2859, 11, 2093, 4294967295, 8, 114, 8, 2870, 1, 4294967295, 4294967295, 1, 114, 72, 2871, 1, 4294967295, 4294967295, 1, 114, 32, 2872, 1, 4294967295, 4294967295, 1, 114, 8, 2873, 1, 4294967295, 4294967295, 5, 114, 8, 2874, 1, 2098, 4294967295, 8, 114, 8, 2875, 1, 4294967295, 4294967295, 10, 114, 10, 2876, 2, 4294967295, 4294967295, 12, 114, 8, 2878, 1, 4294967295, 2101, 9, 114, 8, 2879, 1, 4294967295, 4294967295, 1, 115, 8, 2880, 1, 4294967295, 4294967295, 1, 115, 8, 2881, 1, 4294967295, 4294967295, 1, 116, 8, 2882, 1, 4294967295, 4294967295, 1, 116, 8, 2883, 1, 4294967295, 4294967295, 1, 116, 8, 2884, 1, 4294967295, 4294967295, 1, 117, 8, 2885, 1, 4294967295, 4294967295, 1, 117, 8, 2886, 1, 4294967295, 4294967295, 1, 117, 8, 2887, 1, 4294967295, 4294967295, 3, 117, 8, 2888, 3, 2111, 4294967295, 8, 117, 8, 2891, 1, 4294967295, 4294967295, 1, 118, 32, 2892, 1, 4294967295, 4294967295, 1, 118, 8, 2893, 1, 4294967295, 4294967295, 1, 119, 32, 2894, 1, 4294967295, 4294967295, 1, 119, 8, 2895, 1, 4294967295, 4294967295, 1, 119, 32, 2896, 1, 4294967295, 4294967295, 1, 119, 8, 2897, 1, 4294967295, 4294967295, 5, 119, 8, 2898, 1, 2119, 4294967295, 8, 119, 8, 2899, 1, 4294967295, 4294967295, 10, 119, 8, 2900, 2, 4294967295, 4294967295, 12, 119, 8, 2902, 1, 4294967295, 2122, 9, 119, 8, 2903, 1, 4294967295, 4294967295, 3, 119, 8, 2904, 2, 2124, 4294967295, 8, 119, 8, 2906, 1, 4294967295, 4294967295, 1, 119, 32, 2907, 1, 4294967295, 4294967295, 1, 119, 8, 2908, 1, 4294967295, 4294967295, 1, 120, 32, 2909, 1, 4294967295, 4294967295, 1, 120, 8, 2910, 1, 4294967295, 4294967295, 1, 121, 32, 2911, 1, 4294967295, 4294967295, 1, 121, 8, 2912, 1, 4294967295, 4294967295, 1, 122, 32, 2913, 1, 4294967295, 4294967295, 1, 122, 8, 2914, 1, 4294967295, 4294967295, 1, 122, 32, 2915, 1, 4294967295, 4294967295, 1, 122, 8, 2916, 1, 4294967295, 4294967295, 5, 122, 8, 2917, 1, 2136, 4294967295, 8, 122, 8, 2918, 1, 4294967295, 4294967295, 10, 122, 8, 2919, 2, 4294967295, 4294967295, 12, 122, 8, 2921, 1, 4294967295, 2139, 9, 122, 8, 2922, 1, 4294967295, 4294967295, 1, 122, 32, 2923, 1, 4294967295, 4294967295, 3, 122, 8, 2924, 2, 2142, 4294967295, 8, 122, 8, 2926, 1, 4294967295, 4294967295, 3, 122, 8, 2927, 2, 2144, 4294967295, 8, 122, 8, 2929, 1, 4294967295, 4294967295, 1, 122, 32, 2930, 1, 4294967295, 4294967295, 1, 122, 8, 2931, 1, 4294967295, 4294967295, 3, 122, 8, 2932, 2, 2148, 4294967295, 8, 122, 8, 2934, 1, 4294967295, 4294967295, 1, 123, 32, 2935, 1, 4294967295, 4294967295, 1, 123, 8, 2936, 1, 4294967295, 4294967295, 1, 123, 32, 2937, 1, 4294967295, 4294967295, 1, 123, 8, 2938, 1, 4294967295, 4294967295, 1, 124, 8, 2939, 1, 4294967295, 4294967295, 3, 124, 8, 2940, 2, 2155, 4294967295, 8, 124, 8, 2942, 1, 4294967295, 4294967295, 1, 124, 8, 2943, 1, 4294967295, 4294967295, 3, 124, 8, 2944, 2, 2158, 4294967295, 8, 124, 8, 2946, 1, 4294967295, 4294967295, 1, 124, 8, 2947, 1, 4294967295, 4294967295, 3, 124, 8, 2948, 2, 2161, 4294967295, 8, 124, 8, 2950, 1, 4294967295, 4294967295, 1, 124, 8, 2951, 1, 4294967295, 4294967295, 3, 124, 8, 2952, 2, 2164, 4294967295, 8, 124, 8, 2954, 1, 4294967295, 4294967295, 1, 125, 32, 2955, 1, 4294967295, 4294967295, 1, 125, 8, 2956, 1, 4294967295, 4294967295, 1, 125, 32, 2957, 1, 4294967295, 4294967295, 1, 125, 8, 2958, 1, 4294967295, 4294967295, 5, 125, 8, 2959, 1, 2170, 4294967295, 8, 125, 8, 2960, 1, 4294967295, 4294967295, 10, 125, 8, 2961, 2, 4294967295, 4294967295, 12, 125, 8, 2963, 1, 4294967295, 2173, 9, 125, 8, 2964, 1, 4294967295, 4294967295, 3, 125, 8, 2965, 2, 2175, 4294967295, 8, 125, 8, 2967, 1, 4294967295, 4294967295, 1, 125, 32, 2968, 1, 4294967295, 4294967295, 1, 125, 8, 2969, 1, 4294967295, 4294967295, 1, 126, 8, 2970, 1, 4294967295, 4294967295, 3, 126, 8, 2971, 2, 2180, 4294967295, 8, 126, 8, 2973, 1, 4294967295, 4294967295, 1, 126, 8, 2974, 1, 4294967295, 4294967295, 1, 126, 8, 2975, 1, 4294967295, 4294967295, 1, 127, 8, 2976, 1, 4294967295, 4294967295, 1, 127, 8, 2977, 1, 4294967295, 4294967295, 3, 127, 8, 2978, 2, 2186, 4294967295, 8, 127, 8, 2980, 1, 4294967295, 4294967295, 1, 128, 8, 2981, 1, 4294967295, 4294967295, 1, 128, 32, 2982, 1, 4294967295, 4294967295, 1, 128, 8, 2983, 1, 4294967295, 4294967295, 1, 129, 32, 2984, 1, 4294967295, 4294967295, 1, 129, 8, 2985, 1, 4294967295, 4294967295, 1, 129, 32, 2986, 1, 4294967295, 4294967295, 1, 129, 8, 2987, 1, 4294967295, 4294967295, 5, 129, 8, 2988, 1, 2195, 4294967295, 8, 129, 8, 2989, 1, 4294967295, 4294967295, 10, 129, 8, 2990, 2, 4294967295, 4294967295, 12, 129, 8, 2992, 1, 4294967295, 2198, 9, 129, 8, 2993, 1, 4294967295, 4294967295, 1, 129, 32, 2994, 1, 4294967295, 4294967295, 3, 129, 8, 2995, 2, 2201, 4294967295, 8, 129, 8, 2997, 1, 4294967295, 4294967295, 3, 129, 8, 2998, 2, 2203, 4294967295, 8, 129, 8, 3000, 1, 4294967295, 4294967295, 1, 129, 32, 3001, 1, 4294967295, 4294967295, 1, 129, 8, 3002, 1, 4294967295, 4294967295, 1, 130, 32, 3003, 1, 4294967295, 4294967295, 1, 130, 8, 3004, 1, 4294967295, 4294967295, 1, 130, 32, 3005, 1, 4294967295, 4294967295, 1, 130, 8, 3006, 1, 4294967295, 4294967295, 1, 130, 32, 3007, 1, 4294967295, 4294967295, 1, 130, 8, 3008, 1, 4294967295, 4294967295, 1, 130, 32, 3009, 1, 4294967295, 4294967295, 1, 130, 8, 3010, 1, 4294967295, 4294967295, 1, 130, 32, 3011, 1, 4294967295, 4294967295, 1, 130, 8, 3012, 1, 4294967295, 4294967295, 1, 130, 32, 3013, 1, 4294967295, 4294967295, 1, 130, 8, 3014, 1, 4294967295, 4294967295, 3, 130, 8, 3015, 6, 2219, 4294967295, 8, 130, 8, 3021, 1, 4294967295, 4294967295, 1, 131, 32, 3022, 1, 4294967295, 4294967295, 1, 131, 8, 3023, 1, 4294967295, 4294967295, 3, 131, 8, 3024, 2, 2223, 4294967295, 8, 131, 8, 3026, 1, 4294967295, 4294967295, 1, 132, 8, 3027, 1, 4294967295, 4294967295, 1, 132, 8, 3028, 1, 4294967295, 4294967295, 1, 133, 32, 3029, 1, 4294967295, 4294967295, 1, 133, 8, 3030, 1, 4294967295, 4294967295, 1, 133, 8, 3031, 1, 4294967295, 4294967295, 1, 134, 32, 3032, 1, 4294967295, 4294967295, 1, 134, 8, 3033, 1, 4294967295, 4294967295, 1, 134, 8, 3034, 1, 4294967295, 4294967295, 1, 135, 32, 3035, 1, 4294967295, 4294967295, 1, 135, 8, 3036, 1, 4294967295, 4294967295, 1, 135, 8, 3037, 1, 4294967295, 4294967295, 1, 136, 32, 3038, 1, 4294967295, 4294967295, 1, 136, 8, 3039, 1, 4294967295, 4294967295, 1, 136, 32, 3040, 1, 4294967295, 4294967295, 1, 136, 8, 3041, 1, 4294967295, 4294967295, 1, 137, 32, 3042, 1, 4294967295, 4294967295, 1, 137, 32, 3043, 1, 4294967295, 4294967295, 1, 137, 8, 3044, 1, 4294967295, 4294967295, 1, 138, 8, 3045, 1, 4294967295, 4294967295, 5, 138, 8, 3046, 1, 2244, 4294967295, 8, 138, 8, 3047, 1, 4294967295, 4294967295, 10, 138, 8, 3048, 2, 4294967295, 4294967295, 12, 138, 8, 3050, 1, 4294967295, 2247, 9, 138, 8, 3051, 1, 4294967295, 4294967295, 1, 138, 32, 3052, 1, 4294967295, 4294967295, 1, 138, 8, 3053, 1, 4294967295, 4294967295, 3, 138, 8, 3054, 2, 2251, 4294967295, 8, 138, 8, 3056, 1, 4294967295, 4294967295, 1, 138, 32, 3057, 1, 4294967295, 4294967295, 1, 138, 8, 3058, 1, 4294967295, 4294967295, 1, 139, 8, 3059, 1, 4294967295, 4294967295, 5, 139, 8, 3060, 1, 2256, 4294967295, 8, 139, 8, 3061, 1, 4294967295, 4294967295, 10, 139, 8, 3062, 2, 4294967295, 4294967295, 12, 139, 8, 3064, 1, 4294967295, 2259, 9, 139, 8, 3065, 1, 4294967295, 4294967295, 1, 139, 32, 3066, 1, 4294967295, 4294967295, 1, 139, 8, 3067, 1, 4294967295, 4294967295, 1, 139, 8, 3068, 1, 4294967295, 4294967295, 5, 139, 8, 3069, 1, 2264, 4294967295, 8, 139, 8, 3070, 1, 4294967295, 4294967295, 10, 139, 8, 3071, 2, 4294967295, 4294967295, 12, 139, 8, 3073, 1, 4294967295, 2267, 9, 139, 8, 3074, 1, 4294967295, 4294967295, 1, 139, 8, 3075, 1, 4294967295, 4294967295, 3, 139, 8, 3076, 2, 2270, 4294967295, 8, 139, 8, 3078, 1, 4294967295, 4294967295, 1, 140, 32, 3079, 1, 4294967295, 4294967295, 1, 140, 8, 3080, 1, 4294967295, 4294967295, 3, 140, 8, 3081, 2, 2274, 4294967295, 8, 140, 8, 3083, 1, 4294967295, 4294967295, 1, 140, 8, 3084, 1, 4294967295, 4294967295, 3, 140, 8, 3085, 2, 2277, 4294967295, 8, 140, 8, 3087, 1, 4294967295, 4294967295, 1, 140, 8, 3088, 1, 4294967295, 4294967295, 1, 140, 8, 3089, 1, 4294967295, 4294967295, 1, 141, 32, 3090, 1, 4294967295, 4294967295, 1, 141, 8, 3091, 1, 4294967295, 4294967295, 1, 141, 8, 3092, 1, 4294967295, 4294967295, 3, 141, 8, 3093, 2, 2284, 4294967295, 8, 141, 8, 3095, 1, 4294967295, 4294967295, 1, 141, 32, 3096, 1, 4294967295, 4294967295, 1, 141, 8, 3097, 1, 4294967295, 4294967295, 1, 142, 32, 3098, 1, 4294967295, 4294967295, 1, 142, 32, 3099, 1, 4294967295, 4294967295, 1, 142, 8, 3100, 1, 4294967295, 4294967295, 1, 142, 32, 3101, 1, 4294967295, 4294967295, 1, 142, 8, 3102, 1, 4294967295, 4294967295, 1, 143, 32, 3103, 1, 4294967295, 4294967295, 1, 143, 8, 3104, 1, 4294967295, 4294967295, 1, 143, 8, 3105, 1, 4294967295, 4294967295, 1, 144, 8, 3106, 1, 4294967295, 4294967295, 5, 144, 8, 3107, 1, 2297, 4294967295, 8, 144, 8, 3108, 1, 4294967295, 4294967295, 10, 144, 8, 3109, 2, 4294967295, 4294967295, 12, 144, 8, 3111, 1, 4294967295, 2300, 9, 144, 8, 3112, 1, 4294967295, 4294967295, 1, 144, 32, 3113, 1, 4294967295, 4294967295, 1, 144, 8, 3114, 1, 4294967295, 4294967295, 1, 144, 8, 3115, 1, 4294967295, 4294967295, 1, 145, 8, 3116, 1, 4294967295, 4294967295, 5, 145, 8, 3117, 1, 2306, 4294967295, 8, 145, 8, 3118, 1, 4294967295, 4294967295, 10, 145, 8, 3119, 2, 4294967295, 4294967295, 12, 145, 8, 3121, 1, 4294967295, 2309, 9, 145, 8, 3122, 1, 4294967295, 4294967295, 1, 145, 32, 3123, 1, 4294967295, 4294967295, 3, 145, 8, 3124, 2, 2312, 4294967295, 8, 145, 8, 3126, 1, 4294967295, 4294967295, 1, 145, 32, 3127, 1, 4294967295, 4294967295, 1, 145, 32, 3128, 1, 4294967295, 4294967295, 1, 145, 8, 3129, 1, 4294967295, 4294967295, 1, 145, 8, 3130, 1, 4294967295, 4294967295, 3, 145, 8, 3131, 2, 2318, 4294967295, 8, 145, 8, 3133, 1, 4294967295, 4294967295, 1, 145, 32, 3134, 1, 4294967295, 4294967295, 1, 145, 8, 3135, 1, 4294967295, 4294967295, 1, 145, 8, 3136, 1, 4294967295, 4294967295, 1, 146, 8, 3137, 1, 4294967295, 4294967295, 5, 146, 8, 3138, 1, 2324, 4294967295, 8, 146, 8, 3139, 1, 4294967295, 4294967295, 10, 146, 8, 3140, 2, 4294967295, 4294967295, 12, 146, 8, 3142, 1, 4294967295, 2327, 9, 146, 8, 3143, 1, 4294967295, 4294967295, 1, 146, 32, 3144, 1, 4294967295, 4294967295, 1, 146, 32, 3145, 1, 4294967295, 4294967295, 1, 146, 8, 3146, 1, 4294967295, 4294967295, 1, 146, 32, 3147, 1, 4294967295, 4294967295, 1, 146, 8, 3148, 1, 4294967295, 4294967295, 1, 146, 8, 3149, 1, 4294967295, 4294967295, 1, 147, 8, 3150, 1, 4294967295, 4294967295, 5, 147, 8, 3151, 1, 2336, 4294967295, 8, 147, 8, 3152, 1, 4294967295, 4294967295, 10, 147, 8, 3153, 2, 4294967295, 4294967295, 12, 147, 8, 3155, 1, 4294967295, 2339, 9, 147, 8, 3156, 1, 4294967295, 4294967295, 1, 147, 32, 3157, 1, 4294967295, 4294967295, 1, 147, 32, 3158, 1, 4294967295, 4294967295, 1, 147, 8, 3159, 1, 4294967295, 4294967295, 3, 147, 8, 3160, 2, 2344, 4294967295, 8, 147, 8, 3162, 1, 4294967295, 4294967295, 1, 147, 32, 3163, 1, 4294967295, 4294967295, 1, 147, 8, 3164, 1, 4294967295, 4294967295, 1, 148, 72, 3165, 1, 4294967295, 4294967295, 1, 148, 8, 3166, 1, 4294967295, 4294967295, 1, 148, 8, 3167, 1, 4294967295, 4294967295, 1, 148, 8, 3168, 1, 4294967295, 4294967295, 1, 148, 8, 3169, 1, 4294967295, 4294967295, 1, 148, 8, 3170, 1, 4294967295, 4294967295, 1, 148, 8, 3171, 1, 4294967295, 4294967295, 1, 148, 8, 3172, 1, 4294967295, 4294967295, 1, 148, 8, 3173, 1, 4294967295, 4294967295, 1, 148, 8, 3174, 1, 4294967295, 4294967295, 1, 148, 8, 3175, 1, 4294967295, 4294967295, 1, 148, 8, 3176, 1, 4294967295, 4294967295, 1, 148, 8, 3177, 1, 4294967295, 4294967295, 1, 148, 8, 3178, 1, 4294967295, 4294967295, 1, 148, 8, 3179, 1, 4294967295, 4294967295, 1, 148, 8, 3180, 1, 4294967295, 4294967295, 1, 148, 8, 3181, 1, 4294967295, 4294967295, 1, 148, 8, 3182, 1, 4294967295, 4294967295, 1, 148, 8, 3183, 1, 4294967295, 4294967295, 1, 148, 8, 3184, 1, 4294967295, 4294967295, 1, 148, 8, 3185, 1, 4294967295, 4294967295, 1, 148, 8, 3186, 1, 4294967295, 4294967295, 1, 148, 8, 3187, 1, 4294967295, 4294967295, 1, 148, 8, 3188, 1, 4294967295, 4294967295, 1, 148, 32, 3189, 1, 4294967295, 4294967295, 1, 148, 8, 3190, 1, 4294967295, 4294967295, 3, 148, 8, 3191, 2, 2374, 4294967295, 8, 148, 8, 3193, 1, 4294967295, 4294967295, 1, 148, 8, 3194, 1, 4294967295, 4294967295, 1, 148, 8, 3195, 1, 4294967295, 4294967295, 1, 148, 8, 3196, 1, 4294967295, 4294967295, 1, 148, 8, 3197, 1, 4294967295, 4294967295, 1, 148, 8, 3198, 1, 4294967295, 4294967295, 1, 148, 8, 3199, 1, 4294967295, 4294967295, 1, 148, 8, 3200, 1, 4294967295, 4294967295, 1, 148, 8, 3201, 1, 4294967295, 4294967295, 1, 148, 8, 3202, 1, 4294967295, 4294967295, 1, 148, 8, 3203, 1, 4294967295, 4294967295, 1, 148, 8, 3204, 1, 4294967295, 4294967295, 3, 148, 8, 3205, 35, 2387, 4294967295, 8, 148, 8, 3240, 1, 4294967295, 4294967295, 1, 148, 72, 3241, 1, 4294967295, 4294967295, 1, 148, 32, 3242, 1, 4294967295, 4294967295, 1, 148, 32, 3243, 1, 4294967295, 4294967295, 1, 148, 32, 3244, 1, 4294967295, 4294967295, 1, 148, 32, 3245, 1, 4294967295, 4294967295, 1, 148, 32, 3246, 1, 4294967295, 4294967295, 1, 148, 32, 3247, 1, 4294967295, 4294967295, 1, 148, 32, 3248, 1, 4294967295, 4294967295, 1, 148, 32, 3249, 1, 4294967295, 4294967295, 1, 148, 32, 3250, 1, 4294967295, 4294967295, 1, 148, 32, 3251, 1, 4294967295, 4294967295, 1, 148, 8, 3252, 1, 4294967295, 4294967295, 1, 148, 8, 3253, 1, 4294967295, 4294967295, 1, 148, 32, 3254, 1, 4294967295, 4294967295, 3, 148, 8, 3255, 13, 2403, 4294967295, 8, 148, 8, 3268, 1, 4294967295, 4294967295, 1, 148, 8, 3269, 1, 4294967295, 4294967295, 1, 148, 72, 3270, 1, 4294967295, 4294967295, 1, 148, 32, 3271, 1, 4294967295, 4294967295, 1, 148, 32, 3272, 1, 4294967295, 4294967295, 1, 148, 32, 3273, 1, 4294967295, 4294967295, 1, 148, 32, 3274, 1, 4294967295, 4294967295, 1, 148, 32, 3275, 1, 4294967295, 4294967295, 1, 148, 32, 3276, 1, 4294967295, 4294967295, 1, 148, 8, 3277, 1, 4294967295, 4294967295, 1, 148, 8, 3278, 1, 4294967295, 4294967295, 1, 148, 32, 3279, 1, 4294967295, 4294967295, 1, 148, 32, 3280, 1, 4294967295, 4294967295, 1, 148, 32, 3281, 1, 4294967295, 4294967295, 1, 148, 32, 3282, 1, 4294967295, 4294967295, 1, 148, 32, 3283, 1, 4294967295, 4294967295, 1, 148, 32, 3284, 1, 4294967295, 4294967295, 1, 148, 32, 3285, 1, 4294967295, 4294967295, 1, 148, 32, 3286, 1, 4294967295, 4294967295, 1, 148, 32, 3287, 1, 4294967295, 4294967295, 1, 148, 32, 3288, 1, 4294967295, 4294967295, 1, 148, 32, 3289, 1, 4294967295, 4294967295, 1, 148, 32, 3290, 1, 4294967295, 4294967295, 1, 148, 32, 3291, 1, 4294967295, 4294967295, 1, 148, 32, 3292, 1, 4294967295, 4294967295, 3, 148, 8, 3293, 22, 2429, 4294967295, 8, 148, 8, 3315, 1, 4294967295, 4294967295, 1, 148, 8, 3316, 1, 4294967295, 4294967295, 1, 148, 72, 3317, 1, 4294967295, 4294967295, 1, 148, 32, 3318, 1, 4294967295, 4294967295, 1, 148, 8, 3319, 1, 4294967295, 4294967295, 1, 148, 72, 3320, 1, 4294967295, 4294967295, 1, 148, 32, 3321, 1, 4294967295, 4294967295, 1, 148, 8, 3322, 1, 4294967295, 4294967295, 1, 148, 32, 3323, 1, 4294967295, 4294967295, 1, 148, 8, 3324, 1, 4294967295, 4294967295, 1, 148, 8, 3325, 1, 4294967295, 4294967295, 1, 148, 72, 3326, 1, 4294967295, 4294967295, 1, 148, 8, 3327, 1, 4294967295, 4294967295, 1, 148, 72, 3328, 1, 4294967295, 4294967295, 1, 148, 8, 3329, 1, 4294967295, 4294967295, 1, 148, 72, 3330, 1, 4294967295, 4294967295, 1, 148, 32, 3331, 1, 4294967295, 4294967295, 1, 148, 8, 3332, 1, 4294967295, 4294967295, 1, 148, 72, 3333, 1, 4294967295, 4294967295, 1, 148, 32, 3334, 1, 4294967295, 4294967295, 1, 148, 8, 3335, 1, 4294967295, 4294967295, 1, 148, 72, 3336, 1, 4294967295, 4294967295, 1, 148, 32, 3337, 1, 4294967295, 4294967295, 1, 148, 72, 3338, 1, 4294967295, 4294967295, 1, 148, 32, 3339, 1, 4294967295, 4294967295, 1, 148, 8, 3340, 1, 4294967295, 4294967295, 3, 148, 8, 3341, 2, 2456, 4294967295, 8, 148, 8, 3343, 1, 4294967295, 4294967295, 1, 148, 72, 3344, 1, 4294967295, 4294967295, 1, 148, 32, 3345, 1, 4294967295, 4294967295, 1, 148, 32, 3346, 1, 4294967295, 4294967295, 1, 148, 8, 3347, 1, 4294967295, 4294967295, 1, 148, 32, 3348, 1, 4294967295, 4294967295, 1, 148, 8, 3349, 1, 4294967295, 4294967295, 5, 148, 8, 3350, 1, 2464, 4294967295, 8, 148, 8, 3351, 1, 4294967295, 4294967295, 10, 148, 8, 3352, 2, 4294967295, 4294967295, 12, 148, 8, 3354, 1, 4294967295, 2467, 9, 148, 8, 3355, 1, 4294967295, 4294967295, 1, 148, 32, 3356, 1, 4294967295, 4294967295, 3, 148, 8, 3357, 2, 2470, 4294967295, 8, 148, 8, 3359, 1, 4294967295, 4294967295, 3, 148, 8, 3360, 2, 2472, 4294967295, 8, 148, 8, 3362, 1, 4294967295, 4294967295, 1, 148, 32, 3363, 1, 4294967295, 4294967295, 1, 148, 72, 3364, 1, 4294967295, 4294967295, 1, 148, 32, 3365, 1, 4294967295, 4294967295, 1, 148, 8, 3366, 1, 4294967295, 4294967295, 5, 148, 8, 3367, 12, 2478, 4294967295, 8, 148, 8, 3379, 1, 4294967295, 4294967295, 10, 148, 10, 3380, 2, 4294967295, 4294967295, 12, 148, 8, 3382, 1, 4294967295, 2481, 9, 148, 8, 3383, 1, 4294967295, 4294967295, 1, 149, 8, 3384, 1, 4294967295, 4294967295, 1, 149, 8, 3385, 1, 4294967295, 4294967295, 3, 149, 8, 3386, 2, 2485, 4294967295, 8, 149, 8, 3388, 1, 4294967295, 4294967295, 1, 150, 8, 3389, 1, 4294967295, 4294967295, 5, 150, 8, 3390, 1, 2488, 4294967295, 8, 150, 8, 3391, 1, 4294967295, 4294967295, 10, 150, 8, 3392, 2, 4294967295, 4294967295, 12, 150, 8, 3394, 1, 4294967295, 2491, 9, 150, 8, 3395, 1, 4294967295, 4294967295, 1, 150, 32, 3396, 1, 4294967295, 4294967295, 1, 150, 8, 3397, 1, 4294967295, 4294967295, 3, 150, 8, 3398, 2, 2495, 4294967295, 8, 150, 8, 3400, 1, 4294967295, 4294967295, 1, 150, 8, 3401, 1, 4294967295, 4294967295, 1, 150, 8, 3402, 1, 4294967295, 4294967295, 3, 150, 8, 3403, 2, 2499, 4294967295, 8, 150, 8, 3405, 1, 4294967295, 4294967295, 1, 151, 8, 3406, 1, 4294967295, 4294967295, 1, 151, 8, 3407, 1, 4294967295, 4294967295, 3, 151, 8, 3408, 2, 2503, 4294967295, 8, 151, 8, 3410, 1, 4294967295, 4294967295, 1, 152, 8, 3411, 1, 4294967295, 4294967295, 5, 152, 8, 3412, 1, 2506, 4294967295, 8, 152, 8, 3413, 1, 4294967295, 4294967295, 10, 152, 8, 3414, 2, 4294967295, 4294967295, 12, 152, 8, 3416, 1, 4294967295, 2509, 9, 152, 8, 3417, 1, 4294967295, 4294967295, 1, 152, 8, 3418, 1, 4294967295, 4294967295, 5, 152, 8, 3419, 1, 2512, 4294967295, 8, 152, 8, 3420, 1, 4294967295, 4294967295, 10, 152, 8, 3421, 2, 4294967295, 4294967295, 12, 152, 8, 3423, 1, 4294967295, 2515, 9, 152, 8, 3424, 1, 4294967295, 4294967295, 1, 152, 8, 3425, 1, 4294967295, 4294967295, 3, 152, 8, 3426, 2, 2518, 4294967295, 8, 152, 8, 3428, 1, 4294967295, 4294967295, 1, 152, 8, 3429, 1, 4294967295, 4294967295, 1, 152, 32, 3430, 1, 4294967295, 4294967295, 1, 152, 8, 3431, 1, 4294967295, 4294967295, 1, 152, 8, 3432, 1, 4294967295, 4294967295, 3, 152, 8, 3433, 2, 2524, 4294967295, 8, 152, 8, 3435, 1, 4294967295, 4294967295, 1, 153, 8, 3436, 1, 4294967295, 4294967295, 5, 153, 8, 3437, 1, 2527, 4294967295, 8, 153, 8, 3438, 1, 4294967295, 4294967295, 10, 153, 8, 3439, 2, 4294967295, 4294967295, 12, 153, 8, 3441, 1, 4294967295, 2530, 9, 153, 8, 3442, 1, 4294967295, 4294967295, 1, 153, 8, 3443, 1, 4294967295, 4294967295, 5, 153, 8, 3444, 1, 2533, 4294967295, 8, 153, 8, 3445, 1, 4294967295, 4294967295, 10, 153, 8, 3446, 2, 4294967295, 4294967295, 12, 153, 8, 3448, 1, 4294967295, 2536, 9, 153, 8, 3449, 1, 4294967295, 4294967295, 1, 153, 8, 3450, 1, 4294967295, 4294967295, 1, 153, 32, 3451, 1, 4294967295, 4294967295, 1, 153, 8, 3452, 1, 4294967295, 4294967295, 1, 153, 8, 3453, 1, 4294967295, 4294967295, 3, 153, 8, 3454, 2, 2542, 4294967295, 8, 153, 8, 3456, 1, 4294967295, 4294967295, 1, 154, 32, 3457, 1, 4294967295, 4294967295, 1, 154, 32, 3458, 1, 4294967295, 4294967295, 1, 154, 8, 3459, 1, 4294967295, 4294967295, 1, 154, 32, 3460, 1, 4294967295, 4294967295, 1, 154, 8, 3461, 1, 4294967295, 4294967295, 5, 154, 8, 3462, 1, 2549, 4294967295, 8, 154, 8, 3463, 1, 4294967295, 4294967295, 10, 154, 8, 3464, 2, 4294967295, 4294967295, 12, 154, 8, 3466, 1, 4294967295, 2552, 9, 154, 8, 3467, 1, 4294967295, 4294967295, 1, 154, 32, 3468, 1, 4294967295, 4294967295, 3, 154, 8, 3469, 2, 2555, 4294967295, 8, 154, 8, 3471, 1, 4294967295, 4294967295, 3, 154, 8, 3472, 2, 2557, 4294967295, 8, 154, 8, 3474, 1, 4294967295, 4294967295, 1, 154, 32, 3475, 1, 4294967295, 4294967295, 1, 154, 8, 3476, 1, 4294967295, 4294967295, 1, 155, 8, 3477, 1, 4294967295, 4294967295, 3, 155, 8, 3478, 2, 2562, 4294967295, 8, 155, 8, 3480, 1, 4294967295, 4294967295, 1, 155, 8, 3481, 1, 4294967295, 4294967295, 1, 155, 8, 3482, 1, 4294967295, 4294967295, 1, 156, 32, 3483, 1, 4294967295, 4294967295, 1, 156, 8, 3484, 1, 4294967295, 4294967295, 1, 156, 8, 3485, 1, 4294967295, 4294967295, 3, 156, 8, 3486, 2, 2569, 4294967295, 8, 156, 8, 3488, 1, 4294967295, 4294967295, 1, 157, 32, 3489, 1, 4294967295, 4294967295, 1, 157, 8, 3490, 1, 4294967295, 4294967295, 1, 157, 32, 3491, 1, 4294967295, 4294967295, 1, 157, 8, 3492, 1, 4294967295, 4294967295, 5, 157, 8, 3493, 1, 2575, 4294967295, 8, 157, 8, 3494, 1, 4294967295, 4294967295, 10, 157, 8, 3495, 2, 4294967295, 4294967295, 12, 157, 8, 3497, 1, 4294967295, 2578, 9, 157, 8, 3498, 1, 4294967295, 4294967295, 1, 157, 32, 3499, 1, 4294967295, 4294967295, 3, 157, 8, 3500, 2, 2581, 4294967295, 8, 157, 8, 3502, 1, 4294967295, 4294967295, 3, 157, 8, 3503, 2, 2583, 4294967295, 8, 157, 8, 3505, 1, 4294967295, 4294967295, 1, 157, 32, 3506, 1, 4294967295, 4294967295, 1, 157, 8, 3507, 1, 4294967295, 4294967295, 1, 158, 32, 3508, 1, 4294967295, 4294967295, 1, 158, 8, 3509, 1, 4294967295, 4294967295, 1, 158, 8, 3510, 1, 4294967295, 4294967295, 1, 159, 8, 3511, 1, 4294967295, 4294967295, 1, 159, 8, 3512, 1, 4294967295, 4294967295, 3, 159, 8, 3513, 2, 2592, 4294967295, 8, 159, 8, 3515, 1, 4294967295, 4294967295, 1, 160, 32, 3516, 1, 4294967295, 4294967295, 1, 160, 8, 3517, 1, 4294967295, 4294967295, 1, 160, 8, 3518, 1, 4294967295, 4294967295, 3, 160, 8, 3519, 2, 2597, 4294967295, 8, 160, 8, 3521, 1, 4294967295, 4294967295, 1, 161, 32, 3522, 1, 4294967295, 4294967295, 1, 161, 8, 3523, 1, 4294967295, 4294967295, 1, 161, 8, 3524, 1, 4294967295, 4294967295, 3, 161, 8, 3525, 2, 2602, 4294967295, 8, 161, 8, 3527, 1, 4294967295, 4294967295, 1, 161, 8, 3528, 1, 4294967295, 4294967295, 3, 161, 8, 3529, 2, 2605, 4294967295, 8, 161, 8, 3531, 1, 4294967295, 4294967295, 1, 162, 32, 3532, 1, 4294967295, 4294967295, 1, 162, 8, 3533, 1, 4294967295, 4294967295, 1, 162, 32, 3534, 1, 4294967295, 4294967295, 1, 162, 8, 3535, 1, 4294967295, 4294967295, 1, 162, 8, 3536, 1, 4294967295, 4294967295, 1, 163, 32, 3537, 1, 4294967295, 4294967295, 1, 163, 32, 3538, 1, 4294967295, 4294967295, 1, 163, 8, 3539, 1, 4294967295, 4294967295, 1, 163, 32, 3540, 1, 4294967295, 4294967295, 1, 163, 8, 3541, 1, 4294967295, 4294967295, 1, 163, 32, 3542, 1, 4294967295, 4294967295, 1, 163, 32, 3543, 1, 4294967295, 4294967295, 1, 163, 8, 3544, 1, 4294967295, 4294967295, 1, 163, 32, 3545, 1, 4294967295, 4294967295, 1, 163, 8, 3546, 1, 4294967295, 4294967295, 3, 163, 8, 3547, 2, 2622, 4294967295, 8, 163, 8, 3549, 1, 4294967295, 4294967295, 1, 164, 32, 3550, 1, 4294967295, 4294967295, 1, 164, 8, 3551, 1, 4294967295, 4294967295, 1, 164, 32, 3552, 1, 4294967295, 4294967295, 1, 164, 8, 3553, 1, 4294967295, 4294967295, 5, 164, 8, 3554, 1, 2628, 4294967295, 8, 164, 8, 3555, 1, 4294967295, 4294967295, 10, 164, 8, 3556, 2, 4294967295, 4294967295, 12, 164, 8, 3558, 1, 4294967295, 2631, 9, 164, 8, 3559, 1, 4294967295, 4294967295, 1, 164, 32, 3560, 1, 4294967295, 4294967295, 3, 164, 8, 3561, 2, 2634, 4294967295, 8, 164, 8, 3563, 1, 4294967295, 4294967295, 3, 164, 8, 3564, 2, 2636, 4294967295, 8, 164, 8, 3566, 1, 4294967295, 4294967295, 1, 164, 32, 3567, 1, 4294967295, 4294967295, 1, 164, 8, 3568, 1, 4294967295, 4294967295, 1, 165, 8, 3569, 1, 4294967295, 4294967295, 1, 165, 8, 3570, 1, 4294967295, 4294967295, 1, 165, 8, 3571, 1, 4294967295, 4294967295, 3, 165, 8, 3572, 3, 2643, 4294967295, 8, 165, 8, 3575, 1, 4294967295, 4294967295, 1, 166, 8, 3576, 1, 4294967295, 4294967295, 1, 166, 8, 3577, 1, 4294967295, 4294967295, 1, 167, 32, 3578, 1, 4294967295, 4294967295, 1, 167, 8, 3579, 1, 4294967295, 4294967295, 1, 167, 8, 3580, 1, 4294967295, 4294967295, 1, 168, 32, 3581, 1, 4294967295, 4294967295, 1, 168, 8, 3582, 1, 4294967295, 4294967295, 1, 168, 8, 3583, 1, 4294967295, 4294967295, 1, 169, 8, 3584, 1, 4294967295, 4294967295, 1, 169, 8, 3585, 1, 4294967295, 4294967295, 1, 169, 8, 3586, 1, 4294967295, 4294967295, 1, 170, 32, 3587, 1, 4294967295, 4294967295, 1, 170, 32, 3588, 1, 4294967295, 4294967295, 1, 170, 8, 3589, 1, 4294967295, 4294967295, 1, 170, 32, 3590, 1, 4294967295, 4294967295, 1, 170, 8, 3591, 1, 4294967295, 4294967295, 1, 171, 8, 3592, 1, 4294967295, 4294967295, 1, 171, 8, 3593, 1, 4294967295, 4294967295, 1, 172, 32, 3594, 1, 4294967295, 4294967295, 1, 172, 8, 3595, 1, 4294967295, 4294967295, 1, 173, 32, 3596, 1, 4294967295, 4294967295, 1, 173, 32, 3597, 1, 4294967295, 4294967295, 1, 173, 32, 3598, 1, 4294967295, 4294967295, 5, 173, 8, 3599, 1, 2668, 4294967295, 8, 173, 8, 3600, 1, 4294967295, 4294967295, 10, 173, 8, 3601, 2, 4294967295, 4294967295, 12, 173, 8, 3603, 1, 4294967295, 2671, 9, 173, 8, 3604, 1, 4294967295, 4294967295, 1, 173, 32, 3605, 1, 4294967295, 4294967295, 1, 173, 8, 3606, 1, 4294967295, 4294967295, 1, 173, 8, 3607, 1, 4294967295, 4294967295, 1, 174, 8, 3608, 1, 4294967295, 4294967295, 1, 174, 8, 3609, 1, 4294967295, 4294967295, 1, 175, 32, 3610, 1, 4294967295, 4294967295, 1, 175, 32, 3611, 1, 4294967295, 4294967295, 1, 175, 32, 3612, 1, 4294967295, 4294967295, 1, 175, 8, 3613, 1, 4294967295, 4294967295, 1, 175, 8, 3614, 1, 4294967295, 4294967295, 1, 176, 8, 3615, 1, 4294967295, 4294967295, 1, 176, 8, 3616, 1, 4294967295, 4294967295, 3, 176, 8, 3617, 2, 2685, 4294967295, 8, 176, 8, 3619, 1, 4294967295, 4294967295, 1, 177, 32, 3620, 1, 4294967295, 4294967295, 1, 177, 8, 3621, 1, 4294967295, 4294967295, 1, 178, 32, 3622, 1, 4294967295, 4294967295, 1, 178, 8, 3623, 1, 4294967295, 4294967295, 1, 179, 32, 3624, 1, 4294967295, 4294967295, 1, 179, 8, 3625, 1, 4294967295, 4294967295, 5, 179, 8, 3626, 1, 2693, 4294967295, 8, 179, 8, 3627, 1, 4294967295, 4294967295, 10, 179, 8, 3628, 2, 4294967295, 4294967295, 12, 179, 8, 3630, 1, 4294967295, 2696, 9, 179, 8, 3631, 1, 4294967295, 4294967295, 1, 179, 32, 3632, 1, 4294967295, 4294967295, 1, 179, 32, 3633, 1, 4294967295, 4294967295, 1, 179, 8, 3634, 1, 4294967295, 4294967295, 5, 179, 8, 3635, 1, 2701, 4294967295, 8, 179, 8, 3636, 1, 4294967295, 4294967295, 10, 179, 8, 3637, 2, 4294967295, 4294967295, 12, 179, 8, 3639, 1, 4294967295, 2704, 9, 179, 8, 3640, 1, 4294967295, 4294967295, 1, 179, 32, 3641, 1, 4294967295, 4294967295, 1, 179, 8, 3642, 1, 4294967295, 4294967295, 1, 179, 8, 3643, 1, 4294967295, 4294967295, 5, 179, 8, 3644, 1, 2709, 4294967295, 8, 179, 8, 3645, 1, 4294967295, 4294967295, 10, 179, 8, 3646, 2, 4294967295, 4294967295, 12, 179, 8, 3648, 1, 4294967295, 2712, 9, 179, 8, 3649, 1, 4294967295, 4294967295, 1, 179, 8, 3650, 1, 4294967295, 4294967295, 1, 179, 8, 3651, 1, 4294967295, 4294967295, 1, 179, 8, 3652, 1, 4294967295, 4294967295, 1, 179, 8, 3653, 1, 4294967295, 4294967295, 5, 179, 8, 3654, 1, 2718, 4294967295, 8, 179, 8, 3655, 1, 4294967295, 4294967295, 10, 179, 8, 3656, 2, 4294967295, 4294967295, 12, 179, 8, 3658, 1, 4294967295, 2721, 9, 179, 8, 3659, 1, 4294967295, 4294967295, 1, 179, 8, 3660, 1, 4294967295, 4294967295, 1, 179, 8, 3661, 1, 4294967295, 4294967295, 3, 179, 8, 3662, 4, 2725, 4294967295, 8, 179, 8, 3666, 1, 4294967295, 4294967295, 1, 180, 8, 3667, 1, 4294967295, 4294967295, 1, 180, 8, 3668, 1, 4294967295, 4294967295, 3, 180, 8, 3669, 2, 2729, 4294967295, 8, 180, 8, 3671, 1, 4294967295, 4294967295, 1, 181, 8, 3672, 1, 4294967295, 4294967295, 1, 181, 8, 3673, 1, 4294967295, 4294967295, 1, 182, 32, 3674, 1, 4294967295, 4294967295, 1, 182, 8, 3675, 1, 4294967295, 4294967295, 1, 182, 8, 3676, 1, 4294967295, 4294967295, 3, 182, 8, 3677, 2, 2736, 4294967295, 8, 182, 8, 3679, 1, 4294967295, 4294967295, 1, 182, 8, 3680, 1, 4294967295, 4294967295, 3, 182, 8, 3681, 2, 2739, 4294967295, 8, 182, 8, 3683, 1, 4294967295, 4294967295, 1, 182, 32, 3684, 1, 4294967295, 4294967295, 1, 182, 8, 3685, 1, 4294967295, 4294967295, 1, 183, 32, 3686, 1, 4294967295, 4294967295, 1, 183, 8, 3687, 1, 4294967295, 4294967295, 1, 183, 8, 3688, 1, 4294967295, 4294967295, 1, 184, 32, 3689, 1, 4294967295, 4294967295, 1, 184, 8, 3690, 1, 4294967295, 4294967295, 1, 184, 8, 3691, 1, 4294967295, 4294967295, 1, 185, 32, 3692, 1, 4294967295, 4294967295, 1, 185, 8, 3693, 1, 4294967295, 4294967295, 1, 186, 32, 3694, 1, 4294967295, 4294967295, 1, 186, 32, 3695, 1, 4294967295, 4294967295, 5, 186, 8, 3696, 1, 2753, 4294967295, 8, 186, 8, 3697, 1, 4294967295, 4294967295, 10, 186, 8, 3698, 2, 4294967295, 4294967295, 12, 186, 8, 3700, 1, 4294967295, 2756, 9, 186, 8, 3701, 1, 4294967295, 4294967295, 1, 187, 32, 3702, 1, 4294967295, 4294967295, 1, 187, 8, 3703, 1, 4294967295, 4294967295, 1, 188, 32, 3704, 1, 4294967295, 4294967295, 1, 188, 32, 3705, 1, 4294967295, 4294967295, 1, 188, 32, 3706, 1, 4294967295, 4294967295, 1, 188, 32, 3707, 1, 4294967295, 4294967295, 1, 188, 32, 3708, 1, 4294967295, 4294967295, 1, 188, 8, 3709, 1, 4294967295, 4294967295, 1, 188, 8, 3710, 1, 4294967295, 4294967295, 1, 188, 8, 3711, 1, 4294967295, 4294967295, 1, 188, 8, 3712, 1, 4294967295, 4294967295, 1, 188, 8, 3713, 1, 4294967295, 4294967295, 1, 188, 8, 3714, 1, 4294967295, 4294967295, 1, 188, 8, 3715, 1, 4294967295, 4294967295, 1, 188, 8, 3716, 1, 4294967295, 4294967295, 3, 188, 8, 3717, 13, 2773, 4294967295, 8, 188, 8, 3730, 1, 4294967295, 4294967295, 1, 189, 8, 3731, 1, 4294967295, 4294967295, 1, 189, 32, 3732, 1, 4294967295, 4294967295, 1, 189, 8, 3733, 1, 4294967295, 4294967295, 1, 190, 8, 3734, 1, 4294967295, 4294967295, 1, 190, 32, 3735, 1, 4294967295, 4294967295, 1, 190, 8, 3736, 1, 4294967295, 4294967295, 1, 191, 8, 3737, 1, 4294967295, 4294967295, 1, 191, 32, 3738, 1, 4294967295, 4294967295, 1, 191, 8, 3739, 1, 4294967295, 4294967295, 1, 192, 32, 3740, 1, 4294967295, 4294967295, 1, 192, 32, 3741, 1, 4294967295, 4294967295, 1, 192, 8, 3742, 1, 4294967295, 4294967295, 1, 192, 32, 3743, 1, 4294967295, 4294967295, 1, 192, 8, 3744, 1, 4294967295, 4294967295, 1, 193, 32, 3745, 1, 4294967295, 4294967295, 1, 193, 8, 3746, 1, 4294967295, 4294967295, 1, 193, 8, 3747, 1, 4294967295, 4294967295, 1, 194, 32, 3748, 1, 4294967295, 4294967295, 1, 194, 8, 3749, 1, 4294967295, 4294967295, 1, 194, 32, 3750, 1, 4294967295, 4294967295, 1, 194, 8, 3751, 1, 4294967295, 4294967295, 1, 195, 32, 3752, 1, 4294967295, 4294967295, 1, 195, 8, 3753, 1, 4294967295, 4294967295, 1, 195, 32, 3754, 1, 4294967295, 4294967295, 1, 195, 8, 3755, 1, 4294967295, 4294967295, 1, 195, 32, 3756, 1, 4294967295, 4294967295, 1, 195, 8, 3757, 1, 4294967295, 4294967295, 1, 195, 32, 3758, 1, 4294967295, 4294967295, 1, 195, 8, 3759, 1, 4294967295, 4294967295, 1, 195, 32, 3760, 1, 4294967295, 4294967295, 1, 195, 8, 3761, 1, 4294967295, 4294967295, 1, 195, 32, 3762, 1, 4294967295, 4294967295, 1, 195, 8, 3763, 1, 4294967295, 4294967295, 1, 195, 32, 3764, 1, 4294967295, 4294967295, 1, 195, 8, 3765, 1, 4294967295, 4294967295, 1, 195, 32, 3766, 1, 4294967295, 4294967295, 1, 195, 8, 3767, 1, 4294967295, 4294967295, 1, 195, 32, 3768, 1, 4294967295, 4294967295, 1, 195, 8, 3769, 1, 4294967295, 4294967295, 3, 195, 8, 3770, 9, 2814, 4294967295, 8, 195, 8, 3779, 1, 4294967295, 4294967295, 1, 196, 8, 3780, 1, 4294967295, 4294967295, 1, 196, 8, 3781, 1, 4294967295, 4294967295, 1, 196, 8, 3782, 1, 4294967295, 4294967295, 1, 197, 32, 3783, 1, 4294967295, 4294967295, 1, 197, 8, 3784, 1, 4294967295, 4294967295, 3, 197, 8, 3785, 2, 2821, 4294967295, 8, 197, 8, 3787, 1, 4294967295, 4294967295, 1, 197, 8, 3788, 1, 4294967295, 4294967295, 1, 197, 32, 3789, 1, 4294967295, 4294967295, 1, 197, 8, 3790, 1, 4294967295, 4294967295, 1, 197, 8, 3791, 1, 4294967295, 4294967295, 1, 198, 8, 3792, 1, 4294967295, 4294967295, 5, 198, 8, 3793, 1, 2828, 4294967295, 8, 198, 8, 3794, 1, 4294967295, 4294967295, 10, 198, 8, 3795, 2, 4294967295, 4294967295, 12, 198, 8, 3797, 1, 4294967295, 2831, 9, 198, 8, 3798, 1, 4294967295, 4294967295, 1, 198, 8, 3799, 1, 4294967295, 4294967295, 1, 198, 8, 3800, 1, 4294967295, 4294967295, 3, 198, 8, 3801, 2, 2835, 4294967295, 8, 198, 8, 3803, 1, 4294967295, 4294967295, 1, 199, 8, 3804, 1, 4294967295, 4294967295, 1, 199, 8, 3805, 1, 4294967295, 4294967295, 1, 199, 8, 3806, 1, 4294967295, 4294967295, 1, 199, 8, 3807, 1, 4294967295, 4294967295, 1, 199, 8, 3808, 1, 4294967295, 4294967295, 3, 199, 8, 3809, 5, 2842, 4294967295, 8, 199, 8, 3814, 1, 4294967295, 4294967295, 1, 200, 32, 3815, 1, 4294967295, 4294967295, 1, 200, 8, 3816, 1, 4294967295, 4294967295, 3, 200, 8, 3817, 2, 2846, 4294967295, 8, 200, 8, 3819, 1, 4294967295, 4294967295, 1, 200, 8, 3820, 1, 4294967295, 4294967295, 1, 200, 32, 3821, 1, 4294967295, 4294967295, 1, 200, 8, 3822, 1, 4294967295, 4294967295, 1, 200, 32, 3823, 1, 4294967295, 4294967295, 1, 200, 8, 3824, 1, 4294967295, 4294967295, 1, 200, 32, 3825, 1, 4294967295, 4294967295, 1, 200, 8, 3826, 1, 4294967295, 4294967295, 1, 200, 8, 3827, 1, 4294967295, 4294967295, 3, 200, 8, 3828, 2, 2856, 4294967295, 8, 200, 8, 3830, 1, 4294967295, 4294967295, 1, 201, 32, 3831, 1, 4294967295, 4294967295, 1, 201, 8, 3832, 1, 4294967295, 4294967295, 1, 201, 8, 3833, 1, 4294967295, 4294967295, 1, 202, 32, 3834, 1, 4294967295, 4294967295, 1, 202, 8, 3835, 1, 4294967295, 4294967295, 1, 202, 32, 3836, 1, 4294967295, 4294967295, 1, 202, 8, 3837, 1, 4294967295, 4294967295, 1, 202, 8, 3838, 1, 4294967295, 4294967295, 1, 203, 32, 3839, 1, 4294967295, 4294967295, 1, 203, 8, 3840, 1, 4294967295, 4294967295, 1, 203, 32, 3841, 1, 4294967295, 4294967295, 1, 203, 8, 3842, 1, 4294967295, 4294967295, 5, 203, 8, 3843, 1, 2870, 4294967295, 8, 203, 8, 3844, 1, 4294967295, 4294967295, 10, 203, 8, 3845, 2, 4294967295, 4294967295, 12, 203, 8, 3847, 1, 4294967295, 2873, 9, 203, 8, 3848, 1, 4294967295, 4294967295, 1, 204, 8, 3849, 1, 4294967295, 4294967295, 1, 204, 32, 3850, 1, 4294967295, 4294967295, 3, 204, 8, 3851, 2, 2877, 4294967295, 8, 204, 8, 3853, 1, 4294967295, 4294967295, 1, 205, 32, 3854, 1, 4294967295, 4294967295, 1, 205, 8, 3855, 1, 4294967295, 4294967295, 1, 205, 8, 3856, 1, 4294967295, 4294967295, 1, 206, 8, 3857, 1, 4294967295, 4294967295, 1, 206, 8, 3858, 1, 4294967295, 4294967295, 3, 206, 8, 3859, 2, 2884, 4294967295, 8, 206, 8, 3861, 1, 4294967295, 4294967295, 1, 207, 32, 3862, 1, 4294967295, 4294967295, 1, 207, 8, 3863, 1, 4294967295, 4294967295, 1, 207, 32, 3864, 1, 4294967295, 4294967295, 1, 207, 8, 3865, 1, 4294967295, 4294967295, 1, 207, 8, 3866, 1, 4294967295, 4294967295, 1, 208, 32, 3867, 1, 4294967295, 4294967295, 1, 208, 8, 3868, 1, 4294967295, 4294967295, 1, 208, 8, 3869, 1, 4294967295, 4294967295, 1, 209, 32, 3870, 1, 4294967295, 4294967295, 1, 209, 8, 3871, 1, 4294967295, 4294967295, 1, 209, 8, 3872, 1, 4294967295, 4294967295, 1, 209, 8, 3873, 1, 4294967295, 4294967295, 1, 210, 32, 3874, 1, 4294967295, 4294967295, 1, 210, 8, 3875, 1, 4294967295, 4294967295, 1, 210, 8, 3876, 1, 4294967295, 4294967295, 1, 211, 32, 3877, 1, 4294967295, 4294967295, 1, 211, 32, 3878, 1, 4294967295, 4294967295, 1, 211, 8, 3879, 1, 4294967295, 4294967295, 1, 211, 32, 3880, 1, 4294967295, 4294967295, 1, 211, 8, 3881, 1, 4294967295, 4294967295, 1, 212, 32, 3882, 1, 4294967295, 4294967295, 1, 212, 32, 3883, 1, 4294967295, 4294967295, 1, 212, 8, 3884, 1, 4294967295, 4294967295, 1, 212, 32, 3885, 1, 4294967295, 4294967295, 1, 212, 8, 3886, 1, 4294967295, 4294967295, 1, 212, 32, 3887, 1, 4294967295, 4294967295, 1, 212, 8, 3888, 1, 4294967295, 4294967295, 1, 213, 32, 3889, 1, 4294967295, 4294967295, 1, 213, 32, 3890, 1, 4294967295, 4294967295, 1, 213, 8, 3891, 1, 4294967295, 4294967295, 1, 213, 32, 3892, 1, 4294967295, 4294967295, 1, 213, 8, 3893, 1, 4294967295, 4294967295, 1, 214, 32, 3894, 1, 4294967295, 4294967295, 1, 214, 8, 3895, 1, 4294967295, 4294967295, 1, 214, 8, 3896, 1, 4294967295, 4294967295, 3, 214, 8, 3897, 2, 2921, 4294967295, 8, 214, 8, 3899, 1, 4294967295, 4294967295, 1, 215, 8, 3900, 1, 4294967295, 4294967295, 1, 215, 8, 3901, 1, 4294967295, 4294967295, 3, 215, 8, 3902, 2, 2925, 4294967295, 8, 215, 8, 3904, 1, 4294967295, 4294967295, 1, 215, 32, 3905, 1, 4294967295, 4294967295, 1, 215, 8, 3906, 1, 4294967295, 4294967295, 1, 215, 8, 3907, 1, 4294967295, 4294967295, 1, 216, 32, 3908, 1, 4294967295, 4294967295, 1, 216, 8, 3909, 1, 4294967295, 4294967295, 1, 216, 8, 3910, 1, 4294967295, 4294967295, 1, 217, 32, 3911, 1, 4294967295, 4294967295, 1, 217, 8, 3912, 1, 4294967295, 4294967295, 1, 217, 32, 3913, 1, 4294967295, 4294967295, 1, 217, 8, 3914, 1, 4294967295, 4294967295, 4, 217, 8, 3915, 1, 2937, 4294967295, 8, 217, 8, 3916, 1, 4294967295, 4294967295, 11, 217, 8, 3917, 2, 4294967295, 4294967295, 12, 217, 8, 3919, 1, 4294967295, 2938, 1, 217, 32, 3920, 1, 4294967295, 4294967295, 1, 217, 8, 3921, 1, 4294967295, 4294967295, 1, 218, 32, 3922, 1, 4294967295, 4294967295, 1, 218, 32, 3923, 1, 4294967295, 4294967295, 1, 218, 8, 3924, 1, 4294967295, 4294967295, 1, 218, 32, 3925, 1, 4294967295, 4294967295, 1, 218, 8, 3926, 1, 4294967295, 4294967295, 1, 219, 32, 3927, 1, 4294967295, 4294967295, 1, 219, 32, 3928, 1, 4294967295, 4294967295, 1, 219, 8, 3929, 1, 4294967295, 4294967295, 1, 219, 32, 3930, 1, 4294967295, 4294967295, 1, 219, 8, 3931, 1, 4294967295, 4294967295, 1, 220, 8, 3932, 1, 4294967295, 4294967295, 1, 220, 8, 3933, 1, 4294967295, 4294967295, 1, 220, 8, 3934, 1, 4294967295, 4294967295, 1, 220, 8, 3935, 1, 4294967295, 4294967295, 1, 220, 8, 3936, 1, 4294967295, 4294967295, 1, 220, 8, 3937, 1, 4294967295, 4294967295, 1, 220, 8, 3938, 1, 4294967295, 4294967295, 3, 220, 8, 3939, 7, 2960, 4294967295, 8, 220, 8, 3946, 1, 4294967295, 4294967295, 1, 221, 32, 3947, 1, 4294967295, 4294967295, 1, 221, 8, 3948, 1, 4294967295, 4294967295, 1, 222, 32, 3949, 1, 4294967295, 4294967295, 1, 222, 32, 3950, 1, 4294967295, 4294967295, 1, 222, 32, 3951, 1, 4294967295, 4294967295, 1, 222, 32, 3952, 1, 4294967295, 4294967295, 1, 222, 32, 3953, 1, 4294967295, 4294967295, 1, 222, 32, 3954, 1, 4294967295, 4294967295, 1, 222, 32, 3955, 1, 4294967295, 4294967295, 1, 222, 32, 3956, 1, 4294967295, 4294967295, 1, 222, 32, 3957, 1, 4294967295, 4294967295, 1, 222, 32, 3958, 1, 4294967295, 4294967295, 1, 222, 32, 3959, 1, 4294967295, 4294967295, 1, 222, 32, 3960, 1, 4294967295, 4294967295, 1, 222, 32, 3961, 1, 4294967295, 4294967295, 1, 222, 32, 3962, 1, 4294967295, 4294967295, 1, 222, 32, 3963, 1, 4294967295, 4294967295, 1, 222, 32, 3964, 1, 4294967295, 4294967295, 1, 222, 32, 3965, 1, 4294967295, 4294967295, 1, 222, 32, 3966, 1, 4294967295, 4294967295, 1, 222, 32, 3967, 1, 4294967295, 4294967295, 1, 222, 32, 3968, 1, 4294967295, 4294967295, 1, 222, 32, 3969, 1, 4294967295, 4294967295, 1, 222, 32, 3970, 1, 4294967295, 4294967295, 1, 222, 32, 3971, 1, 4294967295, 4294967295, 1, 222, 32, 3972, 1, 4294967295, 4294967295, 1, 222, 32, 3973, 1, 4294967295, 4294967295, 1, 222, 32, 3974, 1, 4294967295, 4294967295, 1, 222, 32, 3975, 1, 4294967295, 4294967295, 1, 222, 32, 3976, 1, 4294967295, 4294967295, 1, 222, 32, 3977, 1, 4294967295, 4294967295, 1, 222, 32, 3978, 1, 4294967295, 4294967295, 1, 222, 32, 3979, 1, 4294967295, 4294967295, 1, 222, 32, 3980, 1, 4294967295, 4294967295, 1, 222, 32, 3981, 1, 4294967295, 4294967295, 1, 222, 32, 3982, 1, 4294967295, 4294967295, 1, 222, 32, 3983, 1, 4294967295, 4294967295, 1, 222, 32, 3984, 1, 4294967295, 4294967295, 1, 222, 32, 3985, 1, 4294967295, 4294967295, 1, 222, 32, 3986, 1, 4294967295, 4294967295, 1, 222, 32, 3987, 1, 4294967295, 4294967295, 1, 222, 32, 3988, 1, 4294967295, 4294967295, 1, 222, 32, 3989, 1, 4294967295, 4294967295, 1, 222, 32, 3990, 1, 4294967295, 4294967295, 1, 222, 32, 3991, 1, 4294967295, 4294967295, 1, 222, 32, 3992, 1, 4294967295, 4294967295, 1, 222, 32, 3993, 1, 4294967295, 4294967295, 1, 222, 32, 3994, 1, 4294967295, 4294967295, 1, 222, 32, 3995, 1, 4294967295, 4294967295, 1, 222, 32, 3996, 1, 4294967295, 4294967295, 1, 222, 32, 3997, 1, 4294967295, 4294967295, 1, 222, 32, 3998, 1, 4294967295, 4294967295, 1, 222, 32, 3999, 1, 4294967295, 4294967295, 1, 222, 32, 4000, 1, 4294967295, 4294967295, 1, 222, 32, 4001, 1, 4294967295, 4294967295, 1, 222, 32, 4002, 1, 4294967295, 4294967295, 1, 222, 32, 4003, 1, 4294967295, 4294967295, 1, 222, 32, 4004, 1, 4294967295, 4294967295, 1, 222, 32, 4005, 1, 4294967295, 4294967295, 1, 222, 32, 4006, 1, 4294967295, 4294967295, 1, 222, 32, 4007, 1, 4294967295, 4294967295, 1, 222, 32, 4008, 1, 4294967295, 4294967295, 1, 222, 32, 4009, 1, 4294967295, 4294967295, 1, 222, 32, 4010, 1, 4294967295, 4294967295, 1, 222, 32, 4011, 1, 4294967295, 4294967295, 1, 222, 32, 4012, 1, 4294967295, 4294967295, 1, 222, 8, 4013, 1, 4294967295, 4294967295, 3, 222, 8, 4014, 65, 3029, 4294967295, 8, 222, 8, 4079, 1, 4294967295, 4294967295, 1, 223, 8, 4080, 1, 4294967295, 4294967295, 1, 223, 8, 4081, 1, 4294967295, 4294967295, 3, 223, 8, 4082, 2, 3033, 4294967295, 8, 223, 8, 4084, 1, 4294967295, 4294967295, 1, 224, 8, 4085, 1, 4294967295, 4294967295, 1, 224, 8, 4086, 1, 4294967295, 4294967295, 1, 224, 32, 4087, 1, 4294967295, 4294967295, 3, 224, 8, 4088, 3, 3038, 4294967295, 8, 224, 8, 4091, 1, 4294967295, 4294967295, 1, 225, 32, 4092, 1, 4294967295, 4294967295, 1, 225, 8, 4093, 1, 4294967295, 4294967295, 1, 226, 32, 4094, 1, 4294967295, 4294967295, 1, 226, 8, 4095, 1, 4294967295, 4294967295, 1, 227, 32, 4096, 1, 4294967295, 4294967295, 1, 227, 8, 4097, 1, 4294967295, 4294967295, 1, 228, 32, 4098, 1, 4294967295, 4294967295, 1, 228, 8, 4099, 1, 4294967295, 4294967295, 1, 229, 8, 4100, 1, 4294967295, 4294967295, 1, 229, 8, 4101, 1, 4294967295, 4294967295, 3, 229, 8, 4102, 2, 3050, 4294967295, 8, 229, 8, 4104, 1, 4294967295, 4294967295, 1, 230, 32, 4105, 1, 4294967295, 4294967295, 1, 230, 8, 4106, 1, 4294967295, 4294967295, 1, 231, 32, 4107, 1, 4294967295, 4294967295, 1, 231, 8, 4108, 1, 4294967295, 4294967295, 1, 232, 32, 4109, 1, 4294967295, 4294967295, 1, 232, 32, 4110, 1, 4294967295, 4294967295, 1, 232, 32, 4111, 1, 4294967295, 4294967295, 1, 232, 32, 4112, 1, 4294967295, 4294967295, 1, 232, 32, 4113, 1, 4294967295, 4294967295, 1, 232, 32, 4114, 1, 4294967295, 4294967295, 1, 232, 32, 4115, 1, 4294967295, 4294967295, 1, 232, 32, 4116, 1, 4294967295, 4294967295, 1, 232, 32, 4117, 1, 4294967295, 4294967295, 1, 232, 32, 4118, 1, 4294967295, 4294967295, 1, 232, 32, 4119, 1, 4294967295, 4294967295, 1, 232, 32, 4120, 1, 4294967295, 4294967295, 1, 232, 32, 4121, 1, 4294967295, 4294967295, 1, 232, 32, 4122, 1, 4294967295, 4294967295, 1, 232, 32, 4123, 1, 4294967295, 4294967295, 1, 232, 32, 4124, 1, 4294967295, 4294967295, 1, 232, 32, 4125, 1, 4294967295, 4294967295, 1, 232, 32, 4126, 1, 4294967295, 4294967295, 1, 232, 32, 4127, 1, 4294967295, 4294967295, 1, 232, 32, 4128, 1, 4294967295, 4294967295, 1, 232, 32, 4129, 1, 4294967295, 4294967295, 1, 232, 32, 4130, 1, 4294967295, 4294967295, 1, 232, 32, 4131, 1, 4294967295, 4294967295, 1, 232, 32, 4132, 1, 4294967295, 4294967295, 1, 232, 32, 4133, 1, 4294967295, 4294967295, 1, 232, 8, 4134, 1, 4294967295, 4294967295, 1, 232, 8, 4135, 1, 4294967295, 4294967295, 1, 232, 8, 4136, 1, 4294967295, 4294967295, 1, 232, 8, 4137, 1, 4294967295, 4294967295, 1, 232, 32, 4138, 1, 4294967295, 4294967295, 1, 232, 32, 4139, 1, 4294967295, 4294967295, 1, 232, 32, 4140, 1, 4294967295, 4294967295, 1, 232, 32, 4141, 1, 4294967295, 4294967295, 1, 232, 32, 4142, 1, 4294967295, 4294967295, 1, 232, 32, 4143, 1, 4294967295, 4294967295, 1, 232, 32, 4144, 1, 4294967295, 4294967295, 1, 232, 32, 4145, 1, 4294967295, 4294967295, 1, 232, 32, 4146, 1, 4294967295, 4294967295, 1, 232, 32, 4147, 1, 4294967295, 4294967295, 3, 232, 8, 4148, 39, 3095, 4294967295, 8, 232, 8, 4187, 1, 4294967295, 4294967295, 1, 233, 32, 4188, 1, 4294967295, 4294967295, 1, 233, 8, 4189, 1, 4294967295, 4294967295, 1, 234, 32, 4190, 1, 4294967295, 4294967295, 1, 234, 8, 4191, 1, 4294967295, 4294967295, 1, 235, 32, 4192, 1, 4294967295, 4294967295, 1, 235, 8, 4193, 1, 4294967295, 4294967295, 1, 236, 32, 4194, 1, 4294967295, 4294967295, 1, 236, 8, 4195, 1, 4294967295, 4294967295, 1, 237, 32, 4196, 1, 4294967295, 4294967295, 1, 237, 8, 4197, 1, 4294967295, 4294967295, 1, 238, 32, 4198, 1, 4294967295, 4294967295, 1, 238, 32, 4199, 1, 4294967295, 4294967295, 1, 238, 72, 4200, 1, 4294967295, 4294967295, 1, 238, 8, 4201, 1, 4294967295, 4294967295, 1, 239, 32, 4202, 1, 4294967295, 4294967295, 1, 239, 32, 4203, 1, 4294967295, 4294967295, 1, 239, 72, 4204, 1, 4294967295, 4294967295, 1, 239, 32, 4205, 1, 4294967295, 4294967295, 1, 239, 72, 4206, 1, 4294967295, 4294967295, 1, 239, 8, 4207, 1, 4294967295, 4294967295, 1, 240, 32, 4208, 1, 4294967295, 4294967295, 1, 240, 32, 4209, 1, 4294967295, 4294967295, 1, 240, 72, 4210, 1, 4294967295, 4294967295, 1, 240, 8, 4211, 1, 4294967295, 4294967295, 1, 241, 32, 4212, 1, 4294967295, 4294967295, 1, 241, 32, 4213, 1, 4294967295, 4294967295, 1, 241, 72, 4214, 1, 4294967295, 4294967295, 1, 241, 32, 4215, 1, 4294967295, 4294967295, 1, 241, 72, 4216, 1, 4294967295, 4294967295, 1, 241, 8, 4217, 1, 4294967295, 4294967295, 1, 242, 8, 4218, 1, 4294967295, 4294967295, 1, 242, 8, 4219, 1, 4294967295, 4294967295, 1, 242, 32, 4220, 1, 4294967295, 4294967295, 1, 242, 8, 4221, 1, 4294967295, 4294967295, 5, 242, 8, 4222, 1, 3131, 4294967295, 8, 242, 8, 4223, 1, 4294967295, 4294967295, 10, 242, 8, 4224, 2, 4294967295, 4294967295, 12, 242, 8, 4226, 1, 4294967295, 3134, 9, 242, 8, 4227, 1, 4294967295, 4294967295, 1, 243, 8, 4228, 1, 4294967295, 4294967295, 1, 243, 8, 4229, 1, 4294967295, 4294967295, 3, 243, 8, 4230, 2, 3138, 4294967295, 8, 243, 8, 4232, 1, 4294967295, 4294967295, 1, 243, 0, 4233, 0, 4294967295, 4294967295, 1, 491, 0, 0, 0, 1, 514, 0, 0, 0, 1, 490, 0, 0, 0, 1, 1067, 0, 0, 0, 1, 1100, 0, 0, 0, 1, 520, 0, 0, 0, 1, 496, 0, 0, 0, 1, 1073, 0, 0, 0, 1, 1106, 0, 0, 0, 1, 533, 0, 0, 0, 1, 529, 0, 0, 0, 1, 617, 0, 0, 0, 1, 2562, 0, 0, 0, 1, 538, 0, 0, 0, 1, 534, 0, 0, 0, 1, 575, 0, 0, 0, 1, 581, 0, 0, 0, 1, 626, 0, 0, 0, 1, 933, 0, 0, 0, 1, 1775, 0, 0, 0, 1, 1835, 0, 0, 0, 1, 540, 0, 0, 0, 1, 502, 0, 0, 0, 1, 647, 0, 0, 0, 1, 703, 0, 0, 0, 1, 725, 0, 0, 0, 1, 762, 0, 0, 0, 1, 805, 0, 0, 0, 1, 823, 0, 0, 0, 1, 855, 0, 0, 0, 1, 877, 0, 0, 0, 1, 922, 0, 0, 0, 1, 983, 0, 0, 0, 1, 1052, 0, 0, 0, 1, 1085, 0, 0, 0, 1, 1127, 0, 0, 0, 1, 1158, 0, 0, 0, 1, 1178, 0, 0, 0, 1, 1213, 0, 0, 0, 1, 1248, 0, 0, 0, 1, 1303, 0, 0, 0, 1, 1327, 0, 0, 0, 1, 1369, 0, 0, 0, 1, 1403, 0, 0, 0, 1, 1445, 0, 0, 0, 1, 1490, 0, 0, 0, 1, 1532, 0, 0, 0, 1, 1574, 0, 0, 0, 1, 1601, 0, 0, 0, 1, 1703, 0, 0, 0, 1, 1768, 0, 0, 0, 1, 1780, 0, 0, 0, 1, 1793, 0, 0, 0, 1, 1811, 0, 0, 0, 1, 1828, 0, 0, 0, 1, 1840, 0, 0, 0, 1, 1854, 0, 0, 0, 1, 1862, 0, 0, 0, 1, 1871, 0, 0, 0, 1, 1883, 0, 0, 0, 1, 1924, 0, 0, 0, 1, 1939, 0, 0, 0, 1, 1956, 0, 0, 0, 1, 1966, 0, 0, 0, 1, 1987, 0, 0, 0, 1, 2017, 0, 0, 0, 1, 2029, 0, 0, 0, 1, 2041, 0, 0, 0, 1, 2244, 0, 0, 0, 1, 2256, 0, 0, 0, 1, 2297, 0, 0, 0, 1, 2306, 0, 0, 0, 1, 2324, 0, 0, 0, 1, 2336, 0, 0, 0, 1, 2506, 0, 0, 0, 1, 2527, 0, 0, 0, 1, 554, 0, 0, 0, 1, 543, 0, 0, 0, 1, 557, 0, 0, 0, 1, 549, 0, 0, 0, 1, 548, 0, 0, 0, 1, 564, 0, 0, 0, 1, 559, 0, 0, 0, 1, 851, 0, 0, 0, 1, 1064, 0, 0, 0, 1, 1097, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 574, 0, 0, 0, 1, 565, 0, 0, 0, 1, 580, 0, 0, 0, 1, 565, 0, 0, 0, 1, 570, 0, 0, 0, 1, 577, 0, 0, 0, 1, 2478, 0, 0, 0, 1, 2790, 0, 0, 0, 1, 582, 0, 0, 0, 1, 581, 0, 0, 0, 1, 585, 0, 0, 0, 1, 584, 0, 0, 0, 1, 602, 0, 0, 0, 1, 560, 0, 0, 0, 1, 621, 0, 0, 0, 1, 608, 0, 0, 0, 1, 607, 0, 0, 0, 1, 625, 0, 0, 0, 1, 620, 0, 0, 0, 1, 692, 0, 0, 0, 1, 2186, 0, 0, 0, 1, 639, 0, 0, 0, 1, 508, 0, 0, 0, 1, 1079, 0, 0, 0, 1, 1112, 0, 0, 0, 1, 1357, 0, 0, 0, 1, 1395, 0, 0, 0, 1, 1433, 0, 0, 0, 1, 1478, 0, 0, 0, 1, 1520, 0, 0, 0, 1, 1562, 0, 0, 0, 1, 643, 0, 0, 0, 1, 640, 0, 0, 0, 1, 648, 0, 0, 0, 1, 644, 0, 0, 0, 1, 661, 0, 0, 0, 1, 653, 0, 0, 0, 1, 709, 0, 0, 0, 1, 731, 0, 0, 0, 1, 772, 0, 0, 0, 1, 829, 0, 0, 0, 1, 861, 0, 0, 0, 1, 883, 0, 0, 0, 1, 989, 0, 0, 0, 1, 1058, 0, 0, 0, 1, 1091, 0, 0, 0, 1, 1133, 0, 0, 0, 1, 1164, 0, 0, 0, 1, 1184, 0, 0, 0, 1, 1219, 0, 0, 0, 1, 1254, 0, 0, 0, 1, 1309, 0, 0, 0, 1, 1333, 0, 0, 0, 1, 1375, 0, 0, 0, 1, 1409, 0, 0, 0, 1, 1451, 0, 0, 0, 1, 1496, 0, 0, 0, 1, 1538, 0, 0, 0, 1, 1580, 0, 0, 0, 1, 1607, 0, 0, 0, 1, 1709, 0, 0, 0, 1, 1978, 0, 0, 0, 1, 1993, 0, 0, 0, 1, 2488, 0, 0, 0, 1, 2512, 0, 0, 0, 1, 2533, 0, 0, 0, 1, 3029, 0, 0, 0, 1, 663, 0, 0, 0, 1, 659, 0, 0, 0, 1, 714, 0, 0, 0, 1, 1878, 0, 0, 0, 1, 1891, 0, 0, 0, 1, 2318, 0, 0, 0, 1, 672, 0, 0, 0, 1, 669, 0, 0, 0, 1, 668, 0, 0, 0, 1, 679, 0, 0, 0, 1, 675, 0, 0, 0, 1, 2478, 0, 0, 0, 1, 2661, 0, 0, 0, 1, 2676, 0, 0, 0, 1, 691, 0, 0, 0, 1, 685, 0, 0, 0, 1, 684, 0, 0, 0, 1, 796, 0, 0, 0, 1, 795, 0, 0, 0, 1, 2936, 0, 0, 0, 1, 2937, 0, 0, 0, 1, 698, 0, 0, 0, 1, 678, 0, 0, 0, 1, 785, 0, 0, 0, 1, 1230, 0, 0, 0, 1, 1237, 0, 0, 0, 1, 1316, 0, 0, 0, 1, 3138, 0, 0, 0, 1, 704, 0, 0, 0, 1, 644, 0, 0, 0, 1, 721, 0, 0, 0, 1, 640, 0, 0, 0, 1, 726, 0, 0, 0, 1, 722, 0, 0, 0, 1, 747, 0, 0, 0, 1, 738, 0, 0, 0, 1, 848, 0, 0, 0, 1, 873, 0, 0, 0, 1, 899, 0, 0, 0, 1, 1044, 0, 0, 0, 1, 1344, 0, 0, 0, 1, 1385, 0, 0, 0, 1, 1420, 0, 0, 0, 1, 1465, 0, 0, 0, 1, 1507, 0, 0, 0, 1, 1549, 0, 0, 0, 1, 1594, 0, 0, 0, 1, 2006, 0, 0, 0, 1, 2495, 0, 0, 0, 1, 2520, 0, 0, 0, 1, 763, 0, 0, 0, 1, 753, 0, 0, 0, 1, 752, 0, 0, 0, 1, 1206, 0, 0, 0, 1, 1205, 0, 0, 0, 1, 786, 0, 0, 0, 1, 739, 0, 0, 0, 1, 790, 0, 0, 0, 1, 789, 0, 0, 0, 1, 1298, 0, 0, 0, 1, 2478, 0, 0, 0, 1, 2596, 0, 0, 0, 1, 2602, 0, 0, 0, 1, 2651, 0, 0, 0, 1, 806, 0, 0, 0, 1, 746, 0, 0, 0, 1, 849, 0, 0, 0, 1, 874, 0, 0, 0, 1, 908, 0, 0, 0, 1, 1045, 0, 0, 0, 1, 1175, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1786, 0, 0, 0, 1, 2014, 0, 0, 0, 1, 2265, 0, 0, 0, 1, 2279, 0, 0, 0, 1, 2294, 0, 0, 0, 1, 2303, 0, 0, 0, 1, 2498, 0, 0, 0, 1, 2524, 0, 0, 0, 1, 2542, 0, 0, 0, 1, 818, 0, 0, 0, 1, 742, 0, 0, 0, 1, 845, 0, 0, 0, 1, 870, 0, 0, 0, 1, 904, 0, 0, 0, 1, 1041, 0, 0, 0, 1, 1171, 0, 0, 0, 1, 1196, 0, 0, 0, 1, 1237, 0, 0, 0, 1, 2011, 0, 0, 0, 1, 824, 0, 0, 0, 1, 722, 0, 0, 0, 1, 850, 0, 0, 0, 1, 836, 0, 0, 0, 1, 890, 0, 0, 0, 1, 996, 0, 0, 0, 1, 1141, 0, 0, 0, 1, 1191, 0, 0, 0, 1, 1226, 0, 0, 0, 1, 856, 0, 0, 0, 1, 722, 0, 0, 0, 1, 878, 0, 0, 0, 1, 722, 0, 0, 0, 1, 909, 0, 0, 0, 1, 894, 0, 0, 0, 1, 1341, 0, 0, 0, 1, 1382, 0, 0, 0, 1, 1417, 0, 0, 0, 1, 1462, 0, 0, 0, 1, 1504, 0, 0, 0, 1, 1546, 0, 0, 0, 1, 1589, 0, 0, 0, 1, 2001, 0, 0, 0, 1, 923, 0, 0, 0, 1, 915, 0, 0, 0, 1, 914, 0, 0, 0, 1, 931, 0, 0, 0, 1, 898, 0, 0, 0, 1, 1350, 0, 0, 0, 1, 1388, 0, 0, 0, 1, 1426, 0, 0, 0, 1, 1471, 0, 0, 0, 1, 1513, 0, 0, 0, 1, 1555, 0, 0, 0, 1, 1593, 0, 0, 0, 1, 2005, 0, 0, 0, 1, 947, 0, 0, 0, 1, 939, 0, 0, 0, 1, 938, 0, 0, 0, 1, 949, 0, 0, 0, 1, 948, 0, 0, 0, 1, 958, 0, 0, 0, 1, 955, 0, 0, 0, 1, 954, 0, 0, 0, 1, 960, 0, 0, 0, 1, 959, 0, 0, 0, 1, 971, 0, 0, 0, 1, 948, 0, 0, 0, 1, 973, 0, 0, 0, 1, 948, 0, 0, 0, 1, 977, 0, 0, 0, 1, 948, 0, 0, 0, 1, 979, 0, 0, 0, 1, 948, 0, 0, 0, 1, 984, 0, 0, 0, 1, 722, 0, 0, 0, 1, 1048, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1053, 0, 0, 0, 1, 1049, 0, 0, 0, 1, 1086, 0, 0, 0, 1, 1049, 0, 0, 0, 1, 1123, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1128, 0, 0, 0, 1, 1124, 0, 0, 0, 1, 1147, 0, 0, 0, 1, 1146, 0, 0, 0, 1, 1199, 0, 0, 0, 1, 1232, 0, 0, 0, 1, 1159, 0, 0, 0, 1, 1150, 0, 0, 0, 1, 1179, 0, 0, 0, 1, 1124, 0, 0, 0, 1, 1200, 0, 0, 0, 1, 1198, 0, 0, 0, 1, 1214, 0, 0, 0, 1, 1124, 0, 0, 0, 1, 1244, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1249, 0, 0, 0, 1, 1245, 0, 0, 0, 1, 1283, 0, 0, 0, 1, 1262, 0, 0, 0, 1, 1347, 0, 0, 0, 1, 1423, 0, 0, 0, 1, 1468, 0, 0, 0, 1, 1510, 0, 0, 0, 1, 1552, 0, 0, 0, 1, 1294, 0, 0, 0, 1, 1289, 0, 0, 0, 1, 1288, 0, 0, 0, 1, 1296, 0, 0, 0, 1, 1295, 0, 0, 0, 1, 1299, 0, 0, 0, 1, 1295, 0, 0, 0, 1, 1304, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1269, 0, 0, 0, 1, 1268, 0, 0, 0, 1, 1323, 0, 0, 0, 1, 1245, 0, 0, 0, 1, 1328, 0, 0, 0, 1, 1324, 0, 0, 0, 1, 1370, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1324, 0, 0, 0, 1, 1404, 0, 0, 0, 1, 1324, 0, 0, 0, 1, 1446, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1324, 0, 0, 0, 1, 1491, 0, 0, 0, 1, 1324, 0, 0, 0, 1, 1533, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1324, 0, 0, 0, 1, 1575, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1602, 0, 0, 0, 1, 640, 0, 0, 0, 1, 1620, 0, 0, 0, 1, 531, 0, 0, 0, 1, 588, 0, 0, 0, 1, 592, 0, 0, 0, 1, 664, 0, 0, 0, 1, 778, 0, 0, 0, 1, 842, 0, 0, 0, 1, 889, 0, 0, 0, 1, 980, 0, 0, 0, 1, 995, 0, 0, 0, 1, 1140, 0, 0, 0, 1, 1190, 0, 0, 0, 1, 1225, 0, 0, 0, 1, 1297, 0, 0, 0, 1, 1300, 0, 0, 0, 1, 1586, 0, 0, 0, 1, 1639, 0, 0, 0, 1, 1714, 0, 0, 0, 1, 1722, 0, 0, 0, 1, 1725, 0, 0, 0, 1, 1738, 0, 0, 0, 1, 1803, 0, 0, 0, 1, 1998, 0, 0, 0, 1, 2105, 0, 0, 0, 1, 2155, 0, 0, 0, 1, 2225, 0, 0, 0, 1, 2283, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2518, 0, 0, 0, 1, 2601, 0, 0, 0, 1, 2608, 0, 0, 0, 1, 2653, 0, 0, 0, 1, 2658, 0, 0, 0, 1, 2821, 0, 0, 0, 1, 2846, 0, 0, 0, 1, 2910, 0, 0, 0, 1, 2915, 0, 0, 0, 1, 2920, 0, 0, 0, 1, 2945, 0, 0, 0, 1, 3127, 0, 0, 0, 1, 1637, 0, 0, 0, 1, 2568, 0, 0, 0, 1, 1643, 0, 0, 0, 1, 1625, 0, 0, 0, 1, 1640, 0, 0, 0, 1, 1660, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 1675, 0, 0, 0, 1, 1664, 0, 0, 0, 1, 1677, 0, 0, 0, 1, 1670, 0, 0, 0, 1, 1674, 0, 0, 0, 1, 1688, 0, 0, 0, 1, 1683, 0, 0, 0, 1, 1682, 0, 0, 0, 1, 1690, 0, 0, 0, 1, 1666, 0, 0, 0, 1, 1704, 0, 0, 0, 1, 1696, 0, 0, 0, 1, 1695, 0, 0, 0, 1, 1715, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 1717, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 1723, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 1726, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 1736, 0, 0, 0, 1, 1730, 0, 0, 0, 1, 1731, 0, 0, 0, 1, 1764, 0, 0, 0, 1, 812, 0, 0, 0, 1, 1612, 0, 0, 0, 1, 1808, 0, 0, 0, 1, 1825, 0, 0, 0, 1, 1846, 0, 0, 0, 1, 1880, 0, 0, 0, 1, 1921, 0, 0, 0, 1, 1949, 0, 0, 0, 1, 1953, 0, 0, 0, 1, 1963, 0, 0, 0, 1, 2026, 0, 0, 0, 1, 2065, 0, 0, 0, 1, 2321, 0, 0, 0, 1, 2333, 0, 0, 0, 1, 1769, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1781, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1789, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1794, 0, 0, 0, 1, 1790, 0, 0, 0, 1, 1812, 0, 0, 0, 1, 1790, 0, 0, 0, 1, 1829, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1841, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1855, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1863, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1872, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1884, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1925, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1940, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1951, 0, 0, 0, 1, 1950, 0, 0, 0, 1, 1957, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1967, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1988, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2018, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2030, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2042, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2059, 0, 0, 0, 1, 2052, 0, 0, 0, 1, 2071, 0, 0, 0, 1, 2060, 0, 0, 0, 1, 2073, 0, 0, 0, 1, 2072, 0, 0, 0, 1, 2092, 0, 0, 0, 1, 2076, 0, 0, 0, 1, 2098, 0, 0, 0, 1, 2137, 0, 0, 0, 1, 2136, 0, 0, 0, 1, 2151, 0, 0, 0, 1, 2182, 0, 0, 0, 1, 2223, 0, 0, 0, 1, 2228, 0, 0, 0, 1, 2478, 0, 0, 0, 1, 2924, 0, 0, 0, 1, 2102, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2104, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2110, 0, 0, 0, 1, 2106, 0, 0, 0, 1, 2120, 0, 0, 0, 1, 2119, 0, 0, 0, 1, 2148, 0, 0, 0, 1, 2164, 0, 0, 0, 1, 2231, 0, 0, 0, 1, 2654, 0, 0, 0, 1, 2112, 0, 0, 0, 1, 2111, 0, 0, 0, 1, 2114, 0, 0, 0, 1, 2111, 0, 0, 0, 1, 2127, 0, 0, 0, 1, 2111, 0, 0, 0, 1, 2129, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2131, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2149, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2154, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2165, 0, 0, 0, 1, 2158, 0, 0, 0, 1, 2179, 0, 0, 0, 1, 2171, 0, 0, 0, 1, 2170, 0, 0, 0, 1, 2196, 0, 0, 0, 1, 2195, 0, 0, 0, 1, 2185, 0, 0, 0, 1, 2180, 0, 0, 0, 1, 2187, 0, 0, 0, 1, 2186, 0, 0, 0, 1, 2190, 0, 0, 0, 1, 2161, 0, 0, 0, 1, 2218, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2220, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2224, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2226, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2229, 0, 0, 0, 1, 2093, 0, 0, 0, 1, 2232, 0, 0, 0, 1, 2077, 0, 0, 0, 1, 2925, 0, 0, 0, 1, 2235, 0, 0, 0, 1, 2072, 0, 0, 0, 1, 2239, 0, 0, 0, 1, 2072, 0, 0, 0, 1, 2245, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2257, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2271, 0, 0, 0, 1, 2264, 0, 0, 0, 1, 2280, 0, 0, 0, 1, 2274, 0, 0, 0, 1, 2287, 0, 0, 0, 1, 2277, 0, 0, 0, 1, 2292, 0, 0, 0, 1, 2270, 0, 0, 0, 1, 2298, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2307, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2325, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2337, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 2386, 0, 0, 0, 1, 624, 0, 0, 0, 1, 697, 0, 0, 0, 1, 700, 0, 0, 0, 1, 820, 0, 0, 0, 1, 1646, 0, 0, 0, 1, 1650, 0, 0, 0, 1, 1806, 0, 0, 0, 1, 1821, 0, 0, 0, 1, 1823, 0, 0, 0, 1, 1849, 0, 0, 0, 1, 1867, 0, 0, 0, 1, 1897, 0, 0, 0, 1, 1896, 0, 0, 0, 1, 1907, 0, 0, 0, 1, 1914, 0, 0, 0, 1, 1913, 0, 0, 0, 1, 1934, 0, 0, 0, 1, 1946, 0, 0, 0, 1, 2024, 0, 0, 0, 1, 2036, 0, 0, 0, 1, 2048, 0, 0, 0, 1, 2103, 0, 0, 0, 1, 2188, 0, 0, 0, 1, 2219, 0, 0, 0, 1, 2234, 0, 0, 0, 1, 2237, 0, 0, 0, 1, 2251, 0, 0, 0, 1, 2290, 0, 0, 0, 1, 2318, 0, 0, 0, 1, 2331, 0, 0, 0, 1, 2344, 0, 0, 0, 1, 2374, 0, 0, 0, 1, 2478, 0, 0, 0, 1, 2437, 0, 0, 0, 1, 2439, 0, 0, 0, 1, 2456, 0, 0, 0, 1, 2499, 0, 0, 0, 1, 2524, 0, 0, 0, 1, 2542, 0, 0, 0, 1, 2564, 0, 0, 0, 1, 2576, 0, 0, 0, 1, 2575, 0, 0, 0, 1, 2588, 0, 0, 0, 1, 2610, 0, 0, 0, 1, 2614, 0, 0, 0, 1, 2619, 0, 0, 0, 1, 2645, 0, 0, 0, 1, 2648, 0, 0, 0, 1, 2735, 0, 0, 0, 1, 2744, 0, 0, 0, 1, 2786, 0, 0, 0, 1, 2793, 0, 0, 0, 1, 2814, 0, 0, 0, 1, 2825, 0, 0, 0, 1, 2850, 0, 0, 0, 1, 2852, 0, 0, 0, 1, 2855, 0, 0, 0, 1, 2864, 0, 0, 0, 1, 2876, 0, 0, 0, 1, 2880, 0, 0, 0, 1, 2887, 0, 0, 0, 1, 2889, 0, 0, 0, 1, 2892, 0, 0, 0, 1, 2899, 0, 0, 0, 1, 2903, 0, 0, 0, 1, 2908, 0, 0, 0, 1, 2928, 0, 0, 0, 1, 2931, 0, 0, 0, 1, 2950, 0, 0, 0, 1, 2484, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2489, 0, 0, 0, 1, 2485, 0, 0, 0, 1, 2502, 0, 0, 0, 1, 2485, 0, 0, 0, 1, 2507, 0, 0, 0, 1, 2503, 0, 0, 0, 1, 2528, 0, 0, 0, 1, 2503, 0, 0, 0, 1, 2543, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2561, 0, 0, 0, 1, 2550, 0, 0, 0, 1, 2549, 0, 0, 0, 1, 2565, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2570, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2478, 0, 0, 0, 1, 2569, 0, 0, 0, 1, 2597, 0, 0, 0, 1, 2605, 0, 0, 0, 1, 2674, 0, 0, 0, 1, 2681, 0, 0, 0, 1, 2921, 0, 0, 0, 1, 2586, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2591, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2593, 0, 0, 0, 1, 2592, 0, 0, 0, 1, 2598, 0, 0, 0, 1, 2592, 0, 0, 0, 1, 2606, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2621, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2623, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2642, 0, 0, 0, 1, 2629, 0, 0, 0, 1, 2628, 0, 0, 0, 1, 2644, 0, 0, 0, 1, 2643, 0, 0, 0, 1, 2646, 0, 0, 0, 1, 2643, 0, 0, 0, 1, 2649, 0, 0, 0, 1, 2643, 0, 0, 0, 1, 2652, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2655, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2660, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2662, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2664, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2675, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2677, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2684, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2686, 0, 0, 0, 1, 2685, 0, 0, 0, 1, 2688, 0, 0, 0, 1, 2685, 0, 0, 0, 1, 2724, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2728, 0, 0, 0, 1, 2693, 0, 0, 0, 1, 2701, 0, 0, 0, 1, 2709, 0, 0, 0, 1, 2718, 0, 0, 0, 1, 2730, 0, 0, 0, 1, 2729, 0, 0, 0, 1, 2732, 0, 0, 0, 1, 2729, 0, 0, 0, 1, 2742, 0, 0, 0, 1, 2736, 0, 0, 0, 1, 2745, 0, 0, 0, 1, 2739, 0, 0, 0, 1, 2748, 0, 0, 0, 1, 2710, 0, 0, 0, 1, 2750, 0, 0, 0, 1, 2714, 0, 0, 0, 1, 2723, 0, 0, 0, 1, 2757, 0, 0, 0, 1, 2719, 0, 0, 0, 1, 2772, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2774, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2777, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2780, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2783, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2788, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2791, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2813, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2815, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2818, 0, 0, 0, 1, 2816, 0, 0, 0, 1, 2842, 0, 0, 0, 1, 2829, 0, 0, 0, 1, 2817, 0, 0, 0, 1, 2896, 0, 0, 0, 1, 2841, 0, 0, 0, 1, 2828, 0, 0, 0, 1, 2843, 0, 0, 0, 1, 2842, 0, 0, 0, 1, 2857, 0, 0, 0, 1, 2856, 0, 0, 0, 1, 2860, 0, 0, 0, 1, 2842, 0, 0, 0, 1, 2865, 0, 0, 0, 1, 2842, 0, 0, 0, 1, 2874, 0, 0, 0, 1, 2871, 0, 0, 0, 1, 2870, 0, 0, 0, 1, 2878, 0, 0, 0, 1, 2842, 0, 0, 0, 1, 2883, 0, 0, 0, 1, 2834, 0, 0, 0, 1, 2885, 0, 0, 0, 1, 2884, 0, 0, 0, 1, 2890, 0, 0, 0, 1, 2884, 0, 0, 0, 1, 2893, 0, 0, 0, 1, 2835, 0, 0, 0, 1, 2897, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2900, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2905, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2912, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2917, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2922, 0, 0, 0, 1, 2465, 0, 0, 0, 1, 2464, 0, 0, 0, 1, 2929, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2932, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2942, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2947, 0, 0, 0, 1, 2387, 0, 0, 0, 1, 2959, 0, 0, 0, 1, 555, 0, 0, 0, 1, 2961, 0, 0, 0, 1, 517, 0, 0, 0, 1, 539, 0, 0, 0, 1, 583, 0, 0, 0, 1, 674, 0, 0, 0, 1, 736, 0, 0, 0, 1, 782, 0, 0, 0, 1, 867, 0, 0, 0, 1, 893, 0, 0, 0, 1, 930, 0, 0, 0, 1, 1145, 0, 0, 0, 1, 1240, 0, 0, 0, 1, 1261, 0, 0, 0, 1, 1315, 0, 0, 0, 1, 1340, 0, 0, 0, 1, 1416, 0, 0, 0, 1, 1461, 0, 0, 0, 1, 1503, 0, 0, 0, 1, 1545, 0, 0, 0, 1, 1588, 0, 0, 0, 1, 1689, 0, 0, 0, 1, 1739, 0, 0, 0, 1, 1804, 0, 0, 0, 1, 1961, 0, 0, 0, 1, 2000, 0, 0, 0, 1, 2284, 0, 0, 0, 1, 2538, 0, 0, 0, 1, 2823, 0, 0, 0, 1, 2848, 0, 0, 0, 1, 2859, 0, 0, 0, 1, 2862, 0, 0, 0, 1, 2895, 0, 0, 0, 1, 2960, 0, 0, 0, 1, 3137, 0, 0, 0, 1, 3028, 0, 0, 0, 1, 2960, 0, 0, 0, 1, 3032, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2960, 0, 0, 0, 1, 3037, 0, 0, 0, 1, 3033, 0, 0, 0, 1, 3039, 0, 0, 0, 1, 3038, 0, 0, 0, 1, 3041, 0, 0, 0, 1, 3038, 0, 0, 0, 1, 3043, 0, 0, 0, 1, 3033, 0, 0, 0, 1, 3045, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2960, 0, 0, 0, 1, 3049, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2781, 0, 0, 0, 1, 2960, 0, 0, 0, 1, 3051, 0, 0, 0, 1, 3050, 0, 0, 0, 1, 3053, 0, 0, 0, 1, 3050, 0, 0, 0, 1, 3094, 0, 0, 0, 1, 2960, 0, 0, 0, 1, 3096, 0, 0, 0, 1, 2960, 0, 0, 0, 1, 3098, 0, 0, 0, 1, 2731, 0, 0, 0, 1, 2747, 0, 0, 0, 1, 3100, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2775, 0, 0, 0, 1, 3102, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2778, 0, 0, 0, 1, 3104, 0, 0, 0, 1, 1457, 0, 0, 0, 1, 3106, 0, 0, 0, 1, 1037, 0, 0, 0, 1, 2429, 0, 0, 0, 1, 3095, 0, 0, 0, 1, 3110, 0, 0, 0, 1, 1037, 0, 0, 0, 1, 2429, 0, 0, 0, 1, 3095, 0, 0, 0, 1, 3116, 0, 0, 0, 1, 1037, 0, 0, 0, 1, 2403, 0, 0, 0, 1, 3095, 0, 0, 0, 1, 3120, 0, 0, 0, 1, 1037, 0, 0, 0, 1, 2403, 0, 0, 0, 1, 3095, 0, 0, 0, 1, 3126, 0, 0, 0, 1, 1983, 0, 0, 0, 1, 3135, 0, 0, 0, 1, 3132, 0, 0, 0, 1, 3131, 0, 0, 0, 3, 2, 1, 490, 0, 1, 488, 0, 0, 0, 1, 493, 0, 0, 0, 1, 489, 0, 0, 0, 1, 492, 0, 0, 0, 1, 497, 0, 0, 0, 1, 491, 0, 0, 0, 3, 4, 2, 496, 0, 1, 494, 0, 0, 0, 1, 499, 0, 0, 0, 1, 495, 0, 0, 0, 1, 498, 0, 0, 0, 1, 503, 0, 0, 0, 1, 497, 0, 0, 0, 3, 10, 5, 502, 0, 1, 500, 0, 0, 0, 1, 505, 0, 0, 0, 1, 501, 0, 0, 0, 1, 504, 0, 0, 0, 1, 509, 0, 0, 0, 1, 503, 0, 0, 0, 3, 32, 16, 508, 0, 1, 506, 0, 0, 0, 1, 511, 0, 0, 0, 1, 507, 0, 0, 0, 1, 510, 0, 0, 0, 1, 512, 0, 0, 0, 1, 509, 0, 0, 0, 5, 513, 4294967295, 0, 0, 1, 1, 0, 0, 0, 5, 515, 41, 0, 0, 5, 516, 59, 0, 0, 3, 442, 221, 517, 0, 5, 518, 167, 0, 0, 1, 3, 0, 0, 0, 5, 521, 42, 0, 0, 1, 519, 0, 0, 0, 1, 521, 0, 0, 0, 1, 522, 0, 0, 0, 5, 528, 77, 0, 0, 5, 529, 52, 0, 0, 5, 526, 57, 0, 0, 1, 524, 0, 0, 0, 1, 526, 0, 0, 0, 1, 527, 0, 0, 0, 3, 6, 3, 529, 0, 1, 523, 0, 0, 0, 1, 525, 0, 0, 0, 1, 529, 0, 0, 0, 1, 530, 0, 0, 0, 3, 152, 76, 531, 0, 5, 532, 167, 0, 0, 1, 5, 0, 0, 0, 3, 8, 4, 534, 0, 5, 535, 169, 0, 0, 1, 7, 0, 0, 0, 5, 539, 42, 0, 0, 259, 442, 221, 539, 0, 1, 536, 0, 0, 0, 1, 537, 0, 0, 0, 1, 9, 0, 0, 0, 5, 542, 202, 0, 0, 3, 12, 6, 543, 0, 1, 541, 0, 0, 0, 1, 543, 0, 0, 0, 1, 544, 0, 0, 0, 3, 14, 7, 549, 0, 5, 546, 163, 0, 0, 3, 14, 7, 548, 0, 1, 545, 0, 0, 0, 1, 551, 0, 0, 0, 1, 547, 0, 0, 0, 1, 550, 0, 0, 0, 1, 552, 0, 0, 0, 1, 549, 0, 0, 0, 5, 553, 203, 0, 0, 1, 11, 0, 0, 0, 3, 440, 220, 555, 0, 5, 556, 199, 0, 0, 1, 13, 0, 0, 0, 3, 16, 8, 559, 0, 259, 26, 13, 560, 0, 1, 558, 0, 0, 0, 1, 560, 0, 0, 0, 1, 15, 0, 0, 0, 6, 562, 8, 4294967295, 0, 3, 18, 9, 565, 0, 3, 20, 10, 565, 0, 1, 561, 0, 0, 0, 1, 563, 0, 0, 0, 1, 571, 0, 0, 0, 10, 567, 2, 0, 0, 5, 568, 165, 0, 0, 3, 20, 10, 570, 0, 1, 566, 0, 0, 0, 1, 573, 0, 0, 0, 1, 569, 0, 0, 0, 1, 572, 0, 0, 0, 1, 17, 0, 0, 0, 1, 571, 0, 0, 0, 3, 8, 4, 575, 0, 5, 576, 133, 0, 0, 259, 20, 10, 577, 0, 1, 19, 0, 0, 0, 259, 22, 11, 581, 0, 259, 8, 4, 581, 0, 1, 578, 0, 0, 0, 1, 579, 0, 0, 0, 1, 21, 0, 0, 0, 3, 442, 221, 583, 0, 259, 24, 12, 584, 0, 1, 23, 0, 0, 0, 5, 598, 168, 0, 0, 3, 152, 76, 588, 0, 1, 586, 0, 0, 0, 1, 588, 0, 0, 0, 1, 595, 0, 0, 0, 5, 591, 163, 0, 0, 3, 152, 76, 592, 0, 1, 590, 0, 0, 0, 1, 592, 0, 0, 0, 1, 594, 0, 0, 0, 1, 589, 0, 0, 0, 1, 597, 0, 0, 0, 1, 593, 0, 0, 0, 1, 596, 0, 0, 0, 1, 599, 0, 0, 0, 1, 595, 0, 0, 0, 1, 587, 0, 0, 0, 1, 599, 0, 0, 0, 1, 600, 0, 0, 0, 5, 601, 170, 0, 0, 1, 25, 0, 0, 0, 5, 611, 200, 0, 0, 3, 28, 14, 608, 0, 5, 605, 163, 0, 0, 3, 28, 14, 607, 0, 1, 604, 0, 0, 0, 1, 610, 0, 0, 0, 1, 606, 0, 0, 0, 1, 609, 0, 0, 0, 1, 612, 0, 0, 0, 1, 608, 0, 0, 0, 1, 603, 0, 0, 0, 1, 612, 0, 0, 0, 1, 613, 0, 0, 0, 5, 614, 201, 0, 0, 1, 27, 0, 0, 0, 3, 6, 3, 617, 0, 1, 615, 0, 0, 0, 1, 617, 0, 0, 0, 1, 622, 0, 0, 0, 3, 30, 15, 620, 0, 1, 618, 0, 0, 0, 1, 620, 0, 0, 0, 1, 622, 0, 0, 0, 1, 616, 0, 0, 0, 1, 619, 0, 0, 0, 1, 623, 0, 0, 0, 259, 296, 148, 624, 0, 1, 29, 0, 0, 0, 3, 8, 4, 626, 0, 5, 627, 199, 0, 0, 1, 31, 0, 0, 0, 259, 34, 17, 640, 0, 259, 142, 71, 640, 0, 259, 146, 73, 640, 0, 259, 138, 69, 640, 0, 259, 52, 26, 640, 0, 259, 100, 50, 640, 0, 259, 106, 53, 640, 0, 259, 120, 60, 640, 0, 259, 148, 74, 640, 0, 259, 132, 66, 640, 0, 259, 150, 75, 640, 0, 1, 628, 0, 0, 0, 1, 629, 0, 0, 0, 1, 630, 0, 0, 0, 1, 631, 0, 0, 0, 1, 632, 0, 0, 0, 1, 633, 0, 0, 0, 1, 634, 0, 0, 0, 1, 635, 0, 0, 0, 1, 636, 0, 0, 0, 1, 637, 0, 0, 0, 1, 638, 0, 0, 0, 1, 33, 0, 0, 0, 259, 36, 18, 644, 0, 259, 50, 25, 644, 0, 1, 641, 0, 0, 0, 1, 642, 0, 0, 0, 1, 35, 0, 0, 0, 3, 10, 5, 647, 0, 1, 645, 0, 0, 0, 1, 650, 0, 0, 0, 1, 646, 0, 0, 0, 1, 649, 0, 0, 0, 1, 654, 0, 0, 0, 1, 648, 0, 0, 0, 3, 38, 19, 653, 0, 1, 651, 0, 0, 0, 1, 656, 0, 0, 0, 1, 652, 0, 0, 0, 1, 655, 0, 0, 0, 1, 657, 0, 0, 0, 1, 654, 0, 0, 0, 5, 658, 66, 0, 0, 3, 40, 20, 659, 0, 5, 660, 167, 0, 0, 1, 37, 0, 0, 0, 7, 662, 0, 0, 0, 1, 39, 0, 0, 0, 3, 152, 76, 664, 0, 3, 42, 21, 669, 0, 5, 666, 163, 0, 0, 3, 42, 21, 668, 0, 1, 665, 0, 0, 0, 1, 671, 0, 0, 0, 1, 667, 0, 0, 0, 1, 670, 0, 0, 0, 1, 41, 0, 0, 0, 1, 669, 0, 0, 0, 3, 442, 221, 674, 0, 3, 44, 22, 675, 0, 1, 673, 0, 0, 0, 1, 675, 0, 0, 0, 1, 677, 0, 0, 0, 259, 48, 24, 678, 0, 1, 676, 0, 0, 0, 1, 678, 0, 0, 0, 1, 43, 0, 0, 0, 5, 680, 202, 0, 0, 3, 46, 23, 685, 0, 5, 682, 163, 0, 0, 3, 46, 23, 684, 0, 1, 681, 0, 0, 0, 1, 687, 0, 0, 0, 1, 683, 0, 0, 0, 1, 686, 0, 0, 0, 1, 688, 0, 0, 0, 1, 685, 0, 0, 0, 5, 689, 203, 0, 0, 1, 45, 0, 0, 0, 3, 30, 15, 692, 0, 1, 690, 0, 0, 0, 1, 692, 0, 0, 0, 1, 694, 0, 0, 0, 7, 695, 1, 0, 0, 1, 693, 0, 0, 0, 1, 695, 0, 0, 0, 1, 696, 0, 0, 0, 259, 296, 148, 697, 0, 1, 47, 0, 0, 0, 5, 699, 169, 0, 0, 259, 296, 148, 700, 0, 1, 49, 0, 0, 0, 3, 10, 5, 703, 0, 1, 701, 0, 0, 0, 1, 706, 0, 0, 0, 1, 702, 0, 0, 0, 1, 705, 0, 0, 0, 1, 710, 0, 0, 0, 1, 704, 0, 0, 0, 3, 38, 19, 709, 0, 1, 707, 0, 0, 0, 1, 712, 0, 0, 0, 1, 708, 0, 0, 0, 1, 711, 0, 0, 0, 1, 713, 0, 0, 0, 1, 710, 0, 0, 0, 3, 40, 20, 714, 0, 5, 715, 167, 0, 0, 1, 51, 0, 0, 0, 259, 54, 27, 722, 0, 259, 68, 34, 722, 0, 259, 72, 36, 722, 0, 259, 74, 37, 722, 0, 259, 98, 49, 722, 0, 1, 716, 0, 0, 0, 1, 717, 0, 0, 0, 1, 718, 0, 0, 0, 1, 719, 0, 0, 0, 1, 720, 0, 0, 0, 1, 53, 0, 0, 0, 3, 10, 5, 725, 0, 1, 723, 0, 0, 0, 1, 728, 0, 0, 0, 1, 724, 0, 0, 0, 1, 727, 0, 0, 0, 1, 732, 0, 0, 0, 1, 726, 0, 0, 0, 3, 38, 19, 731, 0, 1, 729, 0, 0, 0, 1, 734, 0, 0, 0, 1, 730, 0, 0, 0, 1, 733, 0, 0, 0, 1, 735, 0, 0, 0, 1, 732, 0, 0, 0, 3, 442, 221, 736, 0, 3, 56, 28, 738, 0, 3, 60, 30, 739, 0, 1, 737, 0, 0, 0, 1, 739, 0, 0, 0, 1, 745, 0, 0, 0, 259, 64, 32, 746, 0, 3, 66, 33, 742, 0, 5, 743, 167, 0, 0, 1, 746, 0, 0, 0, 5, 746, 167, 0, 0, 1, 740, 0, 0, 0, 1, 741, 0, 0, 0, 1, 744, 0, 0, 0, 1, 55, 0, 0, 0, 5, 756, 200, 0, 0, 3, 58, 29, 753, 0, 5, 750, 163, 0, 0, 3, 58, 29, 752, 0, 1, 749, 0, 0, 0, 1, 755, 0, 0, 0, 1, 751, 0, 0, 0, 1, 754, 0, 0, 0, 1, 757, 0, 0, 0, 1, 753, 0, 0, 0, 1, 748, 0, 0, 0, 1, 757, 0, 0, 0, 1, 758, 0, 0, 0, 5, 759, 201, 0, 0, 1, 57, 0, 0, 0, 3, 10, 5, 762, 0, 1, 760, 0, 0, 0, 1, 765, 0, 0, 0, 1, 761, 0, 0, 0, 1, 764, 0, 0, 0, 1, 773, 0, 0, 0, 1, 763, 0, 0, 0, 3, 38, 19, 772, 0, 5, 772, 115, 0, 0, 5, 772, 149, 0, 0, 5, 772, 44, 0, 0, 5, 772, 98, 0, 0, 1, 766, 0, 0, 0, 1, 767, 0, 0, 0, 1, 768, 0, 0, 0, 1, 769, 0, 0, 0, 1, 770, 0, 0, 0, 1, 775, 0, 0, 0, 1, 771, 0, 0, 0, 1, 774, 0, 0, 0, 1, 777, 0, 0, 0, 1, 773, 0, 0, 0, 3, 152, 76, 778, 0, 1, 776, 0, 0, 0, 1, 778, 0, 0, 0, 1, 781, 0, 0, 0, 3, 442, 221, 782, 0, 5, 782, 6, 0, 0, 1, 779, 0, 0, 0, 1, 780, 0, 0, 0, 1, 782, 0, 0, 0, 1, 784, 0, 0, 0, 259, 48, 24, 785, 0, 1, 783, 0, 0, 0, 1, 785, 0, 0, 0, 1, 59, 0, 0, 0, 5, 787, 199, 0, 0, 7, 788, 2, 0, 0, 259, 62, 31, 789, 0, 1, 61, 0, 0, 0, 5, 799, 200, 0, 0, 3, 46, 23, 796, 0, 5, 793, 163, 0, 0, 3, 46, 23, 795, 0, 1, 792, 0, 0, 0, 1, 798, 0, 0, 0, 1, 794, 0, 0, 0, 1, 797, 0, 0, 0, 1, 800, 0, 0, 0, 1, 796, 0, 0, 0, 1, 791, 0, 0, 0, 1, 800, 0, 0, 0, 1, 801, 0, 0, 0, 5, 802, 201, 0, 0, 1, 63, 0, 0, 0, 3, 10, 5, 805, 0, 1, 803, 0, 0, 0, 1, 808, 0, 0, 0, 1, 804, 0, 0, 0, 1, 807, 0, 0, 0, 1, 809, 0, 0, 0, 1, 806, 0, 0, 0, 5, 813, 197, 0, 0, 3, 180, 90, 812, 0, 1, 810, 0, 0, 0, 1, 815, 0, 0, 0, 1, 811, 0, 0, 0, 1, 814, 0, 0, 0, 1, 816, 0, 0, 0, 1, 813, 0, 0, 0, 5, 817, 198, 0, 0, 1, 65, 0, 0, 0, 5, 819, 138, 0, 0, 259, 296, 148, 820, 0, 1, 67, 0, 0, 0, 3, 10, 5, 823, 0, 1, 821, 0, 0, 0, 1, 826, 0, 0, 0, 1, 822, 0, 0, 0, 1, 825, 0, 0, 0, 1, 830, 0, 0, 0, 1, 824, 0, 0, 0, 3, 38, 19, 829, 0, 1, 827, 0, 0, 0, 1, 832, 0, 0, 0, 1, 828, 0, 0, 0, 1, 831, 0, 0, 0, 1, 833, 0, 0, 0, 1, 830, 0, 0, 0, 7, 835, 3, 0, 0, 3, 70, 35, 836, 0, 1, 834, 0, 0, 0, 1, 836, 0, 0, 0, 1, 837, 0, 0, 0, 5, 839, 22, 0, 0, 5, 840, 27, 0, 0, 1, 838, 0, 0, 0, 1, 840, 0, 0, 0, 1, 841, 0, 0, 0, 3, 152, 76, 842, 0, 3, 56, 28, 848, 0, 259, 64, 32, 849, 0, 3, 66, 33, 845, 0, 5, 846, 167, 0, 0, 1, 849, 0, 0, 0, 5, 849, 167, 0, 0, 1, 843, 0, 0, 0, 1, 844, 0, 0, 0, 1, 847, 0, 0, 0, 1, 69, 0, 0, 0, 3, 16, 8, 851, 0, 5, 852, 165, 0, 0, 1, 71, 0, 0, 0, 3, 10, 5, 855, 0, 1, 853, 0, 0, 0, 1, 858, 0, 0, 0, 1, 854, 0, 0, 0, 1, 857, 0, 0, 0, 1, 862, 0, 0, 0, 1, 856, 0, 0, 0, 3, 38, 19, 861, 0, 1, 859, 0, 0, 0, 1, 864, 0, 0, 0, 1, 860, 0, 0, 0, 1, 863, 0, 0, 0, 1, 865, 0, 0, 0, 1, 862, 0, 0, 0, 5, 866, 175, 0, 0, 3, 442, 221, 867, 0, 3, 56, 28, 873, 0, 259, 64, 32, 874, 0, 3, 66, 33, 870, 0, 5, 871, 167, 0, 0, 1, 874, 0, 0, 0, 5, 874, 167, 0, 0, 1, 868, 0, 0, 0, 1, 869, 0, 0, 0, 1, 872, 0, 0, 0, 1, 73, 0, 0, 0, 3, 10, 5, 877, 0, 1, 875, 0, 0, 0, 1, 880, 0, 0, 0, 1, 876, 0, 0, 0, 1, 879, 0, 0, 0, 1, 884, 0, 0, 0, 1, 878, 0, 0, 0, 3, 38, 19, 883, 0, 1, 881, 0, 0, 0, 1, 886, 0, 0, 0, 1, 882, 0, 0, 0, 1, 885, 0, 0, 0, 1, 887, 0, 0, 0, 1, 884, 0, 0, 0, 3, 152, 76, 889, 0, 3, 70, 35, 890, 0, 1, 888, 0, 0, 0, 1, 890, 0, 0, 0, 1, 891, 0, 0, 0, 3, 442, 221, 893, 0, 3, 76, 38, 894, 0, 1, 892, 0, 0, 0, 1, 894, 0, 0, 0, 1, 895, 0, 0, 0, 3, 56, 28, 899, 0, 3, 80, 40, 898, 0, 1, 896, 0, 0, 0, 1, 901, 0, 0, 0, 1, 897, 0, 0, 0, 1, 900, 0, 0, 0, 1, 907, 0, 0, 0, 1, 899, 0, 0, 0, 259, 64, 32, 908, 0, 3, 66, 33, 904, 0, 5, 905, 167, 0, 0, 1, 908, 0, 0, 0, 5, 908, 167, 0, 0, 1, 902, 0, 0, 0, 1, 903, 0, 0, 0, 1, 906, 0, 0, 0, 1, 75, 0, 0, 0, 5, 910, 168, 0, 0, 3, 78, 39, 915, 0, 5, 912, 163, 0, 0, 3, 78, 39, 914, 0, 1, 911, 0, 0, 0, 1, 917, 0, 0, 0, 1, 913, 0, 0, 0, 1, 916, 0, 0, 0, 1, 918, 0, 0, 0, 1, 915, 0, 0, 0, 5, 919, 170, 0, 0, 1, 77, 0, 0, 0, 3, 10, 5, 922, 0, 1, 920, 0, 0, 0, 1, 925, 0, 0, 0, 1, 921, 0, 0, 0, 1, 924, 0, 0, 0, 1, 927, 0, 0, 0, 1, 923, 0, 0, 0, 7, 928, 4, 0, 0, 1, 926, 0, 0, 0, 1, 928, 0, 0, 0, 1, 929, 0, 0, 0, 259, 442, 221, 930, 0, 1, 79, 0, 0, 0, 5, 932, 78, 0, 0, 3, 8, 4, 933, 0, 5, 934, 199, 0, 0, 3, 82, 41, 939, 0, 5, 936, 163, 0, 0, 3, 82, 41, 938, 0, 1, 935, 0, 0, 0, 1, 941, 0, 0, 0, 1, 937, 0, 0, 0, 1, 940, 0, 0, 0, 1, 81, 0, 0, 0, 1, 939, 0, 0, 0, 259, 84, 42, 948, 0, 259, 90, 45, 948, 0, 259, 92, 46, 948, 0, 259, 94, 47, 948, 0, 259, 96, 48, 948, 0, 1, 942, 0, 0, 0, 1, 943, 0, 0, 0, 1, 944, 0, 0, 0, 1, 945, 0, 0, 0, 1, 946, 0, 0, 0, 1, 83, 0, 0, 0, 5, 950, 37, 0, 0, 3, 86, 43, 955, 0, 5, 952, 163, 0, 0, 3, 86, 43, 954, 0, 1, 951, 0, 0, 0, 1, 957, 0, 0, 0, 1, 953, 0, 0, 0, 1, 956, 0, 0, 0, 1, 85, 0, 0, 0, 1, 955, 0, 0, 0, 259, 88, 44, 959, 0, 1, 87, 0, 0, 0, 5, 961, 116, 0, 0, 5, 962, 54, 0, 0, 1, 89, 0, 0, 0, 5, 965, 64, 0, 0, 5, 966, 171, 0, 0, 1, 964, 0, 0, 0, 1, 966, 0, 0, 0, 1, 972, 0, 0, 0, 5, 969, 54, 0, 0, 5, 970, 171, 0, 0, 1, 968, 0, 0, 0, 1, 970, 0, 0, 0, 1, 972, 0, 0, 0, 1, 963, 0, 0, 0, 1, 967, 0, 0, 0, 1, 91, 0, 0, 0, 5, 974, 113, 0, 0, 5, 975, 200, 0, 0, 5, 976, 201, 0, 0, 1, 93, 0, 0, 0, 5, 978, 29, 0, 0, 1, 95, 0, 0, 0, 259, 152, 76, 980, 0, 1, 97, 0, 0, 0, 3, 10, 5, 983, 0, 1, 981, 0, 0, 0, 1, 986, 0, 0, 0, 1, 982, 0, 0, 0, 1, 985, 0, 0, 0, 1, 990, 0, 0, 0, 1, 984, 0, 0, 0, 3, 38, 19, 989, 0, 1, 987, 0, 0, 0, 1, 992, 0, 0, 0, 1, 988, 0, 0, 0, 1, 991, 0, 0, 0, 1, 993, 0, 0, 0, 1, 990, 0, 0, 0, 3, 152, 76, 995, 0, 3, 70, 35, 996, 0, 1, 994, 0, 0, 0, 1, 996, 0, 0, 0, 1, 997, 0, 0, 0, 5, 999, 22, 0, 0, 5, 1000, 27, 0, 0, 1, 998, 0, 0, 0, 1, 1000, 0, 0, 0, 1, 1036, 0, 0, 0, 5, 1037, 162, 0, 0, 5, 1037, 164, 0, 0, 5, 1037, 156, 0, 0, 5, 1037, 175, 0, 0, 5, 1037, 125, 0, 0, 5, 1037, 127, 0, 0, 5, 1037, 161, 0, 0, 5, 1037, 166, 0, 0, 5, 1037, 159, 0, 0, 5, 1037, 135, 0, 0, 3, 476, 238, 1037, 0, 3, 478, 239, 1037, 0, 5, 1037, 174, 0, 0, 5, 1037, 160, 0, 0, 5, 1037, 172, 0, 0, 5, 1037, 137, 0, 0, 5, 1037, 120, 0, 0, 5, 1037, 168, 0, 0, 5, 1037, 136, 0, 0, 5, 1037, 170, 0, 0, 5, 1037, 139, 0, 0, 5, 1037, 67, 0, 0, 5, 1037, 99, 0, 0, 5, 1037, 150, 0, 0, 5, 1037, 126, 0, 0, 5, 1037, 128, 0, 0, 5, 1037, 124, 0, 0, 5, 1037, 131, 0, 0, 5, 1037, 121, 0, 0, 5, 1037, 123, 0, 0, 5, 1037, 154, 0, 0, 5, 1037, 144, 0, 0, 5, 1037, 105, 0, 0, 3, 480, 240, 1037, 0, 3, 482, 241, 1037, 0, 1, 1001, 0, 0, 0, 1, 1002, 0, 0, 0, 1, 1003, 0, 0, 0, 1, 1004, 0, 0, 0, 1, 1005, 0, 0, 0, 1, 1006, 0, 0, 0, 1, 1007, 0, 0, 0, 1, 1008, 0, 0, 0, 1, 1009, 0, 0, 0, 1, 1010, 0, 0, 0, 1, 1011, 0, 0, 0, 1, 1012, 0, 0, 0, 1, 1013, 0, 0, 0, 1, 1014, 0, 0, 0, 1, 1015, 0, 0, 0, 1, 1016, 0, 0, 0, 1, 1017, 0, 0, 0, 1, 1018, 0, 0, 0, 1, 1019, 0, 0, 0, 1, 1020, 0, 0, 0, 1, 1021, 0, 0, 0, 1, 1022, 0, 0, 0, 1, 1023, 0, 0, 0, 1, 1024, 0, 0, 0, 1, 1025, 0, 0, 0, 1, 1026, 0, 0, 0, 1, 1027, 0, 0, 0, 1, 1028, 0, 0, 0, 1, 1029, 0, 0, 0, 1, 1030, 0, 0, 0, 1, 1031, 0, 0, 0, 1, 1032, 0, 0, 0, 1, 1033, 0, 0, 0, 1, 1034, 0, 0, 0, 1, 1035, 0, 0, 0, 1, 1038, 0, 0, 0, 3, 56, 28, 1044, 0, 259, 64, 32, 1045, 0, 3, 66, 33, 1041, 0, 5, 1042, 167, 0, 0, 1, 1045, 0, 0, 0, 5, 1045, 167, 0, 0, 1, 1039, 0, 0, 0, 1, 1040, 0, 0, 0, 1, 1043, 0, 0, 0, 1, 99, 0, 0, 0, 259, 102, 51, 1049, 0, 259, 104, 52, 1049, 0, 1, 1046, 0, 0, 0, 1, 1047, 0, 0, 0, 1, 101, 0, 0, 0, 3, 10, 5, 1052, 0, 1, 1050, 0, 0, 0, 1, 1055, 0, 0, 0, 1, 1051, 0, 0, 0, 1, 1054, 0, 0, 0, 1, 1059, 0, 0, 0, 1, 1053, 0, 0, 0, 3, 38, 19, 1058, 0, 1, 1056, 0, 0, 0, 1, 1061, 0, 0, 0, 1, 1057, 0, 0, 0, 1, 1060, 0, 0, 0, 1, 1062, 0, 0, 0, 1, 1059, 0, 0, 0, 5, 1063, 12, 0, 0, 3, 16, 8, 1064, 0, 5, 1068, 167, 0, 0, 3, 2, 1, 1067, 0, 1, 1065, 0, 0, 0, 1, 1070, 0, 0, 0, 1, 1066, 0, 0, 0, 1, 1069, 0, 0, 0, 1, 1074, 0, 0, 0, 1, 1068, 0, 0, 0, 3, 4, 2, 1073, 0, 1, 1071, 0, 0, 0, 1, 1076, 0, 0, 0, 1, 1072, 0, 0, 0, 1, 1075, 0, 0, 0, 1, 1080, 0, 0, 0, 1, 1074, 0, 0, 0, 3, 32, 16, 1079, 0, 1, 1077, 0, 0, 0, 1, 1082, 0, 0, 0, 1, 1078, 0, 0, 0, 1, 1081, 0, 0, 0, 1, 103, 0, 0, 0, 1, 1080, 0, 0, 0, 3, 10, 5, 1085, 0, 1, 1083, 0, 0, 0, 1, 1088, 0, 0, 0, 1, 1084, 0, 0, 0, 1, 1087, 0, 0, 0, 1, 1092, 0, 0, 0, 1, 1086, 0, 0, 0, 3, 38, 19, 1091, 0, 1, 1089, 0, 0, 0, 1, 1094, 0, 0, 0, 1, 1090, 0, 0, 0, 1, 1093, 0, 0, 0, 1, 1095, 0, 0, 0, 1, 1092, 0, 0, 0, 5, 1096, 12, 0, 0, 3, 16, 8, 1097, 0, 5, 1101, 197, 0, 0, 3, 2, 1, 1100, 0, 1, 1098, 0, 0, 0, 1, 1103, 0, 0, 0, 1, 1099, 0, 0, 0, 1, 1102, 0, 0, 0, 1, 1107, 0, 0, 0, 1, 1101, 0, 0, 0, 3, 4, 2, 1106, 0, 1, 1104, 0, 0, 0, 1, 1109, 0, 0, 0, 1, 1105, 0, 0, 0, 1, 1108, 0, 0, 0, 1, 1113, 0, 0, 0, 1, 1107, 0, 0, 0, 3, 32, 16, 1112, 0, 1, 1110, 0, 0, 0, 1, 1115, 0, 0, 0, 1, 1111, 0, 0, 0, 1, 1114, 0, 0, 0, 1, 1116, 0, 0, 0, 1, 1113, 0, 0, 0, 5, 1118, 198, 0, 0, 5, 1119, 167, 0, 0, 1, 1117, 0, 0, 0, 1, 1119, 0, 0, 0, 1, 105, 0, 0, 0, 259, 108, 54, 1124, 0, 259, 114, 57, 1124, 0, 259, 118, 59, 1124, 0, 1, 1120, 0, 0, 0, 1, 1121, 0, 0, 0, 1, 1122, 0, 0, 0, 1, 107, 0, 0, 0, 3, 10, 5, 1127, 0, 1, 1125, 0, 0, 0, 1, 1130, 0, 0, 0, 1, 1126, 0, 0, 0, 1, 1129, 0, 0, 0, 1, 1134, 0, 0, 0, 1, 1128, 0, 0, 0, 3, 38, 19, 1133, 0, 1, 1131, 0, 0, 0, 1, 1136, 0, 0, 0, 1, 1132, 0, 0, 0, 1, 1135, 0, 0, 0, 1, 1137, 0, 0, 0, 1, 1134, 0, 0, 0, 5, 1138, 66, 0, 0, 3, 152, 76, 1140, 0, 3, 70, 35, 1141, 0, 1, 1139, 0, 0, 0, 1, 1141, 0, 0, 0, 1, 1142, 0, 0, 0, 3, 442, 221, 1145, 0, 259, 110, 55, 1146, 0, 5, 1146, 167, 0, 0, 1, 1143, 0, 0, 0, 1, 1144, 0, 0, 0, 1, 109, 0, 0, 0, 5, 1151, 197, 0, 0, 3, 112, 56, 1150, 0, 1, 1148, 0, 0, 0, 1, 1153, 0, 0, 0, 1, 1149, 0, 0, 0, 1, 1152, 0, 0, 0, 1, 1154, 0, 0, 0, 1, 1151, 0, 0, 0, 5, 1155, 198, 0, 0, 1, 111, 0, 0, 0, 3, 10, 5, 1158, 0, 1, 1156, 0, 0, 0, 1, 1161, 0, 0, 0, 1, 1157, 0, 0, 0, 1, 1160, 0, 0, 0, 1, 1165, 0, 0, 0, 1, 1159, 0, 0, 0, 3, 38, 19, 1164, 0, 1, 1162, 0, 0, 0, 1, 1167, 0, 0, 0, 1, 1163, 0, 0, 0, 1, 1166, 0, 0, 0, 1, 1168, 0, 0, 0, 1, 1165, 0, 0, 0, 7, 1174, 5, 0, 0, 259, 64, 32, 1175, 0, 3, 66, 33, 1171, 0, 5, 1172, 167, 0, 0, 1, 1175, 0, 0, 0, 5, 1175, 167, 0, 0, 1, 1169, 0, 0, 0, 1, 1170, 0, 0, 0, 1, 1173, 0, 0, 0, 1, 113, 0, 0, 0, 3, 10, 5, 1178, 0, 1, 1176, 0, 0, 0, 1, 1181, 0, 0, 0, 1, 1177, 0, 0, 0, 1, 1180, 0, 0, 0, 1, 1185, 0, 0, 0, 1, 1179, 0, 0, 0, 3, 38, 19, 1184, 0, 1, 1182, 0, 0, 0, 1, 1187, 0, 0, 0, 1, 1183, 0, 0, 0, 1, 1186, 0, 0, 0, 1, 1188, 0, 0, 0, 1, 1185, 0, 0, 0, 3, 152, 76, 1190, 0, 3, 70, 35, 1191, 0, 1, 1189, 0, 0, 0, 1, 1191, 0, 0, 0, 1, 1192, 0, 0, 0, 5, 1193, 98, 0, 0, 3, 116, 58, 1198, 0, 259, 110, 55, 1199, 0, 3, 66, 33, 1196, 0, 5, 1197, 167, 0, 0, 1, 1199, 0, 0, 0, 1, 1194, 0, 0, 0, 1, 1195, 0, 0, 0, 1, 115, 0, 0, 0, 5, 1201, 202, 0, 0, 3, 58, 29, 1206, 0, 5, 1203, 163, 0, 0, 3, 58, 29, 1205, 0, 1, 1202, 0, 0, 0, 1, 1208, 0, 0, 0, 1, 1204, 0, 0, 0, 1, 1207, 0, 0, 0, 1, 1209, 0, 0, 0, 1, 1206, 0, 0, 0, 5, 1210, 203, 0, 0, 1, 117, 0, 0, 0, 3, 10, 5, 1213, 0, 1, 1211, 0, 0, 0, 1, 1216, 0, 0, 0, 1, 1212, 0, 0, 0, 1, 1215, 0, 0, 0, 1, 1220, 0, 0, 0, 1, 1214, 0, 0, 0, 3, 38, 19, 1219, 0, 1, 1217, 0, 0, 0, 1, 1222, 0, 0, 0, 1, 1218, 0, 0, 0, 1, 1221, 0, 0, 0, 1, 1223, 0, 0, 0, 1, 1220, 0, 0, 0, 3, 152, 76, 1225, 0, 3, 70, 35, 1226, 0, 1, 1224, 0, 0, 0, 1, 1226, 0, 0, 0, 1, 1227, 0, 0, 0, 3, 442, 221, 1240, 0, 3, 110, 55, 1232, 0, 3, 48, 24, 1230, 0, 5, 1231, 167, 0, 0, 1, 1233, 0, 0, 0, 1, 1229, 0, 0, 0, 1, 1233, 0, 0, 0, 1, 1241, 0, 0, 0, 3, 66, 33, 1237, 0, 3, 48, 24, 1237, 0, 1, 1234, 0, 0, 0, 1, 1235, 0, 0, 0, 1, 1238, 0, 0, 0, 5, 1239, 167, 0, 0, 1, 1241, 0, 0, 0, 1, 1228, 0, 0, 0, 1, 1236, 0, 0, 0, 1, 119, 0, 0, 0, 259, 122, 61, 1245, 0, 259, 134, 67, 1245, 0, 1, 1242, 0, 0, 0, 1, 1243, 0, 0, 0, 1, 121, 0, 0, 0, 3, 10, 5, 1248, 0, 1, 1246, 0, 0, 0, 1, 1251, 0, 0, 0, 1, 1247, 0, 0, 0, 1, 1250, 0, 0, 0, 1, 1255, 0, 0, 0, 1, 1249, 0, 0, 0, 3, 38, 19, 1254, 0, 1, 1252, 0, 0, 0, 1, 1257, 0, 0, 0, 1, 1253, 0, 0, 0, 1, 1256, 0, 0, 0, 1, 1258, 0, 0, 0, 1, 1255, 0, 0, 0, 5, 1259, 87, 0, 0, 3, 442, 221, 1261, 0, 3, 124, 62, 1262, 0, 1, 1260, 0, 0, 0, 1, 1262, 0, 0, 0, 1, 1278, 0, 0, 0, 5, 1275, 197, 0, 0, 3, 132, 66, 1269, 0, 5, 1266, 163, 0, 0, 3, 132, 66, 1268, 0, 1, 1265, 0, 0, 0, 1, 1271, 0, 0, 0, 1, 1267, 0, 0, 0, 1, 1270, 0, 0, 0, 1, 1273, 0, 0, 0, 1, 1269, 0, 0, 0, 5, 1274, 163, 0, 0, 1, 1272, 0, 0, 0, 1, 1274, 0, 0, 0, 1, 1276, 0, 0, 0, 1, 1264, 0, 0, 0, 1, 1276, 0, 0, 0, 1, 1277, 0, 0, 0, 5, 1279, 198, 0, 0, 1, 1263, 0, 0, 0, 1, 1279, 0, 0, 0, 1, 1281, 0, 0, 0, 5, 1282, 167, 0, 0, 1, 1280, 0, 0, 0, 1, 1282, 0, 0, 0, 1, 123, 0, 0, 0, 5, 1284, 199, 0, 0, 3, 126, 63, 1289, 0, 5, 1286, 163, 0, 0, 3, 126, 63, 1288, 0, 1, 1285, 0, 0, 0, 1, 1291, 0, 0, 0, 1, 1287, 0, 0, 0, 1, 1290, 0, 0, 0, 1, 125, 0, 0, 0, 1, 1289, 0, 0, 0, 259, 128, 64, 1295, 0, 259, 130, 65, 1295, 0, 1, 1292, 0, 0, 0, 1, 1293, 0, 0, 0, 1, 127, 0, 0, 0, 3, 152, 76, 1297, 0, 259, 62, 31, 1298, 0, 1, 129, 0, 0, 0, 259, 152, 76, 1300, 0, 1, 131, 0, 0, 0, 3, 10, 5, 1303, 0, 1, 1301, 0, 0, 0, 1, 1306, 0, 0, 0, 1, 1302, 0, 0, 0, 1, 1305, 0, 0, 0, 1, 1310, 0, 0, 0, 1, 1304, 0, 0, 0, 3, 38, 19, 1309, 0, 1, 1307, 0, 0, 0, 1, 1312, 0, 0, 0, 1, 1308, 0, 0, 0, 1, 1311, 0, 0, 0, 1, 1313, 0, 0, 0, 1, 1310, 0, 0, 0, 3, 442, 221, 1315, 0, 259, 48, 24, 1316, 0, 1, 1314, 0, 0, 0, 1, 1316, 0, 0, 0, 1, 133, 0, 0, 0, 259, 136, 68, 1324, 0, 259, 138, 69, 1324, 0, 259, 140, 70, 1324, 0, 259, 142, 71, 1324, 0, 259, 144, 72, 1324, 0, 259, 146, 73, 1324, 0, 1, 1317, 0, 0, 0, 1, 1318, 0, 0, 0, 1, 1319, 0, 0, 0, 1, 1320, 0, 0, 0, 1, 1321, 0, 0, 0, 1, 1322, 0, 0, 0, 1, 135, 0, 0, 0, 3, 10, 5, 1327, 0, 1, 1325, 0, 0, 0, 1, 1330, 0, 0, 0, 1, 1326, 0, 0, 0, 1, 1329, 0, 0, 0, 1, 1334, 0, 0, 0, 1, 1328, 0, 0, 0, 3, 38, 19, 1333, 0, 1, 1331, 0, 0, 0, 1, 1336, 0, 0, 0, 1, 1332, 0, 0, 0, 1, 1335, 0, 0, 0, 1, 1337, 0, 0, 0, 1, 1334, 0, 0, 0, 5, 1338, 64, 0, 0, 3, 442, 221, 1340, 0, 3, 76, 38, 1341, 0, 1, 1339, 0, 0, 0, 1, 1341, 0, 0, 0, 1, 1343, 0, 0, 0, 3, 56, 28, 1344, 0, 1, 1342, 0, 0, 0, 1, 1344, 0, 0, 0, 1, 1346, 0, 0, 0, 3, 124, 62, 1347, 0, 1, 1345, 0, 0, 0, 1, 1347, 0, 0, 0, 1, 1351, 0, 0, 0, 3, 80, 40, 1350, 0, 1, 1348, 0, 0, 0, 1, 1353, 0, 0, 0, 1, 1349, 0, 0, 0, 1, 1352, 0, 0, 0, 1, 1362, 0, 0, 0, 1, 1351, 0, 0, 0, 5, 1358, 197, 0, 0, 3, 32, 16, 1357, 0, 1, 1355, 0, 0, 0, 1, 1360, 0, 0, 0, 1, 1356, 0, 0, 0, 1, 1359, 0, 0, 0, 1, 1361, 0, 0, 0, 1, 1358, 0, 0, 0, 5, 1363, 198, 0, 0, 1, 1354, 0, 0, 0, 1, 1363, 0, 0, 0, 1, 1365, 0, 0, 0, 5, 1366, 167, 0, 0, 1, 1364, 0, 0, 0, 1, 1366, 0, 0, 0, 1, 137, 0, 0, 0, 3, 10, 5, 1369, 0, 1, 1367, 0, 0, 0, 1, 1372, 0, 0, 0, 1, 1368, 0, 0, 0, 1, 1371, 0, 0, 0, 1, 1376, 0, 0, 0, 1, 1370, 0, 0, 0, 3, 38, 19, 1375, 0, 1, 1373, 0, 0, 0, 1, 1378, 0, 0, 0, 1, 1374, 0, 0, 0, 1, 1377, 0, 0, 0, 1, 1379, 0, 0, 0, 1, 1376, 0, 0, 0, 5, 1381, 10, 0, 0, 3, 76, 38, 1382, 0, 1, 1380, 0, 0, 0, 1, 1382, 0, 0, 0, 1, 1384, 0, 0, 0, 3, 56, 28, 1385, 0, 1, 1383, 0, 0, 0, 1, 1385, 0, 0, 0, 1, 1389, 0, 0, 0, 3, 80, 40, 1388, 0, 1, 1386, 0, 0, 0, 1, 1391, 0, 0, 0, 1, 1387, 0, 0, 0, 1, 1390, 0, 0, 0, 1, 1392, 0, 0, 0, 1, 1389, 0, 0, 0, 5, 1396, 197, 0, 0, 3, 32, 16, 1395, 0, 1, 1393, 0, 0, 0, 1, 1398, 0, 0, 0, 1, 1394, 0, 0, 0, 1, 1397, 0, 0, 0, 1, 1399, 0, 0, 0, 1, 1396, 0, 0, 0, 5, 1400, 198, 0, 0, 1, 139, 0, 0, 0, 3, 10, 5, 1403, 0, 1, 1401, 0, 0, 0, 1, 1406, 0, 0, 0, 1, 1402, 0, 0, 0, 1, 1405, 0, 0, 0, 1, 1410, 0, 0, 0, 1, 1404, 0, 0, 0, 3, 38, 19, 1409, 0, 1, 1407, 0, 0, 0, 1, 1412, 0, 0, 0, 1, 1408, 0, 0, 0, 1, 1411, 0, 0, 0, 1, 1413, 0, 0, 0, 1, 1410, 0, 0, 0, 5, 1414, 11, 0, 0, 3, 442, 221, 1416, 0, 3, 76, 38, 1417, 0, 1, 1415, 0, 0, 0, 1, 1417, 0, 0, 0, 1, 1419, 0, 0, 0, 3, 56, 28, 1420, 0, 1, 1418, 0, 0, 0, 1, 1420, 0, 0, 0, 1, 1422, 0, 0, 0, 3, 124, 62, 1423, 0, 1, 1421, 0, 0, 0, 1, 1423, 0, 0, 0, 1, 1427, 0, 0, 0, 3, 80, 40, 1426, 0, 1, 1424, 0, 0, 0, 1, 1429, 0, 0, 0, 1, 1425, 0, 0, 0, 1, 1428, 0, 0, 0, 1, 1438, 0, 0, 0, 1, 1427, 0, 0, 0, 5, 1434, 197, 0, 0, 3, 32, 16, 1433, 0, 1, 1431, 0, 0, 0, 1, 1436, 0, 0, 0, 1, 1432, 0, 0, 0, 1, 1435, 0, 0, 0, 1, 1437, 0, 0, 0, 1, 1434, 0, 0, 0, 5, 1439, 198, 0, 0, 1, 1430, 0, 0, 0, 1, 1439, 0, 0, 0, 1, 1441, 0, 0, 0, 5, 1442, 167, 0, 0, 1, 1440, 0, 0, 0, 1, 1442, 0, 0, 0, 1, 141, 0, 0, 0, 3, 10, 5, 1445, 0, 1, 1443, 0, 0, 0, 1, 1448, 0, 0, 0, 1, 1444, 0, 0, 0, 1, 1447, 0, 0, 0, 1, 1452, 0, 0, 0, 1, 1446, 0, 0, 0, 3, 38, 19, 1451, 0, 1, 1449, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1450, 0, 0, 0, 1, 1453, 0, 0, 0, 1, 1455, 0, 0, 0, 1, 1452, 0, 0, 0, 3, 474, 237, 1457, 0, 7, 1458, 6, 0, 0, 1, 1456, 0, 0, 0, 1, 1458, 0, 0, 0, 1, 1459, 0, 0, 0, 3, 442, 221, 1461, 0, 3, 76, 38, 1462, 0, 1, 1460, 0, 0, 0, 1, 1462, 0, 0, 0, 1, 1464, 0, 0, 0, 3, 56, 28, 1465, 0, 1, 1463, 0, 0, 0, 1, 1465, 0, 0, 0, 1, 1467, 0, 0, 0, 3, 124, 62, 1468, 0, 1, 1466, 0, 0, 0, 1, 1468, 0, 0, 0, 1, 1472, 0, 0, 0, 3, 80, 40, 1471, 0, 1, 1469, 0, 0, 0, 1, 1474, 0, 0, 0, 1, 1470, 0, 0, 0, 1, 1473, 0, 0, 0, 1, 1483, 0, 0, 0, 1, 1472, 0, 0, 0, 5, 1479, 197, 0, 0, 3, 32, 16, 1478, 0, 1, 1476, 0, 0, 0, 1, 1481, 0, 0, 0, 1, 1477, 0, 0, 0, 1, 1480, 0, 0, 0, 1, 1482, 0, 0, 0, 1, 1479, 0, 0, 0, 5, 1484, 198, 0, 0, 1, 1475, 0, 0, 0, 1, 1484, 0, 0, 0, 1, 1486, 0, 0, 0, 5, 1487, 167, 0, 0, 1, 1485, 0, 0, 0, 1, 1487, 0, 0, 0, 1, 143, 0, 0, 0, 3, 10, 5, 1490, 0, 1, 1488, 0, 0, 0, 1, 1493, 0, 0, 0, 1, 1489, 0, 0, 0, 1, 1492, 0, 0, 0, 1, 1497, 0, 0, 0, 1, 1491, 0, 0, 0, 3, 38, 19, 1496, 0, 1, 1494, 0, 0, 0, 1, 1499, 0, 0, 0, 1, 1495, 0, 0, 0, 1, 1498, 0, 0, 0, 1, 1500, 0, 0, 0, 1, 1497, 0, 0, 0, 5, 1501, 54, 0, 0, 3, 442, 221, 1503, 0, 3, 76, 38, 1504, 0, 1, 1502, 0, 0, 0, 1, 1504, 0, 0, 0, 1, 1506, 0, 0, 0, 3, 56, 28, 1507, 0, 1, 1505, 0, 0, 0, 1, 1507, 0, 0, 0, 1, 1509, 0, 0, 0, 3, 124, 62, 1510, 0, 1, 1508, 0, 0, 0, 1, 1510, 0, 0, 0, 1, 1514, 0, 0, 0, 3, 80, 40, 1513, 0, 1, 1511, 0, 0, 0, 1, 1516, 0, 0, 0, 1, 1512, 0, 0, 0, 1, 1515, 0, 0, 0, 1, 1525, 0, 0, 0, 1, 1514, 0, 0, 0, 5, 1521, 197, 0, 0, 3, 32, 16, 1520, 0, 1, 1518, 0, 0, 0, 1, 1523, 0, 0, 0, 1, 1519, 0, 0, 0, 1, 1522, 0, 0, 0, 1, 1524, 0, 0, 0, 1, 1521, 0, 0, 0, 5, 1526, 198, 0, 0, 1, 1517, 0, 0, 0, 1, 1526, 0, 0, 0, 1, 1528, 0, 0, 0, 5, 1529, 167, 0, 0, 1, 1527, 0, 0, 0, 1, 1529, 0, 0, 0, 1, 145, 0, 0, 0, 3, 10, 5, 1532, 0, 1, 1530, 0, 0, 0, 1, 1535, 0, 0, 0, 1, 1531, 0, 0, 0, 1, 1534, 0, 0, 0, 1, 1539, 0, 0, 0, 1, 1533, 0, 0, 0, 3, 38, 19, 1538, 0, 1, 1536, 0, 0, 0, 1, 1541, 0, 0, 0, 1, 1537, 0, 0, 0, 1, 1540, 0, 0, 0, 1, 1542, 0, 0, 0, 1, 1539, 0, 0, 0, 5, 1543, 76, 0, 0, 3, 442, 221, 1545, 0, 3, 76, 38, 1546, 0, 1, 1544, 0, 0, 0, 1, 1546, 0, 0, 0, 1, 1548, 0, 0, 0, 3, 56, 28, 1549, 0, 1, 1547, 0, 0, 0, 1, 1549, 0, 0, 0, 1, 1551, 0, 0, 0, 3, 124, 62, 1552, 0, 1, 1550, 0, 0, 0, 1, 1552, 0, 0, 0, 1, 1556, 0, 0, 0, 3, 80, 40, 1555, 0, 1, 1553, 0, 0, 0, 1, 1558, 0, 0, 0, 1, 1554, 0, 0, 0, 1, 1557, 0, 0, 0, 1, 1567, 0, 0, 0, 1, 1556, 0, 0, 0, 5, 1563, 197, 0, 0, 3, 32, 16, 1562, 0, 1, 1560, 0, 0, 0, 1, 1565, 0, 0, 0, 1, 1561, 0, 0, 0, 1, 1564, 0, 0, 0, 1, 1566, 0, 0, 0, 1, 1563, 0, 0, 0, 5, 1568, 198, 0, 0, 1, 1559, 0, 0, 0, 1, 1568, 0, 0, 0, 1, 1570, 0, 0, 0, 5, 1571, 167, 0, 0, 1, 1569, 0, 0, 0, 1, 1571, 0, 0, 0, 1, 147, 0, 0, 0, 3, 10, 5, 1574, 0, 1, 1572, 0, 0, 0, 1, 1577, 0, 0, 0, 1, 1573, 0, 0, 0, 1, 1576, 0, 0, 0, 1, 1581, 0, 0, 0, 1, 1575, 0, 0, 0, 3, 38, 19, 1580, 0, 1, 1578, 0, 0, 0, 1, 1583, 0, 0, 0, 1, 1579, 0, 0, 0, 1, 1582, 0, 0, 0, 1, 1584, 0, 0, 0, 1, 1581, 0, 0, 0, 5, 1585, 18, 0, 0, 3, 152, 76, 1586, 0, 3, 442, 221, 1588, 0, 3, 76, 38, 1589, 0, 1, 1587, 0, 0, 0, 1, 1589, 0, 0, 0, 1, 1590, 0, 0, 0, 3, 56, 28, 1594, 0, 3, 80, 40, 1593, 0, 1, 1591, 0, 0, 0, 1, 1596, 0, 0, 0, 1, 1592, 0, 0, 0, 1, 1595, 0, 0, 0, 1, 1597, 0, 0, 0, 1, 1594, 0, 0, 0, 5, 1598, 167, 0, 0, 1, 149, 0, 0, 0, 3, 10, 5, 1601, 0, 1, 1599, 0, 0, 0, 1, 1604, 0, 0, 0, 1, 1600, 0, 0, 0, 1, 1603, 0, 0, 0, 1, 1608, 0, 0, 0, 1, 1602, 0, 0, 0, 3, 38, 19, 1607, 0, 1, 1605, 0, 0, 0, 1, 1610, 0, 0, 0, 1, 1606, 0, 0, 0, 1, 1609, 0, 0, 0, 1, 1611, 0, 0, 0, 1, 1608, 0, 0, 0, 259, 180, 90, 1612, 0, 1, 151, 0, 0, 0, 6, 1614, 76, 4294967295, 0, 3, 158, 79, 1621, 0, 3, 16, 8, 1621, 0, 3, 170, 85, 1621, 0, 3, 172, 86, 1621, 0, 3, 174, 87, 1621, 0, 3, 176, 88, 1621, 0, 1, 1613, 0, 0, 0, 1, 1615, 0, 0, 0, 1, 1616, 0, 0, 0, 1, 1617, 0, 0, 0, 1, 1618, 0, 0, 0, 1, 1619, 0, 0, 0, 1, 1634, 0, 0, 0, 10, 1624, 9, 0, 0, 3, 156, 78, 1625, 0, 1, 1623, 0, 0, 0, 1, 1626, 0, 0, 0, 1, 1624, 0, 0, 0, 1, 1627, 0, 0, 0, 1, 1633, 0, 0, 0, 10, 1629, 6, 0, 0, 5, 1633, 171, 0, 0, 10, 1631, 5, 0, 0, 5, 1633, 161, 0, 0, 1, 1622, 0, 0, 0, 1, 1628, 0, 0, 0, 1, 1630, 0, 0, 0, 1, 1636, 0, 0, 0, 1, 1632, 0, 0, 0, 1, 1635, 0, 0, 0, 1, 153, 0, 0, 0, 1, 1634, 0, 0, 0, 3, 152, 76, 1639, 0, 3, 156, 78, 1640, 0, 1, 1638, 0, 0, 0, 1, 1641, 0, 0, 0, 1, 1639, 0, 0, 0, 1, 1642, 0, 0, 0, 1, 155, 0, 0, 0, 5, 1656, 202, 0, 0, 3, 296, 148, 1646, 0, 1, 1644, 0, 0, 0, 1, 1646, 0, 0, 0, 1, 1653, 0, 0, 0, 5, 1649, 163, 0, 0, 3, 296, 148, 1650, 0, 1, 1648, 0, 0, 0, 1, 1650, 0, 0, 0, 1, 1652, 0, 0, 0, 1, 1647, 0, 0, 0, 1, 1655, 0, 0, 0, 1, 1651, 0, 0, 0, 1, 1654, 0, 0, 0, 1, 1657, 0, 0, 0, 1, 1653, 0, 0, 0, 1, 1645, 0, 0, 0, 1, 1657, 0, 0, 0, 1, 1658, 0, 0, 0, 5, 1659, 203, 0, 0, 1, 157, 0, 0, 0, 5, 1661, 18, 0, 0, 5, 1663, 161, 0, 0, 3, 160, 80, 1664, 0, 1, 1662, 0, 0, 0, 1, 1664, 0, 0, 0, 1, 1665, 0, 0, 0, 259, 166, 83, 1666, 0, 1, 159, 0, 0, 0, 5, 1669, 32, 0, 0, 259, 162, 81, 1670, 0, 1, 1668, 0, 0, 0, 1, 1670, 0, 0, 0, 1, 1676, 0, 0, 0, 5, 1673, 15, 0, 0, 259, 162, 81, 1674, 0, 1, 1672, 0, 0, 0, 1, 1674, 0, 0, 0, 1, 1676, 0, 0, 0, 1, 1667, 0, 0, 0, 1, 1671, 0, 0, 0, 1, 161, 0, 0, 0, 5, 1678, 202, 0, 0, 3, 164, 82, 1683, 0, 5, 1680, 163, 0, 0, 3, 164, 82, 1682, 0, 1, 1679, 0, 0, 0, 1, 1685, 0, 0, 0, 1, 1681, 0, 0, 0, 1, 1684, 0, 0, 0, 1, 1686, 0, 0, 0, 1, 1683, 0, 0, 0, 5, 1687, 203, 0, 0, 1, 163, 0, 0, 0, 259, 442, 221, 1689, 0, 1, 165, 0, 0, 0, 5, 1691, 168, 0, 0, 3, 168, 84, 1696, 0, 5, 1693, 163, 0, 0, 3, 168, 84, 1695, 0, 1, 1692, 0, 0, 0, 1, 1698, 0, 0, 0, 1, 1694, 0, 0, 0, 1, 1697, 0, 0, 0, 1, 1699, 0, 0, 0, 1, 1696, 0, 0, 0, 5, 1700, 170, 0, 0, 1, 167, 0, 0, 0, 3, 10, 5, 1703, 0, 1, 1701, 0, 0, 0, 1, 1706, 0, 0, 0, 1, 1702, 0, 0, 0, 1, 1705, 0, 0, 0, 1, 1710, 0, 0, 0, 1, 1704, 0, 0, 0, 3, 38, 19, 1709, 0, 1, 1707, 0, 0, 0, 1, 1712, 0, 0, 0, 1, 1708, 0, 0, 0, 1, 1711, 0, 0, 0, 1, 1713, 0, 0, 0, 1, 1710, 0, 0, 0, 259, 152, 76, 1714, 0, 1, 169, 0, 0, 0, 7, 1716, 7, 0, 0, 1, 171, 0, 0, 0, 5, 1719, 116, 0, 0, 5, 1720, 24, 0, 0, 1, 1718, 0, 0, 0, 1, 1720, 0, 0, 0, 1, 1721, 0, 0, 0, 259, 152, 76, 1722, 0, 1, 173, 0, 0, 0, 5, 1724, 48, 0, 0, 259, 152, 76, 1725, 0, 1, 175, 0, 0, 0, 5, 1727, 200, 0, 0, 3, 178, 89, 1730, 0, 5, 1729, 163, 0, 0, 3, 178, 89, 1731, 0, 1, 1728, 0, 0, 0, 1, 1732, 0, 0, 0, 1, 1730, 0, 0, 0, 1, 1733, 0, 0, 0, 1, 1734, 0, 0, 0, 5, 1735, 201, 0, 0, 1, 177, 0, 0, 0, 3, 152, 76, 1738, 0, 259, 442, 221, 1739, 0, 1, 1737, 0, 0, 0, 1, 1739, 0, 0, 0, 1, 179, 0, 0, 0, 259, 64, 32, 1765, 0, 259, 182, 91, 1765, 0, 259, 184, 92, 1765, 0, 259, 186, 93, 1765, 0, 259, 192, 96, 1765, 0, 259, 194, 97, 1765, 0, 259, 196, 98, 1765, 0, 259, 212, 106, 1765, 0, 259, 198, 99, 1765, 0, 259, 200, 100, 1765, 0, 259, 202, 101, 1765, 0, 259, 204, 102, 1765, 0, 259, 206, 103, 1765, 0, 259, 210, 105, 1765, 0, 259, 214, 107, 1765, 0, 259, 216, 108, 1765, 0, 259, 218, 109, 1765, 0, 259, 220, 110, 1765, 0, 259, 276, 138, 1765, 0, 259, 278, 139, 1765, 0, 259, 288, 144, 1765, 0, 259, 290, 145, 1765, 0, 259, 292, 146, 1765, 0, 259, 294, 147, 1765, 0, 1, 1740, 0, 0, 0, 1, 1741, 0, 0, 0, 1, 1742, 0, 0, 0, 1, 1743, 0, 0, 0, 1, 1744, 0, 0, 0, 1, 1745, 0, 0, 0, 1, 1746, 0, 0, 0, 1, 1747, 0, 0, 0, 1, 1748, 0, 0, 0, 1, 1749, 0, 0, 0, 1, 1750, 0, 0, 0, 1, 1751, 0, 0, 0, 1, 1752, 0, 0, 0, 1, 1753, 0, 0, 0, 1, 1754, 0, 0, 0, 1, 1755, 0, 0, 0, 1, 1756, 0, 0, 0, 1, 1757, 0, 0, 0, 1, 1758, 0, 0, 0, 1, 1759, 0, 0, 0, 1, 1760, 0, 0, 0, 1, 1761, 0, 0, 0, 1, 1762, 0, 0, 0, 1, 1763, 0, 0, 0, 1, 181, 0, 0, 0, 3, 10, 5, 1768, 0, 1, 1766, 0, 0, 0, 1, 1771, 0, 0, 0, 1, 1767, 0, 0, 0, 1, 1770, 0, 0, 0, 1, 1772, 0, 0, 0, 1, 1769, 0, 0, 0, 5, 1774, 62, 0, 0, 3, 8, 4, 1775, 0, 1, 1773, 0, 0, 0, 1, 1775, 0, 0, 0, 1, 1776, 0, 0, 0, 5, 1777, 167, 0, 0, 1, 183, 0, 0, 0, 3, 10, 5, 1780, 0, 1, 1778, 0, 0, 0, 1, 1783, 0, 0, 0, 1, 1779, 0, 0, 0, 1, 1782, 0, 0, 0, 1, 1784, 0, 0, 0, 1, 1781, 0, 0, 0, 7, 1785, 8, 0, 0, 259, 64, 32, 1786, 0, 1, 185, 0, 0, 0, 259, 188, 94, 1790, 0, 259, 190, 95, 1790, 0, 1, 1787, 0, 0, 0, 1, 1788, 0, 0, 0, 1, 187, 0, 0, 0, 3, 10, 5, 1793, 0, 1, 1791, 0, 0, 0, 1, 1796, 0, 0, 0, 1, 1792, 0, 0, 0, 1, 1795, 0, 0, 0, 1, 1798, 0, 0, 0, 1, 1794, 0, 0, 0, 5, 1799, 61, 0, 0, 1, 1797, 0, 0, 0, 1, 1799, 0, 0, 0, 1, 1800, 0, 0, 0, 5, 1801, 31, 0, 0, 5, 1802, 200, 0, 0, 3, 152, 76, 1803, 0, 3, 442, 221, 1804, 0, 5, 1805, 149, 0, 0, 3, 296, 148, 1806, 0, 5, 1807, 201, 0, 0, 259, 180, 90, 1808, 0, 1, 189, 0, 0, 0, 3, 10, 5, 1811, 0, 1, 1809, 0, 0, 0, 1, 1814, 0, 0, 0, 1, 1810, 0, 0, 0, 1, 1813, 0, 0, 0, 1, 1816, 0, 0, 0, 1, 1812, 0, 0, 0, 5, 1817, 61, 0, 0, 1, 1815, 0, 0, 0, 1, 1817, 0, 0, 0, 1, 1818, 0, 0, 0, 5, 1819, 31, 0, 0, 5, 1820, 200, 0, 0, 3, 296, 148, 1821, 0, 5, 1822, 149, 0, 0, 3, 296, 148, 1823, 0, 5, 1824, 201, 0, 0, 259, 180, 90, 1825, 0, 1, 191, 0, 0, 0, 3, 10, 5, 1828, 0, 1, 1826, 0, 0, 0, 1, 1831, 0, 0, 0, 1, 1827, 0, 0, 0, 1, 1830, 0, 0, 0, 1, 1832, 0, 0, 0, 1, 1829, 0, 0, 0, 5, 1834, 17, 0, 0, 3, 8, 4, 1835, 0, 1, 1833, 0, 0, 0, 1, 1835, 0, 0, 0, 1, 1836, 0, 0, 0, 5, 1837, 167, 0, 0, 1, 193, 0, 0, 0, 3, 10, 5, 1840, 0, 1, 1838, 0, 0, 0, 1, 1843, 0, 0, 0, 1, 1839, 0, 0, 0, 1, 1842, 0, 0, 0, 1, 1844, 0, 0, 0, 1, 1841, 0, 0, 0, 5, 1845, 147, 0, 0, 3, 180, 90, 1846, 0, 5, 1847, 79, 0, 0, 5, 1848, 200, 0, 0, 3, 296, 148, 1849, 0, 5, 1850, 201, 0, 0, 5, 1851, 167, 0, 0, 1, 195, 0, 0, 0, 3, 10, 5, 1854, 0, 1, 1852, 0, 0, 0, 1, 1857, 0, 0, 0, 1, 1853, 0, 0, 0, 1, 1856, 0, 0, 0, 1, 1858, 0, 0, 0, 1, 1855, 0, 0, 0, 5, 1859, 167, 0, 0, 1, 197, 0, 0, 0, 3, 10, 5, 1862, 0, 1, 1860, 0, 0, 0, 1, 1865, 0, 0, 0, 1, 1861, 0, 0, 0, 1, 1864, 0, 0, 0, 1, 1866, 0, 0, 0, 1, 1863, 0, 0, 0, 3, 296, 148, 1867, 0, 5, 1868, 167, 0, 0, 1, 199, 0, 0, 0, 3, 10, 5, 1871, 0, 1, 1869, 0, 0, 0, 1, 1874, 0, 0, 0, 1, 1870, 0, 0, 0, 1, 1873, 0, 0, 0, 1, 1875, 0, 0, 0, 1, 1872, 0, 0, 0, 5, 1876, 69, 0, 0, 5, 1877, 200, 0, 0, 3, 40, 20, 1878, 0, 5, 1879, 201, 0, 0, 259, 180, 90, 1880, 0, 1, 201, 0, 0, 0, 3, 10, 5, 1883, 0, 1, 1881, 0, 0, 0, 1, 1886, 0, 0, 0, 1, 1882, 0, 0, 0, 1, 1885, 0, 0, 0, 1, 1887, 0, 0, 0, 1, 1884, 0, 0, 0, 5, 1888, 109, 0, 0, 5, 1902, 200, 0, 0, 3, 40, 20, 1891, 0, 1, 1889, 0, 0, 0, 1, 1891, 0, 0, 0, 1, 1903, 0, 0, 0, 3, 296, 148, 1897, 0, 5, 1894, 163, 0, 0, 3, 296, 148, 1896, 0, 1, 1893, 0, 0, 0, 1, 1899, 0, 0, 0, 1, 1895, 0, 0, 0, 1, 1898, 0, 0, 0, 1, 1901, 0, 0, 0, 1, 1897, 0, 0, 0, 1, 1892, 0, 0, 0, 1, 1901, 0, 0, 0, 1, 1903, 0, 0, 0, 1, 1890, 0, 0, 0, 1, 1900, 0, 0, 0, 1, 1904, 0, 0, 0, 5, 1906, 167, 0, 0, 3, 296, 148, 1907, 0, 1, 1905, 0, 0, 0, 1, 1907, 0, 0, 0, 1, 1908, 0, 0, 0, 5, 1917, 167, 0, 0, 3, 296, 148, 1914, 0, 5, 1911, 163, 0, 0, 3, 296, 148, 1913, 0, 1, 1910, 0, 0, 0, 1, 1916, 0, 0, 0, 1, 1912, 0, 0, 0, 1, 1915, 0, 0, 0, 1, 1918, 0, 0, 0, 1, 1914, 0, 0, 0, 1, 1909, 0, 0, 0, 1, 1918, 0, 0, 0, 1, 1919, 0, 0, 0, 5, 1920, 201, 0, 0, 259, 180, 90, 1921, 0, 1, 203, 0, 0, 0, 3, 10, 5, 1924, 0, 1, 1922, 0, 0, 0, 1, 1927, 0, 0, 0, 1, 1923, 0, 0, 0, 1, 1926, 0, 0, 0, 1, 1928, 0, 0, 0, 1, 1925, 0, 0, 0, 5, 1930, 90, 0, 0, 7, 1931, 9, 0, 0, 1, 1929, 0, 0, 0, 1, 1931, 0, 0, 0, 1, 1933, 0, 0, 0, 3, 296, 148, 1934, 0, 1, 1932, 0, 0, 0, 1, 1934, 0, 0, 0, 1, 1935, 0, 0, 0, 5, 1936, 167, 0, 0, 1, 205, 0, 0, 0, 3, 10, 5, 1939, 0, 1, 1937, 0, 0, 0, 1, 1942, 0, 0, 0, 1, 1938, 0, 0, 0, 1, 1941, 0, 0, 0, 1, 1943, 0, 0, 0, 1, 1940, 0, 0, 0, 5, 1944, 148, 0, 0, 5, 1945, 200, 0, 0, 3, 296, 148, 1946, 0, 5, 1947, 201, 0, 0, 3, 180, 90, 1949, 0, 259, 208, 104, 1950, 0, 1, 1948, 0, 0, 0, 1, 1950, 0, 0, 0, 1, 207, 0, 0, 0, 5, 1952, 86, 0, 0, 259, 180, 90, 1953, 0, 1, 209, 0, 0, 0, 3, 10, 5, 1956, 0, 1, 1954, 0, 0, 0, 1, 1959, 0, 0, 0, 1, 1955, 0, 0, 0, 1, 1958, 0, 0, 0, 1, 1960, 0, 0, 0, 1, 1957, 0, 0, 0, 3, 442, 221, 1961, 0, 5, 1962, 199, 0, 0, 259, 180, 90, 1963, 0, 1, 211, 0, 0, 0, 3, 10, 5, 1966, 0, 1, 1964, 0, 0, 0, 1, 1969, 0, 0, 0, 1, 1965, 0, 0, 0, 1, 1968, 0, 0, 0, 1, 1971, 0, 0, 0, 1, 1967, 0, 0, 0, 5, 1972, 61, 0, 0, 1, 1970, 0, 0, 0, 1, 1972, 0, 0, 0, 1, 1974, 0, 0, 0, 5, 1975, 77, 0, 0, 1, 1973, 0, 0, 0, 1, 1975, 0, 0, 0, 1, 1979, 0, 0, 0, 3, 38, 19, 1978, 0, 1, 1976, 0, 0, 0, 1, 1981, 0, 0, 0, 1, 1977, 0, 0, 0, 1, 1980, 0, 0, 0, 1, 1982, 0, 0, 0, 1, 1979, 0, 0, 0, 3, 484, 242, 1983, 0, 5, 1984, 167, 0, 0, 1, 213, 0, 0, 0, 3, 10, 5, 1987, 0, 1, 1985, 0, 0, 0, 1, 1990, 0, 0, 0, 1, 1986, 0, 0, 0, 1, 1989, 0, 0, 0, 1, 1994, 0, 0, 0, 1, 1988, 0, 0, 0, 3, 38, 19, 1993, 0, 1, 1991, 0, 0, 0, 1, 1996, 0, 0, 0, 1, 1992, 0, 0, 0, 1, 1995, 0, 0, 0, 1, 1997, 0, 0, 0, 1, 1994, 0, 0, 0, 3, 152, 76, 1998, 0, 3, 442, 221, 2000, 0, 3, 76, 38, 2001, 0, 1, 1999, 0, 0, 0, 1, 2001, 0, 0, 0, 1, 2002, 0, 0, 0, 3, 56, 28, 2006, 0, 3, 80, 40, 2005, 0, 1, 2003, 0, 0, 0, 1, 2008, 0, 0, 0, 1, 2004, 0, 0, 0, 1, 2007, 0, 0, 0, 1, 2013, 0, 0, 0, 1, 2006, 0, 0, 0, 259, 64, 32, 2014, 0, 3, 66, 33, 2011, 0, 5, 2012, 167, 0, 0, 1, 2014, 0, 0, 0, 1, 2009, 0, 0, 0, 1, 2010, 0, 0, 0, 1, 215, 0, 0, 0, 3, 10, 5, 2017, 0, 1, 2015, 0, 0, 0, 1, 2020, 0, 0, 0, 1, 2016, 0, 0, 0, 1, 2019, 0, 0, 0, 1, 2021, 0, 0, 0, 1, 2018, 0, 0, 0, 5, 2022, 94, 0, 0, 5, 2023, 200, 0, 0, 3, 296, 148, 2024, 0, 5, 2025, 201, 0, 0, 259, 180, 90, 2026, 0, 1, 217, 0, 0, 0, 3, 10, 5, 2029, 0, 1, 2027, 0, 0, 0, 1, 2032, 0, 0, 0, 1, 2028, 0, 0, 0, 1, 2031, 0, 0, 0, 1, 2033, 0, 0, 0, 1, 2030, 0, 0, 0, 5, 2035, 47, 0, 0, 3, 296, 148, 2036, 0, 1, 2034, 0, 0, 0, 1, 2036, 0, 0, 0, 1, 2037, 0, 0, 0, 5, 2038, 167, 0, 0, 1, 219, 0, 0, 0, 3, 10, 5, 2041, 0, 1, 2039, 0, 0, 0, 1, 2044, 0, 0, 0, 1, 2040, 0, 0, 0, 1, 2043, 0, 0, 0, 1, 2045, 0, 0, 0, 1, 2042, 0, 0, 0, 5, 2046, 55, 0, 0, 5, 2047, 200, 0, 0, 3, 296, 148, 2048, 0, 5, 2049, 201, 0, 0, 5, 2053, 197, 0, 0, 3, 222, 111, 2052, 0, 1, 2050, 0, 0, 0, 1, 2055, 0, 0, 0, 1, 2051, 0, 0, 0, 1, 2054, 0, 0, 0, 1, 2056, 0, 0, 0, 1, 2053, 0, 0, 0, 5, 2057, 198, 0, 0, 1, 221, 0, 0, 0, 3, 224, 112, 2060, 0, 1, 2058, 0, 0, 0, 1, 2061, 0, 0, 0, 1, 2059, 0, 0, 0, 1, 2062, 0, 0, 0, 1, 2064, 0, 0, 0, 3, 180, 90, 2065, 0, 1, 2063, 0, 0, 0, 1, 2066, 0, 0, 0, 1, 2064, 0, 0, 0, 1, 2067, 0, 0, 0, 1, 223, 0, 0, 0, 259, 226, 113, 2072, 0, 259, 272, 136, 2072, 0, 259, 274, 137, 2072, 0, 1, 2068, 0, 0, 0, 1, 2069, 0, 0, 0, 1, 2070, 0, 0, 0, 1, 225, 0, 0, 0, 5, 2074, 84, 0, 0, 3, 228, 114, 2076, 0, 3, 270, 135, 2077, 0, 1, 2075, 0, 0, 0, 1, 2077, 0, 0, 0, 1, 2078, 0, 0, 0, 5, 2079, 199, 0, 0, 1, 227, 0, 0, 0, 6, 2081, 114, 4294967295, 0, 3, 268, 134, 2093, 0, 3, 230, 115, 2093, 0, 3, 232, 116, 2093, 0, 3, 242, 121, 2093, 0, 3, 244, 122, 2093, 0, 3, 246, 123, 2093, 0, 3, 248, 124, 2093, 0, 3, 260, 130, 2093, 0, 3, 262, 131, 2093, 0, 3, 264, 132, 2093, 0, 3, 266, 133, 2093, 0, 1, 2080, 0, 0, 0, 1, 2082, 0, 0, 0, 1, 2083, 0, 0, 0, 1, 2084, 0, 0, 0, 1, 2085, 0, 0, 0, 1, 2086, 0, 0, 0, 1, 2087, 0, 0, 0, 1, 2088, 0, 0, 0, 1, 2089, 0, 0, 0, 1, 2090, 0, 0, 0, 1, 2091, 0, 0, 0, 1, 2099, 0, 0, 0, 10, 2095, 12, 0, 0, 7, 2096, 10, 0, 0, 3, 228, 114, 2098, 13, 1, 2094, 0, 0, 0, 1, 2101, 0, 0, 0, 1, 2097, 0, 0, 0, 1, 2100, 0, 0, 0, 1, 229, 0, 0, 0, 1, 2099, 0, 0, 0, 259, 296, 148, 2103, 0, 1, 231, 0, 0, 0, 3, 152, 76, 2105, 0, 259, 234, 117, 2106, 0, 1, 233, 0, 0, 0, 259, 236, 118, 2111, 0, 259, 238, 119, 2111, 0, 259, 240, 120, 2111, 0, 1, 2107, 0, 0, 0, 1, 2108, 0, 0, 0, 1, 2109, 0, 0, 0, 1, 235, 0, 0, 0, 5, 2113, 173, 0, 0, 1, 237, 0, 0, 0, 5, 2123, 200, 0, 0, 3, 234, 117, 2120, 0, 5, 2117, 163, 0, 0, 3, 234, 117, 2119, 0, 1, 2116, 0, 0, 0, 1, 2122, 0, 0, 0, 1, 2118, 0, 0, 0, 1, 2121, 0, 0, 0, 1, 2124, 0, 0, 0, 1, 2120, 0, 0, 0, 1, 2115, 0, 0, 0, 1, 2124, 0, 0, 0, 1, 2125, 0, 0, 0, 5, 2126, 201, 0, 0, 1, 239, 0, 0, 0, 7, 2128, 11, 0, 0, 1, 241, 0, 0, 0, 5, 2130, 173, 0, 0, 1, 243, 0, 0, 0, 5, 2143, 202, 0, 0, 3, 228, 114, 2137, 0, 5, 2134, 163, 0, 0, 3, 228, 114, 2136, 0, 1, 2133, 0, 0, 0, 1, 2139, 0, 0, 0, 1, 2135, 0, 0, 0, 1, 2138, 0, 0, 0, 1, 2141, 0, 0, 0, 1, 2137, 0, 0, 0, 5, 2142, 163, 0, 0, 1, 2140, 0, 0, 0, 1, 2142, 0, 0, 0, 1, 2144, 0, 0, 0, 1, 2132, 0, 0, 0, 1, 2144, 0, 0, 0, 1, 2145, 0, 0, 0, 5, 2147, 203, 0, 0, 259, 234, 117, 2148, 0, 1, 2146, 0, 0, 0, 1, 2148, 0, 0, 0, 1, 245, 0, 0, 0, 5, 2150, 200, 0, 0, 3, 228, 114, 2151, 0, 5, 2152, 201, 0, 0, 1, 247, 0, 0, 0, 3, 152, 76, 2155, 0, 1, 2153, 0, 0, 0, 1, 2155, 0, 0, 0, 1, 2157, 0, 0, 0, 3, 250, 125, 2158, 0, 1, 2156, 0, 0, 0, 1, 2158, 0, 0, 0, 1, 2160, 0, 0, 0, 3, 258, 129, 2161, 0, 1, 2159, 0, 0, 0, 1, 2161, 0, 0, 0, 1, 2163, 0, 0, 0, 259, 234, 117, 2164, 0, 1, 2162, 0, 0, 0, 1, 2164, 0, 0, 0, 1, 249, 0, 0, 0, 5, 2174, 200, 0, 0, 3, 252, 126, 2171, 0, 5, 2168, 163, 0, 0, 3, 252, 126, 2170, 0, 1, 2167, 0, 0, 0, 1, 2173, 0, 0, 0, 1, 2169, 0, 0, 0, 1, 2172, 0, 0, 0, 1, 2175, 0, 0, 0, 1, 2171, 0, 0, 0, 1, 2166, 0, 0, 0, 1, 2175, 0, 0, 0, 1, 2176, 0, 0, 0, 5, 2177, 201, 0, 0, 1, 251, 0, 0, 0, 3, 254, 127, 2180, 0, 1, 2178, 0, 0, 0, 1, 2180, 0, 0, 0, 1, 2181, 0, 0, 0, 259, 228, 114, 2182, 0, 1, 253, 0, 0, 0, 259, 256, 128, 2186, 0, 259, 30, 15, 2186, 0, 1, 2183, 0, 0, 0, 1, 2184, 0, 0, 0, 1, 255, 0, 0, 0, 3, 296, 148, 2188, 0, 5, 2189, 199, 0, 0, 1, 257, 0, 0, 0, 5, 2202, 197, 0, 0, 3, 252, 126, 2196, 0, 5, 2193, 163, 0, 0, 3, 252, 126, 2195, 0, 1, 2192, 0, 0, 0, 1, 2198, 0, 0, 0, 1, 2194, 0, 0, 0, 1, 2197, 0, 0, 0, 1, 2200, 0, 0, 0, 1, 2196, 0, 0, 0, 5, 2201, 163, 0, 0, 1, 2199, 0, 0, 0, 1, 2201, 0, 0, 0, 1, 2203, 0, 0, 0, 1, 2191, 0, 0, 0, 1, 2203, 0, 0, 0, 1, 2204, 0, 0, 0, 5, 2205, 198, 0, 0, 1, 259, 0, 0, 0, 5, 2207, 120, 0, 0, 259, 296, 148, 2219, 0, 5, 2209, 168, 0, 0, 259, 296, 148, 2219, 0, 5, 2211, 136, 0, 0, 259, 296, 148, 2219, 0, 5, 2213, 137, 0, 0, 259, 296, 148, 2219, 0, 5, 2215, 170, 0, 0, 259, 296, 148, 2219, 0, 5, 2217, 139, 0, 0, 259, 296, 148, 2219, 0, 1, 2206, 0, 0, 0, 1, 2208, 0, 0, 0, 1, 2210, 0, 0, 0, 1, 2212, 0, 0, 0, 1, 2214, 0, 0, 0, 1, 2216, 0, 0, 0, 1, 261, 0, 0, 0, 5, 2222, 130, 0, 0, 259, 228, 114, 2223, 0, 1, 2221, 0, 0, 0, 1, 2223, 0, 0, 0, 1, 263, 0, 0, 0, 259, 152, 76, 2225, 0, 1, 265, 0, 0, 0, 5, 2227, 114, 0, 0, 259, 228, 114, 2228, 0, 1, 267, 0, 0, 0, 5, 2230, 119, 0, 0, 259, 234, 117, 2231, 0, 1, 269, 0, 0, 0, 5, 2233, 102, 0, 0, 259, 296, 148, 2234, 0, 1, 271, 0, 0, 0, 5, 2236, 84, 0, 0, 3, 296, 148, 2237, 0, 5, 2238, 199, 0, 0, 1, 273, 0, 0, 0, 5, 2240, 29, 0, 0, 5, 2241, 199, 0, 0, 1, 275, 0, 0, 0, 3, 10, 5, 2244, 0, 1, 2242, 0, 0, 0, 1, 2247, 0, 0, 0, 1, 2243, 0, 0, 0, 1, 2246, 0, 0, 0, 1, 2248, 0, 0, 0, 1, 2245, 0, 0, 0, 5, 2250, 74, 0, 0, 3, 296, 148, 2251, 0, 1, 2249, 0, 0, 0, 1, 2251, 0, 0, 0, 1, 2252, 0, 0, 0, 5, 2253, 167, 0, 0, 1, 277, 0, 0, 0, 3, 10, 5, 2256, 0, 1, 2254, 0, 0, 0, 1, 2259, 0, 0, 0, 1, 2255, 0, 0, 0, 1, 2258, 0, 0, 0, 1, 2260, 0, 0, 0, 1, 2257, 0, 0, 0, 5, 2261, 118, 0, 0, 3, 64, 32, 2265, 0, 3, 280, 140, 2264, 0, 1, 2262, 0, 0, 0, 1, 2267, 0, 0, 0, 1, 2263, 0, 0, 0, 1, 2266, 0, 0, 0, 1, 2269, 0, 0, 0, 1, 2265, 0, 0, 0, 259, 286, 143, 2270, 0, 1, 2268, 0, 0, 0, 1, 2270, 0, 0, 0, 1, 279, 0, 0, 0, 5, 2273, 63, 0, 0, 3, 282, 141, 2274, 0, 1, 2272, 0, 0, 0, 1, 2274, 0, 0, 0, 1, 2276, 0, 0, 0, 3, 284, 142, 2277, 0, 1, 2275, 0, 0, 0, 1, 2277, 0, 0, 0, 1, 2278, 0, 0, 0, 259, 64, 32, 2279, 0, 1, 281, 0, 0, 0, 5, 2281, 200, 0, 0, 3, 152, 76, 2283, 0, 3, 442, 221, 2284, 0, 1, 2282, 0, 0, 0, 1, 2284, 0, 0, 0, 1, 2285, 0, 0, 0, 5, 2286, 201, 0, 0, 1, 283, 0, 0, 0, 5, 2288, 102, 0, 0, 5, 2289, 200, 0, 0, 3, 296, 148, 2290, 0, 5, 2291, 201, 0, 0, 1, 285, 0, 0, 0, 5, 2293, 30, 0, 0, 259, 64, 32, 2294, 0, 1, 287, 0, 0, 0, 3, 10, 5, 2297, 0, 1, 2295, 0, 0, 0, 1, 2300, 0, 0, 0, 1, 2296, 0, 0, 0, 1, 2299, 0, 0, 0, 1, 2301, 0, 0, 0, 1, 2298, 0, 0, 0, 5, 2302, 57, 0, 0, 259, 64, 32, 2303, 0, 1, 289, 0, 0, 0, 3, 10, 5, 2306, 0, 1, 2304, 0, 0, 0, 1, 2309, 0, 0, 0, 1, 2305, 0, 0, 0, 1, 2308, 0, 0, 0, 1, 2311, 0, 0, 0, 1, 2307, 0, 0, 0, 5, 2312, 61, 0, 0, 1, 2310, 0, 0, 0, 1, 2312, 0, 0, 0, 1, 2313, 0, 0, 0, 5, 2314, 77, 0, 0, 5, 2317, 200, 0, 0, 3, 40, 20, 2318, 0, 3, 296, 148, 2318, 0, 1, 2315, 0, 0, 0, 1, 2316, 0, 0, 0, 1, 2319, 0, 0, 0, 5, 2320, 201, 0, 0, 259, 180, 90, 2321, 0, 1, 291, 0, 0, 0, 3, 10, 5, 2324, 0, 1, 2322, 0, 0, 0, 1, 2327, 0, 0, 0, 1, 2323, 0, 0, 0, 1, 2326, 0, 0, 0, 1, 2328, 0, 0, 0, 1, 2325, 0, 0, 0, 5, 2329, 79, 0, 0, 5, 2330, 200, 0, 0, 3, 296, 148, 2331, 0, 5, 2332, 201, 0, 0, 259, 180, 90, 2333, 0, 1, 293, 0, 0, 0, 3, 10, 5, 2336, 0, 1, 2334, 0, 0, 0, 1, 2339, 0, 0, 0, 1, 2335, 0, 0, 0, 1, 2338, 0, 0, 0, 1, 2340, 0, 0, 0, 1, 2337, 0, 0, 0, 5, 2341, 80, 0, 0, 7, 2343, 12, 0, 0, 3, 296, 148, 2344, 0, 1, 2342, 0, 0, 0, 1, 2344, 0, 0, 0, 1, 2345, 0, 0, 0, 5, 2346, 167, 0, 0, 1, 295, 0, 0, 0, 6, 2348, 148, 4294967295, 0, 3, 298, 149, 2387, 0, 3, 308, 154, 2387, 0, 3, 312, 156, 2387, 0, 3, 316, 158, 2387, 0, 3, 318, 159, 2387, 0, 3, 324, 162, 2387, 0, 3, 326, 163, 2387, 0, 3, 328, 164, 2387, 0, 3, 340, 170, 2387, 0, 3, 342, 171, 2387, 0, 3, 344, 172, 2387, 0, 3, 346, 173, 2387, 0, 3, 348, 174, 2387, 0, 3, 350, 175, 2387, 0, 3, 314, 157, 2387, 0, 3, 352, 176, 2387, 0, 3, 358, 179, 2387, 0, 3, 376, 188, 2387, 0, 3, 384, 192, 2387, 0, 3, 386, 193, 2387, 0, 3, 388, 194, 2387, 0, 3, 390, 195, 2387, 0, 3, 392, 196, 2387, 0, 5, 2373, 130, 0, 0, 3, 296, 148, 2374, 0, 1, 2372, 0, 0, 0, 1, 2374, 0, 0, 0, 1, 2387, 0, 0, 0, 3, 420, 210, 2387, 0, 3, 422, 211, 2387, 0, 3, 424, 212, 2387, 0, 3, 426, 213, 2387, 0, 3, 428, 214, 2387, 0, 3, 432, 216, 2387, 0, 3, 434, 217, 2387, 0, 3, 152, 76, 2387, 0, 3, 436, 218, 2387, 0, 3, 438, 219, 2387, 0, 3, 338, 169, 2387, 0, 1, 2347, 0, 0, 0, 1, 2349, 0, 0, 0, 1, 2350, 0, 0, 0, 1, 2351, 0, 0, 0, 1, 2352, 0, 0, 0, 1, 2353, 0, 0, 0, 1, 2354, 0, 0, 0, 1, 2355, 0, 0, 0, 1, 2356, 0, 0, 0, 1, 2357, 0, 0, 0, 1, 2358, 0, 0, 0, 1, 2359, 0, 0, 0, 1, 2360, 0, 0, 0, 1, 2361, 0, 0, 0, 1, 2362, 0, 0, 0, 1, 2363, 0, 0, 0, 1, 2364, 0, 0, 0, 1, 2365, 0, 0, 0, 1, 2366, 0, 0, 0, 1, 2367, 0, 0, 0, 1, 2368, 0, 0, 0, 1, 2369, 0, 0, 0, 1, 2370, 0, 0, 0, 1, 2371, 0, 0, 0, 1, 2375, 0, 0, 0, 1, 2376, 0, 0, 0, 1, 2377, 0, 0, 0, 1, 2378, 0, 0, 0, 1, 2379, 0, 0, 0, 1, 2380, 0, 0, 0, 1, 2381, 0, 0, 0, 1, 2382, 0, 0, 0, 1, 2383, 0, 0, 0, 1, 2384, 0, 0, 0, 1, 2385, 0, 0, 0, 1, 2479, 0, 0, 0, 10, 2402, 44, 0, 0, 5, 2403, 169, 0, 0, 5, 2403, 126, 0, 0, 5, 2403, 128, 0, 0, 5, 2403, 124, 0, 0, 5, 2403, 131, 0, 0, 5, 2403, 121, 0, 0, 5, 2403, 123, 0, 0, 5, 2403, 144, 0, 0, 5, 2403, 154, 0, 0, 5, 2403, 105, 0, 0, 3, 480, 240, 2403, 0, 3, 482, 241, 2403, 0, 5, 2403, 106, 0, 0, 1, 2389, 0, 0, 0, 1, 2390, 0, 0, 0, 1, 2391, 0, 0, 0, 1, 2392, 0, 0, 0, 1, 2393, 0, 0, 0, 1, 2394, 0, 0, 0, 1, 2395, 0, 0, 0, 1, 2396, 0, 0, 0, 1, 2397, 0, 0, 0, 1, 2398, 0, 0, 0, 1, 2399, 0, 0, 0, 1, 2400, 0, 0, 0, 1, 2401, 0, 0, 0, 1, 2404, 0, 0, 0, 3, 296, 148, 2478, 45, 10, 2428, 41, 0, 0, 5, 2429, 162, 0, 0, 5, 2429, 164, 0, 0, 5, 2429, 161, 0, 0, 5, 2429, 166, 0, 0, 5, 2429, 159, 0, 0, 5, 2429, 135, 0, 0, 3, 476, 238, 2429, 0, 3, 478, 239, 2429, 0, 5, 2429, 155, 0, 0, 5, 2429, 122, 0, 0, 5, 2429, 174, 0, 0, 5, 2429, 160, 0, 0, 5, 2429, 172, 0, 0, 5, 2429, 137, 0, 0, 5, 2429, 120, 0, 0, 5, 2429, 168, 0, 0, 5, 2429, 136, 0, 0, 5, 2429, 170, 0, 0, 5, 2429, 139, 0, 0, 5, 2429, 150, 0, 0, 5, 2429, 145, 0, 0, 5, 2429, 140, 0, 0, 1, 2406, 0, 0, 0, 1, 2407, 0, 0, 0, 1, 2408, 0, 0, 0, 1, 2409, 0, 0, 0, 1, 2410, 0, 0, 0, 1, 2411, 0, 0, 0, 1, 2412, 0, 0, 0, 1, 2413, 0, 0, 0, 1, 2414, 0, 0, 0, 1, 2415, 0, 0, 0, 1, 2416, 0, 0, 0, 1, 2417, 0, 0, 0, 1, 2418, 0, 0, 0, 1, 2419, 0, 0, 0, 1, 2420, 0, 0, 0, 1, 2421, 0, 0, 0, 1, 2422, 0, 0, 0, 1, 2423, 0, 0, 0, 1, 2424, 0, 0, 0, 1, 2425, 0, 0, 0, 1, 2426, 0, 0, 0, 1, 2427, 0, 0, 0, 1, 2430, 0, 0, 0, 3, 296, 148, 2478, 42, 10, 2432, 37, 0, 0, 5, 2433, 171, 0, 0, 3, 296, 148, 2478, 38, 10, 2435, 36, 0, 0, 5, 2436, 171, 0, 0, 3, 296, 148, 2437, 0, 5, 2438, 199, 0, 0, 3, 296, 148, 2439, 37, 1, 2478, 0, 0, 0, 10, 2441, 34, 0, 0, 3, 44, 22, 2478, 0, 10, 2443, 25, 0, 0, 3, 62, 31, 2478, 0, 10, 2445, 24, 0, 0, 5, 2446, 150, 0, 0, 3, 228, 114, 2478, 0, 10, 2448, 21, 0, 0, 7, 2449, 13, 0, 0, 3, 20, 10, 2478, 0, 10, 2451, 18, 0, 0, 7, 2478, 14, 0, 0, 10, 2453, 15, 0, 0, 5, 2455, 130, 0, 0, 3, 296, 148, 2456, 0, 1, 2454, 0, 0, 0, 1, 2456, 0, 0, 0, 1, 2478, 0, 0, 0, 10, 2458, 8, 0, 0, 5, 2459, 55, 0, 0, 5, 2471, 197, 0, 0, 3, 430, 215, 2465, 0, 5, 2462, 163, 0, 0, 3, 430, 215, 2464, 0, 1, 2461, 0, 0, 0, 1, 2467, 0, 0, 0, 1, 2463, 0, 0, 0, 1, 2466, 0, 0, 0, 1, 2469, 0, 0, 0, 1, 2465, 0, 0, 0, 5, 2470, 163, 0, 0, 1, 2468, 0, 0, 0, 1, 2470, 0, 0, 0, 1, 2472, 0, 0, 0, 1, 2460, 0, 0, 0, 1, 2472, 0, 0, 0, 1, 2473, 0, 0, 0, 5, 2478, 198, 0, 0, 10, 2475, 2, 0, 0, 5, 2476, 103, 0, 0, 3, 314, 157, 2478, 0, 1, 2388, 0, 0, 0, 1, 2405, 0, 0, 0, 1, 2431, 0, 0, 0, 1, 2434, 0, 0, 0, 1, 2440, 0, 0, 0, 1, 2442, 0, 0, 0, 1, 2444, 0, 0, 0, 1, 2447, 0, 0, 0, 1, 2450, 0, 0, 0, 1, 2452, 0, 0, 0, 1, 2457, 0, 0, 0, 1, 2474, 0, 0, 0, 1, 2481, 0, 0, 0, 1, 2477, 0, 0, 0, 1, 2480, 0, 0, 0, 1, 297, 0, 0, 0, 1, 2479, 0, 0, 0, 259, 300, 150, 2485, 0, 259, 302, 151, 2485, 0, 1, 2482, 0, 0, 0, 1, 2483, 0, 0, 0, 1, 299, 0, 0, 0, 3, 38, 19, 2488, 0, 1, 2486, 0, 0, 0, 1, 2491, 0, 0, 0, 1, 2487, 0, 0, 0, 1, 2490, 0, 0, 0, 1, 2492, 0, 0, 0, 1, 2489, 0, 0, 0, 5, 2494, 18, 0, 0, 3, 56, 28, 2495, 0, 1, 2493, 0, 0, 0, 1, 2495, 0, 0, 0, 1, 2496, 0, 0, 0, 3, 64, 32, 2498, 0, 259, 296, 148, 2499, 0, 1, 2497, 0, 0, 0, 1, 2499, 0, 0, 0, 1, 301, 0, 0, 0, 259, 304, 152, 2503, 0, 259, 306, 153, 2503, 0, 1, 2500, 0, 0, 0, 1, 2501, 0, 0, 0, 1, 303, 0, 0, 0, 3, 10, 5, 2506, 0, 1, 2504, 0, 0, 0, 1, 2509, 0, 0, 0, 1, 2505, 0, 0, 0, 1, 2508, 0, 0, 0, 1, 2513, 0, 0, 0, 1, 2507, 0, 0, 0, 3, 38, 19, 2512, 0, 1, 2510, 0, 0, 0, 1, 2515, 0, 0, 0, 1, 2511, 0, 0, 0, 1, 2514, 0, 0, 0, 1, 2517, 0, 0, 0, 1, 2513, 0, 0, 0, 3, 152, 76, 2518, 0, 1, 2516, 0, 0, 0, 1, 2518, 0, 0, 0, 1, 2519, 0, 0, 0, 3, 56, 28, 2520, 0, 5, 2523, 138, 0, 0, 259, 64, 32, 2524, 0, 259, 296, 148, 2524, 0, 1, 2521, 0, 0, 0, 1, 2522, 0, 0, 0, 1, 305, 0, 0, 0, 3, 10, 5, 2527, 0, 1, 2525, 0, 0, 0, 1, 2530, 0, 0, 0, 1, 2526, 0, 0, 0, 1, 2529, 0, 0, 0, 1, 2534, 0, 0, 0, 1, 2528, 0, 0, 0, 3, 38, 19, 2533, 0, 1, 2531, 0, 0, 0, 1, 2536, 0, 0, 0, 1, 2532, 0, 0, 0, 1, 2535, 0, 0, 0, 1, 2537, 0, 0, 0, 1, 2534, 0, 0, 0, 3, 442, 221, 2538, 0, 5, 2541, 138, 0, 0, 259, 64, 32, 2542, 0, 259, 296, 148, 2542, 0, 1, 2539, 0, 0, 0, 1, 2540, 0, 0, 0, 1, 307, 0, 0, 0, 5, 2544, 113, 0, 0, 5, 2556, 197, 0, 0, 3, 310, 155, 2550, 0, 5, 2547, 163, 0, 0, 3, 310, 155, 2549, 0, 1, 2546, 0, 0, 0, 1, 2552, 0, 0, 0, 1, 2548, 0, 0, 0, 1, 2551, 0, 0, 0, 1, 2554, 0, 0, 0, 1, 2550, 0, 0, 0, 5, 2555, 163, 0, 0, 1, 2553, 0, 0, 0, 1, 2555, 0, 0, 0, 1, 2557, 0, 0, 0, 1, 2545, 0, 0, 0, 1, 2557, 0, 0, 0, 1, 2558, 0, 0, 0, 5, 2559, 198, 0, 0, 1, 309, 0, 0, 0, 3, 6, 3, 2562, 0, 1, 2560, 0, 0, 0, 1, 2562, 0, 0, 0, 1, 2563, 0, 0, 0, 259, 296, 148, 2564, 0, 1, 311, 0, 0, 0, 5, 2566, 113, 0, 0, 3, 154, 77, 2568, 0, 259, 314, 157, 2569, 0, 1, 2567, 0, 0, 0, 1, 2569, 0, 0, 0, 1, 313, 0, 0, 0, 5, 2582, 197, 0, 0, 3, 296, 148, 2576, 0, 5, 2573, 163, 0, 0, 3, 296, 148, 2575, 0, 1, 2572, 0, 0, 0, 1, 2578, 0, 0, 0, 1, 2574, 0, 0, 0, 1, 2577, 0, 0, 0, 1, 2580, 0, 0, 0, 1, 2576, 0, 0, 0, 5, 2581, 163, 0, 0, 1, 2579, 0, 0, 0, 1, 2581, 0, 0, 0, 1, 2583, 0, 0, 0, 1, 2571, 0, 0, 0, 1, 2583, 0, 0, 0, 1, 2584, 0, 0, 0, 5, 2585, 198, 0, 0, 1, 315, 0, 0, 0, 5, 2587, 61, 0, 0, 259, 296, 148, 2588, 0, 1, 317, 0, 0, 0, 259, 320, 160, 2592, 0, 259, 322, 161, 2592, 0, 1, 2589, 0, 0, 0, 1, 2590, 0, 0, 0, 1, 319, 0, 0, 0, 5, 2594, 113, 0, 0, 3, 62, 31, 2596, 0, 259, 314, 157, 2597, 0, 1, 2595, 0, 0, 0, 1, 2597, 0, 0, 0, 1, 321, 0, 0, 0, 5, 2599, 113, 0, 0, 3, 152, 76, 2601, 0, 3, 62, 31, 2602, 0, 1, 2600, 0, 0, 0, 1, 2602, 0, 0, 0, 1, 2604, 0, 0, 0, 259, 314, 157, 2605, 0, 1, 2603, 0, 0, 0, 1, 2605, 0, 0, 0, 1, 323, 0, 0, 0, 5, 2607, 200, 0, 0, 3, 152, 76, 2608, 0, 5, 2609, 201, 0, 0, 259, 296, 148, 2610, 0, 1, 325, 0, 0, 0, 5, 2612, 27, 0, 0, 5, 2613, 200, 0, 0, 3, 296, 148, 2614, 0, 5, 2615, 201, 0, 0, 1, 2622, 0, 0, 0, 5, 2617, 14, 0, 0, 5, 2618, 200, 0, 0, 3, 296, 148, 2619, 0, 5, 2620, 201, 0, 0, 1, 2622, 0, 0, 0, 1, 2611, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 327, 0, 0, 0, 5, 2635, 202, 0, 0, 3, 330, 165, 2629, 0, 5, 2626, 163, 0, 0, 3, 330, 165, 2628, 0, 1, 2625, 0, 0, 0, 1, 2631, 0, 0, 0, 1, 2627, 0, 0, 0, 1, 2630, 0, 0, 0, 1, 2633, 0, 0, 0, 1, 2629, 0, 0, 0, 5, 2634, 163, 0, 0, 1, 2632, 0, 0, 0, 1, 2634, 0, 0, 0, 1, 2636, 0, 0, 0, 1, 2624, 0, 0, 0, 1, 2636, 0, 0, 0, 1, 2637, 0, 0, 0, 5, 2638, 203, 0, 0, 1, 329, 0, 0, 0, 259, 332, 166, 2643, 0, 259, 334, 167, 2643, 0, 259, 336, 168, 2643, 0, 1, 2639, 0, 0, 0, 1, 2640, 0, 0, 0, 1, 2641, 0, 0, 0, 1, 331, 0, 0, 0, 259, 296, 148, 2645, 0, 1, 333, 0, 0, 0, 5, 2647, 130, 0, 0, 259, 296, 148, 2648, 0, 1, 335, 0, 0, 0, 5, 2650, 103, 0, 0, 259, 62, 31, 2651, 0, 1, 337, 0, 0, 0, 3, 152, 76, 2653, 0, 259, 234, 117, 2654, 0, 1, 339, 0, 0, 0, 5, 2656, 29, 0, 0, 5, 2657, 200, 0, 0, 3, 152, 76, 2658, 0, 5, 2659, 201, 0, 0, 1, 341, 0, 0, 0, 259, 44, 22, 2661, 0, 1, 343, 0, 0, 0, 5, 2663, 68, 0, 0, 1, 345, 0, 0, 0, 5, 2665, 113, 0, 0, 5, 2669, 202, 0, 0, 5, 2668, 163, 0, 0, 1, 2666, 0, 0, 0, 1, 2671, 0, 0, 0, 1, 2667, 0, 0, 0, 1, 2670, 0, 0, 0, 1, 2672, 0, 0, 0, 1, 2669, 0, 0, 0, 5, 2673, 203, 0, 0, 259, 314, 157, 2674, 0, 1, 347, 0, 0, 0, 259, 44, 22, 2676, 0, 1, 349, 0, 0, 0, 5, 2678, 5, 0, 0, 5, 2679, 202, 0, 0, 5, 2680, 203, 0, 0, 259, 314, 157, 2681, 0, 1, 351, 0, 0, 0, 259, 354, 177, 2685, 0, 259, 356, 178, 2685, 0, 1, 2682, 0, 0, 0, 1, 2683, 0, 0, 0, 1, 353, 0, 0, 0, 5, 2687, 81, 0, 0, 1, 355, 0, 0, 0, 5, 2689, 98, 0, 0, 1, 357, 0, 0, 0, 5, 2694, 194, 0, 0, 3, 360, 180, 2693, 0, 1, 2691, 0, 0, 0, 1, 2696, 0, 0, 0, 1, 2692, 0, 0, 0, 1, 2695, 0, 0, 0, 1, 2697, 0, 0, 0, 1, 2694, 0, 0, 0, 5, 2725, 157, 0, 0, 5, 2702, 195, 0, 0, 3, 360, 180, 2701, 0, 1, 2699, 0, 0, 0, 1, 2704, 0, 0, 0, 1, 2700, 0, 0, 0, 1, 2703, 0, 0, 0, 1, 2705, 0, 0, 0, 1, 2702, 0, 0, 0, 5, 2725, 157, 0, 0, 3, 370, 185, 2710, 0, 3, 360, 180, 2709, 0, 1, 2707, 0, 0, 0, 1, 2712, 0, 0, 0, 1, 2708, 0, 0, 0, 1, 2711, 0, 0, 0, 1, 2713, 0, 0, 0, 1, 2710, 0, 0, 0, 259, 372, 186, 2714, 0, 1, 2725, 0, 0, 0, 3, 374, 187, 2719, 0, 3, 360, 180, 2718, 0, 1, 2716, 0, 0, 0, 1, 2721, 0, 0, 0, 1, 2717, 0, 0, 0, 1, 2720, 0, 0, 0, 1, 2722, 0, 0, 0, 1, 2719, 0, 0, 0, 259, 372, 186, 2723, 0, 1, 2725, 0, 0, 0, 1, 2690, 0, 0, 0, 1, 2698, 0, 0, 0, 1, 2706, 0, 0, 0, 1, 2715, 0, 0, 0, 1, 359, 0, 0, 0, 259, 362, 181, 2729, 0, 259, 364, 182, 2729, 0, 1, 2726, 0, 0, 0, 1, 2727, 0, 0, 0, 1, 361, 0, 0, 0, 259, 468, 234, 2731, 0, 1, 363, 0, 0, 0, 5, 2733, 197, 0, 0, 3, 296, 148, 2735, 0, 3, 366, 183, 2736, 0, 1, 2734, 0, 0, 0, 1, 2736, 0, 0, 0, 1, 2738, 0, 0, 0, 3, 368, 184, 2739, 0, 1, 2737, 0, 0, 0, 1, 2739, 0, 0, 0, 1, 2740, 0, 0, 0, 5, 2741, 198, 0, 0, 1, 365, 0, 0, 0, 5, 2743, 163, 0, 0, 259, 296, 148, 2744, 0, 1, 367, 0, 0, 0, 5, 2746, 199, 0, 0, 259, 468, 234, 2747, 0, 1, 369, 0, 0, 0, 5, 2749, 196, 0, 0, 1, 371, 0, 0, 0, 5, 2754, 104, 0, 0, 5, 2753, 157, 0, 0, 1, 2751, 0, 0, 0, 1, 2756, 0, 0, 0, 1, 2752, 0, 0, 0, 1, 2755, 0, 0, 0, 1, 373, 0, 0, 0, 1, 2754, 0, 0, 0, 5, 2758, 196, 0, 0, 1, 375, 0, 0, 0, 5, 2773, 29, 0, 0, 5, 2773, 67, 0, 0, 5, 2773, 96, 0, 0, 5, 2773, 99, 0, 0, 5, 2773, 6, 0, 0, 259, 456, 228, 2773, 0, 259, 470, 235, 2773, 0, 259, 446, 223, 2773, 0, 259, 472, 236, 2773, 0, 259, 458, 229, 2773, 0, 259, 378, 189, 2773, 0, 259, 380, 190, 2773, 0, 259, 382, 191, 2773, 0, 1, 2759, 0, 0, 0, 1, 2760, 0, 0, 0, 1, 2761, 0, 0, 0, 1, 2762, 0, 0, 0, 1, 2763, 0, 0, 0, 1, 2764, 0, 0, 0, 1, 2765, 0, 0, 0, 1, 2766, 0, 0, 0, 1, 2767, 0, 0, 0, 1, 2768, 0, 0, 0, 1, 2769, 0, 0, 0, 1, 2770, 0, 0, 0, 1, 2771, 0, 0, 0, 1, 377, 0, 0, 0, 3, 470, 235, 2775, 0, 7, 2776, 15, 0, 0, 1, 379, 0, 0, 0, 3, 472, 236, 2778, 0, 7, 2779, 15, 0, 0, 1, 381, 0, 0, 0, 3, 458, 229, 2781, 0, 7, 2782, 15, 0, 0, 1, 383, 0, 0, 0, 5, 2784, 7, 0, 0, 5, 2785, 200, 0, 0, 3, 296, 148, 2786, 0, 5, 2787, 201, 0, 0, 1, 385, 0, 0, 0, 5, 2789, 165, 0, 0, 259, 20, 10, 2790, 0, 1, 387, 0, 0, 0, 5, 2792, 200, 0, 0, 3, 296, 148, 2793, 0, 5, 2794, 201, 0, 0, 1, 389, 0, 0, 0, 5, 2796, 156, 0, 0, 259, 296, 148, 2814, 0, 5, 2798, 160, 0, 0, 259, 296, 148, 2814, 0, 5, 2800, 161, 0, 0, 259, 296, 148, 2814, 0, 5, 2802, 162, 0, 0, 259, 296, 148, 2814, 0, 5, 2804, 125, 0, 0, 259, 296, 148, 2814, 0, 5, 2806, 164, 0, 0, 259, 296, 148, 2814, 0, 5, 2808, 127, 0, 0, 259, 296, 148, 2814, 0, 5, 2810, 172, 0, 0, 259, 296, 148, 2814, 0, 5, 2812, 175, 0, 0, 259, 296, 148, 2814, 0, 1, 2795, 0, 0, 0, 1, 2797, 0, 0, 0, 1, 2799, 0, 0, 0, 1, 2801, 0, 0, 0, 1, 2803, 0, 0, 0, 1, 2805, 0, 0, 0, 1, 2807, 0, 0, 0, 1, 2809, 0, 0, 0, 1, 2811, 0, 0, 0, 1, 391, 0, 0, 0, 3, 394, 197, 2816, 0, 259, 396, 198, 2817, 0, 1, 393, 0, 0, 0, 5, 2820, 89, 0, 0, 3, 152, 76, 2821, 0, 1, 2819, 0, 0, 0, 1, 2821, 0, 0, 0, 1, 2822, 0, 0, 0, 3, 442, 221, 2823, 0, 5, 2824, 149, 0, 0, 259, 296, 148, 2825, 0, 1, 395, 0, 0, 0, 3, 398, 199, 2828, 0, 1, 2826, 0, 0, 0, 1, 2831, 0, 0, 0, 1, 2827, 0, 0, 0, 1, 2830, 0, 0, 0, 1, 2832, 0, 0, 0, 1, 2829, 0, 0, 0, 3, 412, 206, 2834, 0, 259, 418, 209, 2835, 0, 1, 2833, 0, 0, 0, 1, 2835, 0, 0, 0, 1, 397, 0, 0, 0, 259, 394, 197, 2842, 0, 259, 400, 200, 2842, 0, 259, 404, 202, 2842, 0, 259, 406, 203, 2842, 0, 259, 410, 205, 2842, 0, 1, 2836, 0, 0, 0, 1, 2837, 0, 0, 0, 1, 2838, 0, 0, 0, 1, 2839, 0, 0, 0, 1, 2840, 0, 0, 0, 1, 399, 0, 0, 0, 5, 2845, 93, 0, 0, 3, 152, 76, 2846, 0, 1, 2844, 0, 0, 0, 1, 2846, 0, 0, 0, 1, 2847, 0, 0, 0, 3, 442, 221, 2848, 0, 5, 2849, 149, 0, 0, 3, 296, 148, 2850, 0, 5, 2851, 151, 0, 0, 3, 296, 148, 2852, 0, 5, 2853, 40, 0, 0, 3, 296, 148, 2855, 0, 259, 402, 201, 2856, 0, 1, 2854, 0, 0, 0, 1, 2856, 0, 0, 0, 1, 401, 0, 0, 0, 5, 2858, 92, 0, 0, 259, 442, 221, 2859, 0, 1, 403, 0, 0, 0, 5, 2861, 112, 0, 0, 3, 442, 221, 2862, 0, 5, 2863, 169, 0, 0, 259, 296, 148, 2864, 0, 1, 405, 0, 0, 0, 5, 2866, 33, 0, 0, 3, 408, 204, 2871, 0, 5, 2868, 163, 0, 0, 3, 408, 204, 2870, 0, 1, 2867, 0, 0, 0, 1, 2873, 0, 0, 0, 1, 2869, 0, 0, 0, 1, 2872, 0, 0, 0, 1, 407, 0, 0, 0, 1, 2871, 0, 0, 0, 3, 296, 148, 2876, 0, 7, 2877, 16, 0, 0, 1, 2875, 0, 0, 0, 1, 2877, 0, 0, 0, 1, 409, 0, 0, 0, 5, 2879, 78, 0, 0, 259, 296, 148, 2880, 0, 1, 411, 0, 0, 0, 259, 414, 207, 2884, 0, 259, 416, 208, 2884, 0, 1, 2881, 0, 0, 0, 1, 2882, 0, 0, 0, 1, 413, 0, 0, 0, 5, 2886, 71, 0, 0, 3, 296, 148, 2887, 0, 5, 2888, 146, 0, 0, 259, 296, 148, 2889, 0, 1, 415, 0, 0, 0, 5, 2891, 50, 0, 0, 259, 296, 148, 2892, 0, 1, 417, 0, 0, 0, 5, 2894, 92, 0, 0, 3, 442, 221, 2895, 0, 259, 396, 198, 2896, 0, 1, 419, 0, 0, 0, 5, 2898, 116, 0, 0, 259, 296, 148, 2899, 0, 1, 421, 0, 0, 0, 5, 2901, 8, 0, 0, 5, 2902, 200, 0, 0, 3, 296, 148, 2903, 0, 5, 2904, 201, 0, 0, 1, 423, 0, 0, 0, 5, 2906, 3, 0, 0, 5, 2907, 200, 0, 0, 3, 296, 148, 2908, 0, 5, 2909, 163, 0, 0, 3, 152, 76, 2910, 0, 5, 2911, 201, 0, 0, 1, 425, 0, 0, 0, 5, 2913, 51, 0, 0, 5, 2914, 200, 0, 0, 3, 152, 76, 2915, 0, 5, 2916, 201, 0, 0, 1, 427, 0, 0, 0, 5, 2918, 5, 0, 0, 3, 152, 76, 2920, 0, 259, 314, 157, 2921, 0, 1, 2919, 0, 0, 0, 1, 2921, 0, 0, 0, 1, 429, 0, 0, 0, 3, 228, 114, 2924, 0, 3, 270, 135, 2925, 0, 1, 2923, 0, 0, 0, 1, 2925, 0, 0, 0, 1, 2926, 0, 0, 0, 5, 2927, 138, 0, 0, 259, 296, 148, 2928, 0, 1, 431, 0, 0, 0, 5, 2930, 74, 0, 0, 259, 296, 148, 2931, 0, 1, 433, 0, 0, 0, 5, 2933, 200, 0, 0, 3, 46, 23, 2936, 0, 5, 2935, 163, 0, 0, 3, 46, 23, 2937, 0, 1, 2934, 0, 0, 0, 1, 2938, 0, 0, 0, 1, 2936, 0, 0, 0, 1, 2939, 0, 0, 0, 1, 2940, 0, 0, 0, 5, 2941, 201, 0, 0, 1, 435, 0, 0, 0, 5, 2943, 56, 0, 0, 5, 2944, 200, 0, 0, 3, 152, 76, 2945, 0, 5, 2946, 201, 0, 0, 1, 437, 0, 0, 0, 5, 2948, 57, 0, 0, 5, 2949, 200, 0, 0, 3, 296, 148, 2950, 0, 5, 2951, 201, 0, 0, 1, 439, 0, 0, 0, 259, 456, 228, 2960, 0, 259, 442, 221, 2960, 0, 259, 444, 222, 2960, 0, 259, 446, 223, 2960, 0, 259, 464, 232, 2960, 0, 259, 466, 233, 2960, 0, 259, 458, 229, 2960, 0, 1, 2952, 0, 0, 0, 1, 2953, 0, 0, 0, 1, 2954, 0, 0, 0, 1, 2955, 0, 0, 0, 1, 2956, 0, 0, 0, 1, 2957, 0, 0, 0, 1, 2958, 0, 0, 0, 1, 441, 0, 0, 0, 7, 2962, 17, 0, 0, 1, 443, 0, 0, 0, 5, 3029, 145, 0, 0, 5, 3029, 81, 0, 0, 5, 3029, 82, 0, 0, 5, 3029, 62, 0, 0, 5, 3029, 83, 0, 0, 5, 3029, 84, 0, 0, 5, 3029, 63, 0, 0, 5, 3029, 85, 0, 0, 5, 3029, 27, 0, 0, 5, 3029, 64, 0, 0, 5, 3029, 17, 0, 0, 5, 3029, 28, 0, 0, 5, 3029, 29, 0, 0, 5, 3029, 18, 0, 0, 5, 3029, 147, 0, 0, 5, 3029, 39, 0, 0, 5, 3029, 86, 0, 0, 5, 3029, 87, 0, 0, 5, 3029, 66, 0, 0, 5, 3029, 19, 0, 0, 5, 3029, 67, 0, 0, 5, 3029, 30, 0, 0, 5, 3029, 70, 0, 0, 5, 3029, 109, 0, 0, 5, 3029, 31, 0, 0, 5, 3029, 90, 0, 0, 5, 3029, 148, 0, 0, 5, 3029, 20, 0, 0, 5, 3029, 149, 0, 0, 5, 3029, 111, 0, 0, 5, 3029, 11, 0, 0, 5, 3029, 150, 0, 0, 5, 3029, 94, 0, 0, 5, 3029, 95, 0, 0, 5, 3029, 12, 0, 0, 5, 3029, 96, 0, 0, 5, 3029, 43, 0, 0, 5, 3029, 22, 0, 0, 5, 3029, 115, 0, 0, 5, 3029, 44, 0, 0, 5, 3029, 47, 0, 0, 5, 3029, 72, 0, 0, 5, 3029, 73, 0, 0, 5, 3029, 51, 0, 0, 5, 3029, 5, 0, 0, 5, 3029, 53, 0, 0, 5, 3029, 54, 0, 0, 5, 3029, 55, 0, 0, 5, 3029, 98, 0, 0, 5, 3029, 74, 0, 0, 5, 3029, 99, 0, 0, 5, 3029, 118, 0, 0, 5, 3029, 56, 0, 0, 5, 3029, 100, 0, 0, 5, 3029, 75, 0, 0, 5, 3029, 14, 0, 0, 5, 3029, 58, 0, 0, 5, 3029, 77, 0, 0, 5, 3029, 101, 0, 0, 5, 3029, 79, 0, 0, 5, 3029, 6, 0, 0, 5, 3029, 7, 0, 0, 5, 3029, 8, 0, 0, 5, 3029, 3, 0, 0, 259, 38, 19, 3029, 0, 1, 2963, 0, 0, 0, 1, 2964, 0, 0, 0, 1, 2965, 0, 0, 0, 1, 2966, 0, 0, 0, 1, 2967, 0, 0, 0, 1, 2968, 0, 0, 0, 1, 2969, 0, 0, 0, 1, 2970, 0, 0, 0, 1, 2971, 0, 0, 0, 1, 2972, 0, 0, 0, 1, 2973, 0, 0, 0, 1, 2974, 0, 0, 0, 1, 2975, 0, 0, 0, 1, 2976, 0, 0, 0, 1, 2977, 0, 0, 0, 1, 2978, 0, 0, 0, 1, 2979, 0, 0, 0, 1, 2980, 0, 0, 0, 1, 2981, 0, 0, 0, 1, 2982, 0, 0, 0, 1, 2983, 0, 0, 0, 1, 2984, 0, 0, 0, 1, 2985, 0, 0, 0, 1, 2986, 0, 0, 0, 1, 2987, 0, 0, 0, 1, 2988, 0, 0, 0, 1, 2989, 0, 0, 0, 1, 2990, 0, 0, 0, 1, 2991, 0, 0, 0, 1, 2992, 0, 0, 0, 1, 2993, 0, 0, 0, 1, 2994, 0, 0, 0, 1, 2995, 0, 0, 0, 1, 2996, 0, 0, 0, 1, 2997, 0, 0, 0, 1, 2998, 0, 0, 0, 1, 2999, 0, 0, 0, 1, 3000, 0, 0, 0, 1, 3001, 0, 0, 0, 1, 3002, 0, 0, 0, 1, 3003, 0, 0, 0, 1, 3004, 0, 0, 0, 1, 3005, 0, 0, 0, 1, 3006, 0, 0, 0, 1, 3007, 0, 0, 0, 1, 3008, 0, 0, 0, 1, 3009, 0, 0, 0, 1, 3010, 0, 0, 0, 1, 3011, 0, 0, 0, 1, 3012, 0, 0, 0, 1, 3013, 0, 0, 0, 1, 3014, 0, 0, 0, 1, 3015, 0, 0, 0, 1, 3016, 0, 0, 0, 1, 3017, 0, 0, 0, 1, 3018, 0, 0, 0, 1, 3019, 0, 0, 0, 1, 3020, 0, 0, 0, 1, 3021, 0, 0, 0, 1, 3022, 0, 0, 0, 1, 3023, 0, 0, 0, 1, 3024, 0, 0, 0, 1, 3025, 0, 0, 0, 1, 3026, 0, 0, 0, 1, 3027, 0, 0, 0, 1, 445, 0, 0, 0, 259, 448, 224, 3033, 0, 259, 454, 227, 3033, 0, 1, 3030, 0, 0, 0, 1, 3031, 0, 0, 0, 1, 447, 0, 0, 0, 259, 450, 225, 3038, 0, 259, 452, 226, 3038, 0, 5, 3038, 180, 0, 0, 1, 3034, 0, 0, 0, 1, 3035, 0, 0, 0, 1, 3036, 0, 0, 0, 1, 449, 0, 0, 0, 5, 3040, 178, 0, 0, 1, 451, 0, 0, 0, 5, 3042, 179, 0, 0, 1, 453, 0, 0, 0, 5, 3044, 181, 0, 0, 1, 455, 0, 0, 0, 5, 3046, 182, 0, 0, 1, 457, 0, 0, 0, 259, 460, 230, 3050, 0, 259, 462, 231, 3050, 0, 1, 3047, 0, 0, 0, 1, 3048, 0, 0, 0, 1, 459, 0, 0, 0, 5, 3052, 183, 0, 0, 1, 461, 0, 0, 0, 5, 3054, 184, 0, 0, 1, 463, 0, 0, 0, 5, 3095, 156, 0, 0, 5, 3095, 120, 0, 0, 5, 3095, 159, 0, 0, 5, 3095, 121, 0, 0, 5, 3095, 122, 0, 0, 5, 3095, 160, 0, 0, 5, 3095, 123, 0, 0, 5, 3095, 161, 0, 0, 5, 3095, 124, 0, 0, 5, 3095, 162, 0, 0, 5, 3095, 125, 0, 0, 5, 3095, 126, 0, 0, 5, 3095, 164, 0, 0, 5, 3095, 127, 0, 0, 5, 3095, 128, 0, 0, 5, 3095, 166, 0, 0, 5, 3095, 131, 0, 0, 5, 3095, 168, 0, 0, 5, 3095, 135, 0, 0, 5, 3095, 105, 0, 0, 5, 3095, 136, 0, 0, 5, 3095, 169, 0, 0, 5, 3095, 137, 0, 0, 5, 3095, 170, 0, 0, 5, 3095, 139, 0, 0, 259, 476, 238, 3095, 0, 259, 480, 240, 3095, 0, 259, 478, 239, 3095, 0, 259, 482, 241, 3095, 0, 5, 3095, 140, 0, 0, 5, 3095, 106, 0, 0, 5, 3095, 145, 0, 0, 5, 3095, 150, 0, 0, 5, 3095, 172, 0, 0, 5, 3095, 144, 0, 0, 5, 3095, 174, 0, 0, 5, 3095, 154, 0, 0, 5, 3095, 155, 0, 0, 5, 3095, 175, 0, 0, 1, 3055, 0, 0, 0, 1, 3056, 0, 0, 0, 1, 3057, 0, 0, 0, 1, 3058, 0, 0, 0, 1, 3059, 0, 0, 0, 1, 3060, 0, 0, 0, 1, 3061, 0, 0, 0, 1, 3062, 0, 0, 0, 1, 3063, 0, 0, 0, 1, 3064, 0, 0, 0, 1, 3065, 0, 0, 0, 1, 3066, 0, 0, 0, 1, 3067, 0, 0, 0, 1, 3068, 0, 0, 0, 1, 3069, 0, 0, 0, 1, 3070, 0, 0, 0, 1, 3071, 0, 0, 0, 1, 3072, 0, 0, 0, 1, 3073, 0, 0, 0, 1, 3074, 0, 0, 0, 1, 3075, 0, 0, 0, 1, 3076, 0, 0, 0, 1, 3077, 0, 0, 0, 1, 3078, 0, 0, 0, 1, 3079, 0, 0, 0, 1, 3080, 0, 0, 0, 1, 3081, 0, 0, 0, 1, 3082, 0, 0, 0, 1, 3083, 0, 0, 0, 1, 3084, 0, 0, 0, 1, 3085, 0, 0, 0, 1, 3086, 0, 0, 0, 1, 3087, 0, 0, 0, 1, 3088, 0, 0, 0, 1, 3089, 0, 0, 0, 1, 3090, 0, 0, 0, 1, 3091, 0, 0, 0, 1, 3092, 0, 0, 0, 1, 3093, 0, 0, 0, 1, 465, 0, 0, 0, 7, 3097, 18, 0, 0, 1, 467, 0, 0, 0, 5, 3099, 1, 0, 0, 1, 469, 0, 0, 0, 5, 3101, 186, 0, 0, 1, 471, 0, 0, 0, 5, 3103, 185, 0, 0, 1, 473, 0, 0, 0, 5, 3105, 176, 0, 0, 1, 475, 0, 0, 0, 5, 3107, 170, 0, 0, 5, 3108, 170, 0, 0, 4, 3109, 238, 17, 0, 1, 477, 0, 0, 0, 5, 3111, 170, 0, 0, 5, 3112, 170, 0, 0, 4, 3113, 239, 18, 0, 5, 3114, 170, 0, 0, 4, 3115, 239, 19, 0, 1, 479, 0, 0, 0, 5, 3117, 170, 0, 0, 5, 3118, 139, 0, 0, 4, 3119, 240, 20, 0, 1, 481, 0, 0, 0, 5, 3121, 170, 0, 0, 5, 3122, 170, 0, 0, 4, 3123, 241, 21, 0, 5, 3124, 139, 0, 0, 4, 3125, 241, 22, 0, 1, 483, 0, 0, 0, 3, 152, 76, 3127, 0, 3, 486, 243, 3132, 0, 5, 3129, 163, 0, 0, 3, 486, 243, 3131, 0, 1, 3128, 0, 0, 0, 1, 3134, 0, 0, 0, 1, 3130, 0, 0, 0, 1, 3133, 0, 0, 0, 1, 485, 0, 0, 0, 1, 3132, 0, 0, 0, 3, 442, 221, 3137, 0, 259, 48, 24, 3138, 0, 1, 3136, 0, 0, 0, 1, 3138, 0, 0, 0, 1, 487, 0, 0, 0, 0, 18, 1, 0, 2, 18, 2, 0, 2, 0, 20, 2, 1, 2, 2, 22, 1, 1, 4, 2, 23, 2, 0, 6, 0, 25, 5, 1, 6, 2, 30, 2, 1, 8, 2, 32, 13, 1, 10, 2, 45, 2, 1, 12, 2, 47, 2, 1, 14, 2, 49, 2, 0, 16, 0, 51, 32, 2, 16, 3, 83, 2, 1, 19, 2, 85, 2, 0, 21, 0, 87, 3, 2, 21, 3, 90, 2, 0, 24, 0, 92, 2, 1, 24, 2, 94, 32, 2, 26, 3, 126, 10, 2, 29, 4, 13, 13, 16, 16, 21, 21, 23, 26, 34, 36, 38, 38, 41, 41, 45, 45, 48, 49, 52, 52, 57, 57, 60, 60, 65, 65, 69, 69, 88, 88, 97, 97, 113, 113, 116, 116, 115, 116, 149, 149, 81, 81, 98, 98, 19, 20, 115, 115, 149, 149, 46, 46, 91, 91, 107, 107, 110, 110, 117, 117, 54, 54, 64, 64, 28, 28, 39, 39, 43, 43, 53, 53, 58, 58, 70, 70, 72, 73, 75, 75, 82, 83, 85, 85, 95, 95, 100, 101, 111, 111, 14, 14, 27, 27, 29, 29, 84, 84, 108, 108, 152, 152, 4, 4, 9, 10, 15, 15, 25, 25, 32, 34, 37, 38, 40, 40, 42, 42, 46, 46, 48, 48, 50, 50, 59, 61, 68, 68, 71, 71, 76, 76, 78, 78, 80, 80, 88, 89, 91, 93, 97, 97, 102, 103, 107, 107, 110, 110, 112, 112, 117, 117, 119, 119, 141, 141, 146, 146, 151, 151, 153, 153, 173, 173, 176, 177, 47, 47, 62, 62, 129, 129, 165, 165, 125, 125, 127, 127, 156, 156, 141, 141, 153, 153, 4, 4, 9, 9, 4, 4, 9, 10, 15, 15, 25, 25, 32, 34, 37, 38, 40, 40, 42, 42, 46, 46, 48, 48, 50, 50, 59, 61, 68, 68, 71, 71, 76, 76, 78, 78, 80, 80, 88, 89, 91, 93, 97, 97, 102, 103, 107, 108, 110, 110, 112, 112, 114, 114, 117, 117, 119, 119, 141, 141, 146, 146, 151, 153, 173, 173, 176, 177, 129, 130, 132, 134, 138, 138, 142, 143, 157, 158, 163, 163, 165, 165, 167, 167, 171, 171, 197, 203, 128000000, 303243868, 16777250, 1179650, 0, 0, 131072, 4, 1572864, 0, 0, 0, 0, 16384, 134217728, 2115584, 0, 4194304, 1, 0, 268435456, 69208192, 2150370112, 32816, 134234112, 0, 0, 0, 536870912, 0, 1048576, 0, 33588752, 939869543, 989941904, 10569922, 42213376, 204800, 0, 1073774592, 0, 0, 0, 0, 0, 2684354560, 268435456, 0, 528, 0, 0, 0, 33588752, 939869543, 989941904, 10836162, 58990592, 204800, 0, 0, 0, 0, 1610663030, 2216, 4064, 0, 491, 497, 503, 509, 520, 525, 528, 538, 542, 549, 559, 564, 571, 580, 587, 591, 595, 598, 608, 611, 616, 619, 621, 639, 643, 648, 654, 669, 674, 677, 685, 691, 694, 704, 710, 721, 726, 732, 738, 745, 753, 756, 763, 771, 773, 777, 781, 784, 796, 799, 806, 813, 824, 830, 835, 839, 848, 856, 862, 873, 878, 884, 889, 893, 899, 907, 915, 923, 927, 939, 947, 955, 965, 969, 971, 984, 990, 995, 999, 1036, 1044, 1048, 1053, 1059, 1068, 1074, 1080, 1086, 1092, 1101, 1107, 1113, 1118, 1123, 1128, 1134, 1140, 1145, 1151, 1159, 1165, 1174, 1179, 1185, 1190, 1198, 1206, 1214, 1220, 1225, 1232, 1236, 1240, 1244, 1249, 1255, 1261, 1269, 1273, 1275, 1278, 1281, 1289, 1294, 1304, 1310, 1315, 1323, 1328, 1334, 1340, 1343, 1346, 1351, 1358, 1362, 1365, 1370, 1376, 1381, 1384, 1389, 1396, 1404, 1410, 1416, 1419, 1422, 1427, 1434, 1438, 1441, 1446, 1452, 1457, 1461, 1464, 1467, 1472, 1479, 1483, 1486, 1491, 1497, 1503, 1506, 1509, 1514, 1521, 1525, 1528, 1533, 1539, 1545, 1548, 1551, 1556, 1563, 1567, 1570, 1575, 1581, 1588, 1594, 1602, 1608, 1620, 1626, 1632, 1634, 1641, 1645, 1649, 1653, 1656, 1663, 1669, 1673, 1675, 1683, 1696, 1704, 1710, 1719, 1732, 1738, 1764, 1769, 1774, 1781, 1789, 1794, 1798, 1812, 1816, 1829, 1834, 1841, 1855, 1863, 1872, 1884, 1890, 1897, 1900, 1902, 1906, 1914, 1917, 1925, 1930, 1933, 1940, 1949, 1957, 1967, 1971, 1974, 1979, 1988, 1994, 2000, 2006, 2013, 2018, 2030, 2035, 2042, 2053, 2061, 2066, 2071, 2076, 2092, 2099, 2110, 2120, 2123, 2137, 2141, 2143, 2147, 2154, 2157, 2160, 2163, 2171, 2174, 2179, 2185, 2196, 2200, 2202, 2218, 2222, 2245, 2250, 2257, 2265, 2269, 2273, 2276, 2283, 2298, 2307, 2311, 2317, 2325, 2337, 2343, 2373, 2386, 2402, 2428, 2455, 2465, 2469, 2471, 2477, 2479, 2484, 2489, 2494, 2498, 2502, 2507, 2513, 2517, 2523, 2528, 2534, 2541, 2550, 2554, 2556, 2561, 2568, 2576, 2580, 2582, 2591, 2596, 2601, 2604, 2621, 2629, 2633, 2635, 2642, 2669, 2684, 2694, 2702, 2710, 2719, 2724, 2728, 2735, 2738, 2754, 2772, 2813, 2820, 2829, 2834, 2841, 2845, 2855, 2871, 2876, 2883, 2920, 2924, 2938, 2959, 3028, 3032, 3037, 3049, 3094, 3132, 3137, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459, 461, 463, 465, 467, 469, 471, 473, 475, 477, 479, 481, 483, 485, 487]; -static ATN_CELL: OnceLock = OnceLock::new(); - -/// Validates and caches the packed grammar ATN for all parser instances. -fn atn() -> &'static ParserAtn { - ATN_CELL.get_or_init(|| { - ParserAtn::from_static(PARSER_ATN_DATA) - .unwrap_or_else(|error| panic!("generated parser ATN is incompatible with this runtime: {error}")) - }) -} - -/// Borrows the validated packed parser ATN embedded in this module. -pub fn parser_atn() -> &'static ParserAtn { - atn() -} - -antlr4_runtime::__antlr4_rust_parser_entry_points! { - parser: CSharpParser, - output: CSharpParserParseOutput, - validated_tree: CSharpValidatedTree, - validation_error: CSharpValidationError, - validate_tree: validate_tree_structure, -} - -/// Generated parser. Each grammar rule is exposed as a public method. -/// -/// Pick an entry-rule method that matches the grammar's intended -/// top-level construct for the input being parsed. The generator can -/// infer entry candidates from call paths that reach explicit `EOF` -/// matches, from parser rules that no other rule calls, and from -/// configured entry rules. It cannot infer the semantic choice -/// between multiple candidates. -/// -/// Likely parser entry-rule methods: -/// - `compilation_unit()` -/// -/// All parser rule methods: -/// - `compilation_unit()` -/// - `extern_alias_directive()` -/// - `using_directive()` -/// - `name_equals()` -/// - `identifier_name()` -/// - `attribute_list()` -/// - `attribute_target_specifier()` -/// - `attribute()` -/// - `name()` -/// - `alias_qualified_name()` -/// - `simple_name()` -/// - `generic_name()` -/// - `type_argument_list()` -/// - `attribute_argument_list()` -/// - `attribute_argument()` -/// - `name_colon()` -/// - `member_declaration()` -/// - `base_field_declaration()` -/// - `event_field_declaration()` -/// - `modifier()` -/// - `variable_declaration()` -/// - `variable_declarator()` -/// - `bracketed_argument_list()` -/// - `argument()` -/// - `equals_value_clause()` -/// - `field_declaration()` -/// - `base_method_declaration()` -/// - `constructor_declaration()` -/// - `parameter_list()` -/// - `parameter()` -/// - `constructor_initializer()` -/// - `argument_list()` -/// - `block()` -/// - `arrow_expression_clause()` -/// - `conversion_operator_declaration()` -/// - `explicit_interface_specifier()` -/// - `destructor_declaration()` -/// - `method_declaration()` -/// - `type_parameter_list()` -/// - `type_parameter()` -/// - `type_parameter_constraint_clause()` -/// - `type_parameter_constraint()` -/// - `allows_constraint_clause()` -/// - `allows_constraint()` -/// - `ref_struct_constraint()` -/// - `class_or_struct_constraint()` -/// - `constructor_constraint()` -/// - `default_constraint()` -/// - `type_constraint()` -/// - `operator_declaration()` -/// - `base_namespace_declaration()` -/// - `file_scoped_namespace_declaration()` -/// - `namespace_declaration()` -/// - `base_property_declaration()` -/// - `event_declaration()` -/// - `accessor_list()` -/// - `accessor_declaration()` -/// - `indexer_declaration()` -/// - `bracketed_parameter_list()` -/// - `property_declaration()` -/// - `base_type_declaration()` -/// - `enum_declaration()` -/// - `base_list()` -/// - `base_type()` -/// - `primary_constructor_base_type()` -/// - `simple_base_type()` -/// - `enum_member_declaration()` -/// - `type_declaration()` -/// - `class_declaration()` -/// - `extension_block_declaration()` -/// - `interface_declaration()` -/// - `record_declaration()` -/// - `struct_declaration()` -/// - `union_declaration()` -/// - `delegate_declaration()` -/// - `global_statement()` -/// - `r#type()` -/// - `array_type()` -/// - `array_rank_specifier()` -/// - `function_pointer_type()` -/// - `function_pointer_calling_convention()` -/// - `function_pointer_unmanaged_calling_convention_list()` -/// - `function_pointer_unmanaged_calling_convention()` -/// - `function_pointer_parameter_list()` -/// - `function_pointer_parameter()` -/// - `predefined_type()` -/// - `ref_type()` -/// - `scoped_type()` -/// - `tuple_type()` -/// - `tuple_element()` -/// - `statement()` -/// - `break_statement()` -/// - `checked_statement()` -/// - `common_for_each_statement()` -/// - `for_each_statement()` -/// - `for_each_variable_statement()` -/// - `continue_statement()` -/// - `do_statement()` -/// - `empty_statement()` -/// - `expression_statement()` -/// - `fixed_statement()` -/// - `for_statement()` -/// - `goto_statement()` -/// - `if_statement()` -/// - `else_clause()` -/// - `labeled_statement()` -/// - `local_declaration_statement()` -/// - `local_function_statement()` -/// - `lock_statement()` -/// - `return_statement()` -/// - `switch_statement()` -/// - `switch_section()` -/// - `switch_label()` -/// - `case_pattern_switch_label()` -/// - `pattern()` -/// - `constant_pattern()` -/// - `declaration_pattern()` -/// - `variable_designation()` -/// - `discard_designation()` -/// - `parenthesized_variable_designation()` -/// - `single_variable_designation()` -/// - `discard_pattern()` -/// - `list_pattern()` -/// - `parenthesized_pattern()` -/// - `recursive_pattern()` -/// - `positional_pattern_clause()` -/// - `subpattern()` -/// - `base_expression_colon()` -/// - `expression_colon()` -/// - `property_pattern_clause()` -/// - `relational_pattern()` -/// - `slice_pattern()` -/// - `type_pattern()` -/// - `unary_pattern()` -/// - `var_pattern()` -/// - `when_clause()` -/// - `case_switch_label()` -/// - `default_switch_label()` -/// - `throw_statement()` -/// - `try_statement()` -/// - `catch_clause()` -/// - `catch_declaration()` -/// - `catch_filter_clause()` -/// - `finally_clause()` -/// - `unsafe_statement()` -/// - `using_statement()` -/// - `while_statement()` -/// - `yield_statement()` -/// - `expression()` -/// - `anonymous_function_expression()` -/// - `anonymous_method_expression()` -/// - `lambda_expression()` -/// - `parenthesized_lambda_expression()` -/// - `simple_lambda_expression()` -/// - `anonymous_object_creation_expression()` -/// - `anonymous_object_member_declarator()` -/// - `array_creation_expression()` -/// - `initializer_expression()` -/// - `await_expression()` -/// - `base_object_creation_expression()` -/// - `implicit_object_creation_expression()` -/// - `object_creation_expression()` -/// - `cast_expression()` -/// - `checked_expression()` -/// - `collection_expression()` -/// - `collection_element()` -/// - `expression_element()` -/// - `spread_element()` -/// - `with_element()` -/// - `declaration_expression()` -/// - `default_expression()` -/// - `element_binding_expression()` -/// - `field_expression()` -/// - `implicit_array_creation_expression()` -/// - `implicit_element_access()` -/// - `implicit_stack_alloc_array_creation_expression()` -/// - `instance_expression()` -/// - `base_expression()` -/// - `this_expression()` -/// - `interpolated_string_expression()` -/// - `interpolated_string_content()` -/// - `interpolated_string_text()` -/// - `interpolation()` -/// - `interpolation_alignment_clause()` -/// - `interpolation_format_clause()` -/// - `interpolated_multi_line_raw_string_start_token()` -/// - `interpolated_raw_string_end_token()` -/// - `interpolated_single_line_raw_string_start_token()` -/// - `literal_expression()` -/// - `utf8_multi_line_raw_string_literal_token()` -/// - `utf8_single_line_raw_string_literal_token()` -/// - `utf8_string_literal_token()` -/// - `make_ref_expression()` -/// - `member_binding_expression()` -/// - `parenthesized_expression()` -/// - `prefix_unary_expression()` -/// - `query_expression()` -/// - `from_clause()` -/// - `query_body()` -/// - `query_clause()` -/// - `join_clause()` -/// - `join_into_clause()` -/// - `let_clause()` -/// - `order_by_clause()` -/// - `ordering()` -/// - `where_clause()` -/// - `select_or_group_clause()` -/// - `group_clause()` -/// - `select_clause()` -/// - `query_continuation()` -/// - `ref_expression()` -/// - `ref_type_expression()` -/// - `ref_value_expression()` -/// - `size_of_expression()` -/// - `stack_alloc_array_creation_expression()` -/// - `switch_expression_arm()` -/// - `throw_expression()` -/// - `tuple_expression()` -/// - `type_of_expression()` -/// - `unsafe_expression()` -/// - `syntax_token()` -/// - `identifier_token()` -/// - `keyword()` -/// - `numeric_literal_token()` -/// - `integer_literal_token()` -/// - `decimal_integer_literal_token()` -/// - `hexadecimal_integer_literal_token()` -/// - `real_literal_token()` -/// - `character_literal_token()` -/// - `string_literal_token()` -/// - `regular_string_literal_token()` -/// - `verbatim_string_literal_token()` -/// - `operator_token()` -/// - `punctuation_token()` -/// - `interpolated_string_text_token()` -/// - `multi_line_raw_string_literal_token()` -/// - `single_line_raw_string_literal_token()` -/// - `record_keyword()` -/// - `right_shift()` -/// - `unsigned_right_shift()` -/// - `right_shift_assignment()` -/// - `unsigned_right_shift_assignment()` -/// - `local_variable_declaration()` -/// - `local_variable_declarator()` -#[derive(Debug)] -pub struct CSharpParser -where - L: TokenSource, - H: antlr4_runtime::SemanticHooks, -{ - base: BaseParser, - simulator: Option>, - generated_only: bool, - adaptive_atn: antlr4_runtime::generated::AdaptiveAtnRetryState<2>, -} - -impl CSharpParser -where - L: TokenSource, -{ - pub fn new(input: CommonTokenStream) -> Self { - Self::with_hooks(input, antlr4_runtime::NoSemanticHooks) - } -} - -impl CSharpParser -where - L: TokenSource, - H: antlr4_runtime::SemanticHooks, -{ - pub fn with_hooks(input: CommonTokenStream, hooks: H) -> Self { - let grammar_metadata = metadata(); - let data = grammar_metadata.recognizer_data(); - let mut base = BaseParser::with_semantic_hooks(input, data, hooks); - base.set_unknown_predicate_policy(antlr4_runtime::UnknownSemanticPolicy::Error); - Self { - base, - simulator: None, - generated_only: std::env::var_os("ANTLR4_RUST_GENERATED_ONLY").is_some(), - adaptive_atn: antlr4_runtime::generated::AdaptiveAtnRetryState::new(), - } - } - - const __GENERATED_RULE_BODIES: [Option>; 244] = [ - Some(Self::parse_generated_rule_0), - Some(Self::parse_generated_rule_1), - Some(Self::parse_generated_rule_2), - Some(Self::parse_generated_rule_3), - Some(Self::parse_generated_rule_4), - Some(Self::parse_generated_rule_5), - Some(Self::parse_generated_rule_6), - Some(Self::parse_generated_rule_7), - Some(Self::parse_generated_rule_8_precedence), - Some(Self::parse_generated_rule_9), - Some(Self::parse_generated_rule_10), - Some(Self::parse_generated_rule_11), - Some(Self::parse_generated_rule_12), - Some(Self::parse_generated_rule_13), - Some(Self::parse_generated_rule_14), - Some(Self::parse_generated_rule_15), - Some(Self::parse_generated_rule_16), - Some(Self::parse_generated_rule_17), - Some(Self::parse_generated_rule_18), - Some(Self::parse_generated_rule_19), - Some(Self::parse_generated_rule_20), - Some(Self::parse_generated_rule_21), - Some(Self::parse_generated_rule_22), - Some(Self::parse_generated_rule_23), - Some(Self::parse_generated_rule_24), - Some(Self::parse_generated_rule_25), - Some(Self::parse_generated_rule_26), - Some(Self::parse_generated_rule_27), - Some(Self::parse_generated_rule_28), - Some(Self::parse_generated_rule_29), - Some(Self::parse_generated_rule_30), - Some(Self::parse_generated_rule_31), - Some(Self::parse_generated_rule_32), - Some(Self::parse_generated_rule_33), - Some(Self::parse_generated_rule_34), - Some(Self::parse_generated_rule_35), - Some(Self::parse_generated_rule_36), - Some(Self::parse_generated_rule_37), - Some(Self::parse_generated_rule_38), - Some(Self::parse_generated_rule_39), - Some(Self::parse_generated_rule_40), - Some(Self::parse_generated_rule_41), - Some(Self::parse_generated_rule_42), - Some(Self::parse_generated_rule_43), - Some(Self::parse_generated_rule_44), - Some(Self::parse_generated_rule_45), - Some(Self::parse_generated_rule_46), - Some(Self::parse_generated_rule_47), - Some(Self::parse_generated_rule_48), - Some(Self::parse_generated_rule_49), - Some(Self::parse_generated_rule_50), - Some(Self::parse_generated_rule_51), - Some(Self::parse_generated_rule_52), - Some(Self::parse_generated_rule_53), - Some(Self::parse_generated_rule_54), - Some(Self::parse_generated_rule_55), - Some(Self::parse_generated_rule_56), - Some(Self::parse_generated_rule_57), - Some(Self::parse_generated_rule_58), - Some(Self::parse_generated_rule_59), - Some(Self::parse_generated_rule_60), - Some(Self::parse_generated_rule_61), - Some(Self::parse_generated_rule_62), - Some(Self::parse_generated_rule_63), - Some(Self::parse_generated_rule_64), - Some(Self::parse_generated_rule_65), - Some(Self::parse_generated_rule_66), - Some(Self::parse_generated_rule_67), - Some(Self::parse_generated_rule_68), - Some(Self::parse_generated_rule_69), - Some(Self::parse_generated_rule_70), - Some(Self::parse_generated_rule_71), - Some(Self::parse_generated_rule_72), - Some(Self::parse_generated_rule_73), - Some(Self::parse_generated_rule_74), - Some(Self::parse_generated_rule_75), - Some(Self::parse_generated_rule_76_precedence), - Some(Self::parse_generated_rule_77), - Some(Self::parse_generated_rule_78), - Some(Self::parse_generated_rule_79), - Some(Self::parse_generated_rule_80), - Some(Self::parse_generated_rule_81), - Some(Self::parse_generated_rule_82), - Some(Self::parse_generated_rule_83), - Some(Self::parse_generated_rule_84), - Some(Self::parse_generated_rule_85), - Some(Self::parse_generated_rule_86), - Some(Self::parse_generated_rule_87), - Some(Self::parse_generated_rule_88), - Some(Self::parse_generated_rule_89), - Some(Self::parse_generated_rule_90), - Some(Self::parse_generated_rule_91), - Some(Self::parse_generated_rule_92), - Some(Self::parse_generated_rule_93), - Some(Self::parse_generated_rule_94), - Some(Self::parse_generated_rule_95), - Some(Self::parse_generated_rule_96), - Some(Self::parse_generated_rule_97), - Some(Self::parse_generated_rule_98), - Some(Self::parse_generated_rule_99), - Some(Self::parse_generated_rule_100), - Some(Self::parse_generated_rule_101), - Some(Self::parse_generated_rule_102), - Some(Self::parse_generated_rule_103), - Some(Self::parse_generated_rule_104), - Some(Self::parse_generated_rule_105), - Some(Self::parse_generated_rule_106), - Some(Self::parse_generated_rule_107), - Some(Self::parse_generated_rule_108), - Some(Self::parse_generated_rule_109), - Some(Self::parse_generated_rule_110), - Some(Self::parse_generated_rule_111), - Some(Self::parse_generated_rule_112), - Some(Self::parse_generated_rule_113), - Some(Self::parse_generated_rule_114_precedence), - Some(Self::parse_generated_rule_115), - Some(Self::parse_generated_rule_116), - Some(Self::parse_generated_rule_117), - Some(Self::parse_generated_rule_118), - Some(Self::parse_generated_rule_119), - Some(Self::parse_generated_rule_120), - Some(Self::parse_generated_rule_121), - Some(Self::parse_generated_rule_122), - Some(Self::parse_generated_rule_123), - Some(Self::parse_generated_rule_124), - Some(Self::parse_generated_rule_125), - Some(Self::parse_generated_rule_126), - Some(Self::parse_generated_rule_127), - Some(Self::parse_generated_rule_128), - Some(Self::parse_generated_rule_129), - Some(Self::parse_generated_rule_130), - Some(Self::parse_generated_rule_131), - Some(Self::parse_generated_rule_132), - Some(Self::parse_generated_rule_133), - Some(Self::parse_generated_rule_134), - Some(Self::parse_generated_rule_135), - Some(Self::parse_generated_rule_136), - Some(Self::parse_generated_rule_137), - Some(Self::parse_generated_rule_138), - Some(Self::parse_generated_rule_139), - Some(Self::parse_generated_rule_140), - Some(Self::parse_generated_rule_141), - Some(Self::parse_generated_rule_142), - Some(Self::parse_generated_rule_143), - Some(Self::parse_generated_rule_144), - Some(Self::parse_generated_rule_145), - Some(Self::parse_generated_rule_146), - Some(Self::parse_generated_rule_147), - Some(Self::parse_generated_rule_148_precedence), - Some(Self::parse_generated_rule_149), - Some(Self::parse_generated_rule_150), - Some(Self::parse_generated_rule_151), - Some(Self::parse_generated_rule_152), - Some(Self::parse_generated_rule_153), - Some(Self::parse_generated_rule_154), - Some(Self::parse_generated_rule_155), - Some(Self::parse_generated_rule_156), - Some(Self::parse_generated_rule_157), - Some(Self::parse_generated_rule_158), - Some(Self::parse_generated_rule_159), - Some(Self::parse_generated_rule_160), - Some(Self::parse_generated_rule_161), - Some(Self::parse_generated_rule_162), - Some(Self::parse_generated_rule_163), - Some(Self::parse_generated_rule_164), - Some(Self::parse_generated_rule_165), - Some(Self::parse_generated_rule_166), - Some(Self::parse_generated_rule_167), - Some(Self::parse_generated_rule_168), - Some(Self::parse_generated_rule_169), - Some(Self::parse_generated_rule_170), - Some(Self::parse_generated_rule_171), - Some(Self::parse_generated_rule_172), - Some(Self::parse_generated_rule_173), - Some(Self::parse_generated_rule_174), - Some(Self::parse_generated_rule_175), - Some(Self::parse_generated_rule_176), - Some(Self::parse_generated_rule_177), - Some(Self::parse_generated_rule_178), - Some(Self::parse_generated_rule_179), - Some(Self::parse_generated_rule_180), - Some(Self::parse_generated_rule_181), - Some(Self::parse_generated_rule_182), - Some(Self::parse_generated_rule_183), - Some(Self::parse_generated_rule_184), - Some(Self::parse_generated_rule_185), - Some(Self::parse_generated_rule_186), - Some(Self::parse_generated_rule_187), - Some(Self::parse_generated_rule_188), - Some(Self::parse_generated_rule_189), - Some(Self::parse_generated_rule_190), - Some(Self::parse_generated_rule_191), - Some(Self::parse_generated_rule_192), - Some(Self::parse_generated_rule_193), - Some(Self::parse_generated_rule_194), - Some(Self::parse_generated_rule_195), - Some(Self::parse_generated_rule_196), - Some(Self::parse_generated_rule_197), - Some(Self::parse_generated_rule_198), - Some(Self::parse_generated_rule_199), - Some(Self::parse_generated_rule_200), - Some(Self::parse_generated_rule_201), - Some(Self::parse_generated_rule_202), - Some(Self::parse_generated_rule_203), - Some(Self::parse_generated_rule_204), - Some(Self::parse_generated_rule_205), - Some(Self::parse_generated_rule_206), - Some(Self::parse_generated_rule_207), - Some(Self::parse_generated_rule_208), - Some(Self::parse_generated_rule_209), - Some(Self::parse_generated_rule_210), - Some(Self::parse_generated_rule_211), - Some(Self::parse_generated_rule_212), - Some(Self::parse_generated_rule_213), - Some(Self::parse_generated_rule_214), - Some(Self::parse_generated_rule_215), - Some(Self::parse_generated_rule_216), - Some(Self::parse_generated_rule_217), - Some(Self::parse_generated_rule_218), - Some(Self::parse_generated_rule_219), - Some(Self::parse_generated_rule_220), - Some(Self::parse_generated_rule_221), - Some(Self::parse_generated_rule_222), - Some(Self::parse_generated_rule_223), - Some(Self::parse_generated_rule_224), - Some(Self::parse_generated_rule_225), - Some(Self::parse_generated_rule_226), - Some(Self::parse_generated_rule_227), - Some(Self::parse_generated_rule_228), - Some(Self::parse_generated_rule_229), - Some(Self::parse_generated_rule_230), - Some(Self::parse_generated_rule_231), - Some(Self::parse_generated_rule_232), - Some(Self::parse_generated_rule_233), - Some(Self::parse_generated_rule_234), - Some(Self::parse_generated_rule_235), - Some(Self::parse_generated_rule_236), - Some(Self::parse_generated_rule_237), - Some(Self::parse_generated_rule_238), - Some(Self::parse_generated_rule_239), - Some(Self::parse_generated_rule_240), - Some(Self::parse_generated_rule_241), - Some(Self::parse_generated_rule_242), - Some(Self::parse_generated_rule_243), - ]; - - #[allow(dead_code)] - #[inline(always)] - fn dispatch_generated_rule(&mut self, rule_index: usize, precedence: i32, allow_fallback: bool) -> Result { - let body = Self::__GENERATED_RULE_BODIES.get(rule_index).copied().flatten().expect("generated rule dispatch target"); - antlr4_runtime::generated::dispatch_generated_rule(self, rule_index, precedence, allow_fallback, body) - } - - #[allow(dead_code)] - fn parse_generated_rule(&mut self, rule_index: usize, precedence: i32, allow_fallback: bool) -> Option> { - let _body = Self::__GENERATED_RULE_BODIES.get(rule_index).copied().flatten()?; - match rule_index { - 101 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() => Some(self.dispatch_generated_rule(101, precedence, allow_fallback)), - 101 if !self.adaptive_atn.preferred_rules[0] => Some(self.parse_generated_rule_101_adaptive_dispatch(precedence, allow_fallback, None)), - 101 => None, - 148 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() => Some(self.dispatch_generated_rule(148, precedence, allow_fallback)), - 148 if !self.adaptive_atn.preferred_rules[1] => Some(self.parse_generated_rule_148_adaptive_dispatch(precedence, allow_fallback, None)), - 148 => None, - _ => Some(self.dispatch_generated_rule(rule_index, precedence, allow_fallback)), - } - } - - #[allow(dead_code)] - fn parse_generated_rule_0(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 0isize, 0, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_491 = false; - loop { - self.base.sync_into(atn(), 491, &mut __ctx, __loop_iter_491, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 491) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(0, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(0, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 491, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_491 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 488isize, self.dispatch_generated_rule(1, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_497 = false; - loop { - self.base.sync_into(atn(), 497, &mut __ctx, __loop_iter_497, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 497) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(1, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(1, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 497, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_497 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 494isize, self.dispatch_generated_rule(2, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_503 = false; - loop { - self.base.sync_into(atn(), 503, &mut __ctx, __loop_iter_503, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 503) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(2, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(2, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 503, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_503 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 500isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_509 = false; - loop { - self.base.sync_into(atn(), 509, &mut __ctx, __loop_iter_509, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 509, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_509 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 506isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(-1, 513, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_1(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 2isize, 1, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(41, 515, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(59, 516, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 516isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 518, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_2(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 4isize, 2, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 520, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 42 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 520, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(42, 521, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(77, 528, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 528, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 528) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(6, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(6, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 528, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(52, 529, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.sync_into(atn(), 525, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 57 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 525, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(57, 526, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 527isize, self.dispatch_generated_rule(3, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 530isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 532, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_3(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 6isize, 3, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 533isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(169, 535, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_4(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 8isize, 4, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 538, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 538) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(7, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(7, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 538, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(42, 539, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 537isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_5(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 10isize, 5, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(202, 542, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 542, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 542) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(8, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(8, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 542, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 541isize, self.dispatch_generated_rule(6, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 544isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_549 = false; - loop { - self.base.sync_into(atn(), 549, &mut __ctx, __loop_iter_549, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 549, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_549 = true; - self.base.match_token_into(163, 546, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 546isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(203, 553, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_6(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 12isize, 6, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 554isize, self.dispatch_generated_rule(220, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(199, 556, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_7(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 14isize, 7, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 557isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 559, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 559, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 558isize, self.dispatch_generated_rule(13, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_8(&mut self, allow_fallback: bool) -> Result { - self.parse_generated_rule_8_precedence(0, allow_fallback) - } - - #[allow(dead_code)] - fn parse_generated_rule_8_precedence(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - antlr4_runtime::__antlr4_rust_generated_rule! { - recursive self, 16isize, 8, __precedence, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 564, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 564) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(11, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(11, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 564, &__prediction); - match __prediction.alt { - 1 => { - let action = self.base.parser_action_at_current_indexed(561, 8, 0, __rule_start, __consumed_eof); - let _ = action; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 562isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 563isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - loop { - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.left_recursive_loop_enter_prediction(atn(), 571, __precedence) { - Some(true) => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: true, diagnostic: None }, - Some(false) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - None => { - let __prediction_precedence = if __precedence <= 0 { 0 } else { __precedence as usize }; - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - match __simulator.adaptive_predict_stream_info_with_context(12, __prediction_precedence, self.base.input(), __prediction_context) { - Ok(__prediction) => __prediction, - Err(antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { .. }) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: true, has_semantic_context: false, diagnostic: None }, - Err(_) => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - let __prediction = if __prediction.alt == 1 { - let __semantic_la = self.base.la(1); - if __semantic_la == 165 { - __prediction - } else { - antlr4_runtime::ParserAtnPrediction { alt: 2, ..__prediction } - } - } else { - __prediction - }; - self.base.record_generated_prediction_diagnostic(atn(), 571, &__prediction); - match __prediction.alt { - 1 => { - self.base.parse_listener_exit_rule(8); - if let Some(__depth_error) = self.base.rule_depth_cap_violation() { - return Err(__depth_error); - } - self.base.push_new_recursion_context_with_previous(16isize, 8, &mut __ctx); - if let Some(__listener_error) = self.base.parse_listener_enter_rule(8) { - return Err(__listener_error); - } - if !self.base.precpred(2) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 2)")); - } - self.base.match_token_into(165, 568, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 568isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => break, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_9(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 18isize, 9, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 574isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(133, 576, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 576isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_10(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 20isize, 10, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 580, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 580) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(13, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(13, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 580, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 578isize, self.dispatch_generated_rule(11, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 579isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_11(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 22isize, 11, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 582isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 583isize, self.dispatch_generated_rule(12, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_12(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 24isize, 12, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(168, 598, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 598, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 598) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(17, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(17, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 598, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 587, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 18 | 25 | 28 | 32..=34 | 37..=40 | 42..=43 | 46 | 48 | 50 | 53 | 58..=61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=112 | 114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 170 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 587, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 586isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_595 = false; - loop { - self.base.sync_into(atn(), 595, &mut __ctx, __loop_iter_595, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 170 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 595, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_595 = true; - self.base.match_token_into(163, 591, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 591, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 18 | 25 | 28 | 32..=34 | 37..=40 | 42..=43 | 46 | 48 | 50 | 53 | 58..=61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=112 | 114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 170 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 591, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 590isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(170, 601, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_13(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 26isize, 13, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 611, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 611, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 611, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 603isize, self.dispatch_generated_rule(14, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_608 = false; - loop { - self.base.sync_into(atn(), 608, &mut __ctx, __loop_iter_608, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 608, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_608 = true; - self.base.match_token_into(163, 605, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 605isize, self.dispatch_generated_rule(14, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 614, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_14(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 28isize, 14, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 621, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 621) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(22, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(22, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 621, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 616, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 616) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(20, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(20, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 616, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 615isize, self.dispatch_generated_rule(3, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - self.base.sync_into(atn(), 619, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 619) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(21, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(21, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 619, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 618isize, self.dispatch_generated_rule(15, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 623isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(623isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_15(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 30isize, 15, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 625isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(199, 627, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_16(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 32isize, 16, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19..=20 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 | 54 | 64 | 87 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5..=8 | 14 | 17 | 27 | 29 | 31 | 47 | 51 | 55..=56 | 62 | 67 | 74 | 77 | 79 | 81 | 90 | 94 | 96 | 98..=99 | 109 | 118 | 125 | 127 | 130 | 147..=148 | 156 | 160..=162 | 164..=165 | 167 | 172 | 178..=186 | 194..=197 => antlr4_runtime::ParserAtnPrediction { alt: 11, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 639, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 639) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(23, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(23, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 639, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 628isize, self.dispatch_generated_rule(17, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 629isize, self.dispatch_generated_rule(71, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 630isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 631isize, self.dispatch_generated_rule(69, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 632isize, self.dispatch_generated_rule(26, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 633isize, self.dispatch_generated_rule(50, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 634isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 635isize, self.dispatch_generated_rule(60, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 636isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 10 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 637isize, self.dispatch_generated_rule(66, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 638isize, self.dispatch_generated_rule(75, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_17(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 34isize, 17, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 66 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 18 | 28 | 32..=33 | 37 | 39..=40 | 42..=43 | 46 | 50 | 53 | 58..=59 | 61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 89 | 91..=93 | 95 | 100..=103 | 107..=108 | 110..=112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 643, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 643) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(24, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(24, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 643, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 641isize, self.dispatch_generated_rule(18, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 642isize, self.dispatch_generated_rule(25, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_18(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 36isize, 18, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_648 = false; - loop { - self.base.sync_into(atn(), 648, &mut __ctx, __loop_iter_648, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65..=66 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 648, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_648 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 645isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_654 = false; - loop { - self.base.sync_into(atn(), 654, &mut __ctx, __loop_iter_654, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 66 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 654, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_654 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 651isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(66, 658, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 658isize, self.dispatch_generated_rule(20, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 660, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_19(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 38isize, 19, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(13, 13), (16, 16), (21, 21), (23, 26), (34, 36), (38, 38), (41, 41), (45, 45), (48, 49), (52, 52), (57, 57), (60, 60), (65, 65), (69, 69), (88, 88), (97, 97), (113, 113), (116, 116)], 662, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_20(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 40isize, 20, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 663isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 664isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_669 = false; - loop { - self.base.sync_into(atn(), 669, &mut __ctx, __loop_iter_669, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 | 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 669, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_669 = true; - self.base.match_token_into(163, 666, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 666isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_21(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 42isize, 21, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 672isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 674, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 167 | 169 | 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 674, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 673isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 677, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 169 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 167 | 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 677, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 676isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_22(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 44isize, 22, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(202, 680, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 680isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_685 = false; - loop { - self.base.sync_into(atn(), 685, &mut __ctx, __loop_iter_685, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 685, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_685 = true; - self.base.match_token_into(163, 682, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 682isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(203, 689, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_23(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 46isize, 23, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 691, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 691) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(31, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(31, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 691, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 690isize, self.dispatch_generated_rule(15, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 694, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 694) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(32, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(32, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 694, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_set_into(&[(115, 116), (149, 149)], 695, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 696isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(696isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_24(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 48isize, 24, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(169, 699, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 699isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(699isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_25(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 50isize, 25, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_704 = false; - loop { - self.base.sync_into(atn(), 704, &mut __ctx, __loop_iter_704, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 704, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_704 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 701isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_710 = false; - loop { - self.base.sync_into(atn(), 710, &mut __ctx, __loop_iter_710, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 710) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(34, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(34, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 710, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_710 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 707isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 713isize, self.dispatch_generated_rule(20, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 715, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_26(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 52isize, 26, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19..=20 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 175 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 721, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 721) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(35, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(35, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 721, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 716isize, self.dispatch_generated_rule(27, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 717isize, self.dispatch_generated_rule(34, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 718isize, self.dispatch_generated_rule(36, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 719isize, self.dispatch_generated_rule(37, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 720isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_27(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 54isize, 27, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_726 = false; - loop { - self.base.sync_into(atn(), 726, &mut __ctx, __loop_iter_726, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 21 | 23..=26 | 32..=38 | 40..=42 | 45..=46 | 48..=50 | 52 | 57 | 59..=61 | 65 | 68..=69 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 726, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_726 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 723isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_732 = false; - loop { - self.base.sync_into(atn(), 732, &mut __ctx, __loop_iter_732, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 732) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(37, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(37, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 732, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_732 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 729isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 735isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 736isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 738, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 | 167 | 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 738, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 737isize, self.dispatch_generated_rule(30, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 745, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 745, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 740isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 741isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 743, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(167, 746, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_28(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 56isize, 28, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 756, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 756, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 756) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(41, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(41, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 756, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 748isize, self.dispatch_generated_rule(29, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_753 = false; - loop { - self.base.sync_into(atn(), 753, &mut __ctx, __loop_iter_753, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 753, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_753 = true; - self.base.match_token_into(163, 750, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 750isize, self.dispatch_generated_rule(29, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 759, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_29(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 58isize, 29, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_763 = false; - loop { - self.base.sync_into(atn(), 763, &mut __ctx, __loop_iter_763, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 6 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97..=98 | 100..=103 | 107..=108 | 110..=117 | 119 | 141 | 146 | 149 | 151..=153 | 163 | 169 | 173 | 176..=177 | 200..=201 | 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 763, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_763 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 760isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_773 = false; - loop { - self.base.sync_into(atn(), 773, &mut __ctx, __loop_iter_773, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 773) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(44, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(44, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 773, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_773 = true; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 115 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 149 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 44 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 98 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 771, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 115 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 149 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 44 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 98 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 771, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 766isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(115, 772, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(149, 772, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(44, 772, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(98, 772, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 777, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 777) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(45, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(45, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 777, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 776isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 781, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 6 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 169 | 201 | 203 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 781, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 779isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(6, 782, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 784, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 169 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 201 | 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 784, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 783isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_30(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 60isize, 30, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(199, 787, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_set_into(&[(81, 81), (98, 98)], 788, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 788isize, self.dispatch_generated_rule(31, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_31(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 62isize, 31, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 799, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 799, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 149 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 799, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 791isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_796 = false; - loop { - self.base.sync_into(atn(), 796, &mut __ctx, __loop_iter_796, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 796, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_796 = true; - self.base.match_token_into(163, 793, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 793isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 802, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_32(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 64isize, 32, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_806 = false; - loop { - self.base.sync_into(atn(), 806, &mut __ctx, __loop_iter_806, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 197 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 806, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_806 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 803isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(197, 813, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_813 = false; - loop { - self.base.sync_into(atn(), 813, &mut __ctx, __loop_iter_813, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=18 | 21 | 23..=29 | 31..=43 | 45..=53 | 55..=62 | 65 | 67..=83 | 85 | 88..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 813, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_813 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 810isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 817, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_33(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 66isize, 33, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(138, 819, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 819isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(819isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_34(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 68isize, 34, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_824 = false; - loop { - self.base.sync_into(atn(), 824, &mut __ctx, __loop_iter_824, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 19..=21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 824, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_824 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 821isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_830 = false; - loop { - self.base.sync_into(atn(), 830, &mut __ctx, __loop_iter_830, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19..=20 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 830, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_830 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 827isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_set_into(&[(19, 20)], 835, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 835, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 22 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 835, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 834isize, self.dispatch_generated_rule(35, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(22, 839, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 839, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 18 | 25 | 28 | 32..=34 | 37..=40 | 42..=43 | 46 | 48 | 50 | 53 | 58..=61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=112 | 114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 839, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(27, 840, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 841isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 842isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 848, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 848, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 843isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 844isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 846, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(167, 849, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_35(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 70isize, 35, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 850isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(165, 852, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_36(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 72isize, 36, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_856 = false; - loop { - self.base.sync_into(atn(), 856, &mut __ctx, __loop_iter_856, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 | 175 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 856, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_856 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 853isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_862 = false; - loop { - self.base.sync_into(atn(), 862, &mut __ctx, __loop_iter_862, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 175 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 862, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_862 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 859isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(175, 866, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 866isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 867isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 873, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 873, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 868isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 869isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 871, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(167, 874, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_37(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 74isize, 37, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_878 = false; - loop { - self.base.sync_into(atn(), 878, &mut __ctx, __loop_iter_878, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 878, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_878 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 875isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_884 = false; - loop { - self.base.sync_into(atn(), 884, &mut __ctx, __loop_iter_884, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 884) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(61, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(61, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 884, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_884 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 881isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 887isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 889, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 889) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(62, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(62, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 889, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 888isize, self.dispatch_generated_rule(35, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 891isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 893, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 893, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 892isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 895isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_899 = false; - loop { - self.base.sync_into(atn(), 899, &mut __ctx, __loop_iter_899, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 78 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 | 167 | 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 899, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_899 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 896isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 907, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 907, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 902isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 903isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 905, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(167, 908, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_38(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 76isize, 38, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(168, 910, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 910isize, self.dispatch_generated_rule(39, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_915 = false; - loop { - self.base.sync_into(atn(), 915, &mut __ctx, __loop_iter_915, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 170 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 915, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_915 = true; - self.base.match_token_into(163, 912, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 912isize, self.dispatch_generated_rule(39, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(170, 919, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_39(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 78isize, 39, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_923 = false; - loop { - self.base.sync_into(atn(), 923, &mut __ctx, __loop_iter_923, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114..=115 | 117 | 119 | 141 | 146 | 149 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 923, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_923 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 920isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 927, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 115 | 149 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 927, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_set_into(&[(115, 115), (149, 149)], 928, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 929isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_40(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 80isize, 40, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(78, 932, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 932isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(199, 934, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 934isize, self.dispatch_generated_rule(41, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_939 = false; - loop { - self.base.sync_into(atn(), 939, &mut __ctx, __loop_iter_939, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 138 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 939, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_939 = true; - self.base.match_token_into(163, 936, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 936isize, self.dispatch_generated_rule(41, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_41(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 82isize, 41, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 54 | 64 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 113 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 18 | 25 | 28 | 32..=34 | 38..=40 | 42..=43 | 46 | 48 | 50 | 53 | 58..=61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=112 | 114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 947, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 947) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(70, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(70, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 947, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 942isize, self.dispatch_generated_rule(42, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 943isize, self.dispatch_generated_rule(45, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 944isize, self.dispatch_generated_rule(46, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 945isize, self.dispatch_generated_rule(47, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 946isize, self.dispatch_generated_rule(48, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_42(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 84isize, 42, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(37, 950, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 950isize, self.dispatch_generated_rule(43, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_955 = false; - loop { - self.base.sync_into(atn(), 955, &mut __ctx, __loop_iter_955, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 955) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(71, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(71, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 955, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_955 = true; - self.base.match_token_into(163, 952, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 952isize, self.dispatch_generated_rule(43, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_43(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 86isize, 43, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 958isize, self.dispatch_generated_rule(44, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_44(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 88isize, 44, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(116, 961, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(54, 962, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_45(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 90isize, 45, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 64 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 54 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 971, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 64 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 54 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 971, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(64, 965, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 965, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 171 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 138 | 141 | 146..=148 | 151..=153 | 156 | 160..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 965, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(171, 966, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - self.base.match_token_into(54, 969, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 969, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 171 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 138 | 141 | 146..=148 | 151..=153 | 156 | 160..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 969, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(171, 970, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_46(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 92isize, 46, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(113, 974, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 975, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(201, 976, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_47(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 94isize, 47, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(29, 978, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_48(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 96isize, 48, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 979isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_49(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 98isize, 49, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_984 = false; - loop { - self.base.sync_into(atn(), 984, &mut __ctx, __loop_iter_984, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 984, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_984 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 981isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_990 = false; - loop { - self.base.sync_into(atn(), 990, &mut __ctx, __loop_iter_990, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 990) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(76, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(76, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 990, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_990 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 987isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 993isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 995, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 22 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 995, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 994isize, self.dispatch_generated_rule(35, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(22, 999, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 999, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 67 | 99 | 105 | 120..=121 | 123..=128 | 131 | 135..=137 | 139 | 144 | 150 | 154 | 156 | 159..=162 | 164 | 166 | 168 | 170 | 172 | 174..=175 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 999, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(27, 1000, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 162 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 164 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 156 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 175 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 127 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 161 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 166 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 159 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 135 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 174 => antlr4_runtime::ParserAtnPrediction { alt: 13, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 160 => antlr4_runtime::ParserAtnPrediction { alt: 14, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 172 => antlr4_runtime::ParserAtnPrediction { alt: 15, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 137 => antlr4_runtime::ParserAtnPrediction { alt: 16, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 120 => antlr4_runtime::ParserAtnPrediction { alt: 17, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 168 => antlr4_runtime::ParserAtnPrediction { alt: 18, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 136 => antlr4_runtime::ParserAtnPrediction { alt: 19, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 139 => antlr4_runtime::ParserAtnPrediction { alt: 21, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 67 => antlr4_runtime::ParserAtnPrediction { alt: 22, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 99 => antlr4_runtime::ParserAtnPrediction { alt: 23, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 150 => antlr4_runtime::ParserAtnPrediction { alt: 24, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 126 => antlr4_runtime::ParserAtnPrediction { alt: 25, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 128 => antlr4_runtime::ParserAtnPrediction { alt: 26, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 27, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131 => antlr4_runtime::ParserAtnPrediction { alt: 28, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 121 => antlr4_runtime::ParserAtnPrediction { alt: 29, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 123 => antlr4_runtime::ParserAtnPrediction { alt: 30, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 154 => antlr4_runtime::ParserAtnPrediction { alt: 31, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 144 => antlr4_runtime::ParserAtnPrediction { alt: 32, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 105 => antlr4_runtime::ParserAtnPrediction { alt: 33, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1036, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1036) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(79, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(79, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1036, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(162, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(164, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(156, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(175, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(125, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - self.base.match_token_into(127, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - self.base.match_token_into(161, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 8 => { - self.base.match_token_into(166, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 9 => { - self.base.match_token_into(159, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - self.base.match_token_into(135, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1011isize, self.dispatch_generated_rule(238, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 12 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1012isize, self.dispatch_generated_rule(239, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 13 => { - self.base.match_token_into(174, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 14 => { - self.base.match_token_into(160, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 15 => { - self.base.match_token_into(172, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 16 => { - self.base.match_token_into(137, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 17 => { - self.base.match_token_into(120, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 18 => { - self.base.match_token_into(168, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 19 => { - self.base.match_token_into(136, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 20 => { - self.base.match_token_into(170, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 21 => { - self.base.match_token_into(139, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 22 => { - self.base.match_token_into(67, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 23 => { - self.base.match_token_into(99, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 24 => { - self.base.match_token_into(150, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 25 => { - self.base.match_token_into(126, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 26 => { - self.base.match_token_into(128, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 27 => { - self.base.match_token_into(124, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 28 => { - self.base.match_token_into(131, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 29 => { - self.base.match_token_into(121, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 30 => { - self.base.match_token_into(123, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 31 => { - self.base.match_token_into(154, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 32 => { - self.base.match_token_into(144, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 33 => { - self.base.match_token_into(105, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 34 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1034isize, self.dispatch_generated_rule(240, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 35 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1035isize, self.dispatch_generated_rule(241, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1038isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1044, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1044, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1039isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1040isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 1042, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(167, 1045, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_50(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 100isize, 50, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1048, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1048) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(81, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(81, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1048, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1046isize, self.dispatch_generated_rule(51, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1047isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_51(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 102isize, 51, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1053 = false; - loop { - self.base.sync_into(atn(), 1053, &mut __ctx, __loop_iter_1053, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12..=13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1053, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1053 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1050isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1059 = false; - loop { - self.base.sync_into(atn(), 1059, &mut __ctx, __loop_iter_1059, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1059, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1059 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1056isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(12, 1063, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1063isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 1068, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1068 = false; - loop { - self.base.sync_into(atn(), 1068, &mut __ctx, __loop_iter_1068, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1068) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(84, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(84, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1068, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1068 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1065isize, self.dispatch_generated_rule(1, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1074 = false; - loop { - self.base.sync_into(atn(), 1074, &mut __ctx, __loop_iter_1074, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1074) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(85, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(85, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1074, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1074 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1071isize, self.dispatch_generated_rule(2, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1080 = false; - loop { - self.base.sync_into(atn(), 1080, &mut __ctx, __loop_iter_1080, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1080) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(86, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(86, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1080, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1080 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1077isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_52(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 104isize, 52, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1086 = false; - loop { - self.base.sync_into(atn(), 1086, &mut __ctx, __loop_iter_1086, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12..=13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1086, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1086 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1083isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1092 = false; - loop { - self.base.sync_into(atn(), 1092, &mut __ctx, __loop_iter_1092, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1092, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1092 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1089isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(12, 1096, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1096isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(197, 1101, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1101 = false; - loop { - self.base.sync_into(atn(), 1101, &mut __ctx, __loop_iter_1101, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1101) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(89, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(89, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1101, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1101 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1098isize, self.dispatch_generated_rule(1, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1107 = false; - loop { - self.base.sync_into(atn(), 1107, &mut __ctx, __loop_iter_1107, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1107) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(90, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(90, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1107, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1107 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1104isize, self.dispatch_generated_rule(2, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1113 = false; - loop { - self.base.sync_into(atn(), 1113, &mut __ctx, __loop_iter_1113, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1113, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1113 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1110isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1118, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1118, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1118) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(92, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(92, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1118, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(167, 1119, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_53(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 106isize, 53, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 66 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1123, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1123) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(93, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(93, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1123, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1120isize, self.dispatch_generated_rule(54, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1121isize, self.dispatch_generated_rule(57, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1122isize, self.dispatch_generated_rule(59, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_54(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 108isize, 54, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1128 = false; - loop { - self.base.sync_into(atn(), 1128, &mut __ctx, __loop_iter_1128, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65..=66 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1128, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1128 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1125isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1134 = false; - loop { - self.base.sync_into(atn(), 1134, &mut __ctx, __loop_iter_1134, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 66 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1134, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1134 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1131isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(66, 1138, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1138isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1140, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1140) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(96, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(96, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1140, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1139isize, self.dispatch_generated_rule(35, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1142isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1145, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1145, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1143isize, self.dispatch_generated_rule(55, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(167, 1146, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_55(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 110isize, 55, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(197, 1151, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1151 = false; - loop { - self.base.sync_into(atn(), 1151, &mut __ctx, __loop_iter_1151, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45..=46 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 91 | 97 | 107 | 110 | 113 | 116..=117 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1151, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1151 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1148isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1155, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_56(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 112isize, 56, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1159 = false; - loop { - self.base.sync_into(atn(), 1159, &mut __ctx, __loop_iter_1159, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45..=46 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 91 | 97 | 107 | 110 | 113 | 116..=117 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1159, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1159 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1156isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1165 = false; - loop { - self.base.sync_into(atn(), 1165, &mut __ctx, __loop_iter_1165, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 46 | 91 | 107 | 110 | 117 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1165, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1165 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1162isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_set_into(&[(46, 46), (91, 91), (107, 107), (110, 110), (117, 117)], 1174, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1174, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1174, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1169isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1170isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 1172, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(167, 1175, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_57(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 114isize, 57, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1179 = false; - loop { - self.base.sync_into(atn(), 1179, &mut __ctx, __loop_iter_1179, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1179, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1179 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1176isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1185 = false; - loop { - self.base.sync_into(atn(), 1185, &mut __ctx, __loop_iter_1185, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1185) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(103, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(103, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1185, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1185 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1182isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1188isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1190, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 98 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1190, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1189isize, self.dispatch_generated_rule(35, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(98, 1193, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1193isize, self.dispatch_generated_rule(58, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1198, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1198, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1194isize, self.dispatch_generated_rule(55, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1195isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 1197, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_58(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 116isize, 58, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(202, 1201, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1201isize, self.dispatch_generated_rule(29, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1206 = false; - loop { - self.base.sync_into(atn(), 1206, &mut __ctx, __loop_iter_1206, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1206, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1206 = true; - self.base.match_token_into(163, 1203, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1203isize, self.dispatch_generated_rule(29, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(203, 1210, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_59(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 118isize, 59, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1214 = false; - loop { - self.base.sync_into(atn(), 1214, &mut __ctx, __loop_iter_1214, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1214, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1214 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1211isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1220 = false; - loop { - self.base.sync_into(atn(), 1220, &mut __ctx, __loop_iter_1220, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1220) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(108, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(108, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1220, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1220 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1217isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1223isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1225, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1225) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(109, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(109, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1225, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1224isize, self.dispatch_generated_rule(35, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1227isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 | 169 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1240, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 | 169 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1240, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1228isize, self.dispatch_generated_rule(55, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1232, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 169 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1232, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1229isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 1231, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 138 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 169 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1236, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 138 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 169 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1236, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1234isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1235isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 1239, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_60(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 120isize, 60, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 87 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10..=11 | 54 | 64 | 76 | 176 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1244, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1244) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(113, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(113, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1244, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1242isize, self.dispatch_generated_rule(61, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1243isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_61(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 122isize, 61, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1249 = false; - loop { - self.base.sync_into(atn(), 1249, &mut __ctx, __loop_iter_1249, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 87..=88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1249, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1249 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1246isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1255 = false; - loop { - self.base.sync_into(atn(), 1255, &mut __ctx, __loop_iter_1255, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 87 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1255, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1255 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1252isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(87, 1259, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1259isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1261, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1261, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1260isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1278, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1278) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(120, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(120, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1278, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(197, 1275, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1275, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 13 | 15..=16 | 21 | 23..=26 | 32..=38 | 40..=42 | 45..=46 | 48..=50 | 52 | 57 | 59..=61 | 65 | 68..=69 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1275, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1264isize, self.dispatch_generated_rule(66, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1269 = false; - loop { - self.base.sync_into(atn(), 1269, &mut __ctx, __loop_iter_1269, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1269) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(117, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(117, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1269, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1269 = true; - self.base.match_token_into(163, 1266, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1266isize, self.dispatch_generated_rule(66, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1273, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1273, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(163, 1274, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(198, 1279, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1281, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1281) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(121, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(121, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1281, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(167, 1282, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_62(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 124isize, 62, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(199, 1284, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1284isize, self.dispatch_generated_rule(63, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1289 = false; - loop { - self.base.sync_into(atn(), 1289, &mut __ctx, __loop_iter_1289, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1289, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1289 = true; - self.base.match_token_into(163, 1286, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1286isize, self.dispatch_generated_rule(63, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_63(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 126isize, 63, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1294, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1294) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(123, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(123, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1294, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1292isize, self.dispatch_generated_rule(64, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1293isize, self.dispatch_generated_rule(65, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_64(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 128isize, 64, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1296isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1297isize, self.dispatch_generated_rule(31, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_65(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 130isize, 65, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1299isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_66(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 132isize, 66, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1304 = false; - loop { - self.base.sync_into(atn(), 1304, &mut __ctx, __loop_iter_1304, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 21 | 23..=26 | 32..=38 | 40..=42 | 45..=46 | 48..=50 | 52 | 57 | 59..=61 | 65 | 68..=69 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1304, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1304 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1301isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1310 = false; - loop { - self.base.sync_into(atn(), 1310, &mut __ctx, __loop_iter_1310, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1310) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(125, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(125, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1310, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1310 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1307isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1313isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1315, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 169 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1315, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1314isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_67(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 134isize, 67, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 64 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 176 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 54 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 76 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1323, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1323) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(127, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(127, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1323, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1317isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1318isize, self.dispatch_generated_rule(69, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1319isize, self.dispatch_generated_rule(70, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1320isize, self.dispatch_generated_rule(71, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1321isize, self.dispatch_generated_rule(72, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1322isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_68(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 136isize, 68, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1328 = false; - loop { - self.base.sync_into(atn(), 1328, &mut __ctx, __loop_iter_1328, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 64..=65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1328, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1328 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1325isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1334 = false; - loop { - self.base.sync_into(atn(), 1334, &mut __ctx, __loop_iter_1334, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 64 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1334, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1334 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1331isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(64, 1338, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1338isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1340, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1340, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1339isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1343, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1343) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(131, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(131, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1343, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1342isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1346, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1346, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1345isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1351 = false; - loop { - self.base.sync_into(atn(), 1351, &mut __ctx, __loop_iter_1351, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1351) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(133, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(133, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1351, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1351 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1348isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1362, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1362) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(135, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(135, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1362, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(197, 1358, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1358 = false; - loop { - self.base.sync_into(atn(), 1358, &mut __ctx, __loop_iter_1358, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1358, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1358 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1355isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1363, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1365, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1365) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(136, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(136, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1365, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(167, 1366, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_69(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 138isize, 69, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1370 = false; - loop { - self.base.sync_into(atn(), 1370, &mut __ctx, __loop_iter_1370, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 | 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1370, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1370 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1367isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1376 = false; - loop { - self.base.sync_into(atn(), 1376, &mut __ctx, __loop_iter_1376, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1376, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1376 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1373isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1381, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1381, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78 | 197 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1381, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1380isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1384, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78 | 197 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1384, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1383isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1389 = false; - loop { - self.base.sync_into(atn(), 1389, &mut __ctx, __loop_iter_1389, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 78 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 197 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1389, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1389 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1386isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(197, 1396, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1396 = false; - loop { - self.base.sync_into(atn(), 1396, &mut __ctx, __loop_iter_1396, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1396, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1396 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1393isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1400, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_70(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 140isize, 70, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1404 = false; - loop { - self.base.sync_into(atn(), 1404, &mut __ctx, __loop_iter_1404, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 | 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1404, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1404 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1401isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1410 = false; - loop { - self.base.sync_into(atn(), 1410, &mut __ctx, __loop_iter_1410, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1410, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1410 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1407isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(11, 1414, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1414isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1416, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1416, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1415isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1419, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1419) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(146, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(146, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1419, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1418isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1422, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1422, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1421isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1427 = false; - loop { - self.base.sync_into(atn(), 1427, &mut __ctx, __loop_iter_1427, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1427) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(148, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(148, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1427, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1427 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1424isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1438, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1438) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(150, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(150, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1438, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(197, 1434, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1434 = false; - loop { - self.base.sync_into(atn(), 1434, &mut __ctx, __loop_iter_1434, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1434, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1434 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1431isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1439, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1441, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1441) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(151, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(151, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1441, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(167, 1442, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_71(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 142isize, 71, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1446 = false; - loop { - self.base.sync_into(atn(), 1446, &mut __ctx, __loop_iter_1446, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 | 176 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1446, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1446 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1443isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1452 = false; - loop { - self.base.sync_into(atn(), 1452, &mut __ctx, __loop_iter_1452, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 176 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1452, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1452 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1449isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1455isize, self.dispatch_generated_rule(237, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1457, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 54 | 64 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1457, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_set_into(&[(54, 54), (64, 64)], 1458, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1459isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1461, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1461, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1460isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1464, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1464) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(156, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(156, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1464, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1463isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1467, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1467, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1466isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1472 = false; - loop { - self.base.sync_into(atn(), 1472, &mut __ctx, __loop_iter_1472, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1472) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(158, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(158, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1472, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1472 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1469isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1483, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1483) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(160, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(160, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1483, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(197, 1479, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1479 = false; - loop { - self.base.sync_into(atn(), 1479, &mut __ctx, __loop_iter_1479, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1479, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1479 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1476isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1484, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1486, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1486) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(161, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(161, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1486, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(167, 1487, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_72(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 144isize, 72, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1491 = false; - loop { - self.base.sync_into(atn(), 1491, &mut __ctx, __loop_iter_1491, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 54 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1491, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1491 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1488isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1497 = false; - loop { - self.base.sync_into(atn(), 1497, &mut __ctx, __loop_iter_1497, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 54 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1497, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1497 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1494isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(54, 1501, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1501isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1503, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1503, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1502isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1506, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1506) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(165, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(165, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1506, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1505isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1509, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1509, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1508isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1514 = false; - loop { - self.base.sync_into(atn(), 1514, &mut __ctx, __loop_iter_1514, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1514) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(167, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(167, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1514, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1514 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1511isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1525, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1525) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(169, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(169, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1525, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(197, 1521, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1521 = false; - loop { - self.base.sync_into(atn(), 1521, &mut __ctx, __loop_iter_1521, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1521, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1521 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1518isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1526, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1528, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1528) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(170, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(170, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1528, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(167, 1529, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_73(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 146isize, 73, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1533 = false; - loop { - self.base.sync_into(atn(), 1533, &mut __ctx, __loop_iter_1533, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 76 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1533, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1533 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1530isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1539 = false; - loop { - self.base.sync_into(atn(), 1539, &mut __ctx, __loop_iter_1539, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 76 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1539, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1539 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1536isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(76, 1543, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1543isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1545, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1545, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1544isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1548, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1548) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(174, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(174, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1548, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1547isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1551, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1551, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1550isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1556 = false; - loop { - self.base.sync_into(atn(), 1556, &mut __ctx, __loop_iter_1556, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1556) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(176, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(176, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1556, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1556 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1553isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1567, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1567) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(178, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(178, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1567, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(197, 1563, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1563 = false; - loop { - self.base.sync_into(atn(), 1563, &mut __ctx, __loop_iter_1563, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=83 | 85 | 87..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1563, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1563 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1560isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 1568, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1570, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1570) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(179, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(179, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1570, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(167, 1571, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_74(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 148isize, 74, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1575 = false; - loop { - self.base.sync_into(atn(), 1575, &mut __ctx, __loop_iter_1575, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 18 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1575, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1575 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1572isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1581 = false; - loop { - self.base.sync_into(atn(), 1581, &mut __ctx, __loop_iter_1581, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1581, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1581 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1578isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(18, 1585, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1585isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1586isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1588, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1588, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1587isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1590isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1594 = false; - loop { - self.base.sync_into(atn(), 1594, &mut __ctx, __loop_iter_1594, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 78 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1594, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1594 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1591isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(167, 1598, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_75(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 150isize, 75, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1602 = false; - loop { - self.base.sync_into(atn(), 1602, &mut __ctx, __loop_iter_1602, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1602) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(184, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(184, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1602, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1602 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1599isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1608 = false; - loop { - self.base.sync_into(atn(), 1608, &mut __ctx, __loop_iter_1608, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1608) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(185, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(185, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1608, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1608 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1605isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1611isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_76(&mut self, allow_fallback: bool) -> Result { - self.parse_generated_rule_76_precedence(0, allow_fallback) - } - - #[allow(dead_code)] - fn parse_generated_rule_76_precedence(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - antlr4_runtime::__antlr4_rust_generated_rule! { - recursive self, 152isize, 76, __precedence, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 18 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 | 39 | 43 | 53 | 58 | 70 | 72..=73 | 75 | 82..=83 | 85 | 95 | 100..=101 | 111 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 116 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 200 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1620, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1620) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(186, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(186, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1620, &__prediction); - match __prediction.alt { - 1 => { - let action = self.base.parser_action_at_current_indexed(1613, 76, 1, __rule_start, __consumed_eof); - let _ = action; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1614isize, self.dispatch_generated_rule(79, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1615isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1616isize, self.dispatch_generated_rule(85, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1617isize, self.dispatch_generated_rule(86, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1618isize, self.dispatch_generated_rule(87, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1619isize, self.dispatch_generated_rule(88, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - loop { - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.left_recursive_loop_enter_prediction(atn(), 1634, __precedence) { - Some(true) => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: true, diagnostic: None }, - Some(false) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - None => { - let __prediction_precedence = if __precedence <= 0 { 0 } else { __precedence as usize }; - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - match __simulator.adaptive_predict_stream_info_with_context(189, __prediction_precedence, self.base.input(), __prediction_context) { - Ok(__prediction) => __prediction, - Err(antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { .. }) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: true, has_semantic_context: false, diagnostic: None }, - Err(_) => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1634, &__prediction); - match __prediction.alt { - 1 => { - self.base.parse_listener_exit_rule(76); - if let Some(__depth_error) = self.base.rule_depth_cap_violation() { - return Err(__depth_error); - } - self.base.push_new_recursion_context_with_previous(152isize, 76, &mut __ctx); - if let Some(__listener_error) = self.base.parse_listener_enter_rule(76) { - return Err(__listener_error); - } - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(188, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - if !self.base.precpred(9) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 9)")); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1623isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1626 = true; - loop { - self.base.sync_into(atn(), 1626, &mut __ctx, __loop_iter_1626, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(187, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - self.base.record_generated_prediction_diagnostic(atn(), 1626, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1626 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1623isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if !self.base.precpred(6) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 6)")); - } - self.base.match_token_into(171, 1633, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if !self.base.precpred(5) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 5)")); - } - self.base.match_token_into(161, 1633, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => break, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_77(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 154isize, 77, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1637isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1638isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1641 = true; - loop { - self.base.sync_into(atn(), 1641, &mut __ctx, __loop_iter_1641, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1641) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(190, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(190, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1641, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1641 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1638isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_78(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 156isize, 78, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(202, 1656, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1656, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1656) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(194, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(194, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1656, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 1645, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1645, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1644isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1644isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1653 = false; - loop { - self.base.sync_into(atn(), 1653, &mut __ctx, __loop_iter_1653, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1653, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1653 = true; - self.base.match_token_into(163, 1649, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1649, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1649, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1648isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1648isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(203, 1659, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_79(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 158isize, 79, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(18, 1661, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(161, 1663, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1663, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 15 | 32 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 168 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1663, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1662isize, self.dispatch_generated_rule(80, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1665isize, self.dispatch_generated_rule(83, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_80(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 160isize, 80, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 32 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 15 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1675, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 32 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 15 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1675, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(32, 1669, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1669, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 168 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1669, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1668isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - self.base.match_token_into(15, 1673, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1673, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 168 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1673, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1672isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_81(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 162isize, 81, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(202, 1678, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1678isize, self.dispatch_generated_rule(82, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1683 = false; - loop { - self.base.sync_into(atn(), 1683, &mut __ctx, __loop_iter_1683, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1683, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1683 = true; - self.base.match_token_into(163, 1680, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1680isize, self.dispatch_generated_rule(82, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(203, 1687, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_82(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 164isize, 82, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1688isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_83(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 166isize, 83, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(168, 1691, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1691isize, self.dispatch_generated_rule(84, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1696 = false; - loop { - self.base.sync_into(atn(), 1696, &mut __ctx, __loop_iter_1696, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 170 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1696, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1696 = true; - self.base.match_token_into(163, 1693, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1693isize, self.dispatch_generated_rule(84, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(170, 1700, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_84(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 168isize, 84, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1704 = false; - loop { - self.base.sync_into(atn(), 1704, &mut __ctx, __loop_iter_1704, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1704, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1704 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1701isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1710 = false; - loop { - self.base.sync_into(atn(), 1710, &mut __ctx, __loop_iter_1710, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1710) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(202, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(202, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1710, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1710 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1707isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1713isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_85(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 170isize, 85, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(28, 28), (39, 39), (43, 43), (53, 53), (58, 58), (70, 70), (72, 73), (75, 75), (82, 83), (85, 85), (95, 95), (100, 101), (111, 111)], 1716, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_86(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 172isize, 86, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(116, 1719, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1719, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 24 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 18 | 25 | 28 | 32..=34 | 37..=40 | 42..=43 | 46 | 48 | 50 | 53 | 58..=61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=112 | 114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1719, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(24, 1720, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1721isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_87(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 174isize, 87, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(48, 1724, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1724isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_88(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 176isize, 88, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 1727, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1727isize, self.dispatch_generated_rule(89, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(163, 1729, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1729isize, self.dispatch_generated_rule(89, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1732 = true; - loop { - self.base.sync_into(atn(), 1732, &mut __ctx, __loop_iter_1732, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1732, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1732 = true; - self.base.match_token_into(163, 1729, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1729isize, self.dispatch_generated_rule(89, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(201, 1735, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_89(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 178isize, 89, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1736isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1738, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1738, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1737isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_90(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 180isize, 90, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 62 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 147 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5..=8 | 29 | 51 | 56 | 67 | 81 | 96 | 98..=99 | 125 | 127 | 130 | 156 | 160..=162 | 164..=165 | 172 | 175 | 178..=186 | 194..=196 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109 => antlr4_runtime::ParserAtnPrediction { alt: 11, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 12, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 148 => antlr4_runtime::ParserAtnPrediction { alt: 13, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 => antlr4_runtime::ParserAtnPrediction { alt: 16, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 17, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 55 => antlr4_runtime::ParserAtnPrediction { alt: 18, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 118 => antlr4_runtime::ParserAtnPrediction { alt: 20, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 => antlr4_runtime::ParserAtnPrediction { alt: 23, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1764, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1764) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(206, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(206, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1764, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1740isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1741isize, self.dispatch_generated_rule(91, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1742isize, self.dispatch_generated_rule(92, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1743isize, self.dispatch_generated_rule(93, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1744isize, self.dispatch_generated_rule(96, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1745isize, self.dispatch_generated_rule(97, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1746isize, self.dispatch_generated_rule(98, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1747isize, self.dispatch_generated_rule(106, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1748isize, self.dispatch_generated_rule(99, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 10 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1749isize, self.dispatch_generated_rule(100, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1750isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(101, 0) } else { self.parse_generated_rule_101_adaptive_dispatch(0, false, Some(1750isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 12 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1751isize, self.dispatch_generated_rule(102, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 13 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1752isize, self.dispatch_generated_rule(103, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 14 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1753isize, self.dispatch_generated_rule(105, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 15 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1754isize, self.dispatch_generated_rule(107, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 16 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1755isize, self.dispatch_generated_rule(108, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 17 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1756isize, self.dispatch_generated_rule(109, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 18 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1757isize, self.dispatch_generated_rule(110, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 19 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1758isize, self.dispatch_generated_rule(138, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 20 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1759isize, self.dispatch_generated_rule(139, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 21 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1760isize, self.dispatch_generated_rule(144, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 22 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1761isize, self.dispatch_generated_rule(145, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 23 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1762isize, self.dispatch_generated_rule(146, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 24 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1763isize, self.dispatch_generated_rule(147, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_91(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 182isize, 91, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1769 = false; - loop { - self.base.sync_into(atn(), 1769, &mut __ctx, __loop_iter_1769, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1769, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1769 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1766isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(62, 1774, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1774, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1774, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1773isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 1777, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_92(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 184isize, 92, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1781 = false; - loop { - self.base.sync_into(atn(), 1781, &mut __ctx, __loop_iter_1781, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 | 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1781, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1781 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1778isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_set_into(&[(14, 14), (27, 27)], 1785, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1785isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_93(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 186isize, 93, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1789, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1789) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(210, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(210, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1789, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1787isize, self.dispatch_generated_rule(94, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1788isize, self.dispatch_generated_rule(95, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_94(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 188isize, 94, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1794 = false; - loop { - self.base.sync_into(atn(), 1794, &mut __ctx, __loop_iter_1794, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 | 61 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1794, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1794 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1791isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1798, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 61 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1798, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(61, 1799, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(31, 1801, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 1802, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1802isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1803isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(149, 1805, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1805isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1805isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 1807, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1807isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_95(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 190isize, 95, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1812 = false; - loop { - self.base.sync_into(atn(), 1812, &mut __ctx, __loop_iter_1812, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 | 61 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1812, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1812 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1809isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1816, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 61 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1816, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(61, 1817, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(31, 1819, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 1820, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1820isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1820isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(149, 1822, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1822isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1822isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 1824, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1824isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_96(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 192isize, 96, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1829 = false; - loop { - self.base.sync_into(atn(), 1829, &mut __ctx, __loop_iter_1829, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1829, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1829 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1826isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(17, 1834, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1834, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1834, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1833isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 1837, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_97(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 194isize, 97, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1841 = false; - loop { - self.base.sync_into(atn(), 1841, &mut __ctx, __loop_iter_1841, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 147 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1841, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1841 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1838isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(147, 1845, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1845isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(79, 1847, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 1848, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1848isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1848isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 1850, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(167, 1851, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_98(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 196isize, 98, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1855 = false; - loop { - self.base.sync_into(atn(), 1855, &mut __ctx, __loop_iter_1855, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1855, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1855 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1852isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(167, 1859, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_99(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 198isize, 99, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1863 = false; - loop { - self.base.sync_into(atn(), 1863, &mut __ctx, __loop_iter_1863, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1863) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(219, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(219, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1863, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1863 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1860isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1866isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1866isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(167, 1868, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_100(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 200isize, 100, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1872 = false; - loop { - self.base.sync_into(atn(), 1872, &mut __ctx, __loop_iter_1872, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 69 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1872, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1872 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1869isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(69, 1876, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 1877, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1877isize, self.dispatch_generated_rule(20, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(201, 1879, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1879isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_101_adaptive_dispatch(&mut self, precedence: i32, allow_fallback: bool, invoking_state: Option) -> Result { - if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() { - return self.dispatch_generated_rule(101, precedence, allow_fallback); - } - let __adaptive_outermost = self.adaptive_atn.preference_depths[0] == 0; - let __adaptive_rule_start = antlr4_runtime::IntStream::index(self.base.input()); - let __adaptive_parser_state = self.base.state(); - let __adaptive_diagnostic_marker = self.base.generated_diagnostics_checkpoint(); - if __adaptive_outermost { - self.adaptive_atn.preference_starts[0] = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - .unwrap_or((0, 0)); - self.adaptive_atn.syntax_error_starts[0] = self.base.number_of_syntax_errors(); - } - self.adaptive_atn.preference_depths[0] += 1; - let mut __result = self.dispatch_generated_rule(101, precedence, allow_fallback); - self.adaptive_atn.preference_depths[0] -= 1; - if !self.adaptive_atn.preferred_rules[0] { - if let Some(__adaptive_after) = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - { - let __adaptive_expensive = __result.is_ok() - && self.base.number_of_syntax_errors() == self.adaptive_atn.syntax_error_starts[0] - && antlr4_runtime::ParserAtnSimulator::adaptive_prediction_delta_is_expensive(self.adaptive_atn.preference_starts[0], __adaptive_after); - self.adaptive_atn.preferred_rules[0] = __adaptive_expensive; - if __adaptive_expensive { - self.adaptive_atn.retry_slot = Some(0); - __result = Err(GeneratedRuleError::AdaptiveRetry); - } - } - } - if __adaptive_outermost - && self.adaptive_atn.retry_slot == Some(0) - && matches!(&__result, Err(GeneratedRuleError::AdaptiveRetry)) - { - self.adaptive_atn.retry_slot = None; - self.base.restore_generated_diagnostics(__adaptive_diagnostic_marker); - antlr4_runtime::IntStream::seek(self.base.input(), __adaptive_rule_start); - self.base.set_state(__adaptive_parser_state); - if let Some(invoking_state) = invoking_state { - self.base.push_invoking_state(invoking_state); - } - return self.parse_rule_precedence_from_generated(101, precedence).map_err(GeneratedRuleError::Interpreted); - } - __result - } - - #[allow(dead_code)] - fn parse_generated_rule_101(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 202isize, 101, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1884 = false; - loop { - self.base.sync_into(atn(), 1884, &mut __ctx, __loop_iter_1884, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1884, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1884 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1881isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(109, 1888, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 1902, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1902, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1902) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(225, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(225, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1902, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 1890, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 18 | 25 | 28 | 32..=34 | 37..=40 | 42..=43 | 46 | 48 | 50 | 53 | 58..=61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=112 | 114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1890, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1889isize, self.dispatch_generated_rule(20, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - self.base.sync_into(atn(), 1900, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1900, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1892isize, self.parse_generated_rule_148_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1897 = false; - loop { - self.base.sync_into(atn(), 1897, &mut __ctx, __loop_iter_1897, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1897, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1897 = true; - self.base.match_token_into(163, 1894, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1894isize, self.parse_generated_rule_148_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 1906, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1906, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1906, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1905isize, self.parse_generated_rule_148_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 1917, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1917, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1917, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1909isize, self.parse_generated_rule_148_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1914 = false; - loop { - self.base.sync_into(atn(), 1914, &mut __ctx, __loop_iter_1914, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1914, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1914 = true; - self.base.match_token_into(163, 1911, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1911isize, self.parse_generated_rule_148_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 1920, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1920isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_102(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 204isize, 102, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1925 = false; - loop { - self.base.sync_into(atn(), 1925, &mut __ctx, __loop_iter_1925, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1925, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1925 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1922isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(90, 1930, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1930, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1930) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(230, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(230, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1930, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_set_into(&[(29, 29), (84, 84)], 1931, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1933, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1933, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1932isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1932isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 1936, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_103(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 206isize, 103, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1940 = false; - loop { - self.base.sync_into(atn(), 1940, &mut __ctx, __loop_iter_1940, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1940, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1940 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1937isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(148, 1944, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 1945, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1945isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(1945isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 1947, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1947isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1949, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1949) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(233, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(233, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1949, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1948isize, self.dispatch_generated_rule(104, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_104(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 208isize, 104, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(86, 1952, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1952isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_105(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 210isize, 105, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1957 = false; - loop { - self.base.sync_into(atn(), 1957, &mut __ctx, __loop_iter_1957, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1957, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1957 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1954isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1960isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(199, 1962, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1962isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_106(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 212isize, 106, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1967 = false; - loop { - self.base.sync_into(atn(), 1967, &mut __ctx, __loop_iter_1967, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1967, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1967 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1964isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1971, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1971) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(236, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(236, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1971, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(61, 1972, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1974, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 77 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1974, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(77, 1975, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1979 = false; - loop { - self.base.sync_into(atn(), 1979, &mut __ctx, __loop_iter_1979, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1979) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(238, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(238, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1979, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1979 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1976isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1982isize, self.dispatch_generated_rule(242, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 1984, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_107(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 214isize, 107, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1988 = false; - loop { - self.base.sync_into(atn(), 1988, &mut __ctx, __loop_iter_1988, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1988, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1988 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1985isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1994 = false; - loop { - self.base.sync_into(atn(), 1994, &mut __ctx, __loop_iter_1994, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1994) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(240, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(240, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1994, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1994 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1991isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1997isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1998isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2000, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2000, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1999isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2002isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2006 = false; - loop { - self.base.sync_into(atn(), 2006, &mut __ctx, __loop_iter_2006, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 78 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 | 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2006, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2006 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2003isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2013, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2013, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2009isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2010isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(167, 2012, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_108(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 216isize, 108, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2018 = false; - loop { - self.base.sync_into(atn(), 2018, &mut __ctx, __loop_iter_2018, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2018, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2018 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2015isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(94, 2022, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2023, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2023isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2023isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2025, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2025isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_109(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 218isize, 109, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2030 = false; - loop { - self.base.sync_into(atn(), 2030, &mut __ctx, __loop_iter_2030, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2030, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2030 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2027isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(47, 2035, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2035, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2035, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2034isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2034isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 2038, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_110(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 220isize, 110, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2042 = false; - loop { - self.base.sync_into(atn(), 2042, &mut __ctx, __loop_iter_2042, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 55 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2042, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2042 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2039isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(55, 2046, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2047, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2047isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2047isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2049, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(197, 2053, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2053 = false; - loop { - self.base.sync_into(atn(), 2053, &mut __ctx, __loop_iter_2053, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 29 | 84 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2053, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2053 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2050isize, self.dispatch_generated_rule(111, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(198, 2057, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_111(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 222isize, 111, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2058isize, self.dispatch_generated_rule(112, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2061 = true; - loop { - self.base.sync_into(atn(), 2061, &mut __ctx, __loop_iter_2061, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2061) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(249, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(249, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2061, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2061 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2058isize, self.dispatch_generated_rule(112, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2063isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2066 = true; - loop { - self.base.sync_into(atn(), 2066, &mut __ctx, __loop_iter_2066, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2066) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(250, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(250, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2066, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2066 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2063isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_112(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 224isize, 112, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 29 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2071, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2071) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(251, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(251, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2071, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2068isize, self.dispatch_generated_rule(113, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2069isize, self.dispatch_generated_rule(136, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2070isize, self.dispatch_generated_rule(137, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_113(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 226isize, 113, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(84, 2074, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2074isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2076, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 102 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 199 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2076, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2075isize, self.dispatch_generated_rule(135, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(199, 2079, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_114(&mut self, allow_fallback: bool) -> Result { - self.parse_generated_rule_114_precedence(0, allow_fallback) - } - - #[allow(dead_code)] - fn parse_generated_rule_114_precedence(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - antlr4_runtime::__antlr4_rust_generated_rule! { - recursive self, 228isize, 114, __precedence, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2092, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2092) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(253, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(253, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2092, &__prediction); - match __prediction.alt { - 1 => { - let action = self.base.parser_action_at_current_indexed(2080, 114, 2, __rule_start, __consumed_eof); - let _ = action; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2081isize, self.dispatch_generated_rule(134, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2082isize, self.dispatch_generated_rule(115, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2083isize, self.dispatch_generated_rule(116, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2084isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2085isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2086isize, self.dispatch_generated_rule(123, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2087isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2088isize, self.dispatch_generated_rule(130, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2089isize, self.dispatch_generated_rule(131, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 10 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2090isize, self.dispatch_generated_rule(132, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2091isize, self.dispatch_generated_rule(133, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - loop { - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.left_recursive_loop_enter_prediction(atn(), 2099, __precedence) { - Some(true) => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: true, diagnostic: None }, - Some(false) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - None => { - let __prediction_precedence = if __precedence <= 0 { 0 } else { __precedence as usize }; - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - match __simulator.adaptive_predict_stream_info_with_context(254, __prediction_precedence, self.base.input(), __prediction_context) { - Ok(__prediction) => __prediction, - Err(antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { .. }) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: true, has_semantic_context: false, diagnostic: None }, - Err(_) => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - let __prediction = if __prediction.alt == 1 { - let __semantic_la = self.base.la(1); - if __semantic_la == 108 || __semantic_la == 152 { - __prediction - } else { - antlr4_runtime::ParserAtnPrediction { alt: 2, ..__prediction } - } - } else { - __prediction - }; - self.base.record_generated_prediction_diagnostic(atn(), 2099, &__prediction); - match __prediction.alt { - 1 => { - self.base.parse_listener_exit_rule(114); - if let Some(__depth_error) = self.base.rule_depth_cap_violation() { - return Err(__depth_error); - } - self.base.push_new_recursion_context_with_previous(228isize, 114, &mut __ctx); - if let Some(__listener_error) = self.base.parse_listener_enter_rule(114) { - return Err(__listener_error); - } - if !self.base.precpred(12) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 12)")); - } - self.base.match_set_into(&[(108, 108), (152, 152)], 2096, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2096isize, self.dispatch_generated_rule(114, 13, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => break, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_115(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 230isize, 115, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2102isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2102isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_116(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 232isize, 116, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2104isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2105isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_117(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 234isize, 117, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107 | 110 | 112 | 117 | 119 | 141 | 146 | 151 | 153 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2110, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2110) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(255, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(255, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2110, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2107isize, self.dispatch_generated_rule(118, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2108isize, self.dispatch_generated_rule(119, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2109isize, self.dispatch_generated_rule(120, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_118(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 236isize, 118, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(173, 2113, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_119(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 238isize, 119, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 2123, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2123, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107 | 110 | 112 | 117 | 119 | 141 | 146 | 151 | 153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2123, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2115isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2120 = false; - loop { - self.base.sync_into(atn(), 2120, &mut __ctx, __loop_iter_2120, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2120, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2120 = true; - self.base.match_token_into(163, 2117, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2117isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 2126, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_120(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 240isize, 120, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_set_into(atn().token_set(11).expect("generated parser token-set index"), 2128, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_121(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 242isize, 121, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(173, 2130, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_122(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 244isize, 122, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(202, 2143, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2143, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2143) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(260, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(260, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2143, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2132isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2137 = false; - loop { - self.base.sync_into(atn(), 2137, &mut __ctx, __loop_iter_2137, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2137) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(258, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(258, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2137, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2137 = true; - self.base.match_token_into(163, 2134, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2134isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2141, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2141, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(163, 2142, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(203, 2147, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2147, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2147) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(261, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(261, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2147, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2146isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_123(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 246isize, 123, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 2150, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2150isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(201, 2152, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_124(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 248isize, 124, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2154, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2154) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(262, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(262, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2154, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2153isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2157, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2157) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(263, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(263, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2157, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2156isize, self.dispatch_generated_rule(125, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2160, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2160) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(264, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(264, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2160, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2159isize, self.dispatch_generated_rule(129, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2163, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2163) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(265, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(265, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2163, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2162isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_125(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 250isize, 125, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 2174, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2174, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2174) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(267, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(267, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2174, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2166isize, self.dispatch_generated_rule(126, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2171 = false; - loop { - self.base.sync_into(atn(), 2171, &mut __ctx, __loop_iter_2171, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2171, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2171 = true; - self.base.match_token_into(163, 2168, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2168isize, self.dispatch_generated_rule(126, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 2177, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_126(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 252isize, 126, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2179, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2179) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(268, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(268, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2179, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2178isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2181isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_127(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 254isize, 127, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5..=8 | 13..=14 | 16 | 18 | 21 | 23..=24 | 26..=29 | 35..=36 | 39 | 41 | 43 | 45 | 49 | 51..=53 | 56..=58 | 65 | 67 | 69..=70 | 72..=75 | 81..=83 | 85 | 95..=96 | 98..=101 | 111 | 113 | 116 | 125 | 127 | 130 | 156 | 160..=162 | 164..=165 | 172 | 175 | 178..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2185, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2185) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(269, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(269, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2185, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2183isize, self.dispatch_generated_rule(128, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2184isize, self.dispatch_generated_rule(15, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_128(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 256isize, 128, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2187isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2187isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(199, 2189, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_129(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 258isize, 129, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(197, 2202, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2202, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2202) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(272, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(272, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2202, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2191isize, self.dispatch_generated_rule(126, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2196 = false; - loop { - self.base.sync_into(atn(), 2196, &mut __ctx, __loop_iter_2196, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2196) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(270, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(270, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2196, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2196 = true; - self.base.match_token_into(163, 2193, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2193isize, self.dispatch_generated_rule(126, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2200, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2200, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(163, 2201, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(198, 2205, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_130(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 260isize, 130, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 120 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 168 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 136 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 137 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 170 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 139 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2218, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 120 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 168 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 136 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 137 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 170 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 139 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2218, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(120, 2207, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2207isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2207isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - self.base.match_token_into(168, 2209, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2209isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2209isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 3 => { - self.base.match_token_into(136, 2211, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2211isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2211isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 4 => { - self.base.match_token_into(137, 2213, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2213isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2213isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 5 => { - self.base.match_token_into(170, 2215, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2215isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2215isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 6 => { - self.base.match_token_into(139, 2217, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2217isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2217isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_131(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 262isize, 131, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(130, 2222, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2222, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2222) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(274, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(274, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2222, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2221isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_132(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 264isize, 132, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2224isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_133(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 266isize, 133, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(114, 2227, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2227isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_134(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 268isize, 134, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(119, 2230, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2230isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_135(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 270isize, 135, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(102, 2233, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2233isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2233isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_136(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 272isize, 136, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(84, 2236, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2236isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2236isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(199, 2238, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_137(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 274isize, 137, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(29, 2240, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(199, 2241, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_138(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 276isize, 138, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2245 = false; - loop { - self.base.sync_into(atn(), 2245, &mut __ctx, __loop_iter_2245, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2245, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2245 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2242isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(74, 2250, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2250, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2250, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2249isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2249isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 2253, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_139(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 278isize, 139, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2257 = false; - loop { - self.base.sync_into(atn(), 2257, &mut __ctx, __loop_iter_2257, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 118 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2257, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2257 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2254isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(118, 2261, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2261isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2265 = false; - loop { - self.base.sync_into(atn(), 2265, &mut __ctx, __loop_iter_2265, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=43 | 45..=62 | 64..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 2265, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2265 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2262isize, self.dispatch_generated_rule(140, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2269, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 30 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 3..=21 | 23..=29 | 31..=43 | 45..=62 | 64..=103 | 107..=114 | 116..=119 | 125 | 127 | 130 | 141 | 146..=148 | 151..=153 | 156 | 160..=162 | 164..=165 | 167 | 172..=173 | 175..=186 | 194..=198 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 2269, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2268isize, self.dispatch_generated_rule(143, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_140(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 280isize, 140, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(63, 2273, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2273, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 102 | 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2273, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2272isize, self.dispatch_generated_rule(141, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2276, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 102 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2276, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2275isize, self.dispatch_generated_rule(142, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2278isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_141(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 282isize, 141, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 2281, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2281isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2283, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 25 | 32..=34 | 37..=38 | 40 | 42 | 46 | 48 | 50 | 59..=61 | 68 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2283, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2282isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 2286, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_142(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 284isize, 142, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(102, 2288, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2289, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2289isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2289isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2291, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_143(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 286isize, 143, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(30, 2293, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2293isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_144(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 288isize, 144, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2298 = false; - loop { - self.base.sync_into(atn(), 2298, &mut __ctx, __loop_iter_2298, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 57 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2298, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2298 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2295isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(57, 2302, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2302isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_145(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 290isize, 145, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2307 = false; - loop { - self.base.sync_into(atn(), 2307, &mut __ctx, __loop_iter_2307, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 61 | 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2307, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2307 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2304isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2311, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 61 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2311, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(61, 2312, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(77, 2314, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2317, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5..=8 | 13..=14 | 16 | 21 | 23..=24 | 26..=27 | 29 | 35..=36 | 41 | 45 | 49 | 51..=52 | 56..=57 | 65 | 67 | 69 | 74 | 81 | 96 | 98..=99 | 113 | 125 | 127 | 130 | 156 | 160..=162 | 164..=165 | 172 | 175 | 178..=186 | 194..=197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2317, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2317) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(286, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(286, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2317, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2315isize, self.dispatch_generated_rule(20, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2316isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2316isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(201, 2320, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2320isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_146(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 292isize, 146, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2325 = false; - loop { - self.base.sync_into(atn(), 2325, &mut __ctx, __loop_iter_2325, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2325, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2325 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2322isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(79, 2329, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2330, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2330isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2330isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2332, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2332isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_147(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 294isize, 147, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2337 = false; - loop { - self.base.sync_into(atn(), 2337, &mut __ctx, __loop_iter_2337, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2337, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2337 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2334isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(80, 2341, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_set_into(&[(47, 47), (62, 62)], 2343, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2343, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2343, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2342isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2342isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(167, 2346, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_148_adaptive_probe_dispatch(&mut self, precedence: i32, allow_fallback: bool) -> Result { - let __result = self.dispatch_generated_rule(148, precedence, allow_fallback); - if __result.is_ok() && self.adaptive_atn.retry_slot.is_none() { - if let Some(__adaptive_after) = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - { - if self.adaptive_atn.preference_depths[0] != 0 - && !self.adaptive_atn.preferred_rules[0] - && self.base.number_of_syntax_errors() == self.adaptive_atn.syntax_error_starts[0] - && antlr4_runtime::ParserAtnSimulator::adaptive_prediction_delta_is_decisive(self.adaptive_atn.preference_starts[0], __adaptive_after) - { - self.adaptive_atn.preferred_rules[0] = true; - self.adaptive_atn.retry_slot = Some(0); - return Err(GeneratedRuleError::AdaptiveRetry); - } - } - } - __result - } - - #[allow(dead_code)] - fn parse_generated_rule_148_adaptive_dispatch(&mut self, precedence: i32, allow_fallback: bool, invoking_state: Option) -> Result { - if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() { - return self.dispatch_generated_rule(148, precedence, allow_fallback); - } - let __adaptive_outermost = self.adaptive_atn.preference_depths[1] == 0; - let __adaptive_rule_start = antlr4_runtime::IntStream::index(self.base.input()); - let __adaptive_parser_state = self.base.state(); - let __adaptive_diagnostic_marker = self.base.generated_diagnostics_checkpoint(); - if __adaptive_outermost { - self.adaptive_atn.preference_starts[1] = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - .unwrap_or((0, 0)); - self.adaptive_atn.syntax_error_starts[1] = self.base.number_of_syntax_errors(); - } - self.adaptive_atn.preference_depths[1] += 1; - let mut __result = self.dispatch_generated_rule(148, precedence, allow_fallback); - self.adaptive_atn.preference_depths[1] -= 1; - if !self.adaptive_atn.preferred_rules[1] { - if let Some(__adaptive_after) = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - { - let __adaptive_expensive = __result.is_ok() - && self.base.number_of_syntax_errors() == self.adaptive_atn.syntax_error_starts[1] - && antlr4_runtime::ParserAtnSimulator::adaptive_prediction_delta_is_expensive(self.adaptive_atn.preference_starts[1], __adaptive_after); - self.adaptive_atn.preferred_rules[1] = __adaptive_expensive; - if __adaptive_expensive { - self.adaptive_atn.retry_slot = Some(1); - __result = Err(GeneratedRuleError::AdaptiveRetry); - } - } - } - if __adaptive_outermost - && self.adaptive_atn.retry_slot == Some(1) - && matches!(&__result, Err(GeneratedRuleError::AdaptiveRetry)) - { - self.adaptive_atn.retry_slot = None; - self.base.restore_generated_diagnostics(__adaptive_diagnostic_marker); - antlr4_runtime::IntStream::seek(self.base.input(), __adaptive_rule_start); - self.base.set_state(__adaptive_parser_state); - if let Some(invoking_state) = invoking_state { - self.base.push_invoking_state(invoking_state); - } - return self.parse_rule_precedence_from_generated(148, precedence).map_err(GeneratedRuleError::Interpreted); - } - __result - } - - #[allow(dead_code)] - fn parse_generated_rule_148(&mut self, allow_fallback: bool) -> Result { - self.parse_generated_rule_148_precedence(0, allow_fallback) - } - - #[allow(dead_code)] - fn parse_generated_rule_148_precedence(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - antlr4_runtime::__antlr4_rust_generated_rule! { - recursive self, 296isize, 148, __precedence, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=24 | 26 | 35..=36 | 41 | 45 | 49 | 52 | 65 | 69 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 | 27 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 197 => antlr4_runtime::ParserAtnPrediction { alt: 15, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 | 98 => antlr4_runtime::ParserAtnPrediction { alt: 16, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 194..=196 => antlr4_runtime::ParserAtnPrediction { alt: 17, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 6 | 67 | 96 | 99 | 178..=186 => antlr4_runtime::ParserAtnPrediction { alt: 18, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 19, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 165 => antlr4_runtime::ParserAtnPrediction { alt: 20, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 | 127 | 156 | 160..=162 | 164 | 172 | 175 => antlr4_runtime::ParserAtnPrediction { alt: 22, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 130 => antlr4_runtime::ParserAtnPrediction { alt: 24, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 26, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 => antlr4_runtime::ParserAtnPrediction { alt: 27, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 51 => antlr4_runtime::ParserAtnPrediction { alt: 28, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 30, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 56 => antlr4_runtime::ParserAtnPrediction { alt: 33, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2386, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2386) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(291, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(291, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2386, &__prediction); - match __prediction.alt { - 1 => { - let action = self.base.parser_action_at_current_indexed(2347, 148, 3, __rule_start, __consumed_eof); - let _ = action; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2348isize, self.dispatch_generated_rule(149, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2349isize, self.dispatch_generated_rule(154, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2350isize, self.dispatch_generated_rule(156, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2351isize, self.dispatch_generated_rule(158, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2352isize, self.dispatch_generated_rule(159, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2353isize, self.dispatch_generated_rule(162, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2354isize, self.dispatch_generated_rule(163, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2355isize, self.dispatch_generated_rule(164, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2356isize, self.dispatch_generated_rule(170, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 10 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2357isize, self.dispatch_generated_rule(171, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2358isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 12 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2359isize, self.dispatch_generated_rule(173, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 13 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2360isize, self.dispatch_generated_rule(174, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 14 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2361isize, self.dispatch_generated_rule(175, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 15 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2362isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 16 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2363isize, self.dispatch_generated_rule(176, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 17 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2364isize, self.dispatch_generated_rule(179, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 18 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2365isize, self.dispatch_generated_rule(188, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 19 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2366isize, self.dispatch_generated_rule(192, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 20 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2367isize, self.dispatch_generated_rule(193, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 21 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2368isize, self.dispatch_generated_rule(194, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 22 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2369isize, self.dispatch_generated_rule(195, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 23 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2370isize, self.dispatch_generated_rule(196, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 24 => { - self.base.match_token_into(130, 2373, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2373, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2373) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(290, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(290, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2373, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2372isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2372isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 25 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2375isize, self.dispatch_generated_rule(210, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 26 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2376isize, self.dispatch_generated_rule(211, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 27 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2377isize, self.dispatch_generated_rule(212, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 28 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2378isize, self.dispatch_generated_rule(213, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 29 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2379isize, self.dispatch_generated_rule(214, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 30 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2380isize, self.dispatch_generated_rule(216, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 31 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2381isize, self.dispatch_generated_rule(217, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 32 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2382isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 33 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2383isize, self.dispatch_generated_rule(218, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 34 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2384isize, self.dispatch_generated_rule(219, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 35 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2385isize, self.dispatch_generated_rule(169, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - loop { - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.left_recursive_loop_enter_prediction(atn(), 2479, __precedence) { - Some(true) => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: true, diagnostic: None }, - Some(false) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - None => { - let __prediction_precedence = if __precedence <= 0 { 0 } else { __precedence as usize }; - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - match __simulator.adaptive_predict_stream_info_with_context(299, __prediction_precedence, self.base.input(), __prediction_context) { - Ok(__prediction) => __prediction, - Err(antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { .. }) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: true, has_semantic_context: false, diagnostic: None }, - Err(_) => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2479, &__prediction); - match __prediction.alt { - 1 => { - self.base.parse_listener_exit_rule(148); - if let Some(__depth_error) = self.base.rule_depth_cap_violation() { - return Err(__depth_error); - } - self.base.push_new_recursion_context_with_previous(296isize, 148, &mut __ctx); - if let Some(__listener_error) = self.base.parse_listener_enter_rule(148) { - return Err(__listener_error); - } - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(298, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - if !self.base.precpred(44) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 44)")); - } - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(292, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - self.base.match_token_into(169, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(126, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(128, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(124, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(131, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - self.base.match_token_into(121, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - self.base.match_token_into(123, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 8 => { - self.base.match_token_into(144, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 9 => { - self.base.match_token_into(154, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - self.base.match_token_into(105, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2399isize, self.dispatch_generated_rule(240, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 12 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2400isize, self.dispatch_generated_rule(241, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 13 => { - self.base.match_token_into(106, 2403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2404isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 45) } else { self.parse_generated_rule_148_adaptive_dispatch(45, false, Some(2404isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if !self.base.precpred(41) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 41)")); - } - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(293, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - self.base.match_token_into(162, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(164, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(161, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(166, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(159, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - self.base.match_token_into(135, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2412isize, self.dispatch_generated_rule(238, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2413isize, self.dispatch_generated_rule(239, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - self.base.match_token_into(155, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - self.base.match_token_into(122, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 11 => { - self.base.match_token_into(174, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 12 => { - self.base.match_token_into(160, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 13 => { - self.base.match_token_into(172, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 14 => { - self.base.match_token_into(137, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 15 => { - self.base.match_token_into(120, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 16 => { - self.base.match_token_into(168, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 17 => { - self.base.match_token_into(136, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 18 => { - self.base.match_token_into(170, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 19 => { - self.base.match_token_into(139, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 20 => { - self.base.match_token_into(150, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 21 => { - self.base.match_token_into(145, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 22 => { - self.base.match_token_into(140, 2429, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2430isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 42) } else { self.parse_generated_rule_148_adaptive_dispatch(42, false, Some(2430isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 3 => { - if !self.base.precpred(37) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 37)")); - } - self.base.match_token_into(171, 2433, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2433isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 38) } else { self.parse_generated_rule_148_adaptive_dispatch(38, false, Some(2433isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 4 => { - if !self.base.precpred(36) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 36)")); - } - self.base.match_token_into(171, 2436, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2436isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2436isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(199, 2438, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2438isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 37) } else { self.parse_generated_rule_148_adaptive_dispatch(37, false, Some(2438isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 5 => { - if !self.base.precpred(34) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 34)")); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2441isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - if !self.base.precpred(25) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 25)")); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2443isize, self.dispatch_generated_rule(31, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - if !self.base.precpred(24) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 24)")); - } - self.base.match_token_into(150, 2446, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2446isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - if !self.base.precpred(21) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 21)")); - } - self.base.match_set_into(&[(129, 129), (165, 165)], 2449, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2449isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - if !self.base.precpred(18) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 18)")); - } - self.base.match_token_set_into(atn().token_set(14).expect("generated parser token-set index"), 2478, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - if !self.base.precpred(15) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 15)")); - } - self.base.match_token_into(130, 2455, atn(), &mut __ctx, &mut __consumed_eof)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(294, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2454isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2454isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 11 => { - if !self.base.precpred(8) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 8)")); - } - self.base.match_token_into(55, 2459, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(197, 2471, atn(), &mut __ctx, &mut __consumed_eof)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(297, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2460isize, self.dispatch_generated_rule(215, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2465 = false; - loop { - self.base.sync_into(atn(), 2465, &mut __ctx, __loop_iter_2465, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(295, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - self.base.record_generated_prediction_diagnostic(atn(), 2465, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2465 = true; - self.base.match_token_into(163, 2462, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2462isize, self.dispatch_generated_rule(215, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(296, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - self.base.match_token_into(163, 2470, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(198, 2478, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 12 => { - if !self.base.precpred(2) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 2)")); - } - self.base.match_token_into(103, 2476, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2476isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => break, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_149(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 298isize, 149, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9..=10 | 15 | 28 | 32..=33 | 37 | 39..=40 | 42..=43 | 46 | 50 | 53 | 58..=59 | 61 | 68 | 70..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 89 | 91..=93 | 95 | 100..=103 | 107..=108 | 110..=112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2484, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2484) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(300, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(300, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2484, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2482isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2483isize, self.dispatch_generated_rule(151, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_150(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 300isize, 150, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2489 = false; - loop { - self.base.sync_into(atn(), 2489, &mut __ctx, __loop_iter_2489, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2489, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2489 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2486isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(18, 2494, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2494, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 197 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2494, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2493isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2496isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2498, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2498) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(303, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(303, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2498, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2497isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2497isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_151(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 302isize, 151, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 18 | 28 | 39 | 43 | 53 | 58 | 70 | 72..=73 | 75 | 82..=83 | 85 | 95 | 100..=101 | 111 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2502, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2502) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(304, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(304, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2502, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2500isize, self.dispatch_generated_rule(152, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2501isize, self.dispatch_generated_rule(153, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_152(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 304isize, 152, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2507 = false; - loop { - self.base.sync_into(atn(), 2507, &mut __ctx, __loop_iter_2507, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 18 | 21 | 23..=26 | 28 | 32..=43 | 45..=46 | 48..=50 | 52..=53 | 57..=61 | 65 | 68..=73 | 75..=76 | 78 | 80 | 82..=83 | 85 | 88..=89 | 91..=93 | 95 | 97 | 100..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2507, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2507 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2504isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_2513 = false; - loop { - self.base.sync_into(atn(), 2513, &mut __ctx, __loop_iter_2513, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2513) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(306, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(306, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2513, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2513 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2510isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2517, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2517) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(307, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(307, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2517, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2516isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2519isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(138, 2523, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=196 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2523, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2523) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(308, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(308, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2523, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2521isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2522isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2522isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_153(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 306isize, 153, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2528 = false; - loop { - self.base.sync_into(atn(), 2528, &mut __ctx, __loop_iter_2528, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 13 | 15..=16 | 21 | 23..=26 | 32..=38 | 40..=42 | 45..=46 | 48..=50 | 52 | 57 | 59..=61 | 65 | 68..=69 | 71 | 76 | 78 | 80 | 88..=89 | 91..=93 | 97 | 102..=103 | 107..=108 | 110 | 112..=114 | 116..=117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2528, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2528 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2525isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_2534 = false; - loop { - self.base.sync_into(atn(), 2534, &mut __ctx, __loop_iter_2534, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2534) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(310, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(310, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2534, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2534 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2531isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2537isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(138, 2541, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=196 | 200 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2541, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2541) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(311, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(311, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2541, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2539isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2540isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2540isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_154(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 308isize, 154, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(113, 2544, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(197, 2556, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2556, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2556, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2545isize, self.dispatch_generated_rule(155, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2550 = false; - loop { - self.base.sync_into(atn(), 2550, &mut __ctx, __loop_iter_2550, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2550) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(312, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(312, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2550, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2550 = true; - self.base.match_token_into(163, 2547, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2547isize, self.dispatch_generated_rule(155, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2554, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2554, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(163, 2555, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(198, 2559, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_155(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 310isize, 155, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2561, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2561) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(315, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(315, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2561, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2560isize, self.dispatch_generated_rule(3, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2563isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2563isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_156(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 312isize, 156, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(113, 2566, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2566isize, self.dispatch_generated_rule(77, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2568, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2568) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(316, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(316, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2568, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2567isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_157(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 314isize, 157, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(197, 2582, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2582, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2582, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2571isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2571isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - let mut __loop_iter_2576 = false; - loop { - self.base.sync_into(atn(), 2576, &mut __ctx, __loop_iter_2576, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2576) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(317, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(317, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2576, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2576 = true; - self.base.match_token_into(163, 2573, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2573isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2573isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2580, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2580, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(163, 2581, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(198, 2585, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_158(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 316isize, 158, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(61, 2587, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2587isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2587isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_159(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 318isize, 159, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2591, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2591) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(320, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(320, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2591, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2589isize, self.dispatch_generated_rule(160, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2590isize, self.dispatch_generated_rule(161, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_160(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 320isize, 160, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(113, 2594, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2594isize, self.dispatch_generated_rule(31, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2596, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2596) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(321, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(321, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2596, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2595isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_161(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 322isize, 161, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(113, 2599, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2599isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2601, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2601) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(322, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(322, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2601, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2600isize, self.dispatch_generated_rule(31, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2604, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2604) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(323, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(323, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2604, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2603isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_162(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 324isize, 162, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 2607, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2607isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(201, 2609, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2609isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2609isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_163(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 326isize, 163, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2621, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2621, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(27, 2612, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2613, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2613isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2613isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2615, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(14, 2617, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2618, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2618isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2618isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2620, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_164(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 328isize, 164, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(202, 2635, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2635, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=103 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 130 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2635, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2624isize, self.dispatch_generated_rule(165, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2629 = false; - loop { - self.base.sync_into(atn(), 2629, &mut __ctx, __loop_iter_2629, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2629) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(325, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(325, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2629, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2629 = true; - self.base.match_token_into(163, 2626, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2626isize, self.dispatch_generated_rule(165, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2633, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2633, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(163, 2634, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(203, 2638, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_165(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 330isize, 165, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3..=10 | 13..=16 | 18 | 21 | 23..=29 | 32..=43 | 45..=46 | 48..=53 | 56..=61 | 65 | 67..=76 | 78 | 80..=83 | 85 | 88..=89 | 91..=93 | 95..=102 | 107..=108 | 110..=114 | 116..=117 | 119 | 125 | 127 | 141 | 146 | 151..=153 | 156 | 160..=162 | 164..=165 | 172..=173 | 175..=186 | 194..=197 | 200 | 202 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2642, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2642) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(328, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(328, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2642, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2639isize, self.dispatch_generated_rule(166, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2640isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2641isize, self.dispatch_generated_rule(168, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_166(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 332isize, 166, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2644isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2644isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_167(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 334isize, 167, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(130, 2647, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2647isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2647isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_168(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 336isize, 168, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(103, 2650, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2650isize, self.dispatch_generated_rule(31, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_169(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 338isize, 169, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2652isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2653isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_170(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 340isize, 170, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(29, 2656, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2657, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2657isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(201, 2659, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_171(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 342isize, 171, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2660isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_172(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 344isize, 172, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(68, 2663, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_173(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 346isize, 173, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(113, 2665, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(202, 2669, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2669 = false; - loop { - self.base.sync_into(atn(), 2669, &mut __ctx, __loop_iter_2669, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 203 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2669, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2669 = true; - self.base.match_token_into(163, 2668, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(203, 2673, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2673isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_174(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 348isize, 174, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2675isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_175(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 350isize, 175, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(5, 2678, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(202, 2679, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(203, 2680, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2680isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_176(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 352isize, 176, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 98 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2684, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 98 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2684, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2682isize, self.dispatch_generated_rule(177, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2683isize, self.dispatch_generated_rule(178, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_177(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 354isize, 177, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 2687, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_178(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 356isize, 178, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(98, 2689, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_179(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 358isize, 179, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 194 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 195 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2724, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2724) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(335, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(335, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2724, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(194, 2694, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2694 = false; - loop { - self.base.sync_into(atn(), 2694, &mut __ctx, __loop_iter_2694, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 157 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2694, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2694 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2691isize, self.dispatch_generated_rule(180, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(157, 2725, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(195, 2702, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2702 = false; - loop { - self.base.sync_into(atn(), 2702, &mut __ctx, __loop_iter_2702, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 157 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2702, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2702 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2699isize, self.dispatch_generated_rule(180, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(157, 2725, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2706isize, self.dispatch_generated_rule(185, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2710 = false; - loop { - self.base.sync_into(atn(), 2710, &mut __ctx, __loop_iter_2710, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 104 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2710, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2710 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2707isize, self.dispatch_generated_rule(180, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2713isize, self.dispatch_generated_rule(186, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2715isize, self.dispatch_generated_rule(187, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2719 = false; - loop { - self.base.sync_into(atn(), 2719, &mut __ctx, __loop_iter_2719, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 197 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 104 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2719, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2719 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2716isize, self.dispatch_generated_rule(180, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2722isize, self.dispatch_generated_rule(186, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_180(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 360isize, 180, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 197 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2728, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 1 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 197 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2728, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2726isize, self.dispatch_generated_rule(181, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2727isize, self.dispatch_generated_rule(182, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_181(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 362isize, 181, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2730isize, self.dispatch_generated_rule(234, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_182(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 364isize, 182, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(197, 2733, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2733isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2733isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.sync_into(atn(), 2735, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198..=199 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2735, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2734isize, self.dispatch_generated_rule(183, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2738, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 199 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 198 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2738, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2737isize, self.dispatch_generated_rule(184, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(198, 2741, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_183(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 366isize, 183, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(163, 2743, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2743isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2743isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_184(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 368isize, 184, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(199, 2746, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2746isize, self.dispatch_generated_rule(234, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_185(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 370isize, 185, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(196, 2749, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_186(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 372isize, 186, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(104, 2754, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2754 = false; - loop { - self.base.sync_into(atn(), 2754, &mut __ctx, __loop_iter_2754, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2754) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(339, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(339, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2754, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2754 = true; - self.base.match_token_into(157, 2753, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_187(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 374isize, 187, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(196, 2758, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_188(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 376isize, 188, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 29 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 67 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 96 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 99 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 6 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 182 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 178..=181 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2772, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2772) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(340, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(340, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2772, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(29, 2773, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(67, 2773, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(96, 2773, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(99, 2773, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(6, 2773, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2764isize, self.dispatch_generated_rule(228, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2765isize, self.dispatch_generated_rule(235, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2766isize, self.dispatch_generated_rule(223, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2767isize, self.dispatch_generated_rule(236, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 10 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2768isize, self.dispatch_generated_rule(229, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2769isize, self.dispatch_generated_rule(189, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 12 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2770isize, self.dispatch_generated_rule(190, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 13 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2771isize, self.dispatch_generated_rule(191, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_189(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 378isize, 189, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2774isize, self.dispatch_generated_rule(235, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_set_into(&[(141, 141), (153, 153)], 2776, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_190(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 380isize, 190, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2777isize, self.dispatch_generated_rule(236, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_set_into(&[(141, 141), (153, 153)], 2779, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_191(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 382isize, 191, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2780isize, self.dispatch_generated_rule(229, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_set_into(&[(141, 141), (153, 153)], 2782, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_192(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 384isize, 192, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(7, 2784, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2785, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2785isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2785isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2787, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_193(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 386isize, 193, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(165, 2789, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2789isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_194(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 388isize, 194, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 2792, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2792isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2792isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2794, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_195(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 390isize, 195, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 156 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 160 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 161 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 162 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 164 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 127 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 172 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 175 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2813, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 156 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 160 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 161 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 162 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 164 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 127 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 172 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 175 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2813, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(156, 2796, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2796isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2796isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - self.base.match_token_into(160, 2798, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2798isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2798isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 3 => { - self.base.match_token_into(161, 2800, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2800isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2800isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 4 => { - self.base.match_token_into(162, 2802, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2802isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2802isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 5 => { - self.base.match_token_into(125, 2804, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2804isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2804isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 6 => { - self.base.match_token_into(164, 2806, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2806isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2806isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 7 => { - self.base.match_token_into(127, 2808, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2808isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2808isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 8 => { - self.base.match_token_into(172, 2810, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2810isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2810isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 9 => { - self.base.match_token_into(175, 2812, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2812isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2812isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_196(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 392isize, 196, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2815isize, self.dispatch_generated_rule(197, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2816isize, self.dispatch_generated_rule(198, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_197(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 394isize, 197, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(89, 2820, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2820, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2820) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(342, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(342, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2820, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2819isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2822isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(149, 2824, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2824isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2824isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_198(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 396isize, 198, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2829 = false; - loop { - self.base.sync_into(atn(), 2829, &mut __ctx, __loop_iter_2829, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 33 | 78 | 89 | 93 | 112 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 50 | 71 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2829, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2829 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2826isize, self.dispatch_generated_rule(199, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2832isize, self.dispatch_generated_rule(206, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2834, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2834) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(344, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(344, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2834, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2833isize, self.dispatch_generated_rule(209, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_199(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 398isize, 199, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 89 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 93 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 112 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2841, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 89 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 93 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 112 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2841, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2836isize, self.dispatch_generated_rule(197, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2837isize, self.dispatch_generated_rule(200, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2838isize, self.dispatch_generated_rule(202, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2839isize, self.dispatch_generated_rule(203, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2840isize, self.dispatch_generated_rule(205, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_200(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 400isize, 200, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(93, 2845, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2845, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2845) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(346, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(346, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2845, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2844isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2847isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(149, 2849, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2849isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2849isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(151, 2851, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2851isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2851isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(40, 2853, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2853isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2853isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.sync_into(atn(), 2855, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 92 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 | 50 | 71 | 78 | 89 | 93 | 112 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 2855, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2854isize, self.dispatch_generated_rule(201, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_201(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 402isize, 201, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(92, 2858, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2858isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_202(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 404isize, 202, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(112, 2861, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2861isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(169, 2863, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2863isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2863isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_203(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 406isize, 203, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(33, 2866, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2866isize, self.dispatch_generated_rule(204, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2871 = false; - loop { - self.base.sync_into(atn(), 2871, &mut __ctx, __loop_iter_2871, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 | 50 | 71 | 78 | 89 | 93 | 112 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 2871, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2871 = true; - self.base.match_token_into(163, 2868, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2868isize, self.dispatch_generated_rule(204, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_204(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 408isize, 204, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2874isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2874isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.sync_into(atn(), 2876, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 4 | 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 | 50 | 71 | 78 | 89 | 93 | 112 | 163 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 2876, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_set_into(&[(4, 4), (9, 9)], 2877, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_205(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 410isize, 205, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(78, 2879, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2879isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2879isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_206(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 412isize, 206, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 71 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 50 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2883, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 71 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 50 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2883, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2881isize, self.dispatch_generated_rule(207, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2882isize, self.dispatch_generated_rule(208, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_207(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 414isize, 207, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(71, 2886, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2886isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2886isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(146, 2888, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2888isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2888isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_208(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 416isize, 208, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(50, 2891, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2891isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2891isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_209(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 418isize, 209, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(92, 2894, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2894isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2895isize, self.dispatch_generated_rule(198, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_210(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 420isize, 210, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(116, 2898, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2898isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2898isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_211(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 422isize, 211, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(8, 2901, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2902, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2902isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2902isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2904, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_212(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 424isize, 212, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(3, 2906, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2907, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2907isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2907isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(163, 2909, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2909isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(201, 2911, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_213(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 426isize, 213, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(51, 2913, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2914, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2914isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(201, 2916, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_214(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 428isize, 214, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(5, 2918, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2918isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2920, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2920) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(351, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(351, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2920, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2919isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_215(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 430isize, 215, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2922isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2924, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 102 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 138 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2924, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2923isize, self.dispatch_generated_rule(135, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(138, 2927, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2927isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2927isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_216(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 432isize, 216, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(74, 2930, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2930isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2930isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_217(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 434isize, 217, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(200, 2933, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2933isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(163, 2935, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2935isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2938 = true; - loop { - self.base.sync_into(atn(), 2938, &mut __ctx, __loop_iter_2938, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 201 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2938, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2938 = true; - self.base.match_token_into(163, 2935, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2935isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(201, 2941, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_218(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 436isize, 218, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(56, 2943, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2944, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2944isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(201, 2946, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_219(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 438isize, 219, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(57, 2948, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(200, 2949, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2949isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(148, 0) } else { self.parse_generated_rule_148_adaptive_dispatch(0, false, Some(2949isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(201, 2951, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_220(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 440isize, 220, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 182 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 | 9..=10 | 15 | 32..=33 | 37 | 40 | 42 | 46 | 50 | 59 | 61 | 68 | 71 | 76 | 78 | 80 | 89 | 91..=93 | 102..=103 | 107..=108 | 110 | 112 | 114 | 117 | 119 | 141 | 146 | 151..=153 | 173 | 176..=177 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5..=8 | 11..=14 | 16..=24 | 26..=31 | 35..=36 | 39 | 41 | 43..=45 | 47 | 49 | 51..=58 | 62..=67 | 69..=70 | 72..=75 | 77 | 79 | 81..=87 | 90 | 94..=96 | 98..=101 | 109 | 111 | 113 | 115..=116 | 118 | 147..=149 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 178..=181 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 105..=106 | 120..=128 | 131 | 135..=137 | 139..=140 | 144 | 154..=156 | 159..=162 | 164 | 166 | 168..=170 | 172 | 174..=175 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 129..=130 | 132..=134 | 138 | 142..=143 | 157..=158 | 163 | 165 | 167 | 171 | 197..=203 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 183..=184 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2959, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2959) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(354, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(354, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2959, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2952isize, self.dispatch_generated_rule(228, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2953isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2954isize, self.dispatch_generated_rule(222, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2955isize, self.dispatch_generated_rule(223, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2956isize, self.dispatch_generated_rule(232, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2957isize, self.dispatch_generated_rule(233, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2958isize, self.dispatch_generated_rule(229, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_221(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 442isize, 221, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_set_into(atn().token_set(17).expect("generated parser token-set index"), 2962, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_222(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 444isize, 222, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 145 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 83 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 84 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 64 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 => antlr4_runtime::ParserAtnPrediction { alt: 11, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 12, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 13, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 => antlr4_runtime::ParserAtnPrediction { alt: 14, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 147 => antlr4_runtime::ParserAtnPrediction { alt: 15, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 39 => antlr4_runtime::ParserAtnPrediction { alt: 16, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 86 => antlr4_runtime::ParserAtnPrediction { alt: 17, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 87 => antlr4_runtime::ParserAtnPrediction { alt: 18, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 66 => antlr4_runtime::ParserAtnPrediction { alt: 19, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19 => antlr4_runtime::ParserAtnPrediction { alt: 20, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 67 => antlr4_runtime::ParserAtnPrediction { alt: 21, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 30 => antlr4_runtime::ParserAtnPrediction { alt: 22, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 70 => antlr4_runtime::ParserAtnPrediction { alt: 23, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109 => antlr4_runtime::ParserAtnPrediction { alt: 24, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 => antlr4_runtime::ParserAtnPrediction { alt: 25, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 26, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 148 => antlr4_runtime::ParserAtnPrediction { alt: 27, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 20 => antlr4_runtime::ParserAtnPrediction { alt: 28, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 149 => antlr4_runtime::ParserAtnPrediction { alt: 29, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 111 => antlr4_runtime::ParserAtnPrediction { alt: 30, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 31, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 150 => antlr4_runtime::ParserAtnPrediction { alt: 32, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 => antlr4_runtime::ParserAtnPrediction { alt: 33, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 95 => antlr4_runtime::ParserAtnPrediction { alt: 34, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 35, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 96 => antlr4_runtime::ParserAtnPrediction { alt: 36, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 43 => antlr4_runtime::ParserAtnPrediction { alt: 37, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 22 => antlr4_runtime::ParserAtnPrediction { alt: 38, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 115 => antlr4_runtime::ParserAtnPrediction { alt: 39, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 44 => antlr4_runtime::ParserAtnPrediction { alt: 40, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 41, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 72 => antlr4_runtime::ParserAtnPrediction { alt: 42, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 73 => antlr4_runtime::ParserAtnPrediction { alt: 43, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 51 => antlr4_runtime::ParserAtnPrediction { alt: 44, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 => antlr4_runtime::ParserAtnPrediction { alt: 45, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 46, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 54 => antlr4_runtime::ParserAtnPrediction { alt: 47, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 55 => antlr4_runtime::ParserAtnPrediction { alt: 48, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 98 => antlr4_runtime::ParserAtnPrediction { alt: 49, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 50, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 99 => antlr4_runtime::ParserAtnPrediction { alt: 51, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 118 => antlr4_runtime::ParserAtnPrediction { alt: 52, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 56 => antlr4_runtime::ParserAtnPrediction { alt: 53, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 100 => antlr4_runtime::ParserAtnPrediction { alt: 54, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75 => antlr4_runtime::ParserAtnPrediction { alt: 55, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 56, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 58 => antlr4_runtime::ParserAtnPrediction { alt: 57, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 58, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 101 => antlr4_runtime::ParserAtnPrediction { alt: 59, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 => antlr4_runtime::ParserAtnPrediction { alt: 60, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 6 => antlr4_runtime::ParserAtnPrediction { alt: 61, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 62, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 63, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 => antlr4_runtime::ParserAtnPrediction { alt: 64, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 65, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3028, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 145 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 83 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 84 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 64 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 => antlr4_runtime::ParserAtnPrediction { alt: 11, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 12, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 13, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 => antlr4_runtime::ParserAtnPrediction { alt: 14, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 147 => antlr4_runtime::ParserAtnPrediction { alt: 15, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 39 => antlr4_runtime::ParserAtnPrediction { alt: 16, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 86 => antlr4_runtime::ParserAtnPrediction { alt: 17, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 87 => antlr4_runtime::ParserAtnPrediction { alt: 18, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 66 => antlr4_runtime::ParserAtnPrediction { alt: 19, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19 => antlr4_runtime::ParserAtnPrediction { alt: 20, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 67 => antlr4_runtime::ParserAtnPrediction { alt: 21, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 30 => antlr4_runtime::ParserAtnPrediction { alt: 22, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 70 => antlr4_runtime::ParserAtnPrediction { alt: 23, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109 => antlr4_runtime::ParserAtnPrediction { alt: 24, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 => antlr4_runtime::ParserAtnPrediction { alt: 25, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 26, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 148 => antlr4_runtime::ParserAtnPrediction { alt: 27, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 20 => antlr4_runtime::ParserAtnPrediction { alt: 28, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 149 => antlr4_runtime::ParserAtnPrediction { alt: 29, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 111 => antlr4_runtime::ParserAtnPrediction { alt: 30, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 31, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 150 => antlr4_runtime::ParserAtnPrediction { alt: 32, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 => antlr4_runtime::ParserAtnPrediction { alt: 33, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 95 => antlr4_runtime::ParserAtnPrediction { alt: 34, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 35, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 96 => antlr4_runtime::ParserAtnPrediction { alt: 36, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 43 => antlr4_runtime::ParserAtnPrediction { alt: 37, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 22 => antlr4_runtime::ParserAtnPrediction { alt: 38, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 115 => antlr4_runtime::ParserAtnPrediction { alt: 39, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 44 => antlr4_runtime::ParserAtnPrediction { alt: 40, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 41, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 72 => antlr4_runtime::ParserAtnPrediction { alt: 42, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 73 => antlr4_runtime::ParserAtnPrediction { alt: 43, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 51 => antlr4_runtime::ParserAtnPrediction { alt: 44, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 => antlr4_runtime::ParserAtnPrediction { alt: 45, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 46, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 54 => antlr4_runtime::ParserAtnPrediction { alt: 47, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 55 => antlr4_runtime::ParserAtnPrediction { alt: 48, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 98 => antlr4_runtime::ParserAtnPrediction { alt: 49, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 50, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 99 => antlr4_runtime::ParserAtnPrediction { alt: 51, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 118 => antlr4_runtime::ParserAtnPrediction { alt: 52, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 56 => antlr4_runtime::ParserAtnPrediction { alt: 53, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 100 => antlr4_runtime::ParserAtnPrediction { alt: 54, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75 => antlr4_runtime::ParserAtnPrediction { alt: 55, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 56, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 58 => antlr4_runtime::ParserAtnPrediction { alt: 57, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 58, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 101 => antlr4_runtime::ParserAtnPrediction { alt: 59, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 => antlr4_runtime::ParserAtnPrediction { alt: 60, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 6 => antlr4_runtime::ParserAtnPrediction { alt: 61, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 62, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 63, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 => antlr4_runtime::ParserAtnPrediction { alt: 64, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 16 | 21 | 23..=26 | 34..=36 | 38 | 41 | 45 | 48..=49 | 52 | 57 | 60 | 65 | 69 | 88 | 97 | 113 | 116 => antlr4_runtime::ParserAtnPrediction { alt: 65, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3028, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(145, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(81, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(82, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(62, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(83, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - self.base.match_token_into(84, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - self.base.match_token_into(63, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 8 => { - self.base.match_token_into(85, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 9 => { - self.base.match_token_into(27, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - self.base.match_token_into(64, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 11 => { - self.base.match_token_into(17, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 12 => { - self.base.match_token_into(28, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 13 => { - self.base.match_token_into(29, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 14 => { - self.base.match_token_into(18, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 15 => { - self.base.match_token_into(147, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 16 => { - self.base.match_token_into(39, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 17 => { - self.base.match_token_into(86, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 18 => { - self.base.match_token_into(87, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 19 => { - self.base.match_token_into(66, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 20 => { - self.base.match_token_into(19, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 21 => { - self.base.match_token_into(67, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 22 => { - self.base.match_token_into(30, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 23 => { - self.base.match_token_into(70, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 24 => { - self.base.match_token_into(109, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 25 => { - self.base.match_token_into(31, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 26 => { - self.base.match_token_into(90, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 27 => { - self.base.match_token_into(148, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 28 => { - self.base.match_token_into(20, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 29 => { - self.base.match_token_into(149, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 30 => { - self.base.match_token_into(111, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 31 => { - self.base.match_token_into(11, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 32 => { - self.base.match_token_into(150, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 33 => { - self.base.match_token_into(94, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 34 => { - self.base.match_token_into(95, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 35 => { - self.base.match_token_into(12, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 36 => { - self.base.match_token_into(96, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 37 => { - self.base.match_token_into(43, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 38 => { - self.base.match_token_into(22, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 39 => { - self.base.match_token_into(115, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 40 => { - self.base.match_token_into(44, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 41 => { - self.base.match_token_into(47, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 42 => { - self.base.match_token_into(72, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 43 => { - self.base.match_token_into(73, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 44 => { - self.base.match_token_into(51, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 45 => { - self.base.match_token_into(5, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 46 => { - self.base.match_token_into(53, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 47 => { - self.base.match_token_into(54, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 48 => { - self.base.match_token_into(55, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 49 => { - self.base.match_token_into(98, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 50 => { - self.base.match_token_into(74, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 51 => { - self.base.match_token_into(99, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 52 => { - self.base.match_token_into(118, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 53 => { - self.base.match_token_into(56, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 54 => { - self.base.match_token_into(100, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 55 => { - self.base.match_token_into(75, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 56 => { - self.base.match_token_into(14, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 57 => { - self.base.match_token_into(58, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 58 => { - self.base.match_token_into(77, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 59 => { - self.base.match_token_into(101, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 60 => { - self.base.match_token_into(79, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 61 => { - self.base.match_token_into(6, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 62 => { - self.base.match_token_into(7, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 63 => { - self.base.match_token_into(8, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 64 => { - self.base.match_token_into(3, 3029, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 65 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3027isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_223(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 446isize, 223, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 178..=180 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 181 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3032, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 178..=180 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 181 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3032, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3030isize, self.dispatch_generated_rule(224, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3031isize, self.dispatch_generated_rule(227, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_224(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 448isize, 224, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 178 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 179 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 180 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3037, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 178 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 179 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 180 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3037, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3034isize, self.dispatch_generated_rule(225, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3035isize, self.dispatch_generated_rule(226, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - self.base.match_token_into(180, 3038, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_225(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 450isize, 225, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(178, 3040, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_226(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 452isize, 226, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(179, 3042, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_227(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 454isize, 227, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(181, 3044, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_228(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 456isize, 228, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(182, 3046, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_229(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 458isize, 229, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 183 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 184 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3049, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 183 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 184 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3049, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3047isize, self.dispatch_generated_rule(230, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3048isize, self.dispatch_generated_rule(231, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_230(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 460isize, 230, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(183, 3052, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_231(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 462isize, 231, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(184, 3054, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_232(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 464isize, 232, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 156 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 120 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 159 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 121 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 122 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 160 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 123 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 161 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 162 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 => antlr4_runtime::ParserAtnPrediction { alt: 11, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 126 => antlr4_runtime::ParserAtnPrediction { alt: 12, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 164 => antlr4_runtime::ParserAtnPrediction { alt: 13, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 127 => antlr4_runtime::ParserAtnPrediction { alt: 14, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 128 => antlr4_runtime::ParserAtnPrediction { alt: 15, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 166 => antlr4_runtime::ParserAtnPrediction { alt: 16, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131 => antlr4_runtime::ParserAtnPrediction { alt: 17, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 168 => antlr4_runtime::ParserAtnPrediction { alt: 18, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 135 => antlr4_runtime::ParserAtnPrediction { alt: 19, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 105 => antlr4_runtime::ParserAtnPrediction { alt: 20, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 136 => antlr4_runtime::ParserAtnPrediction { alt: 21, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 169 => antlr4_runtime::ParserAtnPrediction { alt: 22, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 137 => antlr4_runtime::ParserAtnPrediction { alt: 23, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 139 => antlr4_runtime::ParserAtnPrediction { alt: 25, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 140 => antlr4_runtime::ParserAtnPrediction { alt: 30, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 106 => antlr4_runtime::ParserAtnPrediction { alt: 31, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 145 => antlr4_runtime::ParserAtnPrediction { alt: 32, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 150 => antlr4_runtime::ParserAtnPrediction { alt: 33, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 172 => antlr4_runtime::ParserAtnPrediction { alt: 34, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 144 => antlr4_runtime::ParserAtnPrediction { alt: 35, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 174 => antlr4_runtime::ParserAtnPrediction { alt: 36, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 154 => antlr4_runtime::ParserAtnPrediction { alt: 37, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 155 => antlr4_runtime::ParserAtnPrediction { alt: 38, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 175 => antlr4_runtime::ParserAtnPrediction { alt: 39, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3094, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3094) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(359, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(359, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3094, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(156, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(120, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(159, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(121, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(122, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - self.base.match_token_into(160, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - self.base.match_token_into(123, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 8 => { - self.base.match_token_into(161, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 9 => { - self.base.match_token_into(124, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - self.base.match_token_into(162, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 11 => { - self.base.match_token_into(125, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 12 => { - self.base.match_token_into(126, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 13 => { - self.base.match_token_into(164, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 14 => { - self.base.match_token_into(127, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 15 => { - self.base.match_token_into(128, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 16 => { - self.base.match_token_into(166, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 17 => { - self.base.match_token_into(131, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 18 => { - self.base.match_token_into(168, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 19 => { - self.base.match_token_into(135, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 20 => { - self.base.match_token_into(105, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 21 => { - self.base.match_token_into(136, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 22 => { - self.base.match_token_into(169, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 23 => { - self.base.match_token_into(137, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 24 => { - self.base.match_token_into(170, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 25 => { - self.base.match_token_into(139, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 26 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3080isize, self.dispatch_generated_rule(238, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 27 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3081isize, self.dispatch_generated_rule(240, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 28 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3082isize, self.dispatch_generated_rule(239, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 29 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3083isize, self.dispatch_generated_rule(241, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 30 => { - self.base.match_token_into(140, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 31 => { - self.base.match_token_into(106, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 32 => { - self.base.match_token_into(145, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 33 => { - self.base.match_token_into(150, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 34 => { - self.base.match_token_into(172, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 35 => { - self.base.match_token_into(144, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 36 => { - self.base.match_token_into(174, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 37 => { - self.base.match_token_into(154, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 38 => { - self.base.match_token_into(155, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 39 => { - self.base.match_token_into(175, 3095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_233(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 466isize, 233, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_set_into(atn().token_set(18).expect("generated parser token-set index"), 3097, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_234(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 468isize, 234, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(1, 3099, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_235(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 470isize, 235, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(186, 3101, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_236(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 472isize, 236, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(185, 3103, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_237(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 474isize, 237, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(176, 3105, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_238(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 476isize, 238, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(170, 3107, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(170, 3108, atn(), &mut __ctx, &mut __consumed_eof)?; - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 238, 17, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(238, 17, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(238, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_239(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 478isize, 239, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(170, 3111, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(170, 3112, atn(), &mut __ctx, &mut __consumed_eof)?; - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 239, 18, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(239, 18, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(239, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - self.base.match_token_into(170, 3114, atn(), &mut __ctx, &mut __consumed_eof)?; - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 239, 19, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(239, 19, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(239, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_240(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 480isize, 240, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(170, 3117, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(139, 3118, atn(), &mut __ctx, &mut __consumed_eof)?; - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 240, 20, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(240, 20, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(240, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_241(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 482isize, 241, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(170, 3121, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(170, 3122, atn(), &mut __ctx, &mut __consumed_eof)?; - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 241, 21, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(241, 21, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(241, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - self.base.match_token_into(139, 3124, atn(), &mut __ctx, &mut __consumed_eof)?; - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 241, 22, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(241, 22, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(241, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_242(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 484isize, 242, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3126isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3127isize, self.dispatch_generated_rule(243, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3132 = false; - loop { - self.base.sync_into(atn(), 3132, &mut __ctx, __loop_iter_3132, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 3132, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3132 = true; - self.base.match_token_into(163, 3129, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3129isize, self.dispatch_generated_rule(243, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_243(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 486isize, 243, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3135isize, self.dispatch_generated_rule(221, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 3137, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 169 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 163 | 167 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 3137, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3136isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - - - pub fn compilation_unit(&mut self) -> Result { - self.parse_rule(0) - } - pub fn extern_alias_directive(&mut self) -> Result { - self.parse_rule(1) - } - pub fn using_directive(&mut self) -> Result { - self.parse_rule(2) - } - pub fn name_equals(&mut self) -> Result { - self.parse_rule(3) - } - pub fn identifier_name(&mut self) -> Result { - self.parse_rule(4) - } - pub fn attribute_list(&mut self) -> Result { - self.parse_rule(5) - } - pub fn attribute_target_specifier(&mut self) -> Result { - self.parse_rule(6) - } - pub fn attribute(&mut self) -> Result { - self.parse_rule(7) - } - pub fn name(&mut self) -> Result { - self.parse_rule(8) - } - pub fn alias_qualified_name(&mut self) -> Result { - self.parse_rule(9) - } - pub fn simple_name(&mut self) -> Result { - self.parse_rule(10) - } - pub fn generic_name(&mut self) -> Result { - self.parse_rule(11) - } - pub fn type_argument_list(&mut self) -> Result { - self.parse_rule(12) - } - pub fn attribute_argument_list(&mut self) -> Result { - self.parse_rule(13) - } - pub fn attribute_argument(&mut self) -> Result { - self.parse_rule(14) - } - pub fn name_colon(&mut self) -> Result { - self.parse_rule(15) - } - pub fn member_declaration(&mut self) -> Result { - self.parse_rule(16) - } - pub fn base_field_declaration(&mut self) -> Result { - self.parse_rule(17) - } - pub fn event_field_declaration(&mut self) -> Result { - self.parse_rule(18) - } - pub fn modifier(&mut self) -> Result { - self.parse_rule(19) - } - pub fn variable_declaration(&mut self) -> Result { - self.parse_rule(20) - } - pub fn variable_declarator(&mut self) -> Result { - self.parse_rule(21) - } - pub fn bracketed_argument_list(&mut self) -> Result { - self.parse_rule(22) - } - pub fn argument(&mut self) -> Result { - self.parse_rule(23) - } - pub fn equals_value_clause(&mut self) -> Result { - self.parse_rule(24) - } - pub fn field_declaration(&mut self) -> Result { - self.parse_rule(25) - } - pub fn base_method_declaration(&mut self) -> Result { - self.parse_rule(26) - } - pub fn constructor_declaration(&mut self) -> Result { - self.parse_rule(27) - } - pub fn parameter_list(&mut self) -> Result { - self.parse_rule(28) - } - pub fn parameter(&mut self) -> Result { - self.parse_rule(29) - } - pub fn constructor_initializer(&mut self) -> Result { - self.parse_rule(30) - } - pub fn argument_list(&mut self) -> Result { - self.parse_rule(31) - } - pub fn block(&mut self) -> Result { - self.parse_rule(32) - } - pub fn arrow_expression_clause(&mut self) -> Result { - self.parse_rule(33) - } - pub fn conversion_operator_declaration(&mut self) -> Result { - self.parse_rule(34) - } - pub fn explicit_interface_specifier(&mut self) -> Result { - self.parse_rule(35) - } - pub fn destructor_declaration(&mut self) -> Result { - self.parse_rule(36) - } - pub fn method_declaration(&mut self) -> Result { - self.parse_rule(37) - } - pub fn type_parameter_list(&mut self) -> Result { - self.parse_rule(38) - } - pub fn type_parameter(&mut self) -> Result { - self.parse_rule(39) - } - pub fn type_parameter_constraint_clause(&mut self) -> Result { - self.parse_rule(40) - } - pub fn type_parameter_constraint(&mut self) -> Result { - self.parse_rule(41) - } - pub fn allows_constraint_clause(&mut self) -> Result { - self.parse_rule(42) - } - pub fn allows_constraint(&mut self) -> Result { - self.parse_rule(43) - } - pub fn ref_struct_constraint(&mut self) -> Result { - self.parse_rule(44) - } - pub fn class_or_struct_constraint(&mut self) -> Result { - self.parse_rule(45) - } - pub fn constructor_constraint(&mut self) -> Result { - self.parse_rule(46) - } - pub fn default_constraint(&mut self) -> Result { - self.parse_rule(47) - } - pub fn type_constraint(&mut self) -> Result { - self.parse_rule(48) - } - pub fn operator_declaration(&mut self) -> Result { - self.parse_rule(49) - } - pub fn base_namespace_declaration(&mut self) -> Result { - self.parse_rule(50) - } - pub fn file_scoped_namespace_declaration(&mut self) -> Result { - self.parse_rule(51) - } - pub fn namespace_declaration(&mut self) -> Result { - self.parse_rule(52) - } - pub fn base_property_declaration(&mut self) -> Result { - self.parse_rule(53) - } - pub fn event_declaration(&mut self) -> Result { - self.parse_rule(54) - } - pub fn accessor_list(&mut self) -> Result { - self.parse_rule(55) - } - pub fn accessor_declaration(&mut self) -> Result { - self.parse_rule(56) - } - pub fn indexer_declaration(&mut self) -> Result { - self.parse_rule(57) - } - pub fn bracketed_parameter_list(&mut self) -> Result { - self.parse_rule(58) - } - pub fn property_declaration(&mut self) -> Result { - self.parse_rule(59) - } - pub fn base_type_declaration(&mut self) -> Result { - self.parse_rule(60) - } - pub fn enum_declaration(&mut self) -> Result { - self.parse_rule(61) - } - pub fn base_list(&mut self) -> Result { - self.parse_rule(62) - } - pub fn base_type(&mut self) -> Result { - self.parse_rule(63) - } - pub fn primary_constructor_base_type(&mut self) -> Result { - self.parse_rule(64) - } - pub fn simple_base_type(&mut self) -> Result { - self.parse_rule(65) - } - pub fn enum_member_declaration(&mut self) -> Result { - self.parse_rule(66) - } - pub fn type_declaration(&mut self) -> Result { - self.parse_rule(67) - } - pub fn class_declaration(&mut self) -> Result { - self.parse_rule(68) - } - pub fn extension_block_declaration(&mut self) -> Result { - self.parse_rule(69) - } - pub fn interface_declaration(&mut self) -> Result { - self.parse_rule(70) - } - pub fn record_declaration(&mut self) -> Result { - self.parse_rule(71) - } - pub fn struct_declaration(&mut self) -> Result { - self.parse_rule(72) - } - pub fn union_declaration(&mut self) -> Result { - self.parse_rule(73) - } - pub fn delegate_declaration(&mut self) -> Result { - self.parse_rule(74) - } - pub fn global_statement(&mut self) -> Result { - self.parse_rule(75) - } - pub fn r#type(&mut self) -> Result { - self.parse_rule(76) - } - pub fn array_type(&mut self) -> Result { - self.parse_rule(77) - } - pub fn array_rank_specifier(&mut self) -> Result { - self.parse_rule(78) - } - pub fn function_pointer_type(&mut self) -> Result { - self.parse_rule(79) - } - pub fn function_pointer_calling_convention(&mut self) -> Result { - self.parse_rule(80) - } - pub fn function_pointer_unmanaged_calling_convention_list(&mut self) -> Result { - self.parse_rule(81) - } - pub fn function_pointer_unmanaged_calling_convention(&mut self) -> Result { - self.parse_rule(82) - } - pub fn function_pointer_parameter_list(&mut self) -> Result { - self.parse_rule(83) - } - pub fn function_pointer_parameter(&mut self) -> Result { - self.parse_rule(84) - } - pub fn predefined_type(&mut self) -> Result { - self.parse_rule(85) - } - pub fn ref_type(&mut self) -> Result { - self.parse_rule(86) - } - pub fn scoped_type(&mut self) -> Result { - self.parse_rule(87) - } - pub fn tuple_type(&mut self) -> Result { - self.parse_rule(88) - } - pub fn tuple_element(&mut self) -> Result { - self.parse_rule(89) - } - pub fn statement(&mut self) -> Result { - self.parse_rule(90) - } - pub fn break_statement(&mut self) -> Result { - self.parse_rule(91) - } - pub fn checked_statement(&mut self) -> Result { - self.parse_rule(92) - } - pub fn common_for_each_statement(&mut self) -> Result { - self.parse_rule(93) - } - pub fn for_each_statement(&mut self) -> Result { - self.parse_rule(94) - } - pub fn for_each_variable_statement(&mut self) -> Result { - self.parse_rule(95) - } - pub fn continue_statement(&mut self) -> Result { - self.parse_rule(96) - } - pub fn do_statement(&mut self) -> Result { - self.parse_rule(97) - } - pub fn empty_statement(&mut self) -> Result { - self.parse_rule(98) - } - pub fn expression_statement(&mut self) -> Result { - self.parse_rule(99) - } - pub fn fixed_statement(&mut self) -> Result { - self.parse_rule(100) - } - pub fn for_statement(&mut self) -> Result { - self.parse_rule(101) - } - pub fn goto_statement(&mut self) -> Result { - self.parse_rule(102) - } - pub fn if_statement(&mut self) -> Result { - self.parse_rule(103) - } - pub fn else_clause(&mut self) -> Result { - self.parse_rule(104) - } - pub fn labeled_statement(&mut self) -> Result { - self.parse_rule(105) - } - pub fn local_declaration_statement(&mut self) -> Result { - self.parse_rule(106) - } - pub fn local_function_statement(&mut self) -> Result { - self.parse_rule(107) - } - pub fn lock_statement(&mut self) -> Result { - self.parse_rule(108) - } - pub fn return_statement(&mut self) -> Result { - self.parse_rule(109) - } - pub fn switch_statement(&mut self) -> Result { - self.parse_rule(110) - } - pub fn switch_section(&mut self) -> Result { - self.parse_rule(111) - } - pub fn switch_label(&mut self) -> Result { - self.parse_rule(112) - } - pub fn case_pattern_switch_label(&mut self) -> Result { - self.parse_rule(113) - } - pub fn pattern(&mut self) -> Result { - self.parse_rule(114) - } - pub fn constant_pattern(&mut self) -> Result { - self.parse_rule(115) - } - pub fn declaration_pattern(&mut self) -> Result { - self.parse_rule(116) - } - pub fn variable_designation(&mut self) -> Result { - self.parse_rule(117) - } - pub fn discard_designation(&mut self) -> Result { - self.parse_rule(118) - } - pub fn parenthesized_variable_designation(&mut self) -> Result { - self.parse_rule(119) - } - pub fn single_variable_designation(&mut self) -> Result { - self.parse_rule(120) - } - pub fn discard_pattern(&mut self) -> Result { - self.parse_rule(121) - } - pub fn list_pattern(&mut self) -> Result { - self.parse_rule(122) - } - pub fn parenthesized_pattern(&mut self) -> Result { - self.parse_rule(123) - } - pub fn recursive_pattern(&mut self) -> Result { - self.parse_rule(124) - } - pub fn positional_pattern_clause(&mut self) -> Result { - self.parse_rule(125) - } - pub fn subpattern(&mut self) -> Result { - self.parse_rule(126) - } - pub fn base_expression_colon(&mut self) -> Result { - self.parse_rule(127) - } - pub fn expression_colon(&mut self) -> Result { - self.parse_rule(128) - } - pub fn property_pattern_clause(&mut self) -> Result { - self.parse_rule(129) - } - pub fn relational_pattern(&mut self) -> Result { - self.parse_rule(130) - } - pub fn slice_pattern(&mut self) -> Result { - self.parse_rule(131) - } - pub fn type_pattern(&mut self) -> Result { - self.parse_rule(132) - } - pub fn unary_pattern(&mut self) -> Result { - self.parse_rule(133) - } - pub fn var_pattern(&mut self) -> Result { - self.parse_rule(134) - } - pub fn when_clause(&mut self) -> Result { - self.parse_rule(135) - } - pub fn case_switch_label(&mut self) -> Result { - self.parse_rule(136) - } - pub fn default_switch_label(&mut self) -> Result { - self.parse_rule(137) - } - pub fn throw_statement(&mut self) -> Result { - self.parse_rule(138) - } - pub fn try_statement(&mut self) -> Result { - self.parse_rule(139) - } - pub fn catch_clause(&mut self) -> Result { - self.parse_rule(140) - } - pub fn catch_declaration(&mut self) -> Result { - self.parse_rule(141) - } - pub fn catch_filter_clause(&mut self) -> Result { - self.parse_rule(142) - } - pub fn finally_clause(&mut self) -> Result { - self.parse_rule(143) - } - pub fn unsafe_statement(&mut self) -> Result { - self.parse_rule(144) - } - pub fn using_statement(&mut self) -> Result { - self.parse_rule(145) - } - pub fn while_statement(&mut self) -> Result { - self.parse_rule(146) - } - pub fn yield_statement(&mut self) -> Result { - self.parse_rule(147) - } - pub fn expression(&mut self) -> Result { - self.parse_rule(148) - } - pub fn anonymous_function_expression(&mut self) -> Result { - self.parse_rule(149) - } - pub fn anonymous_method_expression(&mut self) -> Result { - self.parse_rule(150) - } - pub fn lambda_expression(&mut self) -> Result { - self.parse_rule(151) - } - pub fn parenthesized_lambda_expression(&mut self) -> Result { - self.parse_rule(152) - } - pub fn simple_lambda_expression(&mut self) -> Result { - self.parse_rule(153) - } - pub fn anonymous_object_creation_expression(&mut self) -> Result { - self.parse_rule(154) - } - pub fn anonymous_object_member_declarator(&mut self) -> Result { - self.parse_rule(155) - } - pub fn array_creation_expression(&mut self) -> Result { - self.parse_rule(156) - } - pub fn initializer_expression(&mut self) -> Result { - self.parse_rule(157) - } - pub fn await_expression(&mut self) -> Result { - self.parse_rule(158) - } - pub fn base_object_creation_expression(&mut self) -> Result { - self.parse_rule(159) - } - pub fn implicit_object_creation_expression(&mut self) -> Result { - self.parse_rule(160) - } - pub fn object_creation_expression(&mut self) -> Result { - self.parse_rule(161) - } - pub fn cast_expression(&mut self) -> Result { - self.parse_rule(162) - } - pub fn checked_expression(&mut self) -> Result { - self.parse_rule(163) - } - pub fn collection_expression(&mut self) -> Result { - self.parse_rule(164) - } - pub fn collection_element(&mut self) -> Result { - self.parse_rule(165) - } - pub fn expression_element(&mut self) -> Result { - self.parse_rule(166) - } - pub fn spread_element(&mut self) -> Result { - self.parse_rule(167) - } - pub fn with_element(&mut self) -> Result { - self.parse_rule(168) - } - pub fn declaration_expression(&mut self) -> Result { - self.parse_rule(169) - } - pub fn default_expression(&mut self) -> Result { - self.parse_rule(170) - } - pub fn element_binding_expression(&mut self) -> Result { - self.parse_rule(171) - } - pub fn field_expression(&mut self) -> Result { - self.parse_rule(172) - } - pub fn implicit_array_creation_expression(&mut self) -> Result { - self.parse_rule(173) - } - pub fn implicit_element_access(&mut self) -> Result { - self.parse_rule(174) - } - pub fn implicit_stack_alloc_array_creation_expression(&mut self) -> Result { - self.parse_rule(175) - } - pub fn instance_expression(&mut self) -> Result { - self.parse_rule(176) - } - pub fn base_expression(&mut self) -> Result { - self.parse_rule(177) - } - pub fn this_expression(&mut self) -> Result { - self.parse_rule(178) - } - pub fn interpolated_string_expression(&mut self) -> Result { - self.parse_rule(179) - } - pub fn interpolated_string_content(&mut self) -> Result { - self.parse_rule(180) - } - pub fn interpolated_string_text(&mut self) -> Result { - self.parse_rule(181) - } - pub fn interpolation(&mut self) -> Result { - self.parse_rule(182) - } - pub fn interpolation_alignment_clause(&mut self) -> Result { - self.parse_rule(183) - } - pub fn interpolation_format_clause(&mut self) -> Result { - self.parse_rule(184) - } - pub fn interpolated_multi_line_raw_string_start_token(&mut self) -> Result { - self.parse_rule(185) - } - pub fn interpolated_raw_string_end_token(&mut self) -> Result { - self.parse_rule(186) - } - pub fn interpolated_single_line_raw_string_start_token(&mut self) -> Result { - self.parse_rule(187) - } - pub fn literal_expression(&mut self) -> Result { - self.parse_rule(188) - } - pub fn utf8_multi_line_raw_string_literal_token(&mut self) -> Result { - self.parse_rule(189) - } - pub fn utf8_single_line_raw_string_literal_token(&mut self) -> Result { - self.parse_rule(190) - } - pub fn utf8_string_literal_token(&mut self) -> Result { - self.parse_rule(191) - } - pub fn make_ref_expression(&mut self) -> Result { - self.parse_rule(192) - } - pub fn member_binding_expression(&mut self) -> Result { - self.parse_rule(193) - } - pub fn parenthesized_expression(&mut self) -> Result { - self.parse_rule(194) - } - pub fn prefix_unary_expression(&mut self) -> Result { - self.parse_rule(195) - } - pub fn query_expression(&mut self) -> Result { - self.parse_rule(196) - } - pub fn from_clause(&mut self) -> Result { - self.parse_rule(197) - } - pub fn query_body(&mut self) -> Result { - self.parse_rule(198) - } - pub fn query_clause(&mut self) -> Result { - self.parse_rule(199) - } - pub fn join_clause(&mut self) -> Result { - self.parse_rule(200) - } - pub fn join_into_clause(&mut self) -> Result { - self.parse_rule(201) - } - pub fn let_clause(&mut self) -> Result { - self.parse_rule(202) - } - pub fn order_by_clause(&mut self) -> Result { - self.parse_rule(203) - } - pub fn ordering(&mut self) -> Result { - self.parse_rule(204) - } - pub fn where_clause(&mut self) -> Result { - self.parse_rule(205) - } - pub fn select_or_group_clause(&mut self) -> Result { - self.parse_rule(206) - } - pub fn group_clause(&mut self) -> Result { - self.parse_rule(207) - } - pub fn select_clause(&mut self) -> Result { - self.parse_rule(208) - } - pub fn query_continuation(&mut self) -> Result { - self.parse_rule(209) - } - pub fn ref_expression(&mut self) -> Result { - self.parse_rule(210) - } - pub fn ref_type_expression(&mut self) -> Result { - self.parse_rule(211) - } - pub fn ref_value_expression(&mut self) -> Result { - self.parse_rule(212) - } - pub fn size_of_expression(&mut self) -> Result { - self.parse_rule(213) - } - pub fn stack_alloc_array_creation_expression(&mut self) -> Result { - self.parse_rule(214) - } - pub fn switch_expression_arm(&mut self) -> Result { - self.parse_rule(215) - } - pub fn throw_expression(&mut self) -> Result { - self.parse_rule(216) - } - pub fn tuple_expression(&mut self) -> Result { - self.parse_rule(217) - } - pub fn type_of_expression(&mut self) -> Result { - self.parse_rule(218) - } - pub fn unsafe_expression(&mut self) -> Result { - self.parse_rule(219) - } - pub fn syntax_token(&mut self) -> Result { - self.parse_rule(220) - } - pub fn identifier_token(&mut self) -> Result { - self.parse_rule(221) - } - pub fn keyword(&mut self) -> Result { - self.parse_rule(222) - } - pub fn numeric_literal_token(&mut self) -> Result { - self.parse_rule(223) - } - pub fn integer_literal_token(&mut self) -> Result { - self.parse_rule(224) - } - pub fn decimal_integer_literal_token(&mut self) -> Result { - self.parse_rule(225) - } - pub fn hexadecimal_integer_literal_token(&mut self) -> Result { - self.parse_rule(226) - } - pub fn real_literal_token(&mut self) -> Result { - self.parse_rule(227) - } - pub fn character_literal_token(&mut self) -> Result { - self.parse_rule(228) - } - pub fn string_literal_token(&mut self) -> Result { - self.parse_rule(229) - } - pub fn regular_string_literal_token(&mut self) -> Result { - self.parse_rule(230) - } - pub fn verbatim_string_literal_token(&mut self) -> Result { - self.parse_rule(231) - } - pub fn operator_token(&mut self) -> Result { - self.parse_rule(232) - } - pub fn punctuation_token(&mut self) -> Result { - self.parse_rule(233) - } - pub fn interpolated_string_text_token(&mut self) -> Result { - self.parse_rule(234) - } - pub fn multi_line_raw_string_literal_token(&mut self) -> Result { - self.parse_rule(235) - } - pub fn single_line_raw_string_literal_token(&mut self) -> Result { - self.parse_rule(236) - } - pub fn record_keyword(&mut self) -> Result { - self.parse_rule(237) - } - pub fn right_shift(&mut self) -> Result { - self.parse_rule(238) - } - pub fn unsigned_right_shift(&mut self) -> Result { - self.parse_rule(239) - } - pub fn right_shift_assignment(&mut self) -> Result { - self.parse_rule(240) - } - pub fn unsigned_right_shift_assignment(&mut self) -> Result { - self.parse_rule(241) - } - pub fn local_variable_declaration(&mut self) -> Result { - self.parse_rule(242) - } - pub fn local_variable_declarator(&mut self) -> Result { - self.parse_rule(243) - } - - - fn run_action(&mut self, action: antlr4_runtime::ParserAction, tree: antlr4_runtime::ParseTree) { - match action.source_state() { - 561 => {} - 1613 => {} - 2080 => {} - 2347 => {} - _ => { let _ = self.base.parser_action_hook(action, tree); } - } - } - -} - -antlr4_runtime::__antlr4_rust_parser_driver! { - type: CSharpParser, - fields: { - base: base, - simulator: simulator, - }, - atn: atn, - adaptive_direct: false, - fallback(parser, rule_index, precedence) { - parser.base.parse_atn_rule_with_runtime_options_and_precedence(atn(), rule_index, precedence, antlr4_runtime::ParserRuntimeOptions { action_indices: &[], track_alt_numbers: false, track_context_alt_numbers: false, predicates: &[], semantics: Some(parser_semantics()), rule_args: &[], member_actions: &[], return_actions: &[], unknown_predicate_policy: antlr4_runtime::UnknownSemanticPolicy::Error , ..antlr4_runtime::ParserRuntimeOptions::default() }) - } -} - - - -antlr4_runtime::__antlr4_rust_parser_facade! { - type: CSharpParser, - fields: { - base: base, - simulator: simulator, - generated_only: generated_only, - }, - metadata: metadata, - parser_atn: parser_atn, - reset(parser) { - parser.adaptive_atn.reset(); - } -} -} - -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -pub use self::__antlr4_rust_generated::*; diff --git a/crates/mehen-csharp-parser/src/generated/decisions.json b/crates/mehen-csharp-parser/src/generated/decisions.json deleted file mode 100644 index b8966f00..00000000 --- a/crates/mehen-csharp-parser/src/generated/decisions.json +++ /dev/null @@ -1,2835 +0,0 @@ -{ - "version": 2, - "fixedLookahead": null, - "grammars": [ - { - "name": "CSharpParser", - "summary": { - "total": 362, - "ll1": 220, - "fixed": 0, - "adaptive": 142 - }, - "decisions": [ - { - "decision": 0, - "rule": "compilation_unit", - "state": 491, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 1, - "rule": "compilation_unit", - "state": 497, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 2, - "rule": "compilation_unit", - "state": 503, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 3, - "rule": "compilation_unit", - "state": 509, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 4, - "rule": "using_directive", - "state": 520, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 5, - "rule": "using_directive", - "state": 525, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 6, - "rule": "using_directive", - "state": 528, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 7, - "rule": "identifier_name", - "state": 538, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 8, - "rule": "attribute_list", - "state": 542, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 9, - "rule": "attribute_list", - "state": 549, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 10, - "rule": "attribute", - "state": 559, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 11, - "rule": "name", - "state": 564, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 12, - "rule": "name", - "state": 571, - "canDefer": true, - "tier": "adaptive", - "reason": "precedence", - "probedLookahead": 0 - }, - { - "decision": 13, - "rule": "simple_name", - "state": 580, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 14, - "rule": "type_argument_list", - "state": 587, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 15, - "rule": "type_argument_list", - "state": 591, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 16, - "rule": "type_argument_list", - "state": 595, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 17, - "rule": "type_argument_list", - "state": 598, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 18, - "rule": "attribute_argument_list", - "state": 608, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 19, - "rule": "attribute_argument_list", - "state": 611, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 20, - "rule": "attribute_argument", - "state": 616, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 21, - "rule": "attribute_argument", - "state": 619, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 22, - "rule": "attribute_argument", - "state": 621, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 23, - "rule": "member_declaration", - "state": 639, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 24, - "rule": "base_field_declaration", - "state": 643, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 25, - "rule": "event_field_declaration", - "state": 648, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 26, - "rule": "event_field_declaration", - "state": 654, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 27, - "rule": "variable_declaration", - "state": 669, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 28, - "rule": "variable_declarator", - "state": 674, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 29, - "rule": "variable_declarator", - "state": 677, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 30, - "rule": "bracketed_argument_list", - "state": 685, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 31, - "rule": "argument", - "state": 691, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 32, - "rule": "argument", - "state": 694, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 33, - "rule": "field_declaration", - "state": 704, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 34, - "rule": "field_declaration", - "state": 710, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 35, - "rule": "base_method_declaration", - "state": 721, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 36, - "rule": "constructor_declaration", - "state": 726, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 37, - "rule": "constructor_declaration", - "state": 732, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 38, - "rule": "constructor_declaration", - "state": 738, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 39, - "rule": "constructor_declaration", - "state": 745, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 40, - "rule": "parameter_list", - "state": 753, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 41, - "rule": "parameter_list", - "state": 756, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 42, - "rule": "parameter", - "state": 763, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 43, - "rule": "parameter", - "state": 771, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 44, - "rule": "parameter", - "state": 773, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 45, - "rule": "parameter", - "state": 777, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 46, - "rule": "parameter", - "state": 781, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 47, - "rule": "parameter", - "state": 784, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 48, - "rule": "argument_list", - "state": 796, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 49, - "rule": "argument_list", - "state": 799, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 50, - "rule": "block", - "state": 806, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 51, - "rule": "block", - "state": 813, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 52, - "rule": "conversion_operator_declaration", - "state": 824, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 53, - "rule": "conversion_operator_declaration", - "state": 830, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 54, - "rule": "conversion_operator_declaration", - "state": 835, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 55, - "rule": "conversion_operator_declaration", - "state": 839, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 56, - "rule": "conversion_operator_declaration", - "state": 848, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 57, - "rule": "destructor_declaration", - "state": 856, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 58, - "rule": "destructor_declaration", - "state": 862, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 59, - "rule": "destructor_declaration", - "state": 873, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 60, - "rule": "method_declaration", - "state": 878, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 61, - "rule": "method_declaration", - "state": 884, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 62, - "rule": "method_declaration", - "state": 889, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 63, - "rule": "method_declaration", - "state": 893, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 64, - "rule": "method_declaration", - "state": 899, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 65, - "rule": "method_declaration", - "state": 907, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 66, - "rule": "type_parameter_list", - "state": 915, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 67, - "rule": "type_parameter", - "state": 923, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 68, - "rule": "type_parameter", - "state": 927, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 69, - "rule": "type_parameter_constraint_clause", - "state": 939, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 70, - "rule": "type_parameter_constraint", - "state": 947, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 71, - "rule": "allows_constraint_clause", - "state": 955, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 72, - "rule": "class_or_struct_constraint", - "state": 965, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 73, - "rule": "class_or_struct_constraint", - "state": 969, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 74, - "rule": "class_or_struct_constraint", - "state": 971, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 75, - "rule": "operator_declaration", - "state": 984, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 76, - "rule": "operator_declaration", - "state": 990, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 77, - "rule": "operator_declaration", - "state": 995, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 78, - "rule": "operator_declaration", - "state": 999, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 79, - "rule": "operator_declaration", - "state": 1036, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 80, - "rule": "operator_declaration", - "state": 1044, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 81, - "rule": "base_namespace_declaration", - "state": 1048, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 82, - "rule": "file_scoped_namespace_declaration", - "state": 1053, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 83, - "rule": "file_scoped_namespace_declaration", - "state": 1059, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 84, - "rule": "file_scoped_namespace_declaration", - "state": 1068, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 85, - "rule": "file_scoped_namespace_declaration", - "state": 1074, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 86, - "rule": "file_scoped_namespace_declaration", - "state": 1080, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 87, - "rule": "namespace_declaration", - "state": 1086, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 88, - "rule": "namespace_declaration", - "state": 1092, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 89, - "rule": "namespace_declaration", - "state": 1101, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 90, - "rule": "namespace_declaration", - "state": 1107, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 91, - "rule": "namespace_declaration", - "state": 1113, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 92, - "rule": "namespace_declaration", - "state": 1118, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 93, - "rule": "base_property_declaration", - "state": 1123, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 94, - "rule": "event_declaration", - "state": 1128, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 95, - "rule": "event_declaration", - "state": 1134, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 96, - "rule": "event_declaration", - "state": 1140, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 97, - "rule": "event_declaration", - "state": 1145, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 98, - "rule": "accessor_list", - "state": 1151, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 99, - "rule": "accessor_declaration", - "state": 1159, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 100, - "rule": "accessor_declaration", - "state": 1165, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 101, - "rule": "accessor_declaration", - "state": 1174, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 102, - "rule": "indexer_declaration", - "state": 1179, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 103, - "rule": "indexer_declaration", - "state": 1185, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 104, - "rule": "indexer_declaration", - "state": 1190, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 105, - "rule": "indexer_declaration", - "state": 1198, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 106, - "rule": "bracketed_parameter_list", - "state": 1206, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 107, - "rule": "property_declaration", - "state": 1214, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 108, - "rule": "property_declaration", - "state": 1220, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 109, - "rule": "property_declaration", - "state": 1225, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 110, - "rule": "property_declaration", - "state": 1232, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 111, - "rule": "property_declaration", - "state": 1236, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 112, - "rule": "property_declaration", - "state": 1240, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 113, - "rule": "base_type_declaration", - "state": 1244, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 114, - "rule": "enum_declaration", - "state": 1249, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 115, - "rule": "enum_declaration", - "state": 1255, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 116, - "rule": "enum_declaration", - "state": 1261, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 117, - "rule": "enum_declaration", - "state": 1269, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 118, - "rule": "enum_declaration", - "state": 1273, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 119, - "rule": "enum_declaration", - "state": 1275, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 120, - "rule": "enum_declaration", - "state": 1278, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 121, - "rule": "enum_declaration", - "state": 1281, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 122, - "rule": "base_list", - "state": 1289, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 123, - "rule": "base_type", - "state": 1294, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 124, - "rule": "enum_member_declaration", - "state": 1304, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 125, - "rule": "enum_member_declaration", - "state": 1310, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 126, - "rule": "enum_member_declaration", - "state": 1315, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 127, - "rule": "type_declaration", - "state": 1323, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 128, - "rule": "class_declaration", - "state": 1328, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 129, - "rule": "class_declaration", - "state": 1334, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 130, - "rule": "class_declaration", - "state": 1340, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 131, - "rule": "class_declaration", - "state": 1343, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 132, - "rule": "class_declaration", - "state": 1346, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 133, - "rule": "class_declaration", - "state": 1351, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 134, - "rule": "class_declaration", - "state": 1358, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 135, - "rule": "class_declaration", - "state": 1362, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 136, - "rule": "class_declaration", - "state": 1365, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 137, - "rule": "extension_block_declaration", - "state": 1370, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 138, - "rule": "extension_block_declaration", - "state": 1376, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 139, - "rule": "extension_block_declaration", - "state": 1381, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 140, - "rule": "extension_block_declaration", - "state": 1384, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 141, - "rule": "extension_block_declaration", - "state": 1389, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 142, - "rule": "extension_block_declaration", - "state": 1396, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 143, - "rule": "interface_declaration", - "state": 1404, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 144, - "rule": "interface_declaration", - "state": 1410, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 145, - "rule": "interface_declaration", - "state": 1416, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 146, - "rule": "interface_declaration", - "state": 1419, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 147, - "rule": "interface_declaration", - "state": 1422, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 148, - "rule": "interface_declaration", - "state": 1427, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 149, - "rule": "interface_declaration", - "state": 1434, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 150, - "rule": "interface_declaration", - "state": 1438, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 151, - "rule": "interface_declaration", - "state": 1441, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 152, - "rule": "record_declaration", - "state": 1446, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 153, - "rule": "record_declaration", - "state": 1452, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 154, - "rule": "record_declaration", - "state": 1457, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 155, - "rule": "record_declaration", - "state": 1461, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 156, - "rule": "record_declaration", - "state": 1464, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 157, - "rule": "record_declaration", - "state": 1467, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 158, - "rule": "record_declaration", - "state": 1472, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 159, - "rule": "record_declaration", - "state": 1479, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 160, - "rule": "record_declaration", - "state": 1483, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 161, - "rule": "record_declaration", - "state": 1486, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 162, - "rule": "struct_declaration", - "state": 1491, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 163, - "rule": "struct_declaration", - "state": 1497, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 164, - "rule": "struct_declaration", - "state": 1503, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 165, - "rule": "struct_declaration", - "state": 1506, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 166, - "rule": "struct_declaration", - "state": 1509, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 167, - "rule": "struct_declaration", - "state": 1514, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 168, - "rule": "struct_declaration", - "state": 1521, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 169, - "rule": "struct_declaration", - "state": 1525, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 170, - "rule": "struct_declaration", - "state": 1528, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 171, - "rule": "union_declaration", - "state": 1533, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 172, - "rule": "union_declaration", - "state": 1539, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 173, - "rule": "union_declaration", - "state": 1545, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 174, - "rule": "union_declaration", - "state": 1548, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 175, - "rule": "union_declaration", - "state": 1551, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 176, - "rule": "union_declaration", - "state": 1556, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 177, - "rule": "union_declaration", - "state": 1563, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 178, - "rule": "union_declaration", - "state": 1567, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 179, - "rule": "union_declaration", - "state": 1570, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 180, - "rule": "delegate_declaration", - "state": 1575, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 181, - "rule": "delegate_declaration", - "state": 1581, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 182, - "rule": "delegate_declaration", - "state": 1588, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 183, - "rule": "delegate_declaration", - "state": 1594, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 184, - "rule": "global_statement", - "state": 1602, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 185, - "rule": "global_statement", - "state": 1608, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 186, - "rule": "type", - "state": 1620, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 187, - "rule": "type", - "state": 1626, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 188, - "rule": "type", - "state": 1632, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 189, - "rule": "type", - "state": 1634, - "canDefer": true, - "tier": "adaptive", - "reason": "precedence", - "probedLookahead": 0 - }, - { - "decision": 190, - "rule": "array_type", - "state": 1641, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 191, - "rule": "array_rank_specifier", - "state": 1645, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 192, - "rule": "array_rank_specifier", - "state": 1649, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 193, - "rule": "array_rank_specifier", - "state": 1653, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 194, - "rule": "array_rank_specifier", - "state": 1656, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 195, - "rule": "function_pointer_type", - "state": 1663, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 196, - "rule": "function_pointer_calling_convention", - "state": 1669, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 197, - "rule": "function_pointer_calling_convention", - "state": 1673, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 198, - "rule": "function_pointer_calling_convention", - "state": 1675, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 199, - "rule": "function_pointer_unmanaged_calling_convention_list", - "state": 1683, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 200, - "rule": "function_pointer_parameter_list", - "state": 1696, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 201, - "rule": "function_pointer_parameter", - "state": 1704, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 202, - "rule": "function_pointer_parameter", - "state": 1710, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 203, - "rule": "ref_type", - "state": 1719, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 204, - "rule": "tuple_type", - "state": 1732, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 205, - "rule": "tuple_element", - "state": 1738, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 206, - "rule": "statement", - "state": 1764, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 207, - "rule": "break_statement", - "state": 1769, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 208, - "rule": "break_statement", - "state": 1774, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 209, - "rule": "checked_statement", - "state": 1781, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 210, - "rule": "common_for_each_statement", - "state": 1789, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 211, - "rule": "for_each_statement", - "state": 1794, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 212, - "rule": "for_each_statement", - "state": 1798, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 213, - "rule": "for_each_variable_statement", - "state": 1812, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 214, - "rule": "for_each_variable_statement", - "state": 1816, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 215, - "rule": "continue_statement", - "state": 1829, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 216, - "rule": "continue_statement", - "state": 1834, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 217, - "rule": "do_statement", - "state": 1841, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 218, - "rule": "empty_statement", - "state": 1855, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 219, - "rule": "expression_statement", - "state": 1863, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 220, - "rule": "fixed_statement", - "state": 1872, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 221, - "rule": "for_statement", - "state": 1884, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 222, - "rule": "for_statement", - "state": 1890, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 223, - "rule": "for_statement", - "state": 1897, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 224, - "rule": "for_statement", - "state": 1900, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 225, - "rule": "for_statement", - "state": 1902, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 226, - "rule": "for_statement", - "state": 1906, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 227, - "rule": "for_statement", - "state": 1914, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 228, - "rule": "for_statement", - "state": 1917, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 229, - "rule": "goto_statement", - "state": 1925, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 230, - "rule": "goto_statement", - "state": 1930, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 231, - "rule": "goto_statement", - "state": 1933, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 232, - "rule": "if_statement", - "state": 1940, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 233, - "rule": "if_statement", - "state": 1949, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 234, - "rule": "labeled_statement", - "state": 1957, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 235, - "rule": "local_declaration_statement", - "state": 1967, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 236, - "rule": "local_declaration_statement", - "state": 1971, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 237, - "rule": "local_declaration_statement", - "state": 1974, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 238, - "rule": "local_declaration_statement", - "state": 1979, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 239, - "rule": "local_function_statement", - "state": 1988, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 240, - "rule": "local_function_statement", - "state": 1994, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 241, - "rule": "local_function_statement", - "state": 2000, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 242, - "rule": "local_function_statement", - "state": 2006, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 243, - "rule": "local_function_statement", - "state": 2013, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 244, - "rule": "lock_statement", - "state": 2018, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 245, - "rule": "return_statement", - "state": 2030, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 246, - "rule": "return_statement", - "state": 2035, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 247, - "rule": "switch_statement", - "state": 2042, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 248, - "rule": "switch_statement", - "state": 2053, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 249, - "rule": "switch_section", - "state": 2061, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 250, - "rule": "switch_section", - "state": 2066, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 251, - "rule": "switch_label", - "state": 2071, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 252, - "rule": "case_pattern_switch_label", - "state": 2076, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 253, - "rule": "pattern", - "state": 2092, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 254, - "rule": "pattern", - "state": 2099, - "canDefer": true, - "tier": "adaptive", - "reason": "precedence", - "probedLookahead": 0 - }, - { - "decision": 255, - "rule": "variable_designation", - "state": 2110, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 256, - "rule": "parenthesized_variable_designation", - "state": 2120, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 257, - "rule": "parenthesized_variable_designation", - "state": 2123, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 258, - "rule": "list_pattern", - "state": 2137, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 259, - "rule": "list_pattern", - "state": 2141, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 260, - "rule": "list_pattern", - "state": 2143, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 261, - "rule": "list_pattern", - "state": 2147, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 262, - "rule": "recursive_pattern", - "state": 2154, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 263, - "rule": "recursive_pattern", - "state": 2157, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 264, - "rule": "recursive_pattern", - "state": 2160, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 265, - "rule": "recursive_pattern", - "state": 2163, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 266, - "rule": "positional_pattern_clause", - "state": 2171, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 267, - "rule": "positional_pattern_clause", - "state": 2174, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 268, - "rule": "subpattern", - "state": 2179, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 269, - "rule": "base_expression_colon", - "state": 2185, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 270, - "rule": "property_pattern_clause", - "state": 2196, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 271, - "rule": "property_pattern_clause", - "state": 2200, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 272, - "rule": "property_pattern_clause", - "state": 2202, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 273, - "rule": "relational_pattern", - "state": 2218, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 274, - "rule": "slice_pattern", - "state": 2222, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 275, - "rule": "throw_statement", - "state": 2245, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 276, - "rule": "throw_statement", - "state": 2250, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 277, - "rule": "try_statement", - "state": 2257, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 278, - "rule": "try_statement", - "state": 2265, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 279, - "rule": "try_statement", - "state": 2269, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 280, - "rule": "catch_clause", - "state": 2273, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 281, - "rule": "catch_clause", - "state": 2276, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 282, - "rule": "catch_declaration", - "state": 2283, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 283, - "rule": "unsafe_statement", - "state": 2298, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 284, - "rule": "using_statement", - "state": 2307, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 285, - "rule": "using_statement", - "state": 2311, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 286, - "rule": "using_statement", - "state": 2317, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 287, - "rule": "while_statement", - "state": 2325, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 288, - "rule": "yield_statement", - "state": 2337, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 289, - "rule": "yield_statement", - "state": 2343, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 290, - "rule": "expression", - "state": 2373, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 291, - "rule": "expression", - "state": 2386, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 292, - "rule": "expression", - "state": 2402, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 293, - "rule": "expression", - "state": 2428, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 294, - "rule": "expression", - "state": 2455, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 295, - "rule": "expression", - "state": 2465, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 296, - "rule": "expression", - "state": 2469, - "canDefer": true, - "tier": "ll1" - }, - { - "decision": 297, - "rule": "expression", - "state": 2471, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 298, - "rule": "expression", - "state": 2477, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 299, - "rule": "expression", - "state": 2479, - "canDefer": true, - "tier": "adaptive", - "reason": "precedence", - "probedLookahead": 0 - }, - { - "decision": 300, - "rule": "anonymous_function_expression", - "state": 2484, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 301, - "rule": "anonymous_method_expression", - "state": 2489, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 302, - "rule": "anonymous_method_expression", - "state": 2494, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 303, - "rule": "anonymous_method_expression", - "state": 2498, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 304, - "rule": "lambda_expression", - "state": 2502, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 305, - "rule": "parenthesized_lambda_expression", - "state": 2507, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 306, - "rule": "parenthesized_lambda_expression", - "state": 2513, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 307, - "rule": "parenthesized_lambda_expression", - "state": 2517, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 308, - "rule": "parenthesized_lambda_expression", - "state": 2523, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 309, - "rule": "simple_lambda_expression", - "state": 2528, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 310, - "rule": "simple_lambda_expression", - "state": 2534, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 311, - "rule": "simple_lambda_expression", - "state": 2541, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 312, - "rule": "anonymous_object_creation_expression", - "state": 2550, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 313, - "rule": "anonymous_object_creation_expression", - "state": 2554, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 314, - "rule": "anonymous_object_creation_expression", - "state": 2556, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 315, - "rule": "anonymous_object_member_declarator", - "state": 2561, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 316, - "rule": "array_creation_expression", - "state": 2568, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 317, - "rule": "initializer_expression", - "state": 2576, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 318, - "rule": "initializer_expression", - "state": 2580, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 319, - "rule": "initializer_expression", - "state": 2582, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 320, - "rule": "base_object_creation_expression", - "state": 2591, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 321, - "rule": "implicit_object_creation_expression", - "state": 2596, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 322, - "rule": "object_creation_expression", - "state": 2601, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 323, - "rule": "object_creation_expression", - "state": 2604, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 324, - "rule": "checked_expression", - "state": 2621, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 325, - "rule": "collection_expression", - "state": 2629, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 326, - "rule": "collection_expression", - "state": 2633, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 327, - "rule": "collection_expression", - "state": 2635, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 328, - "rule": "collection_element", - "state": 2642, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 329, - "rule": "implicit_array_creation_expression", - "state": 2669, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 330, - "rule": "instance_expression", - "state": 2684, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 331, - "rule": "interpolated_string_expression", - "state": 2694, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 332, - "rule": "interpolated_string_expression", - "state": 2702, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 333, - "rule": "interpolated_string_expression", - "state": 2710, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 334, - "rule": "interpolated_string_expression", - "state": 2719, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 335, - "rule": "interpolated_string_expression", - "state": 2724, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 336, - "rule": "interpolated_string_content", - "state": 2728, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 337, - "rule": "interpolation", - "state": 2735, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 338, - "rule": "interpolation", - "state": 2738, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 339, - "rule": "interpolated_raw_string_end_token", - "state": 2754, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 340, - "rule": "literal_expression", - "state": 2772, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 341, - "rule": "prefix_unary_expression", - "state": 2813, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 342, - "rule": "from_clause", - "state": 2820, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 343, - "rule": "query_body", - "state": 2829, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 344, - "rule": "query_body", - "state": 2834, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 345, - "rule": "query_clause", - "state": 2841, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 346, - "rule": "join_clause", - "state": 2845, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 347, - "rule": "join_clause", - "state": 2855, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 348, - "rule": "order_by_clause", - "state": 2871, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 349, - "rule": "ordering", - "state": 2876, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 350, - "rule": "select_or_group_clause", - "state": 2883, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 351, - "rule": "stack_alloc_array_creation_expression", - "state": 2920, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 352, - "rule": "switch_expression_arm", - "state": 2924, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 353, - "rule": "tuple_expression", - "state": 2938, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 354, - "rule": "syntax_token", - "state": 2959, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 355, - "rule": "keyword", - "state": 3028, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 356, - "rule": "numeric_literal_token", - "state": 3032, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 357, - "rule": "integer_literal_token", - "state": 3037, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 358, - "rule": "string_literal_token", - "state": 3049, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 359, - "rule": "operator_token", - "state": 3094, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 360, - "rule": "local_variable_declaration", - "state": 3132, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 361, - "rule": "local_variable_declarator", - "state": 3137, - "canDefer": false, - "tier": "ll1" - } - ] - } - ] -} diff --git a/crates/mehen-csharp-parser/src/generated/semantics.json b/crates/mehen-csharp-parser/src/generated/semantics.json deleted file mode 100644 index 440f874b..00000000 --- a/crates/mehen-csharp-parser/src/generated/semantics.json +++ /dev/null @@ -1,472 +0,0 @@ -{ - "version": 2, - "policy": "error", - "note": "unknown coordinates currently default to assume-true; a future minor release changes the default to error", - "options": [ - { - "name": "tokenVocab", - "value": "CSharpLexer", - "line": 5, - "column": 10, - "disposition": "metadata" - } - ], - "grammars": [ - { - "kind": "lexer", - "name": "CSharpLexer", - "coordinates": [ - { - "kind": "lexer-action", - "rule": "INTERP_NESTED_CLOSE", - "rule_index": 204, - "index": 0, - "atn_state": null, - "line": 608, - "column": 27, - "body": "nestDepth--;", - "disposition": "translated", - "template": "MemberStmt(Add(0, Int(-1)))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_NESTED_LPAREN", - "rule_index": 205, - "index": 1, - "atn_state": null, - "line": 624, - "column": 33, - "body": "nestDepth++;", - "disposition": "translated", - "template": "MemberStmt(Add(0, Int(1)))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_NESTED_RPAREN", - "rule_index": 206, - "index": 2, - "atn_state": null, - "line": 628, - "column": 27, - "body": "nestDepth--;", - "disposition": "translated", - "template": "MemberStmt(Add(0, Int(-1)))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_NESTED_LBRACKET", - "rule_index": 207, - "index": 3, - "atn_state": null, - "line": 632, - "column": 33, - "body": "nestDepth++;", - "disposition": "translated", - "template": "MemberStmt(Add(0, Int(1)))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_NESTED_RBRACKET", - "rule_index": 208, - "index": 4, - "atn_state": null, - "line": 636, - "column": 27, - "body": "nestDepth--;", - "disposition": "translated", - "template": "MemberStmt(Add(0, Int(-1)))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_HOLE_CLOSE_2", - "rule_index": 209, - "index": 5, - "atn_state": null, - "line": 661, - "column": 6, - "body": "nestDepth = holeStack.Pop(); wideStack.Pop();", - "disposition": "translated", - "template": "MemberStmt(Seq([Set(0, MemberTop(0)), Pop(0), Pop(1)]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_HOLE_CLOSE", - "rule_index": 210, - "index": 6, - "atn_state": null, - "line": 666, - "column": 6, - "body": "nestDepth = holeStack.Pop(); wideStack.Pop();", - "disposition": "translated", - "template": "MemberStmt(Seq([Set(0, MemberTop(0)), Pop(0), Pop(1)]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_NESTED_OPEN", - "rule_index": 211, - "index": 7, - "atn_state": null, - "line": 671, - "column": 33, - "body": "nestDepth++;", - "disposition": "translated", - "template": "MemberStmt(Add(0, Int(1)))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_HOLE_OPEN", - "rule_index": 225, - "index": 8, - "atn_state": null, - "line": 721, - "column": 23, - "body": "holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0;", - "disposition": "translated", - "template": "MemberStmt(Seq([Push(0, Member(0)), Push(1, Int(0)), Set(0, Int(0))]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_V_HOLE_OPEN", - "rule_index": 231, - "index": 9, - "atn_state": null, - "line": 741, - "column": 25, - "body": "holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0;", - "disposition": "translated", - "template": "MemberStmt(Seq([Push(0, Member(0)), Push(1, Int(0)), Set(0, Int(0))]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_R_HOLE_OPEN", - "rule_index": 238, - "index": 10, - "atn_state": null, - "line": 764, - "column": 25, - "body": "holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0;", - "disposition": "translated", - "template": "MemberStmt(Seq([Push(0, Member(0)), Push(1, Int(0)), Set(0, Int(0))]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_R2_HOLE_OPEN", - "rule_index": 239, - "index": 11, - "atn_state": null, - "line": 782, - "column": 11, - "body": "holeStack.Push(nestDepth); wideStack.Push(1); nestDepth = 0;", - "disposition": "translated", - "template": "MemberStmt(Seq([Push(0, Member(0)), Push(1, Int(1)), Set(0, Int(0))]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_FORMAT_END_2", - "rule_index": 246, - "index": 12, - "atn_state": null, - "line": 859, - "column": 6, - "body": "nestDepth = holeStack.Pop(); wideStack.Pop();", - "disposition": "translated", - "template": "MemberStmt(Seq([Set(0, MemberTop(0)), Pop(0), Pop(1)]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_FORMAT_END", - "rule_index": 247, - "index": 13, - "atn_state": null, - "line": 863, - "column": 10, - "body": "nestDepth = holeStack.Pop(); wideStack.Pop();", - "disposition": "translated", - "template": "MemberStmt(Seq([Set(0, MemberTop(0)), Pop(0), Pop(1)]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_R4_HOLE_OPEN", - "rule_index": 253, - "index": 14, - "atn_state": null, - "line": 889, - "column": 10, - "body": "holeStack.Push(nestDepth); wideStack.Push(0); nestDepth = 0;", - "disposition": "translated", - "template": "MemberStmt(Seq([Push(0, Member(0)), Push(1, Int(0)), Set(0, Int(0))]))" - }, - { - "kind": "lexer-action", - "rule": "INTERP_R24_HOLE_OPEN", - "rule_index": 254, - "index": 15, - "atn_state": null, - "line": 897, - "column": 11, - "body": "holeStack.Push(nestDepth); wideStack.Push(1); nestDepth = 0;", - "disposition": "translated", - "template": "MemberStmt(Seq([Push(0, Member(0)), Push(1, Int(1)), Set(0, Int(0))]))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_NESTED_CLOSE", - "rule_index": 204, - "index": 0, - "atn_state": null, - "line": 608, - "column": 6, - "body": "nestDepth > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(Member(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_NESTED_LPAREN", - "rule_index": 205, - "index": 1, - "atn_state": null, - "line": 624, - "column": 6, - "body": "holeStack.Count > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(MemberLen(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_NESTED_RPAREN", - "rule_index": 206, - "index": 2, - "atn_state": null, - "line": 628, - "column": 6, - "body": "nestDepth > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(Member(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_NESTED_LBRACKET", - "rule_index": 207, - "index": 3, - "atn_state": null, - "line": 632, - "column": 6, - "body": "holeStack.Count > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(MemberLen(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_NESTED_RBRACKET", - "rule_index": 208, - "index": 4, - "atn_state": null, - "line": 636, - "column": 6, - "body": "nestDepth > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(Member(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_HOLE_CLOSE_2", - "rule_index": 209, - "index": 5, - "atn_state": null, - "line": 660, - "column": 6, - "body": "wideStack.Peek() > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(MemberTop(1))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_HOLE_CLOSE", - "rule_index": 210, - "index": 6, - "atn_state": null, - "line": 665, - "column": 6, - "body": "holeStack.Count > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(MemberLen(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_NESTED_OPEN", - "rule_index": 211, - "index": 7, - "atn_state": null, - "line": 671, - "column": 6, - "body": "holeStack.Count > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(MemberLen(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_NESTED_COLON", - "rule_index": 212, - "index": 8, - "atn_state": null, - "line": 679, - "column": 6, - "body": "nestDepth > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(Member(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_FORMAT_COLON", - "rule_index": 213, - "index": 9, - "atn_state": null, - "line": 683, - "column": 6, - "body": "holeStack.Count > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(MemberLen(0))))" - }, - { - "kind": "lexer-predicate", - "rule": "INTERP_FORMAT_END_2", - "rule_index": 246, - "index": 10, - "atn_state": null, - "line": 858, - "column": 6, - "body": "wideStack.Peek() > 0", - "disposition": "translated", - "template": "MemberExpr(Not(Not(MemberTop(1))))" - } - ] - }, - { - "kind": "parser", - "name": "CSharpParser", - "coordinates": [ - { - "kind": "parser-action", - "rule": "name", - "rule_index": 8, - "index": 0, - "atn_state": 561, - "line": null, - "column": null, - "body": null, - "disposition": "synthetic", - "template": null - }, - { - "kind": "parser-action", - "rule": "type", - "rule_index": 76, - "index": 1, - "atn_state": 1613, - "line": null, - "column": null, - "body": null, - "disposition": "synthetic", - "template": null - }, - { - "kind": "parser-action", - "rule": "pattern", - "rule_index": 114, - "index": 2, - "atn_state": 2080, - "line": null, - "column": null, - "body": null, - "disposition": "synthetic", - "template": null - }, - { - "kind": "parser-action", - "rule": "expression", - "rule_index": 148, - "index": 3, - "atn_state": 2347, - "line": null, - "column": null, - "body": null, - "disposition": "synthetic", - "template": null - }, - { - "kind": "parser-predicate", - "rule": "right_shift", - "rule_index": 238, - "index": 17, - "atn_state": null, - "line": 1572, - "column": 10, - "body": "this.IsRightShift()", - "disposition": "translated", - "template": "TokenPairAdjacent" - }, - { - "kind": "parser-predicate", - "rule": "unsigned_right_shift", - "rule_index": 239, - "index": 18, - "atn_state": null, - "line": 1576, - "column": 10, - "body": "this.IsUnsignedRightShift()", - "disposition": "translated", - "template": "TokenPairAdjacent" - }, - { - "kind": "parser-predicate", - "rule": "unsigned_right_shift", - "rule_index": 239, - "index": 19, - "atn_state": null, - "line": 1576, - "column": 44, - "body": "this.IsUnsignedRightShift()", - "disposition": "translated", - "template": "TokenPairAdjacent" - }, - { - "kind": "parser-predicate", - "rule": "right_shift_assignment", - "rule_index": 240, - "index": 20, - "atn_state": null, - "line": 1580, - "column": 10, - "body": "this.IsRightShiftAssignment()", - "disposition": "translated", - "template": "TokenPairAdjacent" - }, - { - "kind": "parser-predicate", - "rule": "unsigned_right_shift_assignment", - "rule_index": 241, - "index": 21, - "atn_state": null, - "line": 1584, - "column": 10, - "body": "this.IsUnsignedRightShiftAssignment()", - "disposition": "translated", - "template": "TokenPairAdjacent" - }, - { - "kind": "parser-predicate", - "rule": "unsigned_right_shift_assignment", - "rule_index": 241, - "index": 22, - "atn_state": null, - "line": 1584, - "column": 54, - "body": "this.IsUnsignedRightShiftAssignment()", - "disposition": "translated", - "template": "TokenPairAdjacent" - } - ] - } - ] -} diff --git a/crates/mehen-csharp-parser/src/lib.rs b/crates/mehen-csharp-parser/src/lib.rs deleted file mode 100644 index 56ec8a49..00000000 --- a/crates/mehen-csharp-parser/src/lib.rs +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-csharp-parser` — ANTLR-generated C# lexer and parser. -//! -//! This crate holds the machine-generated C# lexer/parser derived from -//! [Roslyn's own published grammar][roslyn] (`CSharp.Generated.g4`, vendored in -//! `grammar/`) running on the [`antlr4_runtime`] Rust runtime. It carries no -//! hand-written Rust beyond this module docs, no mehen-specific logic, and no -//! dependency on `mehen-core`, so it can be consumed on its own — e.g. -//! `mehen-csharp-parser = { git = "https://github.com/ophi-dev/mehen", tag = "…" }` -//! — the same way this repo consumes the ruff/oxc/sqruff parser crates. -//! -//! (Linked to the repository, not docs.rs: the analyzer crates are -//! `publish = false`, so they have no docs.rs page to link to.) -//! -//! The [`mehen-csharp`](https://github.com/ophi-dev/mehen/tree/main/crates/mehen-csharp) analyzer crate depends -//! on this one and walks the resulting [`antlr4_runtime::ParseTree`] to -//! compute metrics. -//! -//! ## Regenerating — never hand-edit -//! -//! The generated modules are produced by `cargo xtask antlr generate csharp` -//! and checked in verbatim (see `src/generated/README.md` and -//! `grammar/PROVENANCE.md`). `cargo xtask antlr check-generated` guards against -//! drift in CI. -//! -//! Generation has an extra step here: Roslyn publishes a *reference* grammar -//! that ANTLR rejects as-is, so `grammar/prepare-grammar.py` derives a -//! generatable lexer/parser pair from it first. Those derived `.g4` files are -//! build artifacts (gitignored); the vendored `CSharp.Generated.g4` is the -//! source of truth. The prep needs [`uv`](https://docs.astral.sh/uv/) in -//! addition to the Rust toolchain. -//! -//! ## No hooks -//! -//! Neither recognizer needs a hand-written hook object: every semantic -//! coordinate lowers to pure SemIR through the derived `patterns.toml`. -//! -//! That includes the awkward one. Interpolated strings need their own lexer -//! modes, and the `}` closing a hole is lexically identical to the one closing a -//! nested block — so the decision needs a brace depth per hole and a -//! *conditional* mode pop, which SemIR has no action for. The grammar instead -//! keeps the depth in `@lexer::members` and splits the `}` into two -//! predicate-gated rules, ordered so that rule selection supplies the condition -//! and each alternative carries an unconditional command. See -//! `grammar/lexer-tokens.g4.in`. -//! -//! ## Quickstart -//! -//! ```no_run -//! use mehen_csharp_parser::c_sharp_parser::{self, CSharpParser}; -//! use mehen_csharp_parser::c_sharp_lexer::CSharpLexer; -//! // `number_of_syntax_errors` is a `Parser`-trait method, so the trait -//! // must be in scope to call it. -//! use antlr4_runtime::Parser; -//! -//! # fn main() -> Result<(), antlr4_runtime::AntlrError> { -//! // One-call setup: build lexer + token stream + parser and run an entry -//! // rule. `parse_with_parser` keeps the parser so you can read diagnostics. -//! let out = c_sharp_parser::parse_with_parser( -//! "class C {}\n", -//! CSharpLexer::new, -//! CSharpParser::compilation_unit, -//! )?; -//! let errors = out.parser.number_of_syntax_errors(); -//! let parsed = out.parser.into_parsed_file(out.result); -//! let _ = (errors, parsed.tree()); -//! # Ok(()) -//! # } -//! ``` -//! -//! [roslyn]: https://github.com/dotnet/roslyn/blob/main/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 - -#![forbid(unsafe_code)] - -/// Re-export of the ANTLR v4 Rust runtime the generated modules were built -/// against, so downstream crates can name the runtime types (`ParseTree`, -/// `Node`, `TokenView`, …) without pinning the runtime version themselves. -pub use antlr4_runtime; - -/// ANTLR-generated C# lexer. -/// -/// Regenerate with `cargo xtask antlr generate csharp` — never hand-edit. -#[path = "generated/c_sharp_lexer.rs"] -pub mod c_sharp_lexer; - -/// ANTLR-generated C# parser. -/// -/// Regenerate with `cargo xtask antlr generate csharp` — never hand-edit. -#[path = "generated/c_sharp_parser.rs"] -pub mod c_sharp_parser; diff --git a/crates/mehen-csharp-parser/tests/hooks.rs b/crates/mehen-csharp-parser/tests/hooks.rs deleted file mode 100644 index fec7235d..00000000 --- a/crates/mehen-csharp-parser/tests/hooks.rs +++ /dev/null @@ -1,442 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Behavioral tests for the derived grammar's semantic surfaces — the -//! interpolated-string state in `@lexer::members` and the pattern-lowered -//! parser predicates. -//! -//! Each test pins one observable consequence so a regression in the grammar — or -//! a regenerate that stops routing a helper — fails here rather than silently -//! skewing downstream metrics. The interpolation cases are the interesting ones: -//! the `}` closing a hole is lexically identical to the one closing a nested -//! block, so telling them apart needs a brace depth per open hole and a -//! *conditional* mode pop. SemIR has no conditional action, so the grammar -//! encodes it as two predicate-gated rules over the same character, ordered so -//! rule selection supplies the conjunction (see `grammar/lexer-tokens.g4.in`). - -use antlr4_runtime::{CommonTokenStream, InputStream, Parser}; -use mehen_csharp_parser::c_sharp_lexer::CSharpLexer; -use mehen_csharp_parser::c_sharp_parser::{self as c_sharp_parser, CSharpParser}; - -/// Parse a compilation unit, returning the recovered syntax-error count. -/// -/// Plain `CSharpLexer::new`: the lexer needs no hooks at all. Its state lives in -/// `@lexer::members` and every action and predicate lowers to pure SemIR through -/// the derived `patterns.toml`, so there is no hand-written Rust to install. -fn syntax_errors(source: &str) -> usize { - let lexer = CSharpLexer::new(InputStream::new(source)); - let tokens = CommonTokenStream::new(lexer); - let mut parser = CSharpParser::new(tokens); - parser.remove_error_listeners(); - let _ = parser - .compilation_unit() - .expect("entry rule must not hard-fail"); - parser.number_of_syntax_errors() -} - -#[test] -fn plain_class_parses_cleanly() { - assert_eq!(syntax_errors("class C { void M() { } }"), 0); -} - -#[test] -fn interpolated_string_parses_cleanly() { - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $"a{X}b"; } }"#), - 0 - ); -} - -#[test] -fn interpolation_hole_tracks_nested_braces() { - // The `}` of the collection initializer must NOT end the hole; only the - // outer one does. This is the case a single unconditional mode command - // cannot express, and the reason the rules are split and ordered. - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $"a{ new[]{1,2}.Length }b"; } }"#), - 0 - ); -} - -#[test] -fn escaped_braces_are_literal_text() { - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $"{{literal}}"; } }"#), - 0 - ); -} - -#[test] -fn interpolation_format_clause_is_not_code() { - // `D4` after the `:` is format text, not an identifier, so it needs its own - // lexer mode — entered by the `:` rule gated on brace depth 0. - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $"{v:D4}"; } }"#), - 0 - ); -} - -#[test] -fn nested_interpolated_strings_parse_cleanly() { - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $"outer {$"inner {x}"} end"; } }"#), - 0 - ); -} - -#[test] -fn verbatim_interpolated_string_keeps_backslash_literal() { - // In `$@"…"` a backslash is an ordinary character, so it must not start an - // escape. Needs a text mode distinct from the regular-string one. - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $@"a{X}\b"; } }"#), - 0 - ); -} - -#[test] -fn verbatim_interpolated_string_doubles_quotes() { - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $@"a""b{X}"; } }"#), - 0 - ); -} - -#[test] -fn nested_generics_close_with_adjacent_angle_brackets() { - // `>>` is emitted as two `>` tokens and rejoined in the parser behind - // `token_index_adjacent`, so a generic closer never lexes as a shift. - assert_eq!(syntax_errors("class C { List> F; }"), 0); -} - -#[test] -fn every_split_shift_operator_still_parses() { - // The other side of the same predicate: adjacent `>` `>` in expression position - // is a shift. All four spellings are split by the prep and rejoined behind - // `token_index_adjacent`, so each junction's predicate is exercised — `>>>=` - // carries two. - for expression in ["a >> b", "a >>> b", "a >>= b", "a >>>= b"] { - assert_eq!( - syntax_errors(&format!( - "class C {{ int M(int a, int b) {{ return {expression}; }} }}" - )), - 0, - "`{expression}` must parse" - ); - } -} - -#[test] -fn record_is_a_contextual_keyword() { - // Roslyn declares the keyword as ``, which its grammar generator - // drops; the prep restores it by minting a real `KW_RECORD` token and widening - // `identifier_token` with it, so `record` stays usable as an ordinary name. - assert_eq!(syntax_errors("record R(int X);"), 0); - assert_eq!(syntax_errors("class C { void M() { int record = 1; } }"), 0); - // An error count is NOT enough here: `record R(int X);` parsed with zero errors - // for a long time while producing a *method* named `R`. The tree shape is pinned - // in `mehen-csharp/tests/structure.rs`, which is where the space kinds are - // visible; this file can only assert parseability. -} - -#[test] -fn a_property_with_both_accessors_is_not_a_record() { - // The counterpart to the record fix: `record_declaration` sits ahead of - // `base_method_declaration` among `member_declaration`'s alternatives, so the - // record path must not be viable for an ordinary property. It is not, because - // `record_keyword` is a real token — with the earlier predicate form this shape - // was a hard error on 29 corpus files. - assert_eq!( - syntax_errors("struct S { public T P { readonly get => 1; set { } } }"), - 0 - ); -} - -#[test] -fn var_is_a_contextual_keyword() { - // The widened `identifier_token` must accept `var` as a name while - // `var_pattern` still recognizes it positionally. - assert_eq!(syntax_errors("class C { void M() { var x = 1; } }"), 0); - assert_eq!(syntax_errors("class C { void M() { int var = 1; } }"), 0); -} - -#[test] -fn discard_designation_parses() { - // `out _` was the one gap whose error recovery grew the runtime's - // diagnostic arena without bound; pinned so it cannot regress silently. - assert_eq!( - syntax_errors("class C { bool M(string p, out int n) => G(p, out n, out _); }"), - 0 - ); -} - -/// Whether any node in the tree is a `declaration_expression`. -/// -/// `F(x)` fits both `declaration_expression : type variable_designation` and -/// `invocation_expression : expression argument_list`, and the published grammar -/// lists the declaration form first — so every method call parsed as a -/// declaration, with zero reported errors. Error counts cannot catch that, hence -/// a shape assertion. -fn has_declaration_expression(source: &str) -> bool { - use antlr4_runtime::Node; - let lexer = CSharpLexer::new(InputStream::new(source)); - let mut parser = CSharpParser::new(CommonTokenStream::new(lexer)); - parser.remove_error_listeners(); - let tree = parser - .compilation_unit() - .expect("entry rule must not hard-fail"); - let parsed = parser.into_parsed_file(tree); - fn walk(node: Node<'_>) -> bool { - if node - .as_rule() - .is_some_and(|rule| rule.rule_index() == c_sharp_parser::RULE_DECLARATION_EXPRESSION) - { - return true; - } - node.children().any(walk) - } - walk(parsed.tree()) -} - -#[test] -fn invocations_are_not_declaration_expressions() { - for source in [ - "class C { void M() { F(x); } }", - "class C { void M() { a.B(); } }", - "class C { void M() { a.B(x).C(y); } }", - "class C { int M() { return F(x); } }", - ] { - assert!( - !has_declaration_expression(source), - "method call mis-parsed as a declaration expression: {source}" - ); - } -} - -#[test] -fn out_declarations_are_still_declaration_expressions() { - // The other side of the same reorder: where nothing else fits, the - // declaration form must still win. - assert!(has_declaration_expression( - "class C { void M() { F(out int x); } }" - )); -} - -#[test] -fn deeply_nested_holes_restore_the_enclosing_depth() { - // `holeStack` saves the enclosing hole's brace depth so an inner hole cannot - // clobber it. Without that, the outer `}` would be misread once the inner - // string had incremented the shared counter. - assert_eq!( - syntax_errors(r#"class C { void M() { var s = $"a{ $"b{ new[]{1}.Length }c" }d"; } }"#), - 0 - ); -} - -#[test] -fn the_entry_rule_consumes_the_whole_file() { - // REGRESSION. Roslyn's `compilation_unit` does not end in `EOF`, so the parser - // stopped at the first token it could not continue with and reported success on - // whatever it had consumed: `class C { } } } }` parsed with ZERO diagnostics and - // the stray braces were never looked at. For a metrics tool "parsed cleanly" has - // to mean the whole file was accounted for, so the prep anchors the entry rule. - assert!( - syntax_errors("class C { }\n} } }\n") > 0, - "an unconsumed tail must be a syntax error" - ); - assert!( - syntax_errors("class C { }\nelse { }\n") > 0, - "a dangling `else` is not a legal top-level member" - ); - // The tail has to be *lexable* and *not a legal member*. `syntax_errors` reports - // the PARSER's count, so unrecognizable characters (`@@@`) are dropped by the - // lexer before the parser sees them; and C# 9 top-level statements mean - // `return 1;` IS a legal `global_statement`, so it is no test of the anchor. -} - -#[test] -fn anchoring_does_not_reject_valid_files() { - // The counterpart: every legal top-level shape must still reach EOF cleanly, - // including the two that are not a plain sequence of type declarations. - for source in [ - "class C { void M() { } }\n", - "namespace N;\nclass C { }\n", - "using System;\nnamespace N { class C { } }\n", - "var x = 1;\n", - ] { - assert_eq!(syntax_errors(source), 0, "must parse: {source:?}"); - } -} - -#[test] -fn an_incomplete_member_is_a_syntax_error() { - // REGRESSION. `incomplete_member : attribute_list* modifier* type` is Roslyn's - // error-*recovery* node: it exists so the compiler can build a tree for source - // being typed, where `public int` is a member the author has not finished. Roslyn - // emits a diagnostic beside it; the published grammar carries only the node. So a - // syntax-only parser accepted `class C { int }` as a complete, error-free unit — - // which contradicts mehen's contract, where a clean parse is what tells - // `mehen metrics` to exit 0. The prep drops the alternative. - assert!(syntax_errors("class C { int }\n") > 0); - assert!(syntax_errors("class C { public int }\n") > 0); -} - -#[test] -fn dropping_incomplete_member_keeps_every_real_member_form() { - // Nothing legal may be lost: each real member form has its own rule, and the - // dropped alternative matched only a type with no declarator after it. - for source in [ - "class C { int x; }\n", - "abstract class C { public abstract void M(); }\n", - "interface I { void M(); }\n", - "class C { public int P { get; set; } }\n", - "class C { public int P { get; set; } = 5; }\n", - "class C { [System.Obsolete] public static readonly int X = 1; }\n", - "unsafe struct S { public fixed int data[4]; }\n", - "class C { public event System.EventHandler E; }\n", - ] { - assert_eq!(syntax_errors(source), 0, "must parse: {source:?}"); - } -} - -#[test] -fn a_switch_statement_requires_its_parentheses() { - // REGRESSION. Roslyn writes `switch_statement`'s parens as independently optional - // (`'switch' '('? expression ')'? '{' … '}'`), so `switch value { … }` — which is - // not valid C# — parsed without recovery and was reported as a clean analysis. The - // paren-free spelling belongs to the switch *expression*, a separate rule. - assert!(syntax_errors("class C { void M(int v) { switch v { default: break; } } }\n") > 0); -} - -#[test] -fn requiring_switch_parens_keeps_both_valid_forms() { - // The statement with parens, and the paren-free switch *expression*. - assert_eq!( - syntax_errors("class C { void M(int v) { switch (v) { default: break; } } }\n"), - 0 - ); - assert_eq!( - syntax_errors("class C { int M(int v) => v switch { _ => 0 }; }\n"), - 0 - ); -} - -/// Which of `statement`'s two overlapping alternatives claimed the method's -/// first statement: `Some(true)` for `local_declaration_statement`, -/// `Some(false)` for `expression_statement`, `None` for neither. -fn first_statement_is_declaration(source: &str) -> Option { - use antlr4_runtime::Node; - let lexer = CSharpLexer::new(InputStream::new(source)); - let mut parser = CSharpParser::new(CommonTokenStream::new(lexer)); - parser.remove_error_listeners(); - let tree = parser - .compilation_unit() - .expect("entry rule must not hard-fail"); - assert_eq!(parser.number_of_syntax_errors(), 0, "must parse: {source}"); - let parsed = parser.into_parsed_file(tree); - fn walk(node: Node<'_>) -> Option { - if let Some(rule) = node.as_rule() { - match rule.rule_index() { - c_sharp_parser::RULE_LOCAL_DECLARATION_STATEMENT => return Some(true), - c_sharp_parser::RULE_EXPRESSION_STATEMENT => return Some(false), - _ => {} - } - } - node.children().find_map(walk) - } - walk(parsed.tree()) -} - -#[test] -fn a_generic_local_declaration_is_not_an_expression_statement() { - // REGRESSION (#218). `statement`'s alternatives are alphabetical upstream, so - // `expression_statement` preceded `local_declaration_statement` — and - // `List l;` is viable as the chained comparison `(List < int) > l`, so - // ANTLR took the expression path with ZERO errors. Same ordering hazard as - // `declaration_expression` and the `member_declaration` hoists; the prep now - // hoists the declaration alternative. An error count cannot catch this, hence - // the shape assertion. The metric consequences are pinned in - // `mehen-csharp/tests/{abc,loc}.rs`. - for source in [ - "class C { void M() { List l; } }", - "class C { void M() { List l = new(); } }", - "class C { void M() { System.Span s = stackalloc int[4]; } }", - "class C { void M() { Dictionary> map = new(); } }", - "class C { void M() { string? s = null; } }", - ] { - assert_eq!( - first_statement_is_declaration(source), - Some(true), - "must be a local_declaration_statement: {source}" - ); - } -} - -#[test] -fn statement_expressions_still_win_where_no_declaration_fits() { - // The other side of the hoist: every legal statement-expression shape - // (invocation, creation, assignment, increment/decrement, qualified await) - // is not viable as `type declarator ;`, so the declaration path must die in - // prediction and leave each an expression statement. The indexed await is - // here because locals get a bracket-less declarator: without that split, - // `tasks[i]` would match the fixed-size-buffer declarator shape and the - // statement would read as a declaration of `tasks[i]` with type `await`. - for source in [ - "class C { void M() { F(x); } }", - "class C { void M(int i) { i = 1; } }", - "class C { void M(int i) { i++; } }", - "class C { void M() { new C(); } }", - "class C { void M() { obj.Method(1); } }", - "class C { async System.Threading.Tasks.Task M() { await x.RunAsync(); } }", - "class C { async System.Threading.Tasks.Task M() { await tasks[i]; } }", - ] { - assert_eq!( - first_statement_is_declaration(source), - Some(false), - "must be an expression_statement: {source}" - ); - } -} - -#[test] -fn the_hoists_residual_trade_is_a_bare_await_operand() { - // The DELIBERATE residual of the hoist, pinned so it stays a decision rather - // than drifting: `await t;` with a bare identifier operand is genuinely - // ambiguous — outside an async method it is a valid declaration of a local - // `t` whose type is named `await`, and Roslyn picks the await expression only - // by asking whether the enclosing method is async, which a syntax-only - // grammar cannot. The hoist resolves it to the declaration, exactly as it - // would for any `T t;`. A declarator cannot be qualified, called, or indexed - // (locals get the bracket-less declarator), so every other await operand - // shape stays an expression — asserted above. - assert_eq!( - first_statement_is_declaration( - "class C { async System.Threading.Tasks.Task M() { await t; } }" - ), - Some(true), - "the documented trade: a bare await operand reads as a declaration" - ); -} - -#[test] -fn a_local_declarator_has_no_fixed_size_buffer_form() { - // The split that keeps `await tasks[i];` an expression must not reach field - // position: `fixed int data[4];` is the fixed-size-buffer declarator, legal - // only as a struct field, and it keeps the bracketed `variable_declarator`. - assert_eq!( - syntax_errors("unsafe struct S { public fixed int data[4]; }"), - 0 - ); - // In statement position the bracketed form is not valid C# (CS0650), and the - // declaration path can no longer take it. It still parses silently — the - // permissive expression hub reads `int buf` as a declaration_expression and - // `[4]` as an element access, and tightening that is not worth carving up - // the inlined expression cycle for input no compiler accepts — but the - // assertion pins the mechanism: statement-position declarators are - // bracket-less. - assert_eq!( - first_statement_is_declaration("class C { void M() { int buf[4]; } }"), - Some(false), - "a bracketed declarator must not reach the local declaration path" - ); -} diff --git a/crates/mehen-csharp/Cargo.toml b/crates/mehen-csharp/Cargo.toml deleted file mode 100644 index c4831061..00000000 --- a/crates/mehen-csharp/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "mehen-csharp" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — C# language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -# The generated C# lexer/parser (plus the hand-written `CSharpLexerBase` hooks -# the grammar's `superClass` requires) live in the standalone, publishable -# `mehen-csharp-parser` crate, produced by `cargo xtask antlr generate csharp`. -# This analyzer depends on it for the grammar and reaches the ANTLR runtime -# through its `antlr4_runtime` re-export. -mehen-csharp-parser = { workspace = true } -# `mehen-antlr` owns the runtime version pin and the shared span/comment/ -# diagnostic helpers; the walker reaches the runtime types (`Node`, -# `RuleNodeView`, `TokenView`, …) through its `runtime` re-export. -mehen-antlr = { workspace = true } -smol_str = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-csharp/src/lib.rs b/crates/mehen-csharp/src/lib.rs deleted file mode 100644 index ab9080bf..00000000 --- a/crates/mehen-csharp/src/lib.rs +++ /dev/null @@ -1,306 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-csharp` — C# language analyzer. -//! -//! C# is parsed by a parser derived from **Roslyn's own published grammar** -//! (`CSharp.Generated.g4`, vendored in `crates/mehen-csharp-parser/grammar/`), -//! running on the ANTLR Rust runtime via [`mehen_antlr`]. Roslyn generates that -//! grammar from `Syntax.xml` — the same model that generates the compiler's syntax -//! node classes — so it tracks **C# as implemented**: records, `is not`, `and`/`or` -//! and relational patterns, list patterns, collection expressions, raw strings, -//! primary constructors, `required` members, and the C# 14 additions (`field`, -//! extension blocks). No community grammar does. -//! -//! Rules are named after the compiler's syntax nodes (`class_declaration`, -//! `property_declaration`, `switch_expression_arm`, `simple_lambda_expression`, …), -//! which is what makes the walker's classification a `rule_index()` match rather -//! than a keyword probe. See [`walker`] for the shape's consequences. -//! -//! The generated lexer/parser modules live in the separate [`mehen_csharp_parser`] -//! crate, produced by `cargo xtask antlr generate csharp` and checked in verbatim. -//! Both recognizers are constructed plainly — `CSharpLexer::new`, -//! `CSharpParser::new` — because that crate ships **no hooks at all**: every -//! semantic coordinate lowers to pure SemIR through the derived `patterns.toml`, -//! and the interpolated-string brace bookkeeping lives in the grammar's own -//! `@lexer::members`. -//! -//! Metric coverage follows SonarC#'s definitions where they exist; see [`walker`] -//! for the per-metric table. -//! -//! # What the transform repairs, and what remains -//! -//! Roslyn's grammar is a **reference** grammar rather than a working parser: ANTLR -//! rejects it outright (empty rules for its "omitted" syntax nodes), it publishes -//! no lexer at all (terminals are character-level *parser* rules), and it is -//! permissive by design — it models syntax nodes including error-recovery ones, and -//! encodes no operator precedence. `prepare-grammar.py` repairs that as a step of -//! parser generation. -//! -//! The catalogue lives in `crates/mehen-csharp-parser/grammar/PROVENANCE.md`, with -//! the measured effect of each repair. Two things worth knowing here: -//! -//! - **A clean parse measures parseability, not correctness.** Twenty-seven distinct -//! *silent misparses* have come out of this grammar — structurally wrong trees -//! with zero reported errors — each caught by a metric test or a parse-tree dump, -//! never by an error count. That is why the per-language tests assert numbers -//! against an equivalent spelling rather than just checking for diagnostics: two of -//! the twenty-seven hid behind a passing test whose input happened to use the one -//! spelling that parses correctly. -//! - **One known limitation remains:** a preprocessor directive that splits a -//! single expression across `#if` branches (a return type, say) yields two -//! partial expressions where one belongs. Five of 322 files in the -//! `System.Text.Json` corpus hit it; they carry `csharp.syntax_error` and their -//! metrics near the split are approximations. - -#![forbid(unsafe_code)] - -mod walker; - -use mehen_antlr::DiagnosticCollector; -use mehen_antlr::runtime::ParsedFile; -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, LineIndex, - ParseDiagnostic, Result, SourceFile, SourceSpan, byte_offset_clamped, -}; -use mehen_metrics::MetricEvidence; - -use mehen_csharp_parser::c_sharp_lexer::CSharpLexer; -use mehen_csharp_parser::c_sharp_parser; - -pub struct CSharpAnalyzer; - -/// A recovered parse: the flat-arena [`ParsedFile`] owns the token store and -/// CST storage, and the walker borrows [`Node`](mehen_antlr::runtime::Node) -/// views from it. `loc_tokens` is precomputed from the (eagerly buffered, -/// hidden-channel-inclusive) token store. -struct ParsedCSharp { - parsed: ParsedFile, - lexer_diagnostics: Vec, - loc_tokens: Vec, -} - -impl CSharpAnalyzer { - pub fn new() -> Self { - Self - } - - /// Parse `source` via the single `compilation_unit` entry rule and return - /// the recovered [`ParsedFile`] plus the source-ordered LOC token list. - /// Returns `None` only if the rule call hard-fails (returns `Err` rather - /// than a recovered tree). - /// - /// Both recognizers are constructed plainly (`CSharpLexer::new`, - /// `CSharpParser::new`): the derived grammar needs no hooks. Its - /// interpolated-string state lives in `@lexer::members` and every action and - /// predicate lowers to pure SemIR through the derived `patterns.toml`, so - /// there is no hand-written Rust to install. - /// - /// Setup goes through the generated [`c_sharp_parser::parse_with_parser`] - /// driver (runtime 0.33): its lexer closure swaps the runtime's default - /// console listener for a structured diagnostic collector, and its entry - /// closure removes the parser console listener before running the rule. - fn parse(&self, source: &str, line_index: &LineIndex) -> Option { - // No hooks: the derived grammar keeps its interpolated-string state in - // `@lexer::members`, lowered to pure SemIR via `patterns.toml`. - let lexer_diagnostics = DiagnosticCollector::default(); - let out = c_sharp_parser::parse_with_parser( - source, - |input| { - let mut lexer = CSharpLexer::new(input); - lexer.remove_error_listeners(); - lexer.add_error_listener(lexer_diagnostics.clone()); - lexer - }, - |parser| { - parser.remove_error_listeners(); - parser.compilation_unit() - }, - ) - .ok()?; - let lexer_diagnostics = - lexer_diagnostics.diagnostics("csharp.syntax_error", 16, line_index); - - // `into_parsed_file` consumes the parser and moves the eagerly-buffered - // token store into the `ParsedFile`; the LOC token list is then read - // straight from that store (all channels, so hidden-channel comments - // are present — no `fill()` step needed). - let parsed = out.parser.into_parsed_file(out.result); - let loc_tokens = collect_loc_tokens(&parsed, line_index); - Some(ParsedCSharp { - parsed, - lexer_diagnostics, - loc_tokens, - }) - } -} - -impl Default for CSharpAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for CSharpAnalyzer { - fn language(&self) -> Language { - Language::CSharp - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::Antlr - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - // `with_unicode_separators`, not `new`: this grammar's lexer treats NEL, - // U+2028, and U+2029 as line terminators (ECMA-334 §6.3.1), so they are real row - // breaks here. The default policy is LF/CRLF-only because every - // tree-sitter-backed analyzer's row source counts only LF, and an index that - // disagrees with the parser produces spans the walker never routes tokens to. - let line_index = LineIndex::with_unicode_separators(&source.text); - - let parsed = match self.parse(&source.text, &line_index) { - Some(parsed) => parsed, - None => { - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: line_index.line_count(), - }; - return Ok(LanguageAnalysis { - language: Language::CSharp, - backend: AnalysisBackend::Antlr, - diagnostics: vec![ParseDiagnostic::fatal( - "csharp.parse_error", - "csharp ANTLR parse failed".to_string(), - )], - root: mehen_antlr::empty_space(span), - contributions: Vec::new(), - }); - } - }; - - // The `ParsedFile` owns the token store and CST; `tree()` is the root - // `Node` borrowing view the walker traverses. - let tree = parsed.parsed.tree(); - let mut evidence = MetricEvidence::new("csharp", config.emit_contributions); - let root = walker::walk( - tree, - &line_index, - source.text.len(), - &parsed.loc_tokens, - &mut evidence, - ); - - // Recovered ANTLR error nodes are surfaced as `error` so the - // diagnostic contract treats the analysis as incomplete. - let mut diagnostics = parsed.lexer_diagnostics; - let remaining = 16usize.saturating_sub(diagnostics.len()); - diagnostics.extend(mehen_antlr::collect_errors( - tree, - "csharp.syntax_error", - remaining, - &line_index, - )); - - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::CSharp, - backend: AnalysisBackend::Antlr, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} - -/// Classify the parsed file's token store into the source-ordered LOC token -/// list that drives the LOC family. -/// -/// C# comments come in four token types here: the two doc-comment forms (`///` -/// and `/** */`) plus the plain `//` and `/* */` forms. Whitespace is -/// `WHITESPACES` and a leading BOM is `BYTE_ORDER_MARK`; neither is code. -/// -/// A preprocessor directive (`DIRECTIVE_LINE`) is **code**, not trivia. mehen does -/// not evaluate `#if` — directives go to their own channel so the parser never sees -/// them, and an inactive region is parsed as ordinary code (see the LOC tests) — -/// but the directive row itself is still a physical line carrying source text. It is -/// deliberately not a *logical* line (`#endif` is not a statement) and not a -/// comment, so leaving it out of PLOC entirely made it fall through to -/// `blank = sloc - ploc - only_comment` and report as a blank line, which it plainly -/// is not. -/// -/// Unlike Kotlin, C# has no trivia-folding operator tokens, so no trivia-bearing -/// token scan is needed. The token store is eagerly buffered through EOF, so every -/// token (all channels) is present. -fn collect_loc_tokens(parsed: &ParsedFile, line_index: &LineIndex) -> Vec { - use mehen_csharp_parser::c_sharp_lexer::{ - BYTE_ORDER_MARK, DELIMITED_COMMENT, DELIMITED_DOC_COMMENT, SINGLE_LINE_COMMENT, - SINGLE_LINE_DOC_COMMENT, WHITESPACES, - }; - - mehen_antlr::loc_tokens( - parsed.tokens(), - &[ - SINGLE_LINE_COMMENT, - DELIMITED_COMMENT, - SINGLE_LINE_DOC_COMMENT, - DELIMITED_DOC_COMMENT, - ], - &[WHITESPACES, BYTE_ORDER_MARK], - &[], - line_index, - ) -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, Language, SourceFile, SpaceKind}; - - fn analyze(source: &str, path: &str) -> LanguageAnalysis { - let analyzer = CSharpAnalyzer::new(); - let file = SourceFile::new(path.into(), Language::CSharp, source.to_string()); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() - } - - #[test] - fn empty_file_yields_root_unit() { - let a = analyze("", "Empty.cs"); - assert_eq!(a.root.kind, SpaceKind::Unit); - assert!(a.root.spaces.is_empty()); - } - - #[test] - fn class_with_method_parses_cleanly() { - let src = - "namespace Demo\n{\n class C\n {\n int M() { return 1; }\n }\n}\n"; - let a = analyze(src, "C.cs"); - assert!( - a.diagnostics.is_empty(), - "compilation unit should parse cleanly, got {}", - a.diagnostics.len() - ); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("C")); - } - - #[test] - fn interpolated_string_parses_cleanly() { - // Interpolation is the grammar's most stateful construct — three lexer - // modes plus a brace-depth stack — and all of it lowers to SemIR, so this - // is the case that would fail loud (`--sem-unknown error`) if a lowering - // regressed. - let src = "class C { string M(int x) { return $\"a{x}b\"; } }\n"; - let a = analyze(src, "C.cs"); - assert!( - a.diagnostics.is_empty(), - "interpolated string should lex/parse cleanly, got {:?}", - a.diagnostics - ); - } -} diff --git a/crates/mehen-csharp/src/walker.rs b/crates/mehen-csharp/src/walker.rs deleted file mode 100644 index a15c7910..00000000 --- a/crates/mehen-csharp/src/walker.rs +++ /dev/null @@ -1,3196 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ANTLR-based C# metric walker. -//! -//! Drives a recursive descent over the ANTLR `ParseTree` (entry rule -//! `compilation_unit`) and produces a populated [`MetricSpace`]. The structure -//! mirrors the `mehen-java` / `mehen-kotlin` walkers — one [`State`] per space, -//! finalize-and-merge on close, with the parent-less ANTLR tree handled by -//! threading context **top-down**. -//! -//! ## Grammar shape -//! -//! The parser is derived from Roslyn's own published grammar (see -//! `mehen-csharp-parser/grammar/PROVENANCE.md`), which names rules after the -//! compiler's *syntax nodes*. Three consequences shape every classification here: -//! -//! - **Each statement form is its own rule.** `if_statement`, `while_statement`, -//! `switch_statement`, `catch_clause`, `else_clause`, … so control flow is -//! dispatched on `rule_index()`. That is also more precise than the keyword -//! probing the previous grammars-v4 grammar required: a `has_token(IF)` test on -//! a shared `simple_embedded_statement` fires for an `if` anywhere in the node, -//! whereas a rule match cannot. -//! - **Each declaration carries its own `attribute_list* modifier*`.** So a -//! member's span already covers its attributes, and its visibility is readable -//! on the declaration itself — no wrapper rule to open the space at, no span -//! widening, and no threading of resolved visibility down a wrapper chain. -//! - **The expression cycle is inlined.** Roslyn's `expression` participates in a -//! mutual left-recursion cycle, and the generator's hub inlining (upstream -//! #221) folds 16 of 17 satellites into it — so `invocation_expression`, -//! `assignment_expression`, `binary_expression`, and `conditional_expression` -//! have no rule index of their own. They are classified by *shape* through the -//! typed `ExpressionContext`: one `expression` child plus an `argument_list` is -//! an invocation, two children a binary/assignment, three a ternary. -//! -//! ## Typed contexts -//! -//! Navigation uses the generated typed contexts, whose accessors reach only a -//! rule's *declared direct children* — the property the untyped `child_rule` / -//! `has_token` probes could assert only by comment. Dispatch stays on -//! `rule_index()`, since a metric walker is fundamentally one match over rule -//! kinds. This mirrors `mehen-java` and `mehen-kotlin`. -//! -//! ## Metric coverage (SonarC#-aligned) -//! -//! - **Cyclomatic**: `if`, every loop (`while`/`do`/`for`/`foreach`), each -//! `case` label, each switch-*expression* arm, the ternary `?:`, each -//! short-circuit `&&`/`||`, and each `and`/`or` pattern combinator. `catch`, -//! `switch` itself, `default:`, and a `_` arm are not decisions (matches SonarC#, -//! which follows the same rule as SonarJava; `catch` counts only in cognitive). -//! A switch expression scores exactly like the equivalent switch statement — -//! rewriting one into the other must not move the number. -//! - **Cognitive**: nesting on `if`, loops, `switch` (statement *and* expression), -//! `catch`, and the ternary; flat `+1` on `else`/`else if` and on `goto`; a -//! sequence-collapsing boolean run on `&&`/`||` and on the `and`/`or` pattern -//! combinators (+1 per operator-kind change, reset per statement and per call -//! argument, matching SonarSource). `try` and `lock` add nothing — the spec -//! increments on the *handler* (`catch`), not the guarded block, and `lock` is not -//! an increment at all. -//! - **ABC**: assignments via the assignment-shaped `expression` (all -//! `=`/compound/`??=` forms), `++`/`--`, and any initialized declarator; -//! branches via every invocation-shaped `expression`, object creation, and -//! `constructor_initializer` (NOT member access — that is qualification, not a -//! call, so a qualified call still scores exactly one branch; and NOT `nameof`, -//! which only has the invocation *shape*); conditions via -//! `if`/`case`/`catch`/`when`/loops/comparison & equality/`&&`/`||`/ternary/ -//! `??`/`is`/`as`/`and`/`or`. An `operator_declaration`'s own symbol is excluded — -//! `operator ++` declares an operator rather than applying one. -//! -//! **Known gap:** null-conditional access (`a?.B`, `a?[i]`) records nothing. It -//! arguably should be a condition — it short-circuits on null exactly as `??` does, -//! and `??` counts — but there is no reliable anchor for it in this tree. Hub -//! inlining scatters the `?` onto an inner `expression` node holding only the -//! receiver, and `member_binding_expression`/`element_binding_expression` are -//! inlined too, so neither the token nor a rule index identifies the construct. -//! Every candidate match tried fired on chained `a?.B?.C` but not on a single -//! `a?.B`, which is worse than counting neither. -//! -//! `<` and `>` need care, because C# spells three unrelated things with them and -//! only the enclosing rule tells them apart. A comparison counts; the other two -//! do not, and each has its own hint: -//! - a **shift** — the prep spells `>>` as adjacent `>` tokens rejoined in the -//! parser (so a generic closer is never mis-lexed as a shift), which means a -//! shift reaches the token scan as two bare `GT` tokens -//! (`ChildHint::in_shift_operator`); -//! - a **generic or function-pointer delimiter** — `List` would otherwise -//! score two conditions, and `Dictionary>` four -//! (`ChildHint::in_type_delimiter`). -//! - **NExit**: `return_statement`, `throw_statement`, `throw_expression`, and -//! `yield_statement` (both `yield return` and `yield break`). -//! - **NArgs**: the `parameter` count of a `parameter_list` / -//! `bracketed_parameter_list`. Roslyn uses one `parameter` rule for every -//! position — methods, operators, lambdas, anonymous methods alike — with -//! `params` as a modifier rather than a distinct rule. -//! - **NOM**: every `method_declaration`, `constructor_declaration`, -//! `destructor_declaration`, `operator_declaration`, -//! `conversion_operator_declaration`, `local_function_statement`, and -//! `accessor_declaration` (one rule covers get/set/init/add/remove) is a -//! function space; `simple_lambda_expression`, -//! `parenthesized_lambda_expression`, and `anonymous_method_expression` are -//! closure-shaped function spaces. -//! - **LOC**: PLOC from per-space code-token rows during the walk, LLOC from -//! statement/declaration-shaped rules, CLOC from a source-ordered pass over the -//! hidden-channel comment tokens routed via `SpaceRangeTracker`. Preprocessor -//! directives are routed through that same post-walk pass: they are on their own -//! channel, so the tree walk never sees them, but a `#if` row still carries source -//! text and must count as PLOC rather than falling out as a phantom blank. -//! - **Halstead**: per-token operator/operand classification — keywords and -//! punctuation are operators; identifiers, literals, `this`, `base` are -//! operands (deduped by text). A terminal reached through `identifier_token` is -//! always an operand, which is what makes C#'s contextual keywords come out -//! right: the prep widens that rule to accept all 42 of them. C# 14's contextual -//! `field` is an operand for the same reason `this` is — in expression position it -//! references the synthesized backing field. The UTF-8 literal suffix (`"text"u8`) -//! contributes *nothing*: real C# lexes the whole thing as one literal, so the -//! preceding `STRING_LIT` already recorded the operand and the split-off suffix -//! would double it. -//! - **NPA / NPM / WMC**: class-vs-interface routing by the declaration rule -//! (`struct` and `record` count as class-like containers; `interface` as an -//! interface). NPA counts `field_declaration` / `event_field_declaration` -//! declarators, named `event_declaration`s, and `enum_member_declaration`s -//! directly under a type body. NPM counts methods/constructors/operators/ -//! properties/indexers directly under a type body. C# visibility: a type -//! member with no access modifier is `private` (NOT public), so only an -//! explicit `public` counts toward NPA/NPM; interface members are implicitly -//! public. `enum` members are implicitly public. - -use mehen_antlr::runtime::token::Token; -use mehen_antlr::runtime::{FromRuleNode, Node, RuleNodeView, TerminalNodeView}; -use mehen_antlr::{LocToken, LocTokenKind, ctx_span, span_from_tokens}; -use mehen_core::{LineIndex, MetricSpace, SourceSpan, SpaceKind}; -use mehen_metrics::{ - ContainerKind, HalsteadOperand, HalsteadOperator, MetricEvidence, MetricTreeBuilder, - SpaceRangeTracker, State, apply_state_to, finalize_state, merge_child_into_parent, -}; -use smol_str::SmolStr; - -use mehen_csharp_parser::c_sharp_lexer as cl; -use mehen_csharp_parser::c_sharp_parser as cp; -// Typed contexts, used for *navigation* — their accessors reach only a rule's -// declared direct children, which is the property the untyped `child_rule` / -// `has_token` probes could only assert by comment. Dispatch stays on -// `rule_index()`: a metric walker is fundamentally one match over rule kinds. -use mehen_csharp_parser::c_sharp_parser::{ - ExpressionContext, OperatorDeclarationContext, PatternContext, SwitchExpressionArmContext, -}; - -/// Drive the walk over the parsed `compilation_unit` tree and return the unit -/// `MetricSpace`. LOC is computed from `loc_tokens` in a single ordered pass -/// *after* the tree walk has opened and closed every space. Contribution -/// evidence is recorded into the caller-owned `evidence` sink (plan §5.4). -pub(crate) fn walk( - tree: Node<'_>, - line_index: &LineIndex, - source_len: usize, - loc_tokens: &[LocToken], - evidence: &mut MetricEvidence, -) -> MetricSpace { - let unit_span = match tree.as_rule() { - Some(rule) => ctx_span(rule, line_index, source_len), - None => mehen_core::SourceSpan::empty(), - }; - - let mut unit_state = State::new(); - unit_state - .loc - .set_span(0, line_index.line_count().saturating_sub(1), true); - - let mut walker = Walker { - line_index, - source_len, - tree: MetricTreeBuilder::new(unit_span), - stack: vec![unit_state], - kinds: vec![SpaceKind::Unit], - suppress_parent_wmc: vec![false], - cognitive: CognitiveContext::default(), - primary_ctor_close: None, - loc_routing: SpaceRangeTracker::new(), - evidence, - }; - - if let Some(rule) = tree.as_rule() { - for child in rule.children() { - walker.visit(child, &ChildHint::default()); - } - } - - let mut unit_state = walker.stack.pop().expect("walker stack underflow"); - - // CLOC pass: route each comment to the deepest enclosing space (or the - // unit) in source order (mirrors `mehen-java`/`mehen-kotlin`). - // - // Preprocessor directives are routed here as well, and only here. PLOC is - // otherwise recorded during the tree walk (`visit_terminal`), which cannot see - // them: a directive goes to its own channel, so it never reaches the parser and - // never appears as a terminal. Without this pass a `#if` / `#define` / `#endif` - // row carried no PLOC observation and fell out as - // `blank = sloc - ploc - only_comment` — reported as a blank line despite - // plainly carrying source text. - for t in loc_tokens { - match t.kind { - LocTokenKind::Comment => walker.loc_routing.observe_comment( - t.start_byte, - t.end_byte, - &mut unit_state.loc, - t.start_row, - t.end_row, - ), - // Only the off-channel tokens need this; an ordinary code token was - // already observed during the walk, and `observe_code_line` inserts into - // a row set, so a repeat is idempotent rather than double-counted. - LocTokenKind::Code => walker.loc_routing.observe_code_line( - t.start_byte, - t.end_byte, - &mut unit_state.loc, - t.start_row, - ), - } - } - - finalize_state(&mut unit_state); - - let mut root = walker.tree.finish(); - let mut unit_halstead = std::mem::take(&mut unit_state.halstead); - let mut unit_loc = std::mem::take(&mut unit_state.loc); - walker - .loc_routing - .finalize_into_tree(&mut root, &mut unit_halstead, &mut unit_loc); - unit_state.halstead = unit_halstead; - unit_state.loc = unit_loc; - apply_state_to(unit_state, &mut root.metrics); - root -} - -/// Per-frame cognitive context — the `(nesting, depth, lambda)` triple used -/// exactly as the Java/Kotlin walkers use it. -#[derive(Clone, Copy, Debug, Default)] -struct CognitiveContext { - nesting: u32, - depth: u32, - lambda: u32, -} - -/// Context threaded *down* into a child during the walk (ANTLR contexts have -/// no parent pointer). -/// -/// `Clone` (not `Copy`): `accessor_owner` carries an owned name so a property's -/// accessors can be named after it. Cloning a `SmolStr` is a cheap refcount -/// bump / inline copy, so threading the hint per child stays allocation-free in -/// the common case. -#[derive(Clone, Debug, Default)] -struct ChildHint { - /// This `if_body`/`embedded_statement` is the `else`-branch body of an - /// enclosing `if`. An `if` reached through this hint is an `else if` and - /// must not add cognitive nesting (only the flat `else` +1 applies). - is_else_branch: bool, - /// This node is a direct member position of the enclosing type body, so - /// NPA/NPM should consider it. - in_type_member: bool, - /// The container kind of the enclosing type body, so a member's counters - /// route to class-vs-interface buckets and inherit the - /// interface-default-public rule. - member_container: Option, - /// The member's resolved visibility, captured at the member-declaration - /// wrapper (`class_member_declaration: attributes? all_member_modifiers? - /// (…)`) where the modifiers are siblings of the inner declaration — the - /// declaration itself has no parent pointer and does not carry them. - /// `None` outside a member position. - member_is_public: Option, - /// This terminal is the token of an `identifier` rule. C#'s contextual - /// keywords (`var`, `async`, `await`, `get`, `set`, `value`, `when`, - /// `where`, `from`, `select`, `nameof`, …) lex as dedicated token types but - /// are identifiers in name position, so a terminal reached through this - /// hint is a Halstead *operand* regardless of its token type (mirrors the - /// Java walker's `identifier` handling). - in_identifier: bool, - /// We are inside an `attributes` list (`[Obsolete("x")]`). Attribute - /// arguments are compile-time metadata, not executable code, so - /// cyclomatic/cognitive/ABC accounting is suppressed for the whole subtree - /// (LOC/Halstead still count — the tokens physically exist). - in_attributes: bool, - /// This terminal belongs to a `right_shift` / `unsigned_right_shift` rule, so - /// its bare `>` tokens are half a shift operator rather than comparisons. - /// - /// The prep spells `>>` as adjacent `>` tokens rejoined in the parser (so a - /// generic closer is never mis-lexed as a shift), which means a *shift* now - /// presents to the token scan as two `GT` tokens. Only the enclosing rule - /// tells them apart. - in_shift_operator: bool, - /// This terminal is a `<`/`>` used as a *delimiter* — a generic argument or - /// parameter list, or a function-pointer signature — not a comparison. - /// - /// C# spells all three with the same `LT`/`GT` tokens it uses for relational - /// operators, so `List f;` would otherwise score two ABC conditions and - /// two Halstead comparison operators. `Dictionary>` would - /// score four. Only the enclosing rule distinguishes them, exactly as for - /// [`ChildHint::in_shift_operator`]. - /// - /// This is deliberately NOT merged with `in_shift_operator`: a shift's `>` - /// tokens are suppressed at the token scan and the operator is recorded once - /// at its rule, whereas a delimiter is not an operator at all and is dropped - /// outright. - in_type_delimiter: bool, - /// This node is inside an `accessor_declaration`'s body. An accessor opens a - /// metric space but is not itself a logical line, so an expression-bodied - /// accessor (`get => _x;`) has nothing else to make its space non-empty — - /// [`Walker::classify_loc_rule`] counts the `arrow_expression_clause` for it. - /// Every other expression body hangs off a declaration that is already - /// counted, where counting the clause too would double. - in_accessor_body: bool, - /// We are inside a creation expression, so a nested `initializer_expression` is - /// that creation's element list rather than an allocation of its own. - /// - /// A brace-only array initializer (`int[] v = { 1, 2 };`) IS an allocation — Roslyn - /// represents the right-hand side as a bare `initializer_expression`, so nothing in - /// the creation list fired and it scored no ABC branch while `new[] { 1, 2 }` and - /// `[1, 2]` each scored one. But `new[] { 1, 2 }` *nests* an initializer inside the - /// creation, so counting the rule unconditionally would score that twice. This flag - /// marks the nested position. - in_creation_expression: bool, - /// The enclosing member returns a *value*, so an expression body is a return. - /// - /// `int F() => 1;` has no `return_statement` node, so NExit stayed 0 while the - /// equivalent `int F() { return 1; }` reported 1 — and NExit's own documentation - /// includes value-returning expressions. Set on a member whose declared return type - /// is not `void`, plus getters and lambdas (a `get` accessor and a lambda body both - /// yield a value by construction); cleared on a `void` member, a constructor, a - /// destructor, and a `set`/`add`/`remove` accessor, none of which return anything. - /// - /// Read at `arrow_expression_clause`, which is the node that *is* the return. - returns_value: bool, - /// The declared name of the enclosing property / indexer / event, threaded - /// down so a `get`/`set` accessor space can be named `Prop.get` rather than - /// anonymous. - /// - /// (No `member_decl_start` or `space_opened_by_wrapper` here: Roslyn puts - /// `attribute_list* modifier*` directly on each declaration, so a member's - /// own span already covers its attributes and there is no wrapper to open the - /// space at. Both fields existed only for the grammars-v4 shape.) - accessor_owner: Option, - /// This terminal is the operator symbol in an `operator_declaration`'s - /// signature — the operator being *declared*, not one being applied. - /// - /// Roslyn spells the symbol as a direct token choice on the declaration - /// (`… KW_OPERATOR KW_CHECKED? (PLUS | PLUS_PLUS | AMP_AMP | LT | …)`), so those - /// tokens reach the scan looking exactly like real operators: `operator ++` - /// recorded an ABC assignment, and `operator &&` / `operator <` would have - /// recorded a decision and a comparison. Set only for the declaration's own - /// direct terminals, so the body and parameter defaults still count normally. - in_operator_symbol: bool, - /// The NArgs an accessor of the enclosing member takes: the *indexer*'s - /// parameter count (`this[int i]`'s getter is a one-argument function), or 0 for - /// a property or event. - /// - /// `accessor_declaration` carries no parameter list of its own, so the count has - /// to come from the owner. Without it, NArgs for the same indexer depended on - /// body syntax — the expression-bodied form opens its space at - /// `indexer_declaration`, where the list is present, and reported 1 where the - /// block-bodied form reported 0. - accessor_args: u32, - /// This literal carries a UTF-8 suffix (`"text"u8`), so its operand key must include - /// it: `"text"u8` is a `ReadOnlySpan` while `"text"` is a `string`, so they are - /// two operands even though the literal token's text is identical. Keying on the text - /// alone collapsed them into one, undercounting vocabulary and volume. - /// - /// Set at the `utf8_*_literal_token` wrapper, which is the only place both the literal - /// and the suffix are visible — they are sibling terminals, so neither can see the - /// other. The suffix terminal itself still contributes nothing, so one C# literal - /// remains one operand *occurrence*. - in_utf8_literal: bool, - /// The enclosing type's name, set on the direct children of a declaration that - /// carries a **primary constructor** (`class C(int x)`), marking the - /// `parameter_list` child as the constructor's own declaration so - /// `classify_loc_rule` counts its logical line. - /// - /// The synthetic space itself is opened by the *parent's* child loop in - /// `visit_children` — not per rule — because it has to stay open from the - /// `parameter_list` through the `base_list`: Roslyn synthesizes no - /// `constructor_declaration` node, so those two siblings together are the whole - /// of the constructor (parameters plus base-constructor call). - /// - /// `None` on any other node, which is what keeps a `delegate_declaration`'s or - /// `extension_block_declaration`'s parameter list — neither of which constructs - /// anything — from minting a constructor. - primary_ctor_name: Option, -} - -struct Walker<'a> { - line_index: &'a LineIndex, - source_len: usize, - tree: MetricTreeBuilder, - stack: Vec, - kinds: Vec, - /// Parallel to `stack`/`kinds`: whether the closing function space must NOT - /// contribute its cyclomatic to the parent's WMC. Set for local functions - /// and lambdas, whose complexity belongs to the enclosing method (already - /// counted there), not as a separate weighted method of the class. - suppress_parent_wmc: Vec, - cognitive: CognitiveContext, - /// A primary constructor's synthetic space is open and must close *inside* - /// the enclosing `base_list`, right after the base-call `base_type` — see - /// the close handoff in [`Walker::visit_children`]. Carries the enclosing - /// (type-scope) cognitive context to restore on close. `None` whenever no - /// such close is pending. - primary_ctor_close: Option, - loc_routing: SpaceRangeTracker, - /// Contribution-evidence sink (plan §5.4). All record methods are no-ops - /// when disabled, so classification sites call them unconditionally next - /// to each stat increment — usually through [`Walker::record_evidence`] / - /// [`Walker::record_token_evidence`], which also skip the span computation - /// when the sink is off. - evidence: &'a mut MetricEvidence, -} - -impl Walker<'_> { - fn current(&mut self) -> &mut State { - self.stack.last_mut().expect("walker stack empty") - } - - /// Record contribution evidence spanning a rule node. Skips the span - /// computation entirely when the sink is disabled, so call sites can - /// invoke this unconditionally next to the stat increment: - /// - /// ```ignore - /// self.current().cyclomatic.record_decision(); - /// self.record_evidence(ctx, |e, s| e.decision(s, rule_name(ri))); - /// ``` - #[inline] - fn record_evidence(&mut self, ctx: RuleNodeView<'_>, record: F) - where - F: FnOnce(&mut MetricEvidence, SourceSpan), - { - if self.evidence.is_enabled() { - let span = ctx_span(ctx, self.line_index, self.source_len); - record(self.evidence, span); - } - } - - /// Record contribution evidence spanning a single terminal token — for the - /// token-level classification sites (`&&`, `==`, `++`, …), where the - /// operator token itself is the construct a reader should be pointed at. - #[inline] - fn record_token_evidence(&mut self, term: &TerminalNodeView<'_>, record: F) - where - F: FnOnce(&mut MetricEvidence, SourceSpan), - { - if self.evidence.is_enabled() { - let symbol = term.symbol(); - let span = span_from_tokens(&symbol, &symbol, self.line_index, self.source_len); - record(self.evidence, span); - } - } - - fn visit(&mut self, node: Node<'_>, hint: &ChildHint) { - if let Some(rule) = node.as_rule() { - self.visit_rule(rule, hint); - } else if let Some(term) = node.as_terminal() { - self.visit_terminal(term, hint); - } - // Error leaves carry no metric contribution; they are surfaced as - // diagnostics by `mehen_antlr::collect_errors` in the analyzer. - } - - fn visit_terminal(&mut self, term: TerminalNodeView<'_>, hint: &ChildHint) { - let tt = term.symbol().token_type(); - - // Cognitive: `else` adds a flat +1 (covers `else if`). The boolean - // operator tokens feed the sequence collapser; unlike Java's flat - // `expression` rule, C#'s precedence cascade gives each `&&`/`||` its - // own node, so observing the tokens in source order is exactly - // SonarSource's flattened sequence. - // - // `in_operator_symbol` suppresses the whole family: in - // `public static C operator ++(C v)` the `++` is the operator being - // *declared*, not a mutation of anything, and `operator &&` / `operator <` - // would likewise have scored a boolean decision and a comparison from their - // own signatures. - if !hint.in_attributes && !hint.in_operator_symbol { - match tt { - cl::KW_ELSE => { - let before = self.current().cognitive.structural; - self.current().cognitive.increment_by_one(); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_token_evidence(&term, |e, s| e.cognitive(s, delta, "else")); - } - cl::AMP_AMP | cl::PIPE_PIPE => { - // Same-operator repeats collapse into one run and apply no - // delta; the sink skips zero-amount events, so only the - // operator that actually moved the metric is evidenced. - let op = if tt == cl::AMP_AMP { "&&" } else { "||" }; - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean(op); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_token_evidence(&term, |e, s| e.cognitive(s, delta, op)); - } - _ => {} - } - - // Cyclomatic: each short-circuit boolean operator token is a - // decision (independent of the cognitive run collapse). - if matches!(tt, cl::AMP_AMP | cl::PIPE_PIPE) { - self.current().cyclomatic.record_decision(); - let op = if tt == cl::AMP_AMP { "&&" } else { "||" }; - self.record_token_evidence(&term, |e, s| e.decision(s, op)); - } - - // ABC conditions: comparison / equality / boolean / null-coalescing - // operator tokens. - // - // Relational `<`/`>` are counted here, but the two constructs that - // reuse those tokens for something else must not be: - // - a shift — the prep spells `>>` as adjacent `>` tokens, so `a >> b` - // would read as two comparisons (`in_shift_operator`); - // - a generic argument/parameter list or function-pointer signature, - // where they are delimiters — `List f;` would read as two - // comparisons (`in_type_delimiter`). - if is_abc_condition_token(tt) && !hint.in_shift_operator && !hint.in_type_delimiter { - self.current().abc.record_condition(); - self.record_token_evidence(&term, |e, s| { - e.abc_condition(s, condition_token_spelling(tt)); - }); - } - - // ABC assignments: `++`/`--` (Fitzpatrick lists both under A). - // The `=`/compound forms are handled at the assignment expression. - if matches!(tt, cl::PLUS_PLUS | cl::MINUS_MINUS) { - self.current().abc.record_assignment(); - let op = if tt == cl::PLUS_PLUS { "++" } else { "--" }; - self.record_token_evidence(&term, |e, s| e.abc_assignment(s, op)); - } - } - - // Halstead operator/operand token classification. A terminal reached - // through an `identifier` rule is always an operand — this covers C#'s - // contextual keywords (`var`, `async`, `get`, `where`, …) used as names, - // which carry dedicated token types but are identifiers here. - let class = if hint.in_identifier { - HalsteadClass::Operand - } else if hint.in_operator_symbol && matches!(tt, cl::KW_TRUE | cl::KW_FALSE) { - // `public static bool operator true(C c)` declares an operator, and its - // symbol happens to be spelled with the same token as the `true` *literal* - // — which is an operand. In this position it is the operator being - // declared, so it belongs with `operator +` and `operator ==` rather than - // in the operand vocabulary. (`operator true`/`false` are the only - // overloadable operators whose symbols are keywords that mean something - // else elsewhere.) - HalsteadClass::Operator - } else { - halstead_class(tt) - }; - match class { - HalsteadClass::Operator => { - // `>>` and `>>>` are spelled as two or three adjacent `>` tokens - // (so a generic closer is never mis-lexed as a shift), but they - // are ONE Halstead operator. Recording each `>` would inflate - // length/volume and would conflate the shift with the `>` - // comparison in the distinct-operator set, so the whole operator - // is recorded once at its enclosing rule instead. - if hint.in_shift_operator { - return; - } - // A generic/function-pointer `<`…`>` is a delimiter, not a - // comparison. It stays an operator (Halstead counts bracket pairs, - // just as `(`/`)` are counted), but under its own name so the - // distinct-operator count does not conflate `List` with - // `a < b`. Halstead pairs a bracket as one operator, so only the - // opener is recorded. - // The hint marks a whole delimiter *list*, but only its `<`/`>` are - // the delimiter — a `,` separating type arguments is ordinary - // punctuation and counts as it does anywhere else. Returning for every - // token in the list dropped it, so `Dictionary` cost one - // operator less than the comma it visibly contains. - if hint.in_type_delimiter && matches!(tt, cl::LT | cl::GT) { - // Halstead pairs a bracket as one operator, so only the opener is - // recorded, under its own name — `List` must not be conflated - // with `a < b` in the distinct-operator set. - if tt == cl::LT { - self.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new("<>"), - text: None, - }); - } - return; - } - self.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(kp_token_name(tt)), - text: None, - }); - } - HalsteadClass::Operand => { - let text = term.symbol().text_or_empty(); - // Identifiers are keyed by the *symbol*, not the spelling. C# admits two - // spellings of one name — the verbatim prefix (`@x` is the identifier - // `x`, spelled that way only to escape a keyword collision) and Unicode - // escapes (`a` is `a`, §6.4.3) — and neither is part of the name. - // Keying on raw text made `int @x = 1; return x;` two distinct operands, - // so Halstead vocabulary and volume tracked spelling rather than - // symbols: the identical program spelled `int x` reported a smaller - // vocabulary. Non-identifier operands (literals, `this`, interpolated - // text) are left verbatim: for those the spelling *is* the value, and - // `1` vs `1L` vs `0x1` are genuinely different operands. - let key = if tt == cl::IDENTIFIER { - normalize_identifier(text) - } else if hint.in_utf8_literal { - // `"text"u8` is a `ReadOnlySpan`; `"text"` is a `string`. Two - // values of two types, so two operands — the suffix has to be part of - // the key even though it contributes no occurrence of its own. - SmolStr::new(format!("{text}u8")) - } else { - SmolStr::new(text) - }; - self.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(key), - }); - } - HalsteadClass::Skip => {} - } - - // PLOC: a visible code token's start row is a code line, recorded into - // the current space during the AST walk. Comments are hidden-channel - // (routed after the walk), and EOF (`tt < 0`) is not code. - // - // A single visible token can span multiple physical lines — a verbatim - // string (`@"…"`, `VERBATIM_STRING_LIT`), a raw string - // (`"""…"""`, `ML_RAW_STRING_LIT`), or an interpolated-string content token - // is one token covering several rows. Record *every* row it covers as code, - // or the interior rows sit inside the enclosing span with no PLOC - // observation and are reported as phantom blank lines - // (`blank = sloc - ploc - only_comment`). - if tt >= 0 { - // The start row comes from `LineIndex`, not from the token's own `line()`. - // The runtime's lexer counts only `\n`, while `LineIndex` (and this - // grammar's lexer) also treat NEL, U+2028, and U+2029 as terminators — so - // taking the token's line would put every row after such a separator one or - // more rows too high, disagreeing with the SLOC span and reporting phantom - // blanks. Deriving it from the byte offset keeps both in one convention. - let start_row = term - .symbol() - .start_byte() - .map(|start| { - self.line_index - .line_at(mehen_core::byte_offset_clamped(start)) - .saturating_sub(1) - }) - .unwrap_or_else(|| (term.symbol().line() as u32).saturating_sub(1)); - // Every C# line terminator, not just `\n` — the lexer accepts all five - // (ECMA-334 §6.3.1) and `LineIndex` counts rows the same way, so a - // multi-row token split by one of them has to expand here too or its - // interior rows read as phantom blanks. CRLF is one break, matching - // `LineIndex`: the `\r` is skipped when an `\n` follows. - let text = term.symbol().text_or_empty(); - let extra_rows = text - .char_indices() - .filter(|&(i, c)| match c { - '\r' => !text[i..].starts_with("\r\n"), - '\n' | '\u{85}' | '\u{2028}' | '\u{2029}' => true, - _ => false, - }) - .count() as u32; - for row in start_row..=start_row.saturating_add(extra_rows) { - self.current().loc.observe_code_line(row); - } - } - } - - fn visit_rule(&mut self, ctx: RuleNodeView<'_>, hint: &ChildHint) { - let ri = ctx.rule_index(); - // Snapshot the cognitive context of the *enclosing* construct before - // anything in this subtree mutates it. Must happen before - // `maybe_open_space`, which resets nesting/lambda and bumps depth for - // function spaces. - let saved_cognitive = self.cognitive; - - // NPA / NPM: classify a direct member of the enclosing type body before - // opening any space for this node, so the kinds stack still has the type - // on top. - // - // Visibility is resolved from THIS node's own `modifier*` children, not - // inherited from the hint. Roslyn puts the modifiers on the declaration - // itself, so by the time the walk reaches `field_declaration` the inbound - // hint (set at `member_declaration`) has nothing to carry — inheriting it - // would fall back to "public" for every member. - if hint.in_type_member - && let Some(container) = hint.member_container - { - // An unmarked class/struct member is private; an unmarked interface - // member is implicitly public. - let default_public = matches!(container, ContainerKind::Interface); - let public = visibility_from_modifiers(ctx).unwrap_or(default_public); - self.classify_type_member(ctx, ri, container, public); - } - - // Capture the enclosing type container BEFORE opening any space for - // this node: a member wrapper may open a nested type space here, and - // `member_propagation` (run after the open) would then see that - // just-opened type instead of the real enclosing scope. - let container_before_open = self.enclosing_container(); - - let (opened, primary_ctor_name) = self.maybe_open_space(ctx, ri, hint); - self.classify_rule(ctx, ri, hint); - - // A call argument (`G(a && b)`) is an independent boolean context: its - // inner short-circuit run must not collapse with a same-kind operator - // outside the call, and vice-versa. Save the enclosing run's `last_op`, - // start the argument fresh, then restore it so the *outer* run - // continues across the call as if it were a single operand. Same for a - // parenthesized sub-expression's interior? No: parentheses ARE - // transparent to SonarSource's flattening, so only arguments isolate. - // A `when` guard isolates the same way, and for the same reason: the guard and - // the arm result are independent expressions, so `1 when a && b => c && d` has - // two runs. A pre-children reset cannot do this — `classify_rule` runs before - // the subtree, so it separates the guard from what came *before* it rather than - // from what follows. - // - // An interpolation hole is the third: each `{…}` in one interpolated string is a - // separate expression, so `$"{a && b}{c && d}"` has two runs and must score 2. - // Without this the first hole left `last_op` set to `&&` and the second collapsed - // into it for 1 — the same string spelled as two locals scores 2, so the two - // spellings disagreed. - // - // `initializer_expression` / `collection_expression` isolate too, but their unit - // is each *element* rather than the whole node — see the per-child reset in - // `visit_children`. They are listed here as well so the enclosing run is - // restored after the last element, making the initializer one operand from - // outside just as a call is. - // - // `anonymous_object_creation_expression` isolates per *member* for the same reason - // an initializer does per element — `new { A = a && b, B = c && d }` has two runs — - // but its members are real `anonymous_object_member_declarator` rules rather than - // bare `expression` children, so each one isolates on its own here rather than - // needing the per-child reset in `visit_children`. - // - // A switch *label* deliberately does NOT isolate, though it looks like it should. - // Each label already resets at `case_switch_label`/`case_pattern_switch_label` in - // `classify_rule`, and that reset runs before the label's own subtree — which is - // the right order here (unlike the `when` guard, whose reset had to move) because - // a label's pattern is the *first* thing in it. Measured: consecutive - // `case > 0 and < 10:` / `case > 20 and < 30:` labels score 3, which is correct - // (switch +1, two independent `and` runs +2), and adding an isolation here changed - // nothing. - let saved_bool = if matches!( - ri, - cp::RULE_ARGUMENT - | cp::RULE_WHEN_CLAUSE - | cp::RULE_INTERPOLATION - | cp::RULE_INITIALIZER_EXPRESSION - | cp::RULE_COLLECTION_EXPRESSION - | cp::RULE_ANONYMOUS_OBJECT_MEMBER_DECLARATOR - // Every LINQ clause is an independent expression, so - // `from x in xs where a && b select c && d` has two runs — the `where` - // predicate and the `select` projection are no more one boolean context - // than two statements are. Without this the predicate left `&&` in - // `last_op` and the projection collapsed into it for 1, where the same - // query with each expression hoisted into a local scores 2. - // - // All six clause rules, not just `where`/`select`: a `let` binding, an - // `ordering` key, a `group … by` key, and a `join … on … equals` operand - // are each their own expression too. - | cp::RULE_WHERE_CLAUSE - | cp::RULE_SELECT_CLAUSE - | cp::RULE_GROUP_CLAUSE - | cp::RULE_LET_CLAUSE - | cp::RULE_ORDERING - | cp::RULE_JOIN_CLAUSE - ) { - Some(self.current().cognitive.boolean_seq.last_op.take()) - } else { - None - }; - - self.visit_children(ctx, ri, hint, container_before_open, primary_ctor_name); - - if let Some(prev) = saved_bool { - self.current().cognitive.boolean_seq.last_op = prev; - } - - if opened { - self.close_space(); - } - - // No accessor-sibling hoisting needed: Roslyn's `accessor_list` holds - // every accessor as a flat sibling, so `{ get; set; }` walks as two peer - // `accessor_declaration` children. (grammars-v4 nested the second - // accessor inside the first accessor's rule, which the walker had to - // undo by re-visiting it after the first space closed.) - self.cognitive = saved_cognitive; - } - - fn visit_children( - &mut self, - ctx: RuleNodeView<'_>, - ri: usize, - hint: &ChildHint, - container_before_open: Option, - // `Some` when this node is a type declaration carrying a primary constructor. - // Names the synthetic space this function opens around the `parameter_list` / - // `base_list` children, and is threaded to the direct children so - // `classify_loc_rule` can count the constructor's logical line at the - // `parameter_list`. Not inherited further — only the direct children see it. - primary_ctor_name: Option, - ) { - // `NodeChildren` is a cheap `Clone` slice-iterator, so it is re-walked - // below without allocating. - - // An `else if` must not add cognitive nesting — only the flat `else` +1 - // applies. Roslyn spells the else branch as its own `else_clause`, so the - // flag is set there and only when its body is a bare `if_statement`; - // `else { if … }` is genuinely nested and gets no flag. That replaces the - // old index-scan for the `if_body` following an `ELSE` token, plus the - // transparency chain that carried the flag down to the nested `if`. - // Set at the `else_clause`, then carried through the intervening - // `statement` dispatch layer so it reaches the nested `if_statement`. - // `else { if … }` is genuinely nested, so a `block` child stops it. - let propagate_else = match ri { - cp::RULE_ELSE_CLAUSE => else_clause_is_else_if(ctx), - cp::RULE_STATEMENT => hint.is_else_branch, - _ => false, - }; - - // Type body member positions originate at the member-declaration - // wrappers, then flow through the transparent `common_member_declaration` - // / `typed_member_declaration` wrappers to the real member rule. The - // visibility is resolved at the wrapper because `all_member_modifiers` - // is a sibling of the inner declaration, not its child. - let (propagate_member, member_container, member_is_public) = - self.member_propagation(ctx, ri, hint, container_before_open); - - // Capture the member wrapper's start so a member space can widen its - // span upward over its own-line attributes/modifiers. A nested type or - // function resets it (their members compute from their own wrappers). - - // A terminal directly under `identifier_token` is a name → Halstead - // operand. This is what makes C#'s contextual keywords come out right: - // the prep widens `identifier_token` to accept all 42 of them, so a - // `KW_VAR` reached here is an operand rather than an operator. - // - // `literal_expression` gets the same treatment, for the keyword-spelled - // literals Roslyn groups there: bare `default` (`string v = default;`) and - // `__arglist`. Those produce a *value* and belong with `true`/`false`/`null`, - // which are already operands — without this they fell through as operators, - // adding a spurious one and omitting the value operand. - // - // Only the *bare* form is affected. `default(T)` is a separate - // `default_expression : KW_DEFAULT LPAREN type RPAREN` rule and stays an - // operator, which is right: there it operates on a type. - let in_identifier = matches!(ri, cp::RULE_IDENTIFIER_TOKEN | cp::RULE_LITERAL_EXPRESSION); - - // Once inside an attribute, stay inside for the whole subtree so - // attribute metadata records no executable complexity. - let in_attributes = hint.in_attributes || ri == cp::RULE_ATTRIBUTE_LIST; - - // Thread the property/indexer/event name down so its accessors can be - // named `Prop.get` / `Prop.set`. Set at the member-bearing declaration; - // a nested function/type resets it. - let accessor_owner = if let Some(name) = accessor_owner_name(ctx, ri) { - Some(name) - } else if opens_type_like(ri) || opens_function_space(ri) { - None - } else { - hint.accessor_owner.clone() - }; - - // The accessors' arity travels with the owner's name, for the same reason: - // `accessor_declaration` has no parameter list, so only the owning - // `indexer_declaration` knows it. A property or event resets it to 0 — its - // accessors take no arguments even though `set`'s `value` is implicit. - let accessor_args = if accessor_owner_name(ctx, ri).is_some() { - ctx.child_rule(cp::RULE_BRACKETED_PARAMETER_LIST) - .map(count_parameters) - .unwrap_or(0) - } else if opens_type_like(ri) || opens_function_space(ri) { - 0 - } else { - hint.accessor_args - }; - - // When this wrapper opened the member OR type space itself (to capture - // own-line attributes/modifiers), tell the inner declaration to skip - // its own open. The flag flows through the transparent - // `common_member_declaration`/`typed_member_declaration` wrappers to - // the declaration node, which consumes it; a real space open clears it - // so a nested declaration inside the body still opens normally. - // `>>` and `>>>` are spelled as adjacent `>` tokens; tag them so the - // token-level ABC scan does not read a shift as two comparisons. - let in_shift_operator = matches!( - ri, - cp::RULE_RIGHT_SHIFT - | cp::RULE_UNSIGNED_RIGHT_SHIFT - | cp::RULE_RIGHT_SHIFT_ASSIGNMENT - | cp::RULE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT - ); - - // A generic argument/parameter list and a function-pointer signature - // delimit with the same `<`/`>` tokens as a comparison. Only the enclosing - // rule tells them apart, so tag the subtree. - // - // The flag does NOT propagate into children: a type argument can contain a - // real comparison (`Func` holding a lambda body, or the `expression` - // inside `relational_pattern`), and a nested `List>` re-enters - // the delimiter rule for its own angle brackets anyway. Only each list's - // *own* `<`/`>` terminals need suppressing, which is exactly the extent of - // a non-propagating flag. - let in_type_delimiter = matches!( - ri, - cp::RULE_TYPE_ARGUMENT_LIST - | cp::RULE_TYPE_PARAMETER_LIST - | cp::RULE_FUNCTION_POINTER_PARAMETER_LIST - ); - - // Sticky for the whole creation subtree: `new[] { new[] { 1 } }` has a nested - // creation whose own initializer must also not double-count. - // `initializer_expression` is included so a bare initializer's *nested* groups - // are part of the same allocation: `int[,] v = { { 1, 2 }, { 3, 4 } };` is one - // array, and without this each of the three initializer nodes scored a branch. - // The explicit `new int[,] { … }` spelling was already correct, because the - // creation set the flag before the initializers were reached. - let in_creation_expression = hint.in_creation_expression - || matches!( - ri, - cp::RULE_INITIALIZER_EXPRESSION - | cp::RULE_OBJECT_CREATION_EXPRESSION - | cp::RULE_IMPLICIT_OBJECT_CREATION_EXPRESSION - | cp::RULE_ANONYMOUS_OBJECT_CREATION_EXPRESSION - | cp::RULE_ARRAY_CREATION_EXPRESSION - | cp::RULE_IMPLICIT_ARRAY_CREATION_EXPRESSION - | cp::RULE_COLLECTION_EXPRESSION - | cp::RULE_STACK_ALLOC_ARRAY_CREATION_EXPRESSION - | cp::RULE_IMPLICIT_STACK_ALLOC_ARRAY_CREATION_EXPRESSION - ); - - // A UTF-8 literal's suffix and its literal token are siblings, so the flag is set - // at their shared wrapper and read by the literal terminal one level down. Not - // propagated further, which costs nothing: the wrapper's only children are the - // literal and the suffix. - let in_utf8_literal = matches!( - ri, - cp::RULE_UTF8_STRING_LITERAL_TOKEN - | cp::RULE_UTF8_SINGLE_LINE_RAW_STRING_LITERAL_TOKEN - | cp::RULE_UTF8_MULTI_LINE_RAW_STRING_LITERAL_TOKEN - ) || (hint.in_utf8_literal - // The literal terminal is not the wrapper's direct child: Roslyn interposes - // dispatch rules (`utf8_string_literal_token -> string_literal_token -> - // regular_string_literal_token -> STRING_LIT`), so the flag has to survive - // them. Only those pure-dispatch layers carry it, which keeps it from - // leaking anywhere a real expression could appear. - && matches!( - ri, - cp::RULE_STRING_LITERAL_TOKEN - | cp::RULE_REGULAR_STRING_LITERAL_TOKEN - | cp::RULE_VERBATIM_STRING_LITERAL_TOKEN - | cp::RULE_SINGLE_LINE_RAW_STRING_LITERAL_TOKEN - | cp::RULE_MULTI_LINE_RAW_STRING_LITERAL_TOKEN - )); - - // The operator symbol in `public static C operator ++(C v)` is a direct - // token of the declaration, so a non-propagating flag covers exactly the - // signature's own terminals and leaves the parameter list and body alone. - let in_operator_symbol = ri == cp::RULE_OPERATOR_DECLARATION; - - // Whether the member this node sits in returns a value, so an expression body - // is a return. Recomputed at every declaration that owns an expression body, and - // otherwise inherited so the `arrow_expression_clause` a few levels down can - // read it. - let returns_value = match ri { - // A getter yields a value by construction; `set`/`init`/`add`/`remove` do - // not. The keyword is a child token rather than part of the rule name. - cp::RULE_ACCESSOR_DECLARATION => ctx.has_token(cl::KW_GET), - // A lambda's body is its result — `x => x + 1` returns. Set for - // completeness, though it currently has no effect: a lambda spells its body - // as a bare `(block | expression)` rather than an `arrow_expression_clause`, - // so there is no node for the exit rule to match. An expression-bodied - // lambda therefore still reports NExit 0, which is a smaller gap than the - // member case (a lambda has no block-bodied form to disagree with unless - // the author writes `x => { return x + 1; }`, which does count). - cp::RULE_SIMPLE_LAMBDA_EXPRESSION | cp::RULE_PARENTHESIZED_LAMBDA_EXPRESSION => true, - // A property or indexer's expression body is its getter. - cp::RULE_PROPERTY_DECLARATION | cp::RULE_INDEXER_DECLARATION => true, - // For the rest, the declared return type decides. A conversion operator - // always produces its target type, so it returns unconditionally. - cp::RULE_CONVERSION_OPERATOR_DECLARATION => true, - cp::RULE_METHOD_DECLARATION - | cp::RULE_OPERATOR_DECLARATION - | cp::RULE_LOCAL_FUNCTION_STATEMENT => ctx - .child_rule(cp::RULE_TYPE) - .is_some_and(|ty| !type_is_void_like(&ty.text(), is_async(ctx))), - // A constructor, destructor, and anonymous method (`delegate { … }`, which - // has no expression-body form) return nothing here. - cp::RULE_CONSTRUCTOR_DECLARATION - | cp::RULE_DESTRUCTOR_DECLARATION - | cp::RULE_ANONYMOUS_METHOD_EXPRESSION => false, - _ => hint.returns_value, - }; - - // Inside an accessor's body from the accessor declaration downward, so - // an expression-bodied `get => _x;` can count its own logical line. A - // nested function or type resets it — their bodies are counted normally. - let in_accessor_body = if ri == cp::RULE_ACCESSOR_DECLARATION { - true - } else if opens_type_like(ri) || opens_function_space(ri) { - false - } else { - hint.in_accessor_body - }; - - // An initializer's or collection expression's *elements* are independent boolean - // contexts, exactly like call arguments — `new[] { a && b, c && d }` has two runs - // and must score 2, matching both `G(a && b, c && d)` and the two-locals - // spelling. Without this the first element left `&&` in `last_op` and the second - // collapsed into it for 1. - // - // Done per *child* here rather than in the pre/post pair around - // `visit_children`, because unlike `RULE_ARGUMENT` these elements have no rule of - // their own to hang the reset on: `initializer_expression` holds them as bare - // `expression` children (`'{' (expression (',' expression)* ','?)? '}'`). A - // per-child reset over the element list is the same save/reset/restore, applied - // at the only place the boundaries are visible. - let isolate_elements = matches!( - ri, - cp::RULE_INITIALIZER_EXPRESSION | cp::RULE_COLLECTION_EXPRESSION - ); - - // A binary pattern is `left op right`, and its operator belongs to the boolean - // *sequence* between its operands — see the note in `classify_rule`'s - // `RULE_PATTERN` arm. Observed here, after the first `pattern` child has been - // walked and before the second, which is what in-order means for this shape. - let pattern_combinator = (ri == cp::RULE_PATTERN) - .then(|| PatternContext::from_rule_node(ctx)) - .flatten() - .and_then(|pattern| { - if pattern.kw_or_token().is_some() { - Some("or") - } else if pattern.kw_and_token().is_some() { - Some("and") - } else { - None - } - }); - let mut seen_operand = false; - - // A **primary constructor**'s synthetic space lives across sibling - // children: it opens when the loop reaches the `parameter_list` and - // closes after the base-constructor call — before any interface entries - // in the base list, the constraint clauses, and - // `{ member_declaration* }`, which all belong to the type. It cannot - // hang on any single rule's open/close in `visit_rule`: opened eagerly - // at the type it received none of its own tokens, and scoped to the - // `parameter_list` alone it missed the base-constructor call — - // `class C(int x) : B(x)` left the `: B(x)` call's ABC branch and - // Halstead tokens on the *type*, where the explicit `: base(x)` - // spelling attributes them to the constructor (#219). - // - // Where it closes depends on what the base list holds. `base_list` is - // `':' base_type (',' base_type)*`, and only its - // `primary_constructor_base_type` entry — the `B(x)` call — is - // constructor syntax; a `simple_base_type` is an implemented interface, - // which the explicit spelling attributes to the type. So: - // - // - base list with a base call (`: B(x)` or `: B(x), IFoo`): the space - // stays open *into* the base list and closes right after the call's - // `base_type` — a mid-subtree close this loop cannot perform, handed - // off through `self.primary_ctor_close` to the `base_list`'s own - // child loop below. - // - no base list, or interfaces only (`struct S(int x) : IFoo`): the - // space closes here, after the `parameter_list` child. - // - // `primary_ctor_cognitive` doubles as the is-open flag and the - // enclosing (type-scope) cognitive context to restore on close — the - // save/restore that `visit_rule` does per node, done manually because - // the space's lifetime is not a node's. - let primary_ctor_closes_in_base_list = primary_ctor_name.is_some() - && ctx - .child_rule(cp::RULE_BASE_LIST) - .is_some_and(base_list_has_base_call); - let mut primary_ctor_cognitive: Option = None; - - for child in ctx.children() { - let child_ri = child.as_rule().map(|r| r.rule_index()); - if let Some(name) = primary_ctor_name.as_deref() - && child_ri == Some(cp::RULE_PARAMETER_LIST) - && primary_ctor_cognitive.is_none() - && let Some(params) = child.as_rule() - { - primary_ctor_cognitive = Some(self.cognitive); - self.open_primary_ctor_space(ctx, params, name); - } - if isolate_elements { - self.current().cognitive.boolean_seq.last_op = None; - } - if let Some(op) = pattern_combinator - && child - .as_rule() - .is_some_and(|r| r.rule_index() == cp::RULE_PATTERN) - { - if seen_operand { - // The right operand is next, so the operator sits here. - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean(op); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, op)); - } else { - seen_operand = true; - } - } - let child_hint = ChildHint { - is_else_branch: propagate_else, - in_type_member: propagate_member, - member_container, - member_is_public, - in_identifier, - in_attributes, - in_shift_operator, - in_type_delimiter, - in_operator_symbol, - in_utf8_literal, - in_creation_expression, - in_accessor_body, - returns_value, - accessor_owner: accessor_owner.clone(), - accessor_args, - primary_ctor_name: primary_ctor_name.clone(), - }; - self.visit(child, &child_hint); - if child_ri == Some(cp::RULE_PARAMETER_LIST) - && let Some(saved) = primary_ctor_cognitive.take() - { - if primary_ctor_closes_in_base_list { - // Keep the space open into the `base_list`; its child loop - // (below, next iteration of this function one level deeper) - // closes it after the base-constructor call. - self.primary_ctor_close = Some(saved); - } else { - self.close_space(); - self.cognitive = saved; - } - } - // The handed-off close: this is the `base_list`'s own child loop, - // and the child just visited is the base-call `base_type` — the last - // piece of the constructor. The remaining entries (`, IFoo`, …) are - // implemented interfaces and belong to the type, exactly as the - // explicit `class C : B, IFoo { public C(int x) : base(x) { } }` - // spelling attributes them. - if ri == cp::RULE_BASE_LIST - && child.as_rule().is_some_and(base_type_is_base_call) - && let Some(saved) = self.primary_ctor_close.take() - { - self.close_space(); - self.cognitive = saved; - } - } - } - - /// Compute the `(in_type_member, container, is_public)` hint for this rule's - /// children. - /// - /// `member_declaration` marks a member position; the `base_*` rules beneath - /// it are pure dispatch alternations (Roslyn's syntax model has abstract - /// bases like `BaseMethodDeclarationSyntax`, so the generator emits one - /// alternation rule per abstraction) and simply pass the position through. - /// - /// Visibility is read on the real declaration, because Roslyn puts - /// `modifier*` there rather than on a wrapper — so unlike the grammars-v4 - /// shape there is nothing to resolve early and thread down. - fn member_propagation( - &self, - _ctx: RuleNodeView<'_>, - ri: usize, - hint: &ChildHint, - container_before_open: Option, - ) -> (bool, Option, Option) { - match ri { - // A member position opens here. The container is captured BEFORE this - // node's `maybe_open_space`, since a member that is itself a nested - // type has already pushed that type's space. - cp::RULE_MEMBER_DECLARATION => (true, container_before_open, None), - // Enum members bypass `member_declaration` entirely: Roslyn inlines - // them into `enum_declaration` (`… '{' (enum_member_declaration (',' - // enum_member_declaration)*)? '}'`), so the position must open here - // too. They are implicitly public constants of the enum. - cp::RULE_ENUM_DECLARATION => (true, Some(ContainerKind::Class), Some(true)), - // Pure dispatch layers: keep the inbound member position so the hint - // reaches the real declaration one level deeper. - cp::RULE_BASE_FIELD_DECLARATION - | cp::RULE_BASE_METHOD_DECLARATION - | cp::RULE_BASE_PROPERTY_DECLARATION - | cp::RULE_BASE_TYPE_DECLARATION - | cp::RULE_TYPE_DECLARATION => ( - hint.in_type_member, - hint.member_container, - hint.member_is_public, - ), - // The real declarations keep the member position so nested spaces - // still know their container. Visibility is NOT computed here: it is - // read from the declaration's own `modifier*` at the point of - // classification (see `visit_rule`), because Roslyn puts the - // modifiers on the declaration rather than on a wrapper above it. - _ if hint.in_type_member && declares_member(ri) => (true, hint.member_container, None), - _ => (false, None, None), - } - } - - /// The `ContainerKind` of the type-like space currently on top of the kinds - /// stack (for member NPA/NPM routing), or `None` if the top is not a - /// type-like scope. - fn enclosing_container(&self) -> Option { - match self.kinds.last() { - Some(SpaceKind::Class | SpaceKind::Impl | SpaceKind::Enum) => { - Some(ContainerKind::Class) - } - Some(SpaceKind::Interface | SpaceKind::Trait) => Some(ContainerKind::Interface), - _ => None, - } - } - - /// Open a `Function` space for a method-shaped member. `span_ctx` supplies - /// the span (the member wrapper when opening at the wrapper, so the span - /// covers own-line attributes/modifiers; otherwise the declaration itself); - /// `fn_ctx` supplies the name and NArgs. - fn open_function_space( - &mut self, - span_ctx: RuleNodeView<'_>, - fn_ctx: RuleNodeView<'_>, - hint: &ChildHint, - kind: SpaceKind, - ) { - let name = function_name(fn_ctx, hint); - // Node identity: the arena addresses every node by a `NodeId`, so - // "different node" is an id comparison, not pointer equality. - let opened_at_wrapper = span_ctx.node().id() != fn_ctx.node().id(); - // When opening at the wrapper, NPM must be recorded into the enclosing - // type BEFORE the member space is pushed (member classification - // normally runs at the inner declaration, but that node now sits inside - // this space and would misroute NPM into the member). - if opened_at_wrapper && let Some(container) = self.enclosing_container() { - let default_public = matches!(container, ContainerKind::Interface); - let public = visibility_from_modifiers(span_ctx).unwrap_or(default_public); - self.current().npm.record_method(container, public); - if public { - let detail = rule_name(fn_ctx.rule_index()); - self.record_evidence(span_ctx, |e, s| e.public_method(s, detail)); - } - } - // Widen the declaration-node span up to its member wrapper so own-line - // attributes/modifiers belong to the member. Unused when opening at the - // wrapper (the span already starts there). - let mut state = self.new_space_state(span_ctx); - // No row adoption needed: Roslyn puts `attribute_list* modifier*` on the - // declaration itself, so the space's own span already starts at the - // member's first attribute row rather than after it. - let is_closure = matches!(kind, SpaceKind::Closure); - let argc = count_args(fn_ctx, hint); - let detail = rule_name(fn_ctx.rule_index()); - if is_closure { - state.nom.record_closure(); - state.nargs.record_closure_args(argc); - self.record_evidence(span_ctx, |e, s| { - e.closure(s, detail); - e.closure_args(s, argc, detail); - }); - } else { - state.nom.record_function(); - state.nargs.record_function_args(argc); - self.record_evidence(span_ctx, |e, s| { - e.function(s, detail); - e.function_args(s, argc, detail); - }); - } - // A local function's and a lambda's complexity belongs to the enclosing - // method (already counted there), so neither rolls into the type's WMC. - let suppress_wmc = is_closure || fn_ctx.rule_index() == cp::RULE_LOCAL_FUNCTION_STATEMENT; - self.push_space(kind, name, span_ctx, state, suppress_wmc); - self.enter_function_cognitive(is_closure); - } - - /// Open a type-like (`Class`/`Enum`/`Interface`) space for `type_ctx`. - /// `span_ctx` supplies the span — the wrapper when opening there (so - /// own-line attributes/modifiers are covered), otherwise the definition. - /// Returns the type's name when it carries a **primary constructor**, for - /// [`ChildHint::primary_ctor_name`] to thread to the `parameter_list` child that - /// opens the synthetic constructor's space. `None` otherwise. - fn open_type_space( - &mut self, - span_ctx: RuleNodeView<'_>, - type_ctx: RuleNodeView<'_>, - ) -> Option { - let name = name_from_identifier(type_ctx); - let ri = type_ctx.rule_index(); - let mut state = self.new_space_state(span_ctx); - state.npa.record_class_like(); - state.npm.record_class_like(); - let kind = match ri { - cp::RULE_ENUM_DECLARATION => { - state.wmc.record_class_like(); - SpaceKind::Enum - } - // An `interface` carries no WMC (its members are not weighted), - // matching the Java walker's interface handling. - cp::RULE_INTERFACE_DECLARATION => SpaceKind::Interface, - // `class`, `struct`, `record`, and `delegate` are class-like. A - // `delegate` is a type declaration with a signature but no body; it - // opens a (childless) class space so its own LOC/NArgs are - // attributed. - _ => { - state.wmc.record_class_like(); - SpaceKind::Class - } - }; - self.push_space(kind, name.clone(), span_ctx, state, false); - self.enter_class_cognitive(); - - // A primary constructor (`class C(int x)`, `record R(int X)`) puts its - // parameters on the *type* declaration, and no `constructor_declaration` node - // exists anywhere in the tree. Without this the constructor is absent from - // NOM entirely and its parameters from NArgs — so `class C(int x)` reported - // NOM 0 where the identical `class C { public C(int x) { } }` reported 1. - // - // Opened as a named function space rather than folded into the type's own - // counters so it appears in the per-space tree the way an explicit - // constructor does, and is named after the type for the same reason. It is - // opened immediately after the type space and closed here: the parameter list - // is the whole of it, since a primary constructor has no body of its own. - // - // Matched on an allowlist of the declaration kinds that actually *support* a - // primary constructor, not on "has a `parameter_list`" — several type-like - // rules carry that child for unrelated reasons and would fabricate a - // constructor from it: - // - // - `delegate_declaration` — `delegate int D(int x);` has a parameter list - // because that IS the delegate's signature. It invented a function named `D`, - // inflating NOM/NArgs and rolling a phantom method into the delegate's WMC, - // which is meant to be a childless space. - // - `extension_block_declaration` — the list is the extension *receiver* - // (`extension(string s)`); nothing is constructed and there is no name. - // - // C# allows a primary constructor on exactly `class`, `struct`, `record`, and - // `record struct` (the last two are both `record_declaration` here), plus - // `interface` since C# 12 — where it declares parameters rather than a body, - // but is still spelled and named the same way. - // C# allows a primary constructor on exactly `class`, `struct`, `record`, and - // `record struct` (the last two are one rule here). An `interface` does NOT — - // `interface I(int x) { }` is not valid C#, and the permissive grammar accepts - // the optional parameter list without a diagnostic, so listing it here minted a - // constructor for invalid source. - if matches!( - ri, - cp::RULE_CLASS_DECLARATION | cp::RULE_STRUCT_DECLARATION | cp::RULE_RECORD_DECLARATION - ) && type_ctx.child_rule(cp::RULE_PARAMETER_LIST).is_some() - { - // NPM on the enclosing type, which is the space currently on top: an explicit - // `class C { public C(int x) { } }` reaches `classify_type_member` and records - // a class method there, but a primary constructor has no `member_declaration` - // to route through — so NPM depended on which spelling the author chose. - // - // Always public: a primary constructor's accessibility cannot be narrowed - // (there are no modifiers to put on it), and its parameters *are* the type's - // construction surface. The container is `Class` for all three declaration - // kinds here — `struct` and `record` are class-like for NPM, as - // `open_type_space` already treats them. - // - // Gated on the name because the synthetic space downstream is too: an - // unnamed declaration (error recovery — `name_from_identifier` found no - // identifier) returns `None`, so `visit_children` opens no space and the - // constructor's NOM/NArgs/LLOC are all dropped. Recording NPM anyway would - // report a public method that appears nowhere else — the constructor's - // metrics must be omitted or recorded *together*. - if name.is_some() { - self.current().npm.record_method(ContainerKind::Class, true); - // Evidence points at the parameter list — the constructor's - // whole declaration, since Roslyn synthesizes no - // `constructor_declaration` node for the primary form. - if let Some(params) = type_ctx.child_rule(cp::RULE_PARAMETER_LIST) { - self.record_evidence(params, |e, s| { - e.public_method(s, "primary_constructor"); - }); - } - } - // The space itself opens when the walk *reaches* the parameter list and - // stays open through the base list — see `open_primary_ctor_space` and the - // child loop in `visit_children`. Pushing and popping it here instead — - // which is what this did — gave the constructor none of the tokens inside - // its own signature: LLOC 0 and Halstead vocabulary 0, against 1 and 8 for - // the explicit spelling. And closing it at the end of the parameter list — - // the next shape this had — still left the base-constructor call's ABC - // branches and Halstead tokens on the *type*: in `class C(int x) : B(x)` - // the `: B(x)` is the primary spelling of `: base(x)`, which the explicit - // form attributes to the constructor. - return name; - } - None - } - - /// Open a metric space for space-introducing rules. Returns whether a space - /// was pushed. - /// Open a metric space when `ctx` is a declaration that owns one. - /// - /// Roslyn's grammar puts `attribute_list* modifier*` directly on every - /// declaration, so a member's span already starts at its attributes and its - /// visibility is readable on the declaration itself. The grammars-v4 shape - /// needed a wrapper rule (`class_member_declaration`, holding - /// `all_member_modifiers` alongside `common_member_declaration`) to factor - /// that prefix out of an LL decision, and the walker had to open the space at - /// the wrapper and widen the span back. None of that applies here — hence no - /// wrapper handling and no span widening. - /// Returns `(opened, primary_ctor_name)` — the second is `Some` only for a type - /// declaration carrying a primary constructor, and is threaded to its - /// `parameter_list` child so the synthetic constructor's space opens there. - fn maybe_open_space( - &mut self, - ctx: RuleNodeView<'_>, - ri: usize, - hint: &ChildHint, - ) -> (bool, Option) { - match ri { - cp::RULE_METHOD_DECLARATION - | cp::RULE_CONSTRUCTOR_DECLARATION - | cp::RULE_DESTRUCTOR_DECLARATION - | cp::RULE_OPERATOR_DECLARATION - | cp::RULE_CONVERSION_OPERATOR_DECLARATION - | cp::RULE_LOCAL_FUNCTION_STATEMENT => { - self.open_function_space(ctx, ctx, hint, SpaceKind::Function); - (true, None) - } - // Property / indexer / event accessors are each their own function - // space (SonarC# counts them as methods): `get`/`set` bodies carry - // real complexity and are the C# analogue of Kotlin's - // `getter`/`setter`. - // - // One rule covers all of get/set/init/add/remove, and `accessor_list` - // holds them as flat siblings — so unlike grammars-v4 there is no - // asymmetry where the second accessor nests inside the first, and no - // sibling-hoisting is needed. - cp::RULE_ACCESSOR_DECLARATION => { - self.open_function_space(ctx, ctx, hint, SpaceKind::Function); - (true, None) - } - // An expression-bodied property or indexer (`int P => 1;`) is - // semantically a getter, but has no `accessor_list` for the arm above - // to fire on — Roslyn spells it as an `arrow_expression_clause` - // directly on the declaration. Without this, two identical getters - // would produce different NOM / NArgs / WMC depending only on which - // syntax the author chose. SonarC# counts both as methods. - cp::RULE_PROPERTY_DECLARATION | cp::RULE_INDEXER_DECLARATION - if ctx.child_rule(cp::RULE_ACCESSOR_LIST).is_none() - && ctx.child_rule(cp::RULE_ARROW_EXPRESSION_CLAUSE).is_some() => - { - self.open_function_space(ctx, ctx, hint, SpaceKind::Function); - (true, None) - } - // Closures: a lambda (`x => …`, `(a, b) => …`) or an anonymous - // method (`delegate(int x) { … }`). NOM/NArgs record them as - // closures, and their cyclomatic must NOT roll into the enclosing - // type's WMC (WMC weights *methods*). Roslyn splits lambdas by - // parameter shape, and all three are real rules rather than labeled - // alternatives — so no `is_anonymous_method` probe. - cp::RULE_SIMPLE_LAMBDA_EXPRESSION - | cp::RULE_PARENTHESIZED_LAMBDA_EXPRESSION - | cp::RULE_ANONYMOUS_METHOD_EXPRESSION => { - self.open_function_space(ctx, ctx, hint, SpaceKind::Closure); - (true, None) - } - // A **primary constructor**'s synthetic space is NOT opened here: it has to - // stay open across two sibling children (`parameter_list` and `base_list`), - // which the one-rule-one-space shape of this function cannot express. It is - // opened and closed inside `visit_children`'s child loop instead — see - // `open_primary_ctor_space`. - _ if opens_type_like(ri) => (true, self.open_type_space(ctx, ctx)), - _ => (false, None), - } - } - - /// Build a space's initial `State` from the context's own span. - /// - /// No span widening, unlike the grammars-v4-backed walkers: those open a - /// member's space at a wrapper rule that excludes the leading `attribute_list* - /// modifier*`, so the span has to be pulled back to cover them. Roslyn puts - /// that prefix on the declaration itself (see [`maybe_open_space`]), so the - /// context's own start is already the member's first byte. - /// - /// [`maybe_open_space`]: Walker::maybe_open_space - fn new_space_state(&self, ctx: RuleNodeView<'_>) -> State { - self.new_space_state_at(ctx_span(ctx, self.line_index, self.source_len)) - } - - /// Build a space's initial `State` from an explicit span — the span-source - /// half of [`new_space_state`], split out so the primary constructor's - /// widened span (see [`open_primary_ctor_space`]) shares the LOC span - /// convention rather than duplicating it. - /// - /// [`new_space_state`]: Walker::new_space_state - /// [`open_primary_ctor_space`]: Walker::open_primary_ctor_space - fn new_space_state_at(&self, span: SourceSpan) -> State { - let mut state = State::new(); - state.loc.set_span( - span.start_line.saturating_sub(1), - span.end_line.saturating_sub(1), - false, - ); - state - } - - /// Open a space over `ctx`'s span, recording it for LOC routing. - /// - /// The span is the context's own, for the same reason [`new_space_state`] does - /// no widening. - /// - /// [`new_space_state`]: Walker::new_space_state - fn push_space( - &mut self, - kind: SpaceKind, - name: Option, - ctx: RuleNodeView<'_>, - state: State, - suppress_parent_wmc: bool, - ) { - let span = ctx_span(ctx, self.line_index, self.source_len); - self.push_space_at(kind, name, span, state, suppress_parent_wmc); - } - - /// Open a space over an explicit `span` — for the one space whose extent is - /// not a single rule node: the primary constructor's, which runs from its - /// `parameter_list` through the end of its `base_list` (see - /// [`open_primary_ctor_space`]). - /// - /// [`open_primary_ctor_space`]: Walker::open_primary_ctor_space - fn push_space_at( - &mut self, - kind: SpaceKind, - name: Option, - span: SourceSpan, - state: State, - suppress_parent_wmc: bool, - ) { - let space_id = self.tree.open(kind.clone(), span, name); - self.loc_routing - .record_open(space_id, span.start_byte, span.end_byte); - self.stack.push(state); - self.kinds.push(kind); - self.suppress_parent_wmc.push(suppress_parent_wmc); - } - - /// Open the synthetic space for a **primary constructor** - /// (`class C(int x) : B(x)`). `type_ctx` is the type declaration carrying it; - /// `params` is its `parameter_list` child; `name` is the type's name, which - /// is the constructor's name exactly as for the explicit spelling. - /// - /// The span runs from the parameter list through the end of the - /// base-constructor call when the base list holds one: Roslyn synthesizes - /// no `constructor_declaration` node, so that header IS the constructor — - /// the parameters plus the base call. Interface entries after the call - /// (`, IFoo`) are the type's, so the span deliberately stops short of them. - /// Widening matters beyond reporting: post-walk LOC routing is by byte - /// range, so a comment inside the base call reaches the constructor only if - /// its range covers it. - /// - /// Opened from `visit_children`'s child loop when the walk reaches the - /// `parameter_list`, and closed there after the base call (or after the - /// parameter list itself when there is none) — the caller saves and restores - /// the cognitive context around that window. - fn open_primary_ctor_space( - &mut self, - type_ctx: RuleNodeView<'_>, - params: RuleNodeView<'_>, - name: &str, - ) { - let mut span = ctx_span(params, self.line_index, self.source_len); - if let Some(base_call) = type_ctx - .child_rule(cp::RULE_BASE_LIST) - .and_then(|base_list| { - base_list - .child_rules(cp::RULE_BASE_TYPE) - .find(|bt| base_type_is_base_call(*bt)) - }) - { - let call_span = ctx_span(base_call, self.line_index, self.source_len); - span.end_byte = span.end_byte.max(call_span.end_byte); - span.end_line = span.end_line.max(call_span.end_line); - } - let mut state = self.new_space_state_at(span); - let argc = count_parameters(params); - state.nom.record_function(); - state.nargs.record_function_args(argc); - // The space's own (widened) span is already computed, so the sink's - // internal no-op check suffices here — no lazy span helper needed. - self.evidence.function(span, "primary_constructor"); - self.evidence - .function_args(span, argc, "primary_constructor"); - self.push_space_at( - SpaceKind::Function, - Some(name.to_owned()), - span, - state, - false, - ); - self.enter_function_cognitive(false); - } - - /// Reset the cognitive context when opening a type-like space. A type body - /// is a fresh scope: code that runs *directly* in it (field initializers) - /// must not inherit the enclosing statement's nesting. - fn enter_class_cognitive(&mut self) { - self.cognitive = CognitiveContext::default(); - } - - fn enter_function_cognitive(&mut self, is_closure: bool) { - // Depth is inherited only from an *enclosing function/closure within - // the same type scope* — a lambda or local function nested directly in - // another function's body. A type scope resets the baseline: a method in - // a nested type is fresh, so its cognitive nesting starts at 0. - let nested_inside_function = self - .kinds - .iter() - .rev() - .skip(1) - .take_while(|k| { - !matches!( - k, - SpaceKind::Class - | SpaceKind::Interface - | SpaceKind::Trait - | SpaceKind::Impl - | SpaceKind::Enum - ) - }) - .any(|k| matches!(k, SpaceKind::Function | SpaceKind::Closure)); - self.cognitive.nesting = 0; - self.cognitive.lambda = 0; - if nested_inside_function { - self.cognitive.depth = self.cognitive.depth.saturating_add(1); - } - let _ = is_closure; - } - - fn close_space(&mut self) { - let closed_kind = self.kinds.pop().expect("kinds underflow"); - let suppress_wmc = self.suppress_parent_wmc.pop().unwrap_or(false); - let mut state = self.stack.pop().expect("stack underflow"); - // A function OR closure space carries its own McCabe value (base + 1), - // used for its per-space cyclomatic and (for methods) the WMC rollup. - if matches!(closed_kind, SpaceKind::Function | SpaceKind::Closure) { - state.wmc.set_cyclomatic(state.cyclomatic.cyclomatic + 1); - } - finalize_state(&mut state); - if let Some(space_id) = self.tree.current_id() { - self.loc_routing - .record_close(space_id, &state.loc, &state.cyclomatic); - } - apply_state_to(state.clone(), self.tree.metrics_mut()); - if let Some(parent) = self.stack.last_mut() { - let parent_kind = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - merge_child_into_parent(parent, &state); - // Roll a closing method's cyclomatic into the parent's WMC. C# WMC - // is *per class* — an interface's members are not weighted, so only - // roll into a class/struct/enum parent. Local functions and lambdas - // are suppressed (their complexity is the enclosing method's). - if matches!(closed_kind, SpaceKind::Function) - && !suppress_wmc - && matches!( - parent_kind, - SpaceKind::Class | SpaceKind::Impl | SpaceKind::Enum - ) - { - let container = container_kind(parent_kind); - state.wmc.finalize_method_into(container, &mut parent.wmc); - } - } - self.tree.close(); - } - - /// Per-rule cyclomatic / cognitive / ABC / exit / LOC classification. - fn classify_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: &ChildHint) { - // Attribute arguments are compile-time metadata, not executable code, - // so they record no executable complexity. LOC/Halstead still count — - // the tokens physically exist. - if !hint.in_attributes { - self.classify_control_flow(ctx, ri, hint); - self.classify_expression(ctx, ri); - self.classify_abc_rule(ctx, ri, hint); - } - // A split shift operator is one Halstead operator, recorded here because - // `visit_terminal` skips its individual `>` tokens (see the - // `in_shift_operator` branch there). Keyed by the rule so `>>` and `>>>` - // stay distinct from each other and from the `>` comparison. - if matches!( - ri, - cp::RULE_RIGHT_SHIFT - | cp::RULE_UNSIGNED_RIGHT_SHIFT - | cp::RULE_RIGHT_SHIFT_ASSIGNMENT - | cp::RULE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT - ) { - self.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(format!("shift{ri}")), - text: None, - }); - } - // An *empty* interpolated string (`$""`, and the verbatim and raw equivalents) - // produces no `INTERPOLATED_TEXT` token at all — the lexer emits only the start - // and end delimiters, which are operators. So the expression contributed zero - // Halstead operands where the equivalent `""` contributes one, skewing volume - // and the maintainability index. Recorded here at the rule, mirroring - // `mehen-kotlin`'s `classify_empty_string_operand`. - // - // "Empty" means no content *rules*: an interpolation hole or a text run is a - // child rule, so this fires only when there are none. - if ri == cp::RULE_INTERPOLATED_STRING_EXPRESSION - && !ctx.children().any(|child| child.as_rule().is_some()) - { - self.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(SmolStr::new("\"\"")), - }); - } - self.classify_loc_rule(ctx, ri, hint); - } - - /// Classify the control-flow constructs. Roslyn gives each its own rule, so - /// these are rule-index matches rather than keyword probes. - fn classify_control_flow(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: &ChildHint) { - let eff = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - // Evidence reason detail: the grammar rule's own snake_case name. - let detail = rule_name(ri); - - // Roslyn gives each statement form its own rule, so these are rule-index - // matches rather than keyword probes on a shared - // `simple_embedded_statement`. That is also more precise: a - // `has_token(IF)` probe fires for an `if` anywhere inside the node, - // whereas a rule match cannot. - match ri { - // Cyclomatic + ABC always; cognitive nesting unless this is an - // `else if`, whose flat +1 is emitted at the `else_clause`. - cp::RULE_IF_STATEMENT => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, detail); - e.abc_condition(s, detail); - }); - if !hint.is_else_branch { - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, detail)); - } - self.current().cognitive.boolean_seq.reset(); - } - cp::RULE_WHILE_STATEMENT - | cp::RULE_DO_STATEMENT - | cp::RULE_FOR_STATEMENT - | cp::RULE_FOR_EACH_STATEMENT - | cp::RULE_FOR_EACH_VARIABLE_STATEMENT => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| { - e.decision(s, detail); - e.abc_condition(s, detail); - e.cognitive(s, delta, detail); - }); - self.current().cognitive.boolean_seq.reset(); - } - // `switch` itself adds cognitive nesting but not cyclomatic — the - // `case` labels carry the decisions. - cp::RULE_SWITCH_STATEMENT => { - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, detail)); - self.current().cognitive.boolean_seq.reset(); - } - // A switch *expression* arm (`v switch { 1 => …, _ => … }`) is the same - // decision as a `case` label and must score identically: rewriting a - // switch statement into the expression form does not make the code - // simpler, so it must not lower the score. - // - // The nesting increment belongs to the whole switch expression, not to - // each arm — but hub inlining folds `switch_expression` into - // `expression`, so it has no rule index and is handled by shape in - // `classify_expression`. Only the per-arm decision lives here. - // - // A discard arm (`_ => …`) is excluded for the same reason `default:` is - // not a decision: it is the fall-through, not a test. - // - // Each arm also starts a fresh boolean sequence. Arms are independent - // expressions — a `case`'s body reaches `RULE_BLOCK` or a statement rule and - // resets there, but an arm's result is a bare `expression` with no such - // boundary. Without the reset, `v switch { 1 => a && b, _ => c && d }` - // collapsed both `&&` into one run and scored 1 less than the equivalent - // switch statement. - cp::RULE_SWITCH_EXPRESSION_ARM => { - if !is_discard_arm(ctx) { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, detail); - e.abc_condition(s, detail); - }); - } - self.current().cognitive.boolean_seq.reset(); - } - // NOTE: `try` and `lock` deliberately score NOTHING. SonarSource's - // cognitive-complexity spec increments on `catch` (a handler is the - // structure a reader must follow), not on the `try` block itself, and - // `lock`/`synchronized` is not in the increment list at all. The - // `catch` nesting is applied at `catch_clause` below, matching - // `mehen-java`. - cp::RULE_RETURN_STATEMENT | cp::RULE_THROW_STATEMENT => { - self.current().nexit.record_exit(); - self.record_evidence(ctx, |e, s| e.exit(s, detail)); - self.current().cognitive.boolean_seq.reset(); - } - // An expression body IS the return, for a member that returns a value. - // `int F() => 1;` has no `return_statement` node at all, so NExit stayed 0 - // where `int F() { return 1; }` reported 1. `returns_value` keeps a `void` - // member, a constructor, and a `set` accessor out of it — none of those - // returns anything, so their expression body is a statement, not an exit. - // `throw` is excluded because `RULE_THROW_EXPRESSION` below records the same - // exit: `int F() => throw new E();` reported NExit 2 where the block-bodied - // `int F() { throw new E(); }` reports 1. The clause is the return only when - // it actually returns a value. - cp::RULE_ARROW_EXPRESSION_CLAUSE if hint.returns_value && !arrow_body_is_throw(ctx) => { - self.current().nexit.record_exit(); - self.record_evidence(ctx, |e, s| e.exit(s, detail)); - self.current().cognitive.boolean_seq.reset(); - } - // The same thing for a lambda, which needs its own arm because it has no - // `arrow_expression_clause` to match: Roslyn spells the body as a bare - // `(block | expression)` directly on the lambda - // (`simple_lambda_expression : … ARROW (block | expression)`). So - // `x => x + 1` reported NExit 0 while `x => { return x + 1; }` reported 1 — - // body syntax again deciding a metric. - // - // The body is the return whenever it is not a block: a lambda's expression body - // is its result by construction, and an `Action`-typed lambda whose body is a - // *statement* expression (`() => Console.WriteLine(x)`) still completes the - // delegate the same way. - // - // The one exception is an *explicitly* `void` lambda, C# 10's - // `void () => Console.WriteLine()`. That does declare a return type, and it - // declares no value — so it must not record an exit, or it disagrees with its own - // block-bodied twin. Only `parenthesized_lambda_expression` can carry a `type?`; - // `x => …` has no slot for one, which is why the check is on the child rather - // than on the rule index. - // - // A block body is excluded because its own `return` statements record the exits, - // and a `throw` body is excluded for the same reason as above: - // `RULE_THROW_EXPRESSION` records that exit itself. - cp::RULE_SIMPLE_LAMBDA_EXPRESSION | cp::RULE_PARENTHESIZED_LAMBDA_EXPRESSION - if ctx.child_rule(cp::RULE_BLOCK).is_none() - && !arrow_body_is_throw(ctx) - && !lambda_returns_void(ctx) => - { - self.current().nexit.record_exit(); - self.record_evidence(ctx, |e, s| e.exit(s, detail)); - self.current().cognitive.boolean_seq.reset(); - } - // `yield return` / `yield break` both leave the iterator. - cp::RULE_YIELD_STATEMENT => { - self.current().nexit.record_exit(); - self.record_evidence(ctx, |e, s| e.exit(s, detail)); - self.current().cognitive.boolean_seq.reset(); - } - // `goto` (including `goto case` / `goto default`) is goto-like: a - // flat +1, no nesting. - cp::RULE_GOTO_STATEMENT => { - let before = self.current().cognitive.structural; - self.current().cognitive.increment_by_one(); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, detail)); - self.current().cognitive.boolean_seq.reset(); - } - // A `case` label is a decision (cyclomatic) and a condition (ABC) in - // both its constant and pattern forms; `default:` is its own rule and - // is neither. The `switch` already opened the cognitive nesting - // level, so a `case` adds no further nesting. - cp::RULE_CASE_SWITCH_LABEL | cp::RULE_CASE_PATTERN_SWITCH_LABEL => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, detail); - e.abc_condition(s, detail); - }); - } - // A `when` guard is a distinct boolean test — on a `case` label - // (`case int i when i > 0:`) or a switch-expression arm — so it - // records one ABC condition of its own. `catch (E e) when (…)` is a - // separate rule with the same meaning. - // The guard's boolean *isolation* is handled in `visit` by the - // save/restore around its subtree, not here — see the `saved_bool` note. - cp::RULE_WHEN_CLAUSE | cp::RULE_CATCH_FILTER_CLAUSE => { - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| e.abc_condition(s, detail)); - } - // A pattern combinator (`o is int and > 5`, `is not null`) is a boolean - // decision, the same as the `&&`/`||`/`!` it replaces. C# 9 spells these - // with the contextual keywords `and`/`or`/`not` rather than the operator - // tokens `visit_terminal` scans, so without this a pattern-heavy method - // reports the complexity of a straight-line one. - // - // Hub inlining folds `binary_pattern` into `pattern` (as it does - // `binary_expression` into `expression`), so the combinator is read from - // the typed context's own `and`/`or` token rather than from a rule index. - // The run tracker is fed the actual keyword because SonarSource collapses - // a run of the *same* operator into one increment, so `a and b or c` must - // stay two. - // - // `not` is handled like the prefix `!`: it marks the run so a following - // same-kind combinator is not collapsed across the negation, but is not - // itself a decision. A relational pattern (`is > 5`) needs nothing here — - // its operator token is an ordinary `GT`/`LE`/… that `visit_terminal` - // already counts as an ABC condition. - cp::RULE_PATTERN => { - if let Some(pattern) = PatternContext::from_rule_node(ctx) { - let combinator = if pattern.kw_or_token().is_some() { - Some("or") - } else if pattern.kw_and_token().is_some() { - Some("and") - } else { - None - }; - if let Some(op) = combinator { - // Cyclomatic and ABC are order-insensitive — each combinator adds - // one wherever it is seen — so they stay here. - // - // `observe_boolean` does NOT: it tracks a *sequence*, and this - // runs pre-order, so a nested pattern's operator arrives after its - // parent's. `v is (> 0 and < 10) or (> 20 and < 30)` was observed - // as `or, and, and` — collapsing the two `and`s into one run for 2 - // — where source order is `and, or, and` and scores 3, matching - // the equivalent `(v > 0 && v < 10) || (v > 20 && v < 30)`. The - // observation therefore happens *between the operands* in - // `visit_children`. - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, op); - e.abc_condition(s, op); - }); - } - } - } - // `not` is the pattern-position `!` and behaves the same way: it is not a - // decision, and it does not break a surrounding `and`/`or` run (see the - // note on `RULE_PREFIX_UNARY_EXPRESSION` below). So `o is not null` costs - // nothing beyond the `is` test itself, and - // `o is (int and not 0) and not 1` is one `and` run. - cp::RULE_UNARY_PATTERN => {} - // `catch` is cognitive-only (matches SonarC#/SonarJava): a nesting - // increment plus an ABC condition, but no cyclomatic decision. One - // rule now covers both the typed and bare forms. - cp::RULE_CATCH_CLAUSE => { - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.cognitive(s, delta, detail); - e.abc_condition(s, detail); - }); - } - // A `throw` *expression* (`x ?? throw new E()`, C# 7) is an exit that - // the statement form above never sees. - cp::RULE_THROW_EXPRESSION => { - self.current().nexit.record_exit(); - self.record_evidence(ctx, |e, s| e.exit(s, detail)); - } - // Statement-shaped positions that are not one of the forms above - // still start a fresh boolean sequence, so operators never collapse - // across a boundary — `F(a && b); G(c && d)` is +2, not +1. - // - // `equals_value_clause` is the initializer of a field, property, or - // parameter default. It belongs here for the same reason: two sibling - // field initializers are independent boolean contexts, but they share - // the enclosing *type* space rather than a statement, so without a - // reset `bool A = x && y; bool B = u && v;` collapsed into one run and - // scored 1 where the equivalent pair of statements scores 2. - cp::RULE_EXPRESSION_STATEMENT - | cp::RULE_LOCAL_DECLARATION_STATEMENT - | cp::RULE_ARROW_EXPRESSION_CLAUSE - | cp::RULE_EQUALS_VALUE_CLAUSE - | cp::RULE_BLOCK => { - self.current().cognitive.boolean_seq.reset(); - } - // NOTE: the prefix `!` deliberately does NOTHING here. - // - // Both SonarJava (`CognitiveComplexityVisitor.flattenLogicalExpression`) - // and SonarKotlin (`CognitiveComplexity.flattenOperators`) flatten only - // the `&&`/`||` operators, treating a negated operand as a plain operand - // where flattening stops — the `!` is invisible to the run. So - // `a && !b && c` is a single `&&` run and costs exactly what - // `a && b && c` costs. - // - // This previously called `boolean_seq.not_operator("!")`, which broke the - // run and scored 2 where `mehen-java` scored 1 on identical logic. The - // comment justifying it claimed parity with Kotlin — and `mehen-kotlin` - // did score 2 — but Kotlin was the deviation, not the reference: - // `mehen-java`'s `negation_does_not_break_boolean_run` cites *both* Sonar - // implementations, SonarKotlin's included, for the correct behaviour. - // `mehen-kotlin` was fixed in issue #217 and now agrees. - _ => {} - } - } - - /// Classify the inlined `expression` rule. - /// - /// Hub inlining (upstream #221) folds `invocation_expression`, - /// `assignment_expression`, `binary_expression`, and `conditional_expression` - /// into `expression`, so none has a rule index of its own. Classification is - /// therefore by *shape*, read entirely through the typed context: - /// - /// | form | `expression_children` | distinguishing feature | - /// |---------------------|-----------------------|------------------------| - /// | invocation `F(x)` | 1 | has an `argument_list` | - /// | binary `a + b` | 2 | the operator terminal | - /// | assignment `y = 1` | 2 | the operator terminal | - /// | ternary `a ? b : c` | 3 | a `?` terminal | - /// - /// `direct_terminals()` (upstream #271) is what makes the operator readable - /// without dropping to untyped scanning: it yields only the node's *own* - /// terminals, so an operator from a nested subexpression cannot leak in. - fn classify_expression(&mut self, ctx: RuleNodeView<'_>, ri: usize) { - if ri != cp::RULE_EXPRESSION { - return; - } - let Some(expr) = ExpressionContext::from_rule_node(ctx) else { - return; - }; - - // A call or object creation is a branch (ABC's B counts function calls, - // method calls, and message sends). - // - // Member access (`a.B`) is deliberately NOT counted: it is the - // qualification `.B`, not a call. Counting it would (a) score a plain - // field/property *read* as a branch, which ABC does not, and (b) score a - // qualified call twice, since `o.Helper()` nests a member access inside - // the invocation. Counting only the invocation keeps one branch per call - // regardless of qualification depth, matching `mehen-java` (which counts - // `methodCall`/`creator`, never field access). - // - // `nameof(x)` is excluded: it has the invocation shape but is a - // compile-time operator that evaluates to a string constant — no call is - // made, nothing is dispatched, and the argument is never evaluated. Scoring - // it as a branch would rank `throw new ArgumentNullException(nameof(arg))` - // above the same throw with a literal. (`typeof`/`sizeof`/`default` are - // dedicated rules and so never reach here at all; `nameof` is only a - // contextual keyword, so it parses as an ordinary invocation and has to be - // filtered by name.) - if expr.argument_list().is_some() && !is_nameof_callee(&expr) { - self.current().abc.record_branch(); - // Hub inlining folds `invocation_expression` into `expression`, so - // the Roslyn syntax-node name is spelled out rather than read from - // the rule table. - self.record_evidence(ctx, |e, s| e.abc_branch(s, "invocation_expression")); - } - - // `>>=` and `>>>=` are the only assignment operators the prep splits into - // separate tokens (`GT GE` / `GT GT GE`), so they reach this node as child - // *rules* rather than as an operator terminal and the token match below - // never sees them. Without this, `a >>= 2` scores no assignment while the - // otherwise-identical `a <<= 2` scores one. - if expr.right_shift_assignment().is_some() - || expr.unsigned_right_shift_assignment().is_some() - { - self.current().abc.record_assignment(); - let detail = if expr.right_shift_assignment().is_some() { - "right_shift_assignment" - } else { - "unsigned_right_shift_assignment" - }; - self.record_evidence(ctx, |e, s| e.abc_assignment(s, detail)); - } - - // A switch expression nests exactly like a switch statement (SonarSource - // scores both the same way). Recognised by its `switch` keyword, since hub - // inlining leaves it without a rule index of its own. Its arms carry the - // decisions, recorded at `switch_expression_arm`. - if expr.kw_switch_token().is_some() { - let eff = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, "switch_expression")); - self.current().cognitive.boolean_seq.reset(); - } - - for terminal in expr.direct_terminals() { - // A recovery-inserted token is not in the source, so scoring it would - // invent a metric the file never contained. - if terminal.is_error() { - continue; - } - match terminal.symbol().token_type() { - // Every assignment form (`=`, compound, `??=`) is one A. - cl::EQ - | cl::PLUS_EQ - | cl::MINUS_EQ - | cl::STAR_EQ - | cl::SLASH_EQ - | cl::PERCENT_EQ - | cl::AMP_EQ - | cl::CARET_EQ - | cl::PIPE_EQ - | cl::LT_LT_EQ - | cl::QUESTION_QUESTION_EQ => { - self.current().abc.record_assignment(); - self.record_evidence(ctx, |e, s| e.abc_assignment(s, "assignment_expression")); - } - // The ternary `?:` — a decision, an ABC condition, and a - // cognitive nesting structure (SonarSource scores it like an - // `if`). Keyed on `?` so the `:` does not score a second time. - // - // NOTE: a *null-conditional* access (`a?.B`, `a?[i]`) also carries a - // bare `?` and is NOT scored anywhere — see the module header. It - // arguably should be an ABC condition (it short-circuits on null, - // exactly as `??` does, and `??` counts), but hub inlining scatters - // its `?` onto an inner `expression` node holding only the receiver, - // and `member_binding_expression`/`element_binding_expression` are - // inlined too — so neither the token nor a rule index is a reliable - // anchor. Left as a known gap rather than a half-working match that - // fires on some chains and not others. - cl::QUESTION => { - let eff = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cyclomatic.record_decision(); - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, "conditional_expression"); - e.cognitive(s, delta, "conditional_expression"); - e.abc_condition(s, "conditional_expression"); - }); - } - // The type tests. Equality, relational, `&&`/`||`, and `??` are - // counted by the token-level scan in `visit_terminal`, which sees - // every token exactly once — so they must not be counted again - // here. - cl::KW_IS | cl::KW_AS => { - let op = if terminal.symbol().token_type() == cl::KW_IS { - "is" - } else { - "as" - }; - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| e.abc_condition(s, op)); - } - _ => {} - } - } - } - - /// ABC accounting for the non-`expression` rules that carry an assignment or - /// a branch. - fn classify_abc_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: &ChildHint) { - // Evidence reason detail: the grammar rule's own snake_case name. - let detail = rule_name(ri); - match ri { - // Object creation is its own rule rather than part of the inlined - // expression cycle, so its branch is recorded here. - // - // The two `stackalloc` forms allocate exactly as the heap forms do, just on - // the stack, so they belong in the same list — without them - // `stackalloc int[4]` scored no branch while `new int[4]` scored one. - // - // `primary_constructor_base_type` is the primary-constructor spelling of a - // base-constructor call: `class D(int x) : B(x)` is the same call as - // `D(int x) : base(x)`, which reaches `constructor_initializer`. Without it - // the two forms disagreed, 0 branches against 1. - // `anonymous_object_creation_expression` (`new { A = 1 }`) belongs here - // too. It has no `argument_list`, so `classify_expression`'s invocation - // shape never sees it, and a real allocation scored nothing. - // C# 12 collection expressions (`int[] v = [1, 2];`) allocate exactly as - // `new[] { 1, 2 }` does — the spelling changed, not the operation. - cp::RULE_OBJECT_CREATION_EXPRESSION - | cp::RULE_IMPLICIT_OBJECT_CREATION_EXPRESSION - | cp::RULE_ANONYMOUS_OBJECT_CREATION_EXPRESSION - | cp::RULE_ARRAY_CREATION_EXPRESSION - | cp::RULE_IMPLICIT_ARRAY_CREATION_EXPRESSION - | cp::RULE_COLLECTION_EXPRESSION - | cp::RULE_STACK_ALLOC_ARRAY_CREATION_EXPRESSION - | cp::RULE_IMPLICIT_STACK_ALLOC_ARRAY_CREATION_EXPRESSION - | cp::RULE_CONSTRUCTOR_INITIALIZER - | cp::RULE_PRIMARY_CONSTRUCTOR_BASE_TYPE => { - self.current().abc.record_branch(); - self.record_evidence(ctx, |e, s| e.abc_branch(s, detail)); - } - // A *bare* initializer is an allocation: `int[] v = { 1, 2 };` has no `new` - // and no `[…]`, so Roslyn puts an `initializer_expression` directly on the - // right-hand side and nothing above fired — it scored 0 where `new[] { 1, 2 }` - // and `[1, 2]` each scored 1. - // - // Guarded on `in_creation_expression` because a creation *nests* an - // initializer for its elements, and counting the rule unconditionally would - // score `new[] { 1, 2 }` twice. - cp::RULE_INITIALIZER_EXPRESSION if !hint.in_creation_expression => { - self.current().abc.record_branch(); - self.record_evidence(ctx, |e, s| e.abc_branch(s, detail)); - } - // A *named* anonymous-object member (`new { A = 1 }`) is an assignment. - // Roslyn puts the `A =` in a `name_equals` child of - // `anonymous_object_member_declarator`, so it is neither an - // assignment-shaped `expression` nor an `equals_value_clause` — it was - // recording nothing, while the equivalent `new C { A = 1 }` recorded one. - // - // Matched at the *declarator* rather than at `name_equals`, because that - // rule is shared with using-alias and attribute-argument names, which are - // not assignments. The unnamed form (`new { x }`, inferring the member name - // from the expression) has no `name_equals` child and correctly records - // nothing. - cp::RULE_ANONYMOUS_OBJECT_MEMBER_DECLARATOR - if ctx.child_rule(cp::RULE_NAME_EQUALS).is_some() => - { - self.current().abc.record_assignment(); - self.record_evidence(ctx, |e, s| e.abc_assignment(s, detail)); - } - // A LINQ `where` is a filter predicate — the query-expression equivalent of - // an `if`, and one ABC condition. Its own comparison (if any) is counted - // separately by the token scan, exactly as `if (x > 0)` counts two; a - // predicate that is already boolean (`where enabled`) has no comparison and - // so scored nothing at all before this. - cp::RULE_WHERE_CLAUSE => { - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| e.abc_condition(s, detail)); - } - // A LINQ `join … on a.Id equals b.Id` is an equality test, so it is a - // condition for the same reason. `equals` is the join's comparison operator, - // but Roslyn spells it as the `KW_EQUALS` contextual keyword rather than as - // an `==` token — so the token-level condition scan never saw it and the - // whole join predicate scored zero, while the method-syntax spelling - // (`xs.Where(a => ys.Any(b => a == b))`) scored one. - // - // Recorded on the clause rather than on the token, matching `where`: the - // clause is the unit that exists exactly once per comparison, and `equals` - // stays a legal identifier elsewhere (it is contextual, so a variable named - // `equals` must not score). - cp::RULE_JOIN_CLAUSE => { - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| e.abc_condition(s, detail)); - } - // An initialized declarator is an assignment. Roslyn spells the - // initializer as an `equals_value_clause` child rather than a bare - // `=` token, so the presence of that child *is* the initialization. - // - // `property_declaration` is here for the auto-property initializer - // (`public int P { get; set; } = 5;`), which carries the clause directly - // on the declaration rather than through a `variable_declarator` — so it - // scored no assignment at all while the equivalent field - // (`public int P = 5;`) scored one. - // - // `local_variable_declarator` is the statement-position declarator the - // prep mints so `await tasks[i];` cannot parse as a declaration (locals - // have no bracketed declarator in real C#); it initializes exactly as - // `variable_declarator` does. - cp::RULE_VARIABLE_DECLARATOR - | cp::RULE_LOCAL_VARIABLE_DECLARATOR - | cp::RULE_PARAMETER - | cp::RULE_ENUM_MEMBER_DECLARATION - | cp::RULE_PROPERTY_DECLARATION - if ctx.child_rule(cp::RULE_EQUALS_VALUE_CLAUSE).is_some() => - { - self.current().abc.record_assignment(); - self.record_evidence(ctx, |e, s| e.abc_assignment(s, detail)); - } - // A query `let` binds a name to a value (`from x in s let y = f(x) …`), - // which is an assignment by any reading. Its `=` is a bare token on - // `let_clause : KW_LET identifier_token EQ expression` rather than an - // `equals_value_clause`, and `let_clause` is not part of the inlined - // `expression`, so neither the token scan nor `classify_expression` saw it. - cp::RULE_LET_CLAUSE => { - self.current().abc.record_assignment(); - self.record_evidence(ctx, |e, s| e.abc_assignment(s, detail)); - } - _ => {} - } - } - - fn classify_loc_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: &ChildHint) { - // A **primary constructor** opens its space at the `parameter_list`, which is not a - // declaration rule, so the space had no logical line of its own — `class C(int x)` - // reported 0 where `class C { C(int x) { } }` reports 1. Its declaration IS the - // parameter list (Roslyn synthesizes no `constructor_declaration`), so the line is - // recorded here. - // - // Exactly the precedent the lambda arm just below sets, which is what settles a - // worry that this double-counts the `class C(int x)` row: the row belongs to the - // *class* space, recorded by `class_declaration`, and this is the *constructor* - // space's own line. Two spaces, one row each, as with a lambda inside a method. - if ri == cp::RULE_PARAMETER_LIST && hint.primary_ctor_name.is_some() { - self.current().loc.observe_lloc(); - } - // An *expression-bodied* lambda (`x => x + 1`) opens a closure space - // but its body contains no statement/declaration, so the closure would - // report `lloc = 0`. Count the lambda itself as one logical line to - // match a block-bodied lambda (whose inner statements already count). - if matches!( - ri, - cp::RULE_SIMPLE_LAMBDA_EXPRESSION | cp::RULE_PARENTHESIZED_LAMBDA_EXPRESSION - ) && !lambda_body_is_block(ctx) - { - self.current().loc.observe_lloc(); - return; - } - // An expression-bodied accessor (`get => _x;`) opens a space whose only - // content is that expression — no statement — so the space would report - // `lloc = 0` without counting the body itself as one logical line. - // - // Roslyn spells every expression body as `arrow_expression_clause`, so - // this is one rule rather than the old `body`/`accessor_body`/ - // `local_function_body` trio. - // - // It must fire only where the enclosing declaration is not itself counted - // below, or `int F() => 1;` would count twice. `in_accessor_body` marks - // the one case that needs it: an `accessor_declaration` opens a space but - // is not a logical line of its own, so an expression-bodied accessor has - // nothing else to count. - if ri == cp::RULE_ARROW_EXPRESSION_CLAUSE && hint.in_accessor_body { - self.current().loc.observe_lloc(); - return; - } - - if matches!( - ri, - // Statement-shaped rules. Roslyn gives each statement form its own - // rule, so this replaces the single `simple_embedded_statement`. - cp::RULE_EXPRESSION_STATEMENT - | cp::RULE_LOCAL_DECLARATION_STATEMENT - | cp::RULE_LOCAL_FUNCTION_STATEMENT - | cp::RULE_IF_STATEMENT - | cp::RULE_WHILE_STATEMENT - | cp::RULE_DO_STATEMENT - | cp::RULE_FOR_STATEMENT - | cp::RULE_FOR_EACH_STATEMENT - | cp::RULE_FOR_EACH_VARIABLE_STATEMENT - | cp::RULE_SWITCH_STATEMENT - | cp::RULE_TRY_STATEMENT - | cp::RULE_USING_STATEMENT - | cp::RULE_LOCK_STATEMENT - | cp::RULE_FIXED_STATEMENT - | cp::RULE_CHECKED_STATEMENT - | cp::RULE_UNSAFE_STATEMENT - | cp::RULE_RETURN_STATEMENT - | cp::RULE_THROW_STATEMENT - | cp::RULE_YIELD_STATEMENT - | cp::RULE_BREAK_STATEMENT - | cp::RULE_CONTINUE_STATEMENT - | cp::RULE_GOTO_STATEMENT - // Declaration-shaped rules. `empty_statement` is deliberately - // absent: a bare `;` is not a logical line. So is `block`, which - // is a wrapper whose inner statements each count — and so is - // `labeled_statement`, which wraps the statement it labels: - // `start: return;` is one logical line, not two, and a label is an - // attribute of its inner statement rather than an executable statement - // of its own. (`mehen-java` omits the equivalent wrapper for the same - // reason.) - | cp::RULE_FIELD_DECLARATION - | cp::RULE_EVENT_FIELD_DECLARATION - | cp::RULE_EVENT_DECLARATION - | cp::RULE_METHOD_DECLARATION - | cp::RULE_CONSTRUCTOR_DECLARATION - | cp::RULE_DESTRUCTOR_DECLARATION - | cp::RULE_OPERATOR_DECLARATION - | cp::RULE_CONVERSION_OPERATOR_DECLARATION - | cp::RULE_PROPERTY_DECLARATION - | cp::RULE_INDEXER_DECLARATION - | cp::RULE_ENUM_MEMBER_DECLARATION - | cp::RULE_CLASS_DECLARATION - | cp::RULE_STRUCT_DECLARATION - | cp::RULE_INTERFACE_DECLARATION - | cp::RULE_ENUM_DECLARATION - | cp::RULE_RECORD_DECLARATION - | cp::RULE_UNION_DECLARATION - // A C# 14 `extension(T x) { … }` block is a declaration like any - // other type container, even though it declares no *name*. Omitting - // it made an extension holding one method report LLOC 1 where the - // analogous `class Inner { … }` container reports 2 — the container - // row itself went uncounted. - | cp::RULE_EXTENSION_BLOCK_DECLARATION - | cp::RULE_DELEGATE_DECLARATION - | cp::RULE_NAMESPACE_DECLARATION - | cp::RULE_FILE_SCOPED_NAMESPACE_DECLARATION - | cp::RULE_USING_DIRECTIVE - | cp::RULE_EXTERN_ALIAS_DIRECTIVE - ) { - self.current().loc.observe_lloc(); - } - } - - /// NPA / NPM classification for a direct member of an enclosing type body. - /// `ctx` is the member declaration rule itself; `public` is the visibility - /// resolved from the member wrapper's modifiers (threaded via [`ChildHint`]). - fn classify_type_member( - &mut self, - ctx: RuleNodeView<'_>, - ri: usize, - container: ContainerKind, - public: bool, - ) { - // Evidence reason detail: the grammar rule's own snake_case name. Only - // *public* members are evidenced — the headline NPA/NPM count public - // members only, and `container` here is always class- or - // interface-like (it comes from `ChildHint::member_container`), so - // `public` alone decides whether the metric moved. - let detail = rule_name(ri); - match ri { - // A field or event-field declaration can declare several variables - // (`int a, b, c;` / `event E a, b;`). `const` is a modifier here - // rather than a separate rule, so there is no `constant_declaration` - // arm — a `const int a, b;` reaches this same path. - cp::RULE_FIELD_DECLARATION | cp::RULE_EVENT_FIELD_DECLARATION => { - let count = declarator_count(ctx).max(1); - for _ in 0..count { - self.current().npa.record_attribute(container, public); - } - if public { - self.record_evidence(ctx, |e, s| { - for _ in 0..count { - e.public_attribute(s, detail); - } - }); - } - } - // A named `event` with accessors declares exactly one member. - cp::RULE_EVENT_DECLARATION => { - self.current().npa.record_attribute(container, public); - if public { - self.record_evidence(ctx, |e, s| e.public_attribute(s, detail)); - } - } - // An `enum` member (`enum E { A, B }`) is a public constant field - // of the enum → a public class attribute. - cp::RULE_ENUM_MEMBER_DECLARATION => { - self.current() - .npa - .record_attribute(ContainerKind::Class, true); - self.record_evidence(ctx, |e, s| e.public_attribute(s, detail)); - } - // Methods, constructors, operators, and the property/indexer forms - // are all methods for NPM purposes (SonarC# counts a property as a - // member of the type's public API). - cp::RULE_METHOD_DECLARATION - | cp::RULE_CONSTRUCTOR_DECLARATION - | cp::RULE_DESTRUCTOR_DECLARATION - | cp::RULE_OPERATOR_DECLARATION - | cp::RULE_CONVERSION_OPERATOR_DECLARATION - | cp::RULE_PROPERTY_DECLARATION - | cp::RULE_INDEXER_DECLARATION => { - self.current().npm.record_method(container, public); - if public { - self.record_evidence(ctx, |e, s| e.public_method(s, detail)); - } - } - _ => {} - } - } -} - -// -------------------------------------------------------------------- -// Free helpers (top-down tree inspection — no parent pointers). -// -------------------------------------------------------------------- - -/// Whether a declared return type yields no value, so an expression body is not a -/// return for NExit purposes. -/// -/// `void` is unconditional. The non-generic awaitables are void-like **only when the -/// method is `async`**, and that distinction is the whole point of the `is_async` -/// parameter: `async` makes the compiler wrap the body's completion in the task, so -/// `async Task M() => await Work();` produces no result — but a non-async -/// `Task M() => Task.CompletedTask;` must literally return a task object, and its -/// block-bodied twin `Task M() { return Task.CompletedTask; }` records an exit. -/// -/// So "is this void-like" is not a property of the type alone. Ignoring `async` fixed -/// the async case and broke the non-async one, which is the same -/// body-syntax-dependent NExit in a different place. -/// -/// `Task` and `ValueTask` return a value even when `async`, which is why only the -/// bare names match. -/// -/// Matched on the type's text, which is all a syntax-only walker has: `System.Threading` -/// is not resolved, so a user-defined type literally named `Task` in an `async` method -/// would be treated as void-like. That is the same class of trade the grammar makes for -/// contextual keywords, and `async` narrows it a great deal — an `async` method whose -/// return type is a *non-awaitable* type named `Task` does not compile. -/// -/// `global::`-qualified and namespace-qualified spellings are accepted by comparing the -/// last dot-separated segment, so `System.Threading.Tasks.Task` matches. Any generic -/// argument list makes the text end in `>`, which no bare name does, so `Task` -/// cannot match by construction. -fn type_is_void_like(text: &str, is_async: bool) -> bool { - let name = text.rsplit(['.', ':']).next().unwrap_or(text).trim(); - name == "void" || (is_async && matches!(name, "Task" | "ValueTask")) -} - -/// Does this declaration carry the `async` modifier? -/// -/// `async` is a `modifier` child rule rather than a direct token of the declaration -/// (Roslyn folds every modifier into one rule), so it cannot be found with `has_token`. -fn is_async(ctx: RuleNodeView<'_>) -> bool { - ctx.child_rules(cp::RULE_MODIFIER) - .any(|m| m.has_token(cl::KW_ASYNC)) -} - -/// Reduce an identifier token's text to the *name* it denotes, for use as a -/// Halstead operand key. -/// -/// Two things in C# are spelling, not name (§6.4.3): -/// -/// - the verbatim prefix `@`, which exists only to let a keyword be used as a name -/// (`@class`), and is not part of the identifier; -/// - Unicode escapes, which are legal identifier characters — `int a = 1;` -/// declares `a`, and `a` and `a` are the same identifier. -/// -/// So `@x` and `x` must share one operand, as must `a` and `a`. Returns the input -/// unchanged (no allocation beyond the `SmolStr`) when neither applies, which is every -/// ordinary identifier. -/// -/// A malformed escape is left verbatim rather than dropped: the lexer's `UnicodeEscape` -/// fragment cannot produce one, but a recovered error token can hold arbitrary text, and -/// silently deleting characters would merge unrelated operands. -fn normalize_identifier(text: &str) -> SmolStr { - let body = text.strip_prefix('@').unwrap_or(text); - if !body.contains('\\') { - // The common path: no escape to decode, so at most the `@` was removed. - return SmolStr::new(body); - } - let mut out = String::with_capacity(body.len()); - let mut rest = body; - while let Some(slash) = rest.find('\\') { - out.push_str(&rest[..slash]); - // `\uXXXX` (4 digits) or `\UXXXXXXXX` (8), per the grammar's `UnicodeEscape`. - let after = &rest[slash + 1..]; - let width = match after.as_bytes().first() { - Some(b'u') => 4, - Some(b'U') => 8, - _ => 0, - }; - let decoded = (width > 0) - .then(|| after.get(1..=width)) - .flatten() - .and_then(|hex| u32::from_str_radix(hex, 16).ok()) - .and_then(char::from_u32); - match decoded { - Some(ch) => { - out.push(ch); - rest = &after[1 + width..]; - } - // Not a well-formed escape — keep the backslash and carry on so nothing - // is lost. - None => { - out.push('\\'); - rest = after; - } - } - } - out.push_str(rest); - SmolStr::new(out) -} - -/// Whether a `base_type` entry is the **base-constructor call** of a primary -/// constructor (`primary_constructor_base_type`: `B(x)`), as opposed to a -/// `simple_base_type` (an implemented interface, or a base class without an -/// argument list). Only the call is constructor syntax; everything else in the -/// base list belongs to the type. -fn base_type_is_base_call(base_type: RuleNodeView<'_>) -> bool { - base_type - .child_rule(cp::RULE_PRIMARY_CONSTRUCTOR_BASE_TYPE) - .is_some() -} - -/// Whether a `base_list` contains a base-constructor call — i.e. whether a -/// primary constructor's synthetic space must stay open into the list (see -/// `visit_children`) rather than closing at the end of its `parameter_list`. -fn base_list_has_base_call(base_list: RuleNodeView<'_>) -> bool { - base_list - .child_rules(cp::RULE_BASE_TYPE) - .any(base_type_is_base_call) -} - -/// Rules that open a type-like metric space (see `maybe_open_space`). -fn opens_type_like(ri: usize) -> bool { - matches!( - ri, - cp::RULE_CLASS_DECLARATION - | cp::RULE_STRUCT_DECLARATION - | cp::RULE_INTERFACE_DECLARATION - | cp::RULE_ENUM_DECLARATION - | cp::RULE_DELEGATE_DECLARATION - // Roslyn models `record` / `record struct` as their own node rather - // than a modifier on a class, so it is a peer here. - | cp::RULE_RECORD_DECLARATION - // A `union` is a type declaration like any other in this grammar. Without - // it the declaration opened no space at all, so a union's members attached - // to the enclosing type or unit and its NPA/NPM/WMC vanished. - | cp::RULE_UNION_DECLARATION - // A C# 14 `extension(T x) { … }` block is a member container in its own - // right: it holds `member_declaration*` exactly as a class body does. It - // has no name of its own, so the space is anonymous — but it must open - // one, or its members would attach to the enclosing static class and - // report as that class's methods. - | cp::RULE_EXTENSION_BLOCK_DECLARATION - ) -} - -/// Rules that open a function/closure metric space (mirrors the function arms -/// of `maybe_open_space`). -/// -/// Roslyn declares one rule per accessor *list* entry rather than one per -/// accessor keyword, so a single `accessor_declaration` covers get/set/init/ -/// add/remove — the keyword is a child token, not part of the rule name. -fn opens_function_space(ri: usize) -> bool { - matches!( - ri, - cp::RULE_METHOD_DECLARATION - | cp::RULE_CONSTRUCTOR_DECLARATION - | cp::RULE_DESTRUCTOR_DECLARATION - | cp::RULE_OPERATOR_DECLARATION - | cp::RULE_CONVERSION_OPERATOR_DECLARATION - | cp::RULE_LOCAL_FUNCTION_STATEMENT - | cp::RULE_ACCESSOR_DECLARATION - // Lambdas are split by parameter shape (`x => …` vs `(x, y) => …`), - // and `delegate { … }` is a third node. - | cp::RULE_SIMPLE_LAMBDA_EXPRESSION - | cp::RULE_PARENTHESIZED_LAMBDA_EXPRESSION - | cp::RULE_ANONYMOUS_METHOD_EXPRESSION - ) -} - -/// Whether a lambda's body is a block (`… => { … }`) rather than an expression. -/// A block body's statements are counted individually for LLOC; an expression -/// body makes the lambda itself one logical line. -/// -/// Roslyn writes the body as `(block | expression)` directly on the lambda rule, -/// so there is no `anonymous_function_body` wrapper to descend through. -fn lambda_body_is_block(ctx: RuleNodeView<'_>) -> bool { - ctx.child_rule(cp::RULE_BLOCK).is_some() -} - -/// Whether an `else_clause`'s body is a bare `if_statement` — i.e. this is an -/// `else if` chain rather than a nested `if` inside an `else` block. -/// -/// Roslyn spells the else branch as its own `else_clause : KW_ELSE statement` -/// rule, so this is one direct-child check. (grammars-v4 wrote -/// `if_statement : IF (…) if_body (ELSE if_body)?`, which forced the walker to -/// find the `if_body` appearing *after* the `ELSE` terminal by index, then track -/// transparency through an `if_body`/`embedded_statement`/`statement` chain.) -/// -/// A block stops the chain: `else { if … }` is genuinely nested, and so is a -/// statement with its own control-flow keyword. -fn else_clause_is_else_if(ctx: RuleNodeView<'_>) -> bool { - ctx.child_rule(cp::RULE_STATEMENT) - .and_then(|stmt| stmt.child_rule(cp::RULE_IF_STATEMENT)) - .is_some() -} - -/// The declared name of a member/type: its first `identifier` child's covered -/// text. Falls back to the `member_name`/`method_member_name` wrapper's text -/// for the members that spell their name through one. -fn name_from_identifier(ctx: RuleNodeView<'_>) -> Option { - for child in ctx.children() { - let Some(c) = child.as_rule() else { continue }; - // Roslyn spells every declared name as `identifier_token`; there is no - // `member_name` / `method_member_name` indirection. - if c.rule_index() == cp::RULE_IDENTIFIER_TOKEN { - let t = c.text(); - if !t.is_empty() { - return Some(t); - } - } - } - None -} - -/// The space name for a function-shaped node. Accessors have no name of their -/// own, so they are named `.get` / `.set` / `.add` / `.remove` from the -/// property/indexer/event name threaded down through [`ChildHint`]. -fn function_name(ctx: RuleNodeView<'_>, hint: &ChildHint) -> Option { - // An expression-bodied property / indexer is its own implicit getter, named - // to match the block form so `int P => 1;` and `int P { get { … } }` report - // the same space name. - if matches!( - ctx.rule_index(), - cp::RULE_PROPERTY_DECLARATION | cp::RULE_INDEXER_DECLARATION - ) { - let owner = if ctx.rule_index() == cp::RULE_INDEXER_DECLARATION { - Some(SmolStr::new("this[]")) - } else { - name_from_identifier(ctx).map(SmolStr::new) - }; - return Some(match owner { - Some(name) => format!("{name}.get"), - None => "get".to_string(), - }); - } - // One `accessor_declaration` covers every accessor kind, with the keyword as - // a direct child token — so the kind is read rather than inferred from which - // of five rules matched. That also picks up `init` (C# 9), which the - // grammars-v4 shape had no rule for. - if ctx.rule_index() == cp::RULE_ACCESSOR_DECLARATION { - let suffix = if ctx.has_token(cl::KW_GET) { - "get" - } else if ctx.has_token(cl::KW_SET) { - "set" - } else if ctx.has_token(cl::KW_INIT) { - "init" - } else if ctx.has_token(cl::KW_ADD) { - "add" - } else if ctx.has_token(cl::KW_REMOVE) { - "remove" - } else { - // The grammar also allows a bare `identifier_token` here, for - // Roslyn's error-recovery shapes. - "accessor" - }; - return Some(match &hint.accessor_owner { - Some(owner) => format!("{owner}.{suffix}"), - None => suffix.to_string(), - }); - } - // An operator's name is `operator `. Roslyn spells the operator as a - // direct token choice on the declaration (`… KW_OPERATOR KW_CHECKED? (PLUS | - // MINUS | …)`) rather than a separate `overloadable_operator` rule, so the - // symbol is read from the token that follows `operator`. Using the token text - // avoids mapping ~30 token types by hand, and `direct_terminals()` cannot - // reach into the parameter list or body. - if ctx.rule_index() == cp::RULE_OPERATOR_DECLARATION { - // Four of the 35 symbol alternatives are child *rules* rather than terminals: - // the prep splits `>>` / `>>>` / `>>=` / `>>>=` into adjacent `>` tokens gated by - // an adjacency predicate, so they are `right_shift`, `unsigned_right_shift`, and - // the two assignment forms. Checked first, because the terminal scan below cannot - // see them at all — it walked straight past to the `;` and named the space - // `operator ;`, which is worse than the fallback it was supposed to hit. - for (rule, symbol) in [ - (cp::RULE_RIGHT_SHIFT, ">>"), - (cp::RULE_UNSIGNED_RIGHT_SHIFT, ">>>"), - (cp::RULE_RIGHT_SHIFT_ASSIGNMENT, ">>="), - (cp::RULE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT, ">>>="), - ] { - if ctx.child_rule(rule).is_some() { - return Some(format!("operator {symbol}")); - } - } - // The symbol is spelled out rather than taken from the child's text because the - // split tokens are not adjacent in the tree's own text rendering — `>>` would come - // back as `> >`, so the name would not match what the author wrote. - let typed = OperatorDeclarationContext::from_rule_node(ctx)?; - let mut seen_operator_keyword = false; - for terminal in typed.direct_terminals() { - let tt = terminal.symbol().token_type(); - if tt == cl::KW_OPERATOR { - seen_operator_keyword = true; - } else if seen_operator_keyword && tt != cl::KW_CHECKED { - let symbol = terminal.symbol().text().unwrap_or_default(); - return Some(format!("operator {symbol}")); - } - } - return Some("operator".to_string()); - } - // A conversion operator is named by its target type (`implicit operator int`), - // which is a rule child rather than a token — so it needs the `type` child's text - // rather than a `direct_terminals()` scan. Without it, a type declaring - // conversions to several targets reported every one as a bare `operator`, - // indistinguishable in per-function output. - // - // The `implicit`/`explicit` keyword is deliberately left out of the name: the two - // cannot both convert to the same target (C# forbids it), so the target type alone - // is unique within a type. - if ctx.rule_index() == cp::RULE_CONVERSION_OPERATOR_DECLARATION { - return Some( - ctx.child_rule(cp::RULE_TYPE) - .map(|target| format!("operator {}", target.text())) - .unwrap_or_else(|| "operator".to_string()), - ); - } - // A lambda / anonymous method is anonymous. - if matches!( - ctx.rule_index(), - cp::RULE_SIMPLE_LAMBDA_EXPRESSION - | cp::RULE_PARENTHESIZED_LAMBDA_EXPRESSION - | cp::RULE_ANONYMOUS_METHOD_EXPRESSION - ) { - return None; - } - // Every other function-shaped declaration — including a local function — - // carries its own `identifier_token` directly, so there is no header rule to - // descend into. - name_from_identifier(ctx) -} - -/// The property/indexer/event name to thread down to its accessors, if `ctx` is -/// one of those member forms. -fn accessor_owner_name(ctx: RuleNodeView<'_>, ri: usize) -> Option { - match ri { - cp::RULE_PROPERTY_DECLARATION | cp::RULE_EVENT_DECLARATION => { - name_from_identifier(ctx).map(SmolStr::new) - } - cp::RULE_INDEXER_DECLARATION => Some(SmolStr::new("this[]")), - _ => None, - } -} - -/// Count the declared parameters of a function-shaped node. -/// -/// Roslyn spells every parameter position with the same `parameter` rule, so one -/// lookup covers methods, constructors, operators, local functions, parenthesized -/// lambdas, and anonymous methods alike. (grammars-v4 needed five distinct shapes — -/// `fixed_parameter`, `parameter_array`, `arg_declaration`, -/// `explicit_anonymous_function_parameter`, and a bare identifier — because LL -/// parsing forced a separate rule per position.) A `params` array is a `KW_PARAMS` -/// modifier on an ordinary parameter, so it counts as one. -/// -/// Two positions are not a `parameter_list` and need naming: -/// - `simple_lambda_expression : … identifier_token ARROW …` — the one parameter is -/// a bare identifier, with no `parameter` node at all. -/// - `accessor_declaration` — an accessor's arity is its owning *indexer*'s, which -/// lives on `indexer_declaration`, not on the accessor. Threaded down through -/// [`ChildHint::accessor_args`]. -fn count_args(ctx: RuleNodeView<'_>, hint: &ChildHint) -> u32 { - match ctx.rule_index() { - // `x => …`: the single parameter is a bare `identifier_token`, so there is no - // `parameter` child to count. Its arity is always exactly one — the grammar - // has no zero- or multi-parameter form of this rule (`() => …` and - // `(a, b) => …` are both `parenthesized_lambda_expression`). - cp::RULE_SIMPLE_LAMBDA_EXPRESSION => 1, - // An accessor of an indexer takes the indexer's parameters (`this[int i]`'s - // getter is a one-argument function); a property's accessor takes none. - // Either way the count comes from the owner, since `accessor_declaration` - // carries no parameter list of its own — without this, NArgs for the *same* - // indexer differed by body syntax, because the expression-bodied form opens - // its space at `indexer_declaration` where the list IS present. - cp::RULE_ACCESSOR_DECLARATION => hint.accessor_args, - // An indexer's parameters are bracketed (`this[int i]`). - _ => ctx - .child_rule(cp::RULE_PARAMETER_LIST) - .or_else(|| ctx.child_rule(cp::RULE_BRACKETED_PARAMETER_LIST)) - .map(count_parameters) - .unwrap_or(0), - } -} - -/// Count the non-empty `parameter` children of `ctx`. -/// -/// Every element of Roslyn's `parameter` rule is optional, so it matches the -/// empty string — `Zero()` parses as a `parameter_list` containing one *empty* -/// `parameter`. (The generator flags this as `G4A004`.) That is deliberate in -/// Roslyn's model, which has a node for every slot including absent ones, so the -/// walker filters rather than the grammar being changed. -fn count_parameters(ctx: RuleNodeView<'_>) -> u32 { - ctx.child_rules(cp::RULE_PARAMETER) - .filter(|parameter| parameter.child_count() > 0) - .count() as u32 -} - -/// Count the declarators of a field / event declaration (`int a, b, c;`). -/// -/// Roslyn has one `variable_declaration : type variable_declarator (',' -/// variable_declarator)*` for all of them — no separate `constant_declarators` -/// list, since `const` is a modifier rather than a distinct declaration rule. -fn declarator_count(ctx: RuleNodeView<'_>) -> u32 { - ctx.child_rule(cp::RULE_VARIABLE_DECLARATION) - .map(|decl| decl.child_rules(cp::RULE_VARIABLE_DECLARATOR).count() as u32) - .unwrap_or(0) -} - -/// Resolve an explicit visibility from a member/type wrapper's -/// `all_member_modifiers`: `Some(true)` if it carries `public`, `Some(false)` -/// if it carries `private`/`protected`/`internal`, `None` if no access modifier -/// is present (caller applies the container default). -/// -/// `internal` is *not* public: it is assembly-scoped, so it does not -/// contribute to the type's public API surface (NPA/NPM). -/// The rules that are a *real* member declaration — the ones carrying their own -/// `attribute_list* modifier*`, as opposed to the `base_*` dispatch alternations -/// above them. -fn declares_member(ri: usize) -> bool { - matches!( - ri, - cp::RULE_FIELD_DECLARATION - | cp::RULE_EVENT_FIELD_DECLARATION - | cp::RULE_METHOD_DECLARATION - | cp::RULE_CONSTRUCTOR_DECLARATION - | cp::RULE_DESTRUCTOR_DECLARATION - | cp::RULE_OPERATOR_DECLARATION - | cp::RULE_CONVERSION_OPERATOR_DECLARATION - | cp::RULE_PROPERTY_DECLARATION - | cp::RULE_INDEXER_DECLARATION - | cp::RULE_EVENT_DECLARATION - | cp::RULE_DELEGATE_DECLARATION - | cp::RULE_CLASS_DECLARATION - | cp::RULE_STRUCT_DECLARATION - | cp::RULE_INTERFACE_DECLARATION - | cp::RULE_ENUM_DECLARATION - | cp::RULE_RECORD_DECLARATION - | cp::RULE_UNION_DECLARATION - ) -} - -/// Resolve a declaration's access from its own `modifier*` children. -/// -/// `Some(true)` for an explicit `public`, `Some(false)` when another access -/// modifier is present, `None` when the declaration states none — the caller -/// supplies the container's default, since an unmarked class member is private -/// while an unmarked interface member is public. -/// -/// Roslyn puts `modifier*` directly on each declaration, so this reads the real -/// node rather than a wrapper. `modifier_children()` is typed and reaches only -/// direct children, so a modifier on a *nested* declaration cannot leak in. -fn visibility_from_modifiers(ctx: RuleNodeView<'_>) -> Option { - let mut saw_non_public = false; - for modifier in ctx.child_rules(cp::RULE_MODIFIER) { - if modifier.has_token(cl::KW_PUBLIC) { - return Some(true); - } - if modifier.has_token(cl::KW_PRIVATE) - || modifier.has_token(cl::KW_PROTECTED) - || modifier.has_token(cl::KW_INTERNAL) - || modifier.has_token(cl::KW_FILE) - { - saw_non_public = true; - } - } - saw_non_public.then_some(false) -} - -fn container_kind(parent_kind: SpaceKind) -> ContainerKind { - match parent_kind { - SpaceKind::Class | SpaceKind::Impl | SpaceKind::Enum => ContainerKind::Class, - SpaceKind::Interface | SpaceKind::Trait => ContainerKind::Interface, - _ => ContainerKind::Other, - } -} - -/// Does this lambda declare an explicit `void` return type? -/// -/// C# 10 allows one — `Action a = void () => Console.WriteLine();` — and it returns no -/// value, so its expression body is not an exit. Without this it recorded one while the -/// block-bodied `void () => { Console.WriteLine(); }` recorded none. -/// -/// Only `parenthesized_lambda_expression` has the `type?` slot (`attribute_list* modifier* -/// type? parameter_list ARROW …`); `x => …` cannot carry one, so a missing child is the -/// common case rather than an error. -fn lambda_returns_void(ctx: RuleNodeView<'_>) -> bool { - ctx.child_rule(cp::RULE_TYPE) - .is_some_and(|ty| ty.text().trim() == "void") -} - -/// Does this expression body consist of a `throw` expression? -/// -/// `int F() => throw new E();` is an exit, but `RULE_THROW_EXPRESSION` already records -/// it — so the body must not record a second one, or the expression-bodied form -/// reports NExit 2 where the block-bodied `int F() { throw new E(); }` reports 1. -/// -/// Used for both an `arrow_expression_clause` and a lambda, whose bodies are the same -/// shape one node down (`ARROW expression` vs `… ARROW (block | expression)`). The lambda -/// case needs it for the identical reason, and a direct `child_rule` probe was not enough -/// there either — `x => throw new E()` reported 2. -/// -/// Checked one level down as well as directly, because hub inlining leaves the `throw` as -/// a child of the body `expression` rather than of the node above it. One level is enough — -/// a `throw` deeper than that is inside a sub-expression (`x ?? throw new E()`), where the -/// body's own return is real and both should count. -fn arrow_body_is_throw(ctx: RuleNodeView<'_>) -> bool { - if ctx.child_rule(cp::RULE_THROW_EXPRESSION).is_some() { - return true; - } - ctx.child_rules(cp::RULE_EXPRESSION) - .any(|body| body.child_rule(cp::RULE_THROW_EXPRESSION).is_some()) -} - -/// Is this switch-expression arm the discard (`_ => …`) catch-all? -/// -/// The discard is the fall-through, not a test, so it is not a decision — the same -/// treatment `default:` gets in a switch statement. -/// -/// Roslyn does give the discard its own `discard_pattern : '_'` rule, but it cannot -/// be reached here: `constant_pattern : expression` is listed *before* it among -/// `pattern`'s alternatives and `_` is a legal identifier expression, so ANTLR takes -/// the constant form first. (Reordering is not an option — `discard_pattern` first -/// would be right for `_` yet the two rules are otherwise unrelated, and Roslyn's own -/// parser distinguishes them semantically, by knowing whether `_` resolves to a -/// declared name.) So the arm's pattern is matched on its text, which is exactly `_` -/// for the discard and cannot be anything else for a one-token pattern. -fn is_discard_arm(ctx: RuleNodeView<'_>) -> bool { - let Some(arm) = SwitchExpressionArmContext::from_rule_node(ctx) else { - return false; - }; - // A *guarded* discard is not the fall-through. `_ when enabled => …` tests - // `enabled` and can fail, so the arm is a real decision — and the equivalent - // `case _ when enabled:` in a switch statement counts as one. Only a bare `_` - // always matches. - if arm.when_clause().is_some() { - return false; - } - arm.pattern().ok().is_some_and(|pattern| { - pattern.discard_pattern().is_some() - || pattern.text() == "_" - // A `var` pattern always matches too, so an unguarded `var x => …` is the - // fall-through just as `_ => …` is — it binds the subject and tests nothing. - // It was scored as a decision and an ABC condition, so the two spellings of - // one catch-all disagreed. - // - // Both designation shapes qualify. A `var` pattern never tests the type, so - // even the deconstructing `var (a, b) => …` succeeds whenever the subject is - // deconstructible — which the compiler has already established statically. - // (A *positional* pattern like `(1, 1) => …` does test, and is a different - // rule.) Measured: both forms scored cyclomatic 3 / conditions 2 against the - // discard's 2 / 1. - || pattern.var_pattern().is_some() - }) -} - -/// Is this invocation-shaped `expression` the `nameof` pseudo-call? -/// -/// `nameof` is a *contextual* keyword: the grammar has no rule for it, so -/// `nameof(x)` parses as an ordinary invocation over the identifier `nameof`. It is -/// nonetheless a compile-time operator — it yields a string constant, calls nothing, -/// and never evaluates its argument — so it must not count as an ABC branch. -/// -/// The callee is the invocation's first `expression` child. Hub inlining collapses a -/// bare identifier callee all the way down (no `simple_name` layer survives on it), -/// so the check is on that child's own text. That is exact rather than a substring -/// probe: the child spans the callee and nothing else, so it equals `"nameof"` only -/// when the callee IS the bare identifier. A qualified `X.nameof(y)` has a `.` in the -/// child's text, so it is not mistaken for the operator. -/// -/// The arity check is what keeps a *user symbol* named `nameof` counting. `nameof` is -/// only contextual, so `Func nameof = …; nameof(1, 2)` is legal C# and -/// is a real delegate call — text alone would suppress it. The operator takes exactly -/// one argument, so anything else cannot be it. (A one-argument delegate named -/// `nameof` is still indistinguishable without a symbol table, which is where Roslyn -/// resolves it; that residue is vanishingly rare next to the `nameof(arg)` idiom this -/// exists for.) -/// -/// Only ever consulted for a node that already has an `argument_list`, so the first -/// `expression` child is the callee by construction. -fn is_nameof_callee(expr: &ExpressionContext<'_>) -> bool { - let one_argument = expr - .argument_list() - .is_some_and(|list| list.argument_children().count() == 1); - one_argument - && expr - .expression_children() - .next() - .is_some_and(|callee| callee.text() == "nameof") -} - -/// Equality / relational / boolean / null-coalescing operator tokens that count as -/// an ABC "condition". -/// -/// Equality (`==`/`!=`), `&&`/`||` and `??` have dedicated tokens that appear -/// nowhere else, so they are safe on this cheap token scan. Relational `<`/`>` are -/// counted here too, but the caller must first exclude the two constructs that -/// reuse those tokens for something other than a comparison — a split shift -/// operator and a generic/function-pointer delimiter (see -/// [`ChildHint::in_shift_operator`] and [`ChildHint::in_type_delimiter`]). -/// -/// `is`/`as` are NOT here: they are counted at the `expression` rule, where the -/// typed context distinguishes them from the `is`-pattern forms. -fn is_abc_condition_token(tt: i32) -> bool { - matches!( - tt, - cl::EQ_EQ - | cl::NE - | cl::AMP_AMP - | cl::PIPE_PIPE - | cl::QUESTION_QUESTION - // Relational comparisons. `>` is also half of a split `>>`, so the - // caller must exclude tokens inside a `right_shift` rule. - | cl::LT - | cl::GT - | cl::LE - | cl::GE - ) -} - -/// The operator spelling for a condition token accepted by -/// [`is_abc_condition_token`], used as the evidence reason detail so -/// `csharp.abc.condition.==` and `csharp.abc.condition.&&` stay -/// distinguishable — the operator IS the construct at these token-level -/// sites, exactly as the Go walker uses tree-sitter's `&&` node kind. -fn condition_token_spelling(tt: i32) -> &'static str { - match tt { - cl::EQ_EQ => "==", - cl::NE => "!=", - cl::AMP_AMP => "&&", - cl::PIPE_PIPE => "||", - cl::QUESTION_QUESTION => "??", - cl::LT => "<", - cl::GT => ">", - cl::LE => "<=", - cl::GE => ">=", - _ => "", - } -} - -/// The grammar's own snake_case name for a rule index, used as the evidence -/// reason detail at rule-level classification sites (`if_statement`, -/// `switch_expression_arm`, …). Out-of-range indices collapse to the bare -/// `csharp.` reason rather than panicking. -fn rule_name(ri: usize) -> &'static str { - cp::rule_names().get(ri).copied().unwrap_or("") -} - -// -------------------------------------------------------------------- -// Halstead token classification. -// -------------------------------------------------------------------- - -enum HalsteadClass { - Operator, - Operand, - Skip, -} - -/// Classify a token type as a Halstead operator, operand, or skipped. -/// -/// Operands: identifiers, literals (including every interpolated-string content -/// token), `this`, `base`. Skipped: whitespace, comments, the BOM, the -/// inactive-`#if` `SKIPPED_SECTION`, and EOF. Everything else (keywords, -/// punctuation, operators) is an operator. -fn halstead_class(tt: i32) -> HalsteadClass { - if matches!( - tt, - cl::IDENTIFIER - | cl::DEC_INT_LIT - | cl::HEX_INT_LIT - | cl::BIN_INT_LIT - | cl::REAL_LIT - | cl::CHAR_LIT - | cl::STRING_LIT - | cl::VERBATIM_STRING_LIT - | cl::ML_RAW_STRING_LIT - | cl::SL_RAW_STRING_LIT - | cl::KW_TRUE - | cl::KW_FALSE - | cl::KW_NULL - | cl::KW_THIS - | cl::KW_BASE - // The C# 14 contextual `field` in a semi-auto property - // (`get => field; set => field = value;`). In expression position it is a - // value reference to the compiler-synthesized backing field — the same - // kind of thing as `this` or `base` — and Roslyn gives it its own - // `field_expression : KW_FIELD` rule there. Without this it fell through - // as an *operator*, adding a spurious one and omitting the backing-field - // operand. - | cl::KW_FIELD - // Every interpolated-string content piece — literal text, escapes, - // doubled braces, and the format specifier — arrives as this one - // token: the hand-written lexer's mode rules all `type(…)` to it. - | cl::INTERPOLATED_TEXT - | cl::XML_TEXT_LIT - ) { - return HalsteadClass::Operand; - } - - if matches!( - tt, - cl::WHITESPACES - | cl::BYTE_ORDER_MARK - | cl::SINGLE_LINE_COMMENT - | cl::DELIMITED_COMMENT - | cl::SINGLE_LINE_DOC_COMMENT - | cl::DELIMITED_DOC_COMMENT - // mehen routes preprocessor directives to their own channel rather - // than evaluating them, so a directive line is neither operator nor - // operand for Halstead. (It IS a physical code line for PLOC — see - // `collect_loc_tokens` — since the row carries source text.) - | cl::DIRECTIVE_LINE - // The C# 11 UTF-8 literal suffix (`"text"u8`, either case) contributes - // NOTHING of its own. Real C# lexes `"text"u8` as one literal token; - // Roslyn splits the suffix off only because it models the syntax node that - // way, and the preceding `STRING_LIT` has already recorded the operand. - // - // Classifying it as an operator was wrong (it is not applied to anything) - // and classifying it as an *operand* was also wrong — that made one C# - // literal contribute two operand occurrences, still inflating length, - // vocabulary, and volume. Skipping it makes `"text"u8` cost exactly what - // `"text"` costs, which is what the source says. - | cl::KW_U8 - | cl::KW_U8_LOWER - ) || tt < 0 - { - return HalsteadClass::Skip; - } - - HalsteadClass::Operator -} - -/// A stable string label for an operator token, used as its Halstead operator -/// key. The numeric token type is stable for a given generated grammar. -fn kp_token_name(tt: i32) -> String { - format!("t{tt}") -} diff --git a/crates/mehen-csharp/tests/abc.rs b/crates/mehen-csharp/tests/abc.rs deleted file mode 100644 index 3feae26b..00000000 --- a/crates/mehen-csharp/tests/abc.rs +++ /dev/null @@ -1,890 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC (Assignments / Branches / Conditions) tests for the ANTLR C# walker. -//! -//! - **A**: `=` and every compound form (including `??=`), `++`/`--`, and any -//! initialized declarator. -//! - **B**: function/method calls and object creation. A *qualified* call -//! (`o.M()`) is ONE branch — the `.M` qualification is not itself a call. -//! - **C**: `if`/`case`/`catch`/`when`, loops, comparisons, equality, -//! `&&`/`||`, the ternary, `??`, `is`, and `as`. Bit-shifts are excluded. - -mod common; - -use common::analyze_clean; - -/// The `(assignments, branches, conditions)` triple for the whole unit. -fn abc(source: &str) -> (u64, u64, u64) { - let a = analyze_clean(source); - let m = mehen_report::metrics_json::abc(&a.root.metrics); - (m.assignments as u64, m.branches as u64, m.conditions as u64) -} - -#[test] -fn plain_assignment_and_initialized_local() { - // `int x = 1;` (declarator init) + `x = 2;` (assignment) = 2 A. - assert_eq!(abc("class C { void F() { int x = 1; x = 2; } }"), (2, 0, 0)); -} - -#[test] -fn compound_and_null_coalescing_assignment_count() { - // `+=` and `??=` are both assignments. - let (a, _, _) = abc("class C { - void F(int i, string s) { - i += 1; - s ??= \"d\"; - } - }"); - assert_eq!(a, 2); -} - -#[test] -fn increment_and_decrement_are_assignments() { - let (a, _, _) = abc("class C { void F(int i) { i++; i--; } }"); - assert_eq!(a, 2); -} - -#[test] -fn uninitialized_declaration_is_not_an_assignment() { - assert_eq!(abc("class C { void F() { int x; } }"), (0, 0, 0)); -} - -#[test] -fn a_qualified_call_is_exactly_one_branch() { - // `o.Helper()` is ONE branch: the `.Helper` member access is qualification, - // not a second call. This pins the fix for an early 3x over-count. - let (_, b, _) = abc("class C { - void Helper() { } - void F(C o) { o.Helper(); } - }"); - assert_eq!(b, 1); -} - -#[test] -fn a_field_read_is_not_a_branch() { - let (_, b, _) = abc("class C { - public int Field; - int F(C o) { return o.Field; } - }"); - assert_eq!(b, 0); -} - -#[test] -fn deeply_qualified_call_is_still_one_branch() { - let (_, b, _) = abc("class C { void F(int x) { System.Console.WriteLine(x); } }"); - assert_eq!(b, 1); -} - -#[test] -fn object_creation_is_a_branch() { - let (_, b, _) = abc("class C { object F() { return new object(); } }"); - assert_eq!(b, 1); -} - -#[test] -fn constructor_initializer_is_a_branch() { - // `: this(0)` chains to another constructor — a call. - let (_, b, _) = abc("class C { - public C() : this(0) { } - public C(int x) { } - }"); - assert_eq!(b, 1); -} - -#[test] -fn if_plus_its_comparison_are_two_conditions() { - // The `if` itself is one condition and the `<` comparison another — - // matching `mehen-java` on the same shape. - let (_, _, c) = abc("class C { int F(int v) { if (v < 0) { return 1; } return 2; } }"); - assert_eq!(c, 2); -} - -#[test] -fn equality_and_relational_operators_are_conditions() { - let (_, _, c) = abc("class C { - bool F(int a, int b) { - return a == b || a != b || a < b || a > b || a <= b || a >= b; - } - }"); - // 6 comparisons + 5 `||` operators = 11. - assert_eq!(c, 11); -} - -#[test] -fn bit_shifts_are_not_conditions() { - // `<<`/`>>` share the bare `LT`/`GT` tokens with comparisons in this - // grammar, so this pins that the walker tells them apart. - let (_, _, c) = abc("class C { int F(int v) { return (v << 2) >> 1; } }"); - assert_eq!(c, 0); -} - -#[test] -fn is_and_as_type_tests_are_conditions() { - let (_, _, c) = abc("class C { - bool F(object o) { return o is string; } - string G(object o) { return o as string; } - }"); - assert_eq!(c, 2); -} - -#[test] -fn null_coalescing_is_a_condition() { - let (_, _, c) = abc("class C { string F(string s) { return s ?? \"d\"; } }"); - assert_eq!(c, 1); -} - -#[test] -fn catch_and_when_filter_are_conditions() { - // `catch` is one condition; the `when` filter adds another; the filter's - // own `>` comparison adds a third. - let (_, _, c) = abc("class C { - void F(int code) { - try { } - catch (System.Exception) when (code > 0) { } - } - }"); - assert_eq!(c, 3); -} - -#[test] -fn case_labels_are_conditions_but_default_is_not() { - // 2 `case` labels = 2 conditions; `default:` adds none. - let (_, _, c) = abc("class C { - int F(int v) { - switch (v) { - case 1: return 1; - case 2: return 2; - default: return 0; - } - } - }"); - assert_eq!(c, 2); -} - -#[test] -fn attribute_arguments_record_no_executable_complexity() { - // An attribute is compile-time metadata: its `= …` named argument must not - // count as an assignment, nor its operators as conditions. - assert_eq!( - abc("class C { - [System.Obsolete(\"x\", true)] - void F() { } - }"), - (0, 0, 0) - ); -} - -#[test] -fn generic_delimiters_are_not_conditions() { - // REGRESSION. C# spells generic argument lists with the same `<`/`>` tokens as - // a comparison, so `List` scored two ABC conditions and - // `Dictionary>` scored four — inflating the score of any file - // that mentions a generic type, which in practice is all of them. - let (_, _, c) = abc("class C { - System.Collections.Generic.Dictionary> Map; - }"); - assert_eq!(c, 0); -} - -#[test] -fn a_generic_type_does_not_mask_a_real_comparison_beside_it() { - // The delimiter exclusion must be positional, not a blanket `<`/`>` mute: a - // comparison in the same expression as a generic type still counts. - let (_, _, c) = abc("class C { - bool F(System.Collections.Generic.List items, int limit) { - return items.Count < limit; - } - }"); - assert_eq!(c, 1); -} - -#[test] -fn a_generic_type_argument_may_still_contain_a_comparison() { - // The hint deliberately does not propagate into children, so a comparison - // *inside* a type argument's lambda still counts. - let (_, _, c) = abc("class C { - System.Func F() { - return x => x > 0; - } - }"); - assert_eq!(c, 1); -} - -#[test] -fn every_shift_assignment_form_counts_one_assignment() { - // REGRESSION. `>>=` and `>>>=` are the only assignment operators the prep - // splits into separate tokens (`GT GE` / `GT GT GE`), so they arrive as child - // *rules* rather than as an operator terminal. `a >>= 2` scored no assignment - // at all while the otherwise-identical `a <<= 2` scored one. - for op in ["<<=", ">>=", ">>>=", "+=", "&="] { - let (a, _, _) = abc(&format!("class C {{ void F(int v) {{ v {op} 2; }} }}")); - assert_eq!(a, 1, "`{op}` must count exactly one assignment"); - } -} - -#[test] -fn nameof_is_not_a_branch() { - // REGRESSION. `nameof` is a contextual keyword with no grammar rule of its - // own, so `nameof(x)` has the invocation shape — but it is a compile-time - // operator that yields a string constant, calls nothing, and never evaluates - // its argument. Counting it ranked - // `throw new ArgumentNullException(nameof(arg))` above the same throw with a - // literal. - let (_, b, _) = abc("class C { string F() { return nameof(F); } }"); - assert_eq!(b, 0); -} - -#[test] -fn a_real_call_is_still_a_branch_beside_nameof() { - // The `nameof` exclusion is by callee, so an ordinary call in the same method - // still counts — including a *method* named `nameof`, which is legal. - let (_, b, _) = abc("class C { - void G() { } - string F() { G(); return nameof(F); } - }"); - assert_eq!(b, 1); -} - -#[test] -fn pattern_combinators_are_conditions() { - // REGRESSION, twice over. C# 9 spells pattern combinators with the contextual - // keywords `and`/`or`/`not` rather than the `&&`/`||`/`!` operator tokens the - // token scan sees, so a pattern-heavy method scored as straight-line code. - // - // The grammar had to be fixed too: widening `identifier_token` with the - // contextual keywords made `o is int and > 5` bind `and` as a *variable name* - // of type `int` via `declaration_pattern`, silently dropping the combinator and - // the `> 5` with it — with zero diagnostics. - let (_, _, c) = abc("class C { bool F(object o) { return o is int and long; } }"); - assert_eq!(c, 2, "the `is` test plus the `and` combinator"); -} - -#[test] -fn a_relational_pattern_counts_its_comparison_once() { - // `is > 5` is the `is` test plus one comparison — the pattern rule must not - // record a second condition on top of the operator token. - let (_, _, c) = abc("class C { bool F(int v) { return v is > 5; } }"); - assert_eq!(c, 2); -} - -#[test] -fn a_combinator_keyword_is_still_a_legal_name_elsewhere() { - // Excluding `and`/`or`/`not` from `single_variable_designation` must not make - // them reserved: each is still a valid field, parameter, and local name. - // One assignment — the `int not = or;` initializer; the uninitialized field - // declarator is not one. - assert_eq!( - abc("class C { - int and; - int F(int or) { int not = or; return and + not; } - }"), - (1, 0, 0) - ); -} - -#[test] -fn switch_expression_arms_are_conditions_but_the_discard_is_not() { - // REGRESSION. A switch *expression* scored nothing: no decision per arm and no - // cognitive nesting, so rewriting a switch statement into the expression form - // silently lowered the score. The discard arm (`_ =>`) is the fall-through - // rather than a test, so it counts no more than `default:` does. - let (_, _, c) = abc("class C { - int F(int v) { - return v switch { 1 => 1, 2 => 2, _ => 0 }; - } - }"); - assert_eq!(c, 2); -} - -#[test] -fn a_split_shift_operator_is_one_halstead_operator() { - // `>>` is spelled as two adjacent `>` tokens so a generic closer is never - // mis-lexed as a shift (see the parser crate's PROVENANCE). Recording each - // `>` would inflate Halstead length and conflate the shift with the `>` - // comparison in the distinct-operator set, so the shift is recorded once at - // its enclosing rule. Pinned against an equivalent single-token operator. - let length = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics).length - }; - assert_eq!( - length("class C { int M(int a) => a >> 1; }"), - length("class C { int M(int a) => a * 1; }"), - "a shift must cost the same Halstead length as any other binary operator" - ); -} - -#[test] -fn an_operator_declarations_symbol_is_not_an_assignment() { - // REGRESSION. Roslyn spells an operator's symbol as a direct token choice on the - // declaration (`… KW_OPERATOR KW_CHECKED? (PLUS | PLUS_PLUS | …)`), so the `++` in - // `operator ++(C v)` reached the token scan looking exactly like a real increment - // and scored an ABC assignment — for the *declaration* of an operator, which - // mutates nothing. - let (a, _, _) = abc("class C { public static C operator ++(C v) => v; }"); - assert_eq!(a, 0); -} - -#[test] -fn an_operator_declarations_symbol_is_not_a_condition() { - // The same suppression covers the comparison and boolean operators: declaring - // `operator <` must not score a comparison from its own signature. - let (_, _, c) = abc("class C { - public static bool operator <(C a, C b) => true; - public static bool operator >(C a, C b) => true; - }"); - assert_eq!(c, 0); -} - -#[test] -fn an_operator_body_still_counts_its_operators() { - // The suppression is positional, not a blanket mute on operator declarations: a - // real `++` inside the body counts, alongside the initializer's `=`. - let (a, _, _) = abc("class C { - public static C operator +(C x, C y) { - int i = 0; - i++; - return x; - } - }"); - assert_eq!(a, 2, "the `int i = 0` initializer plus the `i++`"); -} - -#[test] -fn a_utf8_literal_suffix_is_part_of_the_operand() { - // REGRESSION. `"text"u8` is one literal in real C#; Roslyn's grammar spells the - // suffix as a separate trailing token only because it models the syntax node that - // way. Classifying it as a Halstead *operator* made a UTF-8 literal cost a - // distinct operator that no operator was applied in — pinned against the plain - // literal, which must have the same operator vocabulary. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let utf8 = halstead("class C { System.ReadOnlySpan F() => \"text\"u8; }"); - let plain = halstead("class C { System.ReadOnlySpan F() => \"text\"; }"); - assert_eq!( - utf8.n1, plain.n1, - "the `u8` suffix must not add a distinct operator" - ); - assert_eq!(utf8.big_n1, plain.big_n1, "nor an operator occurrence"); -} - -#[test] -fn an_auto_property_initializer_is_an_assignment() { - // REGRESSION. `public int P { get; set; } = 5;` carries its `equals_value_clause` - // directly on `property_declaration` rather than through a `variable_declarator`, - // so it scored no assignment while the equivalent field `public int P = 5;` - // scored one. - let (a, _, _) = abc("class C { public int P { get; set; } = 5; }"); - assert_eq!(a, 1); - // And an uninitialized auto-property is still not an assignment. - let (a, _, _) = abc("class C { public int P { get; set; } }"); - assert_eq!(a, 0); -} - -#[test] -fn a_query_let_binding_is_an_assignment() { - // REGRESSION. `let_clause : KW_LET identifier_token EQ expression` puts its `=` as - // a bare token on a rule that is not part of the inlined `expression`, so neither - // the token scan nor the expression classifier saw it — a `let` bound a name with - // no assignment recorded. - let (a, _, _) = abc("class C { - static object F(int[] s) { return from x in s let y = x select y; } - }"); - assert_eq!(a, 1); -} - -#[test] -fn a_user_symbol_named_nameof_is_still_a_branch() { - // REGRESSION. `nameof` is only *contextual*, so a delegate can legally be named - // `nameof` — and the operator takes exactly one argument, so a two-argument call - // cannot be it. A text-only callee check suppressed the real delegate call. - let (_, b, _) = abc("class C { - static int F() { - System.Func nameof = (x, y) => x + y; - return nameof(1, 2); - } - }"); - assert_eq!(b, 1, "the delegate call is a real branch"); -} - -#[test] -fn the_nameof_operator_is_still_suppressed() { - // The counterpart: the arity guard must not stop suppressing the actual operator, - // which is always one argument. - let (_, b, _) = abc("class C { static string F() => nameof(F); }"); - assert_eq!(b, 0); -} - -#[test] -fn a_utf8_literal_costs_the_same_as_a_plain_one() { - // REGRESSION, twice. `"text"u8` is ONE literal in C#; Roslyn splits the suffix off - // only to model the syntax node, and the preceding `STRING_LIT` has already - // recorded the operand. Classifying the suffix as an operator was wrong (nothing is - // applied), and classifying it as an *operand* was also wrong — that gave one - // literal two operand occurrences. It contributes nothing. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let utf8 = halstead("class C { static System.ReadOnlySpan F() => \"text\"u8; }"); - let plain = halstead("class C { static System.ReadOnlySpan F() => \"text\"; }"); - assert_eq!(utf8.n1, plain.n1, "no extra distinct operator"); - assert_eq!(utf8.n2, plain.n2, "no extra distinct operand"); - assert_eq!(utf8.length, plain.length, "no extra length"); -} - -#[test] -fn the_contextual_field_keyword_is_an_operand() { - // REGRESSION. C# 14's semi-auto property (`get => field;`) references the - // compiler-synthesized backing field. In expression position that is a value - // reference like `this` or `base` — Roslyn even gives it its own - // `field_expression : KW_FIELD` rule — but the token does not pass through - // `identifier_token`, so it fell through as a Halstead *operator*: a spurious - // operator plus a missing operand. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let semi_auto = halstead("class C { public int P { get => field; } }"); - let explicit = halstead("class C { int _x; public int P { get => _x; } }"); - assert_eq!( - semi_auto.n1, explicit.n1, - "`field` must not add a distinct operator" - ); -} - -#[test] -fn stack_allocation_is_a_branch() { - // REGRESSION. `stackalloc` allocates exactly as `new` does, just on the stack, but - // `stack_alloc_array_creation_expression` and its implicit form were missing from - // the creation list — so `stackalloc int[4]` scored no branch while `new int[4]` - // scored one. - let (_, b, _) = abc("class C { static void F() { var s = stackalloc int[4]; } }"); - assert_eq!(b, 1); - let (_, b, _) = abc("class C { static void F() { var s = stackalloc[] { 1, 2 }; } }"); - assert_eq!(b, 1); -} - -#[test] -fn a_primary_constructors_base_call_is_a_branch() { - // REGRESSION. `class D(int x) : B(x)` is the primary-constructor spelling of a - // base-constructor call, but it reaches `primary_constructor_base_type` rather than - // `constructor_initializer` — so it scored 0 branches where the explicit - // `D(int x) : base(x)` scored 1. Pinned against that form. - let primary = abc("class B { public B(int x) { } } - class D(int x) : B(x) { }"); - let explicit = abc("class B { public B(int x) { } } - class D : B { public D(int x) : base(x) { } }"); - assert_eq!(primary.1, 1); - assert_eq!(primary.1, explicit.1); -} - -#[test] -fn a_linq_where_clause_is_a_condition() { - // REGRESSION. A `where` is the query-expression equivalent of an `if` — a filter - // predicate — and was recording nothing. A predicate that is already boolean has no - // comparison for the token scan to catch, so `where enabled` scored 0. - let (_, _, c) = abc("class C { - static object F(int[] xs, bool enabled) { return from x in xs where enabled select x; } - }"); - assert_eq!(c, 1); - // With a comparison it is two, exactly as `if (x > 0)` is two. - let (_, _, c) = abc("class C { - static object F(int[] xs) { return from x in xs where x > 0 select x; } - }"); - assert_eq!(c, 2); -} - -#[test] -fn a_bare_default_literal_is_an_operand() { - // REGRESSION. Roslyn groups bare `default` under `literal_expression` beside - // `true`/`false`/`null`, which are operands — but `KW_DEFAULT` does not pass - // through `identifier_token`, so it fell through as a Halstead *operator*: a - // spurious operator plus a missing value operand. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let default_lit = halstead("class C { static void F() { string v = default; } }"); - let null_lit = halstead("class C { static void F() { string v = null; } }"); - assert_eq!( - default_lit.n1, null_lit.n1, - "`default` must cost the same as `null`" - ); -} - -#[test] -fn anonymous_object_creation_is_a_branch() { - // REGRESSION. `new { A = 1 }` has no `argument_list`, so `classify_expression`'s - // invocation shape never saw it, and `anonymous_object_creation_expression` was - // missing from the creation list — a real allocation scored nothing while - // `new object()` scored one. - let (_, b, _) = abc("class C { static object F() => new { A = 1 }; }"); - assert_eq!(b, 1); -} - -#[test] -fn a_collection_expression_is_a_branch() { - // REGRESSION. C# 12's `int[] v = [1, 2];` allocates exactly as `new[] { 1, 2 }` - // does — the spelling changed, not the operation — but `collection_expression` was - // missing from the creation list, so it scored 0 where the older form scored 1. - let collection = abc("class C { static int[] F() { int[] v = [1, 2]; return v; } }"); - let explicit = abc("class C { static int[] F() { int[] v = new[] { 1, 2 }; return v; } }"); - assert_eq!(collection.1, 1); - assert_eq!(collection.1, explicit.1); -} - -#[test] -fn a_named_anonymous_object_member_is_an_assignment() { - // REGRESSION. Roslyn puts the `A =` of `new { A = 1 }` in a `name_equals` child of - // `anonymous_object_member_declarator`, so it is neither an assignment-shaped - // `expression` nor an `equals_value_clause` — it recorded nothing, while the - // equivalent `new C { A = 1 }` recorded one. - let (a, _, _) = abc("class C { static object F() => new { A = 1 }; }"); - assert_eq!(a, 1); -} - -#[test] -fn an_inferred_anonymous_member_is_not_an_assignment() { - // The counterpart: `new { x }` infers the member name from the expression and - // assigns nothing explicitly, so it has no `name_equals` child and records nothing. - let (a, _, _) = abc("class C { static object F(int x) => new { x }; }"); - assert_eq!(a, 0); -} - -#[test] -fn a_using_alias_is_not_an_assignment() { - // `name_equals` is shared with using-alias and attribute-argument names, which is - // why the match is at the *declarator* rather than at `name_equals` itself. - assert_eq!(abc("using S = System.String;\nclass C { }"), (0, 0, 0)); -} - -#[test] -fn an_empty_interpolated_string_is_one_operand() { - // REGRESSION. `$""` produces no `INTERPOLATED_TEXT` token at all — only the start - // and end delimiters, which are operators — so it contributed zero Halstead - // operands where `""` contributes one, skewing volume and the maintainability - // index. Mirrors `mehen-kotlin`'s `classify_empty_string_operand`. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let interpolated = halstead("class C { static string F() { var s = $\"\"; return s; } }"); - let plain = halstead("class C { static string F() { var s = \"\"; return s; } }"); - assert_eq!(interpolated.n2, plain.n2, "empty `$\"\"` is one operand"); -} - -#[test] -fn a_generic_lists_comma_is_still_an_operator() { - // REGRESSION introduced by the `in_type_delimiter` fix itself: the hint marks a - // whole delimiter *list*, and the Halstead branch returned for every token in it — - // dropping the `,` between type arguments along with the `>`. Only `<`/`>` are the - // delimiter; a comma is ordinary punctuation and counts as it does in a parameter - // list. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let two = halstead("class C { System.Collections.Generic.Dictionary F; }"); - let one = halstead("class C { System.Collections.Generic.List F; }"); - // Two extra distinct operators over the one-argument form: the `,` and the extra - // type name's operand is separate — so the delta must be 2, not 1. - assert_eq!( - two.n1 - one.n1, - 2.0, - "the type-argument comma must count as an operator" - ); -} - -#[test] -fn overloaded_true_and_false_symbols_are_operators() { - // REGRESSION. `operator true` / `operator false` are the only overloadable - // operators whose symbols are keywords that mean something else elsewhere — as a - // *literal*, `true` is a Halstead operand, and the declaration reused the same - // token. So declaring them added operands rather than operators. `in_operator_symbol` - // already marked the position; it just did not reach the Halstead classification. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let bool_ops = halstead( - "class C { - public static bool operator true(C c) => true; - public static bool operator false(C c) => false; - }", - ); - // Two distinct operators for the two declared symbols. The `true`/`false` in the - // bodies are still operands, so n2 is unaffected. - let plain = halstead("class C { public static C operator +(C a, C b) => a; }"); - assert!( - bool_ops.n1 > plain.n1, - "declaring `operator true`/`false` must add distinct operators, \ - got n1 {} vs {}", - bool_ops.n1, - plain.n1 - ); -} - -#[test] -fn a_brace_only_array_initializer_is_a_branch() { - // REGRESSION. `int[] v = { 1, 2 };` has no `new` and no `[…]`, so Roslyn puts a bare - // `initializer_expression` on the right-hand side and nothing in the creation list - // fired — it scored 0 where `new[] { 1, 2 }` and `[1, 2]` each scored 1, making ABC - // depend on which of three equivalent spellings the author used. - let bare = abc("class C { static int[] F() { int[] v = { 1, 2 }; return v; } }"); - let explicit = abc("class C { static int[] F() { int[] v = new[] { 1, 2 }; return v; } }"); - let collection = abc("class C { static int[] F() { int[] v = [1, 2]; return v; } }"); - assert_eq!(bare.1, 1); - assert_eq!(bare.1, explicit.1); - assert_eq!(bare.1, collection.1); -} - -#[test] -fn a_creations_own_initializer_is_not_a_second_branch() { - // The guard: a creation *nests* an initializer for its elements, so counting the rule - // unconditionally would score `new[] { 1, 2 }` twice. Nested creations too — - // `new[] { new[] { 1 } }` is two allocations, not four. - let nested = abc("class C { - static int[][] F() { int[][] v = new[] { new[] { 1 } }; return v; } - }"); - assert_eq!(nested.1, 2, "two creations, each counted once"); -} - -#[test] -fn a_nested_bare_initializer_is_one_allocation() { - // REGRESSION introduced by the bare-initializer fix: a rectangular array - // `int[,] v = { { 1, 2 }, { 3, 4 } };` has three `initializer_expression` nodes and - // scored three branches, where the explicit `new int[,] { … }` scored one — the - // creation set the hint before its initializers were reached, but a *bare* outer - // initializer did not mark its own nested groups. - let bare = - abc("class C { static int[,] F() { int[,] v = { { 1, 2 }, { 3, 4 } }; return v; } }"); - let explicit = abc("class C { - static int[,] F() { int[,] v = new int[,] { { 1, 2 }, { 3, 4 } }; return v; } - }"); - assert_eq!(bare.1, 1, "one array allocated"); - assert_eq!(bare.1, explicit.1); -} - -#[test] -fn an_identifiers_operand_is_its_name_not_its_spelling() { - // REGRESSION. C# has two spellings that are not part of the name (§6.4.3): the - // verbatim prefix (`@x` IS the identifier `x`, written that way only to escape a - // keyword collision) and Unicode escapes (`a` is `a`). Keying operands on the - // raw token text made `int @x = 1; return x;` two distinct operands, so Halstead - // vocabulary and volume tracked spelling rather than symbols. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let plain = halstead("class C { static int F() { int a = 1; return a; } }"); - for spelling in [ - // verbatim prefix on the declaration, plain at the use - "class C { static int F() { int @a = 1; return a; } }", - // `\uXXXX` (4 hex digits) - "class C { static int F() { int \\u0061 = 1; return a; } }", - // `\UXXXXXXXX` (8) — the other width the grammar's `UnicodeEscape` admits - "class C { static int F() { int \\U00000061 = 1; return a; } }", - ] { - let escaped = halstead(spelling); - assert_eq!( - escaped.n2, plain.n2, - "one name, one distinct operand: {spelling}" - ); - assert_eq!(escaped.volume, plain.volume, "and one volume: {spelling}"); - } -} - -#[test] -fn distinct_names_and_literal_forms_still_stay_distinct() { - // The guard on the normalization above: it must collapse *spellings of one name*, - // never two names, and must not touch non-identifier operands — for a literal the - // spelling IS the value, so `1`, `1L`, and `0x1` are genuinely three operands. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let two_names = halstead("class C { static int F(int x, int y) => x + y; }"); - let one_name = halstead("class C { static int F(int x) => x + x; }"); - assert!( - two_names.n2 > one_name.n2, - "two parameters are two operands" - ); - - let mixed = halstead("class C { static long F() => 1 + 1L + 0x1; }"); - let same = halstead("class C { static long F() => 1 + 1 + 1; }"); - assert!( - mixed.n2 > same.n2, - "three literal forms are three operands, not one" - ); -} - -#[test] -fn a_linq_join_equality_is_a_condition() { - // REGRESSION. `join b in ys on a equals b` is the join's equality test — the - // query-syntax equivalent of `a == b` — but Roslyn spells `equals` as the contextual - // `KW_EQUALS` keyword rather than an `==` token, so the token-level condition scan - // never saw it and the whole join predicate scored zero conditions. - // - // Pinned against the method-syntax spelling of the same comparison, which scored one - // all along. - let join = abc( - "using System.Linq; - class C { - static object F(int[] xs, int[] ys) => from a in xs join b in ys on a equals b select a; - }", - ); - let method = abc("using System.Linq; - class C { - static object F(int[] xs, int[] ys) => xs.Where(a => ys.Any(b => a == b)); - }"); - assert_eq!(join.2, method.2, "the join's equality is one condition"); - assert_eq!(join.2, 1); - - // Recorded on the clause, not on the token, so `equals` stays free as an ordinary - // name — it is contextual, and a variable called `equals` must score nothing. - let identifier = abc("class C { static int F() { int equals = 1; return equals; } }"); - assert_eq!(identifier.2, 0); -} - -#[test] -fn a_query_needs_no_body_clause() { - // REGRESSION, and an upstream defect found while verifying the join above: - // `query_body : query_clause+ select_or_group_clause` required at least one clause - // between the `from` and the `select`, so the two simplest queries C# has did not - // parse at all — 2 and 4 diagnostics respectively. ECMA-334 §12.20.3 makes the clause - // list optional; `Syntax.xml` models it as a plain (possibly empty) list, and the - // generator renders a list as `+`. - // - // It survived because every query in the corpus had a `where` / `orderby` / `let` / - // `join` in between, which parses either way. `abc` asserts a clean parse, so - // reaching the assertions at all is the substance here. - for source in [ - "using System.Linq; class C { static object F(int[] xs) => from a in xs select a; }", - "using System.Linq; class C { static object F(int[] xs) => from a in xs select a + 1; }", - "using System.Linq; class C { static object F(int[] xs) => from a in xs group a by a; }", - ] { - assert_eq!( - abc(source).2, - 0, - "a bodyless query has no condition: {source}" - ); - } - - // And the forms that already worked still do — widening `+` to `*` is a pure - // relaxation, so nothing that parsed before may stop. - for source in [ - "using System.Linq; class C { static object F(int[] xs) => from a in xs where a == 1 select a; }", - "using System.Linq; class C { static object F(int[] xs) => from a in xs orderby a select a; }", - "using System.Linq; class C { static object F(int[] xs) => from a in xs let y = a select y; }", - "using System.Linq; class C { static object F(int[] xs) => from a in xs group a by a into g select g; }", - ] { - let _ = abc(source); - } -} - -#[test] -fn a_utf8_literal_is_a_distinct_operand_from_its_plain_twin() { - // REGRESSION. The `u8` suffix contributes no operand *occurrence* — one C# literal is - // one operand — but it must be part of the operand's KEY: `"x"u8` is a - // `ReadOnlySpan` and `"x"` is a `string`, two values of two types. Skipping the - // suffix entirely collapsed them into one operand, undercounting vocabulary. - let halstead = |source: &str| { - let a = analyze_clean(source); - mehen_report::metrics_json::halstead(&a.root.metrics) - }; - let mixed = halstead("class C { static void F() { var a = \"x\"u8; var b = \"x\"; } }"); - let both_plain = halstead("class C { static void F() { var a = \"x\"; var b = \"x\"; } }"); - let both_u8 = halstead("class C { static void F() { var a = \"x\"u8; var b = \"x\"u8; } }"); - - assert!( - mixed.n2 > both_plain.n2, - "`\"x\"u8` and `\"x\"` are two operands, not one" - ); - assert_eq!( - both_plain.n2, both_u8.n2, - "but two identical literals are still one operand at either type" - ); - // And the suffix still adds no occurrence, which is what the earlier fix established. - assert_eq!(both_u8.big_n2, both_plain.big_n2); -} - -#[test] -fn a_generic_local_declaration_is_not_a_chained_comparison() { - // REGRESSION (#218). `statement`'s alternatives are alphabetical upstream, so - // `expression_statement` preceded `local_declaration_statement` and - // `List l = new();` parsed as the chained comparison `(List < int) > l` — - // two phantom conditions per generic local, in a third of real C# files. The - // `in_type_delimiter` hint from #212 could not reach it: the tokens never - // entered a `type_argument_list` at all, so this was a parse fix (the prep now - // hoists the declaration alternative), not a walker fix. Pinned against the - // `var` spelling of the SAME declaration, so a partial fix cannot pass. - let declared = - abc("class C { static void F() { System.Collections.Generic.List l = new(); } }"); - let inferred = - abc("class C { static void F() { var l = new System.Collections.Generic.List(); } }"); - assert_eq!(declared.2, 0, "generic delimiters are not conditions"); - assert_eq!(declared.2, inferred.2, "must match the `var` control"); - assert_eq!(declared.0, 1, "the initializer is still one assignment"); - - // Independent of the initializer, and same score as the field spelling. - let bare = abc("class C { static void F() { System.Collections.Generic.List l; } }"); - let field = abc("class C { System.Collections.Generic.List l; }"); - assert_eq!(bare.2, 0); - assert_eq!(bare.2, field.2, "must match the field control"); -} - -#[test] -fn a_stackalloc_target_type_is_not_a_comparison_either() { - // The shape that led to #218: `Span s = stackalloc int[4];` scored two - // conditions. The allocation is still one branch, as `new int[4]` is. - let (a, b, c) = abc("class C { static void F() { System.Span s = stackalloc int[4]; } }"); - assert_eq!(c, 0); - assert_eq!(b, 1, "the stack allocation is still a branch"); - assert_eq!(a, 1, "the initializer is still an assignment"); -} - -#[test] -fn a_nullable_local_declaration_is_not_a_ternary() { - // Fixed by the same hoist: before it, `string? s = null;` took the expression - // path too, so the nullable type's `?` reached the token scan in expression - // position and scored a phantom condition. - let (_, _, c) = abc("class C { static void F() { string? s = null; } }"); - assert_eq!(c, 0); -} - -#[test] -fn a_declarations_initializer_may_still_contain_a_real_comparison() { - // The hoist must not mute anything: the one genuine comparison in the - // initializer still counts, while the generic delimiters do not. - let (_, _, c) = abc("class C { - static void F(int w, int x) { - System.Collections.Generic.List l = new() { w < x }; - } - }"); - assert_eq!(c, 1, "exactly the initializer's `<`, not the delimiters"); -} - -#[test] -fn statement_expressions_still_parse_as_expressions() { - // The other side of the hoist: every legal statement-expression shape - // (ECMA-334 §13.7 — invocation, creation, assignment, increment, await) is - // not viable as a declaration, so each must keep its score. The assignment - // and increments score 1 A each; the calls score 1 B each. - let (a, b, _) = abc("class C { - static void G() { } - static void F(int i) { - G(); - System.Console.WriteLine(i); - i = 1; - i++; - i--; - } - }"); - assert_eq!(a, 3, "one assignment plus two increments"); - assert_eq!(b, 2, "two calls"); -} diff --git a/crates/mehen-csharp/tests/cognitive.rs b/crates/mehen-csharp/tests/cognitive.rs deleted file mode 100644 index 11fddb94..00000000 --- a/crates/mehen-csharp/tests/cognitive.rs +++ /dev/null @@ -1,555 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity tests for the ANTLR C# walker. -//! -//! Follows SonarSource's cognitive-complexity specification: nesting -//! increments on `if`, loops, `switch`, `catch`, and the ternary (each costing -//! `1 + current nesting`); flat `+1` on `else`/`else if` and `goto`; and a -//! collapsing boolean run on `&&`/`||` that adds `+1` per operator-kind change. -//! -//! Notably `try` and `lock` add NOTHING — the spec increments on the handler -//! (`catch`), not the guarded block. - -mod common; - -use common::analyze_clean; - -fn sum(a: &mehen_core::LanguageAnalysis) -> f64 { - mehen_report::metrics_json::cognitive(&a.root.metrics).sum -} - -#[test] -fn flat_if_costs_one() { - let a = analyze_clean( - "class C { - void F(int a) { if (a > 0) { } } - }", - ); - assert_eq!(sum(&a), 1.0); -} - -#[test] -fn nested_if_costs_one_plus_nesting() { - // outer if(1) + inner if(1 + 1 nesting) = 3 - let a = analyze_clean( - "class C { - void F(int a, int b) { - if (a > 0) { - if (b > 0) { } - } - } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn else_adds_a_flat_increment() { - // if(1) + else(1) = 2 - let a = analyze_clean( - "class C { - void F(int a) { if (a > 0) { } else { } } - }", - ); - assert_eq!(sum(&a), 2.0); -} - -#[test] -fn else_if_does_not_add_nesting() { - // Per SonarSource's spec an `if`/`else if` chain costs +1 per branch - // keyword and adds NO nesting: if(1) + else-if(1) = 2. Scoring the inner - // `if` as a nested `if` would give 3 — this pins that it does not, and - // matches `mehen-java` on the same shape. - let a = analyze_clean( - "class C { - void F(int a) { - if (a > 0) { } else if (a < 0) { } - } - }", - ); - assert_eq!(sum(&a), 2.0); -} - -#[test] -fn full_else_if_else_chain_costs_one_per_branch() { - // if(1) + else-if(1) + else(1) = 3, all flat. - let a = analyze_clean( - "class C { - void F(int a) { - if (a > 0) { } else if (a < 0) { } else { } - } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn else_with_a_braced_nested_if_does_nest() { - // `else { if … }` is a genuinely nested `if`, unlike `else if`: - // if(1) + else(1) + nested if(1 + 1 nesting) = 4. - let a = analyze_clean( - "class C { - void F(int a) { - if (a > 0) { } else { if (a < 0) { } } - } - }", - ); - assert_eq!(sum(&a), 4.0); -} - -#[test] -fn try_adds_nothing_but_catch_nests() { - // `try` scores 0; `catch` scores 1 (flat, at nesting 0). - let a = analyze_clean( - "class C { - void F() { - try { } catch (System.Exception) { } - } - }", - ); - assert_eq!(sum(&a), 1.0); -} - -#[test] -fn catch_inside_a_loop_pays_the_loop_nesting() { - // foreach(1) + catch(1 + 1 nesting) = 3. This is the shape that caught a - // real bug: scoring `try` too would make it 4+. - let a = analyze_clean( - "class C { - void F(int[] xs) { - foreach (var x in xs) { - try { } catch (System.Exception) { } - } - } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn lock_adds_nothing() { - let a = analyze_clean( - "class C { - private readonly object _g = new object(); - void F() { lock (_g) { } } - }", - ); - assert_eq!(sum(&a), 0.0); -} - -#[test] -fn switch_nests_once_regardless_of_case_count() { - // `switch` costs 1; the individual `case` labels add no cognitive cost. - let a = analyze_clean( - "class C { - void F(int v) { - switch (v) { - case 1: break; - case 2: break; - default: break; - } - } - }", - ); - assert_eq!(sum(&a), 1.0); -} - -#[test] -fn same_boolean_operator_run_collapses() { - // `a && b && c` is ONE run → if(1) + run(1) = 2. - let a = analyze_clean( - "class C { - void F(bool a, bool b, bool c) { if (a && b && c) { } } - }", - ); - assert_eq!(sum(&a), 2.0); -} - -#[test] -fn mixed_boolean_operators_count_each_change() { - // `a && b || c` changes operator once → if(1) + 2 = 3. - let a = analyze_clean( - "class C { - void F(bool a, bool b, bool c) { if (a && b || c) { } } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn boolean_runs_do_not_collapse_across_statements() { - // Two separate statements, each one `&&` run → 2 (not 1). - let a = analyze_clean( - "class C { - bool G(bool x) { return x; } - void F(bool a, bool b) { - G(a && b); - G(a && b); - } - }", - ); - assert_eq!(sum(&a), 2.0); -} - -#[test] -fn ternary_nests_like_an_if() { - let a = analyze_clean( - "class C { - int F(bool a) { return a ? 1 : 2; } - }", - ); - assert_eq!(sum(&a), 1.0); -} - -#[test] -fn goto_adds_a_flat_increment() { - let a = analyze_clean( - "class C { - void F() { - start: - goto start; - } - }", - ); - assert_eq!(sum(&a), 1.0); -} - -#[test] -fn a_method_in_a_nested_type_starts_fresh() { - // The inner type's method must not inherit the outer method's nesting: - // outer if(1) + inner if(1) = 2, not 3. - let a = analyze_clean( - "class Outer { - void F(int a) { - if (a > 0) { } - } - class Inner { - void G(int b) { - if (b > 0) { } - } - } - }", - ); - assert_eq!(sum(&a), 2.0); -} - -#[test] -fn a_switch_expression_nests_like_a_switch_statement() { - // REGRESSION. A switch *expression* added no cognitive nesting, so the modern - // spelling of the same branching scored 0 where the statement form scored 1. - let expression = analyze_clean( - "class C { - int F(int v) { - return v switch { 1 => 1, _ => 0 }; - } - }", - ); - let statement = analyze_clean( - "class C { - int F(int v) { - switch (v) { case 1: return 1; default: return 0; } - } - }", - ); - assert_eq!(sum(&expression), sum(&statement)); - assert_eq!(sum(&expression), 1.0); -} - -#[test] -fn a_switch_expression_nested_in_an_if_costs_its_depth() { - // The nesting increment must be a real level, not a flat +1: the inner switch - // expression sits one level deep, so it costs 2 on top of the `if`'s 1. - let a = analyze_clean( - "class C { - int F(int v, bool flag) { - if (flag) { - return v switch { 1 => 1, _ => 0 }; - } - return 0; - } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn pattern_combinators_score_as_boolean_operators() { - // `and`/`or` are C# 9's pattern-position spelling of `&&`/`||`, so they feed the - // same run-collapsing tracker. A run of the SAME combinator is one increment. - let one_run = analyze_clean( - "class C { - bool F(object o) { return o is int and long and short; } - }", - ); - assert_eq!(sum(&one_run), 1.0, "a same-operator run collapses to +1"); - - // Mixing them breaks the run, exactly as `a && b || c` does. - let mixed = analyze_clean( - "class C { - bool F(object o) { return o is (int and long) or string; } - }", - ); - assert_eq!(sum(&mixed), 2.0); -} - -#[test] -fn sibling_field_initializers_are_independent_boolean_contexts() { - // REGRESSION. Two field initializers share the enclosing *type* space rather - // than a statement, so neither hit any of the statement-shaped rules that reset - // the boolean-run tracker — the two `&&` runs collapsed into one and the pair - // scored 1. Pinned against the equivalent locals, which always scored 2. - let fields = analyze_clean( - "class C { - bool A = X() && Y(); - bool B = U() && V(); - static bool X() => true; - static bool Y() => true; - static bool U() => true; - static bool V() => true; - }", - ); - let locals = analyze_clean( - "class C { - void F() { - bool a = X() && Y(); - bool b = U() && V(); - } - static bool X() => true; - static bool Y() => true; - static bool U() => true; - static bool V() => true; - }", - ); - assert_eq!(sum(&fields), 2.0, "two independent `&&` runs"); - assert_eq!(sum(&fields), sum(&locals)); -} - -#[test] -fn negation_does_not_break_a_boolean_run() { - // REGRESSION, and a cross-language inconsistency: C# scored `a && !b && c` as 2 - // while `mehen-java` scored the identical logic as 1. - // - // Java is right. Both SonarJava (`CognitiveComplexityVisitor - // .flattenLogicalExpression`) and SonarKotlin (`CognitiveComplexity - // .flattenOperators`) flatten only the `&&`/`||` operators and treat a negated - // operand as a plain operand where flattening stops — the `!` is invisible to the - // run. See `mehen-java/tests/cognitive.rs::negation_does_not_break_boolean_run`, - // which cites both. - let negated = analyze_clean( - "class C { - static bool F(bool a, bool b, bool c) { return a && !b && c; } - }", - ); - let plain = analyze_clean( - "class C { - static bool F(bool a, bool b, bool c) { return a && b && c; } - }", - ); - assert_eq!(sum(&negated), 1.0, "the `!` must not split the `&&` run"); - assert_eq!(sum(&negated), sum(&plain)); - - // Multiple negations in one run are equally invisible. - let many = analyze_clean( - "class C { - static bool F(bool a, bool b, bool c) { return !a && !b && c; } - }", - ); - assert_eq!(sum(&many), 1.0); -} - -#[test] -fn mixing_boolean_operators_still_costs_two() { - // The counterpart to the negation fix: ignoring `!` must not also collapse a - // genuine operator *change*. `a && b || c` is two runs. - let a = analyze_clean( - "class C { - static bool F(bool a, bool b, bool c) { return a && b || c; } - }", - ); - assert_eq!(sum(&a), 2.0); -} - -#[test] -fn switch_expression_arms_are_independent_boolean_contexts() { - // REGRESSION. An arm's result is a bare `expression` with no statement boundary, so - // nothing reset the run tracker between arms — `v switch { 1 => a && b, _ => c && d }` - // collapsed both `&&` into one run and scored 1 less than the equivalent switch - // statement, whose `case` bodies reach a statement rule and reset there. - let expression = analyze_clean( - "class C { - static bool F(int v, bool a, bool b, bool c, bool d) => - v switch { 1 => a && b, _ => c && d }; - }", - ); - let statement = analyze_clean( - "class C { - static bool F(int v, bool a, bool b, bool c, bool d) { - switch (v) { case 1: return a && b; default: return c && d; } - } - }", - ); - assert_eq!(sum(&expression), sum(&statement)); - // switch nesting(1) + arm decision(1) + two independent `&&` runs(2) = ... 3. - assert_eq!(sum(&expression), 3.0); -} - -#[test] -fn a_when_guard_is_its_own_boolean_context() { - // REGRESSION. `1 when a && b => c && d` has two independent `&&` runs, but nothing - // separated them — the guard's stayed in `last_op` and the arm result's collapsed - // into it. The guard now resets on entry, and the arm resets again afterwards. - let a = analyze_clean( - "class C { - static bool F(int v, bool a, bool b, bool c, bool d) => - v switch { 1 when a && b => c && d, _ => false }; - }", - ); - // switch nesting(1) + arm decision(0, cognitive) + guard run(1) + result run(1) = 3. - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn each_interpolation_hole_is_its_own_boolean_context() { - // REGRESSION, and the same shape as the `when` guard above: each `{…}` in one - // interpolated string is an independent expression, so `$"{a && b}{c && d}"` has two - // `&&` runs. Nothing separated them — the first hole left `last_op` set to `&&` and - // the second collapsed into it for a single increment. - // - // Pinned against the spelling that hoists each hole into a local, which must agree. - let holes = analyze_clean( - "class C { - static string F(bool a, bool b, bool c, bool d) => $\"{a && b}{c && d}\"; - }", - ); - let locals = analyze_clean( - "class C { - static string F(bool a, bool b, bool c, bool d) - { - var x = a && b; - var y = c && d; - return $\"{x}{y}\"; - } - }", - ); - assert_eq!(sum(&holes), sum(&locals)); - assert_eq!(sum(&holes), 2.0, "two independent runs"); - - // The guard: one hole is still one run, so the isolation did not start splitting a - // single run at the hole boundary. - let one = analyze_clean("class C { static string F(bool a, bool b) => $\"{a && b}\"; }"); - assert_eq!(sum(&one), 1.0); -} - -#[test] -fn each_initializer_element_is_its_own_boolean_context() { - // REGRESSION, and the third instance of this shape after the `when` guard and the - // interpolation hole: each element of an initializer or collection expression is an - // independent expression, so `new[] { a && b, c && d }` has two `&&` runs. The first - // element left `&&` in `last_op` and the second collapsed into it for 1. - // - // Pinned against BOTH equivalent spellings, which already scored 2: the same - // expressions as call arguments, and hoisted into locals. - let initializer = analyze_clean( - "class C { - static bool[] F(bool a, bool b, bool c, bool d) => new[] { a && b, c && d }; - }", - ); - let arguments = analyze_clean( - "class C { - static bool[] G(bool p, bool q) => null; - static bool[] F(bool a, bool b, bool c, bool d) => G(a && b, c && d); - }", - ); - assert_eq!(sum(&initializer), sum(&arguments)); - assert_eq!(sum(&initializer), 2.0, "two independent runs"); - - // A collection expression (C# 12 `[a && b, c && d]`) is the same shape through a - // different rule, so it needs its own arm. - let collection = analyze_clean( - "class C { - static System.Collections.Generic.List F(bool a, bool b, bool c, bool d) - => [a && b, c && d]; - }", - ); - assert_eq!(sum(&collection), 2.0); - - // The guard: one element is still one run, so the per-element reset did not start - // splitting a single run at an element boundary. - let one = analyze_clean("class C { static bool[] F(bool a, bool b) => new[] { a && b }; }"); - assert_eq!(sum(&one), 1.0); -} - -#[test] -fn each_linq_clause_is_its_own_boolean_context() { - // REGRESSION, and the fifth instance of this shape (argument, interpolation hole, - // initializer element, anonymous-object member, now LINQ clause). A query's clauses are - // independent expressions, so `from x in xs where a && b select c && d` has two runs — - // the predicate and the projection are no more one boolean context than two statements - // are. The predicate left `&&` in `last_op` and the projection collapsed into it. - let query = analyze_clean( - "using System.Linq; - class C { - static object F(bool[] xs, bool a, bool b, bool c, bool d) - => from x in xs where a && b select c && d; - }", - ); - let locals = analyze_clean( - "using System.Linq; - class C { - static object F(bool[] xs, bool a, bool b, bool c, bool d) - { - var p = a && b; - var q = c && d; - return from x in xs where p select q; - } - }", - ); - assert_eq!(sum(&query), sum(&locals)); - assert_eq!(sum(&query), 2.0, "two independent runs"); - - // The guard: one clause with a run is still one run. - assert_eq!( - sum(&analyze_clean( - "using System.Linq; - class C { - static object F(bool[] xs, bool a, bool b) => from x in xs where a && b select x; - }" - )), - 1.0 - ); -} - -#[test] -fn nested_pattern_combinators_are_observed_in_source_order() { - // REGRESSION. `classify_rule` runs pre-order, so a nested pattern's combinator was - // observed AFTER its parent's: `v is (> 0 and < 10) or (> 20 and < 30)` came through as - // `or, and, and`, collapsing the two `and`s into one run for 2. Source order is - // `and, or, and` — three runs — and the boolean tracker only collapses ADJACENT - // same-kind operators. - // - // Pinned against the operator spelling of the same test, which scored 3 all along. - let pattern = analyze_clean( - "class C { static bool F(int v) => v is (> 0 and < 10) or (> 20 and < 30); }", - ); - let operators = analyze_clean( - "class C { static bool F(int v) => (v > 0 && v < 10) || (v > 20 && v < 30); }", - ); - assert_eq!(sum(&pattern), sum(&operators)); - assert_eq!(sum(&pattern), 3.0); - - // The guards: the flat cases must not change, since only nesting was mis-ordered. - assert_eq!( - sum(&analyze_clean( - "class C { static bool F(int v) => v is > 0 and < 10; }" - )), - 1.0 - ); - assert_eq!( - sum(&analyze_clean( - "class C { static bool F(int v) => v is > 0 and < 10 or > 20; }" - )), - 2.0, - "one operator change is two runs" - ); -} diff --git a/crates/mehen-csharp/tests/common/mod.rs b/crates/mehen-csharp/tests/common/mod.rs deleted file mode 100644 index 99cb19d4..00000000 --- a/crates/mehen-csharp/tests/common/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Shared harness for the C# metric tests. -//! -//! Included via `mod common;` by each test binary, so the helpers are `pub` -//! for the including binary's benefit but never re-exported across a crate -//! boundary — hence the `unreachable_pub` allowance (the workspace lint is -//! aimed at library code, where an unreachable `pub` really is dead surface). -//! -//! `mehen-java` and `mehen-kotlin` inline an equivalent helper per test file -//! instead, because an earlier attempt at a shared module tripped the workspace's -//! `-D warnings` policy. This crate keeps the shared module deliberately: the -//! `allow` above resolves that (a `mod common` is compiled once per including -//! binary, so a helper any *one* file leaves unused is dead only in that binary), -//! and `analyze_clean`'s diagnostics assertion is load-bearing here in a way the -//! Java/Kotlin harnesses have no equivalent of. Nine copies of it would be nine -//! chances for one file to drop the assertion and start measuring error recovery -//! instead of the construct under test — the exact failure mode -//! `grammar/PROVENANCE.md` catalogues twenty-seven instances of. -#![allow(unreachable_pub, dead_code)] - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_csharp::CSharpAnalyzer; - -/// Analyze a C# snippet, normalizing the trailing newline the way the other -/// per-language test suites do. -pub fn analyze(source: &str) -> LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = CSharpAnalyzer::new(); - let file = SourceFile::new("Foo.cs".into(), Language::CSharp, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Analyze a snippet and assert it produced no parse/lex diagnostics — every -/// metric test's input must be valid C#, or the numbers are measuring recovery -/// rather than the construct under test. -pub fn analyze_clean(source: &str) -> LanguageAnalysis { - let a = analyze(source); - assert!( - a.diagnostics.is_empty(), - "snippet must parse cleanly, got {:?}", - a.diagnostics - ); - a -} diff --git a/crates/mehen-csharp/tests/contributions.rs b/crates/mehen-csharp/tests/contributions.rs deleted file mode 100644 index 6d68ffb1..00000000 --- a/crates/mehen-csharp/tests/contributions.rs +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the C# analyzer (plan §5.4). -//! -//! Pins the reason-code shape (`csharp..`, detail = the -//! grammar rule's snake_case name, or the operator spelling at token-level -//! sites) and the "evidence sums to the metric" invariant for every -//! event-shaped family the walker computes. - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_csharp::CSharpAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - CSharpAnalyzer::new() - .analyze( - &SourceFile::new("S.cs".into(), Language::CSharp, source.to_string()), - config, - ) - .expect("C# analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -public class Widget -{ - public int Count; - - public int Size { get; set; } = 3; - - public int Classify(int a, int b) - { - int total = 0; - if (a > 0 && b > 0) - { - total = a + b; - } - else - { - throw new System.ArgumentException(\"bad\"); - } - var scale = (int x) => x * 2; - total += scale(total); - return total > 10 ? total : 0; - } -} -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!( - analysis.diagnostics.is_empty(), - "fixture must parse cleanly, got {:?}", - analysis.diagnostics - ); - assert!(!analysis.contributions.is_empty()); - - // Families whose rolled-up value is exactly the sum of their per-event - // evidence. Cyclomatic includes the per-space McCabe base rows - // (`csharp.cyclomatic.base.`), so it sums exactly too. - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc.assignments", - "abc.branches", - "abc.conditions", - "nom.functions", - "nom.closures", - "nargs", - "npa", - "npm", - ] { - assert_eq!( - evidence_sum(&analysis, key), - metric(&analysis, key), - "evidence for `{key}` must sum to the published value", - ); - } -} - -#[test] -fn reasons_are_csharp_namespaced_with_rule_names() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - // Cyclomatic: rule-level decision + the token-level `&&`. - "csharp.cyclomatic.if_statement", - "csharp.cyclomatic.&&", - "csharp.cyclomatic.conditional_expression", - // Cognitive: nesting constructs, the flat `else`, the boolean run. - "csharp.cognitive.if_statement", - "csharp.cognitive.else", - "csharp.cognitive.&&", - "csharp.cognitive.conditional_expression", - // NExit: `throw x;` is spelled through `throw_expression` in this - // grammar; the expression-bodied lambda is its own exit. - "csharp.nexit.return_statement", - "csharp.nexit.throw_expression", - "csharp.nexit.parenthesized_lambda_expression", - // ABC. - "csharp.abc.assignment.local_variable_declarator", - "csharp.abc.assignment.assignment_expression", - "csharp.abc.assignment.property_declaration", - "csharp.abc.branch.invocation_expression", - "csharp.abc.branch.object_creation_expression", - "csharp.abc.condition.if_statement", - "csharp.abc.condition.&&", - "csharp.abc.condition.>", - "csharp.abc.condition.conditional_expression", - // NOM / NArgs. - "csharp.nom.function.method_declaration", - "csharp.nom.function.accessor_declaration", - "csharp.nom.closure.parenthesized_lambda_expression", - "csharp.nargs.function.method_declaration", - "csharp.nargs.closure.parenthesized_lambda_expression", - // NPA / NPM (public members only). - "csharp.npa.field_declaration", - "csharp.npm.property_declaration", - "csharp.npm.method_declaration", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("csharp."))); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn cognitive_amounts_carry_nesting_depth() { - // A doubly-nested `if` pays nesting+1 = 2 on the inner node — the §5.4 - // "why did cognitive move +2 here" answer. - let source = "\ -public class Nest -{ - public int Check(int a, int b) - { - if (a > 0) - { - if (b > 0) - { - return 1; - } - } - return 2; - } -} -"; - let analysis = analyze(source, &AnalysisConfig::production()); - let cognitive: Vec = analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == "cognitive.sum") - .map(|item| item.amount) - .collect(); - assert_eq!(cognitive, vec![1.0, 2.0]); - assert_eq!(metric(&analysis, "cognitive.sum"), 3.0); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc", - "nom", - "nargs", - "npa", - "npm", - ] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-csharp/tests/counters.rs b/crates/mehen-csharp/tests/counters.rs deleted file mode 100644 index f3579c71..00000000 --- a/crates/mehen-csharp/tests/counters.rs +++ /dev/null @@ -1,803 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NOM / NArgs / NExit / NPA / NPM / WMC tests for the ANTLR C# walker. -//! -//! C# visibility rules these pin: a class/struct member with no access -//! modifier is `private` (so it does NOT count toward the public API), -//! `internal` is assembly-scoped and likewise not public, interface members are -//! implicitly public, and `enum` members are implicitly public constants. - -mod common; - -use common::analyze_clean; -use mehen_core::MetricSpace; -use mehen_report::metrics_json; - -#[test] -fn nom_counts_functions_and_closures_separately() { - let a = analyze_clean( - "class C { - void M() { } - void N() { - System.Func f = x => x; - } - }", - ); - let nom = metrics_json::nom(&a.root.metrics); - assert_eq!(nom.functions, 2.0, "M and N"); - assert_eq!(nom.closures, 1.0, "the lambda"); -} - -#[test] -fn nargs_counts_parameters_per_shape() { - let a = analyze_clean( - "class C { - void Zero() { } - void Two(int a, int b) { } - void Params(params int[] rest) { } - }", - ); - let nargs = metrics_json::nargs(&a.root.metrics); - // 0 + 2 + 1 (a `params` array is one parameter) = 3 - assert_eq!(nargs.total_functions, 3.0); -} - -#[test] -fn nargs_counts_lambda_parameters_as_closure_args() { - let a = analyze_clean( - "class C { - void F() { - System.Func f = (a, b) => a + b; - } - }", - ); - let nargs = metrics_json::nargs(&a.root.metrics); - assert_eq!(nargs.total_closures, 2.0); -} - -#[test] -fn nargs_counts_operator_parameters() { - let a = analyze_clean( - "class C { - public static C operator +(C a, C b) { return a; } - }", - ); - let nargs = metrics_json::nargs(&a.root.metrics); - assert_eq!(nargs.total_functions, 2.0); -} - -#[test] -fn nexit_counts_returns_throws_and_yields() { - let a = analyze_clean( - "class C { - int F(int v) { - if (v < 0) { throw new System.ArgumentException(); } - return v; - } - System.Collections.Generic.IEnumerable G() { - yield return 1; - yield break; - } - }", - ); - let nexit = metrics_json::nexits(&a.root.metrics); - // throw + return + yield return + yield break = 4 - assert_eq!(nexit.sum, 4.0); -} - -#[test] -fn throw_expression_counts_as_an_exit() { - // A `throw` *expression* (C# 7) never reaches the statement form. - let a = analyze_clean( - "class C { - string F(string s) { return s ?? throw new System.ArgumentNullException(); } - }", - ); - let nexit = metrics_json::nexits(&a.root.metrics); - // the `return` + the `throw` expression = 2 - assert_eq!(nexit.sum, 2.0); -} - -// Key note for the NPA assertions below: in the published family, -// `npa.classes` is the *public* class-attribute count while -// `npa.class_attributes` is the count of ALL class attributes (the CDA -// denominator). So a visibility assertion checks `classes`, and a -// "did we see every declarator" assertion checks `class_attributes`. - -#[test] -fn npa_counts_only_public_fields() { - // `private`, implicit (private), and `internal` fields are all NOT public. - let a = analyze_clean( - "class C { - public int Pub; - private int Priv; - int Implicit; - internal int Internal; - }", - ); - let npa = metrics_json::npa(&a.root.metrics); - assert_eq!(npa.classes, 1.0, "only `public int Pub` is public"); - assert_eq!( - npa.class_attributes, 4.0, - "but all four are attributes (the CDA denominator)" - ); -} - -#[test] -fn npa_counts_each_declarator_of_a_multi_field() { - let a = analyze_clean("class C { public int a, b, c; }"); - let npa = metrics_json::npa(&a.root.metrics); - assert_eq!(npa.classes, 3.0); - assert_eq!(npa.class_attributes, 3.0); -} - -#[test] -fn npa_counts_constants_and_enum_members() { - let a = analyze_clean( - "class C { public const int Max = 1; } - enum E { A, B, C }", - ); - let npa = metrics_json::npa(&a.root.metrics); - // the public const + 3 implicitly-public enum members = 4 - assert_eq!(npa.classes, 4.0); -} - -#[test] -fn npm_counts_only_public_methods_of_a_class() { - let a = analyze_clean( - "class C { - public void Pub() { } - private void Priv() { } - void Implicit() { } - }", - ); - let npm = metrics_json::npm(&a.root.metrics); - // `npm.classes` is the PUBLIC class-method count; `npm.class_methods` is - // all of them (the CDA denominator) — same convention as NPA above. - assert_eq!(npm.classes, 1.0, "only `public void Pub` is public"); - assert_eq!(npm.class_methods, 3.0, "but all three are methods"); -} - -#[test] -fn npm_treats_interface_members_as_implicitly_public() { - let a = analyze_clean( - "interface I { - double Area { get; } - void Scale(double f); - }", - ); - let npm = metrics_json::npm(&a.root.metrics); - assert_eq!(npm.interface_methods, 2.0); - assert_eq!(npm.class_methods, 0.0); -} - -#[test] -fn npm_counts_properties_as_api_members() { - let a = analyze_clean( - "class C { - public int Count { get; set; } - }", - ); - let npm = metrics_json::npm(&a.root.metrics); - assert_eq!(npm.class_methods, 1.0, "the property is one API member"); -} - -#[test] -fn wmc_sums_method_complexity_per_class() { - // F: 1 + if = 2; G: 1. WMC = 3. - let a = analyze_clean( - "class C { - void F(int v) { if (v > 0) { } } - void G() { } - }", - ); - let wmc = metrics_json::wmc(&a.root.metrics); - assert_eq!(wmc.classes, 3.0); -} - -#[test] -fn wmc_excludes_interface_members() { - // An interface's members are not weighted (matches `mehen-java`). - let a = analyze_clean("interface I { void M(); }"); - let wmc = metrics_json::wmc(&a.root.metrics); - assert_eq!(wmc.interfaces, 0.0); - assert_eq!(wmc.classes, 0.0); -} - -#[test] -fn wmc_excludes_lambdas_and_local_functions() { - // Their complexity belongs to the enclosing method, which already counts - // it — so neither may inflate the class's WMC beyond the method's own. - let a = analyze_clean( - "class C { - void F() { - System.Func f = x => x > 0 ? 1 : 0; - int Local(int y) { if (y > 0) { return 1; } return 0; } - } - }", - ); - let wmc = metrics_json::wmc(&a.root.metrics); - // Only `F` is weighted: its own McCabe is 1 (the ternary and the `if` live - // in the lambda / local function, which carry their own spaces). - assert_eq!(wmc.classes, 1.0); -} - -#[test] -fn struct_members_route_to_the_class_buckets() { - let a = analyze_clean( - "struct S { - public int X; - public void M() { } - }", - ); - let npa = metrics_json::npa(&a.root.metrics); - let npm = metrics_json::npm(&a.root.metrics); - assert_eq!(npa.class_attributes, 1.0); - assert_eq!(npm.class_methods, 1.0); - assert_eq!(npa.interface_attributes, 0.0); -} - -#[test] -fn nargs_counts_a_simple_lambda_parameter() { - // REGRESSION. `x => …` puts its single parameter in a bare `identifier_token`, not - // a `parameter` child, so the count came back 0 — while the equivalent `(x) => …` - // (a `parenthesized_lambda_expression`, which does have a `parameter_list`) - // returned 1. Same arity, two different numbers depending on whether the author - // wrote the parentheses. - let bare = analyze_clean( - "class C { - void F() { System.Func f = x => x + 1; } - }", - ); - let parenthesized = analyze_clean( - "class C { - void F() { System.Func f = (x) => x + 1; } - }", - ); - assert_eq!( - metrics_json::nargs(&bare.root.metrics).total_closures, - 1.0, - "`x => …` takes one argument" - ); - assert_eq!( - metrics_json::nargs(&bare.root.metrics).total_closures, - metrics_json::nargs(&parenthesized.root.metrics).total_closures, - "the parentheses must not change the arity" - ); -} - -#[test] -fn nargs_of_an_indexer_accessor_does_not_depend_on_body_syntax() { - // REGRESSION. An accessor's space opens at `accessor_declaration`, which carries no - // parameter list — the indexer's `bracketed_parameter_list` is on the *owner*. So - // the block-bodied form reported 0 while the expression-bodied form, whose space - // opens at `indexer_declaration`, reported 1. The count is now threaded down. - let block = analyze_clean("class C { int this[int i] { get { return i; } } }"); - let expression = analyze_clean("class C { int this[int i] => i; }"); - assert_eq!( - metrics_json::nargs(&block.root.metrics).total_functions, - 1.0, - "an indexer's getter takes the indexer's one argument" - ); - assert_eq!( - metrics_json::nargs(&block.root.metrics).total_functions, - metrics_json::nargs(&expression.root.metrics).total_functions, - ); -} - -#[test] -fn nargs_of_a_property_accessor_is_zero() { - // A property's accessors take nothing — `set`'s `value` is implicit, not declared. - // Pinned alongside the indexer case: the same threading must not leak a count into - // a property. - let a = analyze_clean("class C { int P { get => 1; set { } } }"); - assert_eq!(metrics_json::nargs(&a.root.metrics).total_functions, 0.0); -} - -#[test] -fn nom_and_nargs_count_a_primary_constructor() { - // REGRESSION. A primary constructor's parameters live on the type declaration and - // no `constructor_declaration` node exists, so `class C(int x)` was absent from NOM - // and NArgs entirely. Pinned against the explicit form. - let primary = analyze_clean("class C(int x) { }"); - let explicit = analyze_clean("class C { public C(int x) { } }"); - for a in [&primary, &explicit] { - assert_eq!(metrics_json::nom(&a.root.metrics).functions, 1.0); - assert_eq!(metrics_json::nargs(&a.root.metrics).total_functions, 1.0); - } -} - -#[test] -fn a_primary_constructor_owns_its_whole_header() { - // REGRESSION (#219). The synthetic primary-constructor space got NOM and NArgs — - // computed at the open — but none of the Halstead, LLOC, or ABC contributions of - // the syntax it owns, because the space was closed before the walk reached its - // subtree: those landed on the enclosing type instead. `class C(int x) : B(C.F(x))` - // is the primary spelling of `class C : B { public C(int x) : base(C.F(x)) { } }`, - // so the two forms must *split* their per-space numbers identically — in - // particular the base-constructor call's two ABC branches (the call itself plus - // the nested `C.F(x)` invocation) belong to the constructor, not the class. - // - // Compared over the whole space tree rather than just the constructor, so a - // partial fix cannot pass: widening the synthetic span so the post-walk byte - // routing moves LOC/Halstead would still leave the walk-time ABC branches on the - // type, and the class row here would show them. - let primary = analyze_clean( - "class C(int x) : B(C.F(x)) - { - static int F(int x) { return x; } - }", - ); - let explicit = analyze_clean( - "class C : B - { - public C(int x) : base(C.F(x)) { } - static int F(int x) { return x; } - }", - ); - - /// Flatten the tree into `(depth, kind, name, ABC branches, LLOC)` rows. - fn rows(root: &MetricSpace) -> Vec<(usize, String, Option, f64, f64)> { - fn walk( - s: &MetricSpace, - depth: usize, - out: &mut Vec<(usize, String, Option, f64, f64)>, - ) { - out.push(( - depth, - s.kind.as_str().to_string(), - s.name.clone(), - metrics_json::abc(&s.metrics).branches, - metrics_json::loc(&s.metrics).lloc, - )); - for c in &s.spaces { - walk(c, depth + 1, out); - } - } - let mut out = Vec::new(); - walk(root, 0, &mut out); - out - } - assert_eq!(rows(&primary.root), rows(&explicit.root)); - - // The constructor's Halstead must cover its whole header. The parameter list - // alone is `( int x )` — 3 operator occurrences, 1 operand — so anything - // beyond that is the base list: `: B(C.F(x))` adds `:`, `.`, and two `(`/`)` - // pairs (operators) plus `B`, `C`, `F`, `x` (operands). - let ctor = &primary.root.spaces[0].spaces[0]; - assert_eq!(ctor.name.as_deref(), Some("C")); - let h = metrics_json::halstead(&ctor.metrics); - assert_eq!(h.big_n1, 9.0, "operators: ( int ) : . and 2 more ()-pairs"); - assert_eq!(h.big_n2, 5.0, "operands: x B C F x"); -} - -#[test] -fn a_primary_constructor_does_not_own_implemented_interfaces() { - // The guard on the whole-header fix above: only the base-constructor *call* is - // constructor syntax. An implemented interface in the same base list — - // `class C(int x) : B(x), IFoo` — belongs to the type, exactly as the explicit - // `class C : B, IFoo { public C(int x) : base(x) { } }` spelling attributes it. - // Closing the synthetic space at the end of the full `base_list` swept `IFoo` - // (and the `,`) into the constructor's Halstead. - let a = analyze_clean("class C(int x) : B(x), IFoo { }"); - let ctor = &a.root.spaces[0].spaces[0]; - assert_eq!(ctor.name.as_deref(), Some("C")); - // `( int x ) : B ( x )` and nothing after the call: were `, IFoo` included, N1 - // would gain the `,` and N2 the `IFoo`. - let h = metrics_json::halstead(&ctor.metrics); - assert_eq!(h.big_n1, 6.0, "operators: ( int ) : ( ) — no `,`"); - assert_eq!(h.big_n2, 3.0, "operands: x B x — no IFoo"); - // The base call is still the constructor's ABC branch. - assert_eq!(metrics_json::abc(&ctor.metrics).branches, 1.0); - - // With no base call at all, the base list is purely the type's: the - // constructor is just its parameter list, as for `struct S : IFoo` with an - // explicit constructor. - let a = analyze_clean("struct S(int x) : IFoo { }"); - let ctor = &a.root.spaces[0].spaces[0]; - assert_eq!(ctor.name.as_deref(), Some("S")); - let h = metrics_json::halstead(&ctor.metrics); - assert_eq!(h.big_n1, 3.0, "operators: ( int )"); - assert_eq!(h.big_n2, 1.0, "operands: x — no IFoo, no `:`"); - assert_eq!(metrics_json::abc(&ctor.metrics).branches, 0.0); -} - -#[test] -fn an_expression_bodied_return_is_an_exit() { - // REGRESSION. `int F() => 1;` has no `return_statement` node, so NExit stayed 0 - // while the equivalent `int F() { return 1; }` reported 1 — and NExit's own - // documentation includes value-returning expressions. Pinned against the block form. - let arrow = analyze_clean("class C { static int F() => 1; }"); - let block = analyze_clean("class C { static int F() { return 1; } }"); - assert_eq!(metrics_json::nexits(&arrow.root.metrics).sum, 1.0); - assert_eq!( - metrics_json::nexits(&arrow.root.metrics).sum, - metrics_json::nexits(&block.root.metrics).sum, - ); -} - -#[test] -fn a_void_expression_body_is_not_an_exit() { - // The guard: an expression body is a return only when the member returns a value. - // A `void` member, a constructor, and a `set` accessor return nothing. - let void_member = analyze_clean("class C { static void G() { } static void M() => G(); }"); - assert_eq!(metrics_json::nexits(&void_member.root.metrics).sum, 0.0); - - let constructor = analyze_clean("class C { static void G() { } public C() => G(); }"); - assert_eq!(metrics_json::nexits(&constructor.root.metrics).sum, 0.0); -} - -#[test] -fn a_getter_expression_body_is_an_exit_but_a_setter_is_not() { - // A `get` yields a value; `set` does not. Read per space, since the unit sums both. - let a = analyze_clean("class C { int _x; public int P { get => _x; set => _x = value; } }"); - let accessors: Vec<_> = a.root.spaces[0] - .spaces - .iter() - .map(|s| (s.name.clone(), metrics_json::nexits(&s.metrics).sum)) - .collect(); - assert_eq!( - accessors, - vec![ - (Some("P.get".to_string()), 1.0), - (Some("P.set".to_string()), 0.0), - ] - ); -} - -#[test] -fn a_throw_only_expression_body_is_one_exit() { - // REGRESSION introduced by the expression-body exit fix: `int F() => throw new E();` - // recorded the clause's implicit return AND the descendant `throw`, reporting NExit 2 - // where the block-bodied form reports 1. The clause is the return only when it - // actually returns a value. - let arrow = analyze_clean( - "class C { class E : System.Exception { } static int F() => throw new E(); }", - ); - let block = analyze_clean( - "class C { class E : System.Exception { } static int F() { throw new E(); } }", - ); - assert_eq!(metrics_json::nexits(&arrow.root.metrics).sum, 1.0); - assert_eq!( - metrics_json::nexits(&arrow.root.metrics).sum, - metrics_json::nexits(&block.root.metrics).sum, - ); -} - -#[test] -fn a_throw_inside_a_larger_expression_body_is_a_second_exit() { - // The guard is one level deep, not a subtree scan: in `=> x ?? throw new E();` the - // clause's return is real (it returns `x` when non-null) and the `throw` is another - // exit, so both count — matching the block-bodied `return x ?? throw new E();`. - let arrow = analyze_clean( - "class C { - class E : System.Exception { } - static string F(string x) => x ?? throw new E(); - }", - ); - let block = analyze_clean( - "class C { - class E : System.Exception { } - static string F(string x) { return x ?? throw new E(); } - }", - ); - assert_eq!(metrics_json::nexits(&arrow.root.metrics).sum, 2.0); - assert_eq!( - metrics_json::nexits(&arrow.root.metrics).sum, - metrics_json::nexits(&block.root.metrics).sum, - ); -} - -#[test] -fn a_primary_constructor_is_a_public_method_of_its_type() { - // REGRESSION. A primary constructor records NOM, NArgs, and WMC, but had no - // `member_declaration` to route through — so unlike the explicit spelling, which - // reaches `classify_type_member`, it recorded no NPM. The type's public API therefore - // depended on which constructor spelling the author chose. - // - // Always public: a primary constructor's accessibility cannot be narrowed (there are - // no modifiers to put on it), and its parameters ARE the construction surface. - let primary = analyze_clean("class C(int x) { }"); - let explicit = analyze_clean("class C { public C(int x) { } }"); - // `npm.classes` is the PUBLIC class-method count; `npm.class_methods` is all of them. - let npm = |a: &mehen_core::LanguageAnalysis| { - let m = metrics_json::npm(&a.root.metrics); - (m.classes, m.class_methods) - }; - assert_eq!(npm(&primary), npm(&explicit)); - assert_eq!(npm(&primary), (1.0, 1.0)); - - // `struct` and `record` are class-like for NPM, as they are for the rest of the - // family, so all three declaration kinds that admit a primary constructor agree. - for source in ["struct S(int x) { }", "record R(int X);"] { - assert_eq!(npm(&analyze_clean(source)), (1.0, 1.0), "{source}"); - } -} - -#[test] -fn a_void_like_async_expression_body_is_not_an_exit() { - // REGRESSION. `returns_value` tested the declared type against the text `"void"`, so - // `async Task M() => await Work();` looked like it returned — but it produces no - // result, and its block-bodied twin records no exit. NExit therefore depended on body - // syntax for one of the most common shapes in modern C#. - let nexit = |source: &str| metrics_json::nexits(&analyze_clean(source).root.metrics).sum; - - // The non-generic awaitables are void-like: arrow and block forms must agree. - for ty in ["Task", "ValueTask", "System.Threading.Tasks.Task"] { - let arrow = nexit(&format!( - "using System.Threading.Tasks; - class C {{ static async {ty} M() => await Task.Delay(1); }}" - )); - let block = nexit(&format!( - "using System.Threading.Tasks; - class C {{ static async {ty} M() {{ await Task.Delay(1); }} }}" - )); - assert_eq!(arrow, block, "`{ty}` is void-like"); - assert_eq!(arrow, 0.0, "`{ty}` yields no value"); - } - - // The generic forms DO return, so they must keep their exit — the fix must not mute - // every task-returning method. - for ty in ["Task", "ValueTask"] { - let arrow = nexit(&format!( - "using System.Threading.Tasks; - class C {{ static async {ty} M() => await Task.FromResult(1); }}" - )); - assert_eq!(arrow, 1.0, "`{ty}` returns a value"); - } - - // And an ordinary value-returning arrow body still counts, so the void-like set did - // not widen into everything. - assert_eq!(nexit("class C { static int M() => 1; }"), 1.0); - assert_eq!( - nexit("class C { static void W() { } static void M() => W(); }"), - 0.0 - ); -} - -#[test] -fn a_non_async_task_method_still_returns() { - // REGRESSION introduced by the void-like fix above: treating a bare `Task` as - // void-like unconditionally suppressed the exit for a *non-async* task-returning - // method, which must literally `return` a task object — so - // `Task M() => Task.CompletedTask;` reported 0 while - // `Task M() { return Task.CompletedTask; }` reported 1. The same - // body-syntax-dependent NExit, moved rather than fixed. - // - // "Void-like" is therefore a property of the type AND the `async` modifier, not of - // the type alone: `async` makes the compiler wrap the body's completion in the task. - let nexit = |source: &str| metrics_json::nexits(&analyze_clean(source).root.metrics).sum; - - for ty in ["Task", "ValueTask"] { - let arrow = nexit(&format!( - "using System.Threading.Tasks; - class C {{ static {ty} M() => default; }}" - )); - let block = nexit(&format!( - "using System.Threading.Tasks; - class C {{ static {ty} M() {{ return default; }} }}" - )); - assert_eq!(arrow, block, "non-async `{ty}` returns a value"); - assert_eq!(arrow, 1.0, "non-async `{ty}` is not void-like"); - } - - // `void` stays void-like unconditionally — it has no async/non-async distinction. - assert_eq!( - nexit("class C { static void W() { } static void M() => W(); }"), - 0.0 - ); -} - -#[test] -fn an_expression_bodied_lambda_records_its_exit() { - // REGRESSION. A lambda has no `arrow_expression_clause` for the member arm to match — - // Roslyn spells the body as a bare `(block | expression)` directly on the lambda — so - // `x => x + 1` reported NExit 0 while `x => { return x + 1; }` reported 1. - let closure_nexit = |source: &str| { - let a = analyze_clean(source); - fn walk(s: &mehen_core::MetricSpace, out: &mut Vec) { - if s.kind == mehen_core::SpaceKind::Closure { - out.push(metrics_json::nexits(&s.metrics).sum); - } - for c in &s.spaces { - walk(c, out); - } - } - let mut out = Vec::new(); - walk(&a.root, &mut out); - out - }; - - let arrow = closure_nexit( - "using System; - class C { static void F() { Func f = x => x + 1; f(1); } }", - ); - let block = closure_nexit( - "using System; - class C { static void F() { Func f = x => { return x + 1; }; f(1); } }", - ); - assert_eq!(arrow, block, "the two lambda body spellings must agree"); - assert_eq!(arrow, vec![1.0]); - - // The explicitly-typed C# 10 form is the same node with a `type?` child, so it agrees. - assert_eq!( - closure_nexit( - "using System; - class C { static void F() { Func f = int (int x) => x + 1; f(1); } }" - ), - vec![1.0] - ); - - // A `throw` body is excluded, for the same reason the member arm excludes it: - // `RULE_THROW_EXPRESSION` records that exit itself, so counting here would double it. - assert_eq!( - closure_nexit( - "using System; - class C { static void F() { Func f = x => throw new Exception(); f(1); } }" - ), - vec![1.0], - "a throwing lambda has exactly one exit, not two" - ); -} - -#[test] -fn a_primary_constructor_owns_its_signature_tokens() { - // REGRESSION. The synthetic space was pushed and popped *before* the type's children - // were visited, so it received none of the tokens inside its own signature: Halstead - // vocabulary 0. It now opens when the walk reaches the `parameter_list`, which is what - // the constructor consists of — Roslyn synthesizes no `constructor_declaration` node. - fn ctor_space(a: &mehen_core::LanguageAnalysis) -> mehen_core::MetricSpace { - fn walk(s: &mehen_core::MetricSpace, out: &mut Vec) { - if s.kind == mehen_core::SpaceKind::Function { - out.push(s.clone()); - } - for c in &s.spaces { - walk(c, out); - } - } - let mut out = Vec::new(); - walk(&a.root, &mut out); - out.remove(0) - } - - let primary = ctor_space(&analyze_clean("class C(int x) { }")); - let vocab = - metrics_json::halstead(&primary.metrics).n1 + metrics_json::halstead(&primary.metrics).n2; - assert!( - vocab > 0.0, - "the constructor must own the tokens of `(int x)`, got vocabulary {vocab}" - ); - - // NOT compared against the explicit spelling's vocabulary, deliberately: the two - // occupy different source text. A primary constructor is `(int x)` — four tokens — - // while `public C(int x) { }` is eight, because it repeats the type name and adds a - // modifier and braces. Halstead measures the text, so it must differ; NOM, NArgs, NPM, - // and WMC are the metrics that must agree, and they are pinned above. - assert_eq!(metrics_json::nargs(&primary.metrics).total, 1.0); -} - -#[test] -fn each_anonymous_object_member_is_its_own_boolean_context() { - // REGRESSION, and the fourth instance of this shape (argument, interpolation hole, - // initializer element, now anonymous-object member): each member of - // `new { A = a && b, B = c && d }` is an independent expression, so there are two `&&` - // runs. Its members are real `anonymous_object_member_declarator` rules, so unlike - // initializer elements each isolates on its own rather than needing a per-child reset. - let cognitive = |source: &str| metrics_json::cognitive(&analyze_clean(source).root.metrics).sum; - let anon = cognitive( - "class C { - static object F(bool a, bool b, bool c, bool d) => new { A = a && b, B = c && d }; - }", - ); - let locals = cognitive( - "class C { - static object F(bool a, bool b, bool c, bool d) - { - var x = a && b; - var y = c && d; - return new { A = x, B = y }; - } - }", - ); - assert_eq!(anon, locals); - assert_eq!(anon, 2.0, "two independent runs"); - - // The guard: one member is still one run. - assert_eq!( - cognitive("class C { static object F(bool a, bool b) => new { A = a && b }; }"), - 1.0 - ); -} - -#[test] -fn a_primary_constructor_records_its_logical_line() { - // REGRESSION, and a correction to my own earlier reasoning: opening the synthetic space - // at the `parameter_list` gave it tokens but no logical line, because a parameter list - // is not a declaration rule. `class C(int x) { }` reported LLOC 0 for its constructor - // where `class C { C(int x) { } }` reports 1. - // - // This does NOT double-count the `class C(int x)` row: that row belongs to the *class* - // space, recorded by `class_declaration`. This is the *constructor* space's own line — - // exactly the precedent an expression-bodied lambda sets, which records one so it - // matches its block-bodied twin. - fn first_function(a: &mehen_core::LanguageAnalysis) -> mehen_core::MetricSpace { - fn walk(s: &mehen_core::MetricSpace, out: &mut Vec) { - if s.kind == mehen_core::SpaceKind::Function { - out.push(s.clone()); - } - for c in &s.spaces { - walk(c, out); - } - } - let mut out = Vec::new(); - walk(&a.root, &mut out); - out.remove(0) - } - - let primary = first_function(&analyze_clean("class C(int x) { }")); - let explicit = first_function(&analyze_clean("class C { public C(int x) { } }")); - assert_eq!( - metrics_json::loc(&primary.metrics).lloc, - metrics_json::loc(&explicit.metrics).lloc - ); - assert_eq!(metrics_json::loc(&primary.metrics).lloc, 1.0); - - for source in ["struct S(int x) { }", "record R(int X);"] { - assert_eq!( - metrics_json::loc(&first_function(&analyze_clean(source)).metrics).lloc, - 1.0, - "{source}" - ); - } -} - -#[test] -fn an_explicitly_void_lambda_is_not_an_exit() { - // REGRESSION introduced by the lambda-exit fix: that arm recorded an exit for *every* - // non-block lambda body, but C# 10's `void () => Console.WriteLine()` declares a return - // type and declares no value — so it disagreed with its own block-bodied twin. - let closure_nexits = |source: &str| { - let a = analyze_clean(source); - fn walk(s: &mehen_core::MetricSpace, out: &mut Vec) { - if s.kind == mehen_core::SpaceKind::Closure { - out.push(metrics_json::nexits(&s.metrics).sum); - } - for c in &s.spaces { - walk(c, out); - } - } - let mut out = Vec::new(); - walk(&a.root, &mut out); - out - }; - - let arrow = closure_nexits( - "using System; - class C { static void F() { Action a = void () => Console.WriteLine(); a(); } }", - ); - let block = closure_nexits( - "using System; - class C { static void F() { Action a = void () => { Console.WriteLine(); }; a(); } }", - ); - assert_eq!(arrow, block, "the two void-lambda spellings must agree"); - assert_eq!(arrow, vec![0.0]); - - // The guard: an explicitly-typed *value*-returning lambda keeps its exit, so the check - // reads the declared type rather than muting every typed lambda. - assert_eq!( - closure_nexits( - "using System; - class C { static void F() { Func f = int (int x) => x + 1; f(1); } }" - ), - vec![1.0] - ); - // And an untyped one, which has no `type?` slot at all. - assert_eq!( - closure_nexits( - "using System; - class C { static void F() { Func f = x => x + 1; f(1); } }" - ), - vec![1.0] - ); -} diff --git a/crates/mehen-csharp/tests/cyclomatic.rs b/crates/mehen-csharp/tests/cyclomatic.rs deleted file mode 100644 index 196fff69..00000000 --- a/crates/mehen-csharp/tests/cyclomatic.rs +++ /dev/null @@ -1,228 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity tests for the ANTLR C# walker. -//! -//! Decisions (SonarC#-aligned): `if`, every loop (`while`/`do`/`for`/ -//! `foreach`), each `case` label, the ternary `?:`, and each short-circuit -//! `&&`/`||`. `switch` itself, `catch`, `else`, `try`, and `default:` are not -//! decisions. Every function space contributes a base McCabe `+1`, as does the -//! enclosing type space — so the unit `sum` folds in the type(1) and each -//! member's McCabe value. - -mod common; - -use common::analyze_clean; - -fn sum(a: &mehen_core::LanguageAnalysis) -> f64 { - mehen_report::metrics_json::cyclomatic(&a.root.metrics).sum -} - -#[test] -fn simple_if_is_one_decision() { - // unit(1) + class(1) + method(1 + 1 if) = 4 - let a = analyze_clean( - "class C { - int F(int a, int b) { - if (a > b) { return a; } - return b; - } - }", - ); - assert_eq!(sum(&a), 4.0); -} - -#[test] -fn else_is_not_a_decision() { - // Only the `if` counts; `else` adds nothing to cyclomatic. - let a = analyze_clean( - "class C { - int F(int a) { - if (a > 0) { return 1; } else { return 2; } - } - }", - ); - assert_eq!(sum(&a), 4.0); -} - -#[test] -fn every_loop_form_is_one_decision() { - // unit(1) + class(1) + method(1 + while + do + for + foreach) = 7 - let a = analyze_clean( - "class C { - void F(int[] xs) { - while (true) { break; } - do { break; } while (true); - for (int i = 0; i < 1; i++) { } - foreach (var x in xs) { } - } - }", - ); - assert_eq!(sum(&a), 7.0); -} - -#[test] -fn switch_itself_is_not_a_decision_but_cases_are() { - // unit(1) + class(1) + method(1 + case 1 + case 2) = 5. - // `switch` and `default:` add nothing. - let a = analyze_clean( - "class C { - int F(int v) { - switch (v) { - case 1: return 1; - case 2: return 2; - default: return 0; - } - } - }", - ); - assert_eq!(sum(&a), 5.0); -} - -#[test] -fn ternary_is_a_decision() { - let a = analyze_clean( - "class C { - int F(int a) { return a > 0 ? 1 : 2; } - }", - ); - assert_eq!(sum(&a), 4.0); -} - -#[test] -fn each_short_circuit_operator_is_a_decision() { - // unit(1) + class(1) + method(1 + if + && + ||) = 6 - let a = analyze_clean( - "class C { - bool F(bool a, bool b, bool c) { - if (a && b || c) { return true; } - return false; - } - }", - ); - assert_eq!(sum(&a), 6.0); -} - -#[test] -fn catch_and_try_are_not_decisions() { - // unit(1) + class(1) + method(1) = 3 — neither `try` nor `catch` counts. - let a = analyze_clean( - "class C { - void F() { - try { G(); } catch (System.Exception) { } - } - void G() { } - }", - ); - // Two methods, so unit(1) + class(1) + F(1) + G(1) = 4. - assert_eq!(sum(&a), 4.0); -} - -#[test] -fn null_coalescing_is_not_a_decision() { - // `??` is an ABC condition but not a McCabe decision (it is not a - // short-circuit *boolean* operator in SonarSource's decision list). - let a = analyze_clean( - "class C { - string F(string s) { return s ?? \"d\"; } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn a_switch_expression_scores_like_a_switch_statement() { - // REGRESSION. A switch *expression* scored no decisions at all, so rewriting a - // switch statement into the expression form — which is the idiomatic modern C# - // spelling of exactly the same branching — silently lowered the score. Pinned - // against the statement form rather than an absolute number, since the point is - // the equivalence. - let expression = analyze_clean( - "class C { - int F(int v) { - return v switch { 1 => 1, 2 => 2, _ => 0 }; - } - }", - ); - let statement = analyze_clean( - "class C { - int F(int v) { - switch (v) { - case 1: return 1; - case 2: return 2; - default: return 0; - } - } - }", - ); - assert_eq!(sum(&expression), sum(&statement)); - // unit(1) + class(1) + method(1 + 2 arms) = 5. - assert_eq!(sum(&expression), 5.0); -} - -#[test] -fn pattern_combinators_are_decisions() { - // REGRESSION. `and`/`or` are C# 9's spelling of `&&`/`||` in pattern position; - // they must count the same. `not` mirrors `!` and is not itself a decision. - // unit(1) + class(1) + method(1 + 1 `and`) = 4. - let a = analyze_clean( - "class C { - bool F(object o) { return o is int and long; } - }", - ); - assert_eq!(sum(&a), 4.0); -} - -#[test] -fn a_negated_pattern_is_not_a_decision() { - // `is not null` is one type test, no combinator decision — same as `!x`. - let a = analyze_clean( - "class C { - bool F(object o) { return o is not null; } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn generic_delimiters_are_not_decisions() { - // The `<`/`>` of a generic type are delimiters, not comparisons — and a - // comparison is not a McCabe decision anyway, so this pins that the delimiter - // handling did not accidentally start recording one. - let a = analyze_clean( - "class C { - System.Collections.Generic.List F() { return null; } - }", - ); - assert_eq!(sum(&a), 3.0); -} - -#[test] -fn a_guarded_discard_arm_is_a_decision() { - // REGRESSION. A discard is the fall-through only when it is *unguarded*: - // `_ when enabled => …` tests `enabled` and can fail, so it is a real decision — - // and the equivalent `case _ when enabled:` in a switch statement counts as one. - // The arm was excluded on its pattern alone, so the guard scored nothing. - let expression = analyze_clean( - "class C { - static int F(int v, bool enabled) => v switch { _ when enabled => 1, _ => 0 }; - }", - ); - let statement = analyze_clean( - "class C { - static int F(int v, bool enabled) { - switch (v) { case int _ when enabled: return 1; default: return 0; } - } - }", - ); - assert_eq!(sum(&expression), sum(&statement)); - // unit(1) + class(1) + method(1 + 1 guarded arm) = 4. - assert_eq!(sum(&expression), 4.0); -} - -#[test] -fn an_unguarded_discard_arm_is_not_a_decision() { - // The counterpart: a bare `_` always matches, so it stays the fall-through. - let a = analyze_clean("class C { static int F(int v) => v switch { _ => 0 }; }"); - assert_eq!(sum(&a), 3.0); -} diff --git a/crates/mehen-csharp/tests/lexer.rs b/crates/mehen-csharp/tests/lexer.rs deleted file mode 100644 index 32b80b92..00000000 --- a/crates/mehen-csharp/tests/lexer.rs +++ /dev/null @@ -1,764 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Tokenization tests for the hand-written C# lexer. -//! -//! Roslyn publishes a parser-only grammar, so every terminal in -//! `mehen-csharp-parser/grammar/lexer-tokens.g4.in` is ours. A wrong token -//! *boundary* there is the most dangerous kind of bug in this crate: an -//! over-greedy rule still yields a valid token, so the parser reports no error and -//! the swallowed code silently disappears from every metric. These tests pin the -//! boundaries by measuring what survives — LLOC counts the statements a token span -//! did not eat. -//! -//! See `PROVENANCE.md`: a clean corpus run measures *parseability*, not -//! correctness. - -mod common; - -use common::analyze_clean; -use mehen_report::metrics_json; - -/// LLOC for a snippet that must also parse cleanly. -fn lloc(source: &str) -> f64 { - metrics_json::loc(&analyze_clean(source).root.metrics).lloc -} - -#[test] -fn an_empty_string_does_not_swallow_the_statements_after_it() { - // REGRESSION. The raw-string rule was once fenced with TWO quotes - // (`'""' ~[\r\n]*? '""'`), but `""` is the empty string literal — so this line - // lexed as one "raw string" spanning from the first `""` to the last, eating - // both statements between them. It produced no diagnostic, because the result - // was a perfectly valid token. - // - // class(1) + method(1) + 3 locals = 5. Anything less means a token boundary - // is eating code. - assert_eq!( - lloc( - "class C - { - void M() - { - var a = \"\"; - int x = 1; - var b = \"\"; - } - }" - ), - 5.0 - ); -} - -#[test] -fn a_single_line_raw_string_is_fenced_with_three_quotes() { - // C# 11 raw strings fence with *at least* three quotes in both the - // single- and multi-line forms; the distinction is whether the content holds a - // newline. class(1) + method(1) + 2 locals = 4. - assert_eq!( - lloc( - "class C - { - void M() - { - var a = \"\"\"x\"\"\"; - int y = 1; - } - }" - ), - 4.0 - ); -} - -#[test] -fn a_multi_line_raw_string_spans_rows_without_eating_the_next_statement() { - let source = "class C - { - void M() - { - var a = \"\"\" - line - \"\"\"; - int y = 1; - } - }"; - assert_eq!(lloc(source), 4.0); - // Every interior row of the literal is code, not a phantom blank. - let loc = metrics_json::loc(&analyze_clean(source).root.metrics); - assert_eq!(loc.blank, 0.0); -} - -#[test] -fn both_verbatim_interpolation_prefixes_parse() { - // `$@"…"` and `@$"…"` are the same string in C# 11+. Roslyn's grammar spells - // only the first, so the second needs its own lexer alternative — without it - // `@$"a{X}"` failed to tokenize at all. - for prefix in ["$@", "@$"] { - let source = format!( - "class C - {{ - void M() - {{ - var X = 1; - var s = {prefix}\"a{{X}}b\"; - }} - }}" - ); - assert_eq!(lloc(&source), 4.0, "prefix `{prefix}\"` must parse"); - } -} - -#[test] -fn an_interpolated_raw_string_parses_its_holes() { - // `$"""a{x}b"""` needs its own lexer mode: in the default mode the `a` between - // holes lexes as an IDENTIFIER, which is what made this shape report three - // diagnostics. class(1) + method(1) + 2 locals = 4. - assert_eq!( - lloc( - "class C - { - void M() - { - var X = 1; - var s = $\"\"\"a{X}b\"\"\"; - } - }" - ), - 4.0 - ); -} - -#[test] -fn a_quote_inside_an_interpolated_raw_string_is_literal_text() { - // Only a run of three quotes closes a raw string, so the lone `"` here is - // content and must not end the literal early. - assert_eq!( - lloc( - "class C - { - void M() - { - var X = 1; - var s = $\"\"\"say \"hi\" {X}\"\"\"; - int y = 1; - } - }" - ), - 5.0 - ); -} - -#[test] -fn a_nested_brace_inside_an_interpolation_hole_does_not_close_it() { - // The `}` of the collection initializer is lexically identical to the one that - // ends the hole; the grammar's brace-depth predicates are what tell them apart. - assert_eq!( - lloc( - "class C - { - void M() - { - var s = $\"a{ new[]{ 1, 2 }.Length }b\"; - int y = 1; - } - }" - ), - 4.0 - ); -} - -#[test] -fn an_interpolation_format_specifier_is_not_code() { - // `D4` must not lex as an identifier, and the `:` that introduces it must not - // be read as an ordinary colon. - assert_eq!( - lloc( - "class C - { - void M() - { - var X = 1; - var s = $\"{X:D4}\"; - int y = 1; - } - }" - ), - 5.0 - ); -} - -#[test] -fn a_diagnostic_span_covers_exactly_the_offending_token() { - // REGRESSION. The error-node span added 1 to the runtime's `stop_byte`, but that - // offset is already **exclusive** — `Token::byte_span` is - // `start_byte()..stop_byte()`. Every diagnostic span was therefore one byte too - // long, so a `(` was reported as `"( "`, swallowing the following character. This - // is also the only place in `mehen-antlr` that did so: `span.rs` and `comments.rs` - // already used the offset directly. - let source = "class C { void M( }\n"; - let a = common::analyze(source); - assert!(!a.diagnostics.is_empty(), "this input must not parse"); - for diagnostic in &a.diagnostics { - let Some(span) = diagnostic.span else { - continue; - }; - let text = &source[span.start_byte as usize..span.end_byte as usize]; - assert!( - !text.ends_with(' '), - "span {}..{} = {text:?} runs past its token", - span.start_byte, - span.end_byte - ); - } -} - -#[test] -fn an_interpolation_format_clause_may_contain_a_quoted_literal() { - // REGRESSION. A custom numeric format can carry a quoted literal — - // `$"{n:0\"kg\"}"` is valid C# for "the number, then kg" — but the - // INTERPOLATION_FORMAT mode had no rule for `"` at all, so the backslash lexed as - // ordinary text and the following quote could not be consumed. - // - // The fix has to keep the whole clause as ONE token: the parser rule is - // `interpolation_format_clause : ':' interpolated_string_text_token`, so emitting - // the escape separately made the clause unparsable (the first attempt did exactly - // that and traded three lexer errors for two parser errors). - assert_eq!( - lloc("class C { static string M(int n) => $\"{n:0\\\"kg\\\"}\"; }"), - 2.0 - ); -} - -#[test] -fn a_verbatim_format_clause_may_contain_a_doubled_quote() { - // The verbatim spelling of the same thing. Both escapes are accepted in this mode - // because the enclosing string decides which is legal, and the clause's extent is - // all any metric reads. - assert_eq!( - lloc("class C { static string M(int n) => $@\"{n:0\"\"kg\"\"}\"; }"), - 2.0 - ); -} - -#[test] -fn a_backslash_in_a_format_clause_is_ordinary_text() { - // A backslash that is not part of an escaped quote must still lex — the first fix - // attempt broke this by giving `\` its own rule after the escape rule. - assert_eq!( - lloc("class C { static string M(int n) => $\"{n:0\\\\0}\"; }"), - 2.0 - ); -} - -#[test] -fn an_alignment_and_format_clause_together_still_parse() { - // `{n,5:D4}` — the alignment clause is a separate rule reached before the format - // one, so this pins that widening the format text did not disturb it. - assert_eq!( - lloc("class C { static string M(int n) => $\"{n,5:D4}\"; }"), - 2.0 - ); -} - -#[test] -fn a_parenthesized_ternary_in_an_interpolation_hole_parses() { - // REGRESSION. `nestDepth` counted only braces, so the ternary's `:` sat at depth 0 - // and INTERP_FORMAT_COLON claimed it as a format delimiter — `2)` became - // interpolation text and `$"{(flag ? 1 : 2)}"` reported four diagnostics. The - // counter now tracks every bracketing construct inside a hole, since the only - // question it answers is whether a `:` is still part of the expression. - assert_eq!( - lloc("class C { static string M(bool flag) => $\"{(flag ? 1 : 2)}\"; }"), - 2.0 - ); -} - -#[test] -fn brackets_in_an_interpolation_hole_parse() { - // The `[`/`]` half of the same counter — an indexer or a dictionary initializer - // inside a hole has the same shape as the parenthesized ternary. - assert_eq!( - lloc("class C { static string M(int[] a) => $\"{a[0]}\"; }"), - 2.0 - ); -} - -#[test] -fn a_format_clause_does_not_leak_hole_state() { - // REGRESSION, and the worse of the two: INTERP_FORMAT_END popped both lexer modes - // but left its `holeStack` entry behind, so `holeStack.Count > 0` stayed true after - // the string ended. The next `:` anywhere in the file then matched - // INTERP_FORMAT_COLON and pushed INTERPOLATION_FORMAT again, swallowing the rest of - // the line as format text — here, a ternary three tokens later. - assert_eq!( - lloc( - "class C { - static int M(int n, bool flag) { - var s = $\"{n:D4}\"; - return flag ? 1 : 2; - } - }" - ), - 4.0 - ); -} - -#[test] -fn a_line_comment_ends_at_every_csharp_line_terminator() { - // REGRESSION. ECMA-334 §6.3.1 lists five line terminators — CR, LF, NEL (U+0085), - // LS (U+2028), PS (U+2029) — but the comment rules excluded only CR and LF, so a - // comment ended by one of the other three swallowed the rest of the file. The type - // grammar's optional braces then allowed recovery, so the analysis *completed* with - // the swallowed members silently missing: a clean parse over half a file. - for terminator in ['\n', '\r', '\u{85}', '\u{2028}', '\u{2029}'] { - let source = format!("class C {{ // note{terminator} void M() {{ }} }}"); - let a = analyze_clean(&source); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - assert_eq!( - nom.functions, 1.0, - "U+{:04X} must end the comment so `M` survives", - terminator as u32 - ); - } -} - -#[test] -fn a_unicode_escape_is_a_legal_identifier_character() { - // REGRESSION. `int a = 1;` declares `a` — Roslyn lists - // `unicode_escape_sequence` in both `identifier_start_character` and - // `identifier_part_character`, so tokenizing those rules has to carry it over. The - // backslash could not be consumed and the declaration reported two lexer errors. - assert_eq!( - lloc("class C { static void M() { int \\u0061 = 1; } }"), - 3.0 - ); -} - -#[test] -fn a_directive_ends_at_every_csharp_line_terminator() { - // REGRESSION, and the same oversight as the comment rules one commit earlier: - // `DIRECTIVE_LINE` still stopped only at CR/LF, so a directive ended by NEL / - // U+2028 / U+2029 consumed the separator *and everything after it* onto the - // directive channel — a whole file reported as zero declarations with zero - // diagnostics. - for terminator in ['\n', '\r', '\u{85}', '\u{2028}', '\u{2029}'] { - let source = format!("#if X{terminator}class C {{ void M() {{ }} }}\n#endif\n"); - let a = analyze_clean(&source); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - assert_eq!( - nom.functions, 1.0, - "U+{:04X} must end the directive so the class survives", - terminator as u32 - ); - } -} - -#[test] -fn every_enumerated_raw_string_fence_width_parses() { - // The fence-length rule ("close on a run at least as long as the opening one") needs - // state to express in general — a member holding the opening width and a predicate - // comparing each candidate closer. Every alternative here is stateless, so the widths - // are enumerated three through eight, each embedding one fewer quote than its fence. - // - // Six through eight were added after a review found that five was the ceiling: a - // six-quote fence (which exists to embed `"""""`) reported two diagnostics on valid - // C#. Past eight the three-quote arm matches and terminates early, costing the - // literal's tail — an acceptable floor, since the deepest fence in the 322-file - // corpus is three. - for width in 3..=8 { - let fence = "\"".repeat(width); - let inner = "\"".repeat(width - 1); - let source = format!("class C {{ static string M() => {fence}a{inner}b{fence}; }}"); - assert_eq!( - lloc(&source), - 2.0, - "a {width}-quote fence must embed a {}-quote run", - width - 1 - ); - } -} - -#[test] -fn a_longer_raw_string_fence_can_embed_three_quotes() { - // REGRESSION. `""""a"""b""""` is valid C# — a four-quote fence exists precisely so - // the content can contain `"""` — but a single non-greedy rule stopped at the - // *first* three-quote run, terminating the literal early and leaving `b""""` as - // stray tokens. The fence-length rule ("close on a run at least as long as the - // opening one") needs one alternative per length, longest first. - assert_eq!( - lloc("class C { static string M() => \"\"\"\"a\"\"\"b\"\"\"\"; }"), - 2.0 - ); - // And one length further, for a literal embedding four quotes. - assert_eq!( - lloc("class C { static string M() => \"\"\"\"\"a\"\"\"\"b\"\"\"\"\"; }"), - 2.0 - ); -} - -#[test] -fn a_longer_fence_works_multi_line_too() { - // The multi-line form needs the same per-length alternatives, and the single-line - // rule must still win the tie for a one-liner (ANTLR breaks equal-length matches by - // order, and the parser reaches the two through different rules). - assert_eq!( - lloc( - "class C - { - static string M() => \"\"\"\" - a\"\"\"b - \"\"\"\"; - }" - ), - 2.0 - ); -} - -#[test] -fn u8_is_a_legal_identifier() { - // REGRESSION. `u8`/`U8` are *contextual* — a suffix only directly after a string - // literal — so `class C { int u8; }` is valid C# and reported four diagnostics. - // They had been withheld from the `identifier_token` widening, which is the same - // mistake the comment beside that set already warned about for `_`. - assert_eq!(lloc("class C { int u8; }"), 2.0); - assert_eq!(lloc("class C { int U8; }"), 2.0); -} - -#[test] -fn the_utf8_suffix_still_works_after_a_literal() { - // The counterpart: widening must not break the suffix, which is positional — - // `utf8_string_literal_token : string_literal_token (KW_U8 | KW_U8_LOWER)` requires - // the preceding literal, so a bare `u8` cannot be mistaken for it. - assert_eq!( - lloc("class C { static System.ReadOnlySpan M() => \"x\"u8; }"), - 2.0 - ); -} - -#[test] -fn a_two_dollar_raw_string_opens_its_hole_on_a_doubled_brace() { - // REGRESSION. The dollar count sets the brace width: with `$$"""…"""` a hole opens on - // `{{` and a lone `{` is literal text (C# 11 chose this so brace-heavy text like JSON - // needs no escaping). The lexer had ONE raw mode, whose `{{` rule read a doubled brace - // as escaped text — so `$$"""{{a && b}}"""` swallowed the hole's expression whole. Zero - // diagnostics, and `a && b`'s operators and complexity vanished. - // - // `dotnet/runtime` uses this shape for embedded JSON (`$$"""{"k":{{v}}}"""`), which is - // exactly why it matters, and why it was missed: those files are under `tests/`, not in - // the `src/` corpus. - // - // Asserted through cognitive complexity, which is 0 if the hole is text and 1 if the - // `&&` really reached the parser — pinned against both narrower spellings. - let cognitive = |source: &str| { - mehen_report::metrics_json::cognitive(&analyze_clean(source).root.metrics).sum - }; - let two_dollar = - cognitive("class C { static string F(bool a, bool b) => $$\"\"\"{{a && b}}\"\"\"; }"); - let one_dollar = - cognitive("class C { static string F(bool a, bool b) => $\"\"\"{a && b}\"\"\"; }"); - let plain = cognitive("class C { static string F(bool a, bool b) => $\"{a && b}\"; }"); - assert_eq!(two_dollar, one_dollar, "the hole must reach the parser"); - assert_eq!(two_dollar, plain); - assert_eq!(two_dollar, 1.0); -} - -#[test] -fn a_lone_brace_in_a_two_dollar_raw_string_is_text() { - // The counterpart, and the reason the width-2 text rule is split into single-character - // brace rules: a LONE brace at this width is literal text, so brace-heavy content must - // survive intact. ANTLR takes the longest match and breaks only ties by order, so a - // text rule able to consume `{{a}}` would beat the two-character hole rule no matter - // which came first — that was the first attempt and it swallowed the hole again. - // - // Two statements after the literal: if a brace rule over-matched, the token would eat - // them and LLOC would drop. class(1) + method(1) + 2 locals = 4. - assert_eq!( - lloc( - "class C - { - static void M() - { - var json = $$\"\"\"{\"k\": 1}\"\"\"; - int x = 1; - } - }" - ), - 4.0 - ); -} - -#[test] -fn an_interpolated_raw_string_closes_on_its_own_fence_width() { - // REGRESSION. A four-quote opening fence exists so that an embedded `"""` is content: - // `$""""a"""b""""`. The interpolation modes closed on any three-or-more run, so the - // string ended at the embedded triple and the tail became stray code — 8 diagnostics, - // and the metrics around it wrong too (LLOC 3 against 2). - // - // Only the CLOSE rule is fence-width-sensitive, so each width carries its own mode. - // Four is the documented floor: a wider fence is needed only when the *content* holds a - // run of three or more quotes, and `dotnet/runtime` has no interpolated raw string with - // even a four-quote fence. - // - // `analyze_clean` asserts no diagnostics, so reaching the assertion is the substance; - // LLOC then pins that the token did not eat the statements after it. - for source in [ - "class C { static string F() => $\"\"\"ab\"\"\"; }", - "class C { static string F() => $\"\"\"\"a\"\"\"b\"\"\"\"; }", - "class C { static string F(int v) => $$\"\"\"{{v}}\"\"\"; }", - "class C { static string F(int v) => $$\"\"\"\"{{v}}\"\"\"a\"\"\"b\"\"\"\"; }", - ] { - // class(1) + method(1) = 2. More means the literal's tail leaked out as code. - assert_eq!(lloc(source), 2.0, "fence width must be respected: {source}"); - } -} - -#[test] -fn an_unknown_escape_sequence_is_an_error() { - // REGRESSION. `Escape` ended in `| .`, so any character after a backslash was accepted - // and `'\q'` — not valid C# — lexed as an ordinary character literal. The analyzer - // reported a clean, complete analysis of invalid source, which is the wrong direction - // for a tool whose contract is that a clean parse means something. - // - // `analyze` rather than `analyze_clean`: the point here is that diagnostics DO appear. - for source in [ - "class C { static char F() => '\\q'; }", - "class C { static string F() => \"a\\qb\"; }", - "class C { static string F() => \"a\\eb\"; }", - ] { - assert!( - !common::analyze(source).diagnostics.is_empty(), - "an unknown escape must be reported: {source}" - ); - } -} - -#[test] -fn every_legal_escape_sequence_still_lexes() { - // The guard on the enumeration: narrowing `Escape` must not reject anything ECMA-334 - // §6.4.5.6 allows. The simple set is `\' \" \\ \0 \a \b \f \n \r \t \v`, plus hex - // (one to four digits) and the two unicode widths. - for escape in [ - "\\'", - "\\\"", - "\\\\", - "\\0", - "\\a", - "\\b", - "\\f", - "\\n", - "\\r", - "\\t", - "\\v", - "\\x4", - "\\x41", - "\\x0041", - "\\u0041", - "\\U00000041", - ] { - // Both literal kinds: a char literal has no closure to absorb a mis-sized escape, - // so it is the stricter of the two. - assert_eq!( - lloc(&format!( - "class C {{ static string F() => \"a{escape}b\"; }}" - )), - 2.0, - "`{escape}` must lex in a string" - ); - assert_eq!( - lloc(&format!("class C {{ static char F() => '{escape}'; }}")), - 2.0, - "`{escape}` must lex in a char literal" - ); - } -} - -#[test] -fn an_interpolated_string_validates_its_escapes_too() { - // REGRESSION beyond the ordinary-literal escape fix: the interpolation mode had its own - // `'\\' .` rule, so `$"\q"` still lexed clean while `"\q"` was rejected — the two - // spellings of the same invalid source disagreed. It now reuses the enumerated `Escape` - // fragment. - for source in [ - "class C { static string F() => $\"\\q\"; }", - "class C { static string F() => $\"a\\eb\"; }", - ] { - assert!( - !common::analyze(source).diagnostics.is_empty(), - "an unknown escape in an interpolated string must be reported: {source}" - ); - } - // And a legal one still lexes, in the interpolated spelling as well. - assert_eq!(lloc("class C { static string F() => $\"a\\nb\"; }"), 2.0); -} - -#[test] -fn a_hex_escape_takes_at_most_four_digits() { - // REGRESSION. `'x' [0-9a-fA-F]+` consumed an unbounded run, so `'\x12345'` — five - // digits, not valid C# — lexed as one clean character literal. ECMA-334 allows one to - // four. - assert!( - !common::analyze("class C { static char F() => '\\x12345'; }") - .diagnostics - .is_empty(), - "five hex digits must be reported" - ); - // All four legal widths still lex. - for escape in ["\\x1", "\\x12", "\\x123", "\\x1234"] { - assert_eq!( - lloc(&format!("class C {{ static char F() => '{escape}'; }}")), - 2.0, - "`{escape}` must lex" - ); - } -} - -#[test] -fn an_integer_suffix_takes_at_most_one_marker_of_each_kind() { - // REGRESSION. Two independent `[uUlL]?` slots accepted combinations C# rejects — `1uu`, - // `1LL`, `1uU` all lexed as ordinary integer literals, so invalid source reported a - // clean parse. `IntSuffix` now enumerates the legal pairs: at most one unsigned marker - // and one long marker, in either order. - for bad in ["1uu", "1UU", "1ll", "1LL", "1uU", "1Ll"] { - assert!( - !common::analyze(&format!("class C {{ static object F() => {bad}; }}")) - .diagnostics - .is_empty(), - "`{bad}` is not a legal suffix combination" - ); - } - // Every legal combination, across all three integer bases. - for good in [ - "1u", "1U", "1l", "1L", "1ul", "1uL", "1Ul", "1UL", "1lu", "1lU", "1Lu", "1LU", "0x1u", - "0x1UL", "0b1ul", - ] { - assert_eq!( - lloc(&format!("class C {{ static object F() => {good}; }}")), - 2.0, - "`{good}` must lex" - ); - } -} - -#[test] -fn a_width_two_hole_close_consumes_both_braces() { - // REGRESSION. The hole close lives in the *default* mode, shared by every interpolation - // flavour, and matched one `}`. A hole opened with `{{` therefore left its second brace - // to be re-lexed in the width-two mode, which called it literal text — one phantom - // Halstead operand that the equivalent one-dollar spelling does not have. - // - // A `wideStack` parallel to `holeStack` records each open hole's brace width, so the - // doubled close is gated on it. That gate is load-bearing: a first attempt matched `}}` - // whenever a hole was open, which broke `$"{v}}}"` — a width-one close followed by an - // escaped brace — by taking both braces as the close. - let vocab = |source: &str| { - let a = analyze_clean(source); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - h.n1 + h.n2 - }; - assert_eq!( - vocab("class C { static string F(int v) => $$\"\"\"{{v}}\"\"\"; }"), - vocab("class C { static string F(int v) => $\"\"\"{v}\"\"\"; }"), - "the two hole widths must cost the same" - ); - - // The cases the gate protects, all of which must stay clean: - for source in [ - // width-one close plus an escaped brace - "class C { static string F(int v) => $\"{v}}}\"; }", - // a genuinely literal brace at width two - "class C { static string F() => $$\"\"\"a}b\"\"\"; }", - // nesting: the inner hole's width must not clobber the outer one's - "class C { static string F(int v) => $$\"\"\"{{ $\"{v}\" }}\"\"\"; }", - // and a format clause, whose close pops the same stacks - "class C { static string F(int v) => $$\"\"\"{{v:D4}}\"\"\"; }", - ] { - assert_eq!(lloc(source), 2.0, "{source}"); - } -} - -#[test] -fn a_width_two_format_clause_also_consumes_both_braces() { - // REGRESSION, and a gap in my own previous fix: the doubled hole close was added, but - // the *format-clause* close path was left consuming one brace. So - // `$$"""{{n:D4}}"""` still leaked its second `}` as literal text — one phantom Halstead - // operand that `$"""{n:D4}"""` does not have. - let vocab = |source: &str| { - let a = analyze_clean(source); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - h.n1 + h.n2 - }; - assert_eq!( - vocab("class C { static string F(int n) => $$\"\"\"{{n:D4}}\"\"\"; }"), - vocab("class C { static string F(int n) => $\"\"\"{n:D4}\"\"\"; }"), - "a format clause must cost the same at both hole widths" - ); - // And an alignment clause, which shares the same close path. - assert_eq!( - lloc("class C { static string F(int n) => $$\"\"\"{{n,5}}\"\"\"; }"), - 2.0 - ); -} - -#[test] -fn a_digit_separator_may_not_be_trailing() { - // REGRESSION. `[0-9_]*` let a literal end in a separator, so `1_` — not valid C# — - // lexed as an ordinary integer literal and the analyzer reported a clean parse. - for bad in ["1_", "0x1F_", "0b10_"] { - assert!( - !common::analyze(&format!("class C {{ static object F() => {bad}; }}")) - .diagnostics - .is_empty(), - "`{bad}` ends in a separator, which C# does not allow" - ); - } - - // What must keep working. Separators BETWEEN digits are legal, and C# 7.2 allows runs - // of them (`1___0` compiles), so the fix is `( '_'* [0-9] )*` rather than `'_'?`. - for good in [ - "1_000", - "1__0", - "1___0", - "0x1_F", - "0b1010_1010", - "1_000L", - "0x1_Fu", - ] { - assert_eq!( - lloc(&format!("class C {{ static object F() => {good}; }}")), - 2.0, - "`{good}` is a legal literal" - ); - } - - // A LEADING separator is not a literal at all — `_1` is a legal identifier, and - // narrowing the literal rule must not steal it. - // class(1) + method(1) + declaration(1) + return(1) = 4. - assert_eq!( - lloc("class C { static int F() { int _1 = 5; return _1; } }"), - 4.0 - ); -} - -#[test] -fn a_regular_interpolated_string_cannot_span_rows() { - // REGRESSION. `INTERPOLATED_TEXT`'s negated set excluded only braces, quotes, and the - // backslash, so a physical newline was absorbed as text: `$"ab"` was a clean parse - // where the plain `"ab"` is correctly rejected. A regular interpolated string - // follows ordinary string-literal rules. - for terminator in ['\n', '\r', '\u{85}', '\u{2028}', '\u{2029}'] { - let source = format!("class C {{ static string F() => $\"a{terminator}b\"; }}"); - assert!( - !common::analyze(&source).diagnostics.is_empty(), - "U+{:04X} must not be absorbed into a regular interpolated string", - terminator as u32 - ); - } - - // The verbatim and raw flavours ARE multi-line, which is what distinguishes them — - // narrowing the regular mode must not touch either. - assert_eq!(lloc("class C { static string F() => $@\"a\nb\"; }"), 2.0); - assert_eq!( - lloc("class C { static string F() => $\"\"\"\na\nb\n\"\"\"; }"), - 2.0 - ); -} diff --git a/crates/mehen-csharp/tests/loc.rs b/crates/mehen-csharp/tests/loc.rs deleted file mode 100644 index 0acf99be..00000000 --- a/crates/mehen-csharp/tests/loc.rs +++ /dev/null @@ -1,485 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC-family tests for the ANTLR C# walker. -//! -//! - `sloc`: every physical line in the span. -//! - `ploc`: lines carrying a code token. -//! - `lloc`: statement- and declaration-shaped rules. -//! - `cloc`: comment lines, recovered from the hidden channel (comments never -//! appear in the parse tree). -//! - `blank`: `sloc - ploc - comment-only`. - -mod common; - -use common::analyze_clean; -use mehen_report::metrics_json; - -fn loc(source: &str) -> metrics_json::Loc { - metrics_json::loc(&analyze_clean(source).root.metrics) -} - -#[test] -fn counts_physical_code_and_blank_lines() { - let a = loc("class C - { - void F() - { - int x = 1; - - x = 2; - } - }"); - assert_eq!(a.sloc, 9.0); - assert_eq!(a.ploc, 8.0); - assert_eq!(a.blank, 1.0); -} - -#[test] -fn line_comments_are_cloc_not_ploc() { - // Comments are hidden-channel: they reach LOC only through the - // post-walk comment pass. - let a = loc("// leading - class C - { - // inside - void F() { } - }"); - assert_eq!(a.cloc, 2.0); -} - -#[test] -fn xml_doc_comments_count_as_comments() { - // `///` is a distinct token type (`SINGLE_LINE_DOC_COMMENT`) from `//`, so - // this pins that the analyzer routes all five C# comment token types. - let a = loc("///

Doc. - class C { }"); - assert_eq!(a.cloc, 1.0); -} - -#[test] -fn block_and_delimited_doc_comments_count_every_row() { - let a = loc("/** doc - * continues - */ - class C { }"); - assert_eq!(a.cloc, 3.0); -} - -#[test] -fn a_trailing_comment_shares_its_line_with_code() { - // The line is both code and comment: it counts in ploc AND cloc, and is - // NOT blank. - let a = loc("class C { void F() { } } // trailing"); - assert_eq!(a.sloc, 1.0); - assert_eq!(a.ploc, 1.0); - assert_eq!(a.cloc, 1.0); - assert_eq!(a.blank, 0.0); -} - -#[test] -fn lloc_counts_statements_and_declarations() { - // class(1) + method(1) + 3 statements = 5 - let a = loc("class C - { - void F() - { - int x = 1; - x = 2; - return; - } - }"); - assert_eq!(a.lloc, 5.0); -} - -#[test] -fn a_bare_block_is_not_its_own_logical_line() { - // The `{ }` wrapper adds nothing; only the inner statement counts: - // class(1) + method(1) + inner statement(1) = 3. - let a = loc("class C - { - void F() - { - { int x = 1; } - } - }"); - assert_eq!(a.lloc, 3.0); -} - -#[test] -fn an_empty_statement_is_not_a_logical_line() { - // class(1) + method(1) = 2; the bare `;` adds nothing. - let a = loc("class C - { - void F() { ; } - }"); - assert_eq!(a.lloc, 2.0); -} - -#[test] -fn a_for_header_declaration_is_one_logical_line() { - // The initializer declaration is part of the `for` statement's single - // header line, not a second logical line: - // class(1) + method(1) + for(1) + body statement(1) = 4. - let a = loc("class C - { - void F() - { - for (int i = 0; i < 3; i++) { int x = i; } - } - }"); - assert_eq!(a.lloc, 4.0); -} - -#[test] -fn an_expression_bodied_method_is_one_logical_line() { - // `int F() => 1;` is a single declaration — the `=>` body must NOT add a - // second logical line on top of the declaration itself. - // class(1) + method(1) = 2. - let a = loc("class C - { - int F() => 1; - }"); - assert_eq!(a.lloc, 2.0); -} - -#[test] -fn an_expression_bodied_accessor_counts_its_body() { - // An accessor opens its own space; `get => _x;` has no statement in it, so - // the body counts as that space's one logical line. - // class(1) + field(1) + property(1) + accessor body(1) = 4. - let a = loc("class C - { - private int _x; - public int X { get => _x; } - }"); - assert_eq!(a.lloc, 4.0); -} - -#[test] -fn an_expression_bodied_lambda_counts_one_line() { - // A lambda opens a closure space; `x => x + 1` has no statement, so the - // lambda itself is that space's one logical line. - // class(1) + method(1) + local declaration(1) + lambda(1) = 4. - let a = loc("class C - { - void F() - { - System.Func f = x => x + 1; - } - }"); - assert_eq!(a.lloc, 4.0); -} - -#[test] -fn usings_and_namespace_are_logical_lines() { - // using(1) + namespace(1) + class(1) = 3 - let a = loc("using System; - namespace N - { - class C { } - }"); - assert_eq!(a.lloc, 3.0); -} - -#[test] -fn a_verbatim_string_spanning_lines_marks_every_row_as_code() { - // A multi-line verbatim string is ONE token covering several rows; every - // row must be code, or the interior rows are reported as phantom blanks. - let a = loc("class C - { - string S = @\"one - two - three\"; - }"); - assert_eq!(a.sloc, 6.0); - assert_eq!(a.blank, 0.0, "interior string rows must not read as blank"); -} - -#[test] -fn preprocessor_directives_are_not_comments_and_not_logical_lines() { - // mehen does **not** evaluate `#if`: directives are routed to their own - // channel, so they are neither code nor comment for LOC, and an inactive - // region is still parsed as ordinary code. - // - // That is a deliberate trade. Evaluating `#if` means choosing a symbol set, - // and metrics for one configuration's subset of the file is less useful than - // approximate metrics for all of it — a member excluded in *this* build is - // still code someone maintains. (The previous grammars-v4 lexer evaluated - // directives via a stateful hook and handed the inactive branch over as a - // single hidden `SKIPPED_SECTION` token; this grammar has no such hook.) - let a = loc("class C - { - #if NEVER - void Excluded() { } - #endif - void Kept() { } - }"); - assert_eq!(a.cloc, 0.0, "a directive is not a comment"); - // class(1) + Excluded(1) + Kept(1) = 3 — the `#if`/`#endif` rows themselves - // are not logical lines. - assert_eq!( - a.lloc, 3.0, - "an inactive region is parsed as code, so its member counts" - ); - // A directive row IS a physical code line, though. It carries source text, so - // it must not fall through to `blank = sloc - ploc - only_comment`. - assert_eq!(a.sloc, 7.0); - assert_eq!( - a.ploc, 7.0, - "every row carries a token, directives included" - ); - assert_eq!(a.blank, 0.0, "a directive row is not blank"); -} - -#[test] -fn a_directive_row_is_code_not_blank() { - // REGRESSION. PLOC is recorded during the tree walk, which cannot see a - // directive — it goes to its own channel, so it never reaches the parser as a - // terminal. The row therefore carried no PLOC observation and was reported as a - // *blank line*, which it plainly is not. Directives are now routed through the - // same post-walk pass that handles comments. - let a = loc("class C - { - #define FOO - void M() { } - }"); - assert_eq!(a.sloc, 5.0); - assert_eq!(a.ploc, 5.0); - assert_eq!(a.blank, 0.0); - assert_eq!(a.cloc, 0.0); -} - -#[test] -fn a_real_blank_line_is_still_blank() { - // The counterpart: routing directives into PLOC must not make every row code. - let a = loc("class C - { - - void M() { } - }"); - assert_eq!(a.sloc, 5.0); - assert_eq!(a.ploc, 4.0); - assert_eq!(a.blank, 1.0); -} - -#[test] -fn a_trailing_comment_on_a_directive_still_counts_as_cloc() { - // REGRESSION. `DIRECTIVE_LINE` was `'#' ~[\r\n]*`, which swallowed the whole row — - // so `#if DEBUG // explain why` recorded no CLOC at all. The negated set now - // excludes `/` so the token stops before a comment. - let a = loc("class C { - #if DEBUG // explain why - void M() { } - #endif - }"); - assert_eq!(a.cloc, 1.0); -} - -#[test] -fn a_directive_without_a_comment_records_no_cloc() { - let a = loc("class C { - #if DEBUG - void M() { } - #endif - }"); - assert_eq!(a.cloc, 0.0); -} - -#[test] -fn a_slash_inside_a_directive_does_not_split_it() { - // The second alternative requires the char after `/` not to start a comment, so a - // path-like `#line` directive stays one token while `#pragma … // note` splits. - let path = loc("class C { - #line 1 \"a/b.cs\" - void M() { } - }"); - assert_eq!(path.cloc, 0.0, "a `/` in a path is not a comment"); - let pragma = loc("class C { - #pragma warning disable CA1024 // note - void M() { } - }"); - assert_eq!(pragma.cloc, 1.0); -} - -#[test] -fn a_label_is_not_its_own_logical_line() { - // REGRESSION. `labeled_statement` is a wrapper: it recorded a logical line and the - // nested `return_statement` recorded another, so adding a label turned one statement - // into two even on the same source row. A label is an attribute of the statement it - // labels — `mehen-java` omits the equivalent wrapper for the same reason. - let labeled = loc("class C - { - static void M() { start: return; } - }"); - let plain = loc("class C - { - static void M() { return; } - }"); - assert_eq!(labeled.lloc, plain.lloc); - // class(1) + method(1) + return(1) = 3. - assert_eq!(labeled.lloc, 3.0); -} - -#[test] -fn a_block_comment_counts_every_row_whatever_the_terminator() { - // REGRESSION from this PR's own terminator work: the lexer accepts all five C# line - // terminators, but `loc_tokens` counted only `\n` when finding a delimited - // comment's end row — so `/* ab */` reported one CLOC row instead of two. - for terminator in ['\n', '\r', '\u{85}', '\u{2028}', '\u{2029}'] { - let source = format!("/* a{terminator}b */\nclass C {{ }}"); - let a = loc(&source); - assert_eq!( - a.cloc, 2.0, - "U+{:04X} must split the comment across two CLOC rows", - terminator as u32 - ); - } -} - -#[test] -fn crlf_does_not_double_count_a_comment_row() { - // CRLF is one break, so `/* a\r\nb */` is two rows, not three — matching - // `LineIndex`, which skips the `\n` after a `\r`. - let a = loc("/* a\r\nb */\nclass C { }"); - assert_eq!(a.cloc, 2.0); -} - -#[test] -fn a_comment_after_a_unicode_terminator_lands_on_its_own_row() { - // REGRESSION. `loc_tokens` took each token's start row from `tok.line()`, which the - // *runtime's* lexer advances on `\n` alone — so after any other terminator a comment - // was routed onto the preceding code row, and its real row fell out as a phantom - // blank. The row now comes from the shared `LineIndex`. - for terminator in ['\n', '\r', '\u{85}', '\u{2028}', '\u{2029}'] { - let source = format!("class C {{ }}{terminator}// note"); - let a = loc(&source); - assert_eq!(a.cloc, 1.0, "U+{:04X}: one comment row", terminator as u32); - assert_eq!( - a.blank, 0.0, - "U+{:04X}: the comment row must not read as blank", - terminator as u32 - ); - } -} - -#[test] -fn a_directive_payload_may_end_with_a_slash() { - // REGRESSION introduced by the trailing-comment fix: excluding `/` from the negated - // set meant neither repetition alternative could take a *final* slash, so - // `#region generated/` stopped the token short and the slash surfaced as a visible - // SLASH token — a syntax error on valid source. - // - // The fix requires a line terminator or EOF after that slash. A bare `'/'?` was the - // first attempt and broke the case above: it matched the first `/` of a trailing - // `//` comment and cost the row its CLOC. - let a = loc("#region generated/ - class C { } - #endregion"); - assert_eq!(a.cloc, 0.0, "a directive is not a comment"); - let b = loc("class C - { - #warning path/ - }"); - assert_eq!(b.cloc, 0.0); -} - -#[test] -fn a_comment_marker_inside_a_directive_string_is_string_content() { - // REGRESSION. Roslyn's `line_directive_trivia` / `load_directive_trivia` both accept - // a `string_literal_token`, so `//` and `/*` between those quotes are string - // *content* — but the trailing-comment split above is character-level and stopped at - // the first `/`. `//` therefore left the rest of the row to SINGLE_LINE_COMMENT and - // invented a comment on a row that has none. - for source in [ - "#line 1 \"https://host/a.cs\"\nclass C { }", - "#load \"https://host/a.csx\"\nclass C { }", - ] { - assert_eq!( - loc(source).cloc, - 0.0, - "a `//` inside the directive's string is not a comment: {source}" - ); - } - - // `/*` was worse than a miscount: DELIMITED_COMMENT ran to the next `*/`, so the - // tail of the path came back as *visible* tokens. `loc` asserts a clean parse, so - // reaching the assertion at all is the substance of this case. - assert_eq!(loc("#line 1 \"c:/a/*b*/c.cs\"\nclass C { }").cloc, 0.0); -} - -#[test] -fn an_unpaired_quote_in_a_directive_still_ends_at_the_row() { - // The quote-aware alternative overlaps the plain single-character one, so an - // unclosed quote cannot complete the atom and falls through — consuming the rest of - // the row and no more. ANTLR maximizes the match for the rule as a whole rather than - // committing to the first viable alternative, which is what lets one rule serve both - // cases without a predicate. - // - // Two rows of code after the directive: if the atom had swallowed the newline, the - // class and its method would be inside the directive token and LLOC would drop. - assert_eq!( - loc("#error say \"hi - class C - { - void M() { } - }") - .lloc, - 2.0 - ); -} - -#[test] -fn a_trailing_comment_after_a_directive_string_still_counts() { - // The counterpart to the two cases above: making the scan quote-aware must not cost - // a *real* trailing comment its CLOC, and a `"` inside that comment must not start - // an atom that eats the row's end. - assert_eq!(loc("#line 1 \"a.cs\" // note\nclass C { }").cloc, 1.0); - assert_eq!(loc("#if A // say \"hi\nclass C { }\n#endif").cloc, 1.0); -} - -#[test] -fn an_extension_block_contributes_a_logical_line() { - // REGRESSION. An `extension(T x) { … }` block opens a class-like space, so it must - // record the logical line every other type-like declaration does — it was missing - // from the LLOC allowlist, so an extension holding one method reported 1 where the - // analogous `class Inner { … }` container reports 2. - // - // Asserted against the class control rather than an absolute, since the two - // spellings must be indistinguishable here. - let extension = loc("static class E - { - extension(string s) - { - public int L() { return s.Length; } - } - }"); - let control = loc("static class E - { - class Inner - { - public int L() { return 1; } - } - }"); - assert_eq!(extension.lloc, control.lloc); - // outer class + container + method + return = 4. - assert_eq!(extension.lloc, 4.0); -} - -#[test] -fn a_generic_local_declaration_is_one_logical_line() { - // REGRESSION (#218). While `List l = new();` parsed as a chained - // comparison expression (see the same-named fix in `abc.rs`), its logical-line - // count could drift from the equivalent declarations'. LLOC must not depend on - // which of the three spellings declares the local: class(1) + method(1) + - // declaration(1) = 3 for each. - for source in [ - "class C { static void F() { System.Collections.Generic.List l = new(); } }", - "class C { static void F() { var l = new System.Collections.Generic.List(); } }", - "class C { static void F() { int l = 1; } }", - // And without an initializer — the misparse was independent of the `= …`. - "class C { static void F() { System.Collections.Generic.List l; } }", - ] { - assert_eq!(loc(source).lloc, 3.0, "one declaration line: {source}"); - } -} diff --git a/crates/mehen-csharp/tests/structure.rs b/crates/mehen-csharp/tests/structure.rs deleted file mode 100644 index b91ac179..00000000 --- a/crates/mehen-csharp/tests/structure.rs +++ /dev/null @@ -1,688 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Space-structure tests for the ANTLR C# walker: which constructs open a -//! metric space, what kind it is, and what it is named. -//! -//! These pin the shape of the reported tree, which every per-space metric -//! (NOM, NArgs, WMC, per-space LOC) depends on. - -mod common; - -use common::{analyze, analyze_clean}; -use mehen_core::{MetricSpace, SpaceKind}; - -/// Flatten the space tree into `(depth, kind, name)` triples in tree order. -fn shape(root: &MetricSpace) -> Vec<(usize, String, Option)> { - fn walk(s: &MetricSpace, depth: usize, out: &mut Vec<(usize, String, Option)>) { - out.push((depth, s.kind.as_str().to_string(), s.name.clone())); - for c in &s.spaces { - walk(c, depth + 1, out); - } - } - let mut out = Vec::new(); - walk(root, 0, &mut out); - out -} - -#[test] -fn type_kinds_map_to_space_kinds() { - let a = analyze_clean( - "class K { } - struct S { } - interface I { } - enum E { A }", - ); - let kinds: Vec<_> = shape(&a.root) - .into_iter() - .skip(1) // the unit - .map(|(_, kind, name)| (kind, name)) - .collect(); - assert_eq!( - kinds, - vec![ - ("class".to_string(), Some("K".to_string())), - // A `struct` is a class-like container (it carries WMC/NPA/NPM the - // same way a class does). - ("class".to_string(), Some("S".to_string())), - ("interface".to_string(), Some("I".to_string())), - ("enum".to_string(), Some("E".to_string())), - ] - ); -} - -#[test] -fn every_method_shape_opens_a_named_function_space() { - let a = analyze_clean( - "class C { - public C() { } - ~C() { } - void M() { } - public static C operator +(C a, C b) { return a; } - }", - ); - let names: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - assert_eq!( - names, - vec![ - Some("C".to_string()), // constructor - Some("C".to_string()), // destructor (`~C`) - Some("M".to_string()), // method - Some("operator +".to_string()), - ] - ); -} - -#[test] -fn both_property_accessors_are_sibling_spaces() { - // The grammar nests the SECOND accessor inside the first's rule, but they - // are siblings — and each must be named after its owning property. - let a = analyze_clean( - "class C { - public int Count { get; set; } - }", - ); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(depth, _, name)| (depth, name)) - .collect(); - assert_eq!( - functions, - vec![ - (2, Some("Count.get".to_string())), - (2, Some("Count.set".to_string())), - ], - "accessors must be siblings at the same depth, each named after the property" - ); -} - -#[test] -fn event_accessors_are_sibling_spaces() { - let a = analyze_clean( - "class C { - public event System.EventHandler E { add { } remove { } } - }", - ); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(depth, _, name)| (depth, name)) - .collect(); - assert_eq!( - functions, - vec![ - (2, Some("E.add".to_string())), - (2, Some("E.remove".to_string())), - ] - ); -} - -#[test] -fn expression_bodied_property_opens_one_accessor() { - // `int P => 1;` has no accessor list at all — the property itself is the - // getter, so exactly one function space opens. - let a = analyze_clean( - "class C { - public int P => 1; - }", - ); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - // Exactly one getter, named as the block form would be — two properties that - // are semantically the same getter must not report different NOM / NArgs / - // WMC just because one uses `=> …` and the other `{ get { … } }`. - assert_eq!(functions, vec![Some("P.get".to_string())]); -} - -#[test] -fn lambda_and_anonymous_method_are_closures() { - let a = analyze_clean( - "class C { - void F() { - System.Func a = x => x + 1; - System.Func b = delegate(int x) { return x; }; - } - }", - ); - let closures = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "closure") - .count(); - assert_eq!(closures, 2); -} - -#[test] -fn local_function_is_a_named_nested_function() { - // A local function's name lives on its nested `local_function_header`, so - // this pins that the walker reaches through it. - let a = analyze_clean( - "class C { - void Outer() { - int Inner(int x) => x * 2; - } - }", - ); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(depth, _, name)| (depth, name)) - .collect(); - assert_eq!( - functions, - vec![ - (2, Some("Outer".to_string())), - (3, Some("Inner".to_string())), - ] - ); -} - -#[test] -fn interface_members_open_spaces_under_the_interface() { - let a = analyze_clean( - "interface I { - double Area { get; } - void Scale(double f); - }", - ); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - assert_eq!( - functions, - vec![Some("Area.get".to_string()), Some("Scale".to_string())] - ); -} - -#[test] -fn namespace_does_not_open_a_space_but_its_types_do() { - // A namespace is not a metric space (it carries no complexity of its own); - // the types inside it attach directly to the unit. - let a = analyze_clean( - "namespace N - { - class C { } - }", - ); - assert_eq!(a.root.kind, SpaceKind::Unit); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("C")); -} - -#[test] -fn nested_types_nest_their_spaces() { - let a = analyze_clean( - "class Outer { - class Inner { - void M() { } - } - }", - ); - assert_eq!( - shape(&a.root), - vec![ - (0, "unit".to_string(), None), - (1, "class".to_string(), Some("Outer".to_string())), - (2, "class".to_string(), Some("Inner".to_string())), - (3, "function".to_string(), Some("M".to_string())), - ] - ); -} - -#[test] -fn an_extension_block_is_its_own_container() { - // A C# 14 `extension(T x) { … }` block holds `member_declaration*` exactly as a - // class body does, so it must open its own space — otherwise its members attach - // to the enclosing static class and report as that class's own methods. - // Anonymous, since the block declares no name. - let a = analyze_clean( - "static class E { - extension(string s) { - public int Length => s.Length; - } - }", - ); - assert_eq!( - shape(&a.root), - vec![ - (0, "unit".to_string(), None), - (1, "class".to_string(), Some("E".to_string())), - (2, "class".to_string(), None), - (3, "function".to_string(), Some("Length.get".to_string())), - ] - ); -} - -#[test] -fn an_extension_block_holding_a_method_is_not_a_constructor() { - // REGRESSION, and the third instance of the contextual-keyword ordering hazard - // (`record`, `union`, now `extension`) — but the worst of them, because the - // collision is with `constructor_declaration`: - // - // constructor_declaration - // : attribute_list* modifier* identifier_token parameter_list … block - // - // is exactly the shape of `extension(string s) { … }`, and `member_declaration` - // lists `base_method_declaration` before `base_type_declaration`. So the block - // parsed as a *constructor named `extension`* holding its members as local - // functions — with zero diagnostics and metrics identical to the `E(string s)` - // constructor spelling. - // - // `an_extension_block_is_its_own_container` above did not catch it: it uses a - // *property* member, and a property is not a legal statement, so the constructor - // path dies there and ANTLR falls back to the type path. A method member IS a - // legal statement (`local_function_statement` takes `modifier*`), so the - // constructor path stayed viable end to end. Hence the assertion here is against - // the `class` control rather than a literal shape — an extension container must - // be indistinguishable from any other type container. - let extension = analyze_clean( - "static class E { - extension(string s) { - public int L() { return s.Length; } - } - }", - ); - let control = analyze_clean( - "static class E { - class Inner { - public int L() { return 1; } - } - }", - ); - // Only the container's own name differs — an extension block declares none. - let anonymize = |root: &MetricSpace| { - shape(root) - .into_iter() - .map(|(depth, kind, name)| (depth, kind, if depth == 2 { None } else { name })) - .collect::>() - }; - assert_eq!(anonymize(&extension.root), anonymize(&control.root)); - // Spelled out, so a shape change in both at once cannot pass silently. - assert_eq!( - anonymize(&extension.root), - vec![ - (0, "unit".to_string(), None), - (1, "class".to_string(), Some("E".to_string())), - (2, "class".to_string(), None), - (3, "function".to_string(), Some("L".to_string())), - ] - ); -} - -#[test] -fn the_hoists_residual_trade_is_a_ctor_in_a_type_named_for_the_keyword() { - // The inverse collision, pinned deliberately rather than left to be rediscovered. - // Hoisting settles an ambiguity by alternative ORDER, so whichever order is chosen, - // one of the two shapes loses — and the loser is documented here. - // - // For `extension` it is an initializer-less constructor in a type *named* - // `extension`: `class extension { extension() { } }` reads as an extension block, so - // the constructor is reported as an anonymous nested container. Irreducible without - // semantics — the body cannot disambiguate either, since `int x = 1;` is both a - // statement and a field declaration. - // - // A *second* collision was found and fixed rather than traded: because every element - // after `KW_EXTENSION` was optional upstream, the bare keyword was a complete - // extension block — so `class C { extension M() { … } }` grew a phantom empty - // extension space beside the method. Requiring the body (EXTENSION_BODY_REQUIRED in - // the prep) removes it, and is what makes the return-type case below pass. - // - // Two things bound what remains, both measured: - let anon_container = vec![ - (0, "unit".to_string(), None), - (1, "class".to_string(), Some("extension".to_string())), - (2, "class".to_string(), None), - ]; - assert_eq!( - shape(&analyze_clean("class extension { extension() { } }").root), - anon_container - ); - - // 1. A constructor *initializer* is a token an extension block cannot accept, so the - // common real-world constructor spelling escapes the trade entirely. - let with_initializer = - analyze_clean("class extension { extension() : this(1) { } extension(int x) { } }"); - let functions: Vec<_> = shape(&with_initializer.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .collect(); - assert_eq!( - functions.len(), - 1, - "`: this(…)` disambiguates — the delegating ctor is a function again" - ); - - // 2. The trade does NOT extend to any other position — field, parameter, local, - // return type, property type, or type argument. Only the constructor shape - // collides, because only it is `name (params) { … }`. Each is pinned against the - // same source with an ordinary type name, which must produce an identical tree. - // - // The return-type and property-type rows are the ones the body fix bought: while - // the bare keyword was a complete extension block, both grew a phantom empty - // extension space. `record` and `union` still lose both (a method or property - // typed `record` becomes a *class*), and cannot be fixed the same way — their - // bodies must stay optional, since `record R;` and `record R(int X);` are valid - // C# while `extension;` is not. - for template in [ - "class C { NAME f; }", - "class C { void M(NAME p) { } }", - "class C { void M() { NAME v = null; } }", - "class C { NAME M() { return null; } }", - "class C { NAME P { get; set; } }", - "class C { System.Collections.Generic.List f; }", - ] { - let keyword = analyze_clean(&template.replace("NAME", "extension")); - let control = analyze_clean(&template.replace("NAME", "Foo")); - assert_eq!( - shape(&keyword.root), - shape(&control.root), - "`extension` as an ordinary type name behaves like any other: {template}" - ); - } -} - -#[test] -fn extension_is_still_a_legal_identifier() { - // Hoisting `type_declaration` must not make the word reserved — `extension` is a - // contextual keyword, so it stays usable as an ordinary name. - let a = analyze_clean("class C { void M() { int extension = 1; var x = extension; } }"); - assert_eq!(a.root.spaces[0].spaces.len(), 1); -} - -#[test] -fn a_positional_record_is_a_type_not_a_method() { - // REGRESSION, and the most consequential silent misparse yet: `record R(int X);` - // — the single most common record spelling — parsed as a *method* named `R` - // returning a type called `record`, because `record` is a contextual keyword and - // `member_declaration` tries `base_method_declaration` before the type forms. - // The record was reported as a function space with no NPA/NPM/WMC container, with - // zero diagnostics. Only `record class R { }` parsed correctly, which is how it - // survived: the explicit-kind form cannot match `method_declaration`. - for source in [ - "record R(int X);", - "record R(int X) { }", - "record class R { }", - "record struct R(int X);", - ] { - let a = analyze_clean(source); - assert_eq!( - a.root.spaces[0].kind, - SpaceKind::Class, - "`{source}` must open a type space" - ); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("R")); - } -} - -#[test] -fn record_is_still_a_legal_identifier() { - // Minting a real `KW_RECORD` token must not make `record` reserved: it is - // contextual, so it is widened back into `identifier_token` and remains usable as - // an ordinary name. - let a = analyze_clean( - "class C { - void M() { int record = 1; var x = record; } - }", - ); - assert_eq!(a.root.spaces[0].spaces.len(), 1); -} - -#[test] -fn a_property_with_both_accessors_is_not_a_record() { - // The `record` fix needed a real token precisely because reordering alone put the - // record path on the *committed* path here: `T P { get => …; set { … } }` predicted - // `record_keyword` = `T`, and a predicate cannot prune a committed path — it - // surfaced as a hard error on 29 corpus files. Pinned as a parse-clean assertion - // plus the accessor shape. - let a = analyze_clean("struct S { public T P { readonly get => 1; set { } } }"); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - assert_eq!( - functions, - vec![Some("P.get".to_string()), Some("P.set".to_string())] - ); -} - -#[test] -fn a_primary_constructor_is_a_function_space() { - // A primary constructor's parameters live on the *type* declaration and no - // `constructor_declaration` node exists anywhere, so `class C(int x)` reported - // NOM 0 / NArgs 0 where the identical explicit form reported 1 / 1. Pinned - // against the explicit form, since the point is the equivalence. - let primary = analyze_clean("class C(int x) { }"); - let explicit = analyze_clean("class C { public C(int x) { } }"); - let names = |a: &mehen_core::LanguageAnalysis| { - shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect::>() - }; - assert_eq!(names(&primary), vec![Some("C".to_string())]); - assert_eq!(names(&primary), names(&explicit)); -} - -#[test] -fn an_extension_receiver_is_not_a_primary_constructor() { - // `extension(string s)` carries the same `parameter_list?` a primary constructor - // does, but it is the extension *receiver*: nothing is constructed, and the block - // has no name. Only the member inside it is a function. - let a = analyze_clean( - "static class E { - extension(string s) { public int Length => s.Length; } - }", - ); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - assert_eq!(functions, vec![Some("Length.get".to_string())]); -} - -#[test] -fn conversion_operators_are_named_by_their_target_type() { - // REGRESSION. A conversion operator's name is its target type, which is a rule - // child rather than a token — the code returned a bare `"operator"` while the - // comment above it said otherwise. A type declaring several conversions reported - // them all identically, indistinguishable in per-function output. - let a = analyze_clean( - "class C { - public static implicit operator int(C c) => 0; - public static explicit operator string(C c) => null; - }", - ); - let names: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - assert_eq!( - names, - vec![ - Some("operator int".to_string()), - Some("operator string".to_string()), - ] - ); -} - -#[test] -fn a_union_declaration_opens_a_type_space() { - // REGRESSION, and the same shape as the `record` misparse: `union` is only a - // contextual keyword, so it is widened back into `identifier_token` and - // `union Result { }` matched `method_declaration` with `union` as the return type. - // It differs from `record` in one detail — a union *with members* forces the type - // path, because a member body cannot follow a method signature — which is why only - // the empty form mis-parsed and why this survived longer. - let empty = analyze_clean("union Result { }"); - assert_eq!(empty.root.spaces[0].kind, SpaceKind::Class); - assert_eq!(empty.root.spaces[0].name.as_deref(), Some("Result")); - - // With members it must match the `struct` control exactly. - let union = analyze_clean("union Result { public int A; public void M() { } }"); - let structure = analyze_clean("struct Result { public int A; public void M() { } }"); - assert_eq!(shape(&union.root), shape(&structure.root)); -} - -#[test] -fn union_is_still_a_legal_identifier() { - // Hoisting `union_declaration` must not make the word reserved. - let a = analyze_clean("class C { void M() { int union = 1; var x = union; } }"); - assert_eq!(a.root.spaces[0].spaces.len(), 1); -} - -#[test] -fn a_delegate_does_not_get_a_synthetic_constructor() { - // REGRESSION. `delegate int D(int x);` carries a `parameter_list` because that IS - // its signature, but the primary-constructor path matched on "has a parameter list" - // and fabricated a function named `D` — inflating NOM/NArgs and rolling a phantom - // method into the delegate's WMC, which is meant to be a childless space. - let a = analyze_clean("delegate int D(int x);"); - assert_eq!( - shape(&a.root), - vec![ - (0, "unit".to_string(), None), - (1, "class".to_string(), Some("D".to_string())), - ], - "a delegate opens a childless type space" - ); -} - -#[test] -fn every_primary_constructor_form_still_opens_one() { - // The allowlist must not drop a form that genuinely supports a primary constructor. - for source in [ - "class C(int x) { }", - "struct C(int x) { }", - "record C(int X);", - ] { - let a = analyze_clean(source); - let functions: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - assert_eq!( - functions, - vec![Some("C".to_string())], - "`{source}` must open one constructor space" - ); - } -} - -#[test] -fn an_interface_does_not_take_a_primary_constructor() { - // REGRESSION. `interface I(int x) { }` is not valid C# — primary constructors are - // for `class`, `struct`, and `record` — but Roslyn's permissive grammar accepts the - // optional parameter list without a diagnostic, so listing `interface` in the - // allowlist minted a constructor space for invalid source. - let a = analyze("interface I(int x) { }"); - let functions = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .count(); - assert_eq!(functions, 0, "no constructor for an invalid declaration"); -} - -#[test] -fn a_var_pattern_is_not_a_constant_pattern() { - // REGRESSION, and another silent misparse: `var x` in pattern position parsed as a - // **constant pattern**, so `var_pattern` was unreachable. Two alternatives had to be - // cleared, and the second was the surprise — - // - // - `constant_pattern : expression` is a catch-all listed *second* in `pattern`, and - // hub inlining folds the whole expression cycle into one rule (including - // `declaration_expression`), so `var x` is a viable "expression"; - // - `declaration_pattern : type variable_designation` would take it next anyway, - // because `var` is contextual and hence a viable `type`. - // - // Measured on the tree: the arm's pattern came back as rule 115 (`constant_pattern`) - // and is now 134 (`var_pattern`). - // - // Asserted here through its consequence, which is what a metric consumer sees: an - // unguarded `var x =>` always matches, so it is the fall-through exactly as `_ =>` - // is, and the two spellings of one catch-all must agree. - let var_arm = - analyze_clean("class C { static int F(int v) => v switch { 1 => 1, var x => x }; }"); - let discard = analyze_clean("class C { static int F(int v) => v switch { 1 => 1, _ => 0 }; }"); - let cyclo = |a: &mehen_core::LanguageAnalysis| { - mehen_report::metrics_json::cyclomatic(&a.root.metrics).sum - }; - assert_eq!(cyclo(&var_arm), cyclo(&discard)); - - // The deconstructing form qualifies too: a `var` pattern never tests the type, so - // `var (a, b)` succeeds whenever the subject is deconstructible — which the compiler - // has already established statically. - let decon = analyze_clean( - "class C { static int F((int,int) v) => v switch { (1,1) => 1, var (a,b) => a + b }; }", - ); - let decon_discard = - analyze_clean("class C { static int F((int,int) v) => v switch { (1,1) => 1, _ => 0 }; }"); - assert_eq!(cyclo(&decon), cyclo(&decon_discard)); - - // A *guarded* one is a real decision, since the guard can fail. - let guarded = analyze_clean( - "class C { static int F(int v) => v switch { 1 => 1, var x when x > 5 => x, _ => 0 }; }", - ); - assert!(cyclo(&guarded) > cyclo(&var_arm)); -} - -#[test] -fn the_var_hoist_leaves_every_other_pattern_form_alone() { - // The guard on the hoist: `var_pattern` now precedes the catch-all, so every other - // pattern form must still reach its own rule — and `var` must stay a legal name. - for source in [ - "class C { static int F(object o) => o switch { int i => i, _ => 0 }; }", - "class C { static int F(object o) => o switch { int => 1, _ => 0 }; }", - "class C { static int F(int v) => v switch { > 5 => 1, _ => 0 }; }", - "class C { static int F(int v) => v switch { > 5 and < 9 => 1, _ => 0 }; }", - "class C { static bool F(object o) => o is not null; }", - "class C { static int F(int[] a) => a switch { [1, 2] => 1, _ => 0 }; }", - "class C { static int F(int[] a) => a switch { [1, .. var rest] => rest.Length, _ => 0 }; }", - "class C { static int F(int v) => v switch { (> 5) => 1, _ => 0 }; }", - "class C { static int F() { var x = 1; return x; } }", - "class C { static int F() { int var = 1; return var; } }", - ] { - // `analyze_clean` asserts no diagnostics, which is the whole assertion here. - let _ = analyze_clean(source); - } -} - -#[test] -fn split_shift_operator_overloads_keep_their_symbol_in_the_name() { - // REGRESSION. The prep splits `>>` / `>>>` / `>>=` / `>>>=` into adjacent `>` tokens - // gated by an adjacency predicate, so their symbol is a child *rule* rather than a - // direct terminal. The naming scan looks for the terminal after `operator`, walked - // straight past to the `;`, and named the space `operator ;` — worse than the bare - // `operator` fallback it was meant to hit. - for (op, want) in [ - (">>", "operator >>"), - (">>>", "operator >>>"), - // The unsplit forms, as controls. - ("<<", "operator <<"), - ("+", "operator +"), - ] { - let a = analyze_clean(&format!( - "class C {{ public static C operator {op}(C a, int b) => a; }}" - )); - let names: Vec<_> = shape(&a.root) - .into_iter() - .filter(|(_, kind, _)| kind == "function") - .map(|(_, _, name)| name) - .collect(); - assert_eq!(names, vec![Some(want.to_string())], "operator {op}"); - } -} diff --git a/crates/mehen-engine/Cargo.toml b/crates/mehen-engine/Cargo.toml deleted file mode 100644 index c3ea1c94..00000000 --- a/crates/mehen-engine/Cargo.toml +++ /dev/null @@ -1,84 +0,0 @@ -[package] -name = "mehen-engine" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — pipeline orchestration, language registry, concurrency (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -mehen-git = { workspace = true } -mehen-coverage = { workspace = true } -mehen-coverage-discovery = { workspace = true } -mehen-report = { workspace = true, features = ["docs-diff"] } -mehen-markdown = { workspace = true } - -# Language analyzer crates — feature-gated via the per-language `lang-*` -# features below. The `default` set compiles every analyzer in. -mehen-python = { workspace = true, optional = true } -mehen-typescript = { workspace = true, optional = true } -mehen-php = { workspace = true, optional = true } -mehen-ruby = { workspace = true, optional = true } -mehen-rust = { workspace = true, optional = true } -mehen-go = { workspace = true, optional = true } -mehen-c = { workspace = true, optional = true } -mehen-kotlin = { workspace = true, optional = true } -mehen-java = { workspace = true, optional = true } -mehen-csharp = { workspace = true, optional = true } -mehen-powershell = { workspace = true, optional = true } -mehen-sql = { workspace = true, optional = true } - -camino = { workspace = true } -clap = { workspace = true } -globset = { workspace = true } -ignore = { workspace = true } -gix = { workspace = true } -log = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -toml = { workspace = true } -# `miette` is pinned here (not in `[workspace.dependencies]`) because -# `mehen-engine` is the only consumer — the fancy diagnostic rendering -# for `mehen.toml` is an engine-only concern (`config_file` module). -miette = { version = "^7.6", features = ["fancy"] } - -[dev-dependencies] -insta = { workspace = true } -pretty_assertions = { workspace = true } -tempfile = { workspace = true } - -[features] -default = [ - "lang-python", - "lang-typescript", - "lang-php", - "lang-ruby", - "lang-rust", - "lang-go", - "lang-c", - "lang-kotlin", - "lang-java", - "lang-csharp", - "lang-powershell", - "lang-sql", -] -lang-python = ["dep:mehen-python"] -lang-typescript = ["dep:mehen-typescript"] -lang-php = ["dep:mehen-php"] -lang-ruby = ["dep:mehen-ruby"] -lang-rust = ["dep:mehen-rust"] -lang-go = ["dep:mehen-go"] -lang-c = ["dep:mehen-c"] -lang-kotlin = ["dep:mehen-kotlin"] -lang-java = ["dep:mehen-java"] -lang-csharp = ["dep:mehen-csharp"] -lang-powershell = ["dep:mehen-powershell"] -lang-sql = ["dep:mehen-sql"] - -[lints] -workspace = true diff --git a/crates/mehen-engine/src/ci.rs b/crates/mehen-engine/src/ci.rs deleted file mode 100644 index a69dd209..00000000 --- a/crates/mehen-engine/src/ci.rs +++ /dev/null @@ -1,370 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::path::PathBuf; - -use mehen_git::{ChangeStatus, ChangedFile}; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum CiProvider { - GitHubActions, -} - -#[derive(Debug, Clone)] -#[allow(dead_code)] -pub struct CiContext { - pub provider: CiProvider, - pub event_name: String, - pub base_ref: Option, - pub head_sha: Option, - /// For `push` events, the payload's `before` revision — the tip of - /// the branch before the push. This is the correct diff baseline - /// for a multi-commit push (`HEAD~1` would only cover the final - /// commit). `None` when absent or all-zeros (branch creation). - pub before_sha: Option, - /// For `push` events, the SHA of the *first* pushed commit. Its - /// parent is the analysis baseline for branch-creation pushes, - /// where the payload carries no usable `before` revision. - pub first_commit_sha: Option, - /// Files changed by the CI event, with the change status folded - /// across the commits in that event. For GitHub `push` events the - /// per-commit `added` / `modified` / `removed` arrays are walked in - /// order to derive the *final* per-path status (e.g. a file added - /// in one commit and removed in a later one is dropped entirely; - /// a file modified then removed is `Deleted`). Without that fold - /// the per-file diff downstream loses the new/deleted semantics. - pub changed_files: Option>, - pub pr_number: Option, - pub repository: Option, -} - -pub fn detect() -> Option { - detect_github_actions() -} - -fn detect_github_actions() -> Option { - if std::env::var("GITHUB_ACTIONS").ok()?.as_str() != "true" { - return None; - } - - let event_name = std::env::var("GITHUB_EVENT_NAME").unwrap_or_default(); - let head_sha = std::env::var("GITHUB_SHA").ok(); - let repository = std::env::var("GITHUB_REPOSITORY").ok(); - - let mut base_ref = std::env::var("GITHUB_BASE_REF") - .ok() - .filter(|s| !s.is_empty()); - let mut changed_files = None; - let mut pr_number = None; - let mut before_sha = None; - let mut first_commit_sha = None; - - if let Ok(event_path) = std::env::var("GITHUB_EVENT_PATH") - && let Ok(data) = std::fs::read_to_string(&event_path) - && let Ok(payload) = serde_json::from_str::(&data) - { - match event_name.as_str() { - "push" => { - changed_files = extract_push_changed_files(&payload); - // The all-zeros SHA marks a branch creation — there is - // no pre-push tip; `first_commit_sha`'s parent becomes - // the baseline instead. - before_sha = payload - .get("before") - .and_then(|b| b.as_str()) - .filter(|s| !s.is_empty() && !s.chars().all(|c| c == '0')) - .map(str::to_string); - first_commit_sha = payload - .get("commits") - .and_then(|c| c.as_array()) - .and_then(|commits| commits.first()) - .and_then(|commit| commit.get("id")) - .and_then(|id| id.as_str()) - .map(str::to_string); - } - "pull_request" => { - if let Some(pr) = payload.get("pull_request") { - if base_ref.is_none() { - base_ref = pr - .get("base") - .and_then(|b| b.get("ref")) - .and_then(|r| r.as_str()) - .map(|s| s.to_string()); - } - pr_number = payload.get("number").and_then(|n| n.as_u64()); - } - } - "merge_group" => { - if let Some(mg) = payload.get("merge_group") - && base_ref.is_none() - { - base_ref = mg - .get("base_ref") - .and_then(|r| r.as_str()) - .map(|s| s.to_string()); - } - } - _ => {} - } - } - - Some(CiContext { - provider: CiProvider::GitHubActions, - event_name, - base_ref, - head_sha, - before_sha, - first_commit_sha, - changed_files, - pr_number, - repository, - }) -} - -fn extract_push_changed_files(payload: &serde_json::Value) -> Option> { - let commits = payload.get("commits")?.as_array()?; - // GitHub truncates the webhook `commits` array (documented cap: - // 20 entries); `size` carries the push's true commit count. A - // truncated array cannot be folded faithfully — report the - // payload as unavailable so callers use the tree diff instead. - if let Some(size) = payload.get("size").and_then(|v| v.as_u64()) - && size as usize != commits.len() - { - return None; - } - let mut by_path: std::collections::HashMap = - std::collections::HashMap::new(); - - for commit in commits { - if let Some(arr) = commit.get("added").and_then(|v| v.as_array()) { - for item in arr { - if let Some(path) = item.as_str() { - // A re-added file (was removed earlier in the - // push, now added again) becomes `Modified` in - // the final state — it existed before the push - // and exists after, just changed. - let key = PathBuf::from(path); - let status = match by_path.get(&key) { - Some(ChangeStatus::Deleted) => ChangeStatus::Modified, - _ => ChangeStatus::Added, - }; - by_path.insert(key, status); - } - } - } - if let Some(arr) = commit.get("modified").and_then(|v| v.as_array()) { - for item in arr { - if let Some(path) = item.as_str() { - // A modify after add keeps the path as `Added` - // (the file is new in this push). Otherwise the - // path is `Modified`. A modify after delete is - // illegal in real GitHub payloads but we treat - // it as `Modified` for safety. - let key = PathBuf::from(path); - let status = match by_path.get(&key) { - Some(ChangeStatus::Added) => ChangeStatus::Added, - _ => ChangeStatus::Modified, - }; - by_path.insert(key, status); - } - } - } - if let Some(arr) = commit.get("removed").and_then(|v| v.as_array()) { - for item in arr { - if let Some(path) = item.as_str() { - let key = PathBuf::from(path); - // A file that was added inside this push and then - // removed in a later commit is a no-op — it never - // existed at the head of the push, so drop it. - if matches!(by_path.get(&key), Some(ChangeStatus::Added)) { - by_path.remove(&key); - } else { - by_path.insert(key, ChangeStatus::Deleted); - } - } - } - } - } - - // An *empty* fold is meaningful and distinct from an unavailable - // payload (`commits` missing entirely → `None` above): a push - // whose commits add a file and then remove it changes nothing, and - // callers must not fall back to a ref-range diff that would - // misreport the final commit's deletion. - let mut sorted: Vec = by_path - .into_iter() - .map(|(path, status)| ChangedFile { - path, - status, - // GitHub push payloads carry no rename information. - source_path: None, - }) - .collect(); - sorted.sort_by(|a, b| a.path.cmp(&b.path)); - Some(sorted) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn paths_with_status(files: &[ChangedFile]) -> Vec<(PathBuf, ChangeStatus)> { - files.iter().map(|f| (f.path.clone(), f.status)).collect() - } - - #[test] - fn test_extract_push_preserves_per_path_status() { - let payload = serde_json::json!({ - "commits": [ - { - "added": ["src/new.rs"], - "modified": ["src/main.rs"], - "removed": ["src/old.rs"] - }, - { - "added": [], - "modified": ["src/main.rs", "src/lib.rs"], - "removed": [] - } - ] - }); - - let files = extract_push_changed_files(&payload).unwrap(); - assert_eq!( - paths_with_status(&files), - vec![ - (PathBuf::from("src/lib.rs"), ChangeStatus::Modified), - (PathBuf::from("src/main.rs"), ChangeStatus::Modified), - (PathBuf::from("src/new.rs"), ChangeStatus::Added), - (PathBuf::from("src/old.rs"), ChangeStatus::Deleted), - ] - ); - } - - /// A file added in one commit and modified in a later commit is - /// new at the head of the push, so its final status is `Added` - /// (not `Modified` — the file did not exist before the push). - #[test] - fn test_extract_push_add_then_modify_is_added() { - let payload = serde_json::json!({ - "commits": [ - {"added": ["src/new.rs"], "modified": [], "removed": []}, - {"added": [], "modified": ["src/new.rs"], "removed": []} - ] - }); - let files = extract_push_changed_files(&payload).unwrap(); - assert_eq!( - paths_with_status(&files), - vec![(PathBuf::from("src/new.rs"), ChangeStatus::Added)] - ); - } - - /// A file added then removed in the same push is a no-op against - /// the base — the fold is *empty* (`Some(vec![])`), which callers - /// must honor rather than falling back to a ref-range diff that - /// would misreport the final commit's deletion. - #[test] - fn test_extract_push_add_then_remove_folds_to_empty() { - let payload = serde_json::json!({ - "commits": [ - {"added": ["src/scratch.rs"], "modified": [], "removed": []}, - {"added": [], "modified": [], "removed": ["src/scratch.rs"]} - ] - }); - let files = extract_push_changed_files(&payload).expect("payload is available"); - assert!(files.is_empty(), "add-then-remove folds to nothing"); - } - - /// A file modified then removed across the push is `Deleted` at - /// the head — it existed before the push and doesn't anymore. - #[test] - fn test_extract_push_modify_then_remove_is_deleted() { - let payload = serde_json::json!({ - "commits": [ - {"added": [], "modified": ["src/main.rs"], "removed": []}, - {"added": [], "modified": [], "removed": ["src/main.rs"]} - ] - }); - let files = extract_push_changed_files(&payload).unwrap(); - assert_eq!( - paths_with_status(&files), - vec![(PathBuf::from("src/main.rs"), ChangeStatus::Deleted)] - ); - } - - /// A file removed then re-added across the push is `Modified` — - /// it existed before, exists after, but its content changed. - #[test] - fn test_extract_push_remove_then_add_is_modified() { - let payload = serde_json::json!({ - "commits": [ - {"added": [], "modified": [], "removed": ["src/main.rs"]}, - {"added": ["src/main.rs"], "modified": [], "removed": []} - ] - }); - let files = extract_push_changed_files(&payload).unwrap(); - assert_eq!( - paths_with_status(&files), - vec![(PathBuf::from("src/main.rs"), ChangeStatus::Modified)] - ); - } - - #[test] - fn test_extract_push_no_commits() { - let payload = serde_json::json!({}); - assert!(extract_push_changed_files(&payload).is_none()); - } - - #[test] - fn test_extract_push_empty_commits() { - // An empty commits array is still an *available* payload with - // nothing changed — distinct from a payload with no `commits` - // key at all. - let payload = serde_json::json!({ - "commits": [] - }); - let files = extract_push_changed_files(&payload).expect("payload is available"); - assert!(files.is_empty()); - } - - #[test] - fn test_extract_push_truncated_commits_are_unavailable() { - // GitHub caps the webhook `commits` array at 20 entries; when - // `size` says the push had more, the fold would miss files - // from the omitted commits — the payload must be reported as - // unavailable so the tree diff is used instead. - let payload = serde_json::json!({ - "size": 25, - "commits": [ - {"added": ["src/kept.rs"], "modified": [], "removed": []} - ] - }); - assert!(extract_push_changed_files(&payload).is_none()); - } - - #[test] - fn test_extract_push_complete_commits_with_size_fold_normally() { - let payload = serde_json::json!({ - "size": 1, - "commits": [ - {"added": ["src/new.rs"], "modified": [], "removed": []} - ] - }); - let files = extract_push_changed_files(&payload).unwrap(); - assert_eq!( - paths_with_status(&files), - vec![(PathBuf::from("src/new.rs"), ChangeStatus::Added)] - ); - } - - #[test] - fn test_detect_not_github() { - // Ensure GITHUB_ACTIONS is not set for this test - // SAFETY: single-threaded test context; no other thread reads this var concurrently - #[allow(unsafe_code)] - unsafe { - std::env::remove_var("GITHUB_ACTIONS"); - } - assert!(detect().is_none()); - } -} diff --git a/crates/mehen-engine/src/concurrent_files.rs b/crates/mehen-engine/src/concurrent_files.rs deleted file mode 100644 index 97129229..00000000 --- a/crates/mehen-engine/src/concurrent_files.rs +++ /dev/null @@ -1,619 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; - -use globset::{Glob, GlobSet, GlobSetBuilder}; -use ignore::{DirEntry, WalkBuilder, WalkState}; - -use crate::git_attributes::{GitAttributeFilterSet, GitRepositoryRegistry}; - -/// Build a `GlobSet` from a list of glob strings, ignoring empty and invalid -/// entries. -/// -/// Used by both the `diff` and `top-offenders` orchestrators to turn the -/// user's `--include` / `--exclude` flags into a usable matcher. -pub(crate) fn mk_globset(elems: I) -> GlobSet -where - I: IntoIterator, - S: AsRef, -{ - let mut globset = GlobSetBuilder::new(); - for elem in elems { - let elem = elem.as_ref(); - if !elem.is_empty() - && let Ok(glob) = Glob::new(elem) - { - globset.add(glob); - } - } - globset.build().unwrap_or_else(|_| GlobSet::empty()) -} - -fn is_file(entry: &DirEntry) -> bool { - entry - .file_type() - .is_some_and(|file_type| file_type.is_file()) - || (entry.path_is_symlink() && entry.path().is_file()) -} - -fn path_matches(path: &Path, include: &GlobSet, exclude: &GlobSet) -> bool { - (include.is_empty() || include.is_match(path)) - && (exclude.is_empty() || !exclude.is_match(path)) -} - -#[derive(Clone, Debug)] -struct WalkRoot { - original: PathBuf, - normalized: PathBuf, - is_file: bool, -} - -#[derive(Clone, Debug)] -struct WalkPaths { - roots: Vec, -} - -impl WalkPaths { - fn new(paths: &[PathBuf]) -> Self { - let roots = paths - .iter() - .filter_map(|path| { - if !path.exists() { - log::warn!("File doesn't exist: {path:?}"); - return None; - } - match std::fs::canonicalize(path).or_else(|_| std::path::absolute(path)) { - Ok(normalized) => Some(WalkRoot { - original: path.clone(), - is_file: normalized.is_file(), - normalized, - }), - Err(error) => { - log::warn!("Failed to resolve path {}: {error}", path.display()); - None - } - } - }) - .collect(); - Self { roots } - } - - fn normalized(&self) -> Vec { - self.roots - .iter() - .map(|root| root.normalized.clone()) - .collect() - } - - fn restore(&self, normalized: &Path) -> PathBuf { - for root in &self.roots { - if root.is_file { - if normalized == root.normalized { - return root.original.clone(); - } - continue; - } - if let Ok(relative) = normalized.strip_prefix(&root.normalized) { - return root.original.join(relative); - } - } - normalized.to_path_buf() - } -} - -fn walk_builder( - files_data: &FilesData, - paths: &WalkPaths, - repositories: Option, -) -> WalkBuilder { - let mut builder = WalkBuilder::empty(); - for root in &paths.roots { - builder.add(&root.normalized); - } - if let Some(repositories) = repositories { - builder.filter_entry(move |entry| { - if entry - .file_type() - .is_some_and(|file_type| file_type.is_dir()) - { - repositories.discover_nested_repository(entry.path()); - } - true - }); - } - - // Keep the policy explicit: hidden entries, .ignore, .gitignore, the - // repository-local exclude file, parent rules, and the global Git ignore - // are all honored. `ignore` prunes ignored directories before they can - // enqueue files for analysis. - builder.standard_filters(true); - if !files_data.respect_ignores { - // `--no-ignore` disables ignore files without changing the established - // behavior of omitting hidden children. - builder - .parents(false) - .ignore(false) - .git_ignore(false) - .git_global(false) - .git_exclude(false); - } - builder -} - -fn log_ignore_error(entry: &DirEntry) { - if let Some(error) = entry.error() { - log::warn!( - "Failed to apply an ignore rule while walking {}: {error}", - entry.path().display() - ); - } -} - -fn attribute_filters_for_walk( - paths: &WalkPaths, - respect_ignores: bool, -) -> (GitAttributeFilterSet, Option) { - let filters = if respect_ignores { - GitAttributeFilterSet::for_walk_paths(&paths.normalized()) - } else { - GitAttributeFilterSet::default() - }; - let repositories = respect_ignores.then(|| filters.repository_registry()); - (filters, repositories) -} - -/// Walk all configured roots serially and return matching files. -/// -/// The public `rank_top_offenders` API uses this path. Analysis remains -/// serial there, but traversal follows exactly the same ignore policy as the -/// parallel CLI runner. -pub(crate) fn walk_files(files_data: &FilesData) -> Vec { - let mut paths = Vec::new(); - let walk_paths = WalkPaths::new(&files_data.paths); - let (mut attribute_filters, repositories) = - attribute_filters_for_walk(&walk_paths, files_data.respect_ignores); - for result in walk_builder(files_data, &walk_paths, repositories).build() { - let entry = match result { - Ok(entry) => entry, - Err(error) => { - log::warn!("Failed to walk an input path: {error}"); - continue; - } - }; - log_ignore_error(&entry); - let output_path = walk_paths.restore(entry.path()); - if is_file(&entry) - && path_matches(&output_path, &files_data.include, &files_data.exclude) - && !is_excluded_by_attributes(&mut attribute_filters, entry.path()) - { - paths.push(output_path); - } - } - paths -} - -type ProcFilesFunction = dyn Fn(PathBuf, &Config) -> std::io::Result<()> + Send + Sync; - -/// An error encountered while walking files concurrently. -#[derive(Debug)] -pub(crate) enum ConcurrentErrors { - /// Filesystem traversal failed. - Walk(String), - /// A worker panicked while traversing or processing a file. - Worker(String), -} - -impl std::fmt::Display for ConcurrentErrors { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Walk(msg) => write!(f, "walk error: {msg}"), - Self::Worker(msg) => write!(f, "worker error: {msg}"), - } - } -} - -impl std::error::Error for ConcurrentErrors {} - -/// Data related to files. -#[derive(Debug)] -pub(crate) struct FilesData { - /// Kind of files included in a search. - pub include: GlobSet, - /// Kind of files excluded from a search. - pub exclude: GlobSet, - /// List of file paths. - pub paths: Vec, - /// Whether standard ignore files and Git attributes should be respected. - pub respect_ignores: bool, -} - -/// A runner that traverses and processes files concurrently. -pub(crate) struct ConcurrentRunner { - proc_files: Box>, - num_jobs: usize, -} - -impl std::fmt::Debug for ConcurrentRunner { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("ConcurrentRunner") - .field("num_jobs", &self.num_jobs) - .finish_non_exhaustive() - } -} - -impl ConcurrentRunner { - /// Creates a new `ConcurrentRunner`. - /// - /// * `num_jobs` - Number of jobs utilized to process files concurrently. - /// * `proc_files` - Function that processes each file found during - /// the search. - pub(crate) fn new(num_jobs: usize, proc_files: ProcFiles) -> Self - where - ProcFiles: 'static + Fn(PathBuf, &Config) -> std::io::Result<()> + Send + Sync, - { - Self { - proc_files: Box::new(proc_files), - num_jobs: num_jobs.max(1), - } - } - - /// Walk the configured roots and process each matching file in a traversal - /// worker. - /// - /// `ignore::WalkParallel` schedules directories with work stealing and - /// invokes `proc_files` directly. There is no producer channel that can - /// accumulate one job per file while parsers are busy. - pub(crate) fn run(self, config: Config, files_data: FilesData) -> Result<(), ConcurrentErrors> { - let config = Arc::new(config); - let proc_files: Arc> = Arc::from(self.proc_files); - let include = Arc::new(files_data.include.clone()); - let exclude = Arc::new(files_data.exclude.clone()); - let walk_error: Arc>> = Arc::new(Mutex::new(None)); - let walk_paths = Arc::new(WalkPaths::new(&files_data.paths)); - let (attribute_filters, repositories) = - attribute_filters_for_walk(walk_paths.as_ref(), files_data.respect_ignores); - - let mut builder = walk_builder(&files_data, walk_paths.as_ref(), repositories); - builder.threads(self.num_jobs); - let walker = builder.build_parallel(); - - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - walker.run(|| { - let config = Arc::clone(&config); - let proc_files = Arc::clone(&proc_files); - let include = Arc::clone(&include); - let exclude = Arc::clone(&exclude); - let walk_error = Arc::clone(&walk_error); - let walk_paths = Arc::clone(&walk_paths); - let mut attribute_filters = attribute_filters.clone(); - - Box::new(move |result| { - let entry = match result { - Ok(entry) => entry, - Err(error) => { - if let Ok(mut slot) = walk_error.lock() - && slot.is_none() - { - *slot = Some(error.to_string()); - } - return WalkState::Quit; - } - }; - log_ignore_error(&entry); - let output_path = walk_paths.restore(entry.path()); - if !is_file(&entry) - || !path_matches(&output_path, include.as_ref(), exclude.as_ref()) - || is_excluded_by_attributes(&mut attribute_filters, entry.path()) - { - return WalkState::Continue; - } - - let path = output_path; - if let Err(error) = proc_files(path.clone(), config.as_ref()) { - log::error!("{error:?} for file {path:?}"); - } - WalkState::Continue - }) - }); - })); - - if result.is_err() { - return Err(ConcurrentErrors::Worker( - "a traversal worker panicked".to_owned(), - )); - } - if let Some(error) = walk_error - .lock() - .map_err(|error| ConcurrentErrors::Worker(error.to_string()))? - .take() - { - return Err(ConcurrentErrors::Walk(error)); - } - Ok(()) - } -} - -fn is_excluded_by_attributes(filters: &mut GitAttributeFilterSet, path: &Path) -> bool { - match filters.excludes_path(path) { - Ok(excluded) => excluded, - Err(error) => { - log::warn!( - "Failed to apply Git attributes to {}: {error}", - path.display() - ); - false - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn file_names(paths: &[PathBuf]) -> Vec<&str> { - let mut names: Vec<&str> = paths - .iter() - .filter_map(|path| path.file_name().and_then(|name| name.to_str())) - .collect(); - names.sort_unstable(); - names - } - - fn files_data(root: PathBuf) -> FilesData { - FilesData { - include: GlobSet::empty(), - exclude: GlobSet::empty(), - paths: vec![root], - respect_ignores: true, - } - } - - #[test] - fn walk_files_respects_gitignore_and_nested_ignore_files() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - std::fs::create_dir_all(dir.path().join("build")).unwrap(); - std::fs::create_dir_all(dir.path().join("src/generated")).unwrap(); - std::fs::write(dir.path().join(".gitignore"), "build/\n").unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "* -linguist-generated -linguist-vendored -binary\n", - ) - .unwrap(); - std::fs::write(dir.path().join("src/.ignore"), "generated/\n").unwrap(); - std::fs::write(dir.path().join("src/main.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("build/output.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("src/generated/output.py"), "x = 1\n").unwrap(); - - let paths = walk_files(&files_data(dir.path().to_path_buf())); - - assert_eq!(file_names(&paths), vec!["main.py"]); - } - - #[test] - fn walk_files_respects_parent_gitignore_when_root_is_nested() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - std::fs::create_dir_all(dir.path().join("src/generated")).unwrap(); - std::fs::write(dir.path().join(".gitignore"), "src/generated/\n").unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "* -linguist-generated -linguist-vendored -binary\n", - ) - .unwrap(); - std::fs::write(dir.path().join("src/main.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("src/generated/output.py"), "x = 1\n").unwrap(); - - let paths = walk_files(&files_data(dir.path().join("src"))); - - assert_eq!(file_names(&paths), vec!["main.py"]); - } - - #[test] - fn walk_files_respects_git_info_exclude() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - std::fs::write(dir.path().join(".git/info/exclude"), "local.py\n").unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "* -linguist-generated -linguist-vendored -binary\n", - ) - .unwrap(); - std::fs::write(dir.path().join("kept.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("local.py"), "x = 1\n").unwrap(); - - let paths = walk_files(&files_data(dir.path().to_path_buf())); - - assert_eq!(file_names(&paths), vec!["kept.py"]); - } - - #[test] - fn explicit_ignored_file_is_still_processed() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - let ignored = dir.path().join("ignored.py"); - std::fs::write(dir.path().join(".gitignore"), "ignored.py\n").unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "ignored.py linguist-generated\n", - ) - .unwrap(); - std::fs::write(&ignored, "x = 1\n").unwrap(); - - let paths = walk_files(&files_data(ignored.clone())); - - assert_eq!(paths, vec![ignored]); - } - - #[test] - fn no_ignore_disables_ignore_files_but_keeps_hidden_children_hidden() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - std::fs::create_dir(dir.path().join(".cache")).unwrap(); - std::fs::write(dir.path().join(".gitignore"), "ignored.py\n").unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "generated.py linguist-generated\n", - ) - .unwrap(); - std::fs::write(dir.path().join("ignored.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("generated.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join(".cache/hidden.py"), "x = 1\n").unwrap(); - - let mut data = files_data(dir.path().to_path_buf()); - data.respect_ignores = false; - let paths = walk_files(&data); - - assert_eq!(file_names(&paths), vec!["generated.py", "ignored.py"]); - } - - #[test] - fn walk_files_respects_generated_vendored_and_binary_attributes() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -generated.py linguist-generated -vendored.py linguist-vendored -binary.py binary -", - ) - .unwrap(); - for name in ["kept.py", "generated.py", "vendored.py", "binary.py"] { - std::fs::write(dir.path().join(name), "x = 1\n").unwrap(); - } - - let paths = walk_files(&files_data(dir.path().to_path_buf())); - - assert_eq!(file_names(&paths), vec!["kept.py"]); - } - - #[test] - fn walk_files_applies_attributes_for_each_repository_root() { - let first = tempfile::tempdir().unwrap(); - gix::init(first.path()).unwrap(); - std::fs::write( - first.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -generated.py linguist-generated -", - ) - .unwrap(); - std::fs::write(first.path().join("generated.py"), "x = 1\n").unwrap(); - std::fs::write(first.path().join("first.py"), "x = 1\n").unwrap(); - - let second = tempfile::tempdir().unwrap(); - gix::init(second.path()).unwrap(); - std::fs::write( - second.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -vendored.py linguist-vendored -", - ) - .unwrap(); - std::fs::write(second.path().join("vendored.py"), "x = 1\n").unwrap(); - std::fs::write(second.path().join("second.py"), "x = 1\n").unwrap(); - - let paths = walk_files(&FilesData { - include: GlobSet::empty(), - exclude: GlobSet::empty(), - paths: vec![first.path().to_path_buf(), second.path().to_path_buf()], - respect_ignores: true, - }); - - assert_eq!(file_names(&paths), vec!["first.py", "second.py"]); - } - - #[test] - fn walk_files_normalizes_roots_before_traversal() { - let dir = tempfile::tempdir().unwrap(); - let root = dir.path().join("repo"); - std::fs::create_dir(&root).unwrap(); - gix::init(&root).unwrap(); - std::fs::write( - root.join(".gitattributes"), - "generated.py linguist-generated\n", - ) - .unwrap(); - std::fs::write(root.join("generated.py"), "x = 1\n").unwrap(); - let kept = root.join("kept.py"); - std::fs::write(&kept, "x = 1\n").unwrap(); - - let input_root = root.join("..").join("repo"); - let paths = walk_files(&files_data(input_root.clone())); - - assert_eq!(paths, vec![input_root.join("kept.py")]); - } - - #[test] - fn serial_and_parallel_walks_use_nested_repository_attributes() { - let outer = tempfile::tempdir().unwrap(); - gix::init(outer.path()).unwrap(); - let nested = outer.path().join("vendor/lib"); - std::fs::create_dir_all(&nested).unwrap(); - gix::init(&nested).unwrap(); - std::fs::write( - nested.join(".git/info/attributes"), - "generated.py linguist-vendored\n", - ) - .unwrap(); - let outer_file = outer.path().join("outer.py"); - let nested_file = nested.join("kept.py"); - std::fs::write(&outer_file, "x = 1\n").unwrap(); - std::fs::write(&nested_file, "x = 1\n").unwrap(); - std::fs::write(nested.join("generated.py"), "x = 1\n").unwrap(); - - let data = files_data(outer.path().to_path_buf()); - let paths = walk_files(&data); - assert_eq!(file_names(&paths), vec!["kept.py", "outer.py"]); - - let visited = Arc::new(Mutex::new(Vec::new())); - let output = Arc::clone(&visited); - ConcurrentRunner::new(2, move |path, _: &()| { - output.lock().unwrap().push(path); - Ok(()) - }) - .run((), data) - .unwrap(); - - let paths = visited.lock().unwrap(); - assert_eq!(file_names(&paths), vec!["kept.py", "outer.py"]); - } - - #[test] - fn parallel_runner_uses_the_same_ignore_policy() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - std::fs::create_dir(dir.path().join("node_modules")).unwrap(); - std::fs::write(dir.path().join(".gitignore"), "node_modules/\n").unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -vendored.py linguist-vendored -", - ) - .unwrap(); - std::fs::write(dir.path().join("main.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("vendored.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("node_modules/generated.py"), "x = 1\n").unwrap(); - - let visited = Arc::new(Mutex::new(Vec::new())); - let output = Arc::clone(&visited); - ConcurrentRunner::new(2, move |path, _: &()| { - output.lock().unwrap().push(path); - Ok(()) - }) - .run((), files_data(dir.path().to_path_buf())) - .unwrap(); - - let paths = visited.lock().unwrap(); - assert_eq!(file_names(&paths), vec!["main.py"]); - } -} diff --git a/crates/mehen-engine/src/config_file.rs b/crates/mehen-engine/src/config_file.rs deleted file mode 100644 index f84c5822..00000000 --- a/crates/mehen-engine/src/config_file.rs +++ /dev/null @@ -1,2598 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Repository-local configuration (`mehen.toml` / `.mehen.toml`). -//! -//! The configuration file carries per-metric thresholds, optionally -//! overridden per language: -//! -//! ```toml -//! [thresholds] -//! cognitive = 15 # higher-is-worse metrics: the value is a maximum -//! loc.lloc = 500 # dotted and "quoted.key" spellings are equivalent -//! mi.visual_studio = 40 # higher-is-better metrics: the value is a minimum -//! -//! [languages.python.thresholds] -//! cognitive = 10 # overrides the global limit for Python files only -//! ``` -//! -//! Thresholds gate the metrics a command actually reports: `mehen -//! metrics` evaluates every configured threshold against the file's -//! root metric set, while `mehen diff` and `mehen top-offenders` -//! evaluate the thresholds whose metric is among the selected output -//! columns. Spellings are canonicalized before matching, so a -//! `cognitive.sum` threshold gates a `cognitive` column (both read the -//! same published key). A metric the analyzed file does not publish -//! (e.g. a `sql.*` threshold against a Python file) is skipped — a -//! missing measurement is never treated as `0`. -//! -//! Any crossed threshold fails the command with exit code 1 after a -//! human-readable report on stderr (see [`render_threshold_report`]). -//! -//! Errors and reports render through [`miette`]'s graphical handler: -//! configuration mistakes point at the offending key inside the TOML -//! source and carry a `help:` suggestion; colors engage only when -//! stderr is a terminal (and `NO_COLOR` is unset). -//! -//! Discovery starts at the current working directory and walks up to -//! the enclosing git repository root (the upper boundary — a config -//! above it cannot belong to the project). Outside a repository only -//! the current directory is checked. `mehen.toml` is preferred over -//! `.mehen.toml`; `--config ` bypasses discovery. - -use std::collections::BTreeMap; -use std::fmt; -use std::path::{Path, PathBuf}; - -use miette::{LabeledSpan, NamedSource}; - -use mehen_core::{Language, MetricKey, MetricSpace, Polarity, keys}; - -use crate::metric_selector::{is_higher_is_better_metric, metric_set_key_for}; - -/// Recognized configuration file names, in preference order. -pub(crate) const CONFIG_FILE_NAMES: &[&str] = &["mehen.toml", ".mehen.toml"]; - -/// Every metric key the shared source-code publishers -/// (`mehen-metrics::state`) emit onto a root `MetricSpace`, in the -/// exact published spelling. Configured thresholds must resolve to one -/// of these (or to a `history.*` / `sql.*` / `markdown.*` key) — a -/// name no analyzer can ever publish is rejected at load time, because -/// a threshold that can never read a value is a gate that can never -/// fire. -/// -/// Kept in sync with the publishers by -/// `validator_accepts_every_key_real_analyzers_publish` below, which -/// runs real analyses and asserts every published root key validates. -const PUBLISHED_METRIC_KEYS: &[&str] = &[ - // cyclomatic - "cyclomatic", - "cyclomatic.sum", - "cyclomatic.min", - "cyclomatic.max", - "cyclomatic.avg", - // cognitive - "cognitive", - "cognitive.sum", - "cognitive.average", - "cognitive.min", - "cognitive.max", - // loc family — the bare `loc` key (a mirror of `loc.sloc`) is - // published but deliberately NOT configurable: the GitHub Action - // ecosystem treats bare `loc` as a legacy alias for `loc.lloc`, - // so accepting it would gate a different measurement than the - // name suggests. Use the precise `loc.*` members instead. - "loc.lloc", - "loc.sloc", - "loc.ploc", - "loc.cloc", - "loc.blank", - "loc.lloc.min", - "loc.lloc.max", - "loc.lloc.avg", - "loc.sloc.min", - "loc.sloc.max", - "loc.sloc.avg", - "loc.ploc.min", - "loc.ploc.max", - "loc.ploc.avg", - "loc.cloc.min", - "loc.cloc.max", - "loc.cloc.avg", - "loc.blank.min", - "loc.blank.max", - "loc.blank.avg", - // halstead - "halstead.volume", - "halstead.difficulty", - "halstead.effort", - "halstead.vocabulary", - "halstead.length", - "halstead.n1", - "halstead.N1", - "halstead.n2", - "halstead.N2", - "halstead.estimated_program_length", - "halstead.purity_ratio", - "halstead.level", - "halstead.time", - "halstead.bugs", - // maintainability index (no bare `mi` is published) - "mi.visual_studio", - "mi.original", - "mi.sei", - // abc - "abc", - "abc.assignments", - "abc.branches", - "abc.conditions", - "abc.assignments_average", - "abc.branches_average", - "abc.conditions_average", - "abc.assignments_min", - "abc.assignments_max", - "abc.branches_min", - "abc.branches_max", - "abc.conditions_min", - "abc.conditions_max", - // nargs - "nargs", - "nargs.total_functions", - "nargs.total_closures", - "nargs.average_functions", - "nargs.average_closures", - "nargs.average", - "nargs.functions_min", - "nargs.functions_max", - "nargs.closures_min", - "nargs.closures_max", - // nom — the bare `nom` key (functions + closures total) is - // published but deliberately NOT configurable: the GitHub Action - // ecosystem treats bare `nom` as a legacy alias for - // `nom.functions`, so accepting it would gate a different - // measurement than the name suggests. Use the precise members. - "nom.functions", - "nom.closures", - "nom.functions_average", - "nom.closures_average", - "nom.average", - "nom.functions_min", - "nom.functions_max", - "nom.closures_min", - "nom.closures_max", - // nexit - "nexit", - "nexit.sum", - "nexit.average", - "nexit.min", - "nexit.max", - // npa - "npa", - "npa.classes", - "npa.interfaces", - "npa.class_attributes", - "npa.interface_attributes", - "npa.classes_average", - "npa.interfaces_average", - "npa.total_attributes", - "npa.average", - // npm - "npm", - "npm.classes", - "npm.interfaces", - "npm.class_methods", - "npm.interface_methods", - "npm.classes_average", - "npm.interfaces_average", - "npm.total_methods", - "npm.average", - // wmc - "wmc", - "wmc.classes", - "wmc.interfaces", -]; - -/// Why a metric name failed to resolve to a published key. -pub(crate) enum ResolveError { - /// A `history.*` name outside the fixed family. - UnknownHistory, - /// A `coverage.*` name outside the fixed family. - UnknownCoverage, - /// A `sql.*` / `markdown.*` name the owning analyzer never - /// publishes. - UnknownNamespaced, - /// A namespace this build cannot analyze (`sql.*` without the - /// `lang-sql` feature) — the gate could never fire. - #[cfg(not(feature = "lang-sql"))] - UnavailableNamespace, - /// Everything else the resolver cannot map to a published key. - Unknown, -} - -/// Resolve a configured (or selected) metric name to the canonical -/// key the analyzers actually publish. -/// -/// - `history.*` names must be in the fixed [`keys::HISTORY_ALL`] -/// family and resolve to themselves. -/// - `sql.*` / `markdown.*` names resolve to themselves: the -/// language-owned namespaces are extensible, so their members -/// cannot be enumerated here. -/// - Everything else maps through [`metric_set_key_for`] (`cognitive` -/// → `cognitive.sum`) and must land on a [`PUBLISHED_METRIC_KEYS`] -/// entry, directly or via an aggregate-spelling alias: the -/// underscore sub-bucket form (`nom.functions.max` → -/// `nom.functions_max`) and the `avg` ↔ `average` pair -/// (`nexit.avg` → `nexit.average`). -/// -/// Because evaluation reads exactly the canonical key, "accepted at -/// load time" and "readable at evaluation time" agree by -/// construction: a name this function accepts can fire, a name it -/// rejects never could. `parse_metric_selectors` resolves `--metric` -/// names through the same function, so every key the config can gate -/// is also selectable as a diff/top-offenders column. -pub(crate) fn canonical_metric_key(name: &str) -> Result { - if name == "history" || name.starts_with("history.") { - return if keys::HISTORY_ALL.contains(&name) { - Ok(name.to_string()) - } else { - Err(ResolveError::UnknownHistory) - }; - } - if name == "coverage" || name.starts_with("coverage.") { - // The engine-published `coverage.*` family is fixed, like - // `history.*`: a typo must be rejected up front, or it would - // trigger report discovery/parsing only to read an - // unpublished key. - return if keys::COVERAGE_ALL.contains(&name) { - Ok(name.to_string()) - } else { - Err(ResolveError::UnknownCoverage) - }; - } - if name.starts_with("sql.") { - // The SQL analyzer owns its namespace: validate against its - // published catalogue (fixed keys + enum-backed dynamic - // families) so a typo can never become a gate that cannot - // fire. A build without the SQL analyzer cannot analyze SQL - // files at all, so any `sql.*` threshold would be a dead gate - // there — rejected rather than accepted verbatim. - #[cfg(feature = "lang-sql")] - { - return if mehen_sql::is_published_metric_key(name) { - Ok(name.to_string()) - } else { - Err(ResolveError::UnknownNamespaced) - }; - } - #[cfg(not(feature = "lang-sql"))] - { - return Err(ResolveError::UnavailableNamespace); - } - } - if name.starts_with("markdown.") { - return if mehen_markdown::is_published_metric_key(name) { - Ok(name.to_string()) - } else { - Err(ResolveError::UnknownNamespaced) - }; - } - let key = metric_set_key_for(name); - if PUBLISHED_METRIC_KEYS.contains(&key) { - return Ok(key.to_string()); - } - if let Some((base, suffix)) = key.rsplit_once('.') - && matches!(suffix, "min" | "max" | "avg" | "average" | "sum") - { - let mut candidates = vec![format!("{base}_{suffix}")]; - let alternate = match suffix { - "avg" => Some("average"), - "average" => Some("avg"), - _ => None, - }; - if let Some(alternate) = alternate { - candidates.push(format!("{base}.{alternate}")); - candidates.push(format!("{base}_{alternate}")); - } - if let Some(hit) = candidates - .into_iter() - .find(|candidate| PUBLISHED_METRIC_KEYS.contains(&candidate.as_str())) - { - return Ok(hit); - } - } - Err(ResolveError::Unknown) -} - -/// The canonical key for filter matching, falling back to the raw -/// name for anything unresolvable (a selector the engine accepted is -/// never rejected here — worst case it matches by its own spelling). -fn canonical_for_match(name: &str) -> String { - canonical_metric_key(name).unwrap_or_else(|_| name.to_string()) -} - -/// A parsed and validated configuration file. -#[derive(Debug, Clone)] -pub struct ConfigFile { - /// The file the configuration was loaded from (absolute when the - /// path could be canonicalized). - pub path: PathBuf, - /// Per-metric threshold policy (global + per-language overrides). - pub thresholds: ThresholdPolicy, - /// The `[coverage]` section, when present. - pub coverage: Option, -} - -/// The `[coverage]` section of `mehen.toml`: -/// -/// ```toml -/// [coverage] -/// reports = ["ci-artifacts/lcov.info"] # explicit report paths -/// discover = true # artifact auto-discovery -/// extra-patterns = ["qa/**/*.lcov"] # additive scan globs -/// stale-warning = true # mtime-vs-HEAD warning -/// ``` -/// -/// The section's mere presence opts the run into coverage ingestion -/// when it carries `reports` or an explicit `discover = true`; the -/// `--coverage` CLI flag always wins over the file. -#[derive(Debug, Clone)] -pub struct CoverageConfig { - /// Explicit report paths (relative paths resolve against the - /// invocation's working directory, like every other CLI path). - pub reports: Vec, - /// Whether artifact auto-discovery may run. `None` when the key is - /// omitted (defaults to enabled once coverage is requested); - /// `Some(true)` additionally opts the run in by itself. - pub discover_key: Option, - /// Additive scan globs, matched relative to each discovery root. - pub extra_patterns: Vec, - /// Whether to warn when a discovered report's mtime predates the - /// newest analyzed commit. Default: true. - pub stale_warning: bool, -} - -/// Hand-written so the type carries its documented defaults — the -/// derived impl would silently disable the staleness warning for any -/// caller constructing the (public, re-exported) type directly. -impl Default for CoverageConfig { - fn default() -> Self { - Self { - reports: Vec::new(), - discover_key: None, - extra_patterns: Vec::new(), - stale_warning: true, - } - } -} - -impl CoverageConfig { - /// Effective discovery toggle (`discover` defaults to enabled). - pub(crate) fn discover(&self) -> bool { - self.discover_key.unwrap_or(true) - } - - /// Whether this section by itself opts the run into coverage - /// ingestion (used when the CLI flag is unset and no `coverage.*` - /// selector/threshold asked): explicit reports or an explicit - /// `discover = true`. A section carrying only tuning keys (e.g. - /// `stale-warning = false`) does not. - pub(crate) fn opts_in(&self) -> bool { - !self.reports.is_empty() || self.discover_key == Some(true) - } -} - -/// A configuration loading/validation error. -/// -/// Implements [`miette::Diagnostic`]: where the mistake maps to a spot -/// in the TOML source, the diagnostic carries the file as -/// `source_code` plus a label pointing at the offending key, and a -/// `help:` suggestion. Render with [`render_config_error`]. -/// -/// The payload is boxed so `Result<_, ConfigError>` stays -/// pointer-sized on the happy path (clippy `result_large_err`). -#[derive(Debug)] -pub struct ConfigError(Box); - -#[derive(Debug)] -struct ConfigErrorInner { - message: String, - help: Option, - source_code: Option>, - labels: Vec, -} - -impl ConfigError { - fn new(message: impl Into) -> Self { - Self(Box::new(ConfigErrorInner { - message: message.into(), - help: None, - source_code: None, - labels: Vec::new(), - })) - } - - fn with_help(mut self, help: impl Into) -> Self { - self.0.help = Some(help.into()); - self - } -} - -impl fmt::Display for ConfigError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0.message) - } -} - -impl core::error::Error for ConfigError {} - -impl miette::Diagnostic for ConfigError { - fn code(&self) -> Option> { - Some(Box::new("mehen::config")) - } - - fn help(&self) -> Option> { - self.0 - .help - .as_ref() - .map(|help| Box::new(help) as Box) - } - - fn source_code(&self) -> Option<&dyn miette::SourceCode> { - self.0 - .source_code - .as_ref() - .map(|source| source as &dyn miette::SourceCode) - } - - fn labels(&self) -> Option + '_>> { - if self.0.labels.is_empty() { - None - } else { - Some(Box::new(self.0.labels.iter().cloned())) - } - } -} - -/// Builds [`ConfigError`]s that point back into the configuration -/// source. Spans come straight from the span-preserving TOML parse -/// tree ([`toml::de::DeTable`]), so every label points at the exact -/// occurrence — never at a same-spelled key elsewhere in the file. -struct ErrorContext<'a> { - text: &'a str, - path: &'a Path, -} - -impl ErrorContext<'_> { - fn named_source(&self) -> NamedSource { - NamedSource::new(self.path.display().to_string(), self.text.to_string()) - } - - /// An error without a source span (e.g. structural problems that - /// have no single key to point at). - fn error(&self, message: impl Into) -> ConfigError { - ConfigError::new(message) - } - - /// An error labeled at an exact byte range from the parse tree. - fn error_at( - &self, - span: std::ops::Range, - label: impl Into, - message: impl Into, - ) -> ConfigError { - let mut error = ConfigError::new(message); - error.0.source_code = Some(self.named_source()); - error.0.labels = vec![LabeledSpan::at(span, label.into())]; - error - } -} - -/// One crossed threshold: the measured value, the configured limit, -/// and enough context to render an actionable report line. Serialized -/// verbatim into `mehen diff --output-format json` under -/// `threshold_violations` so machine consumers (e.g. the GitHub -/// Action) can distinguish a quality-gate exit from an analysis -/// failure. -#[derive(Debug, Clone, serde::Serialize)] -pub struct ThresholdBreach { - /// Display path of the offending file. - pub path: String, - /// The metric's dotted key path within [`ThresholdBreach::source_table`] - /// (e.g. `loc.lloc`). Derived from the parse tree, so every TOML - /// spelling — dotted keys, nested headers, inline tables, quoting, - /// escapes — reports the same path. - pub metric: String, - /// Measured value at the evaluated (head) side. - pub value: f64, - /// Configured limit. - pub limit: f64, - /// Whether the limit is a maximum (`HigherIsWorse`) or a minimum - /// (`HigherIsBetter`). - pub polarity: Polarity, - /// Key path of the threshold table that set the limit — - /// `thresholds`, or `languages.py.thresholds` with the language - /// alias preserved (it is a real parsed key, not a spelling - /// variant). Rendered as `set by ` in the report; combined - /// with [`ThresholdBreach::metric`] it forms the entry's full - /// configuration key path. - pub source_table: String, -} - -/// One configured limit: the dotted metric path and the table it sits -/// in (both parse-tree data, for reporting) plus the numeric limit. -/// Keyed by canonical metric key in the policy tables. -#[derive(Debug, Clone)] -struct ThresholdEntry { - /// Dotted metric path within `table` (e.g. `loc.lloc`) — every - /// TOML spelling of the same entry normalizes to this path. - spelling: String, - /// Key path of the owning threshold table (`thresholds`, - /// `languages.py.thresholds` with the alias preserved). - table: String, - limit: f64, -} - -/// Per-metric limits: a global table plus per-language overrides. -/// Tables are keyed by *canonical* metric key (the published -/// spelling), so `cognitive` and `cognitive.sum` are one logical -/// threshold everywhere: duplicate detection, override resolution, -/// and output-column matching. -#[derive(Debug, Clone, Default)] -pub struct ThresholdPolicy { - global: BTreeMap, - /// Sorted by canonical language id for deterministic iteration. - per_language: Vec<(Language, BTreeMap)>, -} - -impl ThresholdPolicy { - /// True when no thresholds are configured at all. - pub fn is_empty(&self) -> bool { - self.global.is_empty() && self.per_language.iter().all(|(_, t)| t.is_empty()) - } - - /// Whether any configured metric name (global or per-language) - /// satisfies the predicate — e.g. "is any `coverage.*` threshold - /// configured?" for the lazy coverage-ingestion trigger. Names are - /// canonical at this point. - pub(crate) fn any_metric(&self, predicate: impl Fn(&str) -> bool) -> bool { - self.global.keys().map(String::as_str).any(&predicate) - || self - .per_language - .iter() - .any(|(_, thresholds)| thresholds.keys().map(String::as_str).any(&predicate)) - } - - /// The effective `canonical metric → entry` map for one language: - /// the language override wins over the global limit, metric by - /// metric. - fn resolved_for(&self, language: Language) -> BTreeMap<&str, &ThresholdEntry> { - let mut resolved: BTreeMap<&str, &ThresholdEntry> = self - .global - .iter() - .map(|(canonical, entry)| (canonical.as_str(), entry)) - .collect(); - if let Some((_, overrides)) = self.per_language.iter().find(|(l, _)| *l == language) { - for (canonical, entry) in overrides { - resolved.insert(canonical.as_str(), entry); - } - } - resolved - } - - /// Evaluate the policy against one file's root metric set. - /// - /// `only_metrics` restricts evaluation to the metrics a command - /// actually reports (`mehen diff` / `mehen top-offenders` pass - /// their selected column names; `mehen metrics` passes `None` - /// because its report carries the full metric set). Matching is - /// canonical on both sides, so a configured `cognitive.sum` gates - /// a selected `cognitive` column — they read the same published - /// key. - /// - /// A threshold whose metric the space does not publish is - /// skipped: an absent measurement must not be compared as `0.0` — - /// under a higher-is-better limit that would fabricate a - /// violation, under higher-is-worse it would fabricate a pass. - pub fn evaluate( - &self, - path: &str, - language: Language, - root: &MetricSpace, - only_metrics: Option<&[&str]>, - ) -> Vec { - let selected: Option> = - only_metrics.map(|names| names.iter().map(|name| canonical_for_match(name)).collect()); - let mut breaches = Vec::new(); - for (canonical, entry) in self.resolved_for(language) { - if let Some(selected) = &selected - && !selected.iter().any(|name| name == canonical) - { - continue; - } - let Some(value) = root - .metrics - .get(&MetricKey::new(canonical)) - .map(|v| v.as_f64()) - else { - continue; - }; - // Undefined measurements publish as NaN (e.g. interface - // averages over a zero interface count): NaN compares - // false under every polarity, which would silently pass - // the gate — skip them as unmeasurable instead. - if !value.is_finite() { - continue; - } - if !value_is_measurable(root, canonical) { - continue; - } - let polarity = polarity_for_metric(canonical); - let violated = match polarity { - Polarity::HigherIsWorse => value > entry.limit, - Polarity::HigherIsBetter => value < entry.limit, - }; - if violated { - breaches.push(ThresholdBreach { - path: path.to_string(), - metric: entry.spelling.clone(), - value, - limit: entry.limit, - polarity, - source_table: entry.table.clone(), - }); - } - } - breaches - } -} - -/// Whether a present metric value is a real measurement for this -/// space, as opposed to a published N/A sentinel. -/// -/// - `sql.modularity_health` emits `0.0` when the file has no CTEs -/// (the score is only meaningful for CTE-bearing files, per -/// `mehen-sql::composite`); applicability is read from the -/// co-published `sql.cte.count`. -/// - `halstead.level` (`L = 1/D`) emits `0.0` when the difficulty is -/// zero — an empty or token-free file where the ratio is undefined; -/// applicability is read from the co-published -/// `halstead.difficulty`. -/// -/// Gating a sentinel under a higher-is-better minimum would fail -/// every inapplicable file, while a genuine low score must keep -/// gating. -fn value_is_measurable(root: &MetricSpace, canonical: &str) -> bool { - let applicability_key = match canonical { - "sql.modularity_health" => "sql.cte.count", - "halstead.level" => "halstead.difficulty", - _ => return true, - }; - root.metrics - .get(&MetricKey::new(applicability_key)) - .is_none_or(|gate| gate.as_f64() > 0.0) -} - -/// Whether a configured limit is a minimum (higher-is-better metric) -/// or a maximum (everything else). Shares the ranking/diff polarity -/// source of truth ([`is_higher_is_better_metric`]): `mi.*`, the -/// Halstead program level, and the enumerated namespaced quality -/// scores are higher-is-better. Applied to canonical keys. -fn polarity_for_metric(name: &str) -> Polarity { - if is_higher_is_better_metric(name) { - Polarity::HigherIsBetter - } else { - Polarity::HigherIsWorse - } -} - -/// Load the configuration for this invocation. -/// -/// With `explicit` (the `--config` flag) the file must exist and -/// parse. Otherwise the configuration is discovered by walking from -/// the current working directory up to the enclosing git repository -/// root (or checking only the working directory outside a -/// repository); no file found means no configuration (`Ok(None)`), -/// which leaves every command's behavior unchanged. -pub fn load_config(explicit: Option<&Path>) -> Result, ConfigError> { - let path = match explicit { - Some(path) => { - if !path.is_file() { - return Err(ConfigError::new(format!( - "config file not found: `{}`", - path.display() - )) - .with_help("check the path passed to --config; it should point at a mehen.toml")); - } - path.to_path_buf() - } - None => { - let cwd = std::env::current_dir() - .map_err(|e| ConfigError::new(format!("cannot resolve current directory: {e}")))?; - match discover_config_path(&cwd) { - Some(path) => path, - None => return Ok(None), - } - } - }; - let text = std::fs::read_to_string(&path) - .map_err(|e| ConfigError::new(format!("failed to read `{}`: {e}", path.display())))?; - // Canonicalize for the report footer so "which file set this - // limit?" has an unambiguous answer even when discovery walked up - // from a nested working directory. - let display_path = std::fs::canonicalize(&path).unwrap_or(path); - parse_config(&text, &display_path).map(Some) -} - -/// Walk from `start` up to the enclosing git repository's work dir -/// (inclusive), returning the first configuration file found. -/// `mehen.toml` wins over `.mehen.toml` within the same directory -/// (with a warning when both exist). -/// -/// The repository root is the upper boundary: a config above it can -/// never belong to this project, and an unbounded walk to the -/// filesystem root would probe every ancestor and could pick up an -/// unrelated file (e.g. a stray `~/mehen.toml`). Outside a repository -/// only `start` itself is checked. -fn discover_config_path(start: &Path) -> Option { - // Resolve symlinks so the boundary comparison is exact — macOS - // tempdirs live behind `/var -> /private/var`, and `gix` reports - // the work dir as discovered, which may differ in spelling from - // `start`. - let start = std::fs::canonicalize(start).unwrap_or_else(|_| start.to_path_buf()); - let boundary = repository_boundary(&start).unwrap_or_else(|| start.clone()); - for dir in start.ancestors() { - let visible = dir.join(CONFIG_FILE_NAMES[0]); - let hidden = dir.join(CONFIG_FILE_NAMES[1]); - match (visible.is_file(), hidden.is_file()) { - (true, true) => { - log::warn!( - "both `mehen.toml` and `.mehen.toml` exist in {}; using `mehen.toml`", - dir.display() - ); - return Some(visible); - } - (true, false) => return Some(visible), - (false, true) => return Some(hidden), - (false, false) => {} - } - if dir == boundary { - break; - } - } - None -} - -/// The enclosing git repository's work dir, canonicalized — the -/// inclusive upper boundary for config discovery. `None` when `start` -/// is not inside a repository (or the repository is bare or -/// unreadable), which limits discovery to `start` itself. -/// -/// Uses `gix::discover` directly rather than -/// `mehen_git::open_repo_at`: the latter rejects shallow clones for -/// the history features, but a shallow CI checkout still has a -/// well-defined configuration boundary. -fn repository_boundary(start: &Path) -> Option { - let repo = gix::discover(start).ok()?; - let workdir = repo.workdir()?.to_path_buf(); - std::fs::canonicalize(&workdir).ok() -} - -/// Parse and validate configuration text. `path` is used for the -/// diagnostic source name and report messages. -/// -/// Parsing goes through the span-preserving [`toml::de::DeTable`] -/// tree, so every diagnostic label and every breach's `[table]` -/// attribution derives from the exact source location of the entry — -/// not from a text search that a same-spelled key elsewhere in the -/// file could defeat. -fn parse_config(text: &str, path: &Path) -> Result { - let ctx = ErrorContext { text, path }; - let root = match toml::de::DeTable::parse(text) { - Ok(root) => root, - Err(e) => { - let message = format!("invalid TOML: {}", e.message()); - let error = match e.span() { - Some(span) => ctx.error_at(span, "syntax error here", message), - None => ctx.error(message), - }; - return Err(error.with_help("fix the TOML syntax; see https://toml.io for the format")); - } - }; - - let mut global: BTreeMap = BTreeMap::new(); - let mut per_language: Vec<(Language, BTreeMap)> = Vec::new(); - let mut coverage: Option = None; - - for (key, value) in root.get_ref() { - let key_str: &str = key.get_ref().as_ref(); - match key_str { - "thresholds" => { - let table = expect_table(value, "thresholds", &ctx)?; - collect_thresholds(table, "thresholds", None, &mut global, &ctx)?; - } - "coverage" => { - let table = expect_table(value, "coverage", &ctx)?; - coverage = Some(collect_coverage(table, &ctx)?); - } - "languages" => { - let table = expect_table(value, "languages", &ctx)?; - for (lang_key, lang_value) in table { - let lang_str: &str = lang_key.get_ref().as_ref(); - // Path segments render TOML-quoted when needed: - // the accepted `c#` alias is not a valid bare key. - let lang_segment = toml_key_segment(lang_str); - let language = lang_str.parse::().map_err(|_| { - ctx.error_at( - lang_key.span(), - "not a recognized language", - format!("unknown language `{lang_str}` in [languages]"), - ) - .with_help( - "use a language identifier such as python, typescript, rust, go, … \ - (aliases like `py`, `ts`, `rb` are accepted)", - ) - })?; - if per_language.iter().any(|(l, _)| *l == language) { - return Err(ctx - .error_at( - lang_key.span(), - "same language configured twice", - format!( - "duplicate [languages.{lang_segment}] section — another key \ - already configures `{}`", - language.canonical() - ), - ) - .with_help( - "language aliases refer to the same language; keep one section \ - per language", - )); - } - let lang_ctx = format!("languages.{lang_segment}"); - let lang_table = expect_table(lang_value, &lang_ctx, &ctx)?; - let mut thresholds: BTreeMap = BTreeMap::new(); - for (sub_key, sub_value) in lang_table { - match sub_key.get_ref().as_ref() { - "thresholds" => { - let threshold_ctx = format!("{lang_ctx}.thresholds"); - let table = expect_table(sub_value, &threshold_ctx, &ctx)?; - collect_thresholds( - table, - &threshold_ctx, - Some(language), - &mut thresholds, - &ctx, - )?; - } - other => { - return Err(ctx - .error_at( - sub_key.span(), - "unrecognized key", - format!("unknown key `{other}` in [{lang_ctx}]"), - ) - .with_help(format!( - "expected `thresholds` (as in [{lang_ctx}.thresholds])" - ))); - } - } - } - per_language.push((language, thresholds)); - } - } - other => { - let mut help = "expected `thresholds`, `languages`, or `coverage`".to_string(); - if let Some(candidate) = - closest_candidate(other, &["thresholds", "languages", "coverage"]) - { - help.push_str(&format!("; did you mean `{candidate}`?")); - } - return Err(ctx - .error_at( - key.span(), - "unrecognized key", - format!("unknown top-level key `{other}`"), - ) - .with_help(help)); - } - } - } - - per_language.sort_by_key(|(language, _)| language.canonical()); - - Ok(ConfigFile { - path: path.to_path_buf(), - thresholds: ThresholdPolicy { - global, - per_language, - }, - coverage, - }) -} - -/// Parse the `[coverage]` section. Unknown keys are rejected with a -/// span-labeled error, like everywhere else in the file — a typo'd -/// `extra-pattern` must not silently disable the intended scan. -fn collect_coverage( - table: &toml::de::DeTable<'_>, - ctx: &ErrorContext<'_>, -) -> Result { - let mut config = CoverageConfig::default(); - for (key, value) in table { - let key_str: &str = key.get_ref().as_ref(); - match key_str { - "reports" => { - for entry in expect_string_array(value, "coverage.reports", ctx)? { - config.reports.push(camino::Utf8PathBuf::from(entry)); - } - } - "extra-patterns" => { - config.extra_patterns = expect_string_array(value, "coverage.extra-patterns", ctx)?; - } - "discover" => { - config.discover_key = Some(expect_bool(value, "coverage.discover", ctx)?); - } - "stale-warning" => { - config.stale_warning = expect_bool(value, "coverage.stale-warning", ctx)?; - } - other => { - let mut help = - "expected `reports`, `discover`, `extra-patterns`, or `stale-warning`" - .to_string(); - if let Some(candidate) = closest_candidate( - other, - &["reports", "discover", "extra-patterns", "stale-warning"], - ) { - help.push_str(&format!("; did you mean `{candidate}`?")); - } - return Err(ctx - .error_at( - key.span(), - "unrecognized key", - format!("unknown key `{other}` in [coverage]"), - ) - .with_help(help)); - } - } - } - Ok(config) -} - -fn expect_string_array( - value: &toml::Spanned>, - context: &str, - ctx: &ErrorContext<'_>, -) -> Result, ConfigError> { - let toml::de::DeValue::Array(items) = value.get_ref() else { - return Err(ctx.error_at( - value.span(), - "not an array", - format!( - "`{context}` must be an array of strings, got {}", - value.get_ref().type_str() - ), - )); - }; - let mut strings = Vec::with_capacity(items.len()); - for item in items { - let toml::de::DeValue::String(s) = item.get_ref() else { - return Err(ctx.error_at( - item.span(), - "not a string", - format!( - "`{context}` entries must be strings, got {}", - item.get_ref().type_str() - ), - )); - }; - strings.push(s.to_string()); - } - Ok(strings) -} - -fn expect_bool( - value: &toml::Spanned>, - context: &str, - ctx: &ErrorContext<'_>, -) -> Result { - match value.get_ref() { - toml::de::DeValue::Boolean(b) => Ok(*b), - other => Err(ctx.error_at( - value.span(), - "not a boolean", - format!( - "`{context}` must be `true` or `false`, got {}", - other.type_str() - ), - )), - } -} - -fn expect_table<'v, 'i>( - value: &'v toml::Spanned>, - context: &str, - ctx: &ErrorContext<'_>, -) -> Result<&'v toml::de::DeTable<'i>, ConfigError> { - match value.get_ref() { - toml::de::DeValue::Table(table) => Ok(table), - other => Err(ctx.error_at( - value.span(), - "not a table", - format!( - "`{context}` must be a table (as in [{context}]), got {}", - other.type_str() - ), - )), - } -} - -/// Flatten one thresholds table into canonical `metric → limit` -/// entries. -/// -/// TOML turns a dotted key (`loc.lloc = 500`) into nested tables, so -/// nested tables are folded back into dotted metric names — the -/// quoted spelling (`"loc.lloc" = 500`), the dotted spelling, a -/// nested header (`[thresholds.loc]` with `lloc = 500`), and an -/// inline table (`loc = { lloc = 500 }`) are all the same entry. -/// Because equivalence extends to canonical aliases (`cognitive` vs -/// `cognitive.sum`), two spellings of one logical metric in the same -/// table are rejected as a duplicate instead of one silently -/// overwriting the other. -fn collect_thresholds( - table: &toml::de::DeTable<'_>, - context: &str, - language: Option, - out: &mut BTreeMap, - ctx: &ErrorContext<'_>, -) -> Result<(), ConfigError> { - fn walk( - table: &toml::de::DeTable<'_>, - prefix: &str, - context: &str, - language: Option, - out: &mut BTreeMap, - ctx: &ErrorContext<'_>, - ) -> Result<(), ConfigError> { - for (key, value) in table { - let key_str: &str = key.get_ref().as_ref(); - let metric = if prefix.is_empty() { - key_str.to_string() - } else { - format!("{prefix}.{key_str}") - }; - // Attribution is pure parse-tree data: the threshold - // table's key path (`context`, language aliases - // preserved) plus the dotted metric path within it. TOML - // spellings — dotted keys, nested headers, inline tables, - // quoting, escapes — all normalize to the same paths, so - // the report never claims a literal spelling and cannot - // point at anything that does not exist semantically. - match value.get_ref() { - toml::de::DeValue::Integer(i) => { - // `as_str` keeps the lexical spelling: strip legal - // digit separators (`1_000`) and the radix prefix - // of hexadecimal/octal/binary spellings (`0x10`) - // before conversion — `from_str_radix` accepts - // bare digits only. - let raw = i.as_str().replace('_', ""); - let digits = raw - .strip_prefix("0x") - .or_else(|| raw.strip_prefix("0o")) - .or_else(|| raw.strip_prefix("0b")) - .unwrap_or(&raw); - let limit = i64::from_str_radix(digits, i.radix()) - .map(|v| v as f64) - .unwrap_or(f64::NAN); - insert_threshold(&metric, key, limit, context, language, out, ctx)?; - } - toml::de::DeValue::Float(f) => { - let limit = f - .as_str() - .replace('_', "") - .parse::() - .unwrap_or(f64::NAN); - insert_threshold(&metric, key, limit, context, language, out, ctx)?; - } - toml::de::DeValue::Table(nested) => { - walk(nested, &metric, context, language, out, ctx)?; - } - other => { - return Err(ctx - .error_at( - value.span(), - "limit must be numeric", - format!( - "`{context}.{metric}` must be a number (the metric's limit), \ - got {}", - other.type_str() - ), - ) - .with_help(format!("write a plain number, e.g. `{metric} = 15`"))); - } - } - } - Ok(()) - } - - walk(table, "", context, language, out, ctx) -} - -/// A key segment as it must be written in a TOML path: bare when the -/// characters allow it, quoted-and-escaped otherwise. The accepted -/// language alias `c#` cannot be a bare key (`#` starts a comment), so -/// a path like `languages."c#".thresholds` must quote it or the -/// reported configuration path could not identify the table. -fn toml_key_segment(segment: &str) -> String { - let bare = !segment.is_empty() - && segment - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-'); - if bare { - segment.to_string() - } else { - format!("\"{}\"", segment.replace('\\', "\\\\").replace('"', "\\\"")) - } -} - -/// Every language mehen can identify, for the "can any enabled -/// analyzer publish this key?" reachability check on global -/// thresholds. -const ALL_LANGUAGES: &[Language] = &[ - Language::Python, - Language::TypeScript, - Language::Tsx, - Language::JavaScript, - Language::Jsx, - Language::Php, - Language::Ruby, - Language::Rust, - Language::Go, - Language::Kotlin, - Language::Java, - Language::CSharp, - Language::PowerShell, - Language::C, - Language::Markdown, - Language::Sql, -]; - -/// Whether files of `language` can ever publish `canonical` onto their -/// root metric set. The engine-injected `history.*` family applies to -/// every language (it needs no analyzer); `sql.*` and `markdown.*` -/// belong to their owning analyzers (which publish nothing else); the -/// class-shape families (`npa`, `npm`, `wmc`) publish only when a -/// class-like construct exists — the C and Go grammars have none; and -/// any static key additionally requires the language's analyzer to be -/// compiled into this build. -fn language_can_publish(language: Language, canonical: &str) -> bool { - if canonical.starts_with("history.") { - // Git-only history keys need no analyzer; the static-dependent - // composites (`history.hotspot`, `history.churn.relative`) - // read analyzer inputs and are omitted when static analysis is - // unavailable — exactly what `selector_available` encodes. - return crate::history_metrics::selector_available(canonical, false, true) - || crate::AnalyzerRegistry::default_set().has_analyzer_for(language); - } - if canonical.starts_with("coverage.") { - // Coverage keys come from ingested reports, never from an - // analyzer: they are injected even into an empty metric space - // when static analysis is unavailable, so a build without the - // language's analyzer can still fire this gate. - return true; - } - if !crate::AnalyzerRegistry::default_set().has_analyzer_for(language) { - return false; - } - match language { - Language::Sql => canonical.starts_with("sql."), - Language::Markdown => canonical.starts_with("markdown."), - _ => { - if canonical.starts_with("sql.") || canonical.starts_with("markdown.") { - return false; - } - if is_class_family_key(canonical) && matches!(language, Language::C | Language::Go) { - return false; - } - // The interface-scoped members of the class families - // measure interface-like spaces (interfaces, traits); - // Python, Ruby, and PowerShell walkers never open one, so - // those overrides could never fire. - if is_interface_scoped_key(canonical) - && matches!( - language, - Language::Python | Language::Ruby | Language::PowerShell - ) - { - return false; - } - true - } - } -} - -/// The class-shape metric families, published only for files with -/// class-like constructs (classes, interfaces, traits, impls). -fn is_class_family_key(canonical: &str) -> bool { - ["npa", "npm", "wmc"] - .iter() - .any(|family| canonical == *family || canonical.starts_with(&format!("{family}."))) -} - -/// The interface-scoped members of the class families -/// (`npa.interfaces`, `npm.interface_methods`, `wmc.interfaces`, …), -/// which measure `SpaceKind::Interface` / `SpaceKind::Trait` spaces -/// exclusively. -fn is_interface_scoped_key(canonical: &str) -> bool { - let Some((_, member)) = canonical.split_once('.') else { - return false; - }; - is_class_family_key(canonical) && member.starts_with("interface") -} - -fn insert_threshold( - metric: &str, - key: &toml::Spanned>, - limit: f64, - context: &str, - language: Option, - out: &mut BTreeMap, - ctx: &ErrorContext<'_>, -) -> Result<(), ConfigError> { - let canonical = validate_metric_name(metric, key.span(), context, ctx)?; - // A global threshold no enabled analyzer can ever publish — e.g. - // `wmc` in a build whose only compiled grammars have no class-like - // constructs — would be a gate that can never fire. (`history.*` - // passes: it needs no analyzer.) - if language.is_none() - && !ALL_LANGUAGES - .iter() - .any(|candidate| language_can_publish(*candidate, &canonical)) - { - return Err(ctx - .error_at( - key.span(), - "unreachable in this build", - format!( - "`{metric}` in [{context}] can never fire: no analyzer compiled into \ - this build publishes it" - ), - ) - .with_help( - "enable the owning language feature (or use a metric one of the compiled \ - analyzers publishes)", - )); - } - // A language override naming a metric its files can never publish - // (`sql.*` under [languages.python], `cognitive` under - // [languages.sql]) would be a gate that can never fire. - if let Some(language) = language - && !language_can_publish(language, &canonical) - { - let help = if !crate::AnalyzerRegistry::default_set().has_analyzer_for(language) { - format!( - "this build was compiled without the {} analyzer; its files cannot be \ - analyzed, so this threshold can never fire (git-only `history.*` \ - thresholds remain valid)", - language.canonical() - ) - } else if canonical.starts_with("sql.") { - "`sql.*` metrics are published by the SQL analyzer; move the threshold to \ - [languages.sql.thresholds] or the global [thresholds] table (global limits apply \ - only to files that publish the metric)" - .to_string() - } else if canonical.starts_with("markdown.") { - "`markdown.*` metrics are published by the Markdown analyzer; move the threshold \ - to [languages.markdown.thresholds] or the global [thresholds] table" - .to_string() - } else if is_interface_scoped_key(&canonical) { - format!( - "the interface-scoped members measure interface-like spaces (interfaces, \ - traits); the {} grammar never opens one", - language.canonical() - ) - } else if is_class_family_key(&canonical) { - format!( - "the class-shape families (npa, npm, wmc) publish only for languages with \ - class-like constructs; the {} grammar has none", - language.canonical() - ) - } else { - format!( - "`{canonical}` is published by the source-code analyzers; {} files publish a \ - different metric family", - language.canonical() - ) - }; - return Err(ctx - .error_at( - key.span(), - "never published for this language", - format!( - "`{metric}` in [{context}] can never fire: {} files do not publish it", - language.canonical() - ), - ) - .with_help(help)); - } - if !limit.is_finite() { - return Err(ctx - .error_at( - key.span(), - "non-finite limit", - format!("`{context}.{metric}` must be a finite number, got `{limit}`"), - ) - .with_help("use a finite numeric limit; `inf` and `nan` cannot gate a metric")); - } - if let Some(existing) = out.get(&canonical) { - let spelled = if existing.spelling == metric { - format!("`{metric}` appears twice") - } else { - format!( - "`{metric}` and `{}` are spellings of the same metric (`{canonical}`)", - existing.spelling - ) - }; - return Err(ctx - .error_at( - key.span(), - "duplicate threshold", - format!("duplicate threshold for `{canonical}` in [{context}]: {spelled}"), - ) - .with_help( - "keep one limit per metric and table; contradictory duplicates would silently \ - disable the stricter gate", - )); - } - out.insert( - canonical, - ThresholdEntry { - spelling: metric.to_string(), - table: context.to_string(), - limit, - }, - ); - Ok(()) -} - -/// Validate a configured metric name and return its canonical -/// published key. A name no analyzer can publish is rejected at load -/// time with a suggestion — otherwise the threshold would be a gate -/// that can never fire. `span` is the key's exact source location. -fn validate_metric_name( - name: &str, - span: std::ops::Range, - context: &str, - ctx: &ErrorContext<'_>, -) -> Result { - match canonical_metric_key(name) { - Ok(canonical) => Ok(canonical), - Err(ResolveError::UnknownHistory) => Err(ctx - .error_at( - span, - "not a history metric", - format!("unknown history metric `{name}` in [{context}]"), - ) - .with_help(format!( - "the fixed `history.*` family is: {}", - keys::HISTORY_ALL.join(", ") - ))), - Err(ResolveError::UnknownCoverage) => Err(ctx - .error_at( - span, - "not a coverage metric", - format!("unknown coverage metric `{name}` in [{context}]"), - ) - .with_help(format!( - "the fixed `coverage.*` family is: {}", - keys::COVERAGE_ALL.join(", ") - ))), - #[cfg(not(feature = "lang-sql"))] - Err(ResolveError::UnavailableNamespace) => Err(ctx - .error_at( - span, - "unavailable in this build", - format!("unavailable metric `{name}` in [{context}]"), - ) - .with_help( - "this build was compiled without the SQL analyzer (`lang-sql` feature); a \ - `sql.*` threshold could never fire", - )), - Err(ResolveError::UnknownNamespaced) => { - let candidates = namespaced_candidates(name); - let help = match closest_candidate(name, candidates) { - Some(candidate) => format!("did you mean `{candidate}`?"), - None => format!( - "the analyzer that owns this namespace never publishes `{name}`; see \ - the metric reference for the published keys" - ), - }; - Err(ctx - .error_at( - span, - "not a published metric", - format!("unknown metric `{name}` in [{context}]"), - ) - .with_help(help)) - } - Err(ResolveError::Unknown) => { - let mut candidates: Vec<&str> = PUBLISHED_METRIC_KEYS.to_vec(); - candidates.extend_from_slice(keys::HISTORY_ALL); - candidates.extend_from_slice(keys::COVERAGE_ALL); - // A name whose family publishes members gets the family - // listing (`mi` → `mi.visual_studio`, …): an edit-distance - // pick like `wmc` for `mi` would point away from the - // obvious intent. - let help = match family_members(name) { - Some(members) => format!( - "no analyzer publishes `{name}`; its family publishes: {}", - members.join(", ") - ), - None => match closest_candidate(name, &candidates) { - Some(candidate) => format!("did you mean `{candidate}`?"), - None => "use a key mehen publishes: the source-code families \ - (cognitive, cyclomatic, loc.*, halstead.*, mi.*, abc, nargs, \ - nexit, nom.*, npa.*, npm.*, wmc), the fixed `history.*` and \ - `coverage.*` keys, or a namespaced `sql.*` / `markdown.*` key" - .to_string(), - }, - }; - Err(ctx - .error_at( - span, - "not a published metric", - format!("unknown metric `{name}` in [{context}]"), - ) - .with_help(help)) - } - } -} - -/// The published-key candidates for a namespaced (`sql.*` / -/// `markdown.*`) suggestion, from the owning analyzer's catalogue. -fn namespaced_candidates(name: &str) -> &'static [&'static str] { - if name.starts_with("sql.") { - #[cfg(feature = "lang-sql")] - { - return mehen_sql::PUBLISHED_METRIC_KEYS; - } - } - if name.starts_with("markdown.") { - return mehen_markdown::PUBLISHED_METRIC_KEYS; - } - &[] -} - -/// Published keys sharing the name's family (`mi` → `mi.visual_studio`, -/// `mi.original`, `mi.sei`; `cognitive.maximum` → the `cognitive` -/// members). Drives the help text for near-miss names too far away for -/// the edit-distance suggestion. -fn family_members(name: &str) -> Option> { - let base = name.split('.').next().unwrap_or(name); - let members: Vec<&'static str> = PUBLISHED_METRIC_KEYS - .iter() - .copied() - .filter(|key| *key == base || key.starts_with(&format!("{base}."))) - .collect(); - if members.is_empty() { - None - } else { - Some(members) - } -} - -/// The candidate within edit distance 2 of `name`, if any (ties break -/// toward the earlier candidate). -fn closest_candidate<'c>(name: &str, candidates: &[&'c str]) -> Option<&'c str> { - let mut best: Option<(usize, &str)> = None; - for candidate in candidates { - let distance = levenshtein(name, candidate); - if distance <= 2 && best.is_none_or(|(d, _)| distance < d) { - best = Some((distance, candidate)); - } - } - best.map(|(_, candidate)| candidate) -} - -fn levenshtein(a: &str, b: &str) -> usize { - let a: Vec = a.chars().collect(); - let b: Vec = b.chars().collect(); - let mut row: Vec = (0..=b.len()).collect(); - for (i, ca) in a.iter().enumerate() { - let mut previous_diagonal = row[0]; - row[0] = i + 1; - for (j, cb) in b.iter().enumerate() { - let substitution = previous_diagonal + usize::from(ca != cb); - previous_diagonal = row[j + 1]; - row[j + 1] = substitution.min(row[j] + 1).min(previous_diagonal + 1); - } - } - row[b.len()] -} - -/// The threshold violation report: a single diagnostic whose body -/// groups violations per file. The graphical handler renders the body -/// under a `│` gutter with the summary marked `×` and the guidance as -/// `help:`. -#[derive(Debug, miette::Diagnostic)] -#[diagnostic(code(mehen::thresholds))] -struct ThresholdReport { - message: String, - #[help] - help: Option, -} - -impl fmt::Display for ThresholdReport { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.message) - } -} - -impl core::error::Error for ThresholdReport {} - -/// Sort breaches by path then metric — the deterministic order shared -/// by the stderr report and the JSON `threshold_violations` payload. -pub(crate) fn sort_breaches(breaches: &mut [ThresholdBreach]) { - breaches.sort_by(|a, b| { - (a.path.as_str(), a.metric.as_str()).cmp(&(b.path.as_str(), b.metric.as_str())) - }); -} - -/// Render the violation report printed to stderr before exiting 1. -/// -/// Sorted by path then metric for determinism, grouped per file; each -/// line names the measured value, the crossed limit, and the exact -/// config table that set it (`[thresholds]` or -/// `[languages..thresholds]`, alias spelling preserved). -pub fn render_threshold_report(breaches: &mut [ThresholdBreach], config_path: &Path) -> String { - sort_breaches(breaches); - - let plural = if breaches.len() == 1 { "" } else { "s" }; - let mut message = format!( - "{} metric threshold violation{plural} (config: {})", - breaches.len(), - config_path.display() - ); - let mut current_path: Option<&str> = None; - for breach in breaches.iter() { - if current_path != Some(breach.path.as_str()) { - current_path = Some(breach.path.as_str()); - message.push_str(&format!("\n\n{}", breach.path)); - } - let comparison = match breach.polarity { - Polarity::HigherIsWorse => format!("exceeds max {}", format_number(breach.limit)), - Polarity::HigherIsBetter => format!("below min {}", format_number(breach.limit)), - }; - message.push_str(&format!( - "\n {} = {} — {comparison} (set by {})", - breach.metric, - format_number(breach.value), - breach.source_table - )); - } - let report = ThresholdReport { - message, - help: Some( - "adjust or remove the limit at the configuration path shown, or bring the file \ - back within it." - .to_string(), - ), - }; - render_diagnostic(&report) -} - -/// Render a configuration error for stderr: source snippet with a -/// caret at the offending key (when available) plus a `help:` line. -pub fn render_config_error(error: &ConfigError) -> String { - render_diagnostic(error) -} - -/// Render any diagnostic through miette's graphical handler. Colors -/// and unicode decorations engage only when stderr is a terminal and -/// `NO_COLOR` is unset, so piped/captured output stays clean. -fn render_diagnostic(diagnostic: &dyn miette::Diagnostic) -> String { - use std::io::IsTerminal; - - use miette::{GraphicalReportHandler, GraphicalTheme}; - - let colors = std::env::var_os("NO_COLOR").is_none() && std::io::stderr().is_terminal(); - let theme = if colors { - GraphicalTheme::unicode() - } else { - GraphicalTheme::unicode_nocolor() - }; - let mut rendered = String::new(); - GraphicalReportHandler::new_themed(theme) - .render_report(&mut rendered, diagnostic) - .expect("rendering a diagnostic into a String cannot fail"); - if !rendered.ends_with('\n') { - rendered.push('\n'); - } - rendered -} - -/// Shortest exact decimal for a metric value or limit (Rust's `f64` -/// `Display` round-trips): `23` stays `23`, `12.4` stays `12.4`, and a -/// close crossing like `0.504` over a `0.503` limit keeps every digit -/// instead of rounding both sides to an impossible-looking `0.50 > -/// 0.50`. -fn format_number(v: f64) -> String { - format!("{v}") -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{SourceSpan, SpaceId, SpaceKind}; - - fn parse(text: &str) -> Result { - parse_config(text, Path::new("mehen.toml")) - } - - /// The full rendered diagnostic (message + snippet + help), as the - /// CLI would print it with captured (non-terminal) stderr. - fn rendered(error: &ConfigError) -> String { - render_config_error(error) - } - - fn space_with(entries: &[(&str, f64)]) -> MetricSpace { - let mut space = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - for (key, value) in entries { - space.metrics.insert(*key, *value); - } - space - } - - fn global_limit(config: &ConfigFile, canonical: &str) -> Option { - config - .thresholds - .global - .get(canonical) - .map(|entry| entry.limit) - } - - #[test] - fn parses_global_thresholds_with_dotted_and_quoted_keys() { - let config = - parse("[thresholds]\ncognitive = 15\nloc.lloc = 500\n\"mi.visual_studio\" = 40.5\n") - .expect("valid config"); - // `cognitive` canonicalizes to its published rollup key. - assert_eq!(global_limit(&config, "cognitive.sum"), Some(15.0)); - assert_eq!(global_limit(&config, "loc.lloc"), Some(500.0)); - assert_eq!(global_limit(&config, "mi.visual_studio"), Some(40.5)); - } - - #[test] - #[cfg(feature = "lang-python")] - fn parses_language_override_with_alias() { - let config = parse("[languages.py.thresholds]\ncognitive = 10\n").expect("valid config"); - assert_eq!(config.thresholds.per_language.len(), 1); - let (language, thresholds) = &config.thresholds.per_language[0]; - assert_eq!(*language, Language::Python); - let entry = thresholds.get("cognitive.sum").expect("entry present"); - assert_eq!(entry.limit, 10.0); - // The table path preserves the alias exactly as written. - assert_eq!(entry.table, "languages.py.thresholds"); - } - - #[test] - fn empty_and_missing_tables_yield_empty_policy() { - assert!(parse("").expect("empty config").thresholds.is_empty()); - assert!( - parse("[thresholds]\n") - .expect("empty thresholds") - .thresholds - .is_empty() - ); - } - - #[test] - fn rejects_unknown_top_level_key_with_suggestion() { - let err = parse("[threshold]\ncognitive = 15\n").unwrap_err(); - assert!( - err.to_string() - .contains("unknown top-level key `threshold`") - ); - let rendered = rendered(&err); - assert!( - rendered.contains("did you mean `thresholds`?"), - "{rendered}" - ); - // The diagnostic points into the TOML source at the bad key. - assert!(rendered.contains("[threshold]"), "{rendered}"); - assert!(rendered.contains("mehen.toml"), "{rendered}"); - } - - #[test] - fn rejects_unknown_metric_with_suggestion() { - let err = parse("[thresholds]\ncognitve = 15\n").unwrap_err(); - assert!(err.to_string().contains("unknown metric `cognitve`")); - let rendered = rendered(&err); - assert!(rendered.contains("did you mean `cognitive`?"), "{rendered}"); - assert!(rendered.contains("cognitve = 15"), "{rendered}"); - } - - #[test] - fn rejects_unpublished_bare_family_root() { - // No analyzer publishes a bare `mi` key — accepting it would - // create a gate that can never fire. - let err = parse("[thresholds]\nmi = 40\n").unwrap_err(); - assert!(err.to_string().contains("unknown metric `mi`")); - let rendered = rendered(&err); - assert!( - rendered.contains("mi.visual_studio") - && rendered.contains("mi.original") - && rendered.contains("mi.sei"), - "help must list the family's published keys: {rendered}" - ); - } - - #[test] - fn rejects_unpublished_aggregate_spelling() { - // `cognitive.maximum` is a plausible near-miss of - // `cognitive.max` that no analyzer publishes. - let err = parse("[thresholds]\n\"cognitive.maximum\" = 1\n").unwrap_err(); - assert!( - err.to_string() - .contains("unknown metric `cognitive.maximum`") - ); - assert!( - rendered(&err).contains("cognitive.max"), - "help must point at the published spelling" - ); - } - - #[test] - fn rejects_duplicate_metric_across_spellings() { - // TOML sees two distinct keys; canonically they are one - // threshold — the stricter gate must not be silently - // overwritten. - let err = parse("[thresholds]\n\"loc.lloc\" = 1000000000\nloc.lloc = 0\n").unwrap_err(); - assert!( - err.to_string() - .contains("duplicate threshold for `loc.lloc`"), - "{err}" - ); - - let err = parse("[thresholds]\ncognitive = 5\n\"cognitive.sum\" = 6\n").unwrap_err(); - let message = err.to_string(); - assert!( - message.contains("duplicate threshold for `cognitive.sum`") - && message.contains("`cognitive.sum` and `cognitive` are spellings"), - "{message}" - ); - } - - #[test] - fn rejects_mistyped_history_metric_listing_family() { - let err = parse("[thresholds]\n\"history.commit_frequncy\" = 5\n").unwrap_err(); - assert!(err.to_string().contains("unknown history metric")); - assert!( - rendered(&err).contains("history.commit_frequency"), - "help must list the real family keys" - ); - } - - #[test] - fn rejects_non_numeric_limit() { - let err = parse("[thresholds]\ncognitive = \"high\"\n").unwrap_err(); - assert!(err.to_string().contains("must be a number")); - assert!( - rendered(&err).contains("write a plain number"), - "help must show the expected shape" - ); - } - - #[test] - fn rejects_non_finite_limit() { - let err = parse("[thresholds]\ncognitive = inf\n").unwrap_err(); - assert!(err.to_string().contains("finite")); - } - - #[test] - fn rejects_invalid_toml_syntax_with_span() { - let err = parse("[thresholds\ncognitive = 5\n").unwrap_err(); - assert!(err.to_string().contains("invalid TOML")); - assert!( - rendered(&err).contains("mehen.toml"), - "syntax errors must name the file" - ); - } - - #[test] - fn rejects_unknown_language() { - let err = parse("[languages.klingon.thresholds]\ncognitive = 5\n").unwrap_err(); - assert!(err.to_string().contains("unknown language `klingon`")); - assert!( - rendered(&err).contains("aliases like `py`, `ts`, `rb` are accepted"), - "help must explain accepted identifiers" - ); - } - - #[test] - #[cfg(feature = "lang-python")] - fn rejects_duplicate_language_via_alias() { - let err = parse( - "[languages.py.thresholds]\ncognitive = 5\n[languages.python.thresholds]\ncognitive = 6\n", - ) - .unwrap_err(); - assert!(err.to_string().contains("duplicate")); - } - - #[test] - fn rejects_unknown_key_inside_language_section() { - let err = parse("[languages.python.limits]\ncognitive = 5\n").unwrap_err(); - assert!(err.to_string().contains("unknown key `limits`")); - assert!( - rendered(&err).contains("[languages.python.thresholds]"), - "help must show the expected table name" - ); - } - - #[test] - #[cfg(feature = "lang-sql")] - fn accepts_namespaced_and_published_member_metrics() { - let config = parse( - "[thresholds]\n\"sql.change_risk_score\" = 3\n\"history.hotspot\" = 100\nnargs = 6\n\"cognitive.max\" = 20\n\"nom.functions.max\" = 9\n", - ) - .expect("valid config"); - assert_eq!(config.thresholds.global.len(), 5); - // Aggregate aliases canonicalize to the published spelling. - assert_eq!(global_limit(&config, "nom.functions_max"), Some(9.0)); - } - - #[test] - #[cfg(all(feature = "lang-python", feature = "lang-rust"))] - fn language_override_wins_over_global() { - let config = - parse("[thresholds]\ncognitive = 15\n[languages.python.thresholds]\ncognitive = 10\n") - .expect("valid config"); - let space = space_with(&[("cognitive.sum", 12.0)]); - // Python resolves the override limit (10) → 12 violates. - let breaches = config - .thresholds - .evaluate("a.py", Language::Python, &space, None); - assert_eq!(breaches.len(), 1); - assert_eq!(breaches[0].limit, 10.0); - assert_eq!(breaches[0].source_table, "languages.python.thresholds"); - // Rust keeps the global limit (15) → 12 passes. - let breaches = config - .thresholds - .evaluate("a.rs", Language::Rust, &space, None); - assert!(breaches.is_empty()); - } - - #[test] - fn evaluate_skips_metrics_the_space_does_not_publish() { - // `mi.visual_studio` is higher-is-better: a fabricated 0.0 for - // the missing key would fire a false violation. - let config = parse("[thresholds]\n\"mi.visual_studio\" = 40\n").expect("valid config"); - let space = space_with(&[("cognitive.sum", 5.0)]); - let breaches = config - .thresholds - .evaluate("a.py", Language::Python, &space, None); - assert!(breaches.is_empty()); - } - - #[test] - fn evaluate_flags_below_minimum_for_higher_is_better() { - let config = parse("[thresholds]\n\"mi.visual_studio\" = 40\n").expect("valid config"); - let space = space_with(&[("mi.visual_studio", 12.4)]); - let breaches = config - .thresholds - .evaluate("a.py", Language::Python, &space, None); - assert_eq!(breaches.len(), 1); - assert_eq!(breaches[0].polarity, Polarity::HigherIsBetter); - } - - #[test] - fn evaluate_respects_output_metric_filter() { - let config = - parse("[thresholds]\ncognitive = 5\n\"loc.lloc\" = 10\n").expect("valid config"); - let space = space_with(&[("cognitive.sum", 50.0), ("loc.lloc", 50.0)]); - let breaches = - config - .thresholds - .evaluate("a.py", Language::Python, &space, Some(&["cognitive"])); - assert_eq!(breaches.len(), 1); - assert_eq!(breaches[0].metric, "cognitive"); - } - - #[test] - fn evaluate_matches_filter_by_canonical_key() { - // A `cognitive.sum` threshold and a selected `cognitive` - // column read the same published key — the gate must fire - // even though the raw spellings differ. - let config = parse("[thresholds]\n\"cognitive.sum\" = 5\n").expect("valid config"); - let space = space_with(&[("cognitive.sum", 50.0)]); - let breaches = - config - .thresholds - .evaluate("a.py", Language::Python, &space, Some(&["cognitive"])); - assert_eq!(breaches.len(), 1, "canonical spellings must match"); - // The report keeps the user's spelling. - assert_eq!(breaches[0].metric, "cognitive.sum"); - } - - #[test] - fn evaluate_exact_limit_is_not_a_violation() { - let config = parse("[thresholds]\ncognitive = 15\n").expect("valid config"); - let space = space_with(&[("cognitive.sum", 15.0)]); - assert!( - config - .thresholds - .evaluate("a.py", Language::Python, &space, None) - .is_empty() - ); - } - - #[test] - fn aggregate_alias_reads_underscore_sub_bucket_key() { - // `nom.functions.max` canonicalizes to the published - // `nom.functions_max` at load time, so evaluation is a direct - // key read. - let config = parse("[thresholds]\n\"nom.functions.max\" = 5\n").expect("valid config"); - let space = space_with(&[("nom.functions_max", 9.0)]); - let breaches = config - .thresholds - .evaluate("a.py", Language::Python, &space, None); - assert_eq!(breaches.len(), 1); - assert_eq!(breaches[0].value, 9.0); - } - - #[test] - fn every_toml_spelling_normalizes_to_the_same_semantic_path() { - // Dotted keys (with legal whitespace, quoting, and escapes), - // nested headers, and inline tables are all the same TOML - // entry; the breach reports the parse-tree path (`loc.lloc` - // set by `thresholds`) for every one of them — no spelling - // recovery from source text is involved. - let space = space_with(&[("loc.lloc", 640.0)]); - for config_text in [ - "[thresholds]\nloc.lloc = 500\n", - "[thresholds]\n\"loc.lloc\" = 500\n", - "[thresholds]\nloc . lloc = 500\n", - "[thresholds]\n\"loc\" . lloc = 500\n", - "[thresholds]\nloc.\"lloc\" = 500\n", - // Basic-string escapes normalize in the parse tree - // (`"lo\u0063"` is the key `loc`). - "[thresholds]\n\"lo\\u0063\".lloc = 500\n", - "[thresholds.loc]\nlloc = 500\n", - "thresholds = { loc = { lloc = 500 } }\n", - "[thresholds]\nloc = { lloc = 500 }\n", - ] { - let config = parse(config_text).expect("valid config"); - let breaches = config - .thresholds - .evaluate("a.py", Language::Python, &space, None); - assert_eq!(breaches.len(), 1, "{config_text}"); - assert_eq!(breaches[0].metric, "loc.lloc", "{config_text}"); - assert_eq!(breaches[0].source_table, "thresholds", "{config_text}"); - } - } - - #[test] - #[cfg(feature = "lang-python")] - fn override_attribution_is_not_fooled_by_spellings_elsewhere() { - // The dotted `loc.lloc` occurrence in the *global* table must - // not affect the override's attribution: paths come from the - // parse tree, never from searching the source text. - let config = parse( - "[thresholds]\n\"loc.lloc\" = 1000\n\n[languages.py.thresholds.loc]\nlloc = 10\n", - ) - .expect("valid config"); - let space = space_with(&[("loc.lloc", 640.0)]); - let breaches = config - .thresholds - .evaluate("a.py", Language::Python, &space, None); - assert_eq!(breaches.len(), 1); - assert_eq!(breaches[0].metric, "loc.lloc"); - assert_eq!(breaches[0].source_table, "languages.py.thresholds"); - assert_eq!(breaches[0].limit, 10.0); - } - - #[test] - fn halstead_level_is_gated_as_a_minimum() { - // Program level is inverse difficulty (L = 1/D): larger is - // healthier, unlike the rest of the halstead family. - let config = parse("[thresholds]\n\"halstead.level\" = 0.2\n").expect("valid config"); - let below = space_with(&[("halstead.level", 0.1)]); - let breaches = config - .thresholds - .evaluate("a.py", Language::Python, &below, None); - assert_eq!(breaches.len(), 1); - assert_eq!(breaches[0].polarity, Polarity::HigherIsBetter); - let above = space_with(&[("halstead.level", 0.3)]); - assert!( - config - .thresholds - .evaluate("a.py", Language::Python, &above, None) - .is_empty() - ); - } - - #[test] - #[cfg(feature = "lang-sql")] - fn sql_modularity_na_sentinel_is_not_gated() { - let config = parse("[thresholds]\n\"sql.modularity_health\" = 50\n").expect("valid config"); - // No CTEs: the published 0.0 is an N/A sentinel, not a score — - // a minimum must not fail every ordinary non-CTE SQL file. - let na = space_with(&[("sql.modularity_health", 0.0), ("sql.cte.count", 0.0)]); - assert!( - config - .thresholds - .evaluate("q.sql", Language::Sql, &na, None) - .is_empty() - ); - // A CTE-bearing file still gates — including a genuine zero. - let scored = space_with(&[("sql.modularity_health", 0.0), ("sql.cte.count", 2.0)]); - assert_eq!( - config - .thresholds - .evaluate("q.sql", Language::Sql, &scored, None) - .len(), - 1 - ); - let low = space_with(&[("sql.modularity_health", 30.0), ("sql.cte.count", 2.0)]); - assert_eq!( - config - .thresholds - .evaluate("q.sql", Language::Sql, &low, None) - .len(), - 1 - ); - } - - #[test] - fn integer_and_float_digit_separators_parse() { - let config = parse("[thresholds]\ncognitive = 1_000\n\"loc.lloc\" = 1_500.5\n") - .expect("digit separators are legal TOML"); - assert_eq!(global_limit(&config, "cognitive.sum"), Some(1000.0)); - assert_eq!(global_limit(&config, "loc.lloc"), Some(1500.5)); - } - - #[test] - fn non_decimal_integer_spellings_parse() { - let config = parse( - "[thresholds]\ncognitive = 0x10\n\"loc.lloc\" = 0o20\n\"loc.sloc\" = 0b1000\nnargs = 0xdead_beef\n", - ) - .expect("hex/octal/binary integers are legal TOML"); - assert_eq!(global_limit(&config, "cognitive.sum"), Some(16.0)); - assert_eq!(global_limit(&config, "loc.lloc"), Some(16.0)); - assert_eq!(global_limit(&config, "loc.sloc"), Some(8.0)); - assert_eq!(global_limit(&config, "nargs"), Some(3735928559.0)); - } - - #[test] - #[cfg(feature = "lang-sql")] - fn rejects_unpublished_namespaced_metrics_with_suggestion() { - // The owning analyzers' catalogues validate `sql.*` and - // `markdown.*` names, so a typo cannot become a gate that - // never fires. - let err = parse("[thresholds]\n\"sql.modularit_health\" = 50\n").unwrap_err(); - assert!( - err.to_string() - .contains("unknown metric `sql.modularit_health`") - ); - assert!( - rendered(&err).contains("did you mean `sql.modularity_health`?"), - "{}", - rendered(&err) - ); - - let err = parse("[thresholds]\n\"markdown.links.borken\" = 1\n").unwrap_err(); - assert!( - err.to_string() - .contains("unknown metric `markdown.links.borken`") - ); - } - - #[test] - #[cfg(feature = "lang-sql")] - fn accepts_namespaced_dynamic_family_members() { - let config = parse( - "[thresholds]\n\"sql.statement.kind_count.select\" = 20\n\"sql.dialect.is_postgres\" = 1\n\"markdown.loc.tloc\" = 400\n", - ) - .expect("published dynamic-family keys are valid"); - assert_eq!(config.thresholds.global.len(), 3); - } - - #[test] - #[cfg(all( - feature = "lang-sql", - feature = "lang-python", - feature = "lang-c", - feature = "lang-go" - ))] - fn rejects_language_incompatible_thresholds() { - // A language override naming a metric its files can never - // publish would be a permanently dead gate. - let err = - parse("[languages.python.thresholds]\n\"sql.change_risk_score\" = 3\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - assert!( - rendered(&err).contains("published by the SQL analyzer"), - "{}", - rendered(&err) - ); - - let err = parse("[languages.sql.thresholds]\ncognitive = 5\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - - let err = parse("[languages.markdown.thresholds]\n\"loc.lloc\" = 100\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - - // Class-shape families need class-like constructs; the C and - // Go grammars have none, so those overrides are dead gates. - let err = parse("[languages.c.thresholds]\nwmc = 1\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - assert!( - rendered(&err).contains("class-like constructs"), - "{}", - rendered(&err) - ); - let err = parse("[languages.go.thresholds]\n\"npm.classes\" = 1\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - // Class-capable languages keep the whole catalogue. - assert!(parse("[languages.python.thresholds]\nwmc = 5\n").is_ok()); - // …except the interface-scoped members: Python classes exist, - // interface-like spaces do not. - let err = - parse("[languages.python.thresholds]\n\"npa.interfaces_average\" = 2\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - assert!( - rendered(&err).contains("never opens one"), - "{}", - rendered(&err) - ); - assert!(parse("[languages.python.thresholds]\n\"npa.classes_average\" = 2\n").is_ok()); - - // The owning language and the engine-injected history family - // stay valid, and global cross-language thresholds are - // untouched (they apply only to files that publish the key). - let config = parse( - "[thresholds]\n\"sql.change_risk_score\" = 3\n\n[languages.sql.thresholds]\n\"sql.cognitive_complexity\" = 40\n\n[languages.python.thresholds]\n\"history.hotspot\" = 100\n", - ) - .expect("compatible thresholds are valid"); - assert!(!config.thresholds.is_empty()); - } - - #[test] - #[cfg(not(feature = "lang-rust"))] - fn rejects_static_overrides_for_uncompiled_analyzers() { - // Feature-reduced builds cannot analyze the language at all, - // so any static override for it is a permanently dead gate — - // including the static-dependent history composites (hotspot - // reads the analyzer's cognitive sum). Git-only history keys - // need no analyzer and stay valid. - let err = parse("[languages.rust.thresholds]\ncognitive = 1\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - assert!( - rendered(&err).contains("compiled without the rust analyzer"), - "{}", - rendered(&err) - ); - let err = parse("[languages.rust.thresholds]\n\"history.hotspot\" = 9\n").unwrap_err(); - assert!(err.to_string().contains("can never fire"), "{err}"); - assert!(parse("[languages.rust.thresholds]\n\"history.churn.abs\" = 40\n").is_ok()); - } - - #[test] - fn rejects_ambiguous_bare_aliases_with_family_help() { - // Bare `loc` / `nom` are published root keys, but the Action - // ecosystem treats them as aliases for `loc.lloc` / - // `nom.functions` — configuring them would gate a different - // measurement than the name suggests. - let err = parse("[thresholds]\nloc = 100\n").unwrap_err(); - assert!(err.to_string().contains("unknown metric `loc`")); - assert!( - rendered(&err).contains("loc.sloc"), - "help must list the precise family members: {}", - rendered(&err) - ); - let err = parse("[thresholds]\nnom = 10\n").unwrap_err(); - assert!( - rendered(&err).contains("nom.functions"), - "{}", - rendered(&err) - ); - } - - #[test] - fn halstead_level_zero_difficulty_sentinel_is_not_gated() { - // `level = 1/D` is undefined at D == 0 and published as 0.0; - // a configured minimum must not fail empty/token-free files. - let config = parse("[thresholds]\n\"halstead.level\" = 0.2\n").expect("valid config"); - let sentinel = space_with(&[("halstead.level", 0.0), ("halstead.difficulty", 0.0)]); - assert!( - config - .thresholds - .evaluate("a.py", Language::Python, &sentinel, None) - .is_empty() - ); - // A measured low level on a real file still gates. - let low = space_with(&[("halstead.level", 0.05), ("halstead.difficulty", 20.0)]); - assert_eq!( - config - .thresholds - .evaluate("a.py", Language::Python, &low, None) - .len(), - 1 - ); - } - - #[test] - #[cfg(feature = "lang-csharp")] - fn csharp_alias_paths_render_toml_quoted() { - // `c#` cannot be a bare TOML key (`#` starts a comment): the - // reported path must quote it or it could not identify the - // table. - let config = parse("[languages.\"c#\".thresholds]\ncognitive = 1\n") - .expect("quoted alias section is valid"); - let space = space_with(&[("cognitive.sum", 5.0)]); - let breaches = config - .thresholds - .evaluate("a.cs", Language::CSharp, &space, None); - assert_eq!(breaches.len(), 1); - assert_eq!(breaches[0].source_table, "languages.\"c#\".thresholds"); - } - - #[test] - fn evaluate_skips_non_finite_measurements() { - // Undefined measurements publish as NaN (e.g. an interface - // average over a zero interface count); NaN compares false - // under both polarities and must be skipped as unmeasurable, - // not silently passed. - let config = parse("[thresholds]\ncognitive = 2\n\"mi.visual_studio\" = 40\n") - .expect("valid config"); - let space = space_with(&[("cognitive.sum", f64::NAN), ("mi.visual_studio", f64::NAN)]); - assert!( - config - .thresholds - .evaluate("a.ts", Language::TypeScript, &space, None) - .is_empty() - ); - } - - #[test] - fn report_preserves_precision_on_close_crossings() { - // Rounding both sides to two decimals would render an - // impossible-looking `0.5 — exceeds max 0.5`. - let mut breaches = vec![ThresholdBreach { - path: "a.py".to_string(), - metric: "sql.change_risk_score".to_string(), - value: 0.504, - limit: 0.503, - polarity: Polarity::HigherIsWorse, - source_table: "thresholds".to_string(), - }]; - let report = render_threshold_report(&mut breaches, Path::new("mehen.toml")); - assert!( - report.contains("sql.change_risk_score = 0.504 — exceeds max 0.503"), - "{report}" - ); - } - - #[test] - fn validator_accepts_every_key_real_analyzers_publish() { - // The `PUBLISHED_METRIC_KEYS` catalogue must not drift behind - // the publishers in `mehen-metrics::state`: analyze real - // sources (functions for the function families, classes for - // npa/npm/wmc) and require every published root key to - // canonicalize to itself. - use mehen_core::{AnalysisConfig, SourceFile}; - - let registry = crate::AnalyzerRegistry::default_set(); - let samples: &[(&str, Language, &str)] = &[ - ( - "sample.py", - Language::Python, - "def foo(x):\n if x:\n return 1\n return 2\n", - ), - ( - "Sample.java", - Language::Java, - "public class Sample {\n private int count;\n public int get() { return count > 0 ? count : 0; }\n}\n", - ), - ]; - for (name, language, body) in samples { - // Feature-reduced builds skip languages they don't compile. - let Some(analyzer) = registry.analyzer_for(*language) else { - continue; - }; - let source = SourceFile::new( - camino::Utf8PathBuf::from(*name), - *language, - (*body).to_string(), - ); - let analysis = analyzer - .analyze(&source, &AnalysisConfig::default()) - .expect("analysis succeeds"); - for (key, _) in analysis.root.metrics.iter() { - let key = key.as_str(); - // Published on the root but deliberately not - // configurable: the GitHub Action ecosystem treats - // these bare names as legacy aliases for `loc.lloc` / - // `nom.functions`, so accepting them would gate a - // different measurement than the name suggests. - if matches!(key, "loc" | "nom") { - assert!( - canonical_metric_key(key).is_err(), - "ambiguous alias `{key}` must stay non-configurable" - ); - continue; - } - let canonical = canonical_metric_key(key) - .unwrap_or_else(|_| panic!("published key `{key}` must validate")); - // The canonical form must be readable from the same - // space (bare `cognitive` aliases to its published - // `cognitive.sum` rollup — both keys carry the value). - assert!( - analysis - .root - .metrics - .get(&MetricKey::new(canonical.as_str())) - .is_some(), - "canonical `{canonical}` of published `{key}` must be readable" - ); - } - } - // The engine-published history family validates too. - for key in keys::HISTORY_ALL { - assert!(canonical_metric_key(key).is_ok(), "{key} must validate"); - } - } - - #[test] - fn report_orders_violations_and_names_config_source() { - let mut breaches = vec![ - ThresholdBreach { - path: "src/util.rs".to_string(), - metric: "mi.visual_studio".to_string(), - value: 12.4, - limit: 40.0, - polarity: Polarity::HigherIsBetter, - source_table: "thresholds".to_string(), - }, - ThresholdBreach { - path: "src/app/core.py".to_string(), - metric: "loc.lloc".to_string(), - value: 640.0, - limit: 500.0, - polarity: Polarity::HigherIsWorse, - source_table: "thresholds".to_string(), - }, - ThresholdBreach { - path: "src/app/core.py".to_string(), - metric: "cognitive".to_string(), - value: 23.0, - limit: 15.0, - polarity: Polarity::HigherIsWorse, - source_table: "languages.py.thresholds".to_string(), - }, - ]; - let report = render_threshold_report(&mut breaches, Path::new("/repo/mehen.toml")); - assert!( - report.contains("3 metric threshold violations (config: /repo/mehen.toml)"), - "{report}" - ); - // The language alias is preserved (it is a real parsed key) - // and the pointer is a semantic key path, not a spelling claim. - let cognitive = "cognitive = 23 — exceeds max 15 (set by languages.py.thresholds)"; - let lloc = "loc.lloc = 640 — exceeds max 500 (set by thresholds)"; - let mi = "mi.visual_studio = 12.4 — below min 40 (set by thresholds)"; - for line in [cognitive, lloc, mi, "src/app/core.py", "src/util.rs"] { - assert!(report.contains(line), "missing `{line}` in:\n{report}"); - } - // Deterministic ordering: path, then metric. - let position = |needle: &str| report.find(needle).expect("line present"); - assert!(position("src/app/core.py") < position(cognitive)); - assert!(position(cognitive) < position(lloc)); - assert!(position(lloc) < position("src/util.rs")); - assert!(position("src/util.rs") < position(mi)); - assert!(report.contains("help:"), "{report}"); - } - - #[test] - fn single_breach_report_uses_singular_wording() { - let mut breaches = vec![ThresholdBreach { - path: "a.py".to_string(), - metric: "cognitive".to_string(), - value: 3.0, - limit: 1.0, - polarity: Polarity::HigherIsWorse, - source_table: "thresholds".to_string(), - }]; - let report = render_threshold_report(&mut breaches, Path::new("mehen.toml")); - assert!( - report.contains("1 metric threshold violation (config: mehen.toml)"), - "{report}" - ); - } - - #[test] - fn discovery_walks_up_and_prefers_visible_name() { - let dir = tempfile::tempdir().expect("tempdir"); - init_git(dir.path()); - let nested = dir.path().join("a/b"); - std::fs::create_dir_all(&nested).expect("mkdirs"); - std::fs::write( - dir.path().join("mehen.toml"), - "[thresholds]\ncognitive = 1\n", - ) - .expect("write config"); - let found = discover_config_path(&nested).expect("config discovered"); - assert_eq!( - std::fs::canonicalize(found).expect("canonical found"), - std::fs::canonicalize(dir.path().join("mehen.toml")).expect("canonical expected") - ); - - // A closer `.mehen.toml` shadows the ancestor's `mehen.toml`. - std::fs::write(nested.join(".mehen.toml"), "[thresholds]\ncognitive = 2\n") - .expect("write hidden config"); - let found = discover_config_path(&nested).expect("config discovered"); - assert_eq!( - std::fs::canonicalize(found).expect("canonical found"), - std::fs::canonicalize(nested.join(".mehen.toml")).expect("canonical expected") - ); - } - - #[test] - fn discovery_stops_at_the_repository_root() { - // outer/mehen.toml sits *above* the repository at outer/repo: - // it cannot belong to the project and must not be picked up. - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write( - dir.path().join("mehen.toml"), - "[thresholds]\ncognitive = 1\n", - ) - .expect("write outer config"); - let repo = dir.path().join("repo"); - let nested = repo.join("src"); - std::fs::create_dir_all(&nested).expect("mkdirs"); - init_git(&repo); - - assert_eq!(discover_config_path(&nested), None); - - // A config at the repository root (the boundary itself) is - // still discovered. - std::fs::write(repo.join("mehen.toml"), "[thresholds]\ncognitive = 2\n") - .expect("write repo config"); - let found = discover_config_path(&nested).expect("repo-root config discovered"); - assert_eq!( - std::fs::canonicalize(found).expect("canonical found"), - std::fs::canonicalize(repo.join("mehen.toml")).expect("canonical expected") - ); - } - - #[test] - fn discovery_outside_a_repository_checks_only_the_start_directory() { - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write( - dir.path().join("mehen.toml"), - "[thresholds]\ncognitive = 1\n", - ) - .expect("write parent config"); - let nested = dir.path().join("a"); - std::fs::create_dir_all(&nested).expect("mkdirs"); - - // No repository anywhere up the tempdir chain: the parent's - // config is out of reach… - assert_eq!(discover_config_path(&nested), None); - - // …but a config in the start directory itself is found. - std::fs::write(nested.join("mehen.toml"), "[thresholds]\ncognitive = 2\n") - .expect("write local config"); - let found = discover_config_path(&nested).expect("local config discovered"); - assert_eq!( - std::fs::canonicalize(found).expect("canonical found"), - std::fs::canonicalize(nested.join("mehen.toml")).expect("canonical expected") - ); - } - - fn init_git(path: &Path) { - let output = std::process::Command::new("git") - .current_dir(path) - .args(["init", "-q", "-b", "main"]) - .output() - .expect("failed to run git init"); - assert!( - output.status.success(), - "git init failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - - #[test] - fn coverage_thresholds_validate_against_the_fixed_family() { - // Every real coverage key is accepted… - for key in keys::COVERAGE_ALL { - let text = format!("[thresholds]\n\"{key}\" = 80\n"); - let config = parse_config(&text, Path::new("mehen.toml")) - .unwrap_or_else(|e| panic!("{key} must validate: {e}")); - assert!(!config.thresholds.is_empty()); - } - // …including inside a per-language table: coverage comes from - // ingested reports, never from an analyzer, so the gate stays - // valid even in builds compiled without that language (the - // `history.*` reachability property). - let per_language = parse_config( - "[languages.rust.thresholds]\n\"coverage.line\" = 80\n", - Path::new("mehen.toml"), - ) - .expect("per-language coverage threshold must validate"); - assert!(!per_language.thresholds.is_empty()); - // …and a typo is rejected with the family listing, so the gate - // can never silently fail to fire. - let err = parse_config( - "[thresholds]\n\"coverage.lines\" = 80\n", - Path::new("mehen.toml"), - ) - .expect_err("typo'd coverage key must be rejected"); - let rendered = rendered(&err); - assert!( - rendered.contains("coverage.line"), - "help must list the fixed family: {rendered}" - ); - } - - #[test] - fn coverage_section_parses_and_validates() { - let config = parse_config( - "[coverage]\nreports = [\"ci/lcov.info\"]\ndiscover = false\n\ - extra-patterns = [\"qa/**/*.lcov\"]\nstale-warning = false\n", - Path::new("mehen.toml"), - ) - .expect("valid [coverage] section"); - let coverage = config.coverage.expect("section present"); - assert_eq!( - coverage.reports, - vec![camino::Utf8PathBuf::from("ci/lcov.info")] - ); - assert_eq!(coverage.discover_key, Some(false)); - assert!(!coverage.discover()); - assert_eq!(coverage.extra_patterns, vec!["qa/**/*.lcov".to_string()]); - assert!(!coverage.stale_warning); - // reports non-empty → the section opts the run in even though - // discovery is off. - assert!(coverage.opts_in()); - - // A tuning-only section does not opt in by itself. - let tuning = parse_config( - "[coverage]\nstale-warning = false\n", - Path::new("mehen.toml"), - ) - .expect("tuning-only section") - .coverage - .expect("section present"); - assert!(!tuning.opts_in()); - assert!(tuning.discover()); - } - - #[test] - fn coverage_section_rejects_unknown_and_mistyped_keys() { - let err = parse_config("[coverage]\nreport = [\"x\"]\n", Path::new("mehen.toml")) - .expect_err("unknown key must be rejected"); - let rendered = rendered(&err); - assert!( - rendered.contains("did you mean `reports`?"), - "suggestion expected: {rendered}" - ); - - let err = parse_config("[coverage]\ndiscover = \"yes\"\n", Path::new("mehen.toml")) - .expect_err("non-boolean discover must be rejected"); - assert!(rendered_contains(&err, "must be `true` or `false`")); - - let err = parse_config( - "[coverage]\nreports = \"lcov.info\"\n", - Path::new("mehen.toml"), - ) - .expect_err("non-array reports must be rejected"); - assert!(rendered_contains(&err, "array of strings")); - } - - fn rendered_contains(err: &ConfigError, needle: &str) -> bool { - let text = rendered(err); - assert!(text.contains(needle), "{text}"); - true - } -} diff --git a/crates/mehen-engine/src/coverage_metrics.rs b/crates/mehen-engine/src/coverage_metrics.rs deleted file mode 100644 index 6cfadb81..00000000 --- a/crates/mehen-engine/src/coverage_metrics.rs +++ /dev/null @@ -1,848 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Engine-level enrichment publishing the `coverage.*` metric family -//! onto per-file `MetricSpace`s from ingested coverage reports. -//! -//! Coverage metrics are report-scope: they cannot come from a -//! `LanguageAnalyzer` (which only sees one file's content), so the -//! orchestrators fold per-file coverage into each file's metric set -//! *after* static analysis — the same enrichment slot the `history.*` -//! family occupies. Ingestion (discovery, parsing, merging, path -//! matching) is comparatively expensive, so callers only trigger it -//! when coverage is actually requested — see [`names_want_coverage`] -//! and [`CoverageOpts`]. -//! -//! Unlike history, coverage is also injected **per function space**: -//! every `Function`/`Closure` space whose line span intersects the -//! report's line records receives its own `coverage.line` / -//! `coverage.branch` keys. That per-function attribution is what a -//! CRAP composite (`cyclomatic² × (1 − coverage/100)³ + cyclomatic`) -//! will read in a follow-up — the same injection-time-composite -//! pattern as `history.hotspot`. -//! -//! Availability honesty (the `history.*` doctrine, unchanged): a file -//! absent from every report publishes nothing and reads as -//! unmeasured; a file present with zero covered lines publishes an -//! honest `0.0`; a function span with no instrumented lines publishes -//! nothing. Each sub-family (`line`, `branch`, `function`) is -//! published only when its report actually measured that dimension — -//! a Go coverprofile has no branch records, so `coverage.branch` -//! stays absent rather than reading a fabricated 100% or 0%. - -use camino::{Utf8Path, Utf8PathBuf}; -use mehen_core::{MetricSpace, SpaceKind, keys}; -use mehen_coverage::{CoverageIndex, FileCoverage, FileMatch, SpanTotals}; - -/// Whether any requested metric name/key belongs to the `coverage.*` -/// family — the trigger for report discovery/parsing when the CLI -/// leaves coverage mode unset. -pub(crate) fn names_want_coverage<'a>(mut names: impl Iterator) -> bool { - // Only *valid* coverage keys trigger ingestion: a typo'd key can - // never read a published value, so discovering and parsing - // reports for it would be pure cost. - names.any(|name| name.starts_with("coverage.") && !is_unknown_coverage_key(name)) -} - -/// A `coverage`-rooted name outside the fixed family -/// (`mehen_core::keys::COVERAGE_ALL`) — including the bare family root -/// `coverage`, which is not a leaf. The CLI selector parser rejects -/// these up front; the public engine boundaries accept arbitrary -/// strings, so they must be checked again there. -pub(crate) fn is_unknown_coverage_key(name: &str) -> bool { - (name == "coverage" || name.starts_with("coverage.")) - && !mehen_core::keys::COVERAGE_ALL.contains(&name) -} - -/// Whether an engine-boundary selector cannot read a published -/// coverage value at all: a `coverage`-rooted key outside the fixed -/// family, **or** a valid key with a non-root aggregator — like -/// history, top-offenders/diff read root keys only, so -/// `coverage.line.max` parses (key `coverage.line`, aggregator `Max`) -/// yet can never resolve. -pub(crate) fn is_invalid_coverage_selector(selector: &mehen_core::MetricSelector) -> bool { - let key = selector.key.as_str(); - if key != "coverage" && !key.starts_with("coverage.") { - return false; - } - is_unknown_coverage_key(key) - || !matches!(selector.aggregator, mehen_core::SelectorAggregator::Root) -} - -/// Publish one covered/total dimension: the rate under `rate_key` -/// plus the two counters. Published only when the dimension was -/// actually measured (`total > 0`) — an absent dimension must read as -/// unmeasured, never as 0% or 100%. -fn publish( - metrics: &mut mehen_core::MetricSet, - totals: SpanTotals, - rate_key: &str, - covered_key: &str, - total_key: &str, -) { - let Some(rate) = totals.rate() else { - return; - }; - metrics.insert(rate_key, rate); - metrics.insert(covered_key, totals.covered as i64); - metrics.insert(total_key, totals.total as i64); -} - -/// Publish the `coverage.*` family onto a file's metric tree. -/// -/// The root (`Unit`) space receives the whole-file line, branch-arm, -/// and function dimensions; every nested `Function`/`Closure` space -/// receives line and branch dimensions scoped to its line span. -/// `file` must be normalized (guaranteed by the parser/merge layer). -pub(crate) fn inject_coverage_metrics(root: &mut MetricSpace, file: &FileCoverage) { - publish( - &mut root.metrics, - file.line_totals(), - keys::COVERAGE_LINE, - keys::COVERAGE_LINE_COVERED, - keys::COVERAGE_LINE_TOTAL, - ); - publish( - &mut root.metrics, - file.branch_totals(), - keys::COVERAGE_BRANCH, - keys::COVERAGE_BRANCH_COVERED, - keys::COVERAGE_BRANCH_TOTAL, - ); - publish( - &mut root.metrics, - file.function_totals(), - keys::COVERAGE_FUNCTION, - keys::COVERAGE_FUNCTION_COVERED, - keys::COVERAGE_FUNCTION_TOTAL, - ); - inject_into_children(&mut root.spaces, file); -} - -fn inject_into_children(spaces: &mut [MetricSpace], file: &FileCoverage) { - for space in spaces { - if matches!(space.kind, SpaceKind::Function | SpaceKind::Closure) - && space.span.start_line > 0 - && space.span.end_line >= space.span.start_line - { - publish( - &mut space.metrics, - file.span_line_totals(space.span.start_line, space.span.end_line), - keys::COVERAGE_LINE, - keys::COVERAGE_LINE_COVERED, - keys::COVERAGE_LINE_TOTAL, - ); - publish( - &mut space.metrics, - file.span_branch_totals(space.span.start_line, space.span.end_line), - keys::COVERAGE_BRANCH, - keys::COVERAGE_BRANCH_COVERED, - keys::COVERAGE_BRANCH_TOTAL, - ); - } - // Functions nest inside classes/impls (and inside each other): - // recurse unconditionally. - inject_into_children(&mut space.spaces, file); - } -} - -/// Whether a selector can be honestly valued given what backs the -/// metric space, coverage included: `coverage`-rooted selectors need a -/// matched coverage entry (and must be a known family key); everything -/// else defers to [`crate::history_metrics::selector_available`]. -pub(crate) fn selector_available_with_coverage( - name: &str, - statics: bool, - history: bool, - coverage: bool, -) -> bool { - if name == "coverage" || name.starts_with("coverage.") { - return coverage && !is_unknown_coverage_key(name); - } - crate::history_metrics::selector_available(name, statics, history) -} - -/// Enrich a single-file metrics report with coverage — the -/// `mehen metrics` entry point. -/// -/// Resolution: the `--coverage` flag, then the `[coverage]` config -/// section, then the lazy trigger (a configured `coverage.*` -/// threshold). Returns whether coverage data was injected. An -/// explicit report path that is missing or unparsable is an error; -/// everything else (no reports found, file not matched) degrades to -/// logs and an untouched report. -pub fn enrich_metrics_with_coverage( - report: &mut mehen_core::MetricsReport, - opts: &CoverageOpts, - config: Option<&crate::config_file::ConfigFile>, -) -> Result { - let mode = opts.mode().map_err(CoverageSetupError)?; - let coverage_config = config.and_then(|c| c.coverage.as_ref()); - // `mehen metrics` has no selector concept: the lazy trigger is a - // configured coverage threshold, which the enriched root will be - // gated against right after rendering. - let wanted = config.is_some_and(|c| { - c.thresholds - .any_metric(|name| name.starts_with("coverage.")) - }); - let Some(root_dir) = coverage_root_for(report.path.as_path()) else { - return Ok(false); - }; - let Some(context) = resolve_coverage(&mode, coverage_config, &[root_dir], wanted)? else { - return Ok(false); - }; - let Some(file_coverage) = coverage_for_file(&context, report.path.as_path()) else { - log::info!( - "no coverage data matched `{}` across {} ingested report file entr{}", - report.path, - context.index.len(), - if context.index.len() == 1 { "y" } else { "ies" } - ); - return Ok(false); - }; - inject_coverage_metrics(&mut report.root, &file_coverage); - Ok(true) -} - -// ─── Coverage input resolution (CLI flag + config + discovery) ─── - -/// The `--coverage` flag, shared by `mehen metrics` and -/// `mehen top-offenders`. -#[derive(Debug, Default, Clone, clap::Args)] -pub struct CoverageOpts { - /// Coverage input: 'auto' discovers report files (LCOV, Cobertura, - /// JaCoCo, Clover, Istanbul, Go coverprofile); 'off' disables - /// coverage; one or more report paths (--coverage=lcov.info) use - /// exactly those files. Bare `--coverage` means 'auto'. When - /// omitted, coverage loads lazily — only if a coverage.* metric or - /// threshold asks for it. - #[arg( - long = "coverage", - value_name = "PATH|auto|off", - num_args = 0..=1, - default_missing_value = "auto", - // The house negatable-flag style (`--ignore-git-attributes`), - // and load-bearing here: without it, `--coverage src/` would - // swallow a positional path as the flag value. - require_equals = true, - action = clap::ArgAction::Append - )] - coverage: Vec, -} - -/// The resolved coverage request. -#[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) enum CoverageMode { - /// No flag: load only when a `coverage.*` selector/threshold (or a - /// `[coverage]` config section) asks. - Unset, - /// Force ingestion (discovery + configured reports). - Auto, - /// Coverage disabled, regardless of config and selectors. - Off, - /// Exactly these report files; discovery does not run. - Explicit(Vec), -} - -impl CoverageOpts { - /// Parse the repeated flag values into a single mode. `auto`/`off` - /// are exclusive — with each other and with paths. - pub(crate) fn mode(&self) -> Result { - let mut auto = false; - let mut off = false; - let mut paths: Vec = Vec::new(); - for value in &self.coverage { - match value.as_str() { - "auto" => auto = true, - "off" | "none" => off = true, - path => paths.push(Utf8PathBuf::from(path)), - } - } - match (auto, off, paths.is_empty()) { - (false, false, true) => Ok(CoverageMode::Unset), - (true, false, true) => Ok(CoverageMode::Auto), - (false, true, true) => Ok(CoverageMode::Off), - (false, false, false) => Ok(CoverageMode::Explicit(paths)), - _ => Err( - "--coverage values conflict: 'auto', 'off', and explicit report paths are \ - mutually exclusive" - .to_string(), - ), - } - } -} - -/// Everything the orchestrators need after ingestion: the -/// calculate-once query index over every parsed, merged report, plus -/// the canonicalized discovery roots used to re-spell absolute query -/// paths repo-relative. Report inventory and discovery diagnostics -/// are surfaced as logs at resolve time (a structured -/// `coverage_ingestion` JSON block is a planned follow-up). -pub(crate) struct CoverageContext { - pub index: CoverageIndex, - /// Canonicalized root directories (repository workdirs), for the - /// repo-relative retry in [`coverage_for_file`]. - pub roots: Vec, -} - -impl CoverageContext { - pub(crate) fn new(index: CoverageIndex, roots: &[Utf8PathBuf]) -> Self { - Self { - index, - roots: roots - .iter() - .filter_map(|root| std::fs::canonicalize(root.as_std_path()).ok()) - .collect(), - } - } -} - -/// A fatal coverage-setup problem (user-attributable: an explicit -/// report path that is missing or unparsable). Discovered-report -/// problems never take this path — they degrade to warnings. -#[derive(Debug)] -pub struct CoverageSetupError(pub String); - -impl std::fmt::Display for CoverageSetupError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.0) - } -} - -impl std::error::Error for CoverageSetupError {} - -/// Read, sniff, and parse one report file. The single implementation -/// behind every ingestion path — the CLI's hard-error explicit reports, -/// discovered reports that degrade to warnings, and the library -/// boundary's diagnostic records — so the sniff window, format -/// detection, and parse behavior can never drift apart between them. -pub(crate) fn ingest_report( - path: &Utf8Path, -) -> Result<(mehen_coverage::CoverageFormat, mehen_coverage::CoverageData), String> { - let bytes = std::fs::read(path.as_std_path()) - .map_err(|e| format!("cannot read coverage report `{path}`: {e}"))?; - let head_len = bytes.len().min(4096); - let Some(format) = mehen_coverage::detect_format(path, &bytes[..head_len]) else { - return Err(format!( - "unrecognized coverage report format: `{path}` (supported: LCOV, Go coverprofile, \ - Istanbul JSON, JaCoCo/Clover/Cobertura XML)" - )); - }; - let data = mehen_coverage::parse_report(format, &bytes) - .map_err(|e| format!("failed to parse coverage report `{path}`: {e}"))?; - Ok((format, data)) -} - -/// Resolve the coverage request into a queryable index. -/// -/// * `mode` — the CLI flag ([`CoverageOpts::mode`]). -/// * `config` — the `[coverage]` section of `mehen.toml`, if any. -/// * `roots` — directories to discover under (typically the enclosing -/// repository workdir per analysis root). -/// * `wanted` — whether a `coverage.*` selector or threshold asked for -/// coverage (the lazy trigger when the flag is unset). -/// -/// Returns `Ok(None)` when coverage is off or nothing requested it. -pub(crate) fn resolve_coverage( - mode: &CoverageMode, - config: Option<&crate::config_file::CoverageConfig>, - roots: &[Utf8PathBuf], - wanted: bool, -) -> Result, CoverageSetupError> { - let config_reports: &[Utf8PathBuf] = config.map(|c| c.reports.as_slice()).unwrap_or(&[]); - let config_discover = config.is_none_or(crate::config_file::CoverageConfig::discover); - - let (explicit, run_discovery) = match mode { - CoverageMode::Off => return Ok(None), - CoverageMode::Explicit(paths) => (paths.clone(), false), - CoverageMode::Auto => (config_reports.to_vec(), config_discover), - CoverageMode::Unset => { - // Lazy path: a coverage.* selector/threshold, or a - // [coverage] config section that opts in, enables the run. - let config_opts_in = config.is_some_and(crate::config_file::CoverageConfig::opts_in); - if !wanted && !config_opts_in { - return Ok(None); - } - (config_reports.to_vec(), config_discover) - } - }; - - let mut parsed: Vec = Vec::new(); - let mut reports: Vec<(Utf8PathBuf, mehen_coverage::CoverageFormat)> = Vec::new(); - - // Explicit reports (CLI paths or config `reports`): every failure - // is a hard, user-attributable error — an explicit gate input that - // silently disappears is a broken CI gate. - for path in &explicit { - let (format, data) = ingest_report(path).map_err(CoverageSetupError)?; - reports.push((path.clone(), format)); - parsed.push(data); - } - - // Discovered reports: failures degrade to warnings — auto-discovery - // must never fail a run. - if run_discovery { - let outcome = - mehen_coverage_discovery::discover(&mehen_coverage_discovery::DiscoveryOptions { - roots: roots.to_vec(), - extra_patterns: config.map(|c| c.extra_patterns.clone()).unwrap_or_default(), - caps: mehen_coverage_discovery::DiscoveryCaps::default(), - }); - let head_time = newest_head_commit_time(roots); - for report in &outcome.reports { - // Skip a discovered file we already parsed explicitly. - if explicit.iter().any(|p| p == &report.path) { - continue; - } - // Discovered-report failures degrade to warnings; the shared - // ingest path keeps sniffing/parsing identical to the - // hard-error explicit branch above. - match ingest_report(&report.path) { - Ok((format, data)) => { - warn_if_stale(report, head_time, config); - reports.push((report.path.clone(), format)); - parsed.push(data); - } - Err(message) => { - log::warn!("skipping discovered coverage report: {message}"); - } - } - } - } - - if parsed.is_empty() { - log::info!("no coverage reports found; coverage metrics will be absent"); - return Ok(None); - } - - log::info!( - "coverage: ingesting {} report(s): {}", - reports.len(), - reports - .iter() - .map(|(p, f)| format!("{p} ({f})")) - .collect::>() - .join(", ") - ); - let merged = mehen_coverage::merge::merge_reports(parsed); - Ok(Some(CoverageContext::new( - CoverageIndex::build(merged), - roots, - ))) -} - -/// Ingest the explicit base-revision reports (`mehen diff -/// --base-coverage`) into a queryable index. -/// -/// Explicit-path semantics match [`CoverageMode::Explicit`]: every -/// failure is a hard, user-attributable error — a base report that -/// silently disappears would quietly demote every coverage trend to a -/// "new measurement". No discovery runs for the base side: the working -/// tree holds *head* artifacts, and reading them as the base -/// measurement would fabricate zero-delta trends. -/// -/// Staleness is the [`warn_if_stale`] doctrine applied to the base -/// side, judged against the *base commit's* committer time rather than -/// the head clock: a report written before the base commit existed -/// cannot describe that commit's code — recency-based retrieval -/// fallbacks (e.g. a CI cache prefix key falling back to an older -/// default-branch entry) land exactly here — so base-side line -/// attribution may be shifted. Warn-only, gated by the same -/// `stale-warning` config key. -pub(crate) fn resolve_base_coverage( - paths: &[Utf8PathBuf], - roots: &[Utf8PathBuf], - base_commit_time: Option, - config: Option<&crate::config_file::CoverageConfig>, -) -> Result, CoverageSetupError> { - if paths.is_empty() { - return Ok(None); - } - let mut parsed: Vec = Vec::new(); - let mut reports: Vec<(Utf8PathBuf, mehen_coverage::CoverageFormat)> = Vec::new(); - for path in paths { - let (format, data) = ingest_report(path).map_err(CoverageSetupError)?; - if config.is_none_or(|c| c.stale_warning) - && let Ok(mtime) = std::fs::metadata(path.as_std_path()).and_then(|m| m.modified()) - && let Some(base_time) = base_commit_time - && mtime < base_time - { - log::warn!( - "base coverage report `{path}` predates the base commit — it likely describes \ - an older revision, so base-side line attribution may be shifted (disable this \ - warning with `stale-warning = false` under [coverage])" - ); - } - reports.push((path.clone(), format)); - parsed.push(data); - } - log::info!( - "base coverage: ingesting {} report(s): {}", - reports.len(), - reports - .iter() - .map(|(p, f)| format!("{p} ({f})")) - .collect::>() - .join(", ") - ); - let merged = mehen_coverage::merge::merge_reports(parsed); - Ok(Some(CoverageContext::new( - CoverageIndex::build(merged), - roots, - ))) -} - -/// Warn-only staleness: a report older than the newest HEAD commit -/// across the roots likely predates the code under analysis, so line -/// attribution may be shifted. mtime-based and heuristic — never an -/// exclusion. -fn warn_if_stale( - report: &mehen_coverage_discovery::DiscoveredReport, - head_time: Option, - config: Option<&crate::config_file::CoverageConfig>, -) { - if !config.is_none_or(|c| c.stale_warning) { - return; - } - if let (Some(mtime), Some(head)) = (report.mtime, head_time) - && mtime < head - { - log::warn!( - "coverage report `{}` predates the newest analyzed commit — line attribution may \ - be shifted; regenerate the report (disable this warning with `stale-warning = \ - false` under [coverage])", - report.path - ); - } -} - -/// The newest HEAD committer timestamp across the discovery roots -/// (the deterministic "now" that survives CI clones). `None` outside -/// a repository or when HEAD is unborn. -fn newest_head_commit_time(roots: &[Utf8PathBuf]) -> Option { - roots - .iter() - .filter_map(|root| { - let repo = gix::discover(root.as_std_path()).ok()?; - let commit = repo.head_commit().ok()?; - let seconds = commit.time().ok()?.seconds; - u64::try_from(seconds) - .ok() - .map(|s| std::time::UNIX_EPOCH + std::time::Duration::from_secs(s)) - }) - .max() -} - -/// The discovery/repository root for one analyzed path: the enclosing -/// repository workdir when there is one (coverage artifacts -/// conventionally live at the repo root even when analyzing `./src`), -/// else the path's own directory. -pub(crate) fn coverage_root_for(path: &Utf8Path) -> Option { - let dir = if path.is_dir() { - path.to_path_buf() - } else { - path.parent()?.to_path_buf() - }; - let start = if dir.as_str().is_empty() { - Utf8PathBuf::from(".") - } else { - dir - }; - let workdir = gix::discover(start.as_std_path()) - .ok() - .and_then(|repo| repo.workdir().map(std::path::Path::to_path_buf)) - .and_then(|workdir| Utf8PathBuf::try_from(workdir).ok()); - Some(workdir.unwrap_or(start)) -} - -/// Look up a file's coverage, logging the ambiguous case. -/// -/// Two-step query: the path as spelled first; then — when it is -/// absolute (or resolves to be) — re-spelled relative to each -/// canonicalized root. The retry is what connects a *local* absolute -/// spelling to a report written on a *different* machine: neither -/// `/local/checkout/src/app.py` nor `/ci/work/repo/src/app.py` is a -/// component-suffix of the other, but the repo-relative `src/app.py` -/// is a suffix of both. Stripping is deliberately root-scoped (the -/// grcov `--prefix-dir` idea, automated) rather than a blanket -/// filename-only match, which would mis-attribute same-named files -/// (`src/util.py` vs `tests/util.py`) across directories. -pub(crate) fn coverage_for_file<'a>( - context: &'a CoverageContext, - path: &Utf8Path, -) -> Option> { - enum Resolution<'a> { - Found(std::borrow::Cow<'a, FileCoverage>), - Ambiguous(usize), - NotFound, - } - fn resolve<'a>(index: &'a CoverageIndex, query: &Utf8Path) -> Resolution<'a> { - match index.file(query) { - FileMatch::Found { coverage } => Resolution::Found(coverage), - FileMatch::Ambiguous { candidates } => Resolution::Ambiguous(candidates), - FileMatch::NotFound => Resolution::NotFound, - } - } - - let mut resolution = resolve(&context.index, path); - if matches!(resolution, Resolution::NotFound) - && let Ok(canonical) = std::fs::canonicalize(path.as_std_path()) - { - for root in &context.roots { - if let Ok(relative) = canonical.strip_prefix(root) - && let Some(relative) = camino::Utf8Path::from_path(relative) - { - resolution = resolve(&context.index, relative); - if !matches!(resolution, Resolution::NotFound) { - break; - } - } - } - } - - match resolution { - Resolution::Found(coverage) => Some(coverage), - Resolution::Ambiguous(candidates) => { - log::warn!( - "coverage for `{path}` is ambiguous ({candidates} report entries match with \ - equal specificity); treating the file as unmeasured" - ); - None - } - Resolution::NotFound => None, - } -} - -#[cfg(test)] -mod tests { - use mehen_core::{MetricSet, SourceSpan, SpaceId}; - use mehen_coverage::{BranchCoverage, FunctionCoverage, LineCoverage}; - - use super::*; - - fn space(kind: SpaceKind, start_line: u32, end_line: u32) -> MetricSpace { - MetricSpace { - id: SpaceId(0), - kind, - name: None, - span: SourceSpan { - start_byte: 0, - end_byte: 0, - start_line, - end_line, - }, - metrics: MetricSet::default(), - spaces: Vec::new(), - } - } - - fn sample_file() -> FileCoverage { - let mut file = FileCoverage::new("src/app.py".to_string()); - file.lines = vec![ - LineCoverage { - line_number: 1, - hit_count: 3, - }, - LineCoverage { - line_number: 5, - hit_count: 1, - }, - LineCoverage { - line_number: 6, - hit_count: 0, - }, - LineCoverage { - line_number: 12, - hit_count: 0, - }, - ]; - file.branches = vec![ - BranchCoverage { - line_number: 5, - branch_index: 0, - hit_count: 1, - }, - BranchCoverage { - line_number: 5, - branch_index: 1, - hit_count: 0, - }, - ]; - file.functions = vec![ - FunctionCoverage { - name: "hit".to_string(), - start_line: Some(5), - end_line: None, - hit_count: 1, - }, - FunctionCoverage { - name: "missed".to_string(), - start_line: Some(12), - end_line: None, - hit_count: 0, - }, - ]; - file.normalize(); - file - } - - fn read(metrics: &MetricSet, key: &str) -> f64 { - metrics - .get(&mehen_core::MetricKey::new(key)) - .map(|v| v.as_f64()) - .unwrap_or_else(|| panic!("missing key {key}")) - } - - #[test] - fn injects_all_three_dimensions_at_root() { - let mut root = space(SpaceKind::Unit, 1, 20); - inject_coverage_metrics(&mut root, &sample_file()); - - // 2 of 4 instrumentable lines hit. - assert_eq!(read(&root.metrics, keys::COVERAGE_LINE), 50.0); - assert_eq!(read(&root.metrics, keys::COVERAGE_LINE_COVERED), 2.0); - assert_eq!(read(&root.metrics, keys::COVERAGE_LINE_TOTAL), 4.0); - // 1 of 2 branch arms taken. - assert_eq!(read(&root.metrics, keys::COVERAGE_BRANCH), 50.0); - // 1 of 2 recorded functions executed. - assert_eq!(read(&root.metrics, keys::COVERAGE_FUNCTION), 50.0); - } - - #[test] - fn function_spaces_get_span_scoped_line_and_branch_coverage() { - let mut root = space(SpaceKind::Unit, 1, 20); - let mut class = space(SpaceKind::Class, 4, 15); - // `hit` spans lines 5..=8: lines 5 (hit) and 6 (missed). - class.spaces.push(space(SpaceKind::Function, 5, 8)); - // `missed` spans lines 12..=14: line 12 (missed). - class.spaces.push(space(SpaceKind::Function, 12, 14)); - root.spaces.push(class); - - inject_coverage_metrics(&mut root, &sample_file()); - - let class = &root.spaces[0]; - // Class spaces are not annotated (root + functions only)… - assert!( - class - .metrics - .get(&mehen_core::MetricKey::new(keys::COVERAGE_LINE)) - .is_none() - ); - // …but the functions nested inside them are. - let hit = &class.spaces[0]; - assert_eq!(read(&hit.metrics, keys::COVERAGE_LINE), 50.0); - assert_eq!(read(&hit.metrics, keys::COVERAGE_BRANCH), 50.0); - let missed = &class.spaces[1]; - assert_eq!(read(&missed.metrics, keys::COVERAGE_LINE), 0.0); - // No branch records within 12..=14 → dimension absent, not 0. - assert!( - missed - .metrics - .get(&mehen_core::MetricKey::new(keys::COVERAGE_BRANCH)) - .is_none() - ); - } - - #[test] - fn uninstrumented_function_span_publishes_nothing() { - // Lines 15..=19 have no instrumentable records: the function - // must read as unmeasured (the CRAP `--missing` policy hook), - // never as 0% or 100%. - let mut root = space(SpaceKind::Unit, 1, 20); - root.spaces.push(space(SpaceKind::Function, 15, 19)); - inject_coverage_metrics(&mut root, &sample_file()); - assert!( - root.spaces[0] - .metrics - .get(&mehen_core::MetricKey::new(keys::COVERAGE_LINE)) - .is_none() - ); - } - - #[test] - fn missing_dimension_stays_absent_at_root() { - // A Go coverprofile has line records only. - let mut file = FileCoverage::new("pkg/a.go".to_string()); - file.lines = vec![LineCoverage { - line_number: 1, - hit_count: 1, - }]; - file.normalize(); - let mut root = space(SpaceKind::Unit, 1, 5); - inject_coverage_metrics(&mut root, &file); - assert_eq!(read(&root.metrics, keys::COVERAGE_LINE), 100.0); - for absent in [keys::COVERAGE_BRANCH, keys::COVERAGE_FUNCTION] { - assert!( - root.metrics - .get(&mehen_core::MetricKey::new(absent)) - .is_none(), - "{absent} must stay absent" - ); - } - } - - #[test] - fn names_want_coverage_detects_family_keys() { - assert!(names_want_coverage( - ["cognitive", "coverage.line"].into_iter() - )); - assert!(!names_want_coverage( - ["cognitive", "history.churn.abs"].into_iter() - )); - // A typo'd coverage key must not trigger ingestion. - assert!(!names_want_coverage(["coverage.lines"].into_iter())); - assert!(!names_want_coverage(std::iter::empty())); - } - - #[test] - fn every_family_key_is_known() { - for key in mehen_core::keys::COVERAGE_ALL { - assert!(!is_unknown_coverage_key(key), "{key} must be known"); - } - assert!(is_unknown_coverage_key("coverage.lines")); - assert!(is_unknown_coverage_key("coverage.statement")); - // The bare family root is not a leaf and must not read the - // missing-key 0.0 fallback as an available metric. - assert!(is_unknown_coverage_key("coverage")); - assert!(!is_unknown_coverage_key("cognitive")); - } - - #[test] - fn bare_family_roots_are_rejected_at_the_engine_boundary() { - // `coverage` / `history` parse as bare keys with the Root - // aggregator; without explicit handling they would slip past - // the prefix guards and rank on fabricated zeros. - let coverage: mehen_core::MetricSelector = "coverage".parse().unwrap(); - assert!(is_invalid_coverage_selector(&coverage)); - assert!(!selector_available_with_coverage( - "coverage", true, true, true - )); - - let history: mehen_core::MetricSelector = "history".parse().unwrap(); - assert!(crate::history_metrics::is_invalid_history_selector( - &history - )); - assert!(!crate::history_metrics::selector_available( - "history", true, true - )); - } - - #[test] - fn coverage_mode_parsing() { - let mode = |values: &[&str]| CoverageOpts { - coverage: values.iter().map(ToString::to_string).collect(), - }; - assert_eq!(mode(&[]).mode().unwrap(), CoverageMode::Unset); - assert_eq!(mode(&["auto"]).mode().unwrap(), CoverageMode::Auto); - assert_eq!(mode(&["off"]).mode().unwrap(), CoverageMode::Off); - assert_eq!( - mode(&["lcov.info", "qa/coverage.xml"]).mode().unwrap(), - CoverageMode::Explicit(vec![ - Utf8PathBuf::from("lcov.info"), - Utf8PathBuf::from("qa/coverage.xml") - ]) - ); - assert!(mode(&["auto", "off"]).mode().is_err()); - assert!(mode(&["auto", "lcov.info"]).mode().is_err()); - } -} diff --git a/crates/mehen-engine/src/detection.rs b/crates/mehen-engine/src/detection.rs deleted file mode 100644 index 9174b08f..00000000 --- a/crates/mehen-engine/src/detection.rs +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use camino::Utf8Path; - -use mehen_core::Language; - -/// Detect a `Language` from a path's extension. -/// -/// 1.0 detection rules (rewrite plan §4.2): -/// - `.py` → Python (no `.pyi` until Phase 6 explicitly adds stub fixtures); -/// - `.ts/.mts/.cts` → TypeScript; `.js/.mjs/.cjs` → JavaScript; -/// - `.tsx` → TSX; `.jsx` → JSX (split out from TS in 1.0); -/// - `.md/.mdx` (and legacy variants) → Markdown; -/// - `.sql/.ddl/.dml` → SQL. -pub fn detect_language(path: &Utf8Path) -> Option { - let ext = path.extension()?.to_ascii_lowercase(); - let lang = match ext.as_str() { - "py" => Language::Python, - "ts" | "mts" | "cts" => Language::TypeScript, - "js" | "mjs" | "cjs" => Language::JavaScript, - "tsx" => Language::Tsx, - "jsx" => Language::Jsx, - "rs" => Language::Rust, - "go" => Language::Go, - "rb" => Language::Ruby, - "kt" | "kts" => Language::Kotlin, - "java" => Language::Java, - // `.csx` is a C# script file (dotnet-script / `csi`); it shares the - // compilation-unit grammar, so it routes to the same analyzer. - "cs" | "csx" => Language::CSharp, - "ps1" | "psm1" | "psd1" => Language::PowerShell, - "c" | "h" => Language::C, - "php" | "php3" | "php4" | "php5" | "php7" | "php8" | "phtml" => Language::Php, - "md" | "markdown" | "mdown" | "mkd" | "mkdn" | "mdx" => Language::Markdown, - "sql" | "ddl" | "dml" => Language::Sql, - _ => return None, - }; - Some(lang) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn detects_common_extensions() { - assert_eq!( - detect_language(Utf8Path::new("foo/bar.py")), - Some(Language::Python) - ); - assert_eq!( - detect_language(Utf8Path::new("FOO.MTS")), - Some(Language::TypeScript) - ); - assert_eq!(detect_language(Utf8Path::new("a.tsx")), Some(Language::Tsx)); - assert_eq!( - detect_language(Utf8Path::new("README.MD")), - Some(Language::Markdown) - ); - } - - #[test] - fn returns_none_for_unknown() { - assert_eq!(detect_language(Utf8Path::new("file.xyz")), None); - assert_eq!(detect_language(Utf8Path::new("Makefile")), None); - } -} diff --git a/crates/mehen-engine/src/diff.rs b/crates/mehen-engine/src/diff.rs deleted file mode 100644 index 27807487..00000000 --- a/crates/mehen-engine/src/diff.rs +++ /dev/null @@ -1,4037 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen diff` orchestrator. -//! -//! Walks `mehen-git`'s changed-file list, analyzes each file at base and -//! head, and assembles a `DiffReport` (the post-1.0 [`analyze_diff`] -//! entry point). The pre-1.0 CLI orchestrator [`run_diff`] lives in -//! this same module so the two share the [`has_blocking_diagnostic`] -//! gate. Per the rewrite plan §4.6, per-file analysis is the -//! parallelism unit; the implementation runs serially and follow-up -//! commits will switch to a thread-per-file pool. The Markdown -//! documentation diff renderer in `mehen-report` consumes this report. - -use std::io::Write; -use std::path::{Component, Path, PathBuf}; -use std::sync::Arc; - -use camino::{Utf8Component, Utf8PathBuf}; - -use mehen_core::{ - AnalysisConfig, DiagnosticSeverity, Language, LanguageAnalysis, MetricSpace, ParseDiagnostic, - SourceFile, Threshold, ThresholdEvaluation, -}; -use mehen_git::{ChangeStatus, GitError}; -use mehen_report::github_markdown_docs::{DocDiffFile, DocRenderCtx, render_doc_section}; - -use crate::ci; -use crate::concurrent_files::mk_globset; -use crate::coverage_metrics; -use crate::detection::detect_language; -use crate::git_attributes::GitAttributeFilter; -use crate::history_metrics; -use crate::metric_selector::{ - MetricSelector, Polarity as SelectorPolarity, coverage_line_selector, - default_selectors_for_language, metric_set_key_for, parse_metric_selectors, - read_metric as read_selector_metric, -}; -use crate::registry::AnalyzerRegistry; -use crate::top_offenders::read_metric; -use mehen_core::{ - AnalysisErrorRecord, DiffFile, DiffInput, DiffReport, DiffSide, ThresholdViolation, -}; - -/// Run `mehen diff` against the workspace and produce a report. -/// -/// Errors flow through the report's `analysis_errors` array (per rewrite -/// plan review §3.5: `analysis_errors` separate from -/// `threshold_violations`); only IO/git-fatal failures bubble up as -/// `Err` so callers can short-circuit the rendering step. -pub fn analyze_diff(input: DiffInput) -> Result { - let repo = mehen_git::open_repo().map_err(DiffError::Git)?; - analyze_diff_in_repo(input, &repo) -} - -struct RevisionGitAttributeFilters { - /// `None` when the base revision doesn't resolve locally (the - /// push-payload fallback after a force-push): baseline attributes - /// are unavailable, and deleted rows are then not attribute- - /// filtered rather than aborting the whole run. - base: Option, - head: GitAttributeFilter, -} - -impl RevisionGitAttributeFilters { - fn new( - repo: &gix::Repository, - from: &str, - to: &str, - ) -> Result> { - let base = if repo.rev_parse_single(from).is_ok() { - Some(GitAttributeFilter::from_revision(repo, from)?) - } else { - log::warn!( - "baseline Git attributes unavailable ({from} does not resolve locally); deleted files are not attribute-filtered" - ); - None - }; - Ok(Self { - base, - head: GitAttributeFilter::from_revision(repo, to)?, - }) - } - - fn excludes(&mut self, file: &mehen_git::ChangedFile) -> std::io::Result { - let filter = if file.status == ChangeStatus::Deleted { - match self.base.as_mut() { - Some(base) => base, - None => return Ok(false), - } - } else { - &mut self.head - }; - filter.excludes_relative_path(&file.path) - } - - /// Whether the base revision excludes `path`, for rename-source - /// eligibility. `None` baseline attributes exclude nothing. - fn base_excludes(&mut self, path: &Path) -> std::io::Result { - match self.base.as_mut() { - Some(base) => base.excludes_relative_path(path), - None => Ok(false), - } - } - - /// Whether the head revision excludes `path`. - fn head_excludes(&mut self, path: &Path) -> std::io::Result { - self.head.excludes_relative_path(path) - } -} - -/// The result of [`split_boundary_renames`]: the adjusted change list -/// plus the split-rename *deletion* rows whose lineage history is -/// already carried by their paired destination row — injecting the -/// source lineage into those deletions too would count it twice -/// (a `+1` on the destination and a full `-N` on the source). -struct SplitChanges { - files: Vec, - history_suppressed_deletions: std::collections::HashSet, -} - -/// Split rename pairs whose two sides fall on different sides of a -/// reporting boundary back into a deletion + addition. -/// -/// A joined rename row is keyed by its *destination*, so a rename to -/// an unsupported extension (`src/foo.py` → `archive/foo.txt`), out -/// of the selected `--paths` scope, or into git-attribute-excluded -/// territory (destination `linguist-generated` at head) would silently -/// swallow the source file's disappearance — and a rename *across -/// languages* (`.py` → `.rs`) would analyze the old blob with the new -/// language's analyzer. A rename is kept joined only when both sides -/// are selected, detect as the same language, and are -/// attribute-eligible at their own revision (source at base, -/// destination at head); otherwise each eligible side is reported on -/// its own. -fn split_boundary_renames( - changed: Vec, - selected: &dyn Fn(&Path) -> bool, - mut attribute_filters: Option<&mut RevisionGitAttributeFilters>, -) -> std::io::Result { - let language_of = |p: &Path| { - Utf8PathBuf::try_from(p.to_path_buf()) - .ok() - .and_then(|p| detect_language(&p)) - }; - let mut out = Vec::with_capacity(changed.len()); - let mut history_suppressed_deletions = std::collections::HashSet::new(); - for cf in changed { - let Some(source) = cf.source_path.clone() else { - out.push(cf); - continue; - }; - // Attribute eligibility is per-side and per-revision: the - // source lived at base, the destination lives at head. Lookup - // failures propagate — treating an unreadable historical - // `.gitattributes` as "eligible" would silently bypass source - // exclusions and compute metrics from incomplete data. - let (src_attr_ok, dest_attr_ok) = match attribute_filters.as_deref_mut() { - Some(filters) => ( - !filters.base_excludes(&source)?, - !filters.head_excludes(&cf.path)?, - ), - None => (true, true), - }; - let dest_ok = selected(&cf.path) && dest_attr_ok; - let src_ok = selected(&source) && src_attr_ok; - let dest_lang = language_of(&cf.path); - let src_lang = language_of(&source); - if dest_ok && src_ok && dest_lang.is_some() && dest_lang == src_lang { - out.push(cf); - continue; - } - let emit_source = src_ok && src_lang.is_some(); - let emit_dest = dest_ok && dest_lang.is_some(); - if emit_source { - // When the paired destination row is also emitted, it - // carries the lineage history (via its retained - // `source_path`); the deletion row then reports the file - // *leaving this path* for static metrics only. - if emit_dest { - history_suppressed_deletions.insert(source.clone()); - } - out.push(mehen_git::ChangedFile { - path: source.clone(), - status: ChangeStatus::Deleted, - source_path: None, - }); - } - if emit_dest { - out.push(mehen_git::ChangedFile { - path: cf.path, - status: ChangeStatus::Added, - // The static baseline must not cross the boundary (an - // `Added` row reads no baseline blob), but the rename - // identity is preserved so *history* enrichment can - // still compare against the source lineage instead of - // manufacturing a full-history spike. - source_path: Some(source), - }); - } - } - Ok(SplitChanges { - files: out, - history_suppressed_deletions, - }) -} - -/// Static inputs the history composites read (`history.hotspot` needs -/// the cognitive sum, `history.churn.relative` the code-line count), -/// per metric family. Staged into a split rename's synthetic baseline -/// for injection and stripped afterwards — the keys are shared with -/// displayed selectors. -const COMPOSITE_INPUT_KEYS: [&str; 6] = [ - mehen_core::keys::LOC_SLOC, - mehen_core::keys::COGNITIVE_SUM, - mehen_core::keys::SQL_LOC_CODE, - mehen_core::keys::SQL_COGNITIVE_COMPLEXITY, - mehen_core::keys::MARKDOWN_LOC_TLOC, - mehen_core::keys::MARKDOWN_COGNITIVE_COMPLEXITY, -]; - -fn analyze_diff_in_repo(input: DiffInput, repo: &gix::Repository) -> Result { - let mut input = input; - // The engine boundary accepts arbitrary threshold keys: a typo'd - // `history.*` key (the family is fixed — `keys::HISTORY_ALL`) can - // never read a published value, so evaluating it would silently - // pass or fail policy against a fabricated `0.0` — and walking - // the repository for it would be pure cost. Such thresholds are - // pulled out here and surfaced as analysis errors on the report. - let (valid_thresholds, unknown_history_thresholds): (Vec, Vec) = input - .thresholds - .drain(..) - .partition(|threshold| !history_metrics::is_invalid_history_selector(&threshold.selector)); - input.thresholds = valid_thresholds; - let registry = Arc::new(AnalyzerRegistry::default_set()); - let changed = mehen_git::changed_files(repo, &input.from, &input.to).map_err(DiffError::Git)?; - let mut git_attribute_filters = RevisionGitAttributeFilters::new(repo, &input.from, &input.to) - .map_err(|error| { - DiffError::Git(GitError::Internal(format!( - "failed to configure Git attribute filtering for {}..{}: {error}", - input.from, input.to - ))) - })?; - let changed = split_boundary_renames( - changed, - &|p: &Path| { - Utf8PathBuf::try_from(p.to_path_buf()) - .map(|utf8| path_is_selected(&utf8, &input.paths)) - .unwrap_or(false) - }, - Some(&mut git_attribute_filters), - ) - .map_err(|error| { - DiffError::Git(GitError::Internal(format!( - "failed to read Git attributes while splitting renames: {error}" - ))) - })? - // Thresholds evaluate the head analysis only; deleted rows have no - // head side, so the deletion history suppression is irrelevant here. - .files; - // Thresholds against `history.*` keys need the repository history - // at the head revision (thresholds are evaluated against the head - // analysis only). Walked lazily — the family is opt-in. - let wants_history = history_metrics::names_want_history( - input.thresholds.iter().map(|t| t.selector.key.as_str()), - ); - // `history.*` metrics change with every touch, not only when the - // endpoint trees differ: a file modified and restored within the - // range gained commit frequency and churn, and a head-side - // threshold can newly trip even though the endpoint diff has no - // row for it. Mirror the CLI diff's range-touch augmentation. - let changed = if wants_history { - let mut changed = changed; - let already: std::collections::HashSet<&PathBuf> = - changed.iter().map(|cf| &cf.path).collect(); - let extra: Vec = - mehen_git::range_touched_files(repo, &input.from, &input.to) - .map_err(DiffError::Git)? - .into_iter() - .filter(|path| !already.contains(path)) - .filter(|path| { - // Unlike the CLI pipeline (whose documentation - // section has no history columns), this API - // analyzes Markdown and evaluates every threshold - // against it — restored Markdown must be included - // or a Git-only policy silently passes for it. - // Undetected languages are skipped by the loop - // anyway. - Utf8PathBuf::try_from(path.clone()) - .ok() - .and_then(|utf8| detect_language(&utf8)) - .is_some() - }) - .map(|path| mehen_git::ChangedFile { - path, - status: ChangeStatus::Modified, - source_path: None, - }) - .collect(); - drop(already); - changed.extend(extra); - changed - } else { - changed - }; - let head_history = if wants_history { - Some(mehen_git::collect_history(repo, &input.to).map_err(DiffError::Git)?) - } else { - None - }; - - let mut report = DiffReport { - schema_version: "1.0".to_string(), - base: input.from.clone(), - head: input.to.clone(), - files: Vec::new(), - markdown_files: Vec::new(), - analysis_errors: Vec::new(), - threshold_violations: Vec::new(), - }; - for threshold in &unknown_history_thresholds { - report.analysis_errors.push(AnalysisErrorRecord { - path: Utf8PathBuf::new(), - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.unknown_metric", - format!( - "unknown history metric `{}` in threshold (not one of the fixed `history.*` keys); the threshold was not evaluated", - threshold.selector.key - ), - )], - }); - } - - for cf in changed { - // mehen-git returns `PathBuf` paths; convert at the boundary. - let Ok(utf8_path) = Utf8PathBuf::try_from(cf.path.clone()) else { - continue; - }; - - // Filter by `--paths` prefix matching. - if !path_is_selected(&utf8_path, &input.paths) { - continue; - } - if git_attribute_filters.excludes(&cf).map_err(|error| { - DiffError::Git(GitError::Internal(format!( - "failed to read Git attributes for {}: {error}", - cf.path.display() - ))) - })? { - continue; - } - - let Some(language) = detect_language(&utf8_path) else { - // Skip files we don't recognize. - continue; - }; - - // Strict decode: analyzing lossy replacement text would - // measure *mutated* source — complexity and SLOC feeding the - // history composites (and every static threshold) would come - // from text that is not the blob's content. An undecodable - // side reads as unavailable instead, exactly like the CLI - // path: git-only history thresholds still evaluate below. - let decode = |bytes: Vec, side: DiffSide, report: &mut DiffReport| { - match String::from_utf8(bytes) { - Ok(text) => Some(text), - Err(_) => { - report.analysis_errors.push(AnalysisErrorRecord { - path: utf8_path.clone(), - side, - diagnostics: vec![ParseDiagnostic::warning( - "engine.undecodable", - "not valid UTF-8; static analysis unavailable for this side" - .to_string(), - )], - }); - None - } - } - }; - let base_text = if cf.status == ChangeStatus::Added { - None - } else { - // Renamed files carry the baseline under their old path. - let base_path = cf.source_path.as_deref().unwrap_or(cf.path.as_path()); - mehen_git::read_blob(repo, &input.from, base_path) - .map_err(DiffError::Git)? - .and_then(|bytes| decode(bytes, DiffSide::Base, &mut report)) - }; - let head_text = if cf.status == ChangeStatus::Deleted { - None - } else { - mehen_git::read_blob(repo, &input.to, &cf.path) - .map_err(DiffError::Git)? - .and_then(|bytes| decode(bytes, DiffSide::Head, &mut report)) - }; - - let analyzer = registry.analyzer_for(language); - if analyzer.is_none() { - // Language detected but no analyzer registered (feature - // off); surface as a non-fatal analysis error. Git-only - // history thresholds still evaluate through the fallback - // below — they need no parser. - record_unavailable(&mut report, &utf8_path, language); - } - - let mut head_analysis: Option = None; - if let Some(analyzer) = analyzer { - for (text, side) in [ - (base_text.as_deref(), DiffSide::Base), - (head_text.as_deref(), DiffSide::Head), - ] { - let Some(text) = text else { continue }; - let source = SourceFile::new(utf8_path.clone(), language, text.to_string()); - match analyzer.analyze(&source, &input.config) { - Ok(analysis) => { - collect_diagnostics(&mut report, &utf8_path, side, &analysis); - if matches!(side, DiffSide::Head) { - head_analysis = Some(analysis); - } - } - Err(err) => { - report.analysis_errors.push(AnalysisErrorRecord { - path: utf8_path.clone(), - side, - diagnostics: vec![ParseDiagnostic::error( - "analysis.error", - err.to_string(), - )], - }); - } - } - } - } - - // Threshold evaluation runs against the head analysis (the - // post-change state) so policy gates like "head cyclomatic must - // not exceed 30" mean what callers expect. Files with a - // blocking diagnostic on the head side skip *static* - // thresholds — the analysis is incomplete and folding a - // partial number into a policy decision would be a false - // positive — but parser-independent `history.*` thresholds - // still evaluate: their complete values come from the - // repository walk, and a malformed file must not silently - // pass a history policy. - let head_blocked = head_analysis - .as_ref() - .is_some_and(|analysis| has_blocking_diagnostic(&analysis.diagnostics)); - // Whether the head-side per-file history lookup succeeded when - // a walk ran: `tracked_file` returning `None` (e.g. a lineage - // truncated by a platform-unrepresentable rename source) means - // history is unmeasurable for this file — `history.*` - // thresholds must be skipped, not read as `0.0` through the - // missing-key fallback (a commit-frequency limit would falsely - // pass, an ownership minimum falsely fail). - let head_history_available = match head_history.as_ref() { - Some(history) => history.tracked_file(cf.path.as_path()).is_some(), - None => true, - }; - if let Some(analysis) = head_analysis.as_mut() - && !head_blocked - { - // Fold `history.*` into the head metric set first so - // history thresholds read real values. `tracked_file`, - // not `file`: a blob created purely by merge conflict - // resolution has no accumulator, and its synthesized - // zero-touch entry (with a real creation-based age) must - // back thresholds like any other measured value. - if let Some(history) = head_history.as_ref() - && let Some(fh) = history.tracked_file(cf.path.as_path()) - { - history_metrics::inject_history_metrics( - &mut analysis.root.metrics, - &fh, - history.head_seconds, - true, - ); - } - if head_history_available { - evaluate_thresholds(&mut report, &utf8_path, &input.thresholds, &analysis.root); - } else { - let static_thresholds: Vec = input - .thresholds - .iter() - .filter(|t| !t.selector.key.as_str().starts_with("history.")) - .cloned() - .collect(); - evaluate_thresholds(&mut report, &utf8_path, &static_thresholds, &analysis.root); - } - } else if cf.status != ChangeStatus::Deleted - && head_history_available - && let Some(history) = head_history.as_ref() - && let Some(fh) = history.tracked_file(cf.path.as_path()) - { - // Only *Git-only* history keys evaluate in this fallback: - // the composites (`history.hotspot`, relative churn) read - // cognitive complexity and SLOC from the unavailable - // static analysis, and injecting them into an empty space - // would score hotspot zero and divide churn by one. - let history_thresholds: Vec = input - .thresholds - .iter() - .filter(|t| { - let key = t.selector.key.as_str(); - key.starts_with("history.") - && key != mehen_core::keys::HISTORY_HOTSPOT - && key != mehen_core::keys::HISTORY_CHURN_RELATIVE - }) - .cloned() - .collect(); - if !history_thresholds.is_empty() { - let mut space = MetricSpace::new( - mehen_core::SpaceId(0), - mehen_core::SpaceKind::Unit, - mehen_core::SourceSpan::empty(), - ); - history_metrics::inject_history_metrics( - &mut space.metrics, - &fh, - history.head_seconds, - false, - ); - evaluate_thresholds(&mut report, &utf8_path, &history_thresholds, &space); - } - } - - if matches!(language, mehen_core::Language::Markdown) { - report.markdown_files.push(DiffFile { path: utf8_path }); - } else { - report.files.push(DiffFile { path: utf8_path }); - } - } - - Ok(report) -} - -/// Apply each `Threshold` to the head analysis's metrics and append a -/// `ThresholdViolation` to the report for every rule that fails. Done -/// per-file so the violation entry carries the originating path. -fn evaluate_thresholds( - report: &mut DiffReport, - path: &Utf8PathBuf, - thresholds: &[Threshold], - root: &MetricSpace, -) { - for threshold in thresholds { - let actual = read_metric(&threshold.selector, root); - let violated = threshold.violated_by(actual); - if violated { - report.threshold_violations.push(ThresholdViolation { - path: path.to_string(), - evaluation: ThresholdEvaluation { - selector: threshold.selector.clone(), - actual, - limit: threshold.value, - polarity: threshold.polarity, - violated: true, - }, - }); - } - } -} - -fn path_is_selected(path: &Utf8PathBuf, paths: &[Utf8PathBuf]) -> bool { - if paths.is_empty() { - return true; - } - paths.iter().any(|prefix| { - let normalized = normalize_utf8_filter(prefix); - // A prefix that normalizes to empty (e.g. `""`, `"."`, - // `"././/"`) names the repo root — treat it as "match - // everything", consistent with the CLI path filter. - normalized.as_str().is_empty() || path.starts_with(&normalized) - }) -} - -/// Strip `.` components from a `Utf8PathBuf` filter prefix so callers -/// can pass intuitive scopes like `"./src"` (or even `"."`) without -/// silently dropping every changed file from the report. Mirrors the -/// CLI-side [`normalize_path_filter`] used for the `--paths` flag. -fn normalize_utf8_filter(path: &Utf8PathBuf) -> Utf8PathBuf { - let mut cleaned = Utf8PathBuf::new(); - for component in path.components() { - match component { - Utf8Component::CurDir => {} - Utf8Component::Normal(part) => cleaned.push(part), - other => cleaned.push(other.as_str()), - } - } - cleaned -} - -fn collect_diagnostics( - report: &mut DiffReport, - path: &Utf8PathBuf, - side: DiffSide, - analysis: &LanguageAnalysis, -) { - // Surface every non-empty diagnostic batch — including - // warning-only batches. Per plan §9.3 a `Warning` is - // *informational* (CLI keeps exit 0 unless thresholds fail), but - // it still has to be visible to callers; otherwise a Ruff-style - // recoverable parse issue or a markdown cross-reference warning - // is silently swallowed before it reaches the JSON output. - // Severity-based exit-code routing happens at the CLI layer - // against this same `analysis_errors` list, which carries the - // severity on every entry via `ParseDiagnostic::severity`. - if analysis.diagnostics.is_empty() { - return; - } - report.analysis_errors.push(AnalysisErrorRecord { - path: path.clone(), - side, - diagnostics: analysis.diagnostics.clone(), - }); -} - -/// Classify a diagnostic batch for diff-side severity gating. -/// -/// Per the diagnostic contract (rewrite plan §9.3), `Warning` is -/// informational, while `Error` or `Fatal` signals that the analysis is -/// incomplete — diff orchestrators must surface those (CLI exit 1, JSON -/// `analysis_errors`). Returns `true` iff any diagnostic in `diagnostics` -/// reaches the blocking threshold. Lives in the post-1.0 `diff` module -/// so it survives the legacy-engine teardown; the legacy diff path -/// re-uses it via `pub(crate)`. -pub(crate) fn has_blocking_diagnostic(diagnostics: &[ParseDiagnostic]) -> bool { - diagnostics.iter().any(|d| { - matches!( - d.severity, - mehen_core::DiagnosticSeverity::Error | mehen_core::DiagnosticSeverity::Fatal - ) - }) -} - -fn record_unavailable(report: &mut DiffReport, path: &Utf8PathBuf, language: mehen_core::Language) { - report.analysis_errors.push(AnalysisErrorRecord { - path: path.clone(), - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.analyzer_unavailable", - format!( - "no analyzer registered for `{}` in this build", - language.canonical() - ), - )], - }); -} - -#[derive(Debug)] -pub enum DiffError { - Git(GitError), -} - -impl core::fmt::Display for DiffError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Self::Git(e) => write!(f, "git: {e}"), - } - } -} - -impl core::error::Error for DiffError {} - -// ── pre-1.0 CLI orchestrator (`mehen diff`) ──────────────────────────── -// -// Everything below drives the published `mehen diff` subcommand and was -// hoisted out of `legacy/diff.rs` into this module so the CLI and the -// post-1.0 `analyze_diff` entry point share `has_blocking_diagnostic`. - -#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)] -pub(crate) enum DiffFormat { - Markdown, - Json, -} - -#[derive(Debug, Clone, serde::Serialize)] -struct MetricDiff { - name: &'static str, - label: &'static str, - current: f64, - baseline: f64, - delta: f64, - polarity: SelectorPolarity, - is_new: bool, - is_deleted: bool, - /// The side exists but this metric could not be computed for it — - /// a static-dependent history composite (`history.hotspot`, - /// `history.churn.relative`) on a side whose static analysis is - /// unavailable. The numeric field then holds a placeholder `0.0` - /// that must not be presented as a measurement: `delta` is forced - /// to `0.0` (no fabricated improvement/regression) and the - /// rendered cell reads `n/a`. Omitted from JSON when `false` so - /// ordinary rows keep their shape. - #[serde(skip_serializing_if = "std::ops::Not::not")] - current_unavailable: bool, - /// See `current_unavailable`, for the baseline side. - #[serde(skip_serializing_if = "std::ops::Not::not")] - baseline_unavailable: bool, -} - -#[derive(Debug, Clone, serde::Serialize)] -struct FileDiff { - path: PathBuf, - metrics: Vec, - is_new: bool, - is_deleted: bool, - /// Head-side function count read directly from the analysis (not - /// from the selected columns — the default set no longer includes - /// `nom.functions`), kept out of the JSON payload. Drives the - /// biggest-files-first report ordering. - #[serde(skip)] - functions: i64, -} - -impl FileDiff { - fn all_unchanged(&self) -> bool { - // An unavailable side is *unknown*, not unchanged: its forced - // `delta == 0.0` claims no direction, but hiding the row would - // present "could not measure" as "measured, nothing changed". - self.metrics - .iter() - .all(|m| m.delta == 0.0 && !m.current_unavailable && !m.baseline_unavailable) - } - - /// Sort key: total function count descending, then path ascending. - fn sort_key(&self) -> (std::cmp::Reverse, PathBuf) { - (std::cmp::Reverse(self.functions), self.path.clone()) - } -} - -#[derive(clap::Args, Debug)] -pub struct DiffOpts { - /// Base revision to compare from. - #[clap(long)] - from: Option, - /// Head revision to compare to. - #[clap(long)] - to: Option, - /// Comma-separated metrics to compare - /// (default: cognitive,abc,mi.visual_studio,history.hotspot,history.churn.relative). - /// Prefix with + for higher-is-better, - for lower-is-better. - /// Namespaced keys (`sql.*`, `markdown.*`, `history.*`) are accepted - /// verbatim; `history.*` metrics (including two of the defaults) - /// trigger a git history walk of both revisions. - #[clap(long, short = 'M', value_delimiter = ',')] - metrics: Vec, - /// Repository-relative files or directories to compare. - #[clap(long, short, value_parser, num_args(0..))] - paths: Vec, - /// Glob to include files. - #[clap(long, short = 'I', num_args(0..))] - include: Vec, - /// Glob to exclude files. - #[clap(long, short = 'X', num_args(0..))] - exclude: Vec, - /// Output format. - #[clap(long, short = 'O', value_enum)] - output_format: Option, - /// Show files where all metrics are unchanged. - #[clap(long)] - show_unchanged: bool, - /// Skip generated, vendored, and binary files marked via Git attributes. - #[clap( - long = "ignore-git-attributes", - visible_alias = "ignore-generated", - default_value_t = true, - action = clap::ArgAction::Set, - num_args = 0..=1, - require_equals = true, - default_missing_value = "true" - )] - ignore_git_attributes: bool, - /// Exit non-zero when the named thresholds are crossed - /// (comma-separated: `dmi-drop`, `new-broken-link`, `filler-high`, `all`). - #[clap( - long, - value_delimiter = ',', - value_parser = parse_fail_on_flag, - )] - fail_on: Vec, - /// Head-side coverage: the shared `--coverage` flag - /// (`PATH|auto|off`, repeatable, bare means `auto`). Also loads - /// lazily when a `coverage.*` column or configured threshold asks, - /// or when `--base-coverage` is given — a base-only report could - /// render at most half a trend. - #[clap(flatten)] - coverage: coverage_metrics::CoverageOpts, - /// Coverage report(s) for the *base* revision (repeatable), - /// enriching the baseline side so `coverage.*` columns carry real - /// trends. Explicit paths only — no discovery, since the working - /// tree holds *head* artifacts. Line numbers are read against the - /// re-analyzed base blobs, so the report must describe the base - /// revision; a file absent from it renders as a new measurement, - /// never a fabricated regression. - #[clap( - long = "base-coverage", - value_name = "PATH", - require_equals = true, - action = clap::ArgAction::Append - )] - base_coverage: Vec, -} - -/// Identifies one of the documented doc-metric CI gates. Any other value is -/// rejected by clap at parse time rather than being silently ignored. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub(crate) enum FailOn { - DmiDrop, - NewBrokenLink, - FillerHigh, - All, -} - -impl FailOn { - fn as_str(self) -> &'static str { - match self { - Self::DmiDrop => "dmi-drop", - Self::NewBrokenLink => "new-broken-link", - Self::FillerHigh => "filler-high", - Self::All => "all", - } - } -} - -/// Custom clap value parser so misspelled flags (e.g. `new-borken-link`) -/// produce an `InvalidValue` error at CLI-parse time instead of being -/// silently dropped downstream. -fn parse_fail_on_flag(raw: &str) -> Result { - match raw.trim().to_ascii_lowercase().as_str() { - "dmi-drop" => Ok(FailOn::DmiDrop), - "new-broken-link" => Ok(FailOn::NewBrokenLink), - "filler-high" => Ok(FailOn::FillerHigh), - "all" => Ok(FailOn::All), - other => Err(clap::Error::raw( - clap::error::ErrorKind::InvalidValue, - format!( - "unknown --fail-on value `{other}`; expected one of: dmi-drop, new-broken-link, filler-high, all\n" - ), - )), - } -} - -pub fn run_diff(opts: DiffOpts, config: Option<&crate::config_file::ConfigFile>) { - if let Err(e) = run_diff_inner(opts, config) { - log::error!("{e}"); - std::process::exit(1); - } -} - -fn run_diff_inner( - opts: DiffOpts, - config: Option<&crate::config_file::ConfigFile>, -) -> Result<(), Box> { - // 1. Resolve refs - let ci_ctx = ci::detect(); - let (from_ref, to_ref) = resolve_refs(&opts, &ci_ctx); - - // 2. Get changed file list - let repo = mehen_git::open_repo()?; - let from_label = mehen_git::friendly_ref_label(&repo, &from_ref); - // The push payload describes the *event's* range; explicit - // `--from`/`--to` overrides compare a different one, where the - // payload holds no authority (an empty fold there must not blank - // out a real requested diff). - let refs_from_event = opts.from.is_none() && opts.to.is_none(); - let changed = get_changed_files(&repo, &from_ref, &to_ref, &ci_ctx, refs_from_event)?; - // `history.*` metrics change with every touch, not only when the - // endpoint trees differ: a file modified in one range commit and - // reverted in a later one gained commit frequency, churn, and - // possibly bug-fix risk between the revisions, yet produces no - // endpoint diff row. When the request can read history columns - // (an explicit history selector, or default metrics — whose - // source-code set includes them), add such surviving touched - // paths as `Modified` rows: their static deltas are zero, and - // rows whose selected metrics all read zero still drop out of - // the report as unchanged. - let may_want_history = if opts.metrics.is_empty() { - true - } else { - history_metrics::names_want_history( - parse_metric_selectors(&opts.metrics).iter().map(|s| s.name), - ) - }; - // An authoritatively-empty push payload (branch created at an - // existing commit, or an add-then-remove push) means *nothing - // changed in this event* — and `resolve_refs`'s `HEAD~1` last - // resort is a guess at a range, not the event's range, so walking - // it would repopulate the report with the tip's previous commit. - let payload_authoritative_empty = refs_from_event - && ci_ctx.as_ref().is_some_and(|ctx| { - ctx.event_name == "push" - && ctx - .changed_files - .as_ref() - .is_some_and(|files| files.is_empty()) - }); - let changed = if may_want_history - && !payload_authoritative_empty - && repo.rev_parse_single(from_ref.as_str()).is_ok() - && repo.rev_parse_single(to_ref.as_str()).is_ok() - { - let mut changed = changed; - let already: std::collections::HashSet<&PathBuf> = - changed.iter().map(|cf| &cf.path).collect(); - let explicit = !opts.metrics.is_empty(); - let extra: Vec = - mehen_git::range_touched_files(&repo, &from_ref, &to_ref)? - .into_iter() - .filter(|path| !already.contains(path)) - .filter(|path| { - // Only languages whose effective selectors read - // history columns benefit from a synthetic row. - // Markdown always routes to the documentation - // pipeline (fixed columns, no history, no - // unchanged-row filter), so a restored-content - // README must never be resurrected here; under - // default metrics, SQL's history-free defaults - // exclude it too. - let Ok(utf8_path) = Utf8PathBuf::try_from(path.clone()) else { - return false; - }; - let Some(language) = detect_language(&utf8_path) else { - return false; - }; - if matches!(language, Language::Markdown) { - return false; - } - explicit - || history_metrics::names_want_history( - crate::metric_selector::default_metrics_for_language(language) - .iter() - .copied(), - ) - }) - .map(|path| mehen_git::ChangedFile { - path, - status: ChangeStatus::Modified, - source_path: None, - }) - .collect(); - drop(already); - changed.extend(extra); - changed - } else { - changed - }; - - // 3. Filter files - let include = mk_globset(opts.include); - let exclude = mk_globset(opts.exclude); - let paths = normalize_path_filters(&opts.paths); - let mut git_attribute_filters = opts - .ignore_git_attributes - .then(|| RevisionGitAttributeFilters::new(&repo, &from_ref, &to_ref)) - .transpose()?; - // Shared selection predicate — the rename splitter and the main - // filter loop must agree, or a rename could be split here and then - // dropped there (or vice versa). - let is_selected = |p: &Path| { - legacy_path_is_selected(p, &paths) - && (include.is_empty() || include.is_match(p)) - && (exclude.is_empty() || !exclude.is_match(p)) - }; - // Rename pairs straddling a path/language/attribute boundary fall - // back to a deletion + addition so neither side silently disappears. - let SplitChanges { - files: changed, - mut history_suppressed_deletions, - } = split_boundary_renames(changed, &is_selected, git_attribute_filters.as_mut())?; - // When the caller passes explicit `--metric` names, that one list applies - // to every file. With no `--metric`, defaults are resolved *per file's - // language*: SQL files publish only `sql.*` keys, so the source-code - // defaults (`cyclomatic`, …) would read 0 for them and drop the file as - // unchanged (Codex P2). `explicit_metrics` selects between the two modes. - let explicit_metrics = !opts.metrics.is_empty(); - let selectors = parse_metric_selectors(&opts.metrics); - // An explicit `--metrics` list where nothing parsed would silently - // produce an empty diff — and bypass every configured threshold - // whose column the typo'd list was meant to select. Fail loudly - // instead (matching `top-offenders`' required-metric guard). - if explicit_metrics && selectors.is_empty() { - log::error!("No valid metrics in --metrics. See `mehen diff --help`."); - std::process::exit(1); - } - - // Coverage ingestion — resolved once per side, then folded into - // each file's spaces after static analysis (the same enrichment - // slot the `history.*` family occupies). The head side keeps the - // `--coverage` semantics of `metrics`/`top-offenders`: explicit - // report problems hard-error, discovery degrades to warnings, and - // the lazy trigger fires on a requested `coverage.*` column, a - // configured `coverage.*` threshold, or `--base-coverage`. The - // base side never discovers — the working tree holds *head* - // artifacts — and judges report staleness against the base - // commit's own time (see `resolve_base_coverage`). - let coverage_config = config.and_then(|c| c.coverage.as_ref()); - let coverage_mode = opts.coverage.mode()?; - let base_coverage_paths: Vec = - opts.base_coverage.iter().map(Utf8PathBuf::from).collect(); - let coverage_wanted = coverage_metrics::names_want_coverage(selectors.iter().map(|s| s.name)) - || config.is_some_and(|c| { - c.thresholds - .any_metric(|name| name.starts_with("coverage.")) - }) - || !base_coverage_paths.is_empty(); - let coverage_roots: Vec = repo - .workdir() - .and_then(|dir| Utf8PathBuf::from_path_buf(dir.to_path_buf()).ok()) - .into_iter() - .collect(); - let head_coverage = coverage_metrics::resolve_coverage( - &coverage_mode, - coverage_config, - &coverage_roots, - coverage_wanted, - )?; - let base_coverage = coverage_metrics::resolve_base_coverage( - &base_coverage_paths, - &coverage_roots, - commit_time(&repo, &from_ref), - coverage_config, - )?; - // With default (per-language) columns and coverage actually - // resolved for either side, surface the line-rate column — the one - // dimension every supported report format measures. An explicit - // `--metrics` list keeps full column control. - let coverage_default_selector: Option = (!explicit_metrics - && (head_coverage.is_some() || base_coverage.is_some())) - .then(coverage_line_selector); - - let registry = Arc::new(AnalyzerRegistry::default_set()); - let analysis_config = AnalysisConfig::default(); - - let mut filtered: Vec<(mehen_git::ChangedFile, Utf8PathBuf, Language)> = Vec::new(); - let mut markdown_files: Vec = Vec::new(); - for cf in changed { - let p = &cf.path; - if !is_selected(p) { - continue; - } - - if let Some(filters) = git_attribute_filters.as_mut() - && filters.excludes(&cf)? - { - continue; - } - - // Convert the git path to UTF-8 once at the boundary; non-UTF-8 - // paths are rare and we drop them rather than fail the diff. - let Ok(utf8_path) = Utf8PathBuf::try_from(p.clone()) else { - continue; - }; - let Some(language) = detect_language(&utf8_path) else { - continue; - }; - - if matches!(language, Language::Markdown) { - markdown_files.push(cf.clone()); - continue; - } - - filtered.push((cf, utf8_path, language)); - } - - // History enrichment (`history.*`): repository-scope process - // metrics computed by one revision walk per side and folded into - // each file's metric set after static analysis. The walk costs one - // tree diff per commit, so it runs only when a file that survived - // filtering will actually read a history selector: any source file - // under an explicit history-bearing `--metrics` list, or any file - // whose *language defaults* include the history columns (SQL has - // its own history-free defaults, and Markdown files use the - // separate documentation pipeline — a SQL-only or docs-only diff - // must not pay for two full-history walks it never reads). - // Both sides are walked so history columns carry real deltas - // (e.g. commits/churn gained between base and head) instead of - // comparing against a phantom zero baseline. - let file_wants_history = - |(_, _, language): &(mehen_git::ChangedFile, Utf8PathBuf, Language)| { - if explicit_metrics { - history_metrics::names_want_history(selectors.iter().map(|s| s.name)) - } else { - history_metrics::names_want_history( - crate::metric_selector::default_metrics_for_language(*language) - .iter() - .copied(), - ) - } - }; - - // A split deletion's lineage is only "carried elsewhere" when its - // paired destination row actually *reads* history columns: it must - // have entered the history-enriched source-code pipeline above - // (not been diverted to the documentation pipeline, or dropped by - // attribute filters or a non-UTF-8 path), and its effective - // selectors must include history metrics (a cross-language rename - // into SQL's history-free defaults reads none). Otherwise the - // deletion keeps its history as the lineage's only trace. - { - let history_consuming_sources: std::collections::HashSet<&PathBuf> = filtered - .iter() - .filter(|entry| file_wants_history(entry)) - .filter_map(|(cf, _, _)| cf.source_path.as_ref()) - .collect(); - history_suppressed_deletions.retain(|src| history_consuming_sources.contains(src)); - } - - let histories: Option<( - Option, - mehen_git::RepositoryHistory, - )> = if filtered.iter().any(file_wants_history) { - // The head walk is a hard requirement — it feeds every - // history column. The *baseline* walk tolerates exactly one - // failure mode: an unresolvable revision (the payload fallback - // for a force-push keeps diffing with `from_ref` pointing at a - // commit that no longer exists locally). Baseline history - // columns then read as an empty baseline. Any other walk - // failure (corrupt or missing historical objects) still aborts - // — emitting full-history deltas from incomplete repository - // data would be silent garbage. - let base_history = match mehen_git::collect_history(&repo, &from_ref) { - Ok(history) => Some(history), - Err(GitError::RefNotFound(rev)) => { - log::warn!( - "baseline history unavailable ({rev} does not resolve locally); history columns compare against an empty baseline" - ); - None - } - Err(e) => return Err(e.into()), - }; - Some((base_history, mehen_git::collect_history(&repo, &to_ref)?)) - } else { - None - }; - - // 4. Compute metrics for each file via the per-language analyzer - // registry. The legacy `langs::get_function_spaces` pipeline is no - // longer used; we drive `LanguageAnalyzer::analyze` and read - // selector values out of the root `MetricSpace`'s `MetricSet`. - // - // Recoverable parser errors are surfaced as - // `DiagnosticSeverity::Error` / `Fatal` by the per-language - // analyzers (plan §9.3). Track whether any analyzed side reported - // an error/fatal so the diff exits non-zero at the end — partial - // metrics from a broken parse must not pass CI silently. - let mut diffs = Vec::new(); - let mut analysis_failed = false; - // Configured metric thresholds (`mehen.toml`): evaluated per file - // against the *head* side of the metrics this diff reports. - let threshold_policy = config - .map(|c| &c.thresholds) - .filter(|policy| !policy.is_empty()); - let mut threshold_breaches: Vec = Vec::new(); - // The union of selectors actually displayed, in first-seen order. With - // explicit `--metric` this is just `selectors`; with per-language defaults - // it accumulates each language's default columns as files are seen, so a - // mixed PR shows source-code columns and SQL columns side by side (each - // file populates only its own language's columns). - let mut display_selectors: Vec = if explicit_metrics { - selectors.clone() - } else { - Vec::new() - }; - for (cf, utf8_path, language) in &filtered { - let is_deleted = cf.status == ChangeStatus::Deleted; - let is_new = cf.status == ChangeStatus::Added; - // Renamed files carry the baseline under their old path — both - // the baseline blob and the baseline history live there. - let base_path = cf.source_path.as_deref().unwrap_or(cf.path.as_path()); - - // No analyzer for a recognized language (the owning crate is - // feature-gated off in this build): static columns are - // unavailable, but repository history needs no parser — a - // requested Git-only selector must still produce a row via - // the synthetic history-only fallback below instead of the - // binary silently dropping the file. - let analyzer = registry.analyzer_for(*language); - if analyzer.is_none() { - log::warn!( - "{}: no analyzer registered for `{}` in this build; static columns unavailable", - cf.path.display(), - language.canonical() - ); - } - - // Selectors for *this* file: the explicit list, or this language's - // defaults. Register any new default columns into the display union. - let file_selectors: Vec = if explicit_metrics { - selectors.clone() - } else { - let mut langs = default_selectors_for_language(*language); - // Coverage is language-orthogonal: the default coverage - // column joins every language's default set. Files no - // report measured render the column as `–` and stay - // droppable as unchanged (see the coverage arm below). - if let Some(coverage_column) = &coverage_default_selector { - langs.push(coverage_column.clone()); - } - for sel in &langs { - if !display_selectors.iter().any(|d| d.name == sel.name) { - display_selectors.push(sel.clone()); - } - } - langs - }; - - let mut analyze = |bytes: Vec, side: &str| -> Option { - let analyzer = analyzer.as_deref()?; - let text = String::from_utf8(bytes).ok()?; - let source = SourceFile::new(utf8_path.clone(), *language, text); - let analysis = match analyzer.analyze(&source, &analysis_config) { - Ok(a) => a, - Err(err) => { - log::error!("{} ({side}): analyzer failed: {err}", cf.path.display()); - analysis_failed = true; - return None; - } - }; - for diag in &analysis.diagnostics { - match diag.severity { - DiagnosticSeverity::Warning => log::warn!( - "{} ({side}): {}: {}", - cf.path.display(), - diag.code, - diag.message - ), - DiagnosticSeverity::Error | DiagnosticSeverity::Fatal => log::error!( - "{} ({side}): {}: {}", - cf.path.display(), - diag.code, - diag.message - ), - } - } - if has_blocking_diagnostic(&analysis.diagnostics) { - analysis_failed = true; - // A partial tree behind an `Error`/`Fatal` diagnostic - // is not a measurement (§9.3): emitting its truncated - // statics — or blending them into the history - // composites — would mislead even though the run - // already exits non-zero. The side falls back to the - // history-only synthetic space below. - return None; - } - Some(analysis.root) - }; - - let mut baseline_space: Option = if is_new { - None - } else { - match mehen_git::read_blob(&repo, &from_ref, base_path) { - Ok(Some(bytes)) => analyze(bytes, "baseline"), - Ok(None) => None, - Err(e) => { - log::warn!("Skipping baseline for {}: {e}", cf.path.display()); - None - } - } - }; - - let mut current_space: Option = if is_deleted { - None - } else { - match mehen_git::read_blob(&repo, &to_ref, &cf.path) { - Ok(Some(bytes)) => analyze(bytes, "current"), - Ok(None) => None, - Err(e) => { - log::warn!("Skipping current for {}: {e}", cf.path.display()); - None - } - } - }; - - // Fold the `history.*` family into each side's metric set, each - // against its own revision's history and head-relative "now". - // The baseline side of a renamed file reads its old path. - // The 🆕 flag is fixed *before* any baseline synthesis below — - // it reflects blob availability, not history availability. - let is_new_row = is_new && baseline_space.is_none(); - // Whether each side's space is backed by real static - // analysis: the synthetic history-only fallbacks below carry - // no static inputs, and the composite keys are then omitted - // (hotspot would read a fabricated 0, relative churn would - // divide by 1). Consulted again when the selector table is - // built — the missing keys must surface as *unavailable*, not - // as a `0.0` that fakes an improvement. The split-rename - // baseline counts as backed exactly when its staged inputs - // were accepted. - let mut baseline_composites = true; - let mut current_composites = true; - // Whether each side's per-file history lookup succeeded when - // a walk ran: `tracked_file` returning `None` (e.g. a lineage - // truncated by a platform-unrepresentable rename source) - // means that side's history is unmeasurable — the Git-only - // selectors must read `n/a`, not a fabricated 0 through the - // missing-key fallback. - let mut baseline_history_available = true; - let mut current_history_available = true; - if let Some((base_history, head_history)) = histories.as_ref() { - baseline_composites = baseline_space.is_some(); - current_composites = current_space.is_some(); - // A split rename (`Added` row carrying `source_path`, e.g. - // a cross-language `a.py → a.rs`) has no baseline *blob*, - // but its baseline *history* is the source lineage. Give - // it a synthetic baseline space so history columns - // compare against real values instead of manufacturing a - // full-history spike. The history *composites* also read - // static inputs at the baseline revision — hotspot needs - // the source's cognitive complexity, relative churn its - // size — so exactly those inputs are staged from an - // analysis of the source blob for the injection below, - // then stripped again (their keys are shared with - // displayed selectors, which must keep reading 0 so the - // row keeps its new-file presentation and the paired - // deletion row isn't double-counted against). - let mut staged_composite_inputs = false; - if baseline_space.is_none() - && cf.source_path.is_some() - && base_history - .as_ref() - .is_some_and(|history| history.tracked_file(base_path).is_some()) - { - let mut space = MetricSpace::new( - mehen_core::SpaceId(0), - mehen_core::SpaceKind::Unit, - mehen_core::SourceSpan::empty(), - ); - if let Ok(Some(bytes)) = mehen_git::read_blob(&repo, &from_ref, base_path) - && let Ok(base_utf8) = Utf8PathBuf::try_from(base_path.to_path_buf()) - && let Some(base_language) = detect_language(&base_utf8) - && let Some(base_analyzer) = registry.analyzer_for(base_language) - && let Ok(text) = String::from_utf8(bytes) - { - let base_source = SourceFile::new(base_utf8, base_language, text); - if let Ok(base_analysis) = base_analyzer.analyze(&base_source, &analysis_config) - && !has_blocking_diagnostic(&base_analysis.diagnostics) - { - for key in COMPOSITE_INPUT_KEYS { - if let Some(value) = base_analysis - .root - .metrics - .get(&mehen_core::MetricKey::new(key)) - { - space.metrics.insert(key, value); - staged_composite_inputs = true; - } - } - } - } - baseline_space = Some(space); - baseline_composites = staged_composite_inputs; - } - // History metrics don't depend on decoding or parsing the - // blob: a side whose static analysis is unavailable (e.g. - // non-UTF-8 but non-binary content the analyzer rejects) - // still has valid repository history. Synthesize an empty - // space for such a side so history-only selectors read the - // real values instead of zero — static columns stay 0. - let empty_space = || { - MetricSpace::new( - mehen_core::SpaceId(0), - mehen_core::SpaceKind::Unit, - mehen_core::SourceSpan::empty(), - ) - }; - if baseline_space.is_none() - && !is_new - && base_history - .as_ref() - .is_some_and(|history| history.tracked_file(base_path).is_some()) - { - baseline_space = Some(empty_space()); - baseline_composites = false; - } - if current_space.is_none() - && !is_deleted - && head_history.tracked_file(&cf.path).is_some() - { - current_space = Some(empty_space()); - current_composites = false; - } - let mut sides: Vec<( - Option<&mut MetricSpace>, - &mehen_git::RepositoryHistory, - &Path, - bool, - bool, - )> = Vec::with_capacity(2); - // A split-rename deletion row's lineage is already carried - // by its paired destination row — injecting it here too - // would double-count the history (a +1 on the destination - // and a full -N on the source). - let deletion_history_suppressed = - is_deleted && history_suppressed_deletions.contains(&cf.path); - if deletion_history_suppressed { - // The suppressed source row's lineage is carried by - // its paired destination row: its history columns - // must read `n/a`, not a measured `0 (was: 0)` that - // falsely claims the source had zero history. - baseline_history_available = false; - } - if let Some(base_history) = base_history.as_ref() - && !deletion_history_suppressed - { - sides.push(( - baseline_space.as_mut(), - base_history, - base_path, - baseline_composites, - false, - )); - } - sides.push(( - current_space.as_mut(), - head_history, - cf.path.as_path(), - current_composites, - true, - )); - for (space, history, path, with_composites, is_current) in sides { - // `tracked_file`, not `file`: each side's path exists - // at that side's revision, the head-blob gate keeps a - // dead prior occupant's history out, and a blob - // created purely by merge conflict resolution reads - // its synthesized zero-touch entry (real - // creation-based age) instead of nothing. A `None` - // here (e.g. a lineage truncated by a platform- - // unrepresentable rename source) means this side's - // history is *unmeasurable* — remembered per side so - // the selector table reads `n/a`, not a measured 0. - let fh = history.tracked_file(path); - if is_current { - current_history_available = fh.is_some(); - } else { - baseline_history_available = fh.is_some(); - } - if let Some(space) = space - && let Some(fh) = fh - { - history_metrics::inject_history_metrics( - &mut space.metrics, - &fh, - history.head_seconds, - with_composites, - ); - } - } - // The staged composite inputs did their job during - // injection; their keys are shared with displayed - // selectors (`cognitive` reads `cognitive.sum`, …), and - // leaving them would subtract the source's statics from - // this new row *and* double-count against the paired - // deletion row, which already carries them. - if staged_composite_inputs && let Some(space) = baseline_space.as_mut() { - for key in COMPOSITE_INPUT_KEYS { - space.metrics.remove(&mehen_core::MetricKey::new(key)); - } - } - } - - // Coverage enrichment (`coverage.*`): fold each side's report - // data into that side's spaces — head from `--coverage` (or - // discovery), base from `--base-coverage`. Same-revision by - // construction: the base report describes the base blobs this - // diff just re-analyzed, so report line numbers and base - // spans line up without any mapping. A side whose blob could - // not be statically analyzed still carries its measured - // coverage via a synthetic space — statics stay honest there - // (`*_composites = false`, and the empty space publishes no - // static keys), mirroring the history-only fallback above. - // The baseline of a renamed file reads its old path: the base - // report was written when the file lived there. - if head_coverage.is_some() || base_coverage.is_some() { - let empty_space = || { - MetricSpace::new( - mehen_core::SpaceId(0), - mehen_core::SpaceKind::Unit, - mehen_core::SourceSpan::empty(), - ) - }; - if let Some(context) = base_coverage.as_ref() - && !is_new - && let Ok(base_utf8) = Utf8PathBuf::try_from(base_path.to_path_buf()) - && let Some(file_coverage) = - coverage_metrics::coverage_for_file(context, &base_utf8) - { - if baseline_space.is_none() { - baseline_space = Some(empty_space()); - baseline_composites = false; - } - if let Some(space) = baseline_space.as_mut() { - coverage_metrics::inject_coverage_metrics(space, &file_coverage); - } - } - if let Some(context) = head_coverage.as_ref() - && !is_deleted - && let Some(file_coverage) = coverage_metrics::coverage_for_file(context, utf8_path) - { - if current_space.is_none() { - current_space = Some(empty_space()); - current_composites = false; - } - if let Some(space) = current_space.as_mut() { - coverage_metrics::inject_coverage_metrics(space, &file_coverage); - } - } - } - - let metric_diffs: Vec = file_selectors - .iter() - .filter_map(|sel| { - // A side whose static analysis is unavailable cannot - // value any analyzer-derived selector: the keys are - // absent from its synthetic history-only space, and - // the missing-key `0.0` fallback must not masquerade - // as a measurement — `cognitive 12 → 0` or `hotspot - // 12 → 0` would fake a full improvement in the diff - // columns. Git-only history selectors stay measurable. - // - // Symmetrically, a *requested but unresolvable* - // baseline walk (the force-push payload fallback keeps - // diffing while `from_ref` no longer resolves locally) - // leaves history selectors with no measured baseline — - // comparing the head's lifetime hotspot/churn against - // a numeric zero would render the entire history as a - // fresh regression and trip delta thresholds on - // fabricated values. New rows keep their 🆕 shape. - // - // Coverage selectors read per-side *key presence* - // instead: `inject_coverage_metrics` publishes a - // dimension only when the report measured it, so the - // key itself is the measured-or-absent signal — per - // dimension (a Go coverprofile measures lines but no - // branches) and per side (absent base coverage renders - // the head value as a new measurement, never a - // fabricated regression — absent ≠ 0, extended to - // diff). A file measured on *neither* side drops the - // entry entirely: the column reads `–` and the row - // stays droppable as unchanged — a permanent `n/a` - // cell on every uninstrumented file would be noise. - let (baseline_unavailable, current_unavailable) = - if sel.name.starts_with("coverage.") { - let measured = |space: &Option| { - space.as_ref().is_some_and(|s| { - s.metrics - .get(&mehen_core::MetricKey::new(metric_set_key_for(sel.name))) - .is_some() - }) - }; - let base_measured = measured(&baseline_space); - let head_measured = measured(¤t_space); - if !base_measured && !head_measured { - return None; - } - ( - baseline_space.is_some() && !base_measured, - current_space.is_some() && !head_measured, - ) - } else { - let baseline_history_missing = - matches!(histories.as_ref(), Some((None, _))) - && !is_new_row - && sel.name.starts_with("history."); - ( - baseline_history_missing - || (baseline_space.is_some() - && !history_metrics::selector_available( - sel.name, - baseline_composites, - baseline_history_available, - )), - current_space.is_some() - && !history_metrics::selector_available( - sel.name, - current_composites, - current_history_available, - ), - ) - }; - let baseline = baseline_space - .as_ref() - .map(|s| read_selector_metric(s, sel)) - .unwrap_or(0.0); - let current = current_space - .as_ref() - .map(|s| read_selector_metric(s, sel)) - .unwrap_or(0.0); - let delta = if baseline_unavailable || current_unavailable { - 0.0 - } else { - current - baseline - }; - Some(MetricDiff { - name: sel.name, - label: sel.label, - current, - baseline, - delta, - polarity: sel.polarity, - is_new: is_new_row, - is_deleted, - current_unavailable, - baseline_unavailable, - }) - }) - .collect(); - - // Configured thresholds gate the head side of the metrics - // this file reports; a deleted file has no head side to gate. - // Keys the head space does not publish — statics behind a - // blocked parse or an unavailable analyzer, history on an - // untracked path — are skipped by `evaluate`, never read as a - // fabricated `0.0`. Evaluation happens *before* the - // unchanged-row filter below: an unchanged-but-over-limit - // metric still fails the gate even when its row is hidden. - if let Some(policy) = threshold_policy - && !is_deleted - && let Some(space) = current_space.as_ref() - { - let names: Vec<&str> = file_selectors.iter().map(|s| s.name).collect(); - threshold_breaches.extend(policy.evaluate( - &cf.path.display().to_string(), - *language, - space, - Some(&names), - )); - } - - diffs.push(FileDiff { - path: cf.path.clone(), - metrics: metric_diffs, - is_new: is_new_row, - is_deleted, - functions: current_space - .as_ref() - .and_then(|s| s.metrics.get(&mehen_core::MetricKey::new("nom.functions"))) - .map(|v| v.as_f64() as i64) - .unwrap_or(0), - }); - } - - // 5. Filter unchanged - if !opts.show_unchanged { - diffs.retain(|d| !d.all_unchanged()); - } - - // 6. Sort - diffs.sort_by_key(|a| a.sort_key()); - - // Markdown doc section — parallel pipeline for `.md`-like files. - let doc_files: Vec = { - let mut out: Vec = Vec::new(); - for cf in &markdown_files { - let is_deleted = cf.status == ChangeStatus::Deleted; - let is_candidate_new = cf.status == ChangeStatus::Added; - // Renamed docs carry the baseline under their old path. - let base_path = cf.source_path.as_deref().unwrap_or(cf.path.as_path()); - let base_metrics = if is_candidate_new { - None - } else { - match mehen_git::read_blob(&repo, &from_ref, base_path) { - // Analyze the baseline *as its old path*: Markdown - // link/grounding metrics resolve relative - // references from the file's location, so a - // renamed doc's baseline must be evaluated from - // the directory it actually lived in — otherwise a - // link broken only by the move looks broken in the - // baseline too and `--fail-on new-broken-link` - // misses the regression. - Ok(Some(bytes)) => Some(mehen_markdown::analyze_markdown( - &String::from_utf8_lossy(&bytes), - base_path, - )), - Ok(None) => None, - Err(e) => { - log::warn!("Skipping baseline for {}: {e}", cf.path.display()); - None - } - } - }; - let head_metrics = if is_deleted { - None - } else { - match mehen_git::read_blob(&repo, &to_ref, &cf.path) { - Ok(Some(bytes)) => Some(mehen_markdown::analyze_markdown( - &String::from_utf8_lossy(&bytes), - &cf.path, - )), - Ok(None) => None, - Err(e) => { - log::warn!("Skipping current for {}: {e}", cf.path.display()); - None - } - } - }; - let is_new = is_candidate_new && base_metrics.is_none(); - out.push(DocDiffFile { - path: cf.path.clone(), - head: head_metrics, - base: base_metrics, - is_new, - is_deleted, - }); - } - out - }; - - // 7. Output - // Deterministic order for both the JSON payload and the stderr - // report (render_threshold_report re-sorts harmlessly). - crate::config_file::sort_breaches(&mut threshold_breaches); - let format = opts.output_format.unwrap_or(DiffFormat::Markdown); - match format { - DiffFormat::Markdown => { - print_markdown(&diffs, &display_selectors, &from_label, &from_ref, &to_ref); - if !doc_files.is_empty() { - let mut ctx = DocRenderCtx::new(&from_label); - let repo_url = ci_ctx - .as_ref() - .and_then(|c| c.repository.as_ref()) - .map(|r| format!("https://github.com/{r}")); - ctx.repo_url = repo_url.as_deref(); - ctx.head_sha = Some(&to_ref); - if let Some(doc_md) = render_doc_section(&doc_files, &ctx) { - let mut stdout = std::io::stdout().lock(); - writeln!(stdout).ok(); - write!(stdout, "{doc_md}").ok(); - } - } - } - DiffFormat::Json => { - let doc_ref: Option<&[DocDiffFile]> = if doc_files.is_empty() { - None - } else { - Some(&doc_files) - }; - // A failed analysis means the measurements behind the - // breaches are partial: withhold the machine-readable gate - // signal so consumers (the GitHub Action) fail fast on the - // analysis error instead of publishing an incomplete - // report as an ordinary gate failure. - let publishable_breaches: &[crate::config_file::ThresholdBreach] = if analysis_failed { - &[] - } else { - &threshold_breaches - }; - if let Err(e) = print_json(&diffs, doc_ref, publishable_breaches) { - // Surface the error loudly — exit code 2 mirrors the - // --fail-on gate and is distinct from the generic exit 1 - // that covers setup/IO errors in run_diff_inner. - log::error!("diff: failed to emit JSON output: {e}"); - std::process::exit(2); - } - } - } - - // Configured metric thresholds (`mehen.toml`): print the report - // before the doc gate below so a combined failure still surfaces - // both; the exit itself happens after the doc gate to keep its - // historical exit code (2) stable. - if !threshold_breaches.is_empty() - && let Some(config) = config - { - eprint!( - "{}", - crate::config_file::render_threshold_report(&mut threshold_breaches, &config.path) - ); - } - - // --fail-on check. - let failures = evaluate_fail_on(&opts.fail_on, &doc_files); - if !failures.is_empty() { - log::error!("--fail-on threshold crossed: {}", failures.join(", ")); - std::process::exit(2); - } - - // Per the diagnostic contract (rewrite plan §9.3), recoverable - // parser errors must surface as a non-zero exit so CI cannot pass - // partial metrics computed from a known-broken parse. Checked - // before the threshold gate: a broken analysis outranks a quality - // gate evaluated on the parseable remainder. Exit 1 lines up with - // the generic setup/IO bucket and is distinct from exit 2 (doc - // gate). Diagnostics are already logged above; this gate only - // flips the exit code. - if analysis_failed { - std::process::exit(1); - } - - // Exit 1: configured quality gates fail with the generic failure - // code (`mehen.toml` threshold contract); the report was printed - // above. - if !threshold_breaches.is_empty() { - std::process::exit(1); - } - - Ok(()) -} - -fn doc_json_payload(files: &[DocDiffFile]) -> Vec { - files - .iter() - .map(|f| { - serde_json::json!({ - "path": f.path.to_string_lossy(), - "is_new": f.is_new, - "is_deleted": f.is_deleted, - "base": f.base, - "head": f.head, - }) - }) - .collect() -} - -fn evaluate_fail_on(flags: &[FailOn], docs: &[DocDiffFile]) -> Vec { - let mut enabled: std::collections::BTreeSet = std::collections::BTreeSet::new(); - for f in flags { - match f { - FailOn::All => { - enabled.insert(FailOn::DmiDrop); - enabled.insert(FailOn::NewBrokenLink); - enabled.insert(FailOn::FillerHigh); - } - other => { - enabled.insert(*other); - } - } - } - if enabled.is_empty() { - return Vec::new(); - } - // If the caller asked to gate on doc metrics but no markdown files are - // in the diff, log a warning so users notice the flag silently matched - // nothing. The gate itself still returns success (no docs → no metric - // breach possible) so existing CI doesn't break. - if docs.iter().all(|f| f.head.is_none()) { - let flags: Vec<&str> = enabled.iter().copied().map(FailOn::as_str).collect(); - log::warn!( - "--fail-on {flags:?} has no Markdown files in the diff; no doc-metric thresholds were evaluated" - ); - } - let mut failures: Vec = Vec::new(); - for f in docs { - let Some(head) = &f.head else { continue }; - let base = f.base.as_ref(); - if enabled.contains(&FailOn::DmiDrop) - && let Some(b) = base - { - let hd = head.maintainability.documentation_maintainability_index; - let bd = b.maintainability.documentation_maintainability_index; - if bd - hd >= 3.0 { - failures.push(format!("dmi-drop:{}", f.path.display())); - } - } - if enabled.contains(&FailOn::NewBrokenLink) { - // Identity-based diff keyed on (class, destination) — line - // numbers MAY change without a new broken link (e.g. a doc - // prepends content, shifting every link down one line). The CI - // gate fires only when a key appears more often in head than in - // base. Line numbers still flow through to the callout layer for - // the PR comment; they just don't drive the fail-on decision. - // See §39.4. - let mut head_counts: std::collections::BTreeMap< - (mehen_markdown::types::LinkClass, &str), - usize, - > = std::collections::BTreeMap::new(); - for l in &head.link_records { - if matches!(l.resolved, Some(false)) { - *head_counts - .entry((l.class, l.destination.as_str())) - .or_insert(0) += 1; - } - } - let mut base_counts: std::collections::BTreeMap< - (mehen_markdown::types::LinkClass, &str), - usize, - > = std::collections::BTreeMap::new(); - if let Some(b) = base { - for l in &b.link_records { - if matches!(l.resolved, Some(false)) { - *base_counts - .entry((l.class, l.destination.as_str())) - .or_insert(0) += 1; - } - } - } - let has_new_broken = head_counts.iter().any(|(key, head_n)| { - let base_n = base_counts.get(key).copied().unwrap_or(0); - *head_n > base_n - }); - if has_new_broken { - failures.push(format!("new-broken-link:{}", f.path.display())); - } - } - if enabled.contains(&FailOn::FillerHigh) && head.ai_era.filler_lazy_structure_risk >= 0.60 { - failures.push(format!("filler-high:{}", f.path.display())); - } - } - failures -} - -// ── Ref resolution ───────────────────────────────────────────────────── - -/// Committer timestamp of a revision, for base-report staleness -/// checks. `None` when the revision or its commit metadata cannot be -/// read (e.g. the force-push payload fallback keeps diffing while -/// `from_ref` no longer resolves locally) — staleness is then simply -/// not judged. -fn commit_time(repo: &gix::Repository, rev: &str) -> Option { - let seconds = repo - .rev_parse_single(rev) - .ok()? - .object() - .ok()? - .peel_to_commit() - .ok()? - .time() - .ok()? - .seconds; - u64::try_from(seconds) - .ok() - .map(|s| std::time::UNIX_EPOCH + std::time::Duration::from_secs(s)) -} - -fn resolve_refs(opts: &DiffOpts, ci_ctx: &Option) -> (String, String) { - if let (Some(from), Some(to)) = (&opts.from, &opts.to) { - return (from.clone(), to.clone()); - } - - if let Some(ctx) = ci_ctx { - let to = opts - .to - .clone() - .or_else(|| ctx.head_sha.clone()) - .unwrap_or_else(|| "HEAD".to_string()); - - let from = opts - .from - .clone() - .unwrap_or_else(|| match ctx.event_name.as_str() { - // A multi-commit push must diff against the branch tip - // *before* the push (the payload's `before` SHA), not - // just the final commit's parent — otherwise renames - // and baselines from earlier commits in the push are - // invisible. A branch-creation push has no `before`; - // the parent of the *first pushed commit* is the right - // baseline there. `HEAD~1` remains the last resort. - "push" => ctx - .before_sha - .clone() - .or_else(|| ctx.first_commit_sha.as_ref().map(|sha| format!("{sha}~1"))) - .unwrap_or_else(|| "HEAD~1".to_string()), - "pull_request" | "merge_group" => ctx - .base_ref - .as_ref() - .map(|b| format!("origin/{b}")) - .unwrap_or_else(|| "origin/main".to_string()), - _ => "main".to_string(), - }); - - return (from, to); - } - - let from = opts.from.clone().unwrap_or_else(|| "main".to_string()); - let to = opts.to.clone().unwrap_or_else(|| "HEAD".to_string()); - (from, to) -} - -fn get_changed_files( - repo: &gix::Repository, - from: &str, - to: &str, - ci_ctx: &Option, - refs_from_event: bool, -) -> Result, GitError> { - // For push events, the payload's folded per-path statuses (PR #95) - // are a *fallback*: the real tree diff over the full push range is - // strictly more accurate — it carries rename identity (including - // break-rewrite recovery when a renamed file's old path was - // reused), correct type-change handling, and blob-only filtering. - // That applies to branch creations too: `resolve_refs` supplies - // the first pushed commit's parent there, so a resolvable baseline - // still yields a full-range tree diff with rename identity the - // payload can never express. The payload is used only when the - // refs don't resolve locally (a force-push discarded the `before` - // commit, or the branch's first commit is a root commit) — and - // only when the compared range *is* the event's range: explicit - // `--from`/`--to` overrides ask about a different range the - // payload knows nothing about. - if refs_from_event - && let Some(ctx) = ci_ctx - && ctx.event_name == "push" - && let Some(ref files) = ctx.changed_files - { - // An *empty* fold is authoritative: the push changed nothing - // net (add-then-remove), or a branch was created pointing at a - // commit that already existed — either way a ref-range diff - // (e.g. the `HEAD~1` last resort) would misreport the tip's - // last commit as this push's changes. - if files.is_empty() { - return Ok(files.clone()); - } - // The payload fallback exists for exactly one failure mode: - // the push *baseline* not resolving locally (a force-push - // discarded the `before` commit, or a created branch's first - // commit is a root commit). Any other tree-diff failure — - // corrupt or missing objects in a resolvable range — must - // propagate rather than silently degrade to the payload's - // rename-less, type-change-less view. - if repo.rev_parse_single(from).is_err() { - log::warn!( - "falling back to the push payload's changed files ({from} does not resolve locally)" - ); - // With the baseline unreadable, every baseline blob read - // downstream would fail and quietly turn `Modified` rows - // into fabricated full-value-vs-zero deltas, while - // `Deleted` rows (neither side analyzable) would vanish. - // Degrade honestly instead: modified files are presented - // as their current state only (an `Added` row, 🆕 in the - // report), and deletions are dropped with a warning. - let degraded = files - .iter() - .filter(|cf| { - if cf.status == ChangeStatus::Deleted { - log::warn!( - "dropping deleted file {} from the report: its baseline \ - ({from}) is not available locally", - cf.path.display() - ); - false - } else { - true - } - }) - .map(|cf| mehen_git::ChangedFile { - path: cf.path.clone(), - status: ChangeStatus::Added, - source_path: cf.source_path.clone(), - }) - .collect(); - return Ok(degraded); - } - } - - mehen_git::changed_files(repo, from, to) -} -fn normalize_path_filters(paths: &[PathBuf]) -> Vec { - paths - .iter() - .map(|path| normalize_path_filter(path)) - .collect() -} - -fn normalize_path_filter(path: &Path) -> PathBuf { - let mut cleaned = PathBuf::new(); - - for component in path.components() { - match component { - Component::CurDir => {} - Component::Normal(part) => cleaned.push(part), - other => cleaned.push(other.as_os_str()), - } - } - - cleaned -} - -/// Pre-1.0 path filter for CLI `--paths`: matches by `Path` prefix or -/// exact equality. Distinct from the post-1.0 [`path_is_selected`] -/// (which works on `Utf8PathBuf` for the `analyze_diff` entry point). -fn legacy_path_is_selected(path: &Path, paths: &[PathBuf]) -> bool { - paths.is_empty() - || paths.iter().any(|selected| { - selected.as_os_str().is_empty() || path == selected || path.starts_with(selected) - }) -} - -// ── Markdown output ──────────────────────────────────────────────────── - -fn print_markdown( - diffs: &[FileDiff], - selectors: &[MetricSelector], - from_label: &str, - from: &str, - to: &str, -) { - let mut out = String::new(); - - // Source-code anchor (§39.1: sibling of the docs anchor). - out.push_str("\n"); - out.push_str(&format!( - "## [Mehen](https://github.com/ophi-dev/mehen) Summary (`{from}`..`{to}`)\n\n" - )); - - if diffs.is_empty() { - out.push_str("No metric changes detected.\n"); - write!(std::io::stdout().lock(), "{out}").unwrap(); - return; - } - - // Header - out.push_str("| File |"); - for sel in selectors { - out.push_str(&format!(" {} |", sel.label)); - } - out.push('\n'); - - // Separator - out.push_str("|---|"); - for _ in selectors { - out.push_str("---:|"); - } - out.push('\n'); - - // Rows. Each cell is looked up by selector *name* against the file's - // metrics, so a file that doesn't publish a given column (e.g. a SQL file - // under the `cyclomatic` column of a mixed PR) renders an em dash rather - // than a misaligned value. - for diff in diffs { - out.push_str(&format!("| {} |", diff.path.display())); - for sel in selectors { - out.push(' '); - match diff.metrics.iter().find(|m| m.name == sel.name) { - Some(md) => out.push_str(&format_metric_cell(md, from_label)), - None => out.push('\u{2013}'), // – (column not applicable to this file) - } - out.push_str(" |"); - } - out.push('\n'); - } - - write!(std::io::stdout().lock(), "{out}").unwrap(); -} - -fn format_metric_cell(md: &MetricDiff, from: &str) -> String { - let current = format_f64(md.current); - - if md.is_new { - if md.current_unavailable { - return "n/a \u{1F195}".to_string(); // 🆕 - } - return format!("{current} \u{1F195}"); // 🆕 - } - - if md.is_deleted { - if md.baseline_unavailable { - // The deleted file's baseline value was never measurable; - // claiming "was: 0" (or a trend) would fabricate one. - return "0 (was: n/a)".to_string(); - } - let baseline = format_f64(md.baseline); - let emoji = trend_emoji(md.delta, md.polarity); - return format!("0 (was: {baseline}) {emoji}"); - } - - if md.current_unavailable || md.baseline_unavailable { - // One side (or both) could not be measured: show what is - // known, claim no direction — a trend emoji would assert an - // improvement/regression no measurement supports. - let cur = if md.current_unavailable { - "n/a".to_string() - } else { - current - }; - if md.baseline_unavailable && md.current_unavailable { - return cur; - } - let base = if md.baseline_unavailable { - "n/a".to_string() - } else { - format_f64(md.baseline) - }; - return format!("{cur} ({from}: {base})"); - } - - if md.delta == 0.0 { - return format!("{current} \u{26AA}"); // ⚪ - } - - let baseline = format_f64(md.baseline); - let emoji = trend_emoji(md.delta, md.polarity); - format!("{current} ({from}: {baseline}) {emoji}") -} - -fn trend_emoji(delta: f64, polarity: SelectorPolarity) -> &'static str { - if delta == 0.0 { - return "\u{26AA}"; // ⚪ - } - match polarity { - SelectorPolarity::LowerIsBetter => { - if delta > 0.0 { - "\u{1F534}" // 🔴 - } else { - "\u{1F7E2}" // 🟢 - } - } - SelectorPolarity::HigherIsBetter => { - if delta > 0.0 { - "\u{1F7E2}" // 🟢 - } else { - "\u{1F534}" // 🔴 - } - } - } -} - -fn format_f64(v: f64) -> String { - if v == v.trunc() { - format!("{}", v as i64) - } else { - format!("{:.2}", v) - } -} - -// ── JSON output ──────────────────────────────────────────────────────── - -/// Emit a single JSON document with a `source_code` key and an optional -/// `markdown` key. Downstream consumers (`jq`, `serde_json`) see one top-level -/// object, not two concatenated arrays. -/// -/// Serialization errors bubble up as `Err` so `run_diff_inner` exits -/// non-zero instead of silently writing an empty `""` to stdout. -fn print_json( - diffs: &[FileDiff], - docs: Option<&[DocDiffFile]>, - threshold_breaches: &[crate::config_file::ThresholdBreach], -) -> Result<(), Box> { - let mut payload = serde_json::Map::new(); - payload.insert("source_code".to_string(), serde_json::to_value(diffs)?); - if let Some(docs) = docs { - payload.insert( - "markdown".to_string(), - serde_json::Value::Array(doc_json_payload(docs)), - ); - } - // Present only when a configured `mehen.toml` gate fired — the - // explicit signal machine consumers (e.g. the GitHub Action) use - // to distinguish a quality-gate exit (1, with this key) from an - // analysis failure (also exit 1, but without it). - if !threshold_breaches.is_empty() { - payload.insert( - "threshold_violations".to_string(), - serde_json::to_value(threshold_breaches)?, - ); - } - let json = serde_json::to_string_pretty(&serde_json::Value::Object(payload))?; - writeln!(std::io::stdout().lock(), "{json}")?; - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn empty_diagnostics_are_not_blocking() { - assert!(!has_blocking_diagnostic(&[])); - } - - #[test] - fn warning_only_is_not_blocking() { - let diags = vec![ParseDiagnostic::warning("python.style", "long line")]; - assert!(!has_blocking_diagnostic(&diags)); - } - - #[test] - fn error_severity_is_blocking() { - let diags = vec![ParseDiagnostic::error( - "ruby.syntax_error", - "unterminated string", - )]; - assert!(has_blocking_diagnostic(&diags)); - } - - #[test] - fn fatal_severity_is_blocking() { - let diags = vec![ParseDiagnostic::fatal( - "rust.parse_error", - "tree-sitter-rust failed", - )]; - assert!(has_blocking_diagnostic(&diags)); - } - - #[test] - fn warning_mixed_with_error_is_blocking() { - let diags = vec![ - ParseDiagnostic::warning("python.style", "long line"), - ParseDiagnostic::error("python.syntax_error", "invalid syntax"), - ]; - assert!(has_blocking_diagnostic(&diags)); - } - - use mehen_core::{ - AnalysisBackend, Language, MetricKey, MetricSpace, Polarity, SourceSpan, SpaceId, SpaceKind, - }; - - fn analysis_with_metric(key: &str, value: f64) -> LanguageAnalysis { - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - root.metrics.insert(MetricKey::new(key), value); - LanguageAnalysis { - language: Language::Rust, - backend: AnalysisBackend::TreeSitter, - diagnostics: Vec::new(), - root, - contributions: Vec::new(), - } - } - - fn empty_report() -> DiffReport { - DiffReport { - schema_version: "1.0".to_string(), - base: "HEAD~1".to_string(), - head: "HEAD".to_string(), - files: Vec::new(), - markdown_files: Vec::new(), - analysis_errors: Vec::new(), - threshold_violations: Vec::new(), - } - } - - fn git_ok(repo: &Path, args: &[&str]) { - let output = std::process::Command::new("git") - .current_dir(repo) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - - #[test] - fn analyze_diff_skips_all_default_git_attribute_classes() { - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -generated.md linguist-generated -vendored.md linguist-vendored -binary.md binary -deleted.md linguist-generated -", - ) - .unwrap(); - for name in [ - "kept.md", - "generated.md", - "vendored.md", - "binary.md", - "deleted.md", - ] { - std::fs::write(dir.path().join(name), "# Base\n").unwrap(); - } - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "attribute-base"]); - - for name in ["kept.md", "generated.md", "vendored.md", "binary.md"] { - std::fs::write(dir.path().join(name), "# Head\n\nChanged.\n").unwrap(); - } - std::fs::remove_file(dir.path().join("deleted.md")).unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -generated.md linguist-generated -vendored.md linguist-vendored -binary.md binary -", - ) - .unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - git_ok(dir.path(), &["tag", "attribute-head"]); - - std::fs::write( - dir.path().join(".gitattributes"), - "* -linguist-generated -linguist-vendored -binary\n", - ) - .unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "checkout"]); - - let repo = gix::discover(dir.path()).unwrap(); - let report = analyze_diff_in_repo( - DiffInput { - from: "attribute-base".to_string(), - to: "attribute-head".to_string(), - paths: Vec::new(), - thresholds: Vec::new(), - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - let paths: Vec<&str> = report - .markdown_files - .iter() - .filter_map(|file| file.path.file_name()) - .collect(); - - assert_eq!(paths, vec!["kept.md"]); - } - - #[test] - fn analyze_diff_evaluates_history_thresholds_against_head_history() { - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("hot.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "history-base"]); - - std::fs::write(dir.path().join("hot.py"), "x = 1\ny = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - git_ok(dir.path(), &["tag", "history-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let thresholds = vec![Threshold::new( - "history.commit_frequency".parse().unwrap(), - 1.0, - Polarity::HigherIsWorse, - )]; - let report = analyze_diff_in_repo( - DiffInput { - from: "history-base".to_string(), - to: "history-head".to_string(), - paths: Vec::new(), - thresholds, - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - // hot.py was touched by 2 commits at head — above the limit of 1. - assert_eq!(report.threshold_violations.len(), 1); - let v = &report.threshold_violations[0]; - assert_eq!(v.path, "hot.py"); - assert_eq!(v.evaluation.actual, 2.0); - assert!(v.evaluation.violated); - } - - #[test] - fn analyze_diff_treats_undecodable_blobs_as_unavailable() { - // Invalid UTF-8 whose lossy replacement would still parse must - // not be analyzed: complexity/SLOC measured from mutated text - // would feed the history composites and static thresholds. - // The side reads as unavailable (recorded), and Git-only - // history thresholds still evaluate. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "latin-base"]); - - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\ny = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - git_ok(dir.path(), &["tag", "latin-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let thresholds = vec![ - // Git-only: must still evaluate (2 commits > 1). - Threshold::new( - "history.commit_frequency".parse().unwrap(), - 1.0, - Polarity::HigherIsWorse, - ), - // Static-dependent composite: must NOT evaluate against - // mutated text (any hotspot > -1 would trip if it did). - Threshold::new( - "history.hotspot".parse().unwrap(), - -1.0, - Polarity::HigherIsWorse, - ), - ]; - let report = analyze_diff_in_repo( - DiffInput { - from: "latin-base".to_string(), - to: "latin-head".to_string(), - paths: Vec::new(), - thresholds, - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - assert!( - report.analysis_errors.iter().any(|record| { - record - .diagnostics - .iter() - .any(|d| d.code == "engine.undecodable") - }), - "undecodable side must be recorded: {:?}", - report.analysis_errors - ); - let violated: Vec<&str> = report - .threshold_violations - .iter() - .map(|v| v.evaluation.selector.key.as_str()) - .collect(); - assert!( - violated.contains(&"history.commit_frequency"), - "git-only threshold must still evaluate: {violated:?}" - ); - assert!( - !violated.contains(&"history.hotspot"), - "a composite must not evaluate against mutated text: {violated:?}" - ); - } - - #[test] - fn analyze_diff_rejects_unknown_history_threshold_keys() { - // The engine boundary accepts arbitrary threshold keys: a - // typo'd history key must be surfaced as an analysis error - // and *not* evaluated — reading the unpublished key as `0.0` - // would silently pass (or, with a zero limit, fail) policy - // against a fabricated value. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("hot.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "typo-base"]); - - std::fs::write(dir.path().join("hot.py"), "x = 1\ny = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "head"]); - git_ok(dir.path(), &["tag", "typo-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let thresholds = vec![ - Threshold::new( - "history.commit_frequncy".parse().unwrap(), - 0.0, - Polarity::HigherIsWorse, - ), - // Valid key, unsupported aggregator: enrichment publishes - // root keys only, so this would read the `0.0` fallback. - Threshold::new( - "history.commit_frequency.max".parse().unwrap(), - -1.0, - Polarity::HigherIsWorse, - ), - ]; - let report = analyze_diff_in_repo( - DiffInput { - from: "typo-base".to_string(), - to: "typo-head".to_string(), - paths: Vec::new(), - thresholds, - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - assert!( - report.threshold_violations.is_empty(), - "a typo'd key must not evaluate: {:?}", - report.threshold_violations - ); - assert!( - report.analysis_errors.iter().any(|record| { - record - .diagnostics - .iter() - .any(|d| d.code == "engine.unknown_metric") - }), - "the typo must be surfaced: {:?}", - report.analysis_errors - ); - } - - #[test] - fn analyze_diff_history_thresholds_cover_restored_files() { - // Modified in one range commit, restored in the next: the - // endpoint trees are identical, but the head history gained - // two commits and the threshold must still trip. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("wobbly.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "restored-base"]); - - std::fs::write(dir.path().join("wobbly.py"), "x = 1\ny = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "grow"]); - std::fs::write(dir.path().join("wobbly.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "restore"]); - git_ok(dir.path(), &["tag", "restored-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let thresholds = vec![Threshold::new( - "history.commit_frequency".parse().unwrap(), - 2.0, - Polarity::HigherIsWorse, - )]; - let report = analyze_diff_in_repo( - DiffInput { - from: "restored-base".to_string(), - to: "restored-head".to_string(), - paths: Vec::new(), - thresholds, - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - assert_eq!(report.threshold_violations.len(), 1); - let v = &report.threshold_violations[0]; - assert_eq!(v.path, "wobbly.py"); - assert_eq!(v.evaluation.actual, 3.0); - assert!(v.evaluation.violated); - } - - #[test] - fn history_thresholds_evaluate_despite_parser_failures() { - // A malformed head file skips static thresholds (incomplete - // analysis) but must not silently pass parser-independent - // history policies. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("broken.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "broken-base"]); - - // Head revision: syntactically invalid Python. - std::fs::write(dir.path().join("broken.py"), "def broken(:\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "break it"]); - git_ok(dir.path(), &["tag", "broken-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let thresholds = vec![Threshold::new( - "history.commit_frequency".parse().unwrap(), - 1.0, - Polarity::HigherIsWorse, - )]; - let report = analyze_diff_in_repo( - DiffInput { - from: "broken-base".to_string(), - to: "broken-head".to_string(), - paths: Vec::new(), - thresholds, - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - assert_eq!(report.threshold_violations.len(), 1); - let v = &report.threshold_violations[0]; - assert_eq!(v.path, "broken.py"); - assert_eq!(v.evaluation.actual, 2.0); - assert!(v.evaluation.violated); - } - - #[test] - fn blocked_parses_suppress_static_dependent_history_thresholds() { - // history.hotspot and history.churn.relative read cognitive - // complexity and SLOC from the unavailable analysis — they - // must not evaluate against an empty space (hotspot 0, churn - // divided by 1), while Git-only keys still do. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("broken.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "mixed-base"]); - std::fs::write(dir.path().join("broken.py"), "def broken(:\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "break it"]); - git_ok(dir.path(), &["tag", "mixed-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let thresholds = vec![ - Threshold::new( - "history.commit_frequency".parse().unwrap(), - 1.0, - Polarity::HigherIsWorse, - ), - // Limit -1 would be violated by *any* evaluated value — - // including the fabricated 0 an empty space would yield. - Threshold::new( - "history.hotspot".parse().unwrap(), - -1.0, - Polarity::HigherIsWorse, - ), - Threshold::new( - "history.churn.relative".parse().unwrap(), - -1.0, - Polarity::HigherIsWorse, - ), - ]; - let report = analyze_diff_in_repo( - DiffInput { - from: "mixed-base".to_string(), - to: "mixed-head".to_string(), - paths: Vec::new(), - thresholds, - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - // Only the Git-only key evaluates against the fallback space. - assert_eq!(report.threshold_violations.len(), 1); - assert_eq!( - report.threshold_violations[0] - .evaluation - .selector - .key - .as_str(), - "history.commit_frequency" - ); - } - - #[test] - fn restored_markdown_evaluates_history_thresholds() { - // analyze_diff analyzes Markdown and evaluates thresholds on - // it — a restored README must not dodge a Git-only policy. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("README.md"), "# T\n\nStable.\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "md-thresh-base"]); - std::fs::write(dir.path().join("README.md"), "# T\n\nTemporary.\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "touch"]); - std::fs::write(dir.path().join("README.md"), "# T\n\nStable.\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "restore"]); - git_ok(dir.path(), &["tag", "md-thresh-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let thresholds = vec![Threshold::new( - "history.commit_frequency".parse().unwrap(), - 2.0, - Polarity::HigherIsWorse, - )]; - let report = analyze_diff_in_repo( - DiffInput { - from: "md-thresh-base".to_string(), - to: "md-thresh-head".to_string(), - paths: Vec::new(), - thresholds, - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - assert_eq!(report.threshold_violations.len(), 1); - let v = &report.threshold_violations[0]; - assert_eq!(v.path, "README.md"); - assert_eq!(v.evaluation.actual, 3.0); - } - - #[test] - fn split_boundary_renames_keeps_same_language_in_scope_renames_joined() { - let rename = mehen_git::ChangedFile { - path: PathBuf::from("src/after.py"), - status: ChangeStatus::Modified, - source_path: Some(PathBuf::from("src/before.py")), - }; - let out = split_boundary_renames(vec![rename], &|_| true, None) - .expect("no attribute filters") - .files; - assert_eq!(out.len(), 1); - assert_eq!(out[0].path, PathBuf::from("src/after.py")); - assert_eq!(out[0].status, ChangeStatus::Modified); - assert_eq!( - out[0].source_path.as_deref(), - Some(Path::new("src/before.py")) - ); - } - - #[test] - fn split_boundary_renames_reports_rename_to_unsupported_extension_as_deletion() { - // src/foo.py -> archive/foo.txt: the destination has no - // detectable language, so the Python file's disappearance must - // still be reported as a deletion instead of vanishing. - let rename = mehen_git::ChangedFile { - path: PathBuf::from("archive/foo.txt"), - status: ChangeStatus::Modified, - source_path: Some(PathBuf::from("src/foo.py")), - }; - let out = split_boundary_renames(vec![rename], &|_| true, None) - .expect("no attribute filters") - .files; - assert_eq!(out.len(), 1); - assert_eq!(out[0].path, PathBuf::from("src/foo.py")); - assert_eq!(out[0].status, ChangeStatus::Deleted); - assert!(out[0].source_path.is_none()); - } - - #[test] - fn split_boundary_renames_splits_cross_language_renames() { - // A .py -> .rs rename must not analyze the Python baseline - // with the Rust analyzer: both sides are reported separately. - let rename = mehen_git::ChangedFile { - path: PathBuf::from("src/port.rs"), - status: ChangeStatus::Modified, - source_path: Some(PathBuf::from("src/port.py")), - }; - let out = split_boundary_renames(vec![rename], &|_| true, None) - .expect("no attribute filters") - .files; - assert_eq!(out.len(), 2); - assert_eq!(out[0].path, PathBuf::from("src/port.py")); - assert_eq!(out[0].status, ChangeStatus::Deleted); - assert_eq!(out[1].path, PathBuf::from("src/port.rs")); - assert_eq!(out[1].status, ChangeStatus::Added); - } - - #[test] - fn split_boundary_renames_reports_rename_out_of_selected_scope_as_deletion() { - // With `--paths src`, a rename src/keep.py -> attic/keep.py - // must report the file leaving the scope. - let rename = mehen_git::ChangedFile { - path: PathBuf::from("attic/keep.py"), - status: ChangeStatus::Modified, - source_path: Some(PathBuf::from("src/keep.py")), - }; - let selected = |p: &Path| p.starts_with("src"); - let out = split_boundary_renames(vec![rename], &selected, None) - .expect("no attribute filters") - .files; - assert_eq!(out.len(), 1); - assert_eq!(out[0].path, PathBuf::from("src/keep.py")); - assert_eq!(out[0].status, ChangeStatus::Deleted); - } - - #[test] - fn split_boundary_renames_splits_when_destination_is_attribute_excluded() { - // A rename whose destination becomes `linguist-generated` at - // head must still report the analyzable source's deletion — - // keeping the pair joined would let the head-side attribute - // check drop the whole row. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - - std::fs::write(dir.path().join("hand_written.py"), "x = 1\ny = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "attr-rename-base"]); - - git_ok(dir.path(), &["mv", "hand_written.py", "generated.py"]); - std::fs::write( - dir.path().join(".gitattributes"), - "generated.py linguist-generated\n", - ) - .unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "generate"]); - git_ok(dir.path(), &["tag", "attr-rename-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let report = analyze_diff_in_repo( - DiffInput { - from: "attr-rename-base".to_string(), - to: "attr-rename-head".to_string(), - paths: Vec::new(), - thresholds: Vec::new(), - config: AnalysisConfig::default(), - }, - &repo, - ) - .unwrap(); - - let paths: Vec<&str> = report.files.iter().map(|f| f.path.as_str()).collect(); - // The source's deletion is reported; the attribute-excluded - // destination is not. - assert!( - paths.contains(&"hand_written.py"), - "source deletion must survive: {paths:?}" - ); - assert!( - !paths.contains(&"generated.py"), - "attribute-excluded destination must be dropped: {paths:?}" - ); - } - - /// A push-shaped [`ci::CiContext`] carrying a folded payload list. - fn push_ctx(files: Vec) -> ci::CiContext { - ci::CiContext { - provider: ci::CiProvider::GitHubActions, - event_name: "push".to_string(), - base_ref: None, - head_sha: None, - before_sha: None, - first_commit_sha: None, - changed_files: Some(files), - pr_number: None, - repository: None, - } - } - - #[test] - fn push_events_prefer_the_tree_diff_over_the_payload() { - // A GitHub push payload reports a rename as removed + added - // (and a reused source path as Modified) with no rename - // identity. When the refs resolve locally, the real tree diff - // must win so the diff compares against the old path's - // baseline instead of a zero baseline / full-history spike. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - std::fs::write(dir.path().join("before.py"), "x = 1\ny = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "base"]); - git_ok(dir.path(), &["tag", "payload-base"]); - git_ok(dir.path(), &["mv", "before.py", "after.py"]); - git_ok(dir.path(), &["commit", "-q", "-m", "rename"]); - git_ok(dir.path(), &["tag", "payload-head"]); - - let repo = gix::discover(dir.path()).unwrap(); - let ctx = Some(push_ctx(vec![ - mehen_git::ChangedFile { - path: PathBuf::from("before.py"), - status: ChangeStatus::Deleted, - source_path: None, - }, - mehen_git::ChangedFile { - path: PathBuf::from("after.py"), - status: ChangeStatus::Added, - source_path: None, - }, - ])); - let out = get_changed_files(&repo, "payload-base", "payload-head", &ctx, true).unwrap(); - assert_eq!(out.len(), 1, "tree diff joins the rename: {out:?}"); - assert_eq!(out[0].path, PathBuf::from("after.py")); - assert_eq!(out[0].status, ChangeStatus::Modified); - assert_eq!(out[0].source_path.as_deref(), Some(Path::new("before.py"))); - } - - #[test] - fn push_events_fall_back_to_the_payload_when_refs_unresolvable() { - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - let repo = gix::discover(dir.path()).unwrap(); - let payload = vec![mehen_git::ChangedFile { - path: PathBuf::from("a.py"), - status: ChangeStatus::Added, - source_path: None, - }]; - let ctx = Some(push_ctx(payload.clone())); - let out = get_changed_files(&repo, "no-such-ref", "also-missing", &ctx, true).unwrap(); - assert_eq!(out.len(), 1); - assert_eq!(out[0].path, payload[0].path); - } - - #[test] - fn empty_push_payloads_are_authoritative_even_when_refs_resolve() { - // A push whose fold is empty (add-then-remove, or a branch - // created at an existing commit) changed nothing — the - // resolvable HEAD~1 range would misreport the tip's last - // commit as this push's changes. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - std::fs::write(dir.path().join("existing.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "one"]); - std::fs::write(dir.path().join("tip.py"), "y = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "two"]); - - let repo = gix::discover(dir.path()).unwrap(); - let ctx = Some(push_ctx(Vec::new())); - // HEAD~1..HEAD resolves and would report tip.py; the empty - // payload must win. - let out = get_changed_files(&repo, "HEAD~1", "HEAD", &ctx, true).unwrap(); - assert!(out.is_empty(), "empty payload is authoritative: {out:?}"); - } - - #[test] - fn explicit_refs_ignore_the_push_payload_entirely() { - // `--from`/`--to` overrides compare a range the event payload - // knows nothing about: neither an empty fold (which would - // blank out the report) nor an unresolvable-baseline fallback - // may apply. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - std::fs::write(dir.path().join("existing.py"), "x = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "one"]); - std::fs::write(dir.path().join("tip.py"), "y = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "two"]); - - let repo = gix::discover(dir.path()).unwrap(); - let ctx = Some(push_ctx(Vec::new())); - let out = get_changed_files(&repo, "HEAD~1", "HEAD", &ctx, false).unwrap(); - assert_eq!(out.len(), 1, "explicit range must be diffed: {out:?}"); - assert_eq!(out[0].path, PathBuf::from("tip.py")); - } - - #[test] - fn unresolvable_baseline_payloads_degrade_modified_and_drop_deleted() { - // With the baseline commit gone (force-push), every baseline - // blob read would fail downstream: a `Modified` row would - // fabricate a full-value-vs-zero delta and a `Deleted` row - // would vanish silently. The fallback must degrade honestly: - // modified files become current-state-only `Added` rows (🆕), - // deletions are dropped with a warning. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - let repo = gix::discover(dir.path()).unwrap(); - let ctx = Some(push_ctx(vec![ - mehen_git::ChangedFile { - path: PathBuf::from("kept.py"), - status: ChangeStatus::Modified, - source_path: None, - }, - mehen_git::ChangedFile { - path: PathBuf::from("gone.py"), - status: ChangeStatus::Deleted, - source_path: None, - }, - mehen_git::ChangedFile { - path: PathBuf::from("new.py"), - status: ChangeStatus::Added, - source_path: None, - }, - ])); - let out = get_changed_files(&repo, "no-such-ref", "also-missing", &ctx, true).unwrap(); - let mut rows: Vec<(&str, ChangeStatus)> = out - .iter() - .map(|f| (f.path.to_str().unwrap(), f.status)) - .collect(); - rows.sort_unstable_by_key(|(path, _)| *path); - assert_eq!( - rows, - vec![ - ("kept.py", ChangeStatus::Added), - ("new.py", ChangeStatus::Added) - ] - ); - } - - #[test] - fn branch_creation_pushes_prefer_the_full_range_tree_diff() { - // With `resolve_refs` supplying the first pushed commit's - // parent as the baseline, a branch-creation push gets a - // full-range tree diff (which carries rename identity the - // payload can never express). The payload — deliberately - // incomplete here — must lose when the baseline resolves. - let dir = tempfile::tempdir().unwrap(); - git_ok(dir.path(), &["init", "-q", "-b", "main"]); - git_ok(dir.path(), &["config", "commit.gpgsign", "false"]); - std::fs::write(dir.path().join("base.py"), "base = 0\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "main base"]); - // The "pushed branch": two commits on top of main. - std::fs::write(dir.path().join("first.py"), "a = 1\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "one"]); - std::fs::write(dir.path().join("second.py"), "b = 2\n").unwrap(); - git_ok(dir.path(), &["add", "-A"]); - git_ok(dir.path(), &["commit", "-q", "-m", "two"]); - - let repo = gix::discover(dir.path()).unwrap(); - let ctx = push_ctx(vec![mehen_git::ChangedFile { - path: PathBuf::from("first.py"), - status: ChangeStatus::Added, - source_path: None, - }]); - // The baseline resolve_refs would supply: first pushed - // commit's parent = HEAD~2 here. - let out = get_changed_files(&repo, "HEAD~2", "HEAD", &Some(ctx), true).unwrap(); - let mut paths: Vec<&str> = out.iter().filter_map(|f| f.path.to_str()).collect(); - paths.sort_unstable(); - assert_eq!( - paths, - vec!["first.py", "second.py"], - "the resolvable full-range tree diff must win over the payload" - ); - } - - fn analysis_with_diagnostics(diagnostics: Vec) -> LanguageAnalysis { - LanguageAnalysis { - language: Language::Rust, - backend: AnalysisBackend::TreeSitter, - diagnostics, - root: MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()), - contributions: Vec::new(), - } - } - - #[test] - fn collect_diagnostics_records_warning_only_batches() { - // Regression: prior gate dropped warning-only batches before - // they reached `analysis_errors`, so a Ruff-style recoverable - // parse warning or a markdown cross-reference warning would - // never surface in `mehen diff --format json`. The - // `analysis_errors` field carries `severity` per entry, so - // CLI exit-code routing can still distinguish warning vs. - // error vs. fatal — but emitting them is required so callers - // can see them at all. - let analysis = - analysis_with_diagnostics(vec![ParseDiagnostic::warning("python.style", "long line")]); - let mut report = empty_report(); - collect_diagnostics( - &mut report, - &Utf8PathBuf::from("src/main.py"), - DiffSide::Head, - &analysis, - ); - assert_eq!(report.analysis_errors.len(), 1); - let rec = &report.analysis_errors[0]; - assert_eq!(rec.path, Utf8PathBuf::from("src/main.py")); - assert_eq!(rec.diagnostics.len(), 1); - assert_eq!(rec.diagnostics[0].code, "python.style"); - } - - #[test] - fn collect_diagnostics_skips_empty_batch() { - let analysis = analysis_with_diagnostics(Vec::new()); - let mut report = empty_report(); - collect_diagnostics( - &mut report, - &Utf8PathBuf::from("src/main.py"), - DiffSide::Head, - &analysis, - ); - assert!(report.analysis_errors.is_empty()); - } - - #[test] - fn collect_diagnostics_records_blocking_batch() { - let analysis = analysis_with_diagnostics(vec![ - ParseDiagnostic::warning("python.style", "long line"), - ParseDiagnostic::error("python.syntax_error", "unexpected token"), - ]); - let mut report = empty_report(); - collect_diagnostics( - &mut report, - &Utf8PathBuf::from("src/main.py"), - DiffSide::Base, - &analysis, - ); - assert_eq!(report.analysis_errors.len(), 1); - // Both diagnostics are preserved, so CLI exit-code routing - // still sees the error severity. - assert_eq!(report.analysis_errors[0].diagnostics.len(), 2); - } - - #[test] - fn higher_is_worse_threshold_above_limit_violates() { - let analysis = analysis_with_metric("cognitive.sum", 42.0); - let thresholds = vec![Threshold::new( - "cognitive.sum".parse().unwrap(), - 30.0, - Polarity::HigherIsWorse, - )]; - let mut report = empty_report(); - evaluate_thresholds( - &mut report, - &Utf8PathBuf::from("src/main.rs"), - &thresholds, - &analysis.root, - ); - assert_eq!(report.threshold_violations.len(), 1); - let v = &report.threshold_violations[0]; - assert_eq!(v.path, "src/main.rs"); - assert_eq!(v.evaluation.actual, 42.0); - assert_eq!(v.evaluation.limit, 30.0); - assert!(v.evaluation.violated); - } - - #[test] - fn higher_is_worse_threshold_at_or_below_limit_does_not_violate() { - let analysis = analysis_with_metric("cognitive.sum", 30.0); - let thresholds = vec![Threshold::new( - "cognitive.sum".parse().unwrap(), - 30.0, - Polarity::HigherIsWorse, - )]; - let mut report = empty_report(); - evaluate_thresholds( - &mut report, - &Utf8PathBuf::from("src/main.rs"), - &thresholds, - &analysis.root, - ); - assert!(report.threshold_violations.is_empty()); - } - - #[test] - fn higher_is_better_threshold_below_limit_violates() { - let analysis = analysis_with_metric("mi.visual_studio", 49.0); - let thresholds = vec![Threshold::new( - "mi.visual_studio".parse().unwrap(), - 50.0, - Polarity::HigherIsBetter, - )]; - let mut report = empty_report(); - evaluate_thresholds( - &mut report, - &Utf8PathBuf::from("src/main.rs"), - &thresholds, - &analysis.root, - ); - assert_eq!(report.threshold_violations.len(), 1); - assert!(report.threshold_violations[0].evaluation.violated); - } - - #[test] - fn multiple_thresholds_each_evaluated_independently() { - let mut analysis = analysis_with_metric("cyclomatic.sum", 50.0); - analysis - .root - .metrics - .insert(MetricKey::new("cognitive.sum"), 5.0); - let thresholds = vec![ - Threshold::new( - "cyclomatic.sum".parse().unwrap(), - 10.0, - Polarity::HigherIsWorse, - ), - Threshold::new( - "cognitive.sum".parse().unwrap(), - 30.0, - Polarity::HigherIsWorse, - ), - ]; - let mut report = empty_report(); - evaluate_thresholds( - &mut report, - &Utf8PathBuf::from("src/main.rs"), - &thresholds, - &analysis.root, - ); - // Only cyclomatic.sum exceeds its limit; cognitive.sum is fine. - assert_eq!(report.threshold_violations.len(), 1); - assert_eq!( - report.threshold_violations[0] - .evaluation - .selector - .key - .as_str(), - "cyclomatic" - ); - } - - #[test] - fn empty_thresholds_produce_no_violations() { - let analysis = analysis_with_metric("cognitive.sum", 999.0); - let mut report = empty_report(); - evaluate_thresholds( - &mut report, - &Utf8PathBuf::from("src/main.rs"), - &[], - &analysis.root, - ); - assert!(report.threshold_violations.is_empty()); - } - - #[test] - fn path_is_selected_treats_curdir_as_match_all() { - // Regression: callers that scope `analyze_diff` to "the whole - // repo" by passing `"."` (or `"./src"` for "src and below") - // used to silently match nothing because raw `starts_with` - // never strips the `.` component. The normalized prefix - // collapses `"."` to empty (= match all) and `"./src"` to - // `"src"` so changed files are actually included. - let changed = Utf8PathBuf::from("src/main.rs"); - - // `"."` selects every file. - assert!(path_is_selected(&changed, &[Utf8PathBuf::from(".")])); - // `""` likewise — both spellings of "root" must match. - assert!(path_is_selected(&changed, &[Utf8PathBuf::from("")])); - // `"./src"` is a real prefix of `src/main.rs`. - assert!(path_is_selected(&changed, &[Utf8PathBuf::from("./src")])); - // A directory we're *not* under must still fail. - assert!(!path_is_selected(&changed, &[Utf8PathBuf::from("./tests")])); - } - - #[test] - fn normalize_utf8_filter_strips_curdir_components() { - assert_eq!( - normalize_utf8_filter(&Utf8PathBuf::from("./src")), - Utf8PathBuf::from("src"), - ); - assert_eq!( - normalize_utf8_filter(&Utf8PathBuf::from(".")), - Utf8PathBuf::from(""), - ); - assert_eq!( - normalize_utf8_filter(&Utf8PathBuf::from("./a/./b")), - Utf8PathBuf::from("a/b"), - ); - assert_eq!( - normalize_utf8_filter(&Utf8PathBuf::from("src")), - Utf8PathBuf::from("src"), - ); - } - - // ── pre-1.0 CLI orchestrator tests ───────────────────────────────── - - use clap::Parser as _; - - #[derive(clap::Parser, Debug)] - struct TestDiffCli { - #[command(flatten)] - opts: DiffOpts, - } - - #[test] - fn test_parse_metric_selectors_defaults() { - // The §9.4 default comment set: one column per orthogonal - // dimension plus the two change-risk history signals. - let selectors = parse_metric_selectors(&[]); - assert_eq!(selectors.len(), 5); - assert_eq!(selectors[0].name, "cognitive"); - assert_eq!(selectors[1].name, "abc"); - assert_eq!(selectors[2].name, "mi.visual_studio"); - assert_eq!(selectors[3].name, "history.hotspot"); - assert_eq!(selectors[4].name, "history.churn.relative"); - } - - #[test] - fn test_parse_metric_selectors_custom() { - let specs = vec!["mi.original".to_string(), "halstead.volume".to_string()]; - let selectors = parse_metric_selectors(&specs); - assert_eq!(selectors.len(), 2); - assert_eq!(selectors[0].name, "mi.original"); - assert_eq!(selectors[0].polarity, SelectorPolarity::HigherIsBetter); - assert_eq!(selectors[1].name, "halstead.volume"); - assert_eq!(selectors[1].polarity, SelectorPolarity::LowerIsBetter); - } - - #[test] - fn test_parse_metric_selectors_all_mi_variants() { - let specs = vec![ - "mi.original".to_string(), - "mi.sei".to_string(), - "mi.visual_studio".to_string(), - ]; - let selectors = parse_metric_selectors(&specs); - assert_eq!(selectors.len(), 3); - assert_eq!(selectors[0].name, "mi.original"); - assert_eq!(selectors[1].name, "mi.sei"); - assert_eq!(selectors[2].name, "mi.visual_studio"); - for sel in &selectors { - assert_eq!(sel.polarity, SelectorPolarity::HigherIsBetter); - } - } - - #[test] - fn test_parse_metric_selectors_bare_mi_is_unknown() { - let specs = vec!["mi".to_string()]; - let selectors = parse_metric_selectors(&specs); - assert!(selectors.is_empty()); - } - - #[test] - fn test_parse_metric_selectors_polarity_override() { - let specs = vec![ - "+nom.functions".to_string(), - "-mi.visual_studio".to_string(), - ]; - let selectors = parse_metric_selectors(&specs); - assert_eq!(selectors.len(), 2); - assert_eq!(selectors[0].name, "nom.functions"); - assert_eq!(selectors[0].polarity, SelectorPolarity::HigherIsBetter); - assert_eq!(selectors[1].name, "mi.visual_studio"); - assert_eq!(selectors[1].polarity, SelectorPolarity::LowerIsBetter); - } - - #[test] - fn test_parse_metric_selectors_unknown() { - let specs = vec!["nonexistent".to_string()]; - let selectors = parse_metric_selectors(&specs); - assert!(selectors.is_empty()); - } - - #[test] - fn test_ignore_git_attributes_defaults_to_true() { - let cli = TestDiffCli::try_parse_from(["mehen"]).unwrap(); - assert!(cli.opts.ignore_git_attributes); - } - - #[test] - fn test_ignore_git_attributes_accepts_bare_flag() { - let cli = TestDiffCli::try_parse_from(["mehen", "--ignore-git-attributes"]).unwrap(); - assert!(cli.opts.ignore_git_attributes); - } - - #[test] - fn test_ignore_git_attributes_can_be_disabled() { - let cli = TestDiffCli::try_parse_from(["mehen", "--ignore-git-attributes=false"]).unwrap(); - assert!(!cli.opts.ignore_git_attributes); - } - - #[test] - fn test_ignore_generated_remains_a_compatibility_alias() { - let cli = TestDiffCli::try_parse_from(["mehen", "--ignore-generated=false"]).unwrap(); - assert!(!cli.opts.ignore_git_attributes); - } - - #[test] - fn test_trend_emoji_lower_is_better() { - assert_eq!( - trend_emoji(1.0, SelectorPolarity::LowerIsBetter), - "\u{1F534}" - ); - assert_eq!( - trend_emoji(-1.0, SelectorPolarity::LowerIsBetter), - "\u{1F7E2}" - ); - assert_eq!( - trend_emoji(0.0, SelectorPolarity::LowerIsBetter), - "\u{26AA}" - ); - } - - #[test] - fn test_trend_emoji_higher_is_better() { - assert_eq!( - trend_emoji(1.0, SelectorPolarity::HigherIsBetter), - "\u{1F7E2}" - ); - assert_eq!( - trend_emoji(-1.0, SelectorPolarity::HigherIsBetter), - "\u{1F534}" - ); - assert_eq!( - trend_emoji(0.0, SelectorPolarity::HigherIsBetter), - "\u{26AA}" - ); - } - - #[test] - fn test_format_f64_integer() { - assert_eq!(format_f64(42.0), "42"); - assert_eq!(format_f64(0.0), "0"); - } - - #[test] - fn test_format_f64_decimal() { - assert_eq!(format_f64(2.75), "2.75"); - assert_eq!(format_f64(100.567), "100.57"); - } - - #[test] - fn test_format_metric_cell_new() { - let md = MetricDiff { - name: "cyclomatic", - label: "Cyclomatic", - current: 5.0, - baseline: 0.0, - delta: 5.0, - polarity: SelectorPolarity::LowerIsBetter, - is_new: true, - is_deleted: false, - current_unavailable: false, - baseline_unavailable: false, - }; - assert_eq!(format_metric_cell(&md, "main"), "5 \u{1F195}"); - } - - #[test] - fn test_format_metric_cell_unchanged() { - let md = MetricDiff { - name: "cyclomatic", - label: "Cyclomatic", - current: 5.0, - baseline: 5.0, - delta: 0.0, - polarity: SelectorPolarity::LowerIsBetter, - is_new: false, - is_deleted: false, - current_unavailable: false, - baseline_unavailable: false, - }; - assert_eq!(format_metric_cell(&md, "main"), "5 \u{26AA}"); - } - - #[test] - fn test_format_metric_cell_increase_lower_is_better() { - let md = MetricDiff { - name: "cyclomatic", - label: "Cyclomatic", - current: 12.0, - baseline: 8.0, - delta: 4.0, - polarity: SelectorPolarity::LowerIsBetter, - is_new: false, - is_deleted: false, - current_unavailable: false, - baseline_unavailable: false, - }; - assert_eq!(format_metric_cell(&md, "main"), "12 (main: 8) \u{1F534}"); - } - - #[test] - fn test_format_metric_cell_deleted() { - let md = MetricDiff { - name: "cyclomatic", - label: "Cyclomatic", - current: 0.0, - baseline: 10.0, - delta: -10.0, - polarity: SelectorPolarity::LowerIsBetter, - is_new: false, - is_deleted: true, - current_unavailable: false, - baseline_unavailable: false, - }; - assert_eq!(format_metric_cell(&md, "main"), "0 (was: 10) \u{1F7E2}"); - } - - #[test] - fn test_format_metric_cell_unavailable_sides_claim_no_trend() { - // A static-dependent composite on a side without static - // analysis is *unavailable*, not zero: the cell must not - // present the placeholder as a measurement or claim a trend - // (a green arrow for "hotspot 12 → 0" would fake a cleared - // hotspot). - let md = |current_unavailable: bool, baseline_unavailable: bool, is_new, is_deleted| { - MetricDiff { - name: "history.hotspot", - label: "Hotspot", - current: 0.0, - baseline: 12.0, - delta: 0.0, - polarity: SelectorPolarity::LowerIsBetter, - is_new, - is_deleted, - current_unavailable, - baseline_unavailable, - } - }; - assert_eq!( - format_metric_cell(&md(true, false, false, false), "main"), - "n/a (main: 12)" - ); - assert_eq!( - format_metric_cell(&md(false, true, false, false), "main"), - "0 (main: n/a)" - ); - assert_eq!( - format_metric_cell(&md(true, true, false, false), "main"), - "n/a" - ); - assert_eq!( - format_metric_cell(&md(true, false, true, false), "main"), - "n/a \u{1F195}" - ); - assert_eq!( - format_metric_cell(&md(false, true, false, true), "main"), - "0 (was: n/a)" - ); - } - - #[test] - fn test_file_diff_all_unchanged() { - let diff = FileDiff { - path: PathBuf::from("foo.rs"), - metrics: vec![MetricDiff { - name: "cyclomatic", - label: "Cyclomatic", - current: 5.0, - baseline: 5.0, - delta: 0.0, - polarity: SelectorPolarity::LowerIsBetter, - is_new: false, - is_deleted: false, - current_unavailable: false, - baseline_unavailable: false, - }], - is_new: false, - is_deleted: false, - functions: 0, - }; - assert!(diff.all_unchanged()); - } - - /// `DiffOpts` fixture for ref-resolution tests — only `from`/`to` - /// vary; everything else is the clap default. - fn resolve_refs_opts(from: Option<&str>, to: Option<&str>) -> DiffOpts { - DiffOpts { - from: from.map(str::to_string), - to: to.map(str::to_string), - metrics: vec![], - paths: vec![], - include: vec![], - exclude: vec![], - output_format: None, - show_unchanged: false, - ignore_git_attributes: true, - fail_on: vec![], - coverage: Default::default(), - base_coverage: vec![], - } - } - - #[test] - fn test_resolve_refs_explicit() { - let opts = resolve_refs_opts(Some("abc"), Some("def")); - let (from, to) = resolve_refs(&opts, &None); - assert_eq!(from, "abc"); - assert_eq!(to, "def"); - } - - #[test] - fn test_resolve_refs_no_ci() { - let opts = resolve_refs_opts(None, None); - let (from, to) = resolve_refs(&opts, &None); - assert_eq!(from, "main"); - assert_eq!(to, "HEAD"); - } - - #[test] - fn test_resolve_refs_github_pr() { - let ctx = ci::CiContext { - provider: ci::CiProvider::GitHubActions, - event_name: "pull_request".to_string(), - base_ref: Some("develop".to_string()), - head_sha: Some("abc123".to_string()), - before_sha: None, - first_commit_sha: None, - changed_files: None, - pr_number: Some(42), - repository: Some("owner/repo".to_string()), - }; - let opts = resolve_refs_opts(None, None); - let (from, to) = resolve_refs(&opts, &Some(ctx)); - assert_eq!(from, "origin/develop"); - assert_eq!(to, "abc123"); - } - - #[test] - fn test_resolve_refs_github_push() { - let ctx = ci::CiContext { - provider: ci::CiProvider::GitHubActions, - event_name: "push".to_string(), - base_ref: None, - head_sha: Some("def456".to_string()), - before_sha: None, - first_commit_sha: None, - changed_files: None, - pr_number: None, - repository: Some("owner/repo".to_string()), - }; - let opts = resolve_refs_opts(None, None); - let (from, to) = resolve_refs(&opts, &Some(ctx)); - assert_eq!(from, "HEAD~1"); - assert_eq!(to, "def456"); - } - - #[test] - fn test_resolve_refs_github_push_uses_payload_before_sha() { - // A multi-commit push must diff against the branch tip before - // the push, not just the final commit's parent — otherwise - // renames/baselines from earlier commits in the push vanish. - let ctx = ci::CiContext { - provider: ci::CiProvider::GitHubActions, - event_name: "push".to_string(), - base_ref: None, - head_sha: Some("def456".to_string()), - before_sha: Some("abc999".to_string()), - first_commit_sha: None, - changed_files: None, - pr_number: None, - repository: Some("owner/repo".to_string()), - }; - let opts = resolve_refs_opts(None, None); - let (from, to) = resolve_refs(&opts, &Some(ctx)); - assert_eq!(from, "abc999"); - assert_eq!(to, "def456"); - } - - #[test] - fn test_resolve_refs_branch_creation_uses_first_pushed_parent() { - // Branch creation has no `before`; the parent of the first - // pushed commit is the right analysis baseline so files - // changed only in earlier pushed commits still show deltas. - let ctx = ci::CiContext { - provider: ci::CiProvider::GitHubActions, - event_name: "push".to_string(), - base_ref: None, - head_sha: Some("def456".to_string()), - before_sha: None, - first_commit_sha: Some("f1r5t".to_string()), - changed_files: None, - pr_number: None, - repository: Some("owner/repo".to_string()), - }; - let opts = resolve_refs_opts(None, None); - let (from, to) = resolve_refs(&opts, &Some(ctx)); - assert_eq!(from, "f1r5t~1"); - assert_eq!(to, "def456"); - } - - #[test] - fn test_normalize_path_filters() { - let paths = normalize_path_filters(&[ - PathBuf::from("."), - PathBuf::from("./internal"), - PathBuf::from("cmd/tally/"), - ]); - - assert_eq!( - paths, - vec![ - PathBuf::new(), - PathBuf::from("internal"), - PathBuf::from("cmd/tally") - ] - ); - } - - #[test] - fn test_legacy_path_is_selected() { - let paths = vec![PathBuf::from("internal"), PathBuf::from("main.go")]; - - assert!(legacy_path_is_selected( - Path::new("internal/config/config.go"), - &paths - )); - assert!(legacy_path_is_selected(Path::new("main.go"), &paths)); - assert!(!legacy_path_is_selected( - Path::new("internal2/config.go"), - &paths - )); - assert!(!legacy_path_is_selected( - Path::new("cmd/tally/main.go"), - &paths - )); - - let paths_with_root = vec![PathBuf::from("internal"), PathBuf::new()]; - assert!(legacy_path_is_selected( - Path::new("cmd/tally/main.go"), - &paths_with_root - )); - } - - #[test] - fn test_diff_filter_reads_all_default_exclusion_attributes() { - let dir = tempfile::tempdir().unwrap(); - let repo = gix::init(dir.path()).unwrap(); - std::fs::create_dir_all(dir.path().join("src")).unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -*.rs linguist-generated -src/manual.rs -linguist-generated -src/false.rs linguist-generated=false -src/unspecified.rs !linguist-generated -src/value.txt linguist-generated=true -src/vendor.txt linguist-vendored -src/archive.txt binary -", - ) - .unwrap(); - - let mut filter = GitAttributeFilter::new(&repo).unwrap(); - - assert!( - filter - .excludes_relative_path(Path::new("src/generated.rs")) - .unwrap() - ); - assert!( - !filter - .excludes_relative_path(Path::new("src/manual.rs")) - .unwrap() - ); - assert!( - !filter - .excludes_relative_path(Path::new("src/false.rs")) - .unwrap() - ); - assert!( - !filter - .excludes_relative_path(Path::new("src/unspecified.rs")) - .unwrap() - ); - for path in ["src/value.txt", "src/vendor.txt", "src/archive.txt"] { - assert!(filter.excludes_relative_path(Path::new(path)).unwrap()); - } - } - - // ── `--fail-on new-broken-link` gating tests ─────────────────────── - // - // Ensure the CI gate keys on `(class, destination)` identity — a link - // that merely shifts to a different line number MUST NOT trip the gate, - // but a duplicate broken destination MUST. - - fn broken_link_for_fail_on( - line: u64, - class: mehen_markdown::types::LinkClass, - destination: &str, - ) -> mehen_markdown::types::LinkRecord { - mehen_markdown::types::LinkRecord { - line, - class, - destination: destination.to_string(), - text: String::new(), - is_image: false, - is_bare_url: false, - resolved: Some(false), - } - } - - fn minimal_md_metrics(path: &str) -> mehen_markdown::types::MarkdownMetrics { - mehen_markdown::types::MarkdownMetrics { - path: path.to_string(), - loc: Default::default(), - loc_ratios: Default::default(), - size: Default::default(), - ecu_inputs: Default::default(), - sections: vec![], - complexity: Default::default(), - links: Default::default(), - link_records: vec![], - visuals: Default::default(), - tables: Default::default(), - maintainability: Default::default(), - grounding: Default::default(), - ai_era: Default::default(), - review: Default::default(), - artifacts: vec![], - prose: Default::default(), - } - } - - #[test] - fn fail_on_new_broken_link_ignores_line_only_shift() { - let mut head = minimal_md_metrics("docs/a.md"); - head.link_records = vec![broken_link_for_fail_on( - 42, - mehen_markdown::types::LinkClass::Relative, - "./guide.md", - )]; - let mut base = minimal_md_metrics("docs/a.md"); - base.link_records = vec![broken_link_for_fail_on( - 10, - mehen_markdown::types::LinkClass::Relative, - "./guide.md", - )]; - - let doc = DocDiffFile { - path: PathBuf::from("docs/a.md"), - head: Some(head), - base: Some(base), - is_new: false, - is_deleted: false, - }; - - let flags = vec![FailOn::NewBrokenLink]; - let failures = evaluate_fail_on(&flags, std::slice::from_ref(&doc)); - assert!( - failures.is_empty(), - "line-only shift must not trip new-broken-link; got: {failures:?}", - ); - } - - #[test] - fn fail_on_new_broken_link_trips_on_new_occurrence() { - // Head has 2 broken refs to the same destination; base has 1. The - // second occurrence is net-new so the gate must fire. - let mut head = minimal_md_metrics("docs/a.md"); - head.link_records = vec![ - broken_link_for_fail_on(10, mehen_markdown::types::LinkClass::Relative, "./g.md"), - broken_link_for_fail_on(20, mehen_markdown::types::LinkClass::Relative, "./g.md"), - ]; - let mut base = minimal_md_metrics("docs/a.md"); - base.link_records = vec![broken_link_for_fail_on( - 10, - mehen_markdown::types::LinkClass::Relative, - "./g.md", - )]; - - let doc = DocDiffFile { - path: PathBuf::from("docs/a.md"), - head: Some(head), - base: Some(base), - is_new: false, - is_deleted: false, - }; - - let flags = vec![FailOn::NewBrokenLink]; - let failures = evaluate_fail_on(&flags, std::slice::from_ref(&doc)); - assert_eq!(failures.len(), 1); - assert!(failures[0].starts_with("new-broken-link:")); - } - - #[test] - fn fail_on_new_broken_link_trips_on_brand_new_destination() { - let mut head = minimal_md_metrics("docs/a.md"); - head.link_records = vec![broken_link_for_fail_on( - 5, - mehen_markdown::types::LinkClass::Relative, - "./added.md", - )]; - let base = minimal_md_metrics("docs/a.md"); - - let doc = DocDiffFile { - path: PathBuf::from("docs/a.md"), - head: Some(head), - base: Some(base), - is_new: false, - is_deleted: false, - }; - - let flags = vec![FailOn::NewBrokenLink]; - let failures = evaluate_fail_on(&flags, std::slice::from_ref(&doc)); - assert_eq!(failures.len(), 1); - } - - // ── print_json error-propagation ──────────────────────────────────── - - #[test] - fn print_json_happy_path_is_ok() { - let diffs: Vec = vec![FileDiff { - path: PathBuf::from("a.rs"), - metrics: vec![], - is_new: false, - is_deleted: false, - functions: 0, - }]; - let res = print_json(&diffs, None, &[]); - assert!(res.is_ok(), "valid input must serialize cleanly"); - } - - #[test] - fn print_json_returns_result_type() { - // §39 regression guard: print_json must return `Result<_, _>` so - // callers can exit non-zero on serialization failure. Before, the - // emitter used `unwrap_or_default` and silently wrote an empty - // JSON document to stdout when serde_json failed. - let diffs: Vec = vec![]; - let res: Result<(), Box> = print_json(&diffs, None, &[]); - assert!(res.is_ok()); - } - - // ── `--fail-on` CLI-parse validation ──────────────────────────────── - - #[test] - fn fail_on_parser_accepts_every_documented_value() { - let cli = TestDiffCli::try_parse_from([ - "mehen", - "--fail-on", - "dmi-drop,new-broken-link,filler-high,all", - ]) - .expect("every documented value must parse"); - assert_eq!( - cli.opts.fail_on, - vec![ - FailOn::DmiDrop, - FailOn::NewBrokenLink, - FailOn::FillerHigh, - FailOn::All, - ] - ); - } - - #[test] - fn fail_on_parser_trims_and_lowercases() { - let cli = TestDiffCli::try_parse_from(["mehen", "--fail-on", " Dmi-Drop , ALL "]) - .expect("case and whitespace must be normalized"); - assert_eq!(cli.opts.fail_on, vec![FailOn::DmiDrop, FailOn::All]); - } - - #[test] - fn fail_on_parser_rejects_unknown_value() { - let err = TestDiffCli::try_parse_from(["mehen", "--fail-on", "new-borken-link"]) - .expect_err("unknown value must be rejected"); - assert!( - matches!( - err.kind(), - clap::error::ErrorKind::InvalidValue | clap::error::ErrorKind::ValueValidation, - ), - "expected InvalidValue or ValueValidation, got: {:?}", - err.kind(), - ); - let rendered = err.to_string(); - assert!( - rendered.contains("new-borken-link"), - "error must mention the offending value, got: {rendered}" - ); - } - - #[test] - fn fail_on_parser_rejects_partial_match_in_list() { - let err = TestDiffCli::try_parse_from(["mehen", "--fail-on", "dmi-drop,filler-hihg"]) - .expect_err("list with an invalid entry must be rejected"); - assert!(matches!( - err.kind(), - clap::error::ErrorKind::InvalidValue | clap::error::ErrorKind::ValueValidation, - )); - assert!(err.to_string().contains("filler-hihg")); - } -} diff --git a/crates/mehen-engine/src/dispatcher.rs b/crates/mehen-engine/src/dispatcher.rs deleted file mode 100644 index 7705c719..00000000 --- a/crates/mehen-engine/src/dispatcher.rs +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use mehen_core::{ - AnalysisConfig, AnalysisError, LanguageAnalysis, LanguageDispatcher, Result, SourceFile, -}; - -use crate::registry::AnalyzerRegistry; - -/// The only `LanguageDispatcher` in 1.0. -/// -/// Owned by `mehen-engine` and handed to `mehen-markdown::analyze_markdown` -/// (and any future analyzer that needs to recursively analyze a nested -/// fragment) so the caller never needs a compile-time dependency on every -/// language crate. -/// -/// Recursion is bounded by `AnalysisConfig::max_dispatch_depth`. Going past -/// the limit returns an `Internal` error rather than producing partial -/// results — the dispatcher is the right layer to enforce the bound. -pub struct EngineDispatcher<'r> { - registry: &'r AnalyzerRegistry, -} - -impl<'r> EngineDispatcher<'r> { - pub fn new(registry: &'r AnalyzerRegistry) -> Self { - Self { registry } - } -} - -impl<'r> LanguageDispatcher for EngineDispatcher<'r> { - fn analyze(&self, source: SourceFile, config: &AnalysisConfig) -> Result { - if config.dispatch_depth >= config.max_dispatch_depth { - return Err(AnalysisError::Internal(format!( - "max dispatch depth exceeded ({})", - config.max_dispatch_depth - ))); - } - let mut child_config = config.clone(); - child_config.dispatch_depth = config.dispatch_depth.saturating_add(1); - - let analyzer = self - .registry - .analyzer_for(source.language) - .ok_or(AnalysisError::AnalyzerUnavailable(source.language))?; - analyzer.analyze(&source, &child_config) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn dispatcher_enforces_depth() { - // Build a registry without any registered analyzer to ensure the - // depth check fires before the lookup. We probe with depth equal - // to the limit, so the dispatcher should refuse without trying to - // call any analyzer. - let registry = AnalyzerRegistry::new(); - let dispatcher = EngineDispatcher::new(®istry); - - let source = SourceFile::new("x.md".into(), mehen_core::Language::Markdown, String::new()); - let mut config = AnalysisConfig::production(); - config.dispatch_depth = config.max_dispatch_depth; - - let err = dispatcher.analyze(source, &config).unwrap_err(); - match err { - AnalysisError::Internal(msg) => assert!(msg.contains("dispatch depth")), - other => panic!("expected Internal, got {other:?}"), - } - } - - #[test] - fn default_config_does_not_trip_depth_guard_on_first_dispatch() { - // Regression for PR #95 review: when `AnalysisConfig` derived - // `Default`, `max_dispatch_depth` was `0` and the very first - // dispatch hit `dispatch_depth (0) >= max_dispatch_depth (0)`. - // The manual `Default` impl on `AnalysisConfig` now reserves a - // realistic depth budget, so callers using `default()` should - // sail past the depth check and only fail (in this test setup) - // because the empty registry has no analyzer registered. - let registry = AnalyzerRegistry::new(); - let dispatcher = EngineDispatcher::new(®istry); - - let source = SourceFile::new("x.md".into(), mehen_core::Language::Markdown, String::new()); - let config = AnalysisConfig::default(); - - let err = dispatcher.analyze(source, &config).unwrap_err(); - match err { - AnalysisError::AnalyzerUnavailable(_) => {} - other => panic!( - "expected AnalyzerUnavailable (depth guard should not fire on first \ - dispatch with default config), got {other:?}" - ), - } - } -} diff --git a/crates/mehen-engine/src/git_attributes.rs b/crates/mehen-engine/src/git_attributes.rs deleted file mode 100644 index 462febe8..00000000 --- a/crates/mehen-engine/src/git_attributes.rs +++ /dev/null @@ -1,486 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::collections::HashSet; -use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{Arc, RwLock}; - -const EXCLUDED_ATTRIBUTES: [&str; 3] = ["linguist-generated", "linguist-vendored", "binary"]; - -/// Matches repository-relative paths against attributes that identify files -/// which should not be analyzed by default. -#[derive(Clone)] -pub(crate) struct GitAttributeFilter { - worktree: Option, - attrs: gix::worktree::Stack, - objects: gix::OdbHandle, - outcome: gix::attrs::search::Outcome, -} - -impl GitAttributeFilter { - pub(crate) fn new(repo: &gix::Repository) -> Result> { - let worktree = repo - .workdir() - .map(|path| std::fs::canonicalize(path).or_else(|_| std::path::absolute(path))) - .transpose()?; - let index = repo.index_or_empty()?; - let source = gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping - .adjust_for_bare(repo.is_bare()); - let attrs = repo.attributes_only(&index, source)?; - let outcome = attrs.selected_attribute_matches(EXCLUDED_ATTRIBUTES); - - Ok(Self { - worktree, - attrs: attrs.detach(), - objects: repo.objects.clone(), - outcome, - }) - } - - pub(crate) fn from_revision( - repo: &gix::Repository, - revision: &str, - ) -> Result> { - let tree_id = repo - .rev_parse_single(revision)? - .object()? - .peel_to_commit()? - .tree_id()?; - let index = repo.index_from_tree(&tree_id)?; - // `Repository::attributes_only` also injects info and configured - // global attributes. Build the virtual stack directly so historical - // reports depend only on committed files and Git's built-in macros. - let mut buffer = Vec::with_capacity(512); - let mut collection = gix::attrs::search::MetadataCollection::default(); - let globals = gix::attrs::Search::new_globals( - std::iter::empty::(), - &mut buffer, - &mut collection, - )?; - let attributes = gix::worktree::stack::state::Attributes::new( - globals, - None, - gix::worktree::stack::state::attributes::Source::IdMapping, - collection, - ); - let attrs = gix::worktree::Stack::from_state_and_ignore_case( - repo.workdir().unwrap_or(repo.git_dir()), - repo.config_snapshot() - .boolean("core.ignoreCase") - .unwrap_or(false), - gix::worktree::stack::State::AttributesStack(attributes), - &index, - index.path_backing(), - ); - let outcome = attrs.selected_attribute_matches(EXCLUDED_ATTRIBUTES); - - Ok(Self { - worktree: None, - attrs, - objects: repo.objects.clone(), - outcome, - }) - } - - pub(crate) fn excludes_relative_path(&mut self, path: &Path) -> std::io::Result { - self.attrs - .at_path(path, None, &self.objects)? - .matching_attributes(&mut self.outcome); - Ok(self - .outcome - .iter_selected() - .any(|matched| is_excluded_state(matched.assignment.state))) - } -} - -/// Repository roots found before or during a walk. -/// -/// The registry contains only normalized paths, so it is cheap to share -/// between traversal workers. Each worker still owns its mutable gix -/// attribute stacks. -#[derive(Default)] -struct GitRepositoryRegistryInner { - worktrees: RwLock>, - generation: AtomicUsize, -} - -#[derive(Clone, Default)] -pub(crate) struct GitRepositoryRegistry { - inner: Arc, -} - -impl GitRepositoryRegistry { - fn for_walk_paths(paths: &[PathBuf]) -> Self { - let registry = Self::default(); - for path in paths.iter().filter(|path| path.is_dir()) { - registry.register_repository(path, false); - } - registry - } - - pub(crate) fn discover_nested_repository(&self, directory: &Path) { - if std::fs::symlink_metadata(directory.join(".git")).is_ok() { - self.register_repository(directory, true); - } - } - - fn register_repository(&self, path: &Path, require_exact_root: bool) { - let Ok(repo) = gix::discover(path) else { - return; - }; - let Some(worktree) = repo.workdir() else { - return; - }; - let Ok(worktree) = - std::fs::canonicalize(worktree).or_else(|_| std::path::absolute(worktree)) - else { - return; - }; - if require_exact_root && worktree != path { - return; - } - - let mut worktrees = self - .inner - .worktrees - .write() - .unwrap_or_else(|error| error.into_inner()); - if !worktrees.contains(&worktree) { - worktrees.push(worktree); - self.inner.generation.fetch_add(1, Ordering::Release); - } - } - - fn snapshot_if_changed(&self, previous_generation: usize) -> Option<(usize, Vec)> { - if self.inner.generation.load(Ordering::Acquire) == previous_generation { - return None; - } - let worktrees = self - .inner - .worktrees - .read() - .unwrap_or_else(|error| error.into_inner()); - let generation = self.inner.generation.load(Ordering::Relaxed); - Some((generation, worktrees.clone())) - } -} - -/// Per-walker attribute filters. Each parallel traversal worker clones this -/// value so its mutable gix attribute stacks remain thread-local. -#[derive(Clone, Default)] -pub(crate) struct GitAttributeFilterSet { - repositories: GitRepositoryRegistry, - filters: Vec, - repository_generation: usize, - loaded_worktrees: HashSet, - explicit_files: HashSet, -} - -impl GitAttributeFilterSet { - pub(crate) fn for_walk_paths(paths: &[PathBuf]) -> Self { - let explicit_files = paths - .iter() - .filter(|path| path.is_file()) - .cloned() - .collect(); - let mut filters = Self { - repositories: GitRepositoryRegistry::for_walk_paths(paths), - filters: Vec::new(), - repository_generation: 0, - loaded_worktrees: HashSet::new(), - explicit_files, - }; - filters.sync_filters(); - filters - } - - pub(crate) fn repository_registry(&self) -> GitRepositoryRegistry { - self.repositories.clone() - } - - pub(crate) fn excludes_path(&mut self, path: &Path) -> std::io::Result { - if self.explicit_files.contains(path) { - return Ok(false); - } - - self.sync_filters(); - for filter in &mut self.filters { - let Some(worktree) = &filter.worktree else { - continue; - }; - if let Ok(relative) = path.strip_prefix(worktree) { - return filter.excludes_relative_path(relative); - } - } - Ok(false) - } - - fn sync_filters(&mut self) { - let Some((generation, worktrees)) = self - .repositories - .snapshot_if_changed(self.repository_generation) - else { - return; - }; - self.repository_generation = generation; - let mut added = false; - for worktree in worktrees { - if !self.loaded_worktrees.insert(worktree.clone()) { - continue; - } - let Ok(repo) = gix::discover(&worktree) else { - log::warn!( - "Failed to discover Git repository at {}", - worktree.display() - ); - continue; - }; - match GitAttributeFilter::new(&repo) { - Ok(filter) => { - self.filters.push(filter); - added = true; - } - Err(error) => log::warn!( - "Failed to configure Git attribute filtering for {}: {error}", - worktree.display() - ), - } - } - if added { - // Prefer the innermost repository when worktrees are nested. - self.filters.sort_by(|a, b| { - b.worktree - .as_ref() - .map_or(0, |path| path.components().count()) - .cmp( - &a.worktree - .as_ref() - .map_or(0, |path| path.components().count()), - ) - }); - } - } -} - -fn is_excluded_state(state: gix::attrs::StateRef<'_>) -> bool { - match state { - gix::attrs::StateRef::Set => true, - gix::attrs::StateRef::Value(value) => { - let value: &[u8] = value.as_bstr().as_ref(); - value.eq_ignore_ascii_case(b"true") - } - gix::attrs::StateRef::Unset | gix::attrs::StateRef::Unspecified => false, - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn filter_matches_generated_vendored_and_binary_attributes() { - let dir = tempfile::tempdir().unwrap(); - let repo = gix::init(dir.path()).unwrap(); - std::fs::create_dir_all(dir.path().join("src")).unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -*.generated linguist-generated -*.vendored linguist-vendored=true -*.bin binary -*.false linguist-generated=false -*.unset -linguist-generated -*.unspecified !linguist-generated -*.upper linguist-generated=TRUE -*.py linguist-generated -", - ) - .unwrap(); - std::fs::write( - dir.path().join("src/.gitattributes"), - "manual.py -linguist-generated -linguist-vendored -binary\n", - ) - .unwrap(); - - let mut filter = GitAttributeFilter::new(&repo).unwrap(); - - for path in [ - "file.generated", - "file.vendored", - "file.bin", - "file.upper", - "src/generated.py", - ] { - assert!( - filter.excludes_relative_path(Path::new(path)).unwrap(), - "{path} should be excluded" - ); - } - for path in [ - "file.false", - "file.unset", - "file.unspecified", - "src/manual.py", - "file.txt", - ] { - assert!( - !filter.excludes_relative_path(Path::new(path)).unwrap(), - "{path} should be retained" - ); - } - } - - #[test] - fn filter_reads_repository_info_attributes() { - let dir = tempfile::tempdir().unwrap(); - let repo = gix::init(dir.path()).unwrap(); - std::fs::write( - dir.path().join(".git/info/attributes"), - "local.py linguist-vendored\n", - ) - .unwrap(); - - let mut filter = GitAttributeFilter::new(&repo).unwrap(); - - assert!( - filter - .excludes_relative_path(Path::new("local.py")) - .unwrap() - ); - } - - #[test] - fn relative_filtering_remains_available_in_bare_repositories() { - let dir = tempfile::tempdir().unwrap(); - let repo = gix::init_bare(dir.path()).unwrap(); - std::fs::write(dir.path().join("info/attributes"), "archive.py binary\n").unwrap(); - - let mut filter = GitAttributeFilter::new(&repo).unwrap(); - - assert!( - filter - .excludes_relative_path(Path::new("archive.py")) - .unwrap() - ); - } - - #[test] - fn walk_filter_set_supports_multiple_repositories_and_explicit_files() { - let first = tempfile::tempdir().unwrap(); - gix::init(first.path()).unwrap(); - std::fs::write( - first.path().join(".gitattributes"), - "*.py linguist-generated\n", - ) - .unwrap(); - let first_generated = first.path().join("generated.py"); - std::fs::write(&first_generated, "x = 1\n").unwrap(); - - let second = tempfile::tempdir().unwrap(); - gix::init(second.path()).unwrap(); - std::fs::write( - second.path().join(".gitattributes"), - "*.py linguist-vendored\n", - ) - .unwrap(); - let second_vendored = second.path().join("vendored.py"); - std::fs::write(&second_vendored, "x = 1\n").unwrap(); - - let first_root = std::fs::canonicalize(first.path()).unwrap(); - let first_generated = std::fs::canonicalize(first_generated).unwrap(); - let second_root = std::fs::canonicalize(second.path()).unwrap(); - let second_vendored = std::fs::canonicalize(second_vendored).unwrap(); - let mut filters = GitAttributeFilterSet::for_walk_paths(&[first_root.clone(), second_root]); - assert!(filters.excludes_path(&first_generated).unwrap()); - assert!(filters.excludes_path(&second_vendored).unwrap()); - - let mut explicit = - GitAttributeFilterSet::for_walk_paths(&[first_root, first_generated.clone()]); - assert!(!explicit.excludes_path(&first_generated).unwrap()); - } - - #[test] - fn revision_filter_uses_only_attributes_from_the_requested_commit() { - let dir = tempfile::tempdir().unwrap(); - gix::init(dir.path()).unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "generated.py linguist-generated\n", - ) - .unwrap(); - for name in ["generated.py", "info-only.py", "global-only.py"] { - std::fs::write(dir.path().join(name), "x = 1\n").unwrap(); - } - let status = std::process::Command::new("git") - .current_dir(dir.path()) - .args(["add", "-A"]) - .status() - .unwrap(); - assert!(status.success()); - let status = std::process::Command::new("git") - .current_dir(dir.path()) - .args([ - "-c", - "user.name=Mehen Test", - "-c", - "user.email=test@mehen.invalid", - "-c", - "commit.gpgsign=false", - "commit", - "-q", - "-m", - "attributes", - ]) - .status() - .unwrap(); - assert!(status.success()); - - std::fs::write( - dir.path().join(".gitattributes"), - "generated.py -linguist-generated\n", - ) - .unwrap(); - std::fs::write( - dir.path().join(".git/info/attributes"), - "\ -generated.py -linguist-generated -info-only.py linguist-vendored -", - ) - .unwrap(); - let global_dir = tempfile::tempdir().unwrap(); - let global_attributes = global_dir.path().join("attributes"); - std::fs::write( - &global_attributes, - "\ -generated.py -linguist-generated -global-only.py binary -", - ) - .unwrap(); - let status = std::process::Command::new("git") - .current_dir(dir.path()) - .args(["config", "core.attributesFile"]) - .arg(&global_attributes) - .status() - .unwrap(); - assert!(status.success()); - - let repo = gix::discover(dir.path()).unwrap(); - let mut filter = GitAttributeFilter::from_revision(&repo, "HEAD").unwrap(); - - assert!( - filter - .excludes_relative_path(Path::new("generated.py")) - .unwrap() - ); - for path in ["info-only.py", "global-only.py"] { - assert!( - !filter.excludes_relative_path(Path::new(path)).unwrap(), - "{path} must not inherit checkout-local attributes" - ); - } - } -} diff --git a/crates/mehen-engine/src/history_metrics.rs b/crates/mehen-engine/src/history_metrics.rs deleted file mode 100644 index 3524aaff..00000000 --- a/crates/mehen-engine/src/history_metrics.rs +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Engine-level enrichment publishing the `history.*` metric family -//! (research foundation §6) onto per-file root `MetricSpace`s. -//! -//! History metrics are repository-scope process metrics: they cannot -//! come from a `LanguageAnalyzer` (which only sees one file's -//! content), so the diff/top-offenders orchestrators compute one -//! [`mehen_git::RepositoryHistory`] per revision and fold the per-file -//! values into each file's metric set *after* static analysis. The -//! walk is comparatively expensive (one tree diff per commit), so -//! callers only trigger it when a `history.*` selector or threshold is -//! actually requested — see [`names_want_history`]. -//! -//! Two keys are composites over the static suite and are therefore -//! computed here rather than in `mehen-git`: -//! -//! * `history.churn.relative` — absolute churn normalized by the -//! file's SLOC at the same revision (Nagappan & Ball's -//! defect-predictive *relative* churn, §6.1). -//! * `history.hotspot` — `cognitive.sum × commit_frequency` (§6.5): -//! mehen upgrades the classic LOC×frequency hotspot with its real -//! complexity metric. - -use mehen_core::{MetricKey, MetricSet, keys}; -use mehen_git::FileHistory; - -/// Whether any requested metric name/key belongs to the `history.*` -/// family — the trigger for running the (comparatively expensive) -/// repository history walk. -pub(crate) fn names_want_history<'a>(mut names: impl Iterator) -> bool { - // Only *valid* history keys trigger the walk: a typo'd key can - // never read a published value, so walking for it would be pure - // cost in service of a `0.0` fallback. - names.any(|name| name.starts_with("history.") && !is_unknown_history_key(name)) -} - -/// A `history`-rooted name that is not one of the fixed keys -/// (`mehen_core::keys::HISTORY_ALL`) — including the bare family root -/// `history`, which is not a leaf. The CLI selector parser rejects -/// these up front; the public engine boundaries (`rank_top_offenders` -/// selectors, `DiffInput` thresholds) accept arbitrary strings, so -/// they must be checked again there — an unvalidated typo would -/// trigger the expensive repository walk only to read `0.0` through -/// the missing-key fallback (an all-zero ranking, or a policy -/// silently evaluated against zero). -pub(crate) fn is_unknown_history_key(name: &str) -> bool { - (name == "history" || name.starts_with("history.")) - && !mehen_core::keys::HISTORY_ALL.contains(&name) -} - -/// Whether an engine-boundary selector cannot read a published -/// history value at all: a `history.*` key outside the fixed family, -/// **or** a valid key with a non-root aggregator — history enrichment -/// publishes flat root keys only, so `history.commit_frequency.max` -/// parses (key `history.commit_frequency`, aggregator `Max`) yet can -/// never resolve, and would rank/gate everything on the `0.0` -/// fallback. -pub(crate) fn is_invalid_history_selector(selector: &mehen_core::MetricSelector) -> bool { - let key = selector.key.as_str(); - if key != "history" && !key.starts_with("history.") { - return false; - } - is_unknown_history_key(key) - || !matches!(selector.aggregator, mehen_core::SelectorAggregator::Root) -} - -/// Whether a selector name is one of the two static-dependent -/// composites (`history.hotspot`, `history.churn.relative`) that -/// [`inject_history_metrics`] omits when `with_composites` is false. -/// -/// Callers evaluating selectors against such a space must treat these -/// as *unavailable* rather than letting the missing-key `0.0` fallback -/// fabricate a value: a diff would report `-baseline` as an apparent -/// improvement and a ranking would score the file as zero (Codex P2). -pub(crate) fn is_history_composite(name: &str) -> bool { - name == keys::HISTORY_HOTSPOT || name == keys::HISTORY_CHURN_RELATIVE -} - -/// Whether a selector can be honestly valued given what backs the -/// metric space. Git-only selectors (the `history.*` family minus its -/// two static-dependent composites) need repository history; the -/// composites need both history and static analysis; every other -/// selector needs static analysis. Reading an unavailable selector -/// through the missing-key `0.0` fallback would fabricate a value — -/// a "cleared" hotspot, a worst-possible MI on an undecodable file, -/// or a zero-age "worst offender" that was never tracked by Git. -pub(crate) fn selector_available(name: &str, statics: bool, history: bool) -> bool { - if is_unknown_history_key(name) { - // A typo'd history key has no published value under any - // circumstances — never "available". - return false; - } - let needs_history = name.starts_with("history."); - let needs_statics = !needs_history || is_history_composite(name); - (statics || !needs_statics) && (history || !needs_history) -} - -/// Publish the `history.*` family onto a file's root metric set. -/// -/// `file` is the walked per-file history at the same revision the -/// metric set was computed from; `head_seconds` is that revision's -/// committer timestamp (the deterministic "now" for code age). Files -/// untouched by any walked commit publish nothing — selectors then -/// read the family as `0.0` via the missing-key fallback. -/// -/// `with_composites` controls the two static-dependent keys -/// (`history.hotspot`, `history.churn.relative`): callers injecting -/// into a synthetic space with no static analysis behind it must pass -/// `false`, or hotspot would read a fabricated 0 and relative churn -/// would divide the absolute churn by 1 — the keys are omitted -/// instead, reading as absent like any unpublished metric. -pub(crate) fn inject_history_metrics( - metrics: &mut MetricSet, - file: &FileHistory, - head_seconds: i64, - with_composites: bool, -) { - let read = |metrics: &MetricSet, key: &str| { - metrics - .get(&MetricKey::new(key)) - .map(|v| v.as_f64()) - .unwrap_or(0.0) - }; - // Composite inputs come from whichever family the analyzer - // publishes: the shared source-code suite (`loc.sloc`, - // `cognitive.sum`), SQL's namespace (`sql.loc.code`, - // `sql.cognitive_complexity`), or Markdown's - // (`markdown.loc.tloc`, - // `markdown.complexity.cognitive_complexity`). Without the - // fallbacks, relative churn would silently equal absolute churn - // and every SQL/Markdown hotspot would read zero (Codex P2). - let read_first = |keys: &[&str]| { - keys.iter() - .map(|key| read(metrics, key)) - .find(|&v| v != 0.0) - .unwrap_or(0.0) - }; - // Relative churn normalizes by the file's current size; a file - // whose analyzer published no (or zero) code-line count falls back - // to a denominator of 1 so the value stays finite and deterministic. - let sloc = read_first(&[keys::LOC_SLOC, keys::SQL_LOC_CODE, keys::MARKDOWN_LOC_TLOC]).max(1.0); - let cognitive_sum = read_first(&[ - keys::COGNITIVE_SUM, - keys::SQL_COGNITIVE_COMPLEXITY, - keys::MARKDOWN_COGNITIVE_COMPLEXITY, - ]); - - let churn_abs = file.churn_abs(); - metrics.insert(keys::HISTORY_CHURN_ABS, churn_abs); - if with_composites { - metrics.insert(keys::HISTORY_CHURN_RELATIVE, churn_abs as f64 / sloc); - } - metrics.insert(keys::HISTORY_AGE_MONTHS, file.age_months(head_seconds)); - metrics.insert(keys::HISTORY_AUTHORS, file.authors); - metrics.insert(keys::HISTORY_MINOR_CONTRIBUTORS, file.minor_contributors); - metrics.insert(keys::HISTORY_OWNERSHIP, file.ownership); - metrics.insert(keys::HISTORY_COMMIT_FREQUENCY, file.commit_frequency); - if with_composites { - metrics.insert( - keys::HISTORY_HOTSPOT, - cognitive_sum * file.commit_frequency as f64, - ); - } - metrics.insert(keys::HISTORY_SUM_OF_COUPLING, file.sum_of_coupling); - metrics.insert(keys::HISTORY_TWR, file.twr); - metrics.insert(keys::HISTORY_BUGFIX_COMMITS, file.bugfix_commits); -} - -#[cfg(test)] -mod tests { - use super::*; - - fn sample_history() -> FileHistory { - FileHistory { - commit_frequency: 4, - churn_added: 30, - churn_removed: 10, - authors: 2, - minor_contributors: 1, - ownership: 0.75, - last_change_seconds: 0, - sum_of_coupling: 3, - bugfix_commits: 2, - twr: 0.5, - } - } - - fn read(metrics: &MetricSet, key: &str) -> f64 { - metrics - .get(&MetricKey::new(key)) - .map(|v| v.as_f64()) - .unwrap_or_else(|| panic!("missing key {key}")) - } - - #[test] - fn names_want_history_detects_family_keys() { - assert!(names_want_history( - ["cognitive", "history.churn.abs"].into_iter() - )); - assert!(!names_want_history( - ["cognitive", "loc.lloc", "sql.change_risk_score"].into_iter() - )); - assert!(!names_want_history(std::iter::empty())); - } - - #[test] - fn injects_all_eleven_family_keys() { - let mut metrics = MetricSet::default(); - metrics.insert("loc.sloc", 20.0); - metrics.insert("cognitive.sum", 8.0); - inject_history_metrics(&mut metrics, &sample_history(), 2_629_746, true); - - assert_eq!(read(&metrics, keys::HISTORY_CHURN_ABS), 40.0); - // 40 churned lines over 20 SLOC. - assert_eq!(read(&metrics, keys::HISTORY_CHURN_RELATIVE), 2.0); - // One average month since last change. - assert!((read(&metrics, keys::HISTORY_AGE_MONTHS) - 1.0).abs() < 1e-9); - assert_eq!(read(&metrics, keys::HISTORY_AUTHORS), 2.0); - assert_eq!(read(&metrics, keys::HISTORY_MINOR_CONTRIBUTORS), 1.0); - assert_eq!(read(&metrics, keys::HISTORY_OWNERSHIP), 0.75); - assert_eq!(read(&metrics, keys::HISTORY_COMMIT_FREQUENCY), 4.0); - // cognitive.sum (8) × commit_frequency (4). - assert_eq!(read(&metrics, keys::HISTORY_HOTSPOT), 32.0); - assert_eq!(read(&metrics, keys::HISTORY_SUM_OF_COUPLING), 3.0); - assert_eq!(read(&metrics, keys::HISTORY_TWR), 0.5); - assert_eq!(read(&metrics, keys::HISTORY_BUGFIX_COMMITS), 2.0); - } - - #[test] - fn missing_static_metrics_keep_composites_finite() { - // No loc.sloc / cognitive.sum published (e.g. analyzer without - // those families): relative churn divides by 1, hotspot is 0. - let mut metrics = MetricSet::default(); - inject_history_metrics(&mut metrics, &sample_history(), 0, true); - assert_eq!(read(&metrics, keys::HISTORY_CHURN_RELATIVE), 40.0); - assert_eq!(read(&metrics, keys::HISTORY_HOTSPOT), 0.0); - } - - #[test] - fn sql_files_use_their_own_namespace_for_composites() { - // The SQL analyzer publishes `sql.loc.code` / `sql.cognitive_complexity` - // instead of `loc.sloc` / `cognitive.sum`; the composites must read - // those so SQL relative churn and hotspots aren't degenerate. - let mut metrics = MetricSet::default(); - metrics.insert("sql.loc.code", 10.0); - metrics.insert("sql.cognitive_complexity", 5.0); - inject_history_metrics(&mut metrics, &sample_history(), 0, true); - // 40 churned lines over 10 SQL code lines. - assert_eq!(read(&metrics, keys::HISTORY_CHURN_RELATIVE), 4.0); - // sql.cognitive_complexity (5) × commit_frequency (4). - assert_eq!(read(&metrics, keys::HISTORY_HOTSPOT), 20.0); - } - - #[test] - fn markdown_files_use_their_own_namespace_for_composites() { - // The Markdown analyzer publishes `markdown.loc.tloc` / - // `markdown.complexity.cognitive_complexity`; the composites - // must read those so a Markdown top-offenders ranking isn't - // degenerate. - let mut metrics = MetricSet::default(); - metrics.insert("markdown.loc.tloc", 20.0); - metrics.insert("markdown.complexity.cognitive_complexity", 3.0); - inject_history_metrics(&mut metrics, &sample_history(), 0, true); - // 40 churned lines over 20 Markdown text lines. - assert_eq!(read(&metrics, keys::HISTORY_CHURN_RELATIVE), 2.0); - // markdown cognitive (3) × commit_frequency (4). - assert_eq!(read(&metrics, keys::HISTORY_HOTSPOT), 12.0); - } -} diff --git a/crates/mehen-engine/src/lib.rs b/crates/mehen-engine/src/lib.rs deleted file mode 100644 index b6128790..00000000 --- a/crates/mehen-engine/src/lib.rs +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-engine` — pipeline orchestration. -//! -//! This crate owns: -//! - language analyzer registry, -//! - language detection by extension and content, -//! - the public engine APIs (`analyze_metrics`, `analyze_diff`, -//! `rank_top_offenders`), -//! - per-file concurrency (per the rewrite plan §4.6: per-file analysis is -//! the parallelism unit; analyzers are constructed per worker; parser -//! arenas live for one analyze call), -//! - the only `LanguageDispatcher` implementation in 1.0, exposed to -//! `mehen-markdown` for the embedded-code path. -//! -//! Phase 1 wired the registry and the dispatcher; Phase 5 added the -//! `analyze_diff` and `rank_top_offenders` orchestrators. The per-file -//! parallelism unit and recursion/depth limits land in follow-up -//! commits; this implementation keeps each operation single-threaded -//! and predictable. - -#![deny(unsafe_code)] - -pub mod ci; -mod concurrent_files; -mod config_file; -mod coverage_metrics; -mod detection; -mod diff; -mod dispatcher; -mod git_attributes; -mod history_metrics; -mod metric_selector; -mod registry; -mod top_offenders; - -pub use config_file::{ - ConfigError, ConfigFile, CoverageConfig, ThresholdBreach, ThresholdPolicy, load_config, - render_config_error, render_threshold_report, -}; -pub use coverage_metrics::{CoverageOpts, CoverageSetupError, enrich_metrics_with_coverage}; -pub use diff::{DiffOpts, run_diff}; -pub use top_offenders::{TopOffendersOpts, run_top_offenders}; - -/// Register the embedded-code dispatch callback the moved -/// [`mehen_markdown::analyze_markdown`] uses to fold fenced source -/// snippets into Markdown metrics. Idempotent — backed by a -/// `OnceLock` inside `mehen-markdown`, so repeat calls are silent -/// no-ops. -/// -/// Every supported fence language is now backed by a per-language -/// analyzer crate, so this dispatch path goes straight through the -/// new `AnalyzerRegistry`. -pub fn init_markdown() { - mehen_markdown::set_embedded_dispatch(markdown_dispatch::dispatch); -} - -mod markdown_dispatch { - use mehen_markdown::{EmbeddedFenceMetrics, FenceLanguage}; - - use crate::AnalyzerRegistry; - - /// Run the AnalyzerRegistry against a fence body. Every supported - /// fence language now has a per-language analyzer crate, so this - /// is the only dispatch path Markdown needs. - /// - /// The registry is shared across calls via a process-wide - /// `OnceLock`: `dispatch` is the `mehen_markdown::DispatchFn` - /// callback (a bare `fn` pointer that can't capture state), and - /// every fenced code block in a Markdown document drives this - /// function once. Without the cache each fence rebuilt the - /// per-language factory `Vec` from scratch — measurable overhead - /// on documents with hundreds of fences. - pub(super) fn dispatch(lang: FenceLanguage, body: String) -> Option { - use std::sync::OnceLock; - - use mehen_core::{AnalysisConfig, MetricKey, SourceFile, keys}; - - static REGISTRY: OnceLock = OnceLock::new(); - let language = language_for(lang); - let registry = REGISTRY.get_or_init(AnalyzerRegistry::default_set); - let analyzer = registry.analyzer_for(language)?; - let path = camino::Utf8PathBuf::try_from(synthetic_path(lang)).ok()?; - let source = SourceFile::new(path, language, body); - let analysis = analyzer.analyze(&source, &AnalysisConfig::default()).ok()?; - // Migrated analyzers can return `Ok(...)` with a partial tree - // alongside an `Error`/`Fatal` diagnostic when the fence body - // doesn't parse cleanly. Per §9.3 those analyses are - // incomplete; folding their numeric metrics back into Markdown - // would silently skew embedded scores. - if crate::diff::has_blocking_diagnostic(&analysis.diagnostics) { - return None; - } - let read = |key: &str| { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .map(|v| v.as_f64()) - .unwrap_or(0.0) - }; - Some(EmbeddedFenceMetrics { - volume: read(keys::HALSTEAD_VOLUME), - cognitive_sum: read("cognitive.sum"), - sloc: read(keys::LOC_SLOC), - }) - } - - fn synthetic_path(lang: FenceLanguage) -> std::path::PathBuf { - let name = match lang { - FenceLanguage::Rust => "fence.rs", - FenceLanguage::Python => "fence.py", - FenceLanguage::Typescript => "fence.ts", - FenceLanguage::Tsx => "fence.tsx", - FenceLanguage::Go => "fence.go", - FenceLanguage::Ruby => "fence.rb", - // A fenced Kotlin snippet is script-like — it commonly contains - // top-level statements (`println(...)`), which the `.kt` - // compilation-unit grammar rejects. Use `.kts` so the Kotlin - // analyzer selects the `script` entry rule (a superset that also - // accepts top-level declarations), avoiding a cascade of recovered - // syntax errors that would otherwise drop the fence's metrics. - FenceLanguage::Kotlin => "fence.kts", - FenceLanguage::Java => "fence.java", - FenceLanguage::Powershell => "fence.ps1", - // `.csx` (script) rather than `.cs`: a fence is usually a snippet of - // top-level statements, which Roslyn's `compilation_unit` accepts via - // `global_statement`, and both extensions route to the same analyzer. - FenceLanguage::CSharp => "fence.csx", - FenceLanguage::C => "fence.c", - FenceLanguage::Php => "fence.php", - }; - std::path::PathBuf::from(name) - } - - fn language_for(lang: FenceLanguage) -> mehen_core::Language { - use mehen_core::Language; - match lang { - FenceLanguage::Rust => Language::Rust, - FenceLanguage::Python => Language::Python, - FenceLanguage::Typescript => Language::TypeScript, - FenceLanguage::Tsx => Language::Tsx, - FenceLanguage::Go => Language::Go, - FenceLanguage::Ruby => Language::Ruby, - FenceLanguage::Kotlin => Language::Kotlin, - FenceLanguage::Java => Language::Java, - FenceLanguage::Powershell => Language::PowerShell, - FenceLanguage::CSharp => Language::CSharp, - FenceLanguage::C => Language::C, - FenceLanguage::Php => Language::Php, - } - } - - #[cfg(test)] - mod tests { - use super::*; - - /// A fence body whose Python code has a hard syntax error. - /// Ruff returns `Ok(LanguageAnalysis)` with a partial tree - /// plus an `Error`-severity diagnostic, so the legacy - /// pre-fix dispatcher would have folded its (mostly-zero - /// but nonzero `loc.sloc`) numbers into the Markdown - /// embedded score. - #[test] - fn registry_dispatch_drops_blocking_diagnostic_python() { - let bad = "def f(:\n return 1\n".to_string(); - assert!(dispatch(FenceLanguage::Python, bad).is_none()); - } - - #[test] - fn registry_dispatch_keeps_clean_python() { - let good = "def f():\n return 1\n".to_string(); - assert!(dispatch(FenceLanguage::Python, good).is_some()); - } - - /// A C# fence must reach the analyzer. Registering `Language::CSharp` in - /// the registry is not enough on its own: the fence tag has to map to a - /// `FenceLanguage` variant, and that variant needs both a synthetic path - /// and a `Language` mapping here, or the fence is silently skipped and - /// its volume/complexity/SLOC never reach the Markdown score. - #[test] - fn registry_dispatch_analyzes_csharp_fence() { - let good = "class C { void M() { } }\n".to_string(); - assert!(dispatch(FenceLanguage::CSharp, good).is_some()); - } - - /// A fence is usually a snippet of top-level statements rather than a - /// full compilation unit, which the Roslyn-derived grammar accepts via - /// `global_statement` (C# 9). Pinned because the synthetic path is - /// `fence.csx` for exactly this reason. - #[test] - fn registry_dispatch_analyzes_csharp_top_level_statements() { - let script = "var total = 1 + 2;\n".to_string(); - assert!(dispatch(FenceLanguage::CSharp, script).is_some()); - } - } -} - -pub use detection::detect_language; -pub use diff::analyze_diff; -pub use dispatcher::EngineDispatcher; -pub use mehen_core::{ - AnalysisErrorRecord, AnalyzeMetricsInput, DiffFile, DiffInput, DiffReport, DiffSide, - MetricsReport, TopOffenderEntry, TopOffendersInput, TopOffendersReport, -}; -pub use registry::{AnalyzerRegistry, RegistryError}; -pub use top_offenders::rank_top_offenders; - -use mehen_core::{AnalysisError, Result}; - -/// Run a single-file analysis using the default registry. -/// -/// The returned report has its `path` populated from the input, so callers -/// don't need to set it manually after the conversion from -/// `LanguageAnalysis` (`LanguageAnalysis` itself does not carry the path). -/// -/// Phase 1 implementation; Phase 5 expands this to the full `mehen metrics` -/// orchestration (output formatting, diagnostics → exit codes, …). -pub fn analyze_metrics(input: AnalyzeMetricsInput) -> Result { - let registry = AnalyzerRegistry::default_set(); - let path = input.source.path.clone(); - let analyzer = registry - .analyzer_for(input.source.language) - .ok_or(AnalysisError::AnalyzerUnavailable(input.source.language))?; - let analysis = analyzer.analyze(&input.source, &input.config)?; - let mut report = MetricsReport::from(analysis); - report.path = path; - Ok(report) -} diff --git a/crates/mehen-engine/src/metric_selector.rs b/crates/mehen-engine/src/metric_selector.rs deleted file mode 100644 index e8cc848e..00000000 --- a/crates/mehen-engine/src/metric_selector.rs +++ /dev/null @@ -1,540 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Shared metric selection primitives used by `diff` and `top-offenders`. -//! -//! A *selector* is a known metric name (e.g. `loc.lloc`) bundled with a -//! display label and a [`Polarity`] (whether higher or lower values are -//! "better"). Production diff/top-offenders pipelines read the -//! `MetricSpace::metrics` map via [`read_metric`]. - -use mehen_core::{MetricKey, MetricSpace}; - -/// Whether a metric is "better" when higher or lower. -/// -/// Used by callers to interpret deltas/rankings (e.g. `Cyclomatic` is -/// [`Polarity::LowerIsBetter`], while `Mi` is [`Polarity::HigherIsBetter`]). -#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)] -#[serde(rename_all = "kebab-case")] -pub(crate) enum Polarity { - LowerIsBetter, - HigherIsBetter, -} - -/// A selector for a single metric column: name, display label, polarity. -#[derive(Debug, Clone)] -pub(crate) struct MetricSelector { - pub name: &'static str, - pub label: &'static str, - pub polarity: Polarity, -} - -type MetricDef = (&'static str, &'static str, Polarity); - -/// Catalogue of metrics that can be referenced by name from the CLI. -pub(crate) const KNOWN_METRICS: &[MetricDef] = &[ - ("cyclomatic", "Cyclomatic", Polarity::LowerIsBetter), - ("cognitive", "Cognitive", Polarity::LowerIsBetter), - ("nom.functions", "Functions", Polarity::LowerIsBetter), - ("loc.lloc", "LLOC", Polarity::LowerIsBetter), - ("mi.original", "MI (Original)", Polarity::HigherIsBetter), - ("mi.sei", "MI (SEI)", Polarity::HigherIsBetter), - ("mi.visual_studio", "MI", Polarity::HigherIsBetter), - ("halstead.volume", "Halstead Vol", Polarity::LowerIsBetter), - ("abc", "ABC", Polarity::LowerIsBetter), - // Default-set history columns get curated labels; the rest of the - // `history.*` family is reachable via the namespaced-key path. - ("history.hotspot", "Hotspot", Polarity::LowerIsBetter), - ("history.churn.relative", "Churn", Polarity::LowerIsBetter), - // The line-rate coverage column `mehen diff` appends to the - // default set when coverage reports are resolved - // (`--coverage`/`--base-coverage`); the rest of the `coverage.*` - // family is reachable via the namespaced-key path. - ("coverage.line", "Coverage", Polarity::HigherIsBetter), -]; - -/// The selector for the coverage column `mehen diff` surfaces by -/// default when coverage was resolved for either side and the caller -/// passed no explicit `--metrics` list. Line rate is the one dimension -/// every supported report format measures (a Go coverprofile has no -/// branch records; LCOV function records are optional), so it is the -/// only dimension promoted to a default column. -pub(crate) fn coverage_line_selector() -> MetricSelector { - KNOWN_METRICS - .iter() - .find(|(name, ..)| *name == mehen_core::keys::COVERAGE_LINE) - .map(|&(name, label, polarity)| MetricSelector { - name, - label, - polarity, - }) - .expect("coverage.line is a KNOWN_METRICS entry") -} - -/// Default metric set for `diff` (kept here so both diff and top-offenders -/// can surface the same fallback from a single source of truth). -/// -/// One column per orthogonal dimension (research foundation §9.3/§9.4): -/// control-flow understandability (`cognitive`), computational volume -/// (`abc`), the one deliberate composite rollup (`mi.visual_studio`), and -/// the two change-risk signals a *diff* comment actually needs — whether -/// this is a fragile, frequently-touched file (`history.hotspot` = -/// cognitive × commit frequency) and how much of the file the change -/// moves, size-normalized (`history.churn.relative`). `cyclomatic` was -/// dropped in favor of cognitive (the two correlate strongly) and -/// `nom.functions`/`loc.lloc` in favor of the missing axes. The history -/// columns trigger the repository history walk on default diffs. -pub(crate) const DEFAULT_METRICS: &[&str] = &[ - "cognitive", - "abc", - "mi.visual_studio", - "history.hotspot", - "history.churn.relative", -]; - -/// Default selectors for SQL files. The source-code defaults -/// ([`DEFAULT_METRICS`]) are all keys the SQL analyzer never publishes, so a -/// SQL file diffed with them reads `0.0` for every column and is dropped as -/// "unchanged". SQL files instead default to the first-release composite set -/// (research foundation §15) so `mehen diff` surfaces SQL changes without the -/// caller needing to know the `sql.*` keys (Codex P2). -pub(crate) const DEFAULT_SQL_METRICS: &[&str] = &[ - "sql.change_risk_score", - "sql.maintainability_index", - "sql.review_burden_index", - "sql.cognitive_complexity", - "sql.loc.code", -]; - -/// Default metric specs for a language, used when the caller passes no -/// explicit `--metric`. SQL owns a disjoint metric namespace, so it gets its -/// own defaults; every other language uses the source-code defaults. -pub(crate) fn default_metrics_for_language( - language: mehen_core::Language, -) -> &'static [&'static str] { - match language { - mehen_core::Language::Sql => DEFAULT_SQL_METRICS, - _ => DEFAULT_METRICS, - } -} - -/// Resolve the default selectors for a language (no explicit `--metric`). -/// -/// SQL defaults are `'static` names, so they are built into `MetricSelector`s -/// directly (no `String` allocation / `Box::leak` round-trip through the -/// namespaced-parsing path). Other languages use the source-code catalogue. -pub(crate) fn default_selectors_for_language( - language: mehen_core::Language, -) -> Vec { - default_metrics_for_language(language) - .iter() - .map(|&name| { - // A KNOWN_METRICS entry carries a curated label/polarity; a - // namespaced key (`sql.*`) is its own label with a by-key polarity. - match KNOWN_METRICS.iter().find(|(n, ..)| *n == name) { - Some(&(n, label, polarity)) => MetricSelector { - name: n, - label, - polarity, - }, - None => MetricSelector { - name, - label: name, - polarity: default_namespaced_polarity(name), - }, - } - }) - .collect() -} - -/// Parse a list of metric specs into resolved [`MetricSelector`]s. -/// -/// A spec is a bare metric name (`cognitive`) or a polarity-prefixed name -/// (`+nom.functions`, `-mi.visual_studio`). Unknown names emit a warning and -/// are skipped. -/// -/// When `specs` is empty, [`DEFAULT_METRICS`] is used as a fallback. This is -/// the contract `diff` expects. Callers that want "no fallback" (e.g. -/// `top-offenders`, where `--metric` is required) should enforce that at the -/// CLI layer before calling this function. -pub(crate) fn parse_metric_selectors(specs: &[String]) -> Vec { - let specs: Vec<&str> = if specs.is_empty() { - DEFAULT_METRICS.to_vec() - } else { - specs.iter().map(|s| s.as_str()).collect() - }; - - let mut selectors = Vec::new(); - for spec in specs { - let (polarity_override, name) = if let Some(rest) = spec.strip_prefix('+') { - (Some(Polarity::HigherIsBetter), rest) - } else if let Some(rest) = spec.strip_prefix('-') { - (Some(Polarity::LowerIsBetter), rest) - } else { - (None, spec) - }; - - if let Some(&(n, label, default_polarity)) = KNOWN_METRICS.iter().find(|(n, ..)| *n == name) - { - selectors.push(MetricSelector { - name: n, - label, - polarity: polarity_override.unwrap_or(default_polarity), - }); - } else if let Ok(canonical) = crate::config_file::canonical_metric_key(name) { - // Any other key the analyzers publish — the same catalogue - // `mehen.toml` threshold validation resolves against: the - // source-code families (`cognitive.max`, `loc.sloc`, - // `nom.functions.max` — aggregate aliases resolve to their - // published spelling), the fixed `history.*` family, and - // the analyzer-owned `sql.*` / `markdown.*` catalogues. - // Routing the namespaced families through the catalogue — - // instead of accepting any prefixed name verbatim — - // rejects typos like `sql.modularit_health` here, so a - // mistyped CI column cannot silently defeat the correctly - // configured threshold on the real key. The selector reads - // the canonical key; the user's spelling stays as the - // column label. - let canonical: &'static str = Box::leak(canonical.into_boxed_str()); - let label: &'static str = Box::leak(name.to_string().into_boxed_str()); - let default_polarity = if is_higher_is_better_metric(canonical) { - Polarity::HigherIsBetter - } else { - Polarity::LowerIsBetter - }; - selectors.push(MetricSelector { - name: canonical, - label, - polarity: polarity_override.unwrap_or(default_polarity), - }); - } else { - log::warn!("Unknown metric '{name}', skipping."); - } - } - - selectors -} - -/// Namespaced (`sql.*` / `markdown.*` / `history.*` / `coverage.*`) -/// metric keys where a -/// *larger* value is healthier. Substring inference is too crude (e.g. -/// `markdown.maintainability.artifact_debt_score` is a penalty despite -/// containing "maintainability", and `sql.dialect.confidence` is -/// higher-is-better), so the higher-is-better metrics are enumerated by exact -/// key and everything else defaults to higher-is-worse. This is the single -/// source of truth shared by the `diff` selector polarity and the -/// `top-offenders` ranking polarity ([`crate::top_offenders`]). -pub(crate) const NAMESPACED_HIGHER_IS_BETTER: &[&str] = &[ - // SQL composite/quality scores where larger is healthier. - "sql.maintainability_index", - "sql.modularity_health", - "sql.select.output_alias_coverage", - "sql.dialect.confidence", - // Markdown quality scores where larger is healthier. - "markdown.maintainability.documentation_maintainability_index", - "markdown.maintainability.section_balance_score", - "markdown.maintainability.good_scaffold_score", - "markdown.grounding.repository_grounding_score", - "markdown.grounding.evidence_coverage_score", - "markdown.links.information_scent_score", - // History process metrics where larger is healthier (research - // foundation §8): long-stable code and concentrated ownership are - // the low-risk end; every other `history.*` signal is a risk count. - mehen_core::keys::HISTORY_AGE_MONTHS, - mehen_core::keys::HISTORY_OWNERSHIP, - // Coverage *rates* — more covered code is always the healthier - // direction, so configured thresholds become minimums - // (`coverage.line = 80`). Deliberately only the three rates: for - // the raw `.covered`/`.total` counters a fixed polarity would gate - // a different measurement than the name suggests (a minimum - // "total instrumented lines" is not a coverage gate), so counters - // keep the neutral default and users flip with `+`/`-` when - // ranking by them. - mehen_core::keys::COVERAGE_LINE, - mehen_core::keys::COVERAGE_BRANCH, - mehen_core::keys::COVERAGE_FUNCTION, -]; - -/// Whether a namespaced metric key is higher-is-better (see -/// [`NAMESPACED_HIGHER_IS_BETTER`]). -pub(crate) fn is_namespaced_higher_is_better(name: &str) -> bool { - NAMESPACED_HIGHER_IS_BETTER.contains(&name) -} - -/// Whether a metric key — source-code or namespaced — is -/// higher-is-better. The single source of truth shared by the config -/// threshold polarity, the published-catalogue selector branch, and -/// the post-1.0 ranking polarity: `mi.*` variants, the Halstead -/// program level (`L = 1/D` — inverse difficulty, so larger is the -/// healthier direction, unlike the rest of the `halstead.*` family), -/// and the enumerated namespaced quality scores (including the three -/// `coverage.*` rates — see [`NAMESPACED_HIGHER_IS_BETTER`] for why -/// the coverage counters are not listed). -pub(crate) fn is_higher_is_better_metric(key: &str) -> bool { - key == "mi" - || key.starts_with("mi.") - || key == "halstead.level" - || is_namespaced_higher_is_better(key) -} - -/// Default polarity for a namespaced metric, by *exact* key. Users can always -/// override with a `+`/`-` prefix. -fn default_namespaced_polarity(name: &str) -> Polarity { - if is_namespaced_higher_is_better(name) { - Polarity::HigherIsBetter - } else { - Polarity::LowerIsBetter - } -} - -/// Translate a CLI selector name (e.g. `cyclomatic`, `nom.functions`, -/// `mi.visual_studio`) to the `MetricSet` key the shared walker -/// publishes onto the root `MetricSpace`. -/// -/// Most names map verbatim; the rolled-up scalar metrics -/// (`cyclomatic`, `cognitive`) live under their `*.sum` key. Any -/// unknown selector (e.g. a namespaced `sql.*`/`markdown.*` key) falls -/// back to its bare name; missing keys read as `0.0` from `read_metric`. -/// -/// The result borrows from `name` for the fallback case, so this never -/// allocates — `read_metric` builds a `MetricKey` from it immediately. -/// (A previous version returned `&'static str` and `Box::leak`ed the -/// fallback, leaking one string per metric-read on namespaced selectors.) -pub(crate) fn metric_set_key_for(name: &str) -> &str { - match name { - "cyclomatic" => "cyclomatic.sum", - "cognitive" => "cognitive.sum", - "nom.functions" => "nom.functions", - "loc.lloc" => "loc.lloc", - "mi.original" => "mi.original", - "mi.sei" => "mi.sei", - "mi.visual_studio" => "mi.visual_studio", - "halstead.volume" => "halstead.volume", - "abc" => "abc", - other => other, - } -} - -/// Read a selector's value from the root `MetricSpace`'s `MetricSet`. -/// -/// Returns `0.0` for any key the analyzer didn't publish — matching -/// the legacy reader, which fell through to `Default`-initialized -/// `FuncSpace` fields when an analyzer left a metric blank. -pub(crate) fn read_metric(root: &MetricSpace, selector: &MetricSelector) -> f64 { - let key = metric_set_key_for(selector.name); - root.metrics - .get(&MetricKey::new(key)) - .map(|v| v.as_f64()) - .unwrap_or(0.0) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn defaults_apply_when_specs_empty() { - let selectors = parse_metric_selectors(&[]); - assert_eq!(selectors.len(), DEFAULT_METRICS.len()); - for (sel, expected) in selectors.iter().zip(DEFAULT_METRICS.iter()) { - assert_eq!(sel.name, *expected); - } - } - - #[test] - fn sql_files_default_to_sql_metrics_not_source_code_metrics() { - // A SQL file diffed with the source-code defaults would read 0 for - // every column (the SQL analyzer publishes none of them) and be - // dropped as unchanged. SQL must default to its own composite set. - let sql = default_selectors_for_language(mehen_core::Language::Sql); - let names: Vec<&str> = sql.iter().map(|s| s.name).collect(); - assert_eq!(names, DEFAULT_SQL_METRICS); - // `sql.maintainability_index` is a higher-is-better quality score. - let mi = sql - .iter() - .find(|s| s.name == "sql.maintainability_index") - .expect("maintainability default present"); - assert_eq!(mi.polarity, Polarity::HigherIsBetter); - // A non-SQL language keeps the source-code defaults. - let ts = default_selectors_for_language(mehen_core::Language::TypeScript); - let ts_names: Vec<&str> = ts.iter().map(|s| s.name).collect(); - assert_eq!(ts_names, DEFAULT_METRICS); - } - - #[test] - fn default_history_columns_have_curated_labels_and_trigger_walk() { - // The §9.4 default set surfaces the two change-risk columns with - // human labels (not raw keys) in the PR-comment table header. - let selectors = parse_metric_selectors(&[]); - let hotspot = selectors - .iter() - .find(|s| s.name == "history.hotspot") - .expect("hotspot default present"); - assert_eq!(hotspot.label, "Hotspot"); - assert_eq!(hotspot.polarity, Polarity::LowerIsBetter); - let churn = selectors - .iter() - .find(|s| s.name == "history.churn.relative") - .expect("churn default present"); - assert_eq!(churn.label, "Churn"); - assert_eq!(churn.polarity, Polarity::LowerIsBetter); - // The default set must request history so `run_diff` walks it. - assert!( - crate::history_metrics::names_want_history(selectors.iter().map(|s| s.name)), - "defaults must trigger the history walk" - ); - } - - #[test] - fn polarity_prefix_overrides_default() { - let specs = vec!["+loc.lloc".to_string(), "-mi.visual_studio".to_string()]; - let selectors = parse_metric_selectors(&specs); - assert_eq!(selectors.len(), 2); - assert_eq!(selectors[0].name, "loc.lloc"); - assert_eq!(selectors[0].polarity, Polarity::HigherIsBetter); - assert_eq!(selectors[1].name, "mi.visual_studio"); - assert_eq!(selectors[1].polarity, Polarity::LowerIsBetter); - } - - #[test] - fn unknown_metric_is_skipped() { - let specs = vec!["nonexistent".to_string()]; - let selectors = parse_metric_selectors(&specs); - assert!(selectors.is_empty()); - } - - #[test] - fn published_catalogue_keys_are_accepted_as_selectors() { - // Every key the shared publishers emit — the catalogue - // `mehen.toml` validation resolves against — must be - // selectable as a column, or a documented, configurable - // threshold could never fire in diff/top-offenders. - let specs = vec![ - "cognitive.max".to_string(), - "loc.sloc".to_string(), - "nom.functions.max".to_string(), - ]; - let selectors = parse_metric_selectors(&specs); - let names: Vec<&str> = selectors.iter().map(|s| s.name).collect(); - // Aggregate aliases resolve to the published spelling; labels - // keep the user's spelling. - assert_eq!(names, ["cognitive.max", "loc.sloc", "nom.functions_max"]); - assert_eq!(selectors[2].label, "nom.functions.max"); - for selector in &selectors { - assert_eq!(selector.polarity, Polarity::LowerIsBetter); - } - // Unpublished near-misses stay rejected — including namespaced - // typos, which previously slipped through by prefix and could - // silently defeat the configured gate on the real key. - assert!(parse_metric_selectors(&["cognitive.maximum".to_string()]).is_empty()); - assert!(parse_metric_selectors(&["sql.modularit_health".to_string()]).is_empty()); - assert!(parse_metric_selectors(&["markdown.links.borken".to_string()]).is_empty()); - } - - #[test] - fn mistyped_history_metric_is_rejected() { - // The `history.*` family is fixed and enumerated: a typo must - // be rejected up front, not accepted by prefix — accepting it - // would trigger the expensive history walk and then read the - // unpublished key as `0.0` (an all-zero ranking / an empty - // diff instead of a warning). - let specs = vec!["history.commit_frequncy".to_string()]; - assert!(parse_metric_selectors(&specs).is_empty()); - // Every real key is still accepted verbatim. - for key in mehen_core::keys::HISTORY_ALL { - let selectors = parse_metric_selectors(&[key.to_string()]); - assert_eq!(selectors.len(), 1, "{key} must parse"); - assert_eq!(selectors[0].name, *key); - } - } - - #[test] - fn bare_mi_is_unknown() { - // `mi` by itself isn't a leaf — you must pick a variant. - let specs = vec!["mi".to_string()]; - let selectors = parse_metric_selectors(&specs); - assert!(selectors.is_empty()); - } - - #[test] - fn namespaced_sql_and_markdown_metrics_are_accepted() { - // Language-owned `sql.*`/`markdown.*` keys aren't in KNOWN_METRICS but - // must be usable as `top-offenders`/`diff` selectors. - let specs = vec![ - "sql.change_risk_score".to_string(), - "markdown.review.review_criticality_index".to_string(), - ]; - let selectors = parse_metric_selectors(&specs); - assert_eq!(selectors.len(), 2); - assert_eq!(selectors[0].name, "sql.change_risk_score"); - assert_eq!( - selectors[1].name, - "markdown.review.review_criticality_index" - ); - } - - #[test] - fn namespaced_metric_default_polarity() { - // Risk/complexity scores are higher-is-worse; health/maintainability - // scores are higher-is-better. - assert_eq!( - default_namespaced_polarity("sql.change_risk_score"), - Polarity::LowerIsBetter - ); - assert_eq!( - default_namespaced_polarity("sql.maintainability_index"), - Polarity::HigherIsBetter - ); - assert_eq!( - default_namespaced_polarity("sql.modularity_health"), - Polarity::HigherIsBetter - ); - } - - #[test] - fn history_metrics_are_accepted_as_namespaced_selectors() { - // The engine-owned `history.*` family is not in KNOWN_METRICS but - // must be usable as a `diff`/`top-offenders` selector. - let specs = vec![ - "history.churn.abs".to_string(), - "history.hotspot".to_string(), - "history.age_months".to_string(), - ]; - let selectors = parse_metric_selectors(&specs); - assert_eq!(selectors.len(), 3); - assert_eq!(selectors[0].name, "history.churn.abs"); - assert_eq!(selectors[1].name, "history.hotspot"); - assert_eq!(selectors[2].name, "history.age_months"); - } - - #[test] - fn history_metric_default_polarity() { - // Long-stable code and concentrated ownership are the healthy end; - // every other history signal is a risk count. - assert_eq!( - default_namespaced_polarity("history.age_months"), - Polarity::HigherIsBetter - ); - assert_eq!( - default_namespaced_polarity("history.ownership"), - Polarity::HigherIsBetter - ); - for risk in [ - "history.churn.abs", - "history.churn.relative", - "history.authors", - "history.minor_contributors", - "history.commit_frequency", - "history.hotspot", - "history.sum_of_coupling", - "history.twr", - "history.bugfix_commits", - ] { - assert_eq!( - default_namespaced_polarity(risk), - Polarity::LowerIsBetter, - "selector {risk}" - ); - } - } -} diff --git a/crates/mehen-engine/src/registry.rs b/crates/mehen-engine/src/registry.rs deleted file mode 100644 index 6497464b..00000000 --- a/crates/mehen-engine/src/registry.rs +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use mehen_core::{Language, LanguageAnalyzer}; - -/// Registry that maps a `Language` to its analyzer. -/// -/// Per the rewrite plan §4.6, analyzers are constructed per worker (or per -/// analyze call) — they never share parser instances across threads. The -/// registry holds *factory* trait objects so each `analyzer_for` call hands -/// the caller a fresh analyzer struct to drive a single source file. -/// -/// In 1.0 the analyzer structs are stateless (Phase 1 tree-sitter -/// placeholders); Phase 7+ may switch them to arena-backed parsers, at -/// which point the same registry shape continues to work because -/// `LanguageAnalysis` is owned and `Send + 'static`. -pub struct AnalyzerRegistry { - entries: Vec, -} - -struct RegistryEntry { - language: Language, - factory: AnalyzerFactory, -} - -type AnalyzerFactory = Box Box + Send + Sync>; - -#[derive(Debug)] -pub enum RegistryError { - DuplicateLanguage(Language), -} - -impl AnalyzerRegistry { - pub fn new() -> Self { - Self { - entries: Vec::new(), - } - } - - pub fn register(&mut self, language: Language, factory: F) -> Result<(), RegistryError> - where - F: Fn() -> Box + Send + Sync + 'static, - { - if self.entries.iter().any(|e| e.language == language) { - return Err(RegistryError::DuplicateLanguage(language)); - } - self.entries.push(RegistryEntry { - language, - factory: Box::new(factory), - }); - Ok(()) - } - - /// Returns a freshly-constructed analyzer for `language`, or `None` if - /// no analyzer is registered (e.g. the owning crate is feature-gated - /// off in this build). - pub fn analyzer_for(&self, language: Language) -> Option> { - self.entries - .iter() - .find(|e| e.language == language) - .map(|e| (e.factory)()) - } - - /// Whether an analyzer is registered for `language`, without - /// constructing one. Used by `mehen.toml` validation: a static - /// threshold for a language this build cannot analyze is a gate - /// that can never fire. - pub fn has_analyzer_for(&self, language: Language) -> bool { - self.entries.iter().any(|e| e.language == language) - } - - /// Default registry assembling every analyzer enabled by feature flags. - /// - /// Also registers the Markdown embedded-code dispatcher - /// (idempotent — backed by `OnceLock` inside `mehen-markdown`). - /// Without this, library callers that use - /// `analyze_metrics`/`analyze_diff`/`rank_top_offenders` directly - /// would receive `0.0` for every fenced-code complexity term — - /// `embedded_code::analyze_fence` returns zero whenever no - /// dispatch function is set, and only the CLI binary used to call - /// `init_markdown()`. See PR #95 review and the - /// `default_set_initializes_markdown_dispatch` test below. - pub fn default_set() -> Self { - let mut registry = Self::new(); - register_default_analyzers(&mut registry); - crate::init_markdown(); - registry - } -} - -impl Default for AnalyzerRegistry { - fn default() -> Self { - Self::default_set() - } -} - -fn register_default_analyzers(registry: &mut AnalyzerRegistry) { - #[cfg(feature = "lang-python")] - { - let _ = registry.register(Language::Python, || { - Box::new(mehen_python::PythonAnalyzer::new()) - }); - } - #[cfg(feature = "lang-typescript")] - { - let _ = registry.register(Language::TypeScript, || { - Box::new(mehen_typescript::TypeScriptAnalyzer::new()) - }); - let _ = registry.register(Language::JavaScript, || { - Box::new(mehen_typescript::JavaScriptAnalyzer::new()) - }); - let _ = registry.register(Language::Tsx, || { - Box::new(mehen_typescript::TsxAnalyzer::new()) - }); - let _ = registry.register(Language::Jsx, || { - Box::new(mehen_typescript::JsxAnalyzer::new()) - }); - } - #[cfg(feature = "lang-php")] - { - let _ = registry.register(Language::Php, || Box::new(mehen_php::PhpAnalyzer::new())); - } - #[cfg(feature = "lang-ruby")] - { - let _ = registry.register(Language::Ruby, || Box::new(mehen_ruby::RubyAnalyzer::new())); - } - #[cfg(feature = "lang-rust")] - { - let _ = registry.register(Language::Rust, || Box::new(mehen_rust::RustAnalyzer::new())); - } - #[cfg(feature = "lang-go")] - { - let _ = registry.register(Language::Go, || Box::new(mehen_go::GoAnalyzer::new())); - } - #[cfg(feature = "lang-c")] - { - let _ = registry.register(Language::C, || Box::new(mehen_c::CAnalyzer::new())); - } - #[cfg(feature = "lang-kotlin")] - { - let _ = registry.register(Language::Kotlin, || { - Box::new(mehen_kotlin::KotlinAnalyzer::new()) - }); - } - #[cfg(feature = "lang-java")] - { - let _ = registry.register(Language::Java, || Box::new(mehen_java::JavaAnalyzer::new())); - } - #[cfg(feature = "lang-csharp")] - { - let _ = registry.register(Language::CSharp, || { - Box::new(mehen_csharp::CSharpAnalyzer::new()) - }); - } - #[cfg(feature = "lang-powershell")] - { - let _ = registry.register(Language::PowerShell, || { - Box::new(mehen_powershell::PowerShellAnalyzer::new()) - }); - } - #[cfg(feature = "lang-sql")] - { - let _ = registry.register(Language::Sql, || Box::new(mehen_sql::SqlAnalyzer::new())); - } - { - let _ = registry.register(Language::Markdown, || { - Box::new(mehen_markdown::MarkdownAnalyzer::new()) - }); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, MetricKey, SourceFile}; - - /// Library callers (anyone using `analyze_metrics`/`analyze_diff`/ - /// `rank_top_offenders` directly without invoking - /// `mehen_engine::init_markdown` first) must still get real - /// embedded-fence metrics. `default_set` now wires the Markdown - /// dispatcher itself; without that fix, the assertion below - /// regresses to `0.0`. - #[test] - #[cfg(all(feature = "lang-python", feature = "lang-c"))] - fn default_set_initializes_markdown_dispatch() { - let registry = AnalyzerRegistry::default_set(); - let analyzer = registry - .analyzer_for(Language::Markdown) - .expect("Markdown analyzer registered"); - - // Markdown source with one fenced Python block and one - // fenced C block. Both languages have analyzers in the - // registry, so the Markdown embedded-code dispatcher should - // route the bodies through them and surface a non-zero - // Halstead-derived `embedded_volume`. - let source = "# Heading\n\n\ - Text before code.\n\n\ - ```python\n\ - def add(a, b):\n \ - return a + b\n\ - ```\n\n\ - ```c\n\ - int add(int a, int b) { return a + b; }\n\ - ```\n"; - let file = SourceFile::new("doc.md".into(), Language::Markdown, source.to_string()); - let analysis = analyzer - .analyze(&file, &AnalysisConfig::default()) - .expect("Markdown analysis succeeds"); - let key = MetricKey::new("markdown.halstead.embedded_volume"); - let value = analysis - .root - .metrics - .get(&key) - .map(|v| v.as_f64()) - .unwrap_or(0.0); - assert!( - value > 0.0, - "library callers using AnalyzerRegistry::default_set() must see \ - non-zero embedded fence metrics; got embedded_volume={value} \ - — did register_default_analyzers() forget to register the \ - Markdown dispatcher? See PR #95 review." - ); - } -} diff --git a/crates/mehen-engine/src/top_offenders.rs b/crates/mehen-engine/src/top_offenders.rs deleted file mode 100644 index 0d8c42d0..00000000 --- a/crates/mehen-engine/src/top_offenders.rs +++ /dev/null @@ -1,2386 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen top-offenders` orchestrator. -//! -//! Phase 5 implementation: walks the input paths, detects each file's -//! language, runs analysis through the registry, and ranks the files by -//! the requested metric selectors. Per the rewrite plan §2.4: -//! deterministic sorted output, ties broken by subsequent selectors. - -use std::collections::{HashMap, HashSet}; -use std::sync::Arc; - -use camino::Utf8PathBuf; -use mehen_core::{ - AnalysisErrorRecord, DiffSide, Language, MetricKey, ParseDiagnostic, Polarity, SourceFile, -}; -use mehen_metrics::{MetricSelector, SelectorAggregator}; - -use crate::detection::detect_language; -use crate::registry::AnalyzerRegistry; -use mehen_core::{TopOffenderEntry, TopOffendersInput, TopOffendersReport}; - -/// Run `mehen top-offenders` against `input.paths` and return a ranked -/// report. -pub fn rank_top_offenders(input: TopOffendersInput) -> TopOffendersReport { - let registry = Arc::new(AnalyzerRegistry::default_set()); - let mut entries: Vec = Vec::new(); - let mut analysis_errors: Vec = Vec::new(); - // The engine boundary accepts arbitrary selector strings: a typo'd - // `history.*` key (the family is fixed — `keys::HISTORY_ALL`) can - // never read a published value, so it is surfaced as an analysis - // error, scores as uncomputable (`None`), and never triggers the - // repository walk below. - for selector in &input.selectors { - if crate::history_metrics::is_invalid_history_selector(selector) { - analysis_errors.push(AnalysisErrorRecord { - path: Utf8PathBuf::new(), - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.unknown_metric", - format!( - "unresolvable history selector `{selector}` (the fixed `history.*` keys publish root values only)", - ), - )], - }); - } - if crate::coverage_metrics::is_invalid_coverage_selector(selector) { - analysis_errors.push(AnalysisErrorRecord { - path: Utf8PathBuf::new(), - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.unknown_metric", - format!( - "unresolvable coverage selector `{selector}` (the fixed `coverage.*` keys publish root values only)", - ), - )], - }); - } - } - // `history.*` selectors need repository histories. Root-load - // failures surface as `analysis_errors` (this API has no fatal - // channel); per-file lazy discovery still covers repositories the - // eager pass missed. Only *resolvable* history selectors trigger - // the walk — an invalid one can never read a value, so walking - // for it would be pure cost. - let histories = if input.selectors.iter().any(|s| { - s.key.as_str().starts_with("history.") - && !crate::history_metrics::is_invalid_history_selector(s) - }) { - let loaded = RepoHistories::new(); - for root in &input.paths { - if let Err(e) = loaded.load_root(root.as_std_path()) { - analysis_errors.push(AnalysisErrorRecord { - path: root.clone(), - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.history_unavailable", - format!("history metrics unavailable for {root}: {e}"), - )], - }); - } - } - Some(loaded) - } else { - None - }; - // `coverage.*` selectors read explicitly supplied report files. - // Parse failures surface as `analysis_errors` (no fatal channel - // here); a resolvable coverage selector without any report reads - // as unavailable per file rather than as fabricated zeros. - let coverage_index = { - let wants_coverage = input.selectors.iter().any(|s| { - s.key.as_str().starts_with("coverage.") - && !crate::coverage_metrics::is_invalid_coverage_selector(s) - }); - if wants_coverage && !input.coverage_reports.is_empty() { - let mut parsed = Vec::new(); - for path in &input.coverage_reports { - // The same ingest path (read + sniff + parse) the CLI - // uses, with a diagnostic-record sink instead of the - // CLI's hard error. - match crate::coverage_metrics::ingest_report(path) { - Ok((_, data)) => parsed.push(data), - Err(message) => analysis_errors.push(AnalysisErrorRecord { - path: path.clone(), - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.coverage_unavailable", - format!("coverage report unusable: {message}"), - )], - }), - } - } - if parsed.is_empty() { - None - } else { - let index = mehen_coverage::CoverageIndex::build( - mehen_coverage::merge::merge_reports(parsed), - ); - let mut roots: Vec = input - .paths - .iter() - .filter_map(|path| crate::coverage_metrics::coverage_root_for(path)) - .collect(); - roots.sort_unstable(); - roots.dedup(); - Some(crate::coverage_metrics::CoverageContext::new(index, &roots)) - } - } else { - None - } - }; - // Dedup files across roots. Without this, callers passing - // overlapping paths (`.` plus `src`, or a directory plus a file - // inside it) would rank the same file multiple times, crowding - // out other files once `max_results` is applied. - // - // All roots share one normalized walk, then each result is mapped back - // through the first matching input root. Canonical keys collapse - // different *spellings* of one path (overlapping roots, directory - // symlinks) but keep a tracked symlink distinct from its target — - // each is its own repository entry with its own history. - let mut seen: HashSet = HashSet::new(); - - for entry in walk_paths(&input.paths, &input.include, &input.exclude) { - if !seen.insert(canonical_key(&entry)) { - continue; - } - let Some(language) = detect_language(entry.as_path()) else { - continue; - }; - let analyzer = registry.analyzer_for(language); - if analyzer.is_none() { - // Language detected but no analyzer registered (the - // owning crate is feature-gated off in this build). - // Surface as a non-fatal `analysis_error` so callers - // can distinguish "no offenders" from "offenders - // silently skipped" — matching the diff path's - // `record_unavailable` (rewrite plan §3.5). History - // metrics need no parser, so the file may still rank - // below on Git-only selectors. - record_unavailable(&mut analysis_errors, &entry, language); - } - // History metrics don't depend on decoding or parsing the - // blob: a recognized file whose contents static analysis - // cannot handle — or whose language's analyzer is - // feature-gated off — still has repository history, and a - // history selector must rank it on real values (via an empty - // metric space) instead of silently dropping it. Static-only - // rankings keep skipping such files. - let history_entry = histories.as_ref().and_then(|h| h.file(entry.as_std_path())); - // Coverage likewise comes from report files, not from the - // blob. - let coverage_entry = coverage_index - .as_ref() - .and_then(|context| crate::coverage_metrics::coverage_for_file(context, &entry)); - let analyzed_root = analyzer.and_then(|analyzer| { - let text = std::fs::read_to_string(entry.as_std_path()).ok()?; - let source = SourceFile::new(entry.clone(), language, text); - let analysis = analyzer.analyze(&source, &input.config).ok()?; - // Migrated analyzers can return `Ok(...)` with a - // partial tree alongside an `Error`/`Fatal` - // diagnostic when the file doesn't parse cleanly. - // Per §9.3 those analyses are incomplete; surfacing - // them in the offender list as if they were measured - // would mislead CI/policy callers. - if crate::diff::has_blocking_diagnostic(&analysis.diagnostics) { - return None; - } - Some(analysis.root) - }); - let statics_available = analyzed_root.is_some(); - let history_available = history_entry.is_some(); - let coverage_available = coverage_entry.is_some(); - let mut root = match analyzed_root { - Some(root) => root, - None if history_available || coverage_available => mehen_core::MetricSpace::new( - mehen_core::SpaceId(0), - mehen_core::SpaceKind::Unit, - mehen_core::SourceSpan::empty(), - ), - None => continue, - }; - - // Fold the `history.*` family into the metric set so history - // selectors rank on real values. The static-dependent - // composites are omitted when no real analysis backs the - // space (see `inject_history_metrics`). - if let Some((fh, head_seconds)) = history_entry { - crate::history_metrics::inject_history_metrics( - &mut root.metrics, - &fh, - head_seconds, - statics_available, - ); - } - - // Fold the `coverage.*` family in: whole-file dimensions on - // the root, span-scoped line/branch coverage on each function - // space. - if let Some(file_coverage) = &coverage_entry { - crate::coverage_metrics::inject_coverage_metrics(&mut root, file_coverage); - } - - let scores: Vec> = input - .selectors - .iter() - .map(|s| { - // A selector the space cannot back — any static - // metric on a history-only fallback, any `history.*` - // metric on a file without recorded Git history, any - // `coverage.*` metric on a file no report measured, - // or a selector no enrichment can resolve (typo'd - // key / non-root aggregator) — has no measurable - // value, and the missing-key `0.0` fallback must not - // rank the file on a fabricated one (worst-possible - // MI on an undecodable file; zero-age "worst - // offender" for an untracked file). - if crate::history_metrics::is_invalid_history_selector(s) - || crate::coverage_metrics::is_invalid_coverage_selector(s) - || !crate::coverage_metrics::selector_available_with_coverage( - s.key.as_str(), - statics_available, - history_available, - coverage_available, - ) - { - None - } else { - Some(read_metric(s, &root)) - } - }) - .collect(); - - entries.push(TopOffenderEntry { - path: entry, - language, - scores, - }); - } - - let polarities: Vec = input.selectors.iter().map(default_polarity_for).collect(); - entries.sort_by(|a, b| cmp_entries(a, b, &polarities)); - if entries.len() > input.max_results { - entries.truncate(input.max_results); - } - - // Lazily discovered repositories whose history was unavailable - // (e.g. a shallow nested clone) must be visible to callers — their - // files were ranked on absent history, not a real zero. - if let Some(histories) = histories.as_ref() { - for (location, message) in histories.take_failures() { - analysis_errors.push(AnalysisErrorRecord { - path: Utf8PathBuf::from_path_buf(location.clone()) - .unwrap_or_else(|_| Utf8PathBuf::from(location.to_string_lossy().into_owned())), - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.history_unavailable", - format!("history metrics unavailable: {message}"), - )], - }); - } - } - - TopOffendersReport { - schema_version: "1.0".to_string(), - selectors: input.selectors.iter().map(|s| s.to_string()).collect(), - entries, - analysis_errors, - } -} - -/// Dedup key across overlapping roots and directory symlinks: the -/// *parent* is canonicalized but the final component is preserved, so -/// two spellings of one file collapse while a tracked symlink and its -/// target remain distinct entries (each with its own history — see -/// `canonical_file_path`). -fn canonical_key(path: &Utf8PathBuf) -> Utf8PathBuf { - canonical_file_path(path.as_std_path()) - .and_then(|canonical| Utf8PathBuf::from_path_buf(canonical).ok()) - .unwrap_or_else(|| path.clone()) -} - -/// Push an `engine.analyzer_unavailable` record for `path` so callers -/// can tell that a file was skipped because the owning language crate -/// is feature-gated off (mirroring the diff path's behavior). -fn record_unavailable( - errors: &mut Vec, - path: &Utf8PathBuf, - language: Language, -) { - errors.push(AnalysisErrorRecord { - path: path.clone(), - // `top-offenders` has no base/head distinction; pick `Head` - // by convention so the JSON shape stays compatible with diff. - side: DiffSide::Head, - diagnostics: vec![ParseDiagnostic::warning( - "engine.analyzer_unavailable", - format!( - "no analyzer registered for `{}` in this build", - language.canonical() - ), - )], - }); -} - -fn walk_paths(roots: &[Utf8PathBuf], include: &[String], exclude: &[String]) -> Vec { - walk_files(&FilesData { - include: mk_globset(include), - exclude: mk_globset(exclude), - paths: roots - .iter() - .map(|root| root.as_std_path().to_path_buf()) - .collect(), - respect_ignores: true, - }) - .into_iter() - .filter_map(|path| Utf8PathBuf::try_from(path).ok()) - .collect() -} - -/// Order entries from most concerning to least. -/// -/// "Most concerning" depends on the metric's polarity. For -/// `HigherIsWorse` metrics (cyclomatic, cognitive, halstead.volume, -/// loc.*) a larger value is worse, so they sort descending. For -/// `HigherIsBetter` metrics (mi.original, mi.sei, mi.visual_studio) -/// a smaller value is worse, so they sort ascending. -/// -/// Cascade through every selector so secondary keys break ties on -/// the primary, tertiary keys break ties on the secondary, etc. -/// Path tie-breaks last for determinism. -fn cmp_entries( - a: &TopOffenderEntry, - b: &TopOffenderEntry, - polarities: &[Polarity], -) -> std::cmp::Ordering { - for (i, polarity) in polarities.iter().enumerate() { - let av = a.scores.get(i).copied().flatten(); - let bv = b.scores.get(i).copied().flatten(); - let ord = match (av, bv) { - // An uncomputable score ranks as least concerning under - // either polarity — it is *absent*, not a zero (which - // would be the *most* concerning value for a - // higher-is-better metric). - (Some(_), None) => std::cmp::Ordering::Less, - (None, Some(_)) => std::cmp::Ordering::Greater, - (None, None) => std::cmp::Ordering::Equal, - (Some(av), Some(bv)) => { - let base = av.partial_cmp(&bv).unwrap_or(std::cmp::Ordering::Equal); - match polarity { - // Worst-first: larger value is more concerning, so a > b - // should put `a` first → reverse the natural ordering. - Polarity::HigherIsWorse => base.reverse(), - // Worst-first: smaller value is more concerning, so a < b - // should put `a` first → use the natural ordering. - Polarity::HigherIsBetter => base, - } - } - }; - if ord != std::cmp::Ordering::Equal { - return ord; - } - } - a.path.cmp(&b.path) -} - -/// Resolve a metric's "higher is worse / better" polarity from its -/// key. Maintainability-index variants (`mi.*`) are higher-is-better; -/// the language-owned `sql.*`/`markdown.*` quality scores -/// (`sql.maintainability_index`, `sql.modularity_health`, …) are too — -/// otherwise `rank_top_offenders` would surface the *healthiest* SQL/doc -/// files as the worst offenders (Codex P2). Every other metric the engine -/// publishes (cyclomatic, cognitive, loc.*, halstead.*, abc, nom, nargs, -/// nexit, npa, npm, wmc) is higher-is-worse. This mirrors the legacy -/// `KNOWN_METRICS` catalog and the rewrite plan §5.1 metric contract. -fn default_polarity_for(selector: &MetricSelector) -> Polarity { - if crate::metric_selector::is_higher_is_better_metric(selector.key.as_str()) { - Polarity::HigherIsBetter - } else { - Polarity::HigherIsWorse - } -} - -pub(crate) fn read_metric(selector: &MetricSelector, root: &mehen_core::MetricSpace) -> f64 { - let lookup = |key: &MetricKey| root.metrics.get(key).map(|v| v.as_f64()); - match selector.aggregator { - SelectorAggregator::Root => lookup(&selector.key).unwrap_or(0.0), - SelectorAggregator::Sum => suffixed_lookup(&selector.key, &["sum"], &lookup), - SelectorAggregator::Min => suffixed_lookup(&selector.key, &["min"], &lookup), - SelectorAggregator::Max => suffixed_lookup(&selector.key, &["max"], &lookup), - // Per `mehen-metrics::state`, average is published as either - // `.avg` (cyclomatic, loc.*) or `.average` - // (cognitive, nom, nargs, nexit, npa, npm). Try the short form - // first to match the selector spelling, then fall back. - SelectorAggregator::Avg => suffixed_lookup(&selector.key, &["avg", "average"], &lookup), - } -} - -/// Look the selector key up under each suffix in order (e.g. -/// `["avg", "average"]` for the avg aggregator), returning the first -/// hit. `0.0` if none match — keeps the behavior of a missing metric -/// the same as a missing root-level key. -/// -/// For each suffix the lookup tries the dotted form first -/// (`.`) and falls back to the underscore form -/// (`_`). The underscore form is what the shared -/// publishers in `mehen-metrics::state` use for sub-bucket aggregates: -/// `nom.functions_max`, `nom.closures_min`, `abc.assignments_average`, -/// `npa.classes_average`, `npm.interfaces_average`, `nargs.functions_max`, -/// etc. Without the fallback, selectors like `nom.functions.max` would -/// silently read `0.0` even when the analyzer published the value, -/// misordering top-offenders rankings and suppressing diff-threshold -/// violations. -fn suffixed_lookup( - base: &MetricKey, - suffixes: &[&str], - lookup: &dyn Fn(&MetricKey) -> Option, -) -> f64 { - for suffix in suffixes { - let dotted = MetricKey::new(format!("{base}.{suffix}")); - if let Some(v) = lookup(&dotted) { - return v; - } - let underscored = MetricKey::new(format!("{base}_{suffix}")); - if let Some(v) = lookup(&underscored) { - return v; - } - } - 0.0 -} - -// ── pre-1.0 CLI orchestrator (`mehen top-offenders`) ─────────────────── -// -// Everything below drives the published `mehen top-offenders` subcommand -// and was hoisted out of `legacy/top_offenders.rs` into this module so -// the CLI shares the same module tree as the post-1.0 `rank_top_offenders` -// entry point above. Names that overlap with the post-1.0 surface -// (`MetricSelector`, `read_metric`) are imported under aliases. - -use std::cmp::Ordering; -use std::io::Write; -use std::path::{Path, PathBuf}; -use std::process; -use std::sync::Mutex; -use std::thread::available_parallelism; - -use crate::concurrent_files::{ConcurrentRunner, FilesData, mk_globset, walk_files}; -use crate::metric_selector::{ - MetricSelector as CliMetricSelector, Polarity as SelectorPolarity, parse_metric_selectors, - read_metric as read_selector_metric, -}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)] -pub(crate) enum TopOffendersFormat { - Markdown, - Json, -} - -#[derive(clap::Args, Debug)] -pub struct TopOffendersOpts { - /// Metric to rank by. Repeatable; order matters — the first `--metric` is - /// the primary sort key, the next breaks ties, etc. - /// - /// Prefix with `+` to flip a metric to higher-is-better (best at top) or - /// `-` for lower-is-better. Without a prefix the metric's default polarity - /// is used. Known names: `cyclomatic`, `cognitive`, `nom.functions`, - /// `loc.lloc`, `mi.original`, `mi.sei`, `mi.visual_studio`, - /// `halstead.volume`, `abc`. Namespaced keys (`sql.*`, `markdown.*`, - /// `history.*`) are accepted verbatim; `history.*` metrics require a git - /// repository and trigger a history walk of `HEAD`. - #[clap( - long = "metric", - short = 'M', - required = true, - num_args = 1, - allow_hyphen_values = true - )] - metrics: Vec, - - /// Maximum number of offenders to return. - #[clap(long, default_value_t = 10)] - max_results: usize, - - /// Output format. - #[clap(long, short = 'O', value_enum, default_value_t = TopOffendersFormat::Markdown)] - output_format: TopOffendersFormat, - - /// Glob to include files. Repeat the flag for multiple patterns. - #[clap(long, short = 'I', num_args = 1)] - include: Vec, - - /// Glob to exclude files. Repeat the flag for multiple patterns. - #[clap(long, short = 'X', num_args = 1)] - exclude: Vec, - - /// Do not respect ignore files or generated/vendored/binary Git - /// attributes while walking directories. - #[clap(long)] - no_ignore: bool, - - /// Number of parser jobs. - #[clap(long, short = 'j')] - num_jobs: Option, - - /// Language type override (skip auto-detection). - #[clap(long, short)] - language_type: Option, - - #[clap(flatten)] - coverage: crate::coverage_metrics::CoverageOpts, - - /// One or more files or directories to analyze. - #[clap(required = true, num_args = 1..)] - paths: Vec, -} - -#[derive(Debug, Clone, serde::Serialize)] -struct CliMetricValue { - name: &'static str, - label: &'static str, - /// `None` (JSON `null`): the metric could not be computed for - /// this file — a static-dependent history composite on a file - /// whose static analysis is unavailable. Rendered as `n/a` and - /// ranked as least concerning, never as a fabricated zero. - value: Option, -} - -#[derive(Debug, Clone, serde::Serialize)] -struct FileOffender { - path: PathBuf, - metrics: Vec, -} - -struct TopOffendersCfg { - selectors: Vec, - language_override: Option, - registry: Arc, - /// Per-repository histories at `HEAD` for every repository the - /// input roots belong to — present only when a `history.*` metric - /// was requested. Shared with the orchestrator, which drains - /// recorded lazy-discovery failures after the run. - history: Option>, - /// Ingested coverage reports — present only when coverage was - /// requested (flag, config, or a `coverage.*` selector/threshold). - coverage: Option>, - results: Arc>>, - /// Configured metric thresholds (`mehen.toml`), present only when - /// the loaded config carries any. Evaluated per file against the - /// selected ranking metrics; crossings fail the run with exit 1. - thresholds: Option, - breaches: Arc>>, -} - -/// Lazily discovered `HEAD` histories, one per repository work dir. -/// -/// Each analyzed file is mapped to its *innermost* containing -/// repository by discovering from the file's (symlink-preserving, -/// canonicalized) parent directory, so nested repositories found -/// during traversal read their own history instead of zeros. -/// Discovery results and walked histories are cached; repositories -/// that cannot be opened or walked (e.g. a shallow nested clone) read -/// the family as absent. -struct RepoHistories { - state: Mutex, -} - -#[derive(Default)] -struct RepoHistoriesState { - /// Canonical parent dir → canonical work dir (`None`: not in a - /// repository, or discovery failed). - dir_to_workdir: HashMap>, - /// Canonical work dir → lazily initialized `HEAD` history - /// (`None` inside an initialized cell: walk failed). The - /// `OnceLock` serializes each repository's cold walk across - /// workers while different repositories initialize concurrently. - histories: HashMap>>>, - /// Lazily discovered repositories that exist but whose history is - /// unavailable (shallow nested clone, walk failure). Recorded once - /// per location so callers can surface them instead of silently - /// ranking those files on zero-valued history. - failures: Vec<(PathBuf, String)>, -} - -impl RepoHistories { - fn new() -> Self { - Self { - state: Mutex::new(RepoHistoriesState::default()), - } - } - - /// Eagerly load the repository containing an explicitly analyzed - /// root, propagating errors — a requested history ranking must not - /// silently be all zeros because a root isn't in a (full) clone. - /// - /// A directory root (or a symlink to one) discovers from its - /// canonicalized target; a file or file-symlink root discovers - /// from its *lexical* parent so a tracked symlink pointing outside - /// its repository still resolves to the repository that tracks it. - fn load_root(&self, root: &Path) -> Result<(), Box> { - let metadata = std::fs::metadata(root) - .map_err(|e| format!("cannot resolve path {}: {e}", root.display()))?; - let discover_from = if metadata.is_dir() { - std::fs::canonicalize(root)? - } else { - let parent = match root.parent() { - Some(parent) if !parent.as_os_str().is_empty() => parent, - _ => Path::new("."), - }; - std::fs::canonicalize(parent)? - }; - let repo = match mehen_git::open_repo_at(&discover_from) { - Ok(repo) => repo, - // A directory root that is not itself inside Git may still - // *contain* repositories: per-file lookups discover the - // innermost repository lazily (see `file`), so an eager - // hard failure here would reject valid layouts like a - // container directory of checkouts. Files directly under - // such a root simply have no history. Genuine open - // failures (untrusted or unreadable repositories, shallow - // clones) still propagate. - Err(mehen_git::GitError::RepoNotFound) if metadata.is_dir() => { - let mut state = self.state.lock().expect("repo histories mutex poisoned"); - state.dir_to_workdir.insert(discover_from, None); - return Ok(()); - } - Err(e) => return Err(e.into()), - }; - let workdir = repo - .workdir() - .ok_or("repository has no work dir (bare repository)")? - .to_path_buf(); - let canonical_workdir = std::fs::canonicalize(&workdir)?; - let cell = { - let mut state = self.state.lock().expect("repo histories mutex poisoned"); - state - .dir_to_workdir - .insert(discover_from, Some(canonical_workdir.clone())); - state - .histories - .entry(canonical_workdir) - .or_default() - .clone() - }; - // Walk outside the state lock (other repositories keep - // loading); the cell serializes duplicate initializers. - let mut walk_error: Option = None; - cell.get_or_init(|| match mehen_git::collect_history(&repo, "HEAD") { - Ok(history) => Some(history), - Err(e) => { - walk_error = Some(e); - None - } - }); - match walk_error { - Some(e) => Err(e.into()), - None => Ok(()), - } - } - - /// The per-file history entry and that repository's deterministic - /// "now" for one analyzed file. Untracked files and files outside - /// every discoverable repository read as absent. - /// - /// The lock is held only for cache reads/writes — repository - /// discovery and (expensive) cold history walks run unlocked so - /// concurrent workers analyzing other repositories never serialize - /// behind one walk. Each repository's cold walk runs exactly once: - /// workers racing the same repository block on its `OnceLock` - /// cell rather than launching duplicate walks. - fn file(&self, file_path: &Path) -> Option<(mehen_git::FileHistory, i64)> { - let canonical = canonical_file_path(file_path)?; - let parent = canonical.parent()?.to_path_buf(); - - let cached_workdir = { - let state = self.state.lock().expect("repo histories mutex poisoned"); - state.dir_to_workdir.get(&parent).cloned() - }; - let workdir = match cached_workdir { - Some(cached) => cached, - None => { - // A directory outside any repository is a normal case - // (RepoNotFound stays silent); a repository that - // exists but can't be used — e.g. a shallow nested - // clone — is a real failure that must not silently - // read as zero history. - let discovered = match mehen_git::open_repo_at(&parent) { - Ok(repo) => repo.workdir().and_then(|wd| std::fs::canonicalize(wd).ok()), - Err(mehen_git::GitError::RepoNotFound) => None, - Err(e) => { - log::warn!("history unavailable under {}: {e}", parent.display()); - let mut state = self.state.lock().expect("repo histories mutex poisoned"); - state.failures.push((parent.clone(), e.to_string())); - None - } - }; - let mut state = self.state.lock().expect("repo histories mutex poisoned"); - state - .dir_to_workdir - .entry(parent) - .or_insert(discovered) - .clone() - } - }?; - - // Per-worktree cold-walk coordination: the first worker to - // reach a repository initializes its `OnceLock` while others - // block on that cell only — different repositories still load - // concurrently, and a large repository is walked exactly once - // instead of once per worker that races the cold cache. - let cell = { - let mut state = self.state.lock().expect("repo histories mutex poisoned"); - state.histories.entry(workdir.clone()).or_default().clone() - }; - let history = cell - .get_or_init(|| { - match mehen_git::open_repo_at(&workdir) - .and_then(|repo| mehen_git::collect_history(&repo, "HEAD")) - { - Ok(history) => Some(history), - Err(e) => { - log::warn!("history walk failed for {}: {e}", workdir.display()); - let mut state = self.state.lock().expect("repo histories mutex poisoned"); - state.failures.push((workdir.clone(), e.to_string())); - None - } - } - }) - .as_ref()?; - let relative = canonical.strip_prefix(&workdir).ok()?; - // `tracked_file`, not `file`: a workspace path may be an - // untracked file (or a symlink) occupying a spot whose tracked - // blob HEAD deleted — the dead occupant's history is not this - // file's. - history - .tracked_file(relative) - .map(|fh| (fh, history.head_seconds)) - } - - /// Drain the recorded lazy-discovery failures (repositories that - /// exist but whose history was unavailable). - fn take_failures(&self) -> Vec<(PathBuf, String)> { - let mut state = self.state.lock().expect("repo histories mutex poisoned"); - std::mem::take(&mut state.failures) - } -} - -/// Canonicalize a file path *without resolving the final component*: -/// a tracked symlink like `alias.py -> real.py` must keep its own -/// (empty) history rather than borrowing the target file's churn and -/// authorship. Directory components are still resolved so the result -/// is comparable with the canonicalized repository work dir. -fn canonical_file_path(path: &Path) -> Option { - let file_name = path.file_name()?; - let parent = match path.parent() { - Some(parent) if !parent.as_os_str().is_empty() => parent, - _ => Path::new("."), - }; - Some(std::fs::canonicalize(parent).ok()?.join(file_name)) -} - -fn act_on_file(path: PathBuf, cfg: &TopOffendersCfg) -> std::io::Result<()> { - let utf8_path = match Utf8PathBuf::try_from(path.clone()) { - Ok(p) => p, - Err(_) => return Ok(()), - }; - - let language = match cfg.language_override { - Some(l) => l, - None => match detect_language(&utf8_path) { - Some(l) => l, - None => return Ok(()), - }, - }; - - let analyzer = cfg.registry.analyzer_for(language); - - // History metrics don't depend on decoding or parsing the blob: - // a recognized file whose contents static analysis cannot handle - // (e.g. non-UTF-8 but non-binary) — or whose language's analyzer - // is feature-gated off in this build — still has repository - // history, and a history selector must rank it on real values - // instead of silently dropping it. Static-only rankings keep - // skipping such files (an all-zero row would be noise). - let history_entry = cfg.history.as_ref().and_then(|h| h.file(&path)); - - // Coverage likewise comes from report files, not from parsing the - // blob: a matched coverage entry ranks the file on real values - // even when static analysis is unavailable. - let coverage_entry = cfg - .coverage - .as_ref() - .and_then(|context| crate::coverage_metrics::coverage_for_file(context, &utf8_path)); - - let analyzed_root = analyzer.and_then(|analyzer| { - let text = std::fs::read_to_string(&path).ok()?; - let source = SourceFile::new(utf8_path.clone(), language, text); - let analysis = analyzer - .analyze(&source, &mehen_core::AnalysisConfig::default()) - .ok()?; - // A partial tree behind an `Error`/`Fatal` diagnostic is an - // incomplete measurement (§9.3): ranking on it — or feeding - // its truncated cognitive/SLOC values into the history - // composites — would mislead; fall back to history-only. - if crate::diff::has_blocking_diagnostic(&analysis.diagnostics) { - return None; - } - Some(analysis.root) - }); - let statics_available = analyzed_root.is_some(); - let history_available = history_entry.is_some(); - let coverage_available = coverage_entry.is_some(); - let mut root = match analyzed_root { - Some(root) => root, - None if history_available || coverage_available => mehen_core::MetricSpace::new( - mehen_core::SpaceId(0), - mehen_core::SpaceKind::Unit, - mehen_core::SourceSpan::empty(), - ), - None => return Ok(()), - }; - - // Fold the `history.*` family into the metric set so history - // selectors rank on real values. Files without recorded history - // (untracked, outside every known work dir) read the family as - // *unavailable* below; the static-dependent composites are - // omitted when no real analysis backs the space (see - // `inject_history_metrics`). - if let Some((fh, head_seconds)) = history_entry { - crate::history_metrics::inject_history_metrics( - &mut root.metrics, - &fh, - head_seconds, - statics_available, - ); - } - - // Fold the `coverage.*` family in: whole-file dimensions on the - // root, span-scoped line/branch coverage on each function space. - if let Some(file_coverage) = &coverage_entry { - crate::coverage_metrics::inject_coverage_metrics(&mut root, file_coverage); - } - - let metrics: Vec = cfg - .selectors - .iter() - .map(|sel| CliMetricValue { - name: sel.name, - label: sel.label, - // A selector the space cannot back — any static metric on - // a history-only fallback, any `history.*` metric on a - // file without recorded Git history, or any `coverage.*` - // metric on a file no report measured — has no measurable - // value, and the missing-key `0.0` fallback must not rank - // the file on a fabricated one. - value: if crate::coverage_metrics::selector_available_with_coverage( - sel.name, - statics_available, - history_available, - coverage_available, - ) { - Some(read_selector_metric(&root, sel)) - } else { - None - }, - }) - .collect(); - - // Configured thresholds (`mehen.toml`) gate the metrics this - // ranking reports. Evaluation reads the root metric set directly: - // a key the space does not publish is *skipped*, never compared - // as the `0.0` the ranking column falls back to — a fabricated - // zero under a higher-is-better limit would fire a false - // violation on every cross-language file. - if let Some(policy) = &cfg.thresholds { - let names: Vec<&str> = cfg.selectors.iter().map(|s| s.name).collect(); - let breaches = policy.evaluate(&path.display().to_string(), language, &root, Some(&names)); - if !breaches.is_empty() { - cfg.breaches - .lock() - .expect("top-offenders breaches mutex poisoned") - .extend(breaches); - } - } - - cfg.results - .lock() - .expect("top-offenders results mutex poisoned") - .push(FileOffender { path, metrics }); - - Ok(()) -} - -fn cmp_offenders(a: &FileOffender, b: &FileOffender, selectors: &[CliMetricSelector]) -> Ordering { - for (i, sel) in selectors.iter().enumerate() { - let av = a.metrics.get(i).and_then(|m| m.value); - let bv = b.metrics.get(i).and_then(|m| m.value); - let ord = match (av, bv) { - // An uncomputable value ranks as least concerning under - // either polarity — absent, not zero. - (Some(_), None) => Ordering::Less, - (None, Some(_)) => Ordering::Greater, - (None, None) => Ordering::Equal, - (Some(av), Some(bv)) => { - let base = av.total_cmp(&bv); - match sel.polarity { - SelectorPolarity::LowerIsBetter => base.reverse(), - SelectorPolarity::HigherIsBetter => base, - } - } - }; - if ord != Ordering::Equal { - return ord; - } - } - a.path.cmp(&b.path) -} - -fn print_json_offenders(offenders: &[FileOffender]) { - let json = - serde_json::to_string_pretty(offenders).expect("offender list is always serializable"); - writeln!(std::io::stdout().lock(), "{json}").expect("failed to write to stdout"); -} - -fn print_markdown_offenders(offenders: &[FileOffender], selectors: &[CliMetricSelector]) { - let mut out = String::new(); - - if offenders.is_empty() { - out.push_str("## Top Offenders\n\nNo matching files found.\n"); - write!(std::io::stdout().lock(), "{out}").expect("failed to write to stdout"); - return; - } - - let metric_list = selectors - .iter() - .map(|s| s.name) - .collect::>() - .join(", "); - out.push_str(&format!("## Top Offenders (by {metric_list})\n\n")); - - out.push_str("| File |"); - for sel in selectors { - out.push_str(&format!(" {} |", sel.label)); - } - out.push('\n'); - - out.push_str("|---|"); - for _ in selectors { - out.push_str("---:|"); - } - out.push('\n'); - - for o in offenders { - out.push_str(&format!("| {} |", o.path.display())); - for mv in &o.metrics { - out.push_str(&format!( - " {} |", - match mv.value { - Some(v) => format_value(v), - // Uncomputable for this file (see `CliMetricValue::value`). - None => "n/a".to_string(), - } - )); - } - out.push('\n'); - } - - write!(std::io::stdout().lock(), "{out}").expect("failed to write to stdout"); -} - -fn format_value(v: f64) -> String { - if v.is_nan() { - "NaN".to_string() - } else if v == v.trunc() && v.abs() < 1e18 { - format!("{}", v as i64) - } else { - format!("{:.2}", v) - } -} - -fn resolve_num_jobs(requested: Option, available: Option) -> usize { - requested.unwrap_or_else(|| available.unwrap_or(2)) -} - -/// Resolve a `--language` CLI override (e.g. `ps1`, `python`) to the -/// `Language` enum. The legacy spelling is accepted via the -/// `language_aliases()` table in `mehen-core`. -fn parse_language_override(raw: &str) -> Option { - raw.parse::().ok() -} - -pub fn run_top_offenders(opts: TopOffendersOpts, config: Option<&crate::config_file::ConfigFile>) { - let selectors = parse_metric_selectors(&opts.metrics); - if selectors.is_empty() { - log::error!("No valid metrics selected. See `mehen top-offenders --help`."); - process::exit(1); - } - - let language_override = match opts.language_type.as_deref().filter(|s| !s.is_empty()) { - Some(raw) => match parse_language_override(raw) { - Some(language) => Some(language), - None => { - log::error!("Unknown language type '{raw}'."); - process::exit(1); - } - }, - None => None, - }; - - let num_jobs = resolve_num_jobs( - opts.num_jobs, - available_parallelism().ok().map(|threads| threads.get()), - ); - - let include = mk_globset(opts.include); - let exclude = mk_globset(opts.exclude); - - // A `history.*` metric was explicitly requested: the ranking is - // meaningless without the repository walk, so failing to load it - // is a hard error rather than a silent all-zeros column. - let history = if crate::history_metrics::names_want_history(selectors.iter().map(|s| s.name)) { - let histories = RepoHistories::new(); - for root in &opts.paths { - if let Err(e) = histories.load_root(root) { - log::error!("history metrics unavailable for {}: {e}", root.display()); - process::exit(1); - } - } - Some(Arc::new(histories)) - } else { - None - }; - - // Coverage: resolve the flag, the `[coverage]` config section, and - // the lazy trigger (a `coverage.*` ranking column or threshold) - // into an ingested report index. Explicit report problems are hard - // errors; discovery problems degrade to warnings. - let coverage_mode = match opts.coverage.mode() { - Ok(mode) => mode, - Err(e) => { - log::error!("{e}"); - process::exit(1); - } - }; - let coverage_wanted = - crate::coverage_metrics::names_want_coverage(selectors.iter().map(|s| s.name)) - || config.is_some_and(|c| { - c.thresholds - .any_metric(|name| name.starts_with("coverage.")) - }); - let coverage_roots: Vec = { - let mut roots: Vec = opts - .paths - .iter() - .filter_map(|path| Utf8PathBuf::from_path_buf(path.clone()).ok()) - .filter_map(|path| crate::coverage_metrics::coverage_root_for(&path)) - .collect(); - roots.sort_unstable(); - roots.dedup(); - roots - }; - let coverage = match crate::coverage_metrics::resolve_coverage( - &coverage_mode, - config.and_then(|c| c.coverage.as_ref()), - &coverage_roots, - coverage_wanted, - ) { - Ok(context) => context.map(Arc::new), - Err(e) => { - log::error!("{e}"); - process::exit(1); - } - }; - - let results: Arc>> = Arc::new(Mutex::new(Vec::new())); - let breaches: Arc>> = - Arc::new(Mutex::new(Vec::new())); - let registry = Arc::new(AnalyzerRegistry::default_set()); - - let cfg = TopOffendersCfg { - selectors: selectors.clone(), - language_override, - registry, - history: history.clone(), - coverage, - results: results.clone(), - thresholds: config - .map(|c| c.thresholds.clone()) - .filter(|policy| !policy.is_empty()), - breaches: breaches.clone(), - }; - - let files_data = FilesData { - include, - exclude, - paths: opts.paths, - respect_ignores: !opts.no_ignore, - }; - - if let Err(e) = ConcurrentRunner::new(num_jobs, act_on_file).run(cfg, files_data) { - log::error!("{e}"); - process::exit(1); - } - - // A history metric was explicitly requested; a repository whose - // history could not be loaded during lazy discovery (e.g. a - // shallow nested clone found mid-traversal) means part of the - // ranking silently ran on absent history — that must fail the - // command, matching the eager root-load semantics. - if let Some(histories) = history.as_ref() { - let failures = histories.take_failures(); - if !failures.is_empty() { - for (location, message) in &failures { - log::error!( - "history metrics unavailable for {}: {message}", - location.display() - ); - } - process::exit(1); - } - } - - let mut offenders = Arc::try_unwrap(results) - .expect("results Arc still has outstanding references") - .into_inner() - .expect("results mutex poisoned"); - - offenders.sort_by(|a, b| cmp_offenders(a, b, &selectors)); - offenders.truncate(opts.max_results); - - match opts.output_format { - TopOffendersFormat::Json => print_json_offenders(&offenders), - TopOffendersFormat::Markdown => print_markdown_offenders(&offenders, &selectors), - } - - // Configured metric thresholds (`mehen.toml`): evaluated against - // *every* analyzed file — not just the displayed top N, so a - // violation cannot hide below the `--max-results` cut. The - // ranking above still prints in full before the run fails. - let mut breaches = Arc::try_unwrap(breaches) - .expect("breaches Arc still has outstanding references") - .into_inner() - .expect("top-offenders breaches mutex poisoned"); - if !breaches.is_empty() - && let Some(config) = config - { - eprint!( - "{}", - crate::config_file::render_threshold_report(&mut breaches, &config.path) - ); - // Exit 1: configured quality gates fail with the generic - // failure code (`mehen.toml` threshold contract). - process::exit(1); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::Language; - - fn entry(path: &str, scores: &[f64]) -> TopOffenderEntry { - TopOffenderEntry { - path: Utf8PathBuf::from(path), - language: Language::Rust, - scores: scores.iter().copied().map(Some).collect(), - } - } - - const HIW2: &[Polarity] = &[Polarity::HigherIsWorse, Polarity::HigherIsWorse]; - const HIW3: &[Polarity] = &[ - Polarity::HigherIsWorse, - Polarity::HigherIsWorse, - Polarity::HigherIsWorse, - ]; - - #[test] - fn primary_score_ranks_first() { - let mut xs = [entry("a.rs", &[10.0, 0.0]), entry("b.rs", &[20.0, 0.0])]; - xs.sort_by(|a, b| cmp_entries(a, b, HIW2)); - assert_eq!(xs[0].path, "b.rs"); - assert_eq!(xs[1].path, "a.rs"); - } - - #[test] - fn secondary_selector_breaks_ties_on_primary() { - // All three files tie on primary `loc.lloc = 100.0`. The - // secondary `cognitive` selector must determine the order; - // the file with the highest cognitive score is most - // concerning. - let mut xs = [ - entry("a.rs", &[100.0, 5.0]), - entry("b.rs", &[100.0, 30.0]), - entry("c.rs", &[100.0, 12.0]), - ]; - xs.sort_by(|a, b| cmp_entries(a, b, HIW2)); - assert_eq!(xs[0].path, "b.rs"); - assert_eq!(xs[1].path, "c.rs"); - assert_eq!(xs[2].path, "a.rs"); - } - - #[test] - fn tertiary_selector_breaks_ties_on_secondary() { - let mut xs = [ - entry("a.rs", &[10.0, 5.0, 1.0]), - entry("b.rs", &[10.0, 5.0, 9.0]), - entry("c.rs", &[10.0, 5.0, 4.0]), - ]; - xs.sort_by(|a, b| cmp_entries(a, b, HIW3)); - assert_eq!(xs[0].path, "b.rs"); - assert_eq!(xs[1].path, "c.rs"); - assert_eq!(xs[2].path, "a.rs"); - } - - #[test] - fn fully_tied_falls_through_to_path() { - let mut xs = [ - entry("zzz.rs", &[42.0, 7.0]), - entry("aaa.rs", &[42.0, 7.0]), - entry("mmm.rs", &[42.0, 7.0]), - ]; - xs.sort_by(|a, b| cmp_entries(a, b, HIW2)); - assert_eq!(xs[0].path, "aaa.rs"); - assert_eq!(xs[1].path, "mmm.rs"); - assert_eq!(xs[2].path, "zzz.rs"); - } - - #[test] - fn nan_score_is_treated_as_equal() { - let mut xs = [ - entry("a.rs", &[f64::NAN, 5.0]), - entry("b.rs", &[f64::NAN, 30.0]), - ]; - xs.sort_by(|a, b| cmp_entries(a, b, HIW2)); - // NaN primaries compare equal; secondary breaks the tie. - assert_eq!(xs[0].path, "b.rs"); - assert_eq!(xs[1].path, "a.rs"); - } - - #[test] - fn uncomputable_score_ranks_least_concerning_under_either_polarity() { - // `None` marks a score that could not be computed (e.g. a - // history composite without static analysis). It must sort - // *after* every real value — including under higher-is-better - // polarity, where the old `0.0` fallback would have ranked - // the file as the very worst offender. - let none_entry = |path: &str| TopOffenderEntry { - path: Utf8PathBuf::from(path), - language: Language::Rust, - scores: vec![None], - }; - for polarity in [Polarity::HigherIsWorse, Polarity::HigherIsBetter] { - let mut xs = [ - none_entry("na.rs"), - entry("real_low.rs", &[1.0]), - entry("real_high.rs", &[50.0]), - ]; - xs.sort_by(|a, b| cmp_entries(a, b, &[polarity])); - assert_eq!( - xs[2].path, "na.rs", - "uncomputable score must rank last for {polarity:?}" - ); - } - } - - #[test] - fn higher_is_better_metric_sorts_smallest_first() { - // For maintainability index a low value is the worst offender, - // so `bad.rs` (mi = 10) must rank above `good.rs` (mi = 120). - let mut xs = [ - entry("good.rs", &[120.0]), - entry("bad.rs", &[10.0]), - entry("mid.rs", &[60.0]), - ]; - xs.sort_by(|a, b| cmp_entries(a, b, &[Polarity::HigherIsBetter])); - assert_eq!(xs[0].path, "bad.rs"); - assert_eq!(xs[1].path, "mid.rs"); - assert_eq!(xs[2].path, "good.rs"); - } - - #[test] - fn mixed_polarities_sort_each_axis_independently() { - // Primary loc.lloc (lower-is-worse): 200 > 10, so high-LOC - // files rank first. Secondary mi (higher-is-worse): when LOC - // ties, the file with the *lower* mi should rank first. - let mut xs = [ - entry("low_loc_high_mi.rs", &[10.0, 120.0]), - entry("high_loc_high_mi.rs", &[200.0, 120.0]), - entry("high_loc_low_mi.rs", &[200.0, 30.0]), - ]; - xs.sort_by(|a, b| cmp_entries(a, b, &[Polarity::HigherIsWorse, Polarity::HigherIsBetter])); - assert_eq!(xs[0].path, "high_loc_low_mi.rs"); - assert_eq!(xs[1].path, "high_loc_high_mi.rs"); - assert_eq!(xs[2].path, "low_loc_high_mi.rs"); - } - - #[test] - fn default_polarity_treats_mi_variants_as_higher_is_better() { - for s in ["mi.original", "mi.sei", "mi.visual_studio", "mi"] { - assert_eq!( - default_polarity_for(&sel(s)), - Polarity::HigherIsBetter, - "selector {s}", - ); - } - } - - #[test] - fn default_polarity_treats_other_metrics_as_higher_is_worse() { - for s in [ - "cyclomatic", - "cognitive", - "loc.lloc", - "halstead.volume", - "abc", - "nom.functions", - ] { - assert_eq!( - default_polarity_for(&sel(s)), - Polarity::HigherIsWorse, - "selector {s}", - ); - } - } - - fn space_with_metrics(pairs: &[(&str, f64)]) -> mehen_core::MetricSpace { - use mehen_core::{MetricSpace, SourceSpan, SpaceId, SpaceKind}; - let mut space = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - for (k, v) in pairs { - space.metrics.insert(MetricKey::new(*k), *v); - } - space - } - - fn sel(s: &str) -> MetricSelector { - s.parse().unwrap() - } - - #[test] - fn root_aggregator_reads_bare_key() { - let space = space_with_metrics(&[("loc.lloc", 42.0), ("loc.lloc.max", 999.0)]); - assert_eq!(read_metric(&sel("loc.lloc"), &space), 42.0); - } - - #[test] - fn sql_quality_scores_are_higher_is_better_for_ranking() { - // Regression: `default_polarity_for` only knew `mi.*`, so the SQL - // quality scores were ranked higher-is-worse — surfacing the - // *healthiest* SQL files as the top offenders (Codex P2). - assert_eq!( - default_polarity_for(&sel("sql.maintainability_index")), - Polarity::HigherIsBetter - ); - assert_eq!( - default_polarity_for(&sel("sql.modularity_health")), - Polarity::HigherIsBetter - ); - // A risk score stays higher-is-worse (larger = more offending). - assert_eq!( - default_polarity_for(&sel("sql.change_risk_score")), - Polarity::HigherIsWorse - ); - // mi.* is unchanged. - assert_eq!( - default_polarity_for(&sel("mi.visual_studio")), - Polarity::HigherIsBetter - ); - } - - #[test] - fn sum_aggregator_reads_sum_suffixed_key() { - let space = space_with_metrics(&[ - ("cyclomatic", 1.0), - ("cyclomatic.sum", 17.0), - ("cyclomatic.max", 9.0), - ]); - assert_eq!(read_metric(&sel("cyclomatic.sum"), &space), 17.0); - } - - #[test] - fn min_aggregator_reads_min_suffixed_key() { - let space = space_with_metrics(&[ - ("loc.lloc", 100.0), - ("loc.lloc.min", 3.0), - ("loc.lloc.max", 50.0), - ]); - assert_eq!(read_metric(&sel("loc.lloc.min"), &space), 3.0); - } - - #[test] - fn max_aggregator_reads_max_suffixed_key() { - let space = space_with_metrics(&[ - ("loc.lloc", 100.0), - ("loc.lloc.min", 3.0), - ("loc.lloc.max", 50.0), - ]); - assert_eq!(read_metric(&sel("loc.lloc.max"), &space), 50.0); - } - - #[test] - fn avg_aggregator_prefers_avg_then_average() { - // `cyclomatic` publishes `.avg`; `cognitive` publishes - // `.average`. The aggregator must locate either spelling so - // selectors written `cognitive.avg` still resolve to the - // analyzer's `cognitive.average` value. - let cyclomatic = space_with_metrics(&[("cyclomatic.avg", 2.5)]); - assert_eq!(read_metric(&sel("cyclomatic.avg"), &cyclomatic), 2.5); - - let cognitive = space_with_metrics(&[("cognitive.average", 3.5)]); - assert_eq!(read_metric(&sel("cognitive.avg"), &cognitive), 3.5); - } - - #[test] - fn missing_aggregated_key_falls_back_to_zero() { - // When the analyzer didn't publish the requested aggregation, - // matches the existing root-key contract: 0.0 instead of - // panicking, so a single missing metric doesn't break the - // whole rank pass. - let space = space_with_metrics(&[("loc.lloc", 100.0)]); - assert_eq!(read_metric(&sel("loc.lloc.max"), &space), 0.0); - } - - #[test] - fn min_max_aggregators_resolve_underscore_subbucket_keys() { - // Regression: `mehen-metrics::state::publish_nom` writes - // `nom.functions_min`, `nom.functions_max`, `nom.closures_min`, - // `nom.closures_max` (underscore suffixes), and `publish_abc` / - // `publish_npa` / `publish_npm` / `publish_nargs` follow the - // same convention for their sub-bucket aggregates. Pre-fix the - // suffix lookup only tried the dotted form - // (`nom.functions.max`), so any selector targeting one of - // those buckets — `nom.functions.max`, `abc.assignments.min`, - // `npa.classes.average`, etc. — silently read 0.0. That - // misordered top-offenders rankings and suppressed - // diff-threshold violations whenever users gated on a - // sub-bucket aggregate. - let space = space_with_metrics(&[ - ("nom.functions", 12.0), - ("nom.functions_min", 1.0), - ("nom.functions_max", 7.0), - ("nom.functions_average", 3.5), - ("nom.closures_max", 4.0), - ("abc.assignments_max", 9.0), - ("npa.classes_average", 2.25), - ("nargs.functions_max", 6.0), - ]); - assert_eq!(read_metric(&sel("nom.functions.min"), &space), 1.0); - assert_eq!(read_metric(&sel("nom.functions.max"), &space), 7.0); - assert_eq!(read_metric(&sel("nom.functions.avg"), &space), 3.5); - assert_eq!(read_metric(&sel("nom.closures.max"), &space), 4.0); - assert_eq!(read_metric(&sel("abc.assignments.min"), &space), 0.0); - assert_eq!(read_metric(&sel("abc.assignments.max"), &space), 9.0); - assert_eq!(read_metric(&sel("npa.classes.avg"), &space), 2.25); - assert_eq!(read_metric(&sel("nargs.functions.max"), &space), 6.0); - } - - #[test] - fn dotted_form_takes_precedence_over_underscore() { - // If both forms exist, the dotted form wins — `cyclomatic.max` - // is the canonical convention; underscore is only a fallback - // for the sub-bucket families. This guards against a future - // analyzer bug where a publisher accidentally writes both - // forms with different values: the canonical key still drives - // ranking. - let space = space_with_metrics(&[("nom.functions.max", 11.0), ("nom.functions_max", 99.0)]); - assert_eq!(read_metric(&sel("nom.functions.max"), &space), 11.0); - } - - #[test] - fn rank_top_offenders_ranks_history_selectors_on_real_values() { - // The exported API must honor `history.*` selectors just like - // the CLI path — a library caller supplying - // `history.commit_frequency` gets a history-based ranking, not - // all zeros in alphabetical order. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - let git = |args: &[&str]| { - let output = std::process::Command::new("git") - .current_dir(dir.path()) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - }; - git(&["init", "-q", "-b", "main"]); - git(&["config", "commit.gpgsign", "false"]); - // aaa_calm.py sorts first alphabetically but has one commit; - // zzz_busy.py has two — the history ranking must invert the - // alphabetical order. - std::fs::write(dir.path().join("aaa_calm.py"), "a = 1\n").unwrap(); - std::fs::write(dir.path().join("zzz_busy.py"), "z = 1\n").unwrap(); - git(&["add", "-A"]); - git(&["commit", "-q", "-m", "one"]); - std::fs::write(dir.path().join("zzz_busy.py"), "z = 1\ny = 2\n").unwrap(); - git(&["add", "-A"]); - git(&["commit", "-q", "-m", "two"]); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![sel("history.commit_frequency")], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - assert!(report.analysis_errors.is_empty(), "no history-load errors"); - let ranked: Vec<(&str, f64)> = report - .entries - .iter() - .map(|e| { - ( - e.path.file_name().unwrap_or(""), - e.scores[0].expect("score computed"), - ) - }) - .collect(); - assert_eq!( - ranked, - vec![("zzz_busy.py", 2.0), ("aaa_calm.py", 1.0)], - "history selector must drive the ranking" - ); - } - - #[test] - fn rank_top_offenders_ranks_undecodable_files_on_history() { - // A recognized file whose contents static analysis cannot - // decode still has repository history — the exported API must - // rank it (empty metric space + injection) instead of - // silently dropping it. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - let git = |args: &[&str]| { - let output = std::process::Command::new("git") - .current_dir(dir.path()) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - }; - git(&["init", "-q", "-b", "main"]); - git(&["config", "commit.gpgsign", "false"]); - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\n").unwrap(); - std::fs::write(dir.path().join("plain.py"), "y = 1\n").unwrap(); - git(&["add", "-A"]); - git(&["commit", "-q", "-m", "one"]); - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\nz = 2\n").unwrap(); - git(&["add", "-A"]); - git(&["commit", "-q", "-m", "two"]); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![sel("history.commit_frequency")], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - let ranked: Vec<(&str, f64)> = report - .entries - .iter() - .map(|e| { - ( - e.path.file_name().unwrap_or(""), - e.scores[0].expect("score computed"), - ) - }) - .collect(); - assert_eq!( - ranked, - vec![("latin.py", 2.0), ("plain.py", 1.0)], - "undecodable file must rank on its history" - ); - } - - #[test] - fn rank_top_offenders_reports_composites_as_uncomputable_without_statics() { - // The static-dependent composites (`history.hotspot`, - // `history.churn.relative`) cannot be valued for a file whose - // static analysis is unavailable — the score must surface as - // `None` (JSON `null`) and rank least concerning, not as a - // fabricated `0.0` read through the missing-key fallback. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - let git = |args: &[&str]| { - let output = std::process::Command::new("git") - .current_dir(dir.path()) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - }; - git(&["init", "-q", "-b", "main"]); - git(&["config", "commit.gpgsign", "false"]); - // latin.py is undecodable (Latin-1) but *busier* in history; - // plain.py decodes and has a real (possibly zero) hotspot. - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\n").unwrap(); - std::fs::write(dir.path().join("plain.py"), "y = 1\n").unwrap(); - git(&["add", "-A"]); - git(&["commit", "-q", "-m", "one"]); - std::fs::write(dir.path().join("latin.py"), b"# caf\xe9\nx = 1\nz = 2\n").unwrap(); - git(&["add", "-A"]); - git(&["commit", "-q", "-m", "two"]); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![ - sel("history.hotspot"), - sel("history.churn.relative"), - sel("loc.lloc"), - ], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - let latin = report - .entries - .iter() - .find(|e| e.path.file_name() == Some("latin.py")) - .expect("undecodable file still ranked (history-only)"); - assert_eq!( - latin.scores, - vec![None, None, None], - "composites *and* plain statics must be uncomputable, not zero" - ); - let plain = report - .entries - .iter() - .find(|e| e.path.file_name() == Some("plain.py")) - .expect("decodable file ranked"); - assert!( - plain.scores.iter().all(|s| s.is_some()), - "statically analyzed file keeps real composite values" - ); - // Least concerning: the uncomputable entry sorts after the - // real (even zero-valued) one. - assert_eq!( - report.entries.last().map(|e| e.path.file_name()), - Some(Some("latin.py")) - ); - } - - #[test] - fn rank_top_offenders_marks_history_unavailable_for_untracked_files() { - // An untracked file has statics but no recorded Git history: - // its `history.*` scores must read as uncomputable (`None`) - // and rank least concerning — `history.age_months = 0` or - // `history.ownership = 0` would otherwise crown it the worst - // offender and crowd real tracked files out of the ranking. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - let git = |args: &[&str]| { - let output = std::process::Command::new("git") - .current_dir(dir.path()) - .args(args) - .env("GIT_AUTHOR_NAME", "Mehen Test") - .env("GIT_AUTHOR_EMAIL", "test@mehen.invalid") - .env("GIT_COMMITTER_NAME", "Mehen Test") - .env("GIT_COMMITTER_EMAIL", "test@mehen.invalid") - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - }; - git(&["init", "-q", "-b", "main"]); - git(&["config", "commit.gpgsign", "false"]); - std::fs::write(dir.path().join("tracked.py"), "x = 1\n").unwrap(); - git(&["add", "-A"]); - git(&["commit", "-q", "-m", "one"]); - // Present in the workspace only. - std::fs::write(dir.path().join("untracked.py"), "y = 1\n").unwrap(); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![sel("history.commit_frequency")], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - let score = |name: &str| { - report - .entries - .iter() - .find(|e| e.path.file_name() == Some(name)) - .unwrap_or_else(|| panic!("{name} missing from {:?}", report.entries)) - .scores[0] - }; - assert_eq!(score("tracked.py"), Some(1.0)); - assert_eq!( - score("untracked.py"), - None, - "no Git history means no measurable history score" - ); - assert_eq!( - report.entries.last().map(|e| e.path.file_name()), - Some(Some("untracked.py")), - "unmeasured files rank least concerning" - ); - } - - #[test] - fn rank_top_offenders_rejects_unknown_history_selectors() { - // The engine boundary accepts arbitrary selector strings: a - // typo'd history key must surface as an analysis error and - // score as uncomputable — never as an all-zero ranking after - // a pointless repository walk. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write(dir.path().join("plain.py"), "y = 1\n").unwrap(); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![ - sel("history.commit_frequncy"), - // Valid key, unsupported aggregator: enrichment - // publishes root keys only. - sel("history.commit_frequency.max"), - ], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - assert!( - report.analysis_errors.iter().any(|record| { - record - .diagnostics - .iter() - .any(|d| d.code == "engine.unknown_metric") - }), - "the typo must be surfaced: {:?}", - report.analysis_errors - ); - let plain = report - .entries - .iter() - .find(|e| e.path.file_name() == Some("plain.py")) - .expect("statically analyzed file still listed"); - assert_eq!( - plain.scores, - vec![None, None], - "unresolvable selectors must score as uncomputable, not zero" - ); - } - - #[test] - fn rank_top_offenders_skips_files_with_blocking_diagnostics() { - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - // Valid Python file: should appear in the offender list. - std::fs::write( - dir.path().join("ok.py"), - "def f():\n if True:\n return 1\n", - ) - .unwrap(); - // Syntax error: ruff returns Ok(LanguageAnalysis) with an - // Error-severity diagnostic and a partial tree. Pre-fix this - // file would be ranked alongside ok.py with bogus partial - // metrics; post-fix it must be skipped. - std::fs::write(dir.path().join("broken.py"), "def f(:\n return 1\n").unwrap(); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![sel("loc.lloc")], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - let paths: Vec<&str> = report - .entries - .iter() - .map(|e| e.path.file_name().unwrap_or("")) - .collect(); - assert!( - paths.contains(&"ok.py"), - "expected ok.py in entries, got {paths:?}" - ); - assert!( - !paths.contains(&"broken.py"), - "broken.py should be skipped due to blocking diagnostic, got {paths:?}" - ); - } - - #[test] - fn rank_top_offenders_skips_gitignored_and_attributed_files() { - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - gix::init(dir.path()).unwrap(); - std::fs::create_dir(dir.path().join("node_modules")).unwrap(); - std::fs::write(dir.path().join(".gitignore"), "node_modules/\n").unwrap(); - std::fs::write( - dir.path().join(".gitattributes"), - "\ -* -linguist-generated -linguist-vendored -binary -generated.py linguist-generated -vendored.py linguist-vendored -binary.py binary -", - ) - .unwrap(); - std::fs::write(dir.path().join("kept.py"), "x = 1\n").unwrap(); - std::fs::write( - dir.path().join("node_modules/generated.py"), - "def generated():\n if True:\n return 1\n", - ) - .unwrap(); - for name in ["generated.py", "vendored.py", "binary.py"] { - std::fs::write( - dir.path().join(name), - "def excluded():\n if True:\n return 1\n", - ) - .unwrap(); - } - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![sel("loc.lloc")], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - let names: Vec<&str> = report - .entries - .iter() - .filter_map(|entry| entry.path.file_name()) - .collect(); - - assert_eq!(names, vec!["kept.py"]); - } - - #[test] - fn rank_top_offenders_dedupes_overlapping_roots() { - // Regression: when callers pass overlapping roots (a directory - // plus a child directory, or a directory plus an explicit file - // inside it), `rank_top_offenders` previously analyzed and - // pushed each matching file once per root, crowding out other - // files at `max_results` truncation. Post-fix the dedup set - // collapses every spelling of the same canonical path to one - // entry. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - let sub = dir.path().join("sub"); - std::fs::create_dir(&sub).unwrap(); - std::fs::write(sub.join("a.py"), "x = 1\n").unwrap(); - std::fs::write(sub.join("b.py"), "y = 2\n").unwrap(); - - let outer = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap(); - let inner = Utf8PathBuf::from_path_buf(sub.clone()).unwrap(); - let explicit_file = Utf8PathBuf::from_path_buf(sub.join("a.py")).unwrap(); - - let input = TopOffendersInput { - // Overlapping inputs: root + child directory + explicit - // file inside the child. Without dedup, `a.py` appears - // three times in `entries`. - paths: vec![outer, inner, explicit_file], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![sel("loc.lloc")], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - let names: Vec<&str> = report - .entries - .iter() - .map(|e| e.path.file_name().unwrap_or("")) - .collect(); - - let a_count = names.iter().filter(|n| **n == "a.py").count(); - let b_count = names.iter().filter(|n| **n == "b.py").count(); - assert_eq!( - a_count, 1, - "a.py must be ranked exactly once, got {names:?}" - ); - assert_eq!( - b_count, 1, - "b.py must be ranked exactly once, got {names:?}" - ); - assert_eq!( - report.entries.len(), - 2, - "expected 2 unique offenders across overlapping roots, got {names:?}" - ); - } - - #[cfg(unix)] - #[test] - fn rank_top_offenders_keeps_symlink_aliases_distinct() { - use std::os::unix::fs::symlink; - - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write(dir.path().join("source.py"), "x = 1\n").unwrap(); - symlink("source.py", dir.path().join("alias.py")).unwrap(); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec![sel("loc.lloc")], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - - // A tracked symlink is its own repository entry with its own - // (empty) history — collapsing it into its target would make - // history rankings depend on traversal order and diverge from - // the CLI path, which reports both identities. Dedup still - // collapses different *spellings* of one path (overlapping - // roots, directory symlinks) via parent canonicalization. - let mut names: Vec<&str> = report - .entries - .iter() - .filter_map(|e| e.path.file_name()) - .collect(); - names.sort_unstable(); - assert_eq!( - names, - vec!["alias.py", "source.py"], - "a file and its symlink alias are distinct identities" - ); - } - - #[test] - fn walk_paths_applies_exclude_patterns() { - let dir = tempfile::tempdir().expect("tempdir"); - let kept = dir.path().join("kept.py"); - let skipped = dir.path().join("skipped.py"); - std::fs::write(&kept, "x = 1\n").unwrap(); - std::fs::write(&skipped, "x = 1\n").unwrap(); - - let root = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap(); - let result = walk_paths( - std::slice::from_ref(&root), - &[], - &["**/skipped.py".to_string()], - ); - let names: Vec<&str> = result.iter().filter_map(|p| p.file_name()).collect(); - assert!(names.contains(&"kept.py"), "expected kept.py in {names:?}"); - assert!( - !names.contains(&"skipped.py"), - "skipped.py should be excluded, got {names:?}" - ); - } - - #[test] - fn walk_paths_applies_include_patterns() { - let dir = tempfile::tempdir().expect("tempdir"); - let py = dir.path().join("a.py"); - let rs = dir.path().join("a.rs"); - std::fs::write(&py, "x = 1\n").unwrap(); - std::fs::write(&rs, "fn main() {}\n").unwrap(); - - let root = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap(); - let result = walk_paths(std::slice::from_ref(&root), &["**/*.py".to_string()], &[]); - let names: Vec<&str> = result.iter().filter_map(|p| p.file_name()).collect(); - assert!(names.contains(&"a.py"), "expected a.py in {names:?}"); - assert!( - !names.contains(&"a.rs"), - "a.rs should not be included, got {names:?}" - ); - } - - #[test] - fn walk_paths_empty_filters_keep_all_files() { - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write(dir.path().join("a.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("b.rs"), "fn main() {}\n").unwrap(); - - let root = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap(); - let result = walk_paths(std::slice::from_ref(&root), &[], &[]); - let names: Vec<&str> = result.iter().filter_map(|p| p.file_name()).collect(); - assert!(names.contains(&"a.py")); - assert!(names.contains(&"b.rs")); - } - - #[test] - fn walk_paths_filters_a_single_file_root() { - // When `root` itself is a file, the include/exclude patterns - // still apply: an excluded file must not appear in the list. - let dir = tempfile::tempdir().expect("tempdir"); - let path = dir.path().join("vendored.py"); - std::fs::write(&path, "x = 1\n").unwrap(); - let root = Utf8PathBuf::from_path_buf(path).unwrap(); - let result = walk_paths( - std::slice::from_ref(&root), - &[], - &["**/vendored.py".to_string()], - ); - assert!( - result.is_empty(), - "single-file root must respect exclude, got {result:?}" - ); - } - - // ── pre-1.0 CLI orchestrator tests ───────────────────────────────── - - fn cli_selector(name: &'static str, polarity: SelectorPolarity) -> CliMetricSelector { - CliMetricSelector { - name, - label: name, - polarity, - } - } - - fn offender(path: &str, values: &[(&'static str, f64)]) -> FileOffender { - FileOffender { - path: PathBuf::from(path), - metrics: values - .iter() - .map(|(n, v)| CliMetricValue { - name: n, - label: n, - value: Some(*v), - }) - .collect(), - } - } - - #[test] - fn cli_lower_is_better_puts_largest_value_first() { - let selectors = [cli_selector("loc.lloc", SelectorPolarity::LowerIsBetter)]; - let mut xs = [ - offender("small.rs", &[("loc.lloc", 10.0)]), - offender("huge.rs", &[("loc.lloc", 1000.0)]), - offender("medium.rs", &[("loc.lloc", 100.0)]), - ]; - xs.sort_by(|a, b| cmp_offenders(a, b, &selectors)); - assert_eq!(xs[0].path, PathBuf::from("huge.rs")); - assert_eq!(xs[1].path, PathBuf::from("medium.rs")); - assert_eq!(xs[2].path, PathBuf::from("small.rs")); - } - - #[test] - fn cli_higher_is_better_puts_smallest_value_first() { - let selectors = [cli_selector( - "mi.visual_studio", - SelectorPolarity::HigherIsBetter, - )]; - let mut xs = [ - offender("good.rs", &[("mi", 120.0)]), - offender("bad.rs", &[("mi", 10.0)]), - offender("mid.rs", &[("mi", 60.0)]), - ]; - xs.sort_by(|a, b| cmp_offenders(a, b, &selectors)); - assert_eq!(xs[0].path, PathBuf::from("bad.rs")); - assert_eq!(xs[1].path, PathBuf::from("mid.rs")); - assert_eq!(xs[2].path, PathBuf::from("good.rs")); - } - - #[test] - fn cli_ties_on_primary_metric_fall_through_to_secondary() { - let selectors = [ - cli_selector("loc.lloc", SelectorPolarity::LowerIsBetter), - cli_selector("cognitive", SelectorPolarity::LowerIsBetter), - ]; - let mut xs = [ - offender("a.rs", &[("loc.lloc", 100.0), ("cognitive", 5.0)]), - offender("b.rs", &[("loc.lloc", 100.0), ("cognitive", 30.0)]), - offender("c.rs", &[("loc.lloc", 50.0), ("cognitive", 999.0)]), - ]; - xs.sort_by(|a, b| cmp_offenders(a, b, &selectors)); - assert_eq!(xs[0].path, PathBuf::from("b.rs")); - assert_eq!(xs[1].path, PathBuf::from("a.rs")); - assert_eq!(xs[2].path, PathBuf::from("c.rs")); - } - - #[test] - fn cli_all_tied_breaks_by_path_for_determinism() { - let selectors = [cli_selector("loc.lloc", SelectorPolarity::LowerIsBetter)]; - let mut xs = [ - offender("zzz.rs", &[("loc.lloc", 42.0)]), - offender("aaa.rs", &[("loc.lloc", 42.0)]), - offender("mmm.rs", &[("loc.lloc", 42.0)]), - ]; - xs.sort_by(|a, b| cmp_offenders(a, b, &selectors)); - assert_eq!(xs[0].path, PathBuf::from("aaa.rs")); - assert_eq!(xs[1].path, PathBuf::from("mmm.rs")); - assert_eq!(xs[2].path, PathBuf::from("zzz.rs")); - } - - #[test] - fn cli_mixed_polarities_sort_each_axis_independently() { - let selectors = [ - cli_selector("loc.lloc", SelectorPolarity::LowerIsBetter), - cli_selector("mi.visual_studio", SelectorPolarity::HigherIsBetter), - ]; - let mut xs = [ - offender("low_loc_high_mi.rs", &[("loc", 10.0), ("mi", 120.0)]), - offender("high_loc_high_mi.rs", &[("loc", 200.0), ("mi", 120.0)]), - offender("high_loc_low_mi.rs", &[("loc", 200.0), ("mi", 30.0)]), - ]; - xs.sort_by(|a, b| cmp_offenders(a, b, &selectors)); - assert_eq!(xs[0].path, PathBuf::from("high_loc_low_mi.rs")); - assert_eq!(xs[1].path, PathBuf::from("high_loc_high_mi.rs")); - assert_eq!(xs[2].path, PathBuf::from("low_loc_high_mi.rs")); - } - - #[test] - fn cli_format_value_renders_integers_without_decimals() { - assert_eq!(format_value(42.0), "42"); - assert_eq!(format_value(0.0), "0"); - assert_eq!(format_value(1.5), "1.50"); - assert_eq!(format_value(100.567), "100.57"); - } - - #[test] - fn cli_explicit_num_jobs_is_not_predecremented() { - assert_eq!(resolve_num_jobs(Some(8), Some(16)), 8); - } - - #[test] - fn cli_num_jobs_falls_back_to_conservative_thread_count() { - assert_eq!(resolve_num_jobs(None, None), 2); - } - - #[test] - fn cli_no_ignore_is_opt_in() { - #[derive(clap::Parser)] - struct TestCli { - #[command(flatten)] - opts: TopOffendersOpts, - } - - let default = - ::try_parse_from(["mehen", "--metric", "loc.lloc", "."]) - .unwrap(); - assert!(!default.opts.no_ignore); - - let disabled = ::try_parse_from([ - "mehen", - "--metric", - "loc.lloc", - "--no-ignore", - ".", - ]) - .unwrap(); - assert!(disabled.opts.no_ignore); - } - - #[test] - fn record_unavailable_emits_warning_record() { - // Regression: when language detection succeeds but no analyzer - // is registered (feature-gated build), the file must surface - // as a non-fatal `analysis_error` so callers can tell that an - // offender was silently dropped, instead of believing the - // ranking is complete. Mirrors `mehen-engine::diff`'s - // `record_unavailable`. - let mut errors: Vec = Vec::new(); - record_unavailable( - &mut errors, - &Utf8PathBuf::from("src/main.kt"), - Language::Kotlin, - ); - assert_eq!(errors.len(), 1); - let rec = &errors[0]; - assert_eq!(rec.path, Utf8PathBuf::from("src/main.kt")); - assert_eq!(rec.side, DiffSide::Head); - assert_eq!(rec.diagnostics.len(), 1); - assert_eq!(rec.diagnostics[0].code, "engine.analyzer_unavailable"); - assert!( - rec.diagnostics[0].message.contains("kotlin"), - "message must name the unavailable language; got: {}", - rec.diagnostics[0].message - ); - assert_eq!( - rec.diagnostics[0].severity, - mehen_core::DiagnosticSeverity::Warning, - "unavailable analyzer is non-fatal" - ); - } - - #[test] - fn rank_top_offenders_includes_empty_analysis_errors_when_clean() { - // A clean run with all analyzers available produces an - // `analysis_errors` field — even when empty — so JSON - // consumers can rely on its presence. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write(dir.path().join("ok.py"), "x = 1\n").unwrap(); - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec!["loc.lloc".parse().unwrap()], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - assert!(report.analysis_errors.is_empty()); - } - - #[test] - fn rank_top_offenders_ranks_on_explicit_coverage_reports() { - // A `coverage.*` selector backed by an explicit LCOV report: - // matched files score real values; unmatched files read the - // selector as unavailable (`None`), never as fabricated 0%. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write(dir.path().join("covered.py"), "x = 1\ny = 2\n").unwrap(); - std::fs::write(dir.path().join("unmeasured.py"), "z = 3\n").unwrap(); - // Report spelled with a CI-style absolute prefix that does not - // exist here — the suffix matcher must absorb it. - std::fs::write( - dir.path().join("lcov.info"), - "TN:\nSF:/home/ci/work/repo/repo/covered.py\nDA:1,1\nDA:2,0\nend_of_record\n", - ) - .unwrap(); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec!["coverage.line".parse().unwrap()], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: vec![ - Utf8PathBuf::from_path_buf(dir.path().join("lcov.info")).unwrap(), - ], - }; - let report = rank_top_offenders(input); - let score_for = |name: &str| { - report - .entries - .iter() - .find(|e| e.path.as_str().ends_with(name)) - .map(|e| e.scores[0]) - }; - // 1 of 2 instrumented lines hit → 50%. - assert_eq!(score_for("covered.py"), Some(Some(50.0))); - // Unmeasured file: `None`, ranked as least concerning. - assert_eq!(score_for("unmeasured.py"), Some(None)); - assert!(report.analysis_errors.is_empty()); - } - - #[test] - fn rank_top_offenders_reports_unusable_coverage_report() { - // An unreadable/unparsable explicit report surfaces as an - // `analysis_error` (this API has no fatal channel), and the - // coverage column reads as unavailable for every file. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write(dir.path().join("ok.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("bogus.info"), "not a coverage report").unwrap(); - - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec!["coverage.line".parse().unwrap()], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: vec![ - // Read failure: exercises the diagnostic-record sink. - Utf8PathBuf::from_path_buf(dir.path().join("missing.info")).unwrap(), - // `.info` extension sniffs as LCOV, but the content has - // no SF record — an empty report. - Utf8PathBuf::from_path_buf(dir.path().join("bogus.info")).unwrap(), - ], - }; - let report = rank_top_offenders(input); - assert!( - report.analysis_errors.iter().any(|e| { - e.path.as_str().ends_with("missing.info") - && e.diagnostics[0].code == "engine.coverage_unavailable" - }), - "expected an engine.coverage_unavailable record, got {:?}", - report.analysis_errors - ); - // The empty report yields no measurements: every file reads - // unavailable, never fabricated 0%. - for entry in &report.entries { - assert_eq!(entry.scores[0], None, "{}", entry.path); - } - } - - #[test] - fn coverage_selector_with_aggregator_is_rejected() { - // `coverage.line.max` parses as key `coverage.line` + - // aggregator `Max`, which enrichment can never resolve (flat - // root keys only) — it must be flagged, mirroring history. - use mehen_core::{AnalysisConfig, TopOffendersInput}; - - let dir = tempfile::tempdir().expect("tempdir"); - std::fs::write(dir.path().join("ok.py"), "x = 1\n").unwrap(); - let input = TopOffendersInput { - paths: vec![Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).unwrap()], - include: Vec::new(), - exclude: Vec::new(), - selectors: vec!["coverage.line.max".parse().unwrap()], - max_results: 10, - config: AnalysisConfig::default(), - coverage_reports: Vec::new(), - }; - let report = rank_top_offenders(input); - assert!( - report - .analysis_errors - .iter() - .any(|e| e.diagnostics[0].message.contains("coverage")), - "expected an unresolvable-coverage-selector record, got {:?}", - report.analysis_errors - ); - } -} diff --git a/crates/mehen-git/Cargo.toml b/crates/mehen-git/Cargo.toml deleted file mode 100644 index 5d5e473e..00000000 --- a/crates/mehen-git/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "mehen-git" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — git/repository operations and changed-file detection (internal)." -publish = false - -[dependencies] -gix = { workspace = true } -log = { workspace = true } - -[dev-dependencies] -tempfile = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-git/src/history.rs b/crates/mehen-git/src/history.rs deleted file mode 100644 index d2c02cb4..00000000 --- a/crates/mehen-git/src/history.rs +++ /dev/null @@ -1,2423 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Git history-walk subsystem backing the `history.*` metric family -//! (post-classical metrics research foundation §6). -//! -//! [`collect_history`] performs a single revision walk from a given rev -//! and accumulates deterministic per-file process metrics: churn, code -//! age, authorship/ownership, commit frequency, sum of coupling, -//! bug-fix commit count, and Google's Time-Weighted Risk. -//! -//! Determinism contract: every value is a pure function of the -//! repository state at the walked rev. "Now" is the walked commit's -//! own committer time (research foundation §6.2), never wall-clock -//! time, so results are reproducible across runs and machines. -//! -//! Walk semantics match the common reference implementations -//! (code-maat, PyDriller, `git log --no-merges --numstat`): -//! merge commits are skipped and every other commit is diffed against -//! its first parent (or the empty tree for root commits). Renames use -//! `gix` rewrite plumbing with pinned `-M50%` options and a raw-object, -//! attribute-free diff pipeline, so machine configuration cannot alter -//! identity. A renamed file keeps its accumulated history under its -//! head-relative path, and a pure rename churns no lines. - -use std::collections::HashMap; -use std::path::{Path, PathBuf}; - -use crate::GitError; -use crate::tree_changes::{ - RENAME_SIMILARITY, TreeChange, blob_lineage_similarity, blob_modifications_between_trees, - blob_size, changes_between_trees, count_lines, is_binary, line_diff_counts, read_blob_data, - same_blob_lineage, -}; - -/// Average Gregorian month in seconds (30.436875 days), used to express -/// code age in months without depending on calendar arithmetic. -const SECONDS_PER_MONTH: f64 = 2_629_746.0; - -/// Commits touching more than this many files are ignored for the -/// sum-of-coupling signal (code-maat / CodeScene changeset noise -/// threshold, research foundation §6.4). Such commits — bulk renames, -/// reformat sweeps, vendored imports — carry no architectural coupling -/// signal. All other metrics still count them. -const MAX_COUPLING_CHANGESET: usize = 30; - -/// An author contributing less than this share of a file's added -/// lines is a "minor contributor" (PyDriller's fixed 5% threshold, -/// research foundation §6.3). -const MINOR_CONTRIBUTOR_SHARE: f64 = 0.05; - -/// Steepness / decay-window constants of the Time-Weighted Risk -/// logistic: `1 / (1 + e^(-12t + 12))` (Lewis et al., ICSE 2013, with -/// ω hard-coded to 12 as in the paper's deployed variant). -const TWR_STEEPNESS: f64 = 12.0; -const TWR_OMEGA: f64 = 12.0; - -/// Blobs larger than this are never materialized for churn counting; -/// they contribute zero lines, mirroring `git log --numstat`, which -/// reports `-` (no line counts) for binary files. Sizes are checked -/// via object headers, so a historically modified multi-gigabyte -/// binary costs two header reads per touching commit instead of -/// exhausting memory. -const MAX_CHURN_BLOB_BYTES: u64 = 8 * 1024 * 1024; - -/// Deterministic per-file history statistics, finalized over the full -/// walk. Raw counts are exposed alongside derived ratios so callers can -/// build composites (e.g. hotspot = complexity × [`Self::commit_frequency`]). -#[derive(Debug, Clone, PartialEq)] -pub struct FileHistory { - /// Number of non-merge commits that touched the file - /// (`history.commit_frequency`). - pub commit_frequency: u64, - /// Total lines added across those commits. - pub churn_added: u64, - /// Total lines removed across those commits. - pub churn_removed: u64, - /// Number of distinct authors (`history.authors`), identified by - /// lower-cased author email (falling back to the author name when - /// the email is empty). - pub authors: u64, - /// Authors who wrote less than 5% of the file's added lines - /// (`history.minor_contributors`, PyDriller's fixed threshold). - pub minor_contributors: u64, - /// Share of the file's added lines written by the single top - /// author (`history.ownership`), in `[0, 1]`. Only *added* lines - /// count as authorship — deleting someone else's code is not - /// writing code. `0` when no lines were ever added. - pub ownership: f64, - /// Committer timestamp (seconds since epoch) of the last commit - /// touching the file. - pub last_change_seconds: i64, - /// Sum over qualifying commits of the number of *other* files - /// changed alongside this one (`history.sum_of_coupling`). - pub sum_of_coupling: u64, - /// Commits whose message matches the bug-fix heuristic - /// (`history.bugfix_commits`). - pub bugfix_commits: u64, - /// Time-Weighted Risk over the bug-fixing commits - /// (`history.twr`). - pub twr: f64, -} - -impl FileHistory { - /// Absolute churn: lines added + lines removed - /// (`history.churn.abs`, code-maat's `abs-churn` definition). - pub fn churn_abs(&self) -> u64 { - self.churn_added + self.churn_removed - } - - /// Months since the file's last change, relative to `head_seconds` - /// (`history.age_months`). Clamped at zero for robustness against - /// clock-skewed commit metadata. - pub fn age_months(&self, head_seconds: i64) -> f64 { - let delta = head_seconds.saturating_sub(self.last_change_seconds); - (delta.max(0) as f64) / SECONDS_PER_MONTH - } - - /// A tracked blob no walked (non-merge) commit ever touched — - /// e.g. one created purely by merge conflict resolution. Every - /// count reads a legitimate zero; the last change is the blob's - /// creation time (the introducing merge's timestamp, or the - /// walked rev when unknown), so `age_months` measures the time it - /// has sat untouched. - fn untouched(creation_seconds: i64) -> Self { - Self { - commit_frequency: 0, - churn_added: 0, - churn_removed: 0, - authors: 0, - minor_contributors: 0, - ownership: 0.0, - last_change_seconds: creation_seconds, - sum_of_coupling: 0, - bugfix_commits: 0, - twr: 0.0, - } - } -} - -/// Per-file history statistics for an entire repository at a fixed rev. -#[derive(Debug)] -pub struct RepositoryHistory { - /// Committer timestamp (seconds since epoch) of the walked rev — - /// the deterministic "now" for age computations. - pub head_seconds: i64, - files: HashMap, - /// Blob paths present in the walked rev's tree, for - /// [`tracked_file`](Self::tracked_file). - head_blobs: std::collections::HashSet, - /// Creation timestamps of conflict-resolution-created blobs - /// (merge-introduced additions, which never accumulate - /// contributions) — the basis for a synthesized zero entry's age. - merge_creation_seconds: HashMap, - /// Files whose lineage crosses a path this platform cannot - /// represent (Windows, raw non-UTF-8 rename source): their - /// earlier commits, churn, and authorship are unreachable here, - /// so the per-file lookups report them unmeasurable rather than - /// publishing the truncated remainder as if it were the whole - /// history. Always empty on Unix. - truncated_lineages: std::collections::HashSet, -} - -impl RepositoryHistory { - /// History stats for a repository-relative path, if any walked - /// commit touched it — including files *deleted* at the walked - /// rev, whose history diff baselines still read. - pub fn file(&self, path: &Path) -> Option<&FileHistory> { - if self.truncated_lineages.contains(path) { - // The lineage crosses a platform-unrepresentable path: - // whatever accumulated is a truncated fabrication, not - // this file's history. - return None; - } - self.files.get(path) - } - - /// Like [`file`](Self::file), but only for paths that exist as - /// blobs at the walked rev. Workspace-oriented consumers (ranking - /// files found on disk) must use this: an untracked file — or a - /// symlink — occupying a path whose tracked blob HEAD deleted has - /// no history of its own, and returning the dead occupant's would - /// assign it someone else's commits, churn, and authors. - /// - /// A tracked blob *without* an accumulator (created purely by - /// merge conflict resolution, never touched by a walked non-merge - /// commit) reads a legitimate all-zero history rather than `None` - /// — it is measured (nothing ever happened to it), not - /// unmeasurable like an untracked path. - pub fn tracked_file(&self, path: &Path) -> Option { - if !self.head_blobs.contains(path) || self.truncated_lineages.contains(path) { - return None; - } - Some(self.files.get(path).cloned().unwrap_or_else(|| { - // Age measures from the creating merge — pinning it to - // the walked rev would make an old, untouched blob read - // as newly changed forever. - FileHistory::untouched( - self.merge_creation_seconds - .get(path) - .copied() - .unwrap_or(self.head_seconds), - ) - })) - } - - /// Number of files with recorded history. - pub fn len(&self) -> usize { - self.files.len() - } - - /// Whether the walk recorded no file history at all. - pub fn is_empty(&self) -> bool { - self.files.is_empty() - } -} - -/// One walked change contributing to a file identity. Contributions -/// stay un-folded until the walk finishes: a rename discovered later -/// (walk order is newest-first) may have to split everything -/// accumulated under its source path between the renamed lineage and -/// a newer occupant of the vacated path, and that partition is by -/// commit ancestry — folded counters could not be taken apart again. -#[derive(Debug, Clone)] -struct Contribution { - commit: gix::ObjectId, - /// Committer timestamp in seconds. - seconds: i64, - author: std::sync::Arc<[u8]>, - added: u64, - removed: u64, - /// Other files changed in the same commit (`history.coupling`). - coupled_others: u64, - /// Whether the changeset was small enough to count for coupling. - coupling_eligible: bool, - is_bugfix: bool, - /// Whether this change *created* the file (a tree-diff addition). - is_addition: bool, -} - -/// Per-file accumulator filled during the walk, finalized into -/// [`FileHistory`] once repository-wide bounds (first/head commit -/// times) are known. -#[derive(Debug, Default)] -struct FileAccumulator { - contributions: Vec, - /// Whether any contribution created the file — cached because the - /// delete-then-recreate boundary check runs once per deletion. - has_addition: bool, -} - -impl FileAccumulator { - fn push(&mut self, contribution: Contribution) { - self.has_addition |= contribution.is_addition; - self.contributions.push(contribution); - } - - /// Fold another accumulator into this one — used when a rename is - /// discovered *after* the walk already accumulated changes under - /// the source path (a parallel branch's later-timestamp commit can - /// precede the rename in the newest-first order). - fn merge(&mut self, other: FileAccumulator) { - self.has_addition |= other.has_addition; - self.contributions.extend(other.contributions); - } - - fn is_empty(&self) -> bool { - self.contributions.is_empty() - } -} - -/// Walk the full history reachable from `rev` (first-parent diffs; -/// merges contribute no churn but may install rename identity) and -/// accumulate per-file process statistics. -/// -/// The cost is one tree diff per commit plus one line diff per -/// modified blob; results depend only on the repository state at -/// `rev`. -pub fn collect_history(repo: &gix::Repository, rev: &str) -> Result { - // Accelerate the walk's many commit/blob lookups (gix maintainer - // guidance): an in-memory object cache for repeated reads, and one - // reusable revision graph for all ancestry queries. - let mut repo = repo.clone(); - repo.object_cache_size_if_unset(4 * 1024 * 1024); - let repo = &repo; - let commit_graph_cache = repo - .commit_graph_if_enabled() - .map_err(|e| GitError::Internal(e.to_string()))?; - let mut ancestry: AncestryGraph<'_, '_> = repo.revision_graph(commit_graph_cache.as_ref()); - - let head_id = repo - .rev_parse_single(rev) - .map_err(|_| GitError::RefNotFound(rev.to_string()))?; - let head_commit = head_id - .object() - .map_err(|e| GitError::Internal(e.to_string()))? - .peel_to_commit() - .map_err(|e| GitError::Internal(e.to_string()))?; - let head_seconds = commit_seconds(&head_commit)?; - let head_blobs = tree_blob_paths(&head_commit)?; - - let mut files: HashMap = HashMap::new(); - let mut first_commit_seconds = head_seconds; - // Rename identity: maps a historical path to entries describing - // what it became (a head-relative path, or a tombstone standing in - // for a dead prior occupant), each scoped by the commit that - // installed it — see `resolve_alias` for the ancestry gate and - // preference order. Values are stored fully resolved; resolution - // is a single lookup, deliberately not chain-following (chasing - // chains through a later destination boundary would misroute a - // lineage into a tombstone). Rename destinations get a *boundary* - // entry: older direct changes to the destination path belong to a - // dead prior occupant, and are redirected to a per-boundary - // tombstone so the surviving file never inherits them. - let mut aliases: HashMap> = HashMap::new(); - let mut tombstones: usize = 0; - // Conflict-resolution-created blobs (merge-introduced additions) - // never accumulate contributions, but their *creation time* is - // real history: `tracked_file` synthesizes their zero entry from - // it so `history.age_months` measures time since the creating - // merge instead of reading an eternal 0. Newest-first walk: the - // first-seen merge addition for a path is the one that created - // the blob HEAD still carries. - let mut merge_creation_seconds: HashMap = HashMap::new(); - // Files whose lineage crosses a path this platform cannot - // represent (Windows, raw non-UTF-8 rename source): their earlier - // history is unreachable here, and publishing the truncated - // remainder would fabricate a young, single-author file — the - // per-file lookups report them unmeasurable instead. Always empty - // on Unix. - let mut truncated_lineages: std::collections::HashSet = - std::collections::HashSet::new(); - // Every walked merge `(id, parents)` — including ones that - // introduced no identity changes. The phase-2 delete-then-recreate - // cut consults this to recognize a *bypassed* deletion: one whose - // path survived around it through another parent of a downstream - // merge (see below). Ids only; no tree work is done here. - let mut walked_merges: Vec<(gix::ObjectId, Vec)> = Vec::new(); - - // Date-order traversal (`git rev-list --date-order`): commits come - // newest-first by timestamp, but crucially *no parent is emitted - // before all of its children* — the rename-alias machinery depends - // on seeing every descendant (and its renames) before an ancestor, - // which plain commit-time ordering cannot guarantee when clock - // skew makes an ancestor's timestamp newer than a descendant's. - let walk = gix::traverse::commit::topo::Builder::from_iters( - repo.objects.clone(), - [head_commit.id], - None::>, - ) - .sorting(gix::traverse::commit::topo::Sorting::DateOrder) - .build() - .map_err(|e| GitError::Internal(e.to_string()))?; - - for info in walk { - let info = info.map_err(|e| GitError::Internal(e.to_string()))?; - let is_merge = info.parent_ids.len() > 1; - - let commit = repo - .find_object(info.id) - .map_err(|e| GitError::Internal(e.to_string()))? - .peel_to_commit() - .map_err(|e| GitError::Internal(e.to_string()))?; - - // Merge commits contribute no churn: their first-parent diff - // would double-count every line already attributed to the - // merged commits (matching `git log --no-merges` / code-maat). - // But a merge can still *create identity*: conflict resolution - // may commit a tree that renames a file present in a parent - // (`a.rs` in the parents, `b.rs` in the merged tree) or - // creates a file at a brand-new path. Such merge-introduced - // changes — destination absent from every parent tree — must - // install aliases and boundaries like any other commit, or - // older commits accumulate under vacated paths while the - // surviving files read an empty (or worse, a dead prior - // occupant's) history. - let (changes, non_blob_changes, commit_truncated) = if is_merge { - walked_merges.push((info.id, info.parent_ids.iter().copied().collect())); - let mut merge_truncated: Vec = Vec::new(); - let introduced = merge_introduced_changes(repo, &commit, &mut merge_truncated)?; - if introduced.is_empty() && merge_truncated.is_empty() { - continue; - } - // Identity only — merges never reach the coupling math. - (introduced, 0, merge_truncated) - } else { - diff_against_first_parent(repo, &commit)? - }; - // Truncated-lineage markers are keyed by the *live* identity: - // the marker's path is the rename destination as of this - // commit, but a newer (already-walked) rename may have moved - // the file on — resolving through the pre-commit alias map - // lands the marker on the path `tracked_file` will actually - // be asked about. A tombstone resolution means the truncated - // line is already fenced off as dead: nothing to mark. - for path in commit_truncated { - if let (FileIdentity::Path(live), _, _) = - resolve_alias(repo, &mut ancestry, &aliases, &path, info.id, false)? - { - truncated_lineages.insert(live); - } - } - if is_merge && changes.is_empty() { - continue; - } - - let seconds = commit_seconds(&commit)?; - if !is_merge { - // Merges never accumulate, so they don't bound the TWR - // normalization window either (as before this walk saw - // identity-bearing merges at all). - first_commit_seconds = first_commit_seconds.min(seconds); - } - let author: std::sync::Arc<[u8]> = std::sync::Arc::from(author_identity(&commit)?); - let is_bugfix = is_bugfix_message(commit.message_raw_sloppy()); - - // ── Phase 1: resolve every change against the *pre-commit* - // alias map, so same-commit rename cycles (an a↔b swap) don't - // resolve through each other's just-installed aliases. Each - // resolution remembers which entry applied (if any) so the - // consumed flag lands on the right one. - let mut targets: Vec = Vec::with_capacity(changes.len()); - let mut used_entries: Vec> = Vec::with_capacity(changes.len()); - let mut floor_gated_entries: Vec> = Vec::with_capacity(changes.len()); - for change in &changes { - let (target, used, floor_gated) = resolve_alias( - repo, - &mut ancestry, - &aliases, - &change.path, - info.id, - change.is_addition, - )?; - targets.push(target); - used_entries.push(used); - floor_gated_entries.push(floor_gated); - } - // Paths that are rename *sources* in this commit: a swap's - // destination is simultaneously a source, and its older - // changes are a lineage this commit moves elsewhere — not a - // dead prior occupant to fence off. - let commit_sources: std::collections::HashSet<&PathBuf> = changes - .iter() - .filter_map(|change| change.source_path.as_ref()) - .collect(); - - // ── Phase 2: a deletion *older* than a re-creation of the - // same path cuts the lineage: the re-creation (and everything - // on its descendants) belongs to a new file, and this deletion - // plus everything older belongs to the dead prior occupant. - // The proof must be ancestry-precise: either an accumulated - // *addition* at this path from a descendant of the deletion, - // or a consumed alias entry installed on the deletion's own - // descendant line (the recreation was redirected through it). - // A parallel branch's *edits* walked earlier are modifications - // only and must not split the identity. - for ((change, target), used) in changes.iter().zip(targets.iter_mut()).zip(&used_entries) { - if !change.is_deletion || used.is_some() { - continue; - } - let mut recreation_seen = false; - if let Some(acc) = files.get(&FileIdentity::Path(change.path.clone())) { - for c in &acc.contributions { - if c.is_addition && is_descendant_of(repo, &mut ancestry, info.id, c.commit)? { - recreation_seen = true; - break; - } - } - } - if !recreation_seen && let Some(entries) = aliases.get(&change.path) { - for entry in entries { - if entry.consumed - && !entry.from_discarded_occupant - && entry.applies_to(repo, &mut ancestry, info.id, false)? - { - recreation_seen = true; - break; - } - } - } - if !recreation_seen { - continue; - } - // A recreation-cut deletion may still be *bypassed*: an - // already-walked merge kept the path alive through another - // parent whose line never dropped it, discarding this - // deletion's branch. Then the recreation on this line is a - // dead occupant — not the live file's birth — and cutting - // here would tombstone the shared pre-branch creation away - // from the survivor. When the discarded recreation's blob - // differs from some endpoint the merge-time fences catch - // it; a recreation byte-identical to the surviving blob is - // invisible to every tree diff and only this walk-level - // check can see it. The bypass requires exact - // continuation: a merge parent that does not descend from - // this deletion, holds the very blob the merged tree - // keeps, and carries it over an uninterrupted line. - let mut bypass: Option<(gix::ObjectId, Option)> = None; - 'merges: for (merge_id, parents) in &walked_merges { - let Some(merge_oid) = blob_oid_in_commit(repo, *merge_id, &change.path)? else { - continue; - }; - for q in parents { - // The parent that carried this deletion into the - // merge. - if !is_descendant_of(repo, &mut ancestry, info.id, *q)? { - continue; - } - for s in parents { - if s == q - || is_descendant_of(repo, &mut ancestry, info.id, *s)? - || blob_oid_in_commit(repo, *s, &change.path)? != Some(merge_oid) - { - continue; - } - let floor = match repo.merge_base(*s, *q) { - Ok(base) => Some(base.detach()), - Err(gix::repository::merge_base::Error::NotFound { .. }) => None, - Err(e) => return Err(GitError::Internal(e.to_string())), - }; - if let Some(floor) = floor - && path_deleted_in_range(repo, *s, floor, &change.path)? - { - continue; - } - bypass = Some((*q, floor)); - break 'merges; - } - } - } - tombstones += 1; - let tombstone = FileIdentity::Tombstone(tombstones); - if let Some((scope, floor)) = bypass { - // Install the fence the merge would have installed had - // the recreation been visible to its diffs, and move - // the already-accumulated dead-line contributions (the - // recreation and its descendants up to the discarded - // parent) behind it. The deletion itself stays a touch - // on the surviving path, exactly like a merge-time - // fence leaves it. - let path_id = FileIdentity::Path(change.path.clone()); - if let Some(acc) = files.get_mut(&path_id) { - let contributions = std::mem::take(&mut acc.contributions); - let mut kept = Vec::with_capacity(contributions.len()); - let mut moved: Vec = Vec::new(); - for c in contributions { - if is_descendant_of(repo, &mut ancestry, info.id, c.commit)? - && is_descendant_of(repo, &mut ancestry, c.commit, scope)? - { - moved.push(c); - } else { - kept.push(c); - } - } - acc.has_addition = kept.iter().any(|c| c.is_addition); - acc.contributions = kept; - if acc.is_empty() { - files.remove(&path_id); - } - if !moved.is_empty() { - let dead = files.entry(tombstone.clone()).or_default(); - for c in moved { - dead.push(c); - } - } - } - let mut entry = AliasEntry::new(tombstone, vec![scope]); - entry.floor = floor; - entry.from_discarded_occupant = true; - aliases.entry(change.path.clone()).or_default().push(entry); - } else { - aliases - .entry(change.path.clone()) - .or_default() - .push(AliasEntry::new(tombstone.clone(), vec![info.id])); - *target = tombstone; - } - } - - // ── Phase 3: install rename aliases, boundaries, and stranded - // merges (all against the phase-1 resolutions). Entry vectors - // only ever grow or mark entries consumed here — removing - // entries would invalidate the indices phase 4 uses to mark - // consumption. - let mut new_boundaries: Vec<(PathBuf, FileIdentity)> = Vec::new(); - // Entries a change of this very commit resolved through: such - // an entry is *in use* — e.g. a same-commit replacement's - // creation resolving into a later deletion's fence — and must - // not be reclaimed or retired by this commit's renames. - let mut in_use: HashMap<&PathBuf, std::collections::HashSet> = HashMap::new(); - for (change, used) in changes.iter().zip(&used_entries) { - if let Some(idx) = used { - in_use.entry(&change.path).or_default().insert(*idx); - } - } - for (change, target) in changes.iter().zip(targets.iter()) { - let Some(source) = &change.source_path else { - continue; - }; - if matches!(target, FileIdentity::Path(p) if p == source) { - // A rename returning to its own identity (a→b→a): - // reconnect the lineage by retiring stale destination - // boundaries, so pre-rename commits flow to the - // survivor again instead of a tombstone. - if let Some(entries) = aliases.get_mut(source) { - for (idx, entry) in entries.iter_mut().enumerate() { - if matches!(entry.target, FileIdentity::Tombstone(_)) - && !in_use.get(source).is_some_and(|s| s.contains(&idx)) - { - entry.consumed = true; - } - } - } - continue; - } - // Install alongside any existing entries: ancestry scoping - // disambiguates at resolution time. When parallel branches - // renamed the same source differently and the merge kept - // both, each branch's pre-rename edits are ancestors of - // only their own rename and route to the right survivor; - // for shared ancestors (the common pre-branch lineage) the - // first-visited entry wins — deterministic under the - // deterministic walk order, and the shared history is - // counted once rather than duplicated into both survivors. - // A *tombstone* entry is reclaimable outright — unless a - // change of this same commit resolved through it (the - // fence is in active use), or this very commit installed - // it (a same-commit deletion boundary, e.g. a merge that - // both moves one parent's file and fences another - // parent's dead occupant of the same path) — because this - // rename explains where the fenced-off occupant actually - // went (it was renamed away, not merely deleted): its - // fenced contributions move to the rename target and the - // fence retires. - let entries = aliases.entry(source.clone()).or_default(); - let mut reclaimed = FileAccumulator::default(); - for (idx, entry) in entries.iter_mut().enumerate() { - if entry.consumed - || !matches!(entry.target, FileIdentity::Tombstone(_)) - || in_use.get(source).is_some_and(|s| s.contains(&idx)) - || entry.scopes.contains(&info.id) - { - continue; - } - if let Some(fenced) = files.remove(&entry.target) { - reclaimed.merge(fenced); - } - entry.consumed = true; - } - // The alias redirects the *older* commits that are walked - // after this rename (the pre-rename lineage). A - // merge-introduced rename carries the scopes of the - // parents that supplied the source (and an addition floor - // when they span several parents); everything else is - // scoped to this commit. - let mut alias_entry = AliasEntry::new( - target.clone(), - change.alias_scopes.clone().unwrap_or_else(|| vec![info.id]), - ); - alias_entry.addition_floor = change.alias_addition_floor; - entries.push(alias_entry); - if !reclaimed.is_empty() { - files.entry(target.clone()).or_default().merge(reclaimed); - } - // Anything already accumulated under the source path is - // *newer in walk order* than this rename — but it can mix - // two occupants: concurrent branches' edits belong to the - // renamed lineage (they edited the file that moved away), - // while a re-creation of the vacated path (and the edits - // in its descendants) is a distinct newer file. Commit - // ancestry separates the two: descendants of this rename - // postdate it on its own line, and a concurrent *addition* - // is a parallel branch's re-creation (an addition cannot - // edit the moved file) — both belong to the new occupant, - // as do edits descending from such a re-creation. Anything - // else concurrent edited the renamed lineage. - let source_id = FileIdentity::Path(source.clone()); - if let Some(stranded) = files.remove(&source_id) { - let mut occupant = FileAccumulator::default(); - let mut recreations: Vec = Vec::new(); - let mut pending: Vec = Vec::new(); - for contribution in stranded.contributions { - if contribution.is_addition - && !is_descendant_of(repo, &mut ancestry, info.id, contribution.commit)? - { - recreations.push(contribution.commit); - occupant.push(contribution); - } else if is_descendant_of(repo, &mut ancestry, info.id, contribution.commit)? { - occupant.push(contribution); - } else { - pending.push(contribution); - } - } - let mut lineage = FileAccumulator::default(); - 'pending: for contribution in pending { - for recreation in &recreations { - if is_descendant_of(repo, &mut ancestry, *recreation, contribution.commit)? - { - occupant.push(contribution); - continue 'pending; - } - } - lineage.push(contribution); - } - if !occupant.is_empty() { - files.insert(source_id, occupant); - } - if !lineage.is_empty() { - files.entry(target.clone()).or_default().merge(lineage); - } - } - // Destination identity boundary: older direct changes to - // the destination path belong to a dead prior occupant — - // unless the destination is itself a rename source in this - // same commit (a swap), in which case its older changes - // are a live lineage this commit moves elsewhere, or the - // change opts out (a merge rename converging onto a - // parent-owned destination whose older history is real). - if change.install_destination_boundary && !commit_sources.contains(&change.path) { - tombstones += 1; - let boundary = FileIdentity::Tombstone(tombstones); - aliases - .entry(change.path.clone()) - .or_default() - .push(AliasEntry::new(boundary.clone(), vec![info.id])); - new_boundaries.push((change.path.clone(), boundary)); - } - } - // A commit that renames one file *over* another emits both - // `Renamed(a → b)` and `Deleted(b)`; the deletion is the old - // occupant of `b` dying, and belongs behind the destination - // boundary just installed — not in the surviving lineage, - // where its removed lines, author, and commit would pollute - // the new `b`'s history. - for ((change, target), used) in changes.iter().zip(targets.iter_mut()).zip(&used_entries) { - if !change.is_deletion || used.is_some() { - continue; - } - if let Some((_, boundary)) = - new_boundaries.iter().find(|(path, _)| *path == change.path) - { - *target = boundary.clone(); - } - } - - // ── Phase 4: accumulate. Merge commits install identity only — - // their churn is deliberately excluded (see above). - if is_merge { - // A merge-introduced *addition* (conflict resolution - // creating a file at a path absent from every parent) - // establishes a fresh identity: older commits touching - // the path belong to a dead prior occupant. Merges never - // accumulate, so the usual delete-then-recreate fence - // (which needs an accumulated creation as proof) can - // never fire for them — install the boundary eagerly. - for (change, target) in changes.iter().zip(targets.iter()) { - if let Some((scope, floor)) = change.discarded_occupant_fence { - tombstones += 1; - let mut entry = - AliasEntry::new(FileIdentity::Tombstone(tombstones), vec![scope]); - entry.floor = floor; - entry.from_discarded_occupant = true; - aliases.entry(change.path.clone()).or_default().push(entry); - } - if change.is_addition { - // Record the creation time only when the addition - // resolves to a live path — and key it by that - // *resolved* path: a parallel merge's discarded - // occupant resolves through its fence to a - // tombstone (skipped), and a merge-created file - // later renamed by another merge resolves to its - // final name, which is the key `tracked_file` - // will look up. - if let FileIdentity::Path(live) = target { - merge_creation_seconds - .entry(live.clone()) - .or_insert(seconds); - } - tombstones += 1; - aliases - .entry(change.path.clone()) - .or_default() - .push(AliasEntry::new( - FileIdentity::Tombstone(tombstones), - vec![info.id], - )); - } - } - continue; - } - // The changeset size for coupling includes every changed leaf - // path — symlinks and submodule pointer bumps co-change like - // any other file even though they carry no analyzable text — - // so both the noise threshold and the "other files in this - // commit" count use the full cardinality. - let coupling_paths = changes.len() + non_blob_changes; - let coupling_eligible = coupling_paths <= MAX_COUPLING_CHANGESET; - // The "other files in this commit" count is the same for every - // file in the changeset. - let coupled_others = coupling_paths.saturating_sub(1) as u64; - for (index, ((change, target), used)) in changes - .iter() - .zip(targets.iter()) - .zip(&used_entries) - .enumerate() - { - // An addition that resolved *through* an alias entry is - // the redirected occupant's birth: every deletion or - // rename of this path walked from here on is older than - // that birth and belongs to a previous occupant, so mark - // the applied entry consumed (see `AliasEntry`). - if change.is_addition - && let Some(idx) = used - && let Some(entries) = aliases.get_mut(&change.path) - { - entries[*idx].consumed = true; - } - // A *floor-gated* addition is a recreated occupant's birth - // on a scoped line (see `AliasEntry::addition_floor`). Its - // edits — descendants of this addition, inside the entry's - // scopes — were walked earlier and routed through the - // alias into the rename target; pull them back to the - // occupant's own identity now that its birth proves they - // belong to it. Genuine parallel edits of the moved file - // are concurrent with (not descendants of) the recreation - // and stay put, as do the rename target's own commits - // (outside the entry's scopes). - if change.is_addition - && let Some(idx) = floor_gated_entries[index] - { - let (entry_target, entry_scopes) = { - let entry = &aliases[&change.path][idx]; - (entry.target.clone(), entry.scopes.clone()) - }; - let mut moved: Vec = Vec::new(); - if let Some(acc) = files.get_mut(&entry_target) { - let contributions = std::mem::take(&mut acc.contributions); - let mut kept = Vec::with_capacity(contributions.len()); - for c in contributions { - let mut is_occupant_edit = - is_descendant_of(repo, &mut ancestry, info.id, c.commit)?; - if is_occupant_edit { - let mut in_scope = false; - for scope in &entry_scopes { - if is_descendant_of(repo, &mut ancestry, c.commit, *scope)? { - in_scope = true; - break; - } - } - is_occupant_edit = in_scope; - } - if is_occupant_edit { - moved.push(c); - } else { - kept.push(c); - } - } - acc.has_addition = kept.iter().any(|c| c.is_addition); - acc.contributions = kept; - if acc.is_empty() { - files.remove(&entry_target); - } - } - if !moved.is_empty() { - let occupant = files.entry(target.clone()).or_default(); - for c in moved { - occupant.push(c); - } - } - } - files.entry(target.clone()).or_default().push(Contribution { - commit: info.id, - seconds, - author: author.clone(), - added: change.added, - removed: change.removed, - coupled_others, - coupling_eligible, - is_bugfix, - is_addition: change.is_addition, - }); - } - } - - let files = files - .into_iter() - .filter_map(|(identity, acc)| match identity { - FileIdentity::Path(path) => { - Some((path, finalize_file(acc, first_commit_seconds, head_seconds))) - } - // Dead prior occupants: their fenced-off accumulations - // exist only so live lineages don't inherit them. - FileIdentity::Tombstone(_) => None, - }) - .collect(); - - Ok(RepositoryHistory { - head_seconds, - files, - head_blobs, - merge_creation_seconds, - truncated_lineages, - }) -} - -/// Blob paths in a commit's tree (recursive). -fn tree_blob_paths( - commit: &gix::Commit<'_>, -) -> Result, GitError> { - let internal = |e: &dyn std::error::Error| GitError::Internal(e.to_string()); - let tree = commit.tree().map_err(|e| internal(&e))?; - let mut recorder = gix::traverse::tree::Recorder::default(); - tree.traverse() - .breadthfirst(&mut recorder) - .map_err(|e| internal(&e))?; - Ok(recorder - .records - .into_iter() - .filter(|entry| entry.mode.is_blob()) - .filter_map(|entry| crate::tree_changes::path_from_git(&entry.filepath)) - .collect()) -} - -/// Fold a walk-time accumulator into the public [`FileHistory`]. -fn finalize_file(acc: FileAccumulator, first_seconds: i64, head_seconds: i64) -> FileHistory { - let mut churn_added = 0u64; - let mut churn_removed = 0u64; - let mut last_change_seconds = i64::MIN; - let mut sum_of_coupling = 0u64; - let mut bugfix_seconds: Vec = Vec::new(); - let mut authors: std::collections::HashSet<&[u8]> = std::collections::HashSet::new(); - // Added lines per author — the *authorship* signal driving - // ownership and minor-contributor classification. Deletion-only / - // rename-only touches deliberately never appear here: a zero - // entry would classify the toucher as a sub-5% minor contributor - // despite having written nothing. - let mut author_lines: HashMap<&[u8], u64> = HashMap::new(); - for c in &acc.contributions { - churn_added += c.added; - churn_removed += c.removed; - last_change_seconds = last_change_seconds.max(c.seconds); - if c.coupling_eligible { - sum_of_coupling += c.coupled_others; - } - if c.is_bugfix { - bugfix_seconds.push(c.seconds); - } - authors.insert(&c.author); - if c.added > 0 { - *author_lines.entry(&c.author).or_insert(0) += c.added; - } - } - - let authors = authors.len() as u64; - let total_lines: u64 = author_lines.values().sum(); - let (minor_contributors, ownership) = if total_lines == 0 { - // A history of pure renames/mode changes/deletions adds no - // lines; ownership is undefined — report zero rather than - // dividing by zero. - (0, 0.0) - } else { - let total = total_lines as f64; - let minor = author_lines - .values() - .filter(|&&lines| (lines as f64) / total < MINOR_CONTRIBUTOR_SHARE) - .count() as u64; - let top = author_lines.values().copied().max().unwrap_or(0); - (minor, (top as f64) / total) - }; - - FileHistory { - commit_frequency: acc.contributions.len() as u64, - churn_added, - churn_removed, - authors, - minor_contributors, - ownership, - // Signed: valid raw commit metadata can be pre-epoch, and - // clamping the timestamp itself would misreport `age_months` - // for a pre-epoch analyzed revision (the elapsed difference - // is clamped where it is computed instead). `i64::MIN` only - // survives an accumulator with no contributions; pin it to - // the walked rev so the degenerate age reads 0. - last_change_seconds: if last_change_seconds == i64::MIN { - head_seconds - } else { - last_change_seconds - }, - sum_of_coupling, - bugfix_commits: bugfix_seconds.len() as u64, - twr: time_weighted_risk(&bugfix_seconds, first_seconds, head_seconds), - } -} - -/// Google Time-Weighted Risk (Lewis et al., ICSE 2013): -/// `Σᵢ 1 / (1 + e^(−12·tᵢ + 12))` where `tᵢ` is the bug-fixing -/// commit's time normalized to `[0, 1]` over the walked history -/// (0 = oldest walked commit, 1 = head). -/// -/// The result is quantized to 1e-9 before publication: `f64::exp` has -/// no cross-platform bit-exactness guarantee, and TWR is both -/// serialized raw and used as a ranking key. Each summand lies in -/// `[0, 1]` with sub-ULP libm variance, so absorbing everything below -/// a nanounit keeps identical repositories identical across platforms. -fn time_weighted_risk(bugfix_seconds: &[i64], first_seconds: i64, head_seconds: i64) -> f64 { - if bugfix_seconds.is_empty() { - return 0.0; - } - // Saturating: raw commit metadata can carry arbitrary i64 - // timestamps (git objects can be written directly), and a - // repository spanning extreme negative and positive values would - // overflow a plain subtraction — a debug-build panic mid-walk, a - // silently wrapped TWR in release. - let span = head_seconds.saturating_sub(first_seconds).max(0) as f64; - // Sort so the float summation order is independent of the walk - // order (cross-platform determinism contract). - let mut times: Vec = bugfix_seconds.to_vec(); - times.sort_unstable(); - let sum: f64 = times - .iter() - .map(|&s| { - let t = if span == 0.0 { - // Single-commit histories: the fix is "now". - 1.0 - } else { - ((s.saturating_sub(first_seconds).max(0) as f64) / span).clamp(0.0, 1.0) - }; - 1.0 / (1.0 + (-TWR_STEEPNESS * t + TWR_OMEGA).exp()) - }) - .sum(); - (sum * 1e9).round() / 1e9 -} - -/// A single file's change within one commit, with line-level churn. -struct CommitFileChange { - path: PathBuf, - /// The pre-rename path when this change is a rename. - source_path: Option, - added: u64, - removed: u64, - /// Whether this change removed the file (used to tell a dead - /// post-rename path reuse apart from parallel-branch lineage - /// edits — see the stranded-accumulator merge). - is_deletion: bool, - /// Whether this change *created* the file (a tree-diff addition). - /// A delete-then-recreate boundary requires the newer occupant to - /// have actually been created after the deletion; parallel-branch - /// edits are modifications and must not trigger a split. - is_addition: bool, - /// For merge-introduced renames: the parent commits whose lineage - /// the rename describes (parents whose trees contain the source). - /// `None` for ordinary changes — the walked commit itself scopes - /// the alias. - alias_scopes: Option>, - /// Whether the rename installs a destination identity boundary. - /// True everywhere except a merge rename onto a path some parent - /// already owns: that parent's older history at the destination - /// is legitimate lineage converging into the merged file, not a - /// dead prior occupant to fence off. - install_destination_boundary: bool, - /// See [`AliasEntry::addition_floor`] — set for merge renames - /// whose scopes span several parents. - alias_addition_floor: Option, - /// A same-path occupant fence a merge must install: `(scope, - /// floor)` for a parent whose version of this path the merge - /// discarded in favor of another parent's continuation. Older - /// commits on that parent's post-divergence line describe the - /// discarded occupant, not the survivor. - discarded_occupant_fence: Option<(gix::ObjectId, Option)>, -} - -/// A reusable revision graph for merge-base queries, per the gix -/// maintainer's guidance (GitoxideLabs/gitoxide#2914): reusing one -/// graph across queries amortizes commit lookups (and leverages the -/// commit-graph file when present) instead of re-walking from scratch -/// on every ancestry check. -type AncestryGraph<'repo, 'cache> = gix::revwalk::Graph< - 'repo, - 'cache, - gix::revwalk::graph::Commit, ->; - -/// Whether `commit` is a descendant of `ancestor` (equal ids count). -/// -/// Used to partition an accumulator stranded at a rename source: a -/// contribution from a descendant of the rename commit postdates the -/// rename on its own line (the path was re-created there), while a -/// concurrent contribution edited the file that moved away. Rename -/// events with stranded contributions are rare, and the shared graph -/// caches commit lookups across queries, so the cost stays negligible -/// next to the per-commit tree diffs. -fn is_descendant_of( - repo: &gix::Repository, - graph: &mut AncestryGraph<'_, '_>, - ancestor: gix::ObjectId, - commit: gix::ObjectId, -) -> Result { - if ancestor == commit { - return Ok(true); - } - match repo.merge_base_with_graph(ancestor, commit, graph) { - Ok(base) => Ok(base.detach() == ancestor), - // Disjoint histories (e.g. an orphan branch): not an ancestor. - Err(gix::repository::merge_base_with_graph::Error::NotFound { .. }) => Ok(false), - Err(e) => Err(GitError::Internal(e.to_string())), - } -} - -/// Whether `path` was deleted on `tip`'s *first-parent chain* between -/// `base` and `tip`: a present→absent flip along the candidate -/// parent's own line is an identity boundary, even when the path is -/// later re-created with byte-identical contents — endpoint blobs -/// alone cannot see the interruption. Deliberately not a full range -/// walk: a side branch merged into the candidate may have deleted the -/// path while the candidate's own copy survived uninterrupted (the -/// merge kept it), and that side deletion says nothing about the -/// candidate's lineage. The chain reads commit headers and per-commit -/// tree lookups only, and runs just for the rare multi-parent-source -/// merge rename. -/// The blob OID at `path` in `commit`'s tree (`None`: absent or not a -/// blob). -fn blob_oid_in_commit( - repo: &gix::Repository, - commit: gix::ObjectId, - path: &Path, -) -> Result, GitError> { - let internal = |e: &dyn std::error::Error| GitError::Internal(e.to_string()); - Ok(repo - .find_object(commit) - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))? - .tree() - .map_err(|e| internal(&e))? - .lookup_entry_by_path(path) - .map_err(|e| internal(&e))? - .filter(|entry| entry.mode().is_blob()) - .map(|entry| entry.oid().to_owned())) -} - -fn path_deleted_in_range( - repo: &gix::Repository, - tip: gix::ObjectId, - base: gix::ObjectId, - path: &Path, -) -> Result { - let internal = |e: &dyn std::error::Error| GitError::Internal(e.to_string()); - let blob_oid = |id: gix::ObjectId| -> Result, GitError> { - Ok(repo - .find_object(id) - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))? - .tree() - .map_err(|e| internal(&e))? - .lookup_entry_by_path(path) - .map_err(|e| internal(&e))? - .filter(|entry| entry.mode().is_blob()) - .map(|entry| entry.oid().to_owned())) - }; - - let mut current = tip; - let mut current_oid = blob_oid(current)?; - while current != base { - let commit = repo - .find_object(current) - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))?; - let parents: Vec = commit.parent_ids().map(|id| id.detach()).collect(); - let Some(&first_parent) = parents.first() else { - break; - }; - // At a merge, follow the parent that actually *supplied* the - // blob the lineage carries: exact blob-oid match first; when - // conflict resolution edited the merged blob (no parent - // matches exactly), the parent whose blob *continues* it at - // rename similarity — falling back to the first parent - // holding any blob would happily pick an unrelated - // delete-and-recreate occupant on that line. Last resorts: - // any blob-holding parent, then the first parent. - let mut next = first_parent; - if parents.len() > 1 - && let Some(oid) = current_oid - { - let mut exact: Option = None; - // The *strongest* threshold-passing continuation wins: a - // weaker passing parent may be an unrelated recreation - // while a later parent holds the closer lineage. - let mut best_continuing: Option<(f64, gix::ObjectId)> = None; - let mut any_blob: Option = None; - for &parent in &parents { - let Some(parent_oid) = blob_oid(parent)? else { - continue; - }; - if parent_oid == oid { - exact = Some(parent); - break; - } - if let Some(similarity) = blob_lineage_similarity(repo, &parent_oid, &oid)? - && similarity >= RENAME_SIMILARITY - && best_continuing.is_none_or(|(best, _)| similarity > best) - { - best_continuing = Some((similarity, parent)); - } - if any_blob.is_none() { - any_blob = Some(parent); - } - } - next = exact - .or(best_continuing.map(|(_, parent)| parent)) - .or(any_blob) - .unwrap_or(first_parent); - } - let next_oid = blob_oid(next)?; - // A presence flip in either direction along the followed line - // is an identity boundary: absent→present downward means the - // path was deleted here; present→absent downward means the - // tip's file was *created* inside the range — and since the - // qualification already verified the path exists at the base, - // a prior occupant must have been deleted below. - if current_oid.is_some() != next_oid.is_some() { - return Ok(true); - } - current = next; - current_oid = next_oid; - } - Ok(false) -} - -/// Tree changes a merge commit itself introduced: renames and -/// additions whose destination path exists in *no* parent tree — -/// conflict resolution that committed a file under a brand-new path. -/// The merge tree is compared against **every** parent: a rename -/// whose source lives only in a non-first parent is invisible to the -/// first-parent diff (the destination looks like a plain addition). -/// Rename pairings win over plain additions for the same destination, -/// and the first parent's pairing wins ties — deterministic parent -/// order. Everything else in a merge's diffs is either a parent's own -/// changes replayed (their commits are walked separately) or churn -/// that `--no-merges` semantics deliberately exclude; accordingly the -/// returned changes carry no churn (identity only, never accumulated). -fn merge_introduced_changes( - repo: &gix::Repository, - commit: &gix::Commit<'_>, - truncated: &mut Vec, -) -> Result, GitError> { - let internal = |e: &dyn std::error::Error| GitError::Internal(e.to_string()); - let to_tree = commit.tree().map_err(|e| internal(&e))?; - let mut parent_trees = Vec::new(); - let mut parent_ids: Vec = Vec::new(); - for parent_id in commit.parent_ids() { - parent_ids.push(parent_id.detach()); - let parent = parent_id - .object() - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))?; - parent_trees.push(parent.tree().map_err(|e| internal(&e))?); - } - let mut diffs: Vec> = Vec::with_capacity(parent_trees.len()); - let mut truncated_candidates: Vec<(usize, PathBuf)> = Vec::new(); - for (q_idx, base) in parent_trees.iter().enumerate() { - let tc = changes_between_trees(repo, Some(base), &to_tree)?; - truncated_candidates.extend(tc.truncated_lineages.into_iter().map(|path| (q_idx, path))); - diffs.push(tc.changes); - } - - // A destination is merge-introduced only when no parent has a - // *blob* there: a parent holding a symlink or gitlink at the path - // is a different identity entirely (conflict resolution replacing - // a symlink with a real file still creates that file), and a - // parent holding a blob performed (or already contained) the - // change itself — walking its commits handles identity. - let blob_in = |tree: &gix::Tree<'_>, path: &Path| -> Result { - Ok(tree - .lookup_entry_by_path(path) - .map_err(|e| internal(&e))? - .is_some_and(|entry| entry.mode().is_blob())) - }; - let in_any_parent = |path: &Path| -> Result { - for tree in &parent_trees { - if blob_in(tree, path)? { - return Ok(true); - } - } - Ok(false) - }; - - let blob_oid_at = - |tree: &gix::Tree<'_>, path: &Path| -> Result, GitError> { - Ok(tree - .lookup_entry_by_path(path) - .map_err(|e| internal(&e))? - .filter(|entry| entry.mode().is_blob()) - .map(|entry| entry.oid().to_owned())) - }; - - // A truncation marker from a *discarded* parent's diff must not - // poison the survivor: when another parent's blob at the path - // continues the merged blob (exact, or similar at the rename - // threshold), the surviving lineage flows through that parent and - // the raw-path rename this diff paired says nothing about it. - for (q_idx, path) in truncated_candidates { - let Some(merged_oid) = blob_oid_at(&to_tree, &path)? else { - truncated.push(path); - continue; - }; - let mut supplied_by_other = false; - for (idx, tree) in parent_trees.iter().enumerate() { - if idx == q_idx { - continue; - } - if let Some(parent_oid) = blob_oid_at(tree, &path)? - && (parent_oid == merged_oid || same_blob_lineage(repo, &parent_oid, &merged_oid)?) - { - supplied_by_other = true; - break; - } - } - if !supplied_by_other { - truncated.push(path); - } - } - - let mut introduced: Vec = Vec::new(); - let mut seen: std::collections::HashSet = std::collections::HashSet::new(); - // Renames first, across all parent diffs. Distinct sources may - // converge on one destination (two branches renamed the shared - // file differently and conflict resolution committed a third - // name): every pairing installs its own alias, deduplicated per - // (destination, source) pair, so no branch's intermediate-path - // lineage is stranded. - let mut seen_pairs: std::collections::HashSet<(PathBuf, PathBuf)> = - std::collections::HashSet::new(); - for (supplier_idx, diff) in diffs.iter().enumerate() { - for change in diff { - let TreeChange::Renamed { - path, source_path, .. - } = change - else { - continue; - }; - if seen_pairs.contains(&(path.clone(), source_path.clone())) { - continue; - } - // A destination some parent already owns is still a merge - // rename when the merged content does *not continue* that - // parent's version — conflict resolution carried the - // source lineage into the existing path, and both files' - // histories converge there. Continuation is judged like - // rename similarity (equal blob, or ≥50% similar): an - // edited-but-kept destination is retention, and treating - // every unequal blob as proof that the source lineage won - // would merge a discarded source into a surviving file. - // Such convergent renames skip the destination boundary: - // the owning parent's older history at the path is real - // lineage, not a dead occupant. - let dest_in_parent = in_any_parent(path)?; - if dest_in_parent { - let merged_oid = blob_oid_at(&to_tree, path)?; - let mut retained = merged_oid.is_none(); - if let Some(merged_oid) = merged_oid { - for tree in &parent_trees { - if let Some(parent_oid) = blob_oid_at(tree, path)? - && same_blob_lineage(repo, &parent_oid, &merged_oid)? - { - retained = true; - break; - } - } - } - if retained { - continue; - } - } - // Scope the alias to the parents whose lineage the rename - // actually describes. The supplying parent (whose diff - // paired the rename) always qualifies. When the merged - // tree *retains a blob at the source path*, every other - // parent is excluded outright: whatever survives there — - // a delete-and-recreate resolved in that branch's favor, - // even one edited during conflict resolution — is the - // occupant those parents' commits describe, not the moved - // lineage. Otherwise another parent holding a blob at the - // source qualifies only when the path predates the - // branches' divergence (their merge base has it): an - // occupant independently created on that line is an - // unrelated file, and admitting its commits would route - // them into the rename target and let its creation - // consume the alias before the real lineage is walked. - let supplier = parent_ids[supplier_idx]; - let mut scopes = vec![supplier]; - let source_retained = blob_in(&to_tree, source_path)?; - let mut addition_floor: Option = None; - for (idx, (parent_id, tree)) in parent_ids.iter().zip(&parent_trees).enumerate() { - if source_retained || idx == supplier_idx || !blob_in(tree, source_path)? { - continue; - } - let shares_lineage = match repo.merge_base(supplier, *parent_id) { - Ok(base) => { - let base_commit = base - .object() - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))?; - let base_tree = base_commit.tree().map_err(|e| internal(&e))?; - // The path merely *existing* at the base is - // not enough: a parent that deleted the base - // file and re-created an unrelated one at the - // same path crossed an identity boundary, and - // its commits describe the discarded - // re-creation, not the moved lineage. Require - // the parent's blob to plausibly continue the - // base's (equal, or similar at git's rename - // threshold) — and require no delete/recreate - // boundary inside the range, which endpoint - // blobs cannot see when the re-creation is - // byte-identical. - match ( - blob_oid_at(&base_tree, source_path)?, - blob_oid_at(tree, source_path)?, - ) { - (Some(base_oid), Some(parent_oid)) => { - let shares = same_blob_lineage(repo, &base_oid, &parent_oid)? - && !path_deleted_in_range( - repo, - *parent_id, - base_commit.id, - source_path, - )? - // The *supplier* must continue the - // base lineage too: a supplier - // whose own line deleted and - // recreated the source after the - // base renamed its *recreation* — - // the other parent's retained - // original is a different - // (discarded) occupant. Widening - // would route that original into - // the rename target while the - // addition floor rejects the - // supplier's actual recreation, - // stranding its edits; keep the - // alias supplier-only instead. - && !path_deleted_in_range( - repo, - supplier, - base_commit.id, - source_path, - )?; - if shares && addition_floor.is_none() { - // Additions through a multi-parent - // scope must predate the - // divergence: an addition on just - // one line is a delete-and- - // recreate inside its unchecked - // sub-branches, not the moved - // file's creation. - addition_floor = Some(base_commit.id); - } - shares - } - _ => false, - } - } - // Disjoint histories cannot share the file. - Err(gix::repository::merge_base::Error::NotFound { .. }) => false, - Err(e) => return Err(GitError::Internal(e.to_string())), - }; - if shares_lineage { - scopes.push(*parent_id); - } - } - seen_pairs.insert((path.clone(), source_path.clone())); - seen.insert(path.clone()); - introduced.push(CommitFileChange { - path: path.clone(), - source_path: Some(source_path.clone()), - added: 0, - removed: 0, - is_deletion: false, - is_addition: false, - alias_scopes: Some(scopes), - install_destination_boundary: !dest_in_parent, - alias_addition_floor: addition_floor, - discarded_occupant_fence: None, - }); - } - } - // Then plain additions: a merge-created file at a brand-new path - // establishes a fresh identity, fencing off any dead prior - // occupant of that path (see the boundary install in the walk). - for diff in &diffs { - for change in diff { - let TreeChange::Added { path, .. } = change else { - continue; - }; - if seen.contains(path) || in_any_parent(path)? { - continue; - } - seen.insert(path.clone()); - introduced.push(CommitFileChange { - path: path.clone(), - source_path: None, - added: 0, - removed: 0, - is_deletion: false, - is_addition: true, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: None, - }); - } - } - // Finally merge-performed deletions: a path present in a parent - // but absent from the merged tree was resolved away by the merge - // itself. Passing the deletion through lets the walk's - // delete-then-recreate boundary fence the dead occupant when a - // newer commit reuses the path — without it, the pre-merge - // occupant's history would leak into the unrelated new file. A - // deletion is suppressed only for parent lineages the rename - // alias actually covers: a merge can move one parent's `a.rs` - // *and* delete another parent's unrelated occupant of the same - // path, and the latter still needs its fence. Like every merge - // change, deletions carry no churn and are never accumulated. - let mut rename_source_scopes: HashMap<&PathBuf, Vec> = HashMap::new(); - for change in &introduced { - if let (Some(source), Some(scopes)) = - (change.source_path.as_ref(), change.alias_scopes.as_ref()) - { - rename_source_scopes - .entry(source) - .or_default() - .extend(scopes.iter().copied()); - } - } - let mut deletions: Vec = Vec::new(); - for (parent_idx, diff) in diffs.iter().enumerate() { - for change in diff { - let TreeChange::Deleted { path, .. } = change else { - continue; - }; - if seen.contains(path) || blob_in(&to_tree, path)? { - continue; - } - if rename_source_scopes - .get(path) - .is_some_and(|scopes| scopes.contains(&parent_ids[parent_idx])) - { - // This parent's lineage moved with the rename — its - // "deletion" is the move itself. - continue; - } - seen.insert(path.clone()); - deletions.push(CommitFileChange { - path: path.clone(), - source_path: None, - added: 0, - removed: 0, - is_deletion: true, - is_addition: false, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: None, - }); - } - } - introduced.extend(deletions); - // Discarded same-path occupants: the merged tree keeps a blob at - // a path, but some parent's blob there does *not* continue it — - // that parent's post-divergence line held a different occupant - // (e.g. a delete-and-recreate) which the merge resolved away. - // Without a fence, the discarded occupant's recreation would - // accumulate under the live path and its deletion could fence the - // survivor's own pre-branch history. The fence is scoped to the - // discarding parent and floored at its divergence from the - // supplying parent, so shared ancestors stay with the survivor. - // One fence per (path, discarding parent): an octopus merge can - // discard several parents' independent occupants of one path, and - // each needs its own scoped fence. - let mut fenced: std::collections::HashSet<(PathBuf, gix::ObjectId)> = - std::collections::HashSet::new(); - // Bounded: the similarity checks below load blobs, and a mass - // conflict resolution can put thousands of modified paths here. - let mut lineage_budget: u64 = MERGE_LINEAGE_BYTE_BUDGET; - for (q_idx, diff) in diffs.iter().enumerate() { - for change in diff { - let TreeChange::Modified { - path, - previous_oid, - oid, - } = change - else { - continue; - }; - if seen.contains(path) || fenced.contains(&(path.clone(), parent_ids[q_idx])) { - continue; - } - // Find the parent that supplied the merged blob (exact, - // then similarity) — the survivor's lineage. - let mut supplier: Option = None; - let mut best = 0.0_f64; - // Whether the budget (not content) prevented a conclusive - // answer somewhere for this path: guessing either way - // could fold unrelated lineages together or fence a real - // one, so such paths are marked unmeasurable instead. - let mut budget_limited = false; - for (idx, (parent_id, tree)) in parent_ids.iter().zip(&parent_trees).enumerate() { - if idx == q_idx { - continue; - } - let Some(parent_oid) = blob_oid_at(tree, path)? else { - continue; - }; - if parent_oid == *oid { - supplier = Some(*parent_id); - break; - } - let similarity = match lineage_check_cost(repo, &parent_oid, oid)? { - Some(cost) if cost <= lineage_budget => { - lineage_budget -= cost; - blob_lineage_similarity(repo, &parent_oid, oid)? - } - // Oversized: never loaded — no signal by design. - None => None, - // Over budget: the answer exists but was not - // affordable. - Some(_) => { - budget_limited = true; - None - } - }; - if let Some(similarity) = similarity - && similarity >= RENAME_SIMILARITY - && similarity > best - { - supplier = Some(*parent_id); - best = similarity; - } - } - let Some(supplier) = supplier else { - if budget_limited { - // A similarity supplier may exist behind the - // exhausted budget; without it no fence installs - // and the walk would fold both branches' unrelated - // histories into the survivor. Unmeasurable. - truncated.push(path.clone()); - } - // No parent continues the merged blob (conflict - // resolution rewrote it): ambiguous — leave identity - // handling to the ordinary walk. - continue; - }; - let floor = match repo.merge_base(supplier, parent_ids[q_idx]) { - Ok(base) => Some(base.detach()), - Err(gix::repository::merge_base::Error::NotFound { .. }) => None, - Err(e) => return Err(GitError::Internal(e.to_string())), - }; - // Endpoint similarity alone cannot prove continuation: - // a recreation may resemble the survivor (or be judged - // against an edited merge blob). The parent's own line is - // consulted for a delete/recreate boundary since the - // divergence — only an uninterrupted, similar version is - // a genuine continuation needing no fence. - let continuation = match lineage_check_cost(repo, previous_oid, oid)? { - Some(cost) if cost <= lineage_budget => { - lineage_budget -= cost; - same_blob_lineage(repo, previous_oid, oid)? - } - // Oversized blobs conservatively don't continue - // (never loaded — matches `same_blob_lineage`). - None => false, - // Budget exhausted: no signal either way. Fencing on - // a guess could cut real lineages; skipping the fence - // would fold a discarded occupant into the survivor. - // Unmeasurable. - Some(_) => { - truncated.push(path.clone()); - continue; - } - }; - if continuation - && match floor { - Some(base) => !path_deleted_in_range(repo, parent_ids[q_idx], base, path)?, - // No merge base (`--allow-unrelated-histories`): - // the parents cannot share a lineage, so endpoint - // similarity between two independently created - // files proves nothing — fence the discarded - // occupant (with no floor: there is no shared - // pre-branch history to protect). - None => false, - } - { - continue; - } - fenced.insert((path.clone(), parent_ids[q_idx])); - introduced.push(CommitFileChange { - path: path.clone(), - source_path: None, - added: 0, - removed: 0, - is_deletion: false, - is_addition: false, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: Some((parent_ids[q_idx], floor)), - }); - } - } - // Byte-identical recreated occupants: a parent whose line deleted - // and recreated the path with content byte-equal to the blob the - // merge keeps leaves *no entry at all* in its parent-to-merge diff - // (exact OID equality erases the path), so the Modified-based pass - // above never sees a candidate — yet the recreation still ends at - // its deletion boundary. Without a fence it would accumulate under - // the survivor and its deletion would tombstone the shared - // pre-branch creation. Candidates are recovered by diffing each - // parent against its divergence base — the recreation is visible - // *there* whenever its content differs from the base (a recreation - // byte-equal to the base as well is a pure revert and reads as - // lineage continuation). Because both blobs are byte-equal, line - // continuity — not content — is the only survivor signal: the - // fence installs only when another parent carries the same blob - // through an uninterrupted line. If no parent does, the recreation - // is itself the survivor and the ordinary walk fence handles its - // older history. - for (q_idx, q_id) in parent_ids.iter().enumerate() { - if parent_ids.len() < 2 { - break; - } - // Divergence base for candidate detection; per-path floors - // are still derived from the chosen supplier below. For an - // octopus merge this approximates the divergence with the - // first other parent — a deeper true base only widens the - // candidate diff, and the boundary scan filters the excess. - let other = parent_ids[usize::from(q_idx == 0)]; - let base = match repo.merge_base(other, *q_id) { - Ok(base) => base.detach(), - Err(gix::repository::merge_base::Error::NotFound { .. }) => continue, - Err(e) => return Err(GitError::Internal(e.to_string())), - }; - let base_tree = repo - .find_object(base) - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))? - .tree() - .map_err(|e| internal(&e))?; - for (path, q_oid) in - blob_modifications_between_trees(repo, &base_tree, &parent_trees[q_idx])? - { - if seen.contains(&path) || fenced.contains(&(path.clone(), *q_id)) { - continue; - } - // Only the invisible case: the parent's endpoint blob is - // byte-equal to the merged blob. Anything else produced a - // parent-to-merge diff entry and was handled above. - if blob_oid_at(&to_tree, &path)? != Some(q_oid) { - continue; - } - // A supplier must carry the identical blob through an - // uninterrupted post-divergence line. - let mut supplier: Option = None; - for (idx, (parent_id, tree)) in parent_ids.iter().zip(&parent_trees).enumerate() { - if idx == q_idx || blob_oid_at(tree, &path)? != Some(q_oid) { - continue; - } - let s_base = match repo.merge_base(*parent_id, *q_id) { - Ok(base) => base.detach(), - Err(gix::repository::merge_base::Error::NotFound { .. }) => continue, - Err(e) => return Err(GitError::Internal(e.to_string())), - }; - if path_deleted_in_range(repo, *parent_id, s_base, &path)? { - continue; - } - supplier = Some(*parent_id); - break; - } - let Some(supplier) = supplier else { - continue; - }; - let floor = match repo.merge_base(supplier, *q_id) { - Ok(base) => base.detach(), - Err(gix::repository::merge_base::Error::NotFound { .. }) => continue, - Err(e) => return Err(GitError::Internal(e.to_string())), - }; - // The fence needs proof, not endpoint similarity: only a - // deletion on this parent's own post-divergence line makes - // the byte-equal blob a *recreation* rather than the - // surviving file itself. - if !path_deleted_in_range(repo, *q_id, floor, &path)? { - continue; - } - fenced.insert((path.clone(), *q_id)); - introduced.push(CommitFileChange { - path: path.clone(), - source_path: None, - added: 0, - removed: 0, - is_deletion: false, - is_addition: false, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: Some((*q_id, Some(floor))), - }); - } - } - // Unrelated parents (`--allow-unrelated-histories`) can hold - // *byte-identical* same-path roots: exact OID equality erases the - // path from every parent-to-merge diff, and the base-relative - // recovery pass above has no base to diff against — yet without a - // fence both independent root additions accumulate under the - // surviving path, doubling churn/frequency and merging unrelated - // authorship. The shape is rare, so the merged tree is enumerated - // only when some parent pair actually lacks a merge base: the - // first parent holding the merged blob supplies the survivor, and - // every *unrelated* other parent holding the identical blob gets - // an unfloored fence (no shared pre-branch history exists). - let related = |a: gix::ObjectId, b: gix::ObjectId| -> Result { - match repo.merge_base(a, b) { - Ok(_) => Ok(true), - Err(gix::repository::merge_base::Error::NotFound { .. }) => Ok(false), - Err(e) => Err(GitError::Internal(e.to_string())), - } - }; - let mut any_unrelated = false; - 'pairs: for (i, a) in parent_ids.iter().enumerate() { - for b in &parent_ids[i + 1..] { - if !related(*a, *b)? { - any_unrelated = true; - break 'pairs; - } - } - } - if any_unrelated { - let mut recorder = gix::traverse::tree::Recorder::default(); - to_tree - .traverse() - .breadthfirst(&mut recorder) - .map_err(|e| internal(&e))?; - for entry in recorder.records { - if !entry.mode.is_blob() { - continue; - } - let Some(path) = crate::tree_changes::path_from_git(&entry.filepath) else { - continue; - }; - if seen.contains(&path) { - continue; - } - let mut supplier: Option = None; - for (parent_id, tree) in parent_ids.iter().zip(&parent_trees) { - if blob_oid_at(tree, &path)? == Some(entry.oid) { - supplier = Some(*parent_id); - break; - } - } - let Some(supplier) = supplier else { - continue; - }; - for (parent_id, tree) in parent_ids.iter().zip(&parent_trees) { - if *parent_id == supplier - || fenced.contains(&(path.clone(), *parent_id)) - || blob_oid_at(tree, &path)? != Some(entry.oid) - || related(supplier, *parent_id)? - { - continue; - } - fenced.insert((path.clone(), *parent_id)); - introduced.push(CommitFileChange { - path: path.clone(), - source_path: None, - added: 0, - removed: 0, - is_deletion: false, - is_addition: false, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: Some((*parent_id, None)), - }); - } - } - } - Ok(introduced) -} - -/// Cumulative blob-byte budget for one merge's discarded-occupant -/// lineage checks: a mass conflict resolution can push thousands of -/// `Modified` paths through similarity checks that load up to two -/// 8-MiB blobs each, and without an aggregate cap a single merge -/// could read gigabytes during the walk. Entries past the budget -/// leave identity handling to the ordinary walk — no fence is -/// installed on a guess. -const MERGE_LINEAGE_BYTE_BUDGET: u64 = 64 * 1024 * 1024; - -/// The blob-byte cost of one lineage-similarity check, or `None` -/// when a side exceeds the per-blob cap (such checks never load -/// anything). Equal OIDs cost nothing. -fn lineage_check_cost( - repo: &gix::Repository, - a: &gix::ObjectId, - b: &gix::ObjectId, -) -> Result, GitError> { - if a == b { - return Ok(Some(0)); - } - let (size_a, size_b) = (blob_size(repo, a)?, blob_size(repo, b)?); - if size_a > crate::tree_changes::FUZZY_MAX_BLOB_BYTES - || size_b > crate::tree_changes::FUZZY_MAX_BLOB_BYTES - { - return Ok(None); - } - Ok(Some(size_a + size_b)) -} - -/// The paths whose *identity* a merge commit changes — conflict- -/// resolution creations, merge-only renames and deletions (with their -/// sources), and discarded-occupant fences. `range_touched_files` -/// consults this: such changes alter `history.*` metrics even when -/// the endpoint trees are byte-identical and no non-merge commit -/// touched the path. -pub(crate) fn merge_identity_paths( - repo: &gix::Repository, - commit: &gix::Commit<'_>, -) -> Result, GitError> { - let mut truncated: Vec = Vec::new(); - let mut paths: Vec = merge_introduced_changes(repo, commit, &mut truncated)? - .into_iter() - .flat_map(|change| std::iter::once(change.path).chain(change.source_path)) - .collect(); - // A lineage truncated at this merge changed identity too. - paths.extend(truncated); - Ok(paths) -} - -/// The identity a historical change accumulates under: a real -/// head-relative path, or a synthetic tombstone standing in for a dead -/// prior occupant of a rename destination (or of a delete-then- -/// recreate boundary). A dedicated variant rather than a sentinel -/// `PathBuf`: Git permits arbitrary bytes in filenames on some -/// platforms, so no in-namespace sentinel can be collision-free. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -enum FileIdentity { - Path(PathBuf), - Tombstone(usize), -} - -/// One rename-identity redirection. `scopes` are the commits whose -/// *ancestors* the entry applies to: an alias only describes the -/// lineage it redirected, so *concurrent* changes (a parallel branch -/// re-creating the path) must not resolve through it. For an ordinary -/// rename the scope is the renaming commit itself; for a -/// merge-introduced rename it is the parents whose trees contain the -/// source — scoping to the merge commit would wrongly capture every -/// parent's line, including one where an unrelated file lived and died -/// at the same path. `consumed` retires an entry from resolution — -/// either because the walk accumulated the *creation* of the aliased -/// path through it (the redirected occupant's birth has been found, so -/// anything older at that path belongs to a previous occupant), or -/// because an older rename reclaimed the fence after explaining where -/// the fenced occupant went. An older rename may install alongside a -/// consumed entry, and an older deletion fences history off behind a -/// fresh tombstone (matching the delete-then-recreate boundary). -/// Entries are never removed: phase 4 marks consumption by index, so -/// indices must stay stable. -#[derive(Clone, Debug)] -struct AliasEntry { - target: FileIdentity, - scopes: Vec, - /// For merge-installed aliases whose scopes span several parents: - /// an *addition* resolves through the entry only when it is an - /// ancestor of this floor (the parents' merge base). The moved - /// file's true creation predates the divergence; an addition on - /// just one scoped line is a delete-and-recreate inside that - /// line's sub-branches — a different identity that must neither - /// route into the rename target nor consume the alias. `None` - /// (ordinary renames, single-scope merges) leaves additions - /// gated by the scopes alone. - addition_floor: Option, - /// A floor for *every* change: the entry applies only to commits - /// that are **not** ancestors of it. Used by discarded-occupant - /// fences, whose events all postdate the divergence — the shared - /// pre-branch history belongs to the surviving file, not behind - /// the fence. - floor: Option, - /// A fence for a same-path occupant a merge discarded (see the - /// merge handling in the walk). Excluded from the - /// delete-then-recreate "consumed entry" proof: the path stayed - /// continuously occupied by the survivor, so a consumed fence - /// says nothing about *its* older history. - from_discarded_occupant: bool, - consumed: bool, -} - -impl AliasEntry { - fn new(target: FileIdentity, scopes: Vec) -> Self { - Self { - target, - scopes, - addition_floor: None, - floor: None, - from_discarded_occupant: false, - consumed: false, - } - } - - /// Whether the entry applies to a change made by `commit`: the - /// change must be an ancestor of (or equal to) one of the scopes, - /// must postdate the all-change floor when one is set, and an - /// addition must additionally pass the addition floor. - fn applies_to( - &self, - repo: &gix::Repository, - graph: &mut AncestryGraph<'_, '_>, - commit: gix::ObjectId, - is_addition: bool, - ) -> Result { - if let Some(floor) = self.floor - && is_descendant_of(repo, graph, commit, floor)? - { - // Pre-divergence commits are the surviving lineage's. - return Ok(false); - } - if is_addition - && let Some(floor) = self.addition_floor - && !is_descendant_of(repo, graph, commit, floor)? - { - return Ok(false); - } - for scope in &self.scopes { - if is_descendant_of(repo, graph, commit, *scope)? { - return Ok(true); - } - } - Ok(false) - } -} - -/// Resolve a historical path to its identity for a change made by -/// `commit`, returning the applied entry's index when an alias was -/// used (so the caller can mark it consumed). -/// -/// An entry applies only when `commit` is an *ancestor* of the commit -/// that installed it: aliases redirect the pre-rename lineage on the -/// installer's own line, and a concurrent change (a parallel branch -/// re-creating or deleting the path) knows nothing of that rename. -/// Consumed entries never apply — the occupant they redirected has -/// been fully walked, so anything older belongs to someone else. -/// Among applicable entries, real-path targets win over tombstones -/// (a rename explains where the file went; a deletion boundary is -/// only a fence), first-installed first — deterministic under the -/// deterministic walk order. -fn resolve_alias( - repo: &gix::Repository, - graph: &mut AncestryGraph<'_, '_>, - aliases: &HashMap>, - path: &Path, - commit: gix::ObjectId, - is_addition: bool, -) -> Result<(FileIdentity, Option, Option), GitError> { - let Some(entries) = aliases.get(path) else { - return Ok((FileIdentity::Path(path.to_path_buf()), None, None)); - }; - let mut tombstone: Option<(FileIdentity, usize)> = None; - // The first entry whose scopes admit this addition but whose - // addition floor rejects it: the caller uses it to recognize a - // recreated occupant's birth and pull the occupant's already- - // routed edits back out of the alias target (see phase 4). - let mut floor_gated: Option = None; - for (idx, entry) in entries.iter().enumerate() { - if entry.consumed { - continue; - } - if is_addition - && entry.addition_floor.is_some() - && entry.applies_to(repo, graph, commit, false)? - && !entry.applies_to(repo, graph, commit, true)? - { - if floor_gated.is_none() { - floor_gated = Some(idx); - } - continue; - } - if !entry.applies_to(repo, graph, commit, is_addition)? { - continue; - } - match &entry.target { - FileIdentity::Path(_) => return Ok((entry.target.clone(), Some(idx), floor_gated)), - FileIdentity::Tombstone(_) => { - if tombstone.is_none() { - tombstone = Some((entry.target.clone(), idx)); - } - } - } - } - Ok(match tombstone { - Some((target, idx)) => (target, Some(idx), floor_gated), - None => (FileIdentity::Path(path.to_path_buf()), None, floor_gated), - }) -} - -/// Diff `commit` against its first parent (or the empty tree for root -/// commits) with deterministic `gix` rewrite tracking, and compute -/// line-level churn per changed blob. Also returns the count of changed -/// non-blob leaf paths (symlinks, gitlinks) — they carry no analyzable -/// text but still belong to the commit's changeset for coupling. -fn diff_against_first_parent( - repo: &gix::Repository, - commit: &gix::Commit<'_>, -) -> Result<(Vec, usize, Vec), GitError> { - let internal = |e: &dyn std::error::Error| GitError::Internal(e.to_string()); - - let to_tree = commit.tree().map_err(|e| internal(&e))?; - let parent_tree = match commit.parent_ids().next() { - Some(parent_id) => { - let parent = parent_id - .object() - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))?; - Some(parent.tree().map_err(|e| internal(&e))?) - } - // Root commit: diff against the empty tree. - None => None, - }; - - let records = changes_between_trees(repo, parent_tree.as_ref(), &to_tree)?; - let non_blob_changes = records.non_blob_changes; - let truncated_lineages = records.truncated_lineages; - let records = records.changes; - let mut changes = Vec::with_capacity(records.len()); - for change in records { - let file_change = match change { - TreeChange::Added { path, oid } => CommitFileChange { - path, - source_path: None, - added: blob_line_count(repo, &oid)?, - removed: 0, - is_deletion: false, - is_addition: true, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: None, - }, - TreeChange::Deleted { path, oid } => CommitFileChange { - path, - source_path: None, - added: 0, - removed: blob_line_count(repo, &oid)?, - is_deletion: true, - is_addition: false, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: None, - }, - TreeChange::Modified { - path, - previous_oid, - oid, - } => { - // Mode-only changes keep the same blob and churn no - // lines — skip the two blob reads. - let (added, removed) = if previous_oid == oid { - (0, 0) - } else { - blob_line_diff(repo, &previous_oid, &oid)? - }; - CommitFileChange { - path, - source_path: None, - added, - removed, - is_deletion: false, - is_addition: false, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: None, - } - } - TreeChange::Renamed { - path, - source_path, - previous_oid, - oid, - } => { - // A perfect rename keeps the blob — zero churn. - let (added, removed) = if previous_oid == oid { - (0, 0) - } else { - blob_line_diff(repo, &previous_oid, &oid)? - }; - CommitFileChange { - path, - source_path: Some(source_path), - added, - removed, - is_deletion: false, - is_addition: false, - alias_scopes: None, - install_destination_boundary: true, - alias_addition_floor: None, - discarded_occupant_fence: None, - } - } - }; - changes.push(file_change); - } - - Ok((changes, non_blob_changes, truncated_lineages)) -} - -/// Number of lines in a blob (a trailing fragment without `\n` counts -/// as a line). Oversized and binary blobs count zero lines -/// (numstat-style binary handling); oversized ones are never loaded. -fn blob_line_count(repo: &gix::Repository, oid: &gix::ObjectId) -> Result { - if blob_size(repo, oid)? > MAX_CHURN_BLOB_BYTES { - return Ok(0); - } - let data = read_blob_data(repo, oid)?; - if is_binary(&data) { - return Ok(0); - } - Ok(count_lines(&data)) -} - -/// Line-level (added, removed) counts between two blob versions. Pairs -/// with an oversized or binary side churn zero lines — mirroring -/// `git log --numstat`, which reports `-` for binary files, so e.g. a -/// NUL-containing generated revision doesn't count its bytes as -/// "source lines" churned. Oversized blobs are never loaded. -fn blob_line_diff( - repo: &gix::Repository, - old: &gix::ObjectId, - new: &gix::ObjectId, -) -> Result<(u64, u64), GitError> { - if blob_size(repo, old)? > MAX_CHURN_BLOB_BYTES || blob_size(repo, new)? > MAX_CHURN_BLOB_BYTES - { - return Ok((0, 0)); - } - let old_data = read_blob_data(repo, old)?; - let new_data = read_blob_data(repo, new)?; - if is_binary(&old_data) || is_binary(&new_data) { - return Ok((0, 0)); - } - Ok(line_diff_counts(&old_data, &new_data)) -} - -/// Committer timestamp in seconds since the Unix epoch. -fn commit_seconds(commit: &gix::Commit<'_>) -> Result { - Ok(commit - .time() - .map_err(|e| GitError::Internal(e.to_string()))? - .seconds) -} - -/// Author identity for ownership metrics: the author's raw email -/// bytes (ASCII-lowercased), falling back to the name for commits -/// without one. Byte-preserving deliberately — a lossy UTF-8 -/// conversion would replace every invalid sequence with U+FFFD and -/// collapse distinct identities that differ only in such bytes, -/// undercounting `history.authors` and skewing ownership shares. -fn author_identity(commit: &gix::Commit<'_>) -> Result, GitError> { - let author = commit - .author() - .map_err(|e| GitError::Internal(e.to_string()))?; - let email: &[u8] = author.email.as_ref(); - let bytes: &[u8] = if email.iter().all(u8::is_ascii_whitespace) { - author.name.as_ref() - } else { - email - }; - Ok(bytes.to_ascii_lowercase()) -} - -/// Bug-fix commit heuristic (Lewis et al. use a message classifier; the -/// transparent variant here matches whole words from a fixed list). -/// -/// Word-boundary matching avoids classics like "prefix" or "debug" -/// counting as fixes. Issue references (`#123`) are deliberately *not* -/// treated as bug-fix markers: on GitHub-style squash merges every PR -/// commit carries one. -fn is_bugfix_message(message: &[u8]) -> bool { - const BUGFIX_WORDS: &[&str] = &[ - "fix", "fixes", "fixed", "fixing", "fixup", "hotfix", "bugfix", "bug", "bugs", - ]; - let lowered = String::from_utf8_lossy(message).to_lowercase(); - lowered - .split(|c: char| !c.is_ascii_alphanumeric()) - .any(|word| BUGFIX_WORDS.contains(&word)) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn bugfix_heuristic_matches_whole_words_only() { - assert!(is_bugfix_message(b"fix: broken parser")); - assert!(is_bugfix_message(b"Fixed the flaky test")); - assert!(is_bugfix_message(b"hotfix for release")); - assert!(is_bugfix_message(b"chore: fixup review comments")); - assert!(is_bugfix_message(b"resolve BUG in walker")); - // Substrings must not match. - assert!(!is_bugfix_message(b"add prefix support")); - assert!(!is_bugfix_message(b"improve debugging output")); - assert!(!is_bugfix_message(b"feat: add suffix trees")); - // Issue references alone are not bug-fix markers. - assert!(!is_bugfix_message(b"feat: add pagination (#123)")); - } - - #[test] - fn twr_of_no_bugfixes_is_zero() { - assert_eq!(time_weighted_risk(&[], 0, 100), 0.0); - } - - #[test] - fn twr_weights_recent_fixes_higher() { - // One fix at the very start vs one at head: the recent fix - // scores ~0.5, the old one ~e^-12. - let old = time_weighted_risk(&[0], 0, 1_000_000); - let recent = time_weighted_risk(&[1_000_000], 0, 1_000_000); - assert!(old < 1e-4, "old fix should decay to ~0, got {old}"); - assert!( - (recent - 0.5).abs() < 1e-9, - "fix at head should score 0.5, got {recent}" - ); - assert!(recent > old); - } - - #[test] - fn twr_zero_span_treats_fix_as_now() { - let v = time_weighted_risk(&[42], 42, 42); - assert!((v - 0.5).abs() < 1e-9); - } - - #[test] - fn twr_is_order_independent() { - let a = time_weighted_risk(&[10, 500_000, 999_999], 0, 1_000_000); - let b = time_weighted_risk(&[999_999, 10, 500_000], 0, 1_000_000); - assert_eq!(a, b); - } - - /// A minimal contribution for finalize-focused tests. - fn contribution(author: &str, added: u64) -> Contribution { - Contribution { - commit: gix::ObjectId::null(gix::hash::Kind::Sha1), - seconds: 0, - author: author.as_bytes().into(), - added, - removed: 0, - coupled_others: 0, - coupling_eligible: true, - is_bugfix: false, - is_addition: false, - } - } - - #[test] - fn finalize_ownership_and_minor_contributors() { - let mut acc = FileAccumulator::default(); - // 100 added lines total: alice 90, bob 7, carol 3. - acc.push(contribution("alice@x", 90)); - acc.push(contribution("bob@x", 7)); - acc.push(contribution("carol@x", 3)); - let fh = finalize_file(acc, 0, 0); - assert_eq!(fh.authors, 3); - // carol (3%) is minor; bob (7%) is not. - assert_eq!(fh.minor_contributors, 1); - assert!((fh.ownership - 0.9).abs() < 1e-9); - } - - #[test] - fn deletion_only_authors_count_as_authors_but_not_minor_contributors() { - // dave touched the file (pure deletion) — he is an author, but - // a zero-added entry must not be classified as a sub-5% minor - // contributor: he wrote nothing, minor or otherwise. - let mut acc = FileAccumulator::default(); - acc.push(contribution("alice@x", 100)); - acc.push(contribution("dave@x", 0)); - let fh = finalize_file(acc, 0, 0); - assert_eq!(fh.authors, 2); - assert_eq!(fh.minor_contributors, 0); - assert!((fh.ownership - 1.0).abs() < 1e-9); - } - - #[test] - fn finalize_zero_churn_has_defined_ownership() { - let acc = FileAccumulator::default(); - let fh = finalize_file(acc, 0, 0); - assert_eq!(fh.minor_contributors, 0); - assert_eq!(fh.ownership, 0.0); - assert_eq!(fh.churn_abs(), 0); - } - - #[test] - fn age_months_is_head_relative_and_clamped() { - let fh = FileHistory { - commit_frequency: 1, - churn_added: 1, - churn_removed: 0, - authors: 1, - minor_contributors: 0, - ownership: 1.0, - last_change_seconds: 0, - sum_of_coupling: 0, - bugfix_commits: 0, - twr: 0.0, - }; - // One average month after the last change. - assert!((fh.age_months(2_629_746) - 1.0).abs() < 1e-9); - // Clock skew (last change "after" head) clamps to zero. - assert_eq!(fh.age_months(-100), 0.0); - } -} diff --git a/crates/mehen-git/src/lib.rs b/crates/mehen-git/src/lib.rs deleted file mode 100644 index efef4417..00000000 --- a/crates/mehen-git/src/lib.rs +++ /dev/null @@ -1,393 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-git` — git/repository operations and changed-file detection. -//! -//! Per rewrite plan §8.1, this is the home of the pre-1.0 `src/git.rs` -//! helpers. Phase-6+ may introduce a `Utf8PathBuf`-based API per plan -//! §4.8; for now the API surface matches the pre-1.0 shape (`PathBuf`) -//! so the still-in-place `src/diff.rs` keeps compiling unchanged. - -#![deny(unsafe_code)] - -mod history; -mod tree_changes; - -pub use history::{FileHistory, RepositoryHistory, collect_history}; - -use std::fmt; -use std::path::{Path, PathBuf}; - -/// Collapses any trailing run of `\n` / `\r` into a single `\n`. -/// -/// When a blob has *no* trailing newline (or is empty), the buffer is -/// left unchanged — appending a synthetic `\n` would mutate repository -/// content and create spurious metric deltas between revisions. -/// -/// Inlined from the pre-1.0 `src/tools.rs` so this crate has no -/// dependency on the legacy `mehen` library. -fn remove_blank_lines(data: &mut Vec) { - let count_trailing = data - .iter() - .rev() - .take_while(|&c| *c == b'\n' || *c == b'\r') - .count(); - if count_trailing == 0 { - return; - } - data.truncate(data.len() - count_trailing); - data.push(b'\n'); -} - -#[derive(Debug)] -pub enum GitError { - RepoNotFound, - ShallowClone { - hint: String, - }, - RefNotFound(String), - #[allow(dead_code)] - BlobNotFound { - rev: String, - path: PathBuf, - }, - Internal(String), -} - -impl fmt::Display for GitError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::RepoNotFound => write!(f, "Not a git repository."), - Self::ShallowClone { hint } => write!(f, "Shallow clone detected. {hint}"), - Self::RefNotFound(r) => write!(f, "Could not resolve ref '{r}'."), - Self::BlobNotFound { rev, path } => { - write!(f, "Could not find '{}' at rev '{rev}'.", path.display()) - } - Self::Internal(msg) => write!(f, "Git error: {msg}"), - } - } -} - -impl std::error::Error for GitError {} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum ChangeStatus { - Added, - Modified, - Deleted, -} - -#[derive(Debug, Clone)] -pub struct ChangedFile { - pub path: PathBuf, - pub status: ChangeStatus, - /// The pre-rename path when this change is a rename detected - /// between the two revisions (`status` is then `Modified`). - /// Callers should read the baseline side from this path. - pub source_path: Option, -} - -/// Discover a git repository from the current working directory. -/// Fails fast on shallow clones. -pub fn open_repo() -> Result { - open_repo_at(Path::new(".")) -} - -/// Discover the git repository containing `path` (walking up from it, -/// like `gix::discover`). Fails fast on shallow clones — history-based -/// features need the full commit graph. -/// -/// Only genuine "there is no repository here" outcomes map to -/// [`GitError::RepoNotFound`]; discovery/open *failures* (inaccessible -/// directories, malformed metadata, trust errors) surface as -/// [`GitError::Internal`] so callers can tell "not a repo" apart from -/// "a repo we couldn't read". -pub fn open_repo_at(path: &Path) -> Result { - let repo = gix::discover(path).map_err(|e| match &e { - gix::discover::Error::Discover( - gix::discover::upwards::Error::NoGitRepository { .. } - | gix::discover::upwards::Error::NoGitRepositoryWithinCeiling { .. } - | gix::discover::upwards::Error::NoGitRepositoryWithinFs { .. }, - ) => GitError::RepoNotFound, - // A repository *was* found but failed the trust check: that is - // "a repo we couldn't read", not "no repo here" — mapping it to - // `RepoNotFound` would make history consumers silently rank - // the repo's files with missing `history.*` values. - _ => GitError::Internal(e.to_string()), - })?; - - if repo.is_shallow() { - return Err(GitError::ShallowClone { - hint: "Use 'actions/checkout' with 'fetch-depth: 0' for full history.".to_string(), - }); - } - - Ok(repo) -} - -/// List files changed between two revisions via tree-to-tree diff with -/// deterministic `gix` rewrite tracking (`-M50%` semantics over raw -/// object bytes, with pinned options and no repository/user diff -/// configuration or attributes). A renamed file is reported once as -/// `Modified` under its new path with [`ChangedFile::source_path`] set, -/// instead of a deletion + addition pair with full-value metric deltas. -/// -/// Only blob entries are reported: directories, symlinks, and gitlinks -/// (submodules) carry no analyzable text. An entry changing *type* -/// across the revisions is reported from the blob side — a file -/// replaced by a submodule is that file's deletion, and vice versa — -/// so downstream blob reads never touch a gitlink OID. -pub fn changed_files( - repo: &gix::Repository, - from: &str, - to: &str, -) -> Result, GitError> { - let from_tree = resolve_tree(repo, from)?; - let to_tree = resolve_tree(repo, to)?; - - let changes = tree_changes::changes_between_trees(repo, Some(&from_tree), &to_tree)?.changes; - let files = changes - .into_iter() - .map(|change| match change { - tree_changes::TreeChange::Added { path, .. } => ChangedFile { - path, - status: ChangeStatus::Added, - source_path: None, - }, - tree_changes::TreeChange::Deleted { path, .. } => ChangedFile { - path, - status: ChangeStatus::Deleted, - source_path: None, - }, - tree_changes::TreeChange::Modified { path, .. } => ChangedFile { - path, - status: ChangeStatus::Modified, - source_path: None, - }, - tree_changes::TreeChange::Renamed { - path, source_path, .. - } => ChangedFile { - path, - status: ChangeStatus::Modified, - source_path: Some(source_path), - }, - }) - .collect(); - - Ok(files) -} - -/// Paths *touched* by non-merge commits in `from..to` that still exist -/// in both endpoint trees, even when the endpoint-to-endpoint diff is -/// empty for them (modified in one commit, reverted in a later one). -/// -/// The endpoint tree diff is the right source for *static* metric -/// deltas, but `history.*` metrics change with every touch: a file -/// modified and restored within the range gained commit frequency, -/// churn, and possibly bug-fix risk between the two revisions, and a -/// diff limited to endpoint changes would silently omit it. Paths -/// absent from either endpoint are excluded — a net-new-and-removed -/// file has no row to hang a delta on. -pub fn range_touched_files( - repo: &gix::Repository, - from: &str, - to: &str, -) -> Result, GitError> { - // Peel to commits: an annotated tag's own object id would fail - // the topological walker, which decodes its tips as commits. - let from_id = repo - .rev_parse_single(from) - .map_err(|_| GitError::RefNotFound(from.to_string()))? - .object() - .map_err(|e| GitError::Internal(e.to_string()))? - .peel_to_commit() - .map_err(|e| GitError::Internal(e.to_string()))? - .id; - let to_id = repo - .rev_parse_single(to) - .map_err(|_| GitError::RefNotFound(to.to_string()))? - .object() - .map_err(|e| GitError::Internal(e.to_string()))? - .peel_to_commit() - .map_err(|e| GitError::Internal(e.to_string()))? - .id; - let from_tree = resolve_tree(repo, from)?; - let to_tree = resolve_tree(repo, to)?; - let internal = |e: &dyn std::error::Error| GitError::Internal(e.to_string()); - - let mut touched: std::collections::BTreeSet = std::collections::BTreeSet::new(); - // Both directions: for a non-fast-forward range (sibling branches, - // or a reversed range) a file may have been touched only on the - // `from` side — its baseline history then differs from the head's - // even though the endpoint trees agree, and the resulting - // `history.*` decrease must still be reported. - for (tip, hidden) in [(to_id, from_id), (from_id, to_id)] { - let walk = gix::traverse::commit::topo::Builder::from_iters( - repo.objects.clone(), - [tip], - Some([hidden]), - ) - .build() - .map_err(|e| internal(&e))?; - - for info in walk { - let info = info.map_err(|e| internal(&e))?; - let commit = repo - .find_object(info.id) - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))?; - // Merge commits replay their parents' *content* changes - // (the parents' own commits are walked — mirroring the - // history walk's `--no-merges` accounting), but conflict - // resolution can change identity on its own: a merge-only - // deletion, recreation, or rename alters `history.*` - // metrics even when the endpoint trees are byte-identical - // and no non-merge commit touched the path. - if info.parent_ids.len() > 1 { - for path in history::merge_identity_paths(repo, &commit)? { - touched.insert(path); - } - continue; - } - let parent_tree = match commit.parent_ids().next() { - Some(parent_id) => Some( - parent_id - .object() - .map_err(|e| internal(&e))? - .peel_to_commit() - .map_err(|e| internal(&e))? - .tree() - .map_err(|e| internal(&e))?, - ), - None => None, - }; - let commit_tree = commit.tree().map_err(|e| internal(&e))?; - for change in - tree_changes::changes_between_trees(repo, parent_tree.as_ref(), &commit_tree)? - .changes - { - match change { - tree_changes::TreeChange::Added { path, .. } - | tree_changes::TreeChange::Deleted { path, .. } - | tree_changes::TreeChange::Modified { path, .. } => { - touched.insert(path); - } - tree_changes::TreeChange::Renamed { - path, source_path, .. - } => { - touched.insert(path); - touched.insert(source_path); - } - } - } - } - } - - let mut survivors = Vec::new(); - for path in touched { - // Both endpoints must hold *blob* entries — `changed_files`' - // blob-only contract. A path that is a symlink at both - // endpoints (with a transient blob life inside the range) has - // no analyzable text to hang a diff row on. - let blob_at = |tree: &gix::Tree<'_>| -> Result { - Ok(tree - .lookup_entry_by_path(&path) - .map_err(|e| internal(&e))? - .is_some_and(|entry| entry.mode().is_blob())) - }; - if blob_at(&from_tree)? && blob_at(&to_tree)? { - survivors.push(path); - } - } - Ok(survivors) -} - -/// Read file content at a specific revision. Returns `None` if the path -/// doesn't exist at that revision (e.g. newly added file with no baseline). -pub fn read_blob( - repo: &gix::Repository, - rev: &str, - path: &Path, -) -> Result>, GitError> { - let tree = resolve_tree(repo, rev)?; - - let entry = tree - .lookup_entry_by_path(path) - .map_err(|e| GitError::Internal(e.to_string()))?; - - let Some(entry) = entry else { - return Ok(None); - }; - - let object = entry - .object() - .map_err(|e| GitError::Internal(e.to_string()))?; - - let mut data = object.detach().data; - remove_blank_lines(&mut data); - Ok(Some(data)) -} - -/// Try to resolve a rev string to a friendly symbolic branch name. -/// -/// Resolves `rev` to a commit OID, then scans local and remote branches for -/// one that points at the same commit. Returns the short branch name -/// (e.g. `"main"`) on a match, or falls back to `rev` unchanged. -pub fn friendly_ref_label(repo: &gix::Repository, rev: &str) -> String { - let friendly_name = (|| { - let id = repo.rev_parse_single(rev).ok()?; - let commit = id.object().ok()?.peel_to_commit().ok()?; - let refs = repo.references().ok()?; - - find_branch_for_commit(&refs, commit.id, true) - .or_else(|| find_branch_for_commit(&refs, commit.id, false)) - })(); - - friendly_name.unwrap_or_else(|| rev.to_string()) -} - -fn find_branch_for_commit( - refs: &gix::reference::iter::Platform<'_>, - commit_id: gix::ObjectId, - local: bool, -) -> Option { - let iter = if local { - refs.local_branches().ok()? - } else { - refs.remote_branches().ok()? - }; - let peeled = iter.peeled().ok()?; - for reference in peeled.flatten() { - if reference.id() == commit_id { - let full = reference.name().as_bstr().to_string(); - return Some(shorten_ref_name(&full).to_string()); - } - } - None -} - -/// Strip standard ref prefixes to produce a short branch name. -fn shorten_ref_name(full: &str) -> &str { - full.strip_prefix("refs/heads/") - .or_else(|| full.strip_prefix("refs/remotes/origin/")) - .or_else(|| { - full.strip_prefix("refs/remotes/") - .and_then(|s: &str| s.split_once('/').map(|(_, branch)| branch)) - }) - .unwrap_or(full) -} - -fn resolve_tree<'a>(repo: &'a gix::Repository, rev: &str) -> Result, GitError> { - let id = repo - .rev_parse_single(rev) - .map_err(|_| GitError::RefNotFound(rev.to_string()))?; - - let object = id.object().map_err(|e| GitError::Internal(e.to_string()))?; - - let commit = object - .peel_to_commit() - .map_err(|e| GitError::Internal(e.to_string()))?; - - commit.tree().map_err(|e| GitError::Internal(e.to_string())) -} diff --git a/crates/mehen-git/src/tree_changes.rs b/crates/mehen-git/src/tree_changes.rs deleted file mode 100644 index 650cf928..00000000 --- a/crates/mehen-git/src/tree_changes.rs +++ /dev/null @@ -1,1116 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Deterministic tree-to-tree change detection with rename tracking. -//! -//! The tree walk and rename matcher come from `gix` plumbing. Unlike -//! `Repository::diff_tree_to_tree`, this module supplies an explicit -//! [`gix::diff::Rewrites`] configuration and a raw-object diff platform -//! with no repository attributes, filters, drivers, or diff settings. -//! Rename results therefore depend only on the compared trees. -//! This is the lower-level integration recommended by the `gix` -//! maintainer in GitoxideLabs/gitoxide#2915. -//! -//! Two narrow additions remain in-crate because `gix` does not provide -//! them: a bounded `-B`-style break-rewrite pass for reused paths, and -//! a byte-span fallback for edited one-line files that line-tokenized -//! similarity cannot recognize. -//! -//! Only blob entries are reported: directories, symlinks, and gitlinks -//! (submodules) carry no analyzable text. An entry changing *type* -//! across the trees is reported from the blob side — a file replaced -//! by a submodule is that file's deletion, and vice versa. - -use std::collections::{HashMap, HashSet}; -use std::convert::Infallible; -use std::path::PathBuf; - -use gix::diff::blob::{Algorithm, Diff, InternedInput, sources::byte_lines}; -use gix::diff::rewrites::tracker::ChangeKind; -use gix::diff::tree::recorder::Change as TreeRecord; -use gix::objs::TreeRefIter; -use gix::objs::tree::EntryMode; - -use crate::GitError; - -/// Similarity threshold for rename detection (git's `-M50%` default). -pub(crate) const RENAME_SIMILARITY: f64 = 0.5; - -/// Upper bound on deletion×addition pairs examined by either fuzzy -/// rename pass. Exact (same-blob) renames are always detected by `gix`; -/// beyond this budget, inexact renames degrade to deletion + addition. -const RENAME_FUZZY_PAIR_LIMIT: usize = 10_000; - -/// Blobs larger than this never enter a fuzzy similarity pass. Sizes -/// are checked through object headers before data is materialized; -/// exact renames still match at any size. -pub(crate) const FUZZY_MAX_BLOB_BYTES: u64 = 8 * 1024 * 1024; - -/// Total bytes the byte-span fallback may materialize per tree diff. -/// Applied in sorted path order so truncation is deterministic. -const FUZZY_TOTAL_BYTE_BUDGET: u64 = 64 * 1024 * 1024; - -/// Total bytes the break-rewrite scan may materialize per tree diff, -/// separate from the fuzzy fallback budget. -const BREAK_TOTAL_BYTE_BUDGET: u64 = 64 * 1024 * 1024; - -/// Fixed-offset span bound for byte-span similarity. -const SPAN_FIXED_BYTES: usize = 64; - -/// Bounds for content-defined similarity chunks. -const SPAN_MIN_BYTES: usize = 16; -const SPAN_MAX_BYTES: usize = 256; -const SPAN_CUT_MASK: u64 = 0x3F; - -/// Binary detection window: git treats content with a NUL byte in the -/// first 8000 bytes as binary. -const BINARY_SNIFF_BYTES: usize = 8000; - -/// Small modifications-only commits still get the break-rewrite scan -/// so edited swaps can be recovered without an add/delete loose end. -const SWAP_SCAN_MAX_MODIFICATIONS: usize = 8; - -/// Spanhash similarity of two blobs, when both are loadable within -/// the per-blob cap (equal ids score 1.0). -pub(crate) fn blob_lineage_similarity( - repo: &gix::Repository, - a: &gix::ObjectId, - b: &gix::ObjectId, -) -> Result, GitError> { - if a == b { - return Ok(Some(1.0)); - } - if blob_size(repo, a)? > FUZZY_MAX_BLOB_BYTES || blob_size(repo, b)? > FUZZY_MAX_BLOB_BYTES { - return Ok(None); - } - let a_data = read_blob_data(repo, a)?; - let b_data = read_blob_data(repo, b)?; - Ok(Some(spanhash_similarity(&a_data, &b_data))) -} - -/// Whether two blobs plausibly hold the same file lineage. -pub(crate) fn same_blob_lineage( - repo: &gix::Repository, - a: &gix::ObjectId, - b: &gix::ObjectId, -) -> Result { - Ok(blob_lineage_similarity(repo, a, b)?.is_some_and(|s| s >= RENAME_SIMILARITY)) -} - -/// Convert a git tree path to a native path without lossy UTF-8 -/// replacement. A path that the platform cannot represent is skipped -/// at emission while still contributing one opaque changeset member. -pub(crate) fn path_from_git(path: &gix::bstr::BString) -> Option { - match gix::path::try_from_bstr(path.as_ref() as &gix::bstr::BStr) { - Ok(path) => Some(path.into_owned()), - Err(_) => { - log::warn!( - "skipping git path not representable on this platform: {}", - String::from_utf8_lossy(path) - ); - None - } - } -} - -/// One file-level change between two trees, blob entries only. -pub(crate) enum TreeChange { - Added { - path: PathBuf, - oid: gix::ObjectId, - }, - Deleted { - path: PathBuf, - oid: gix::ObjectId, - }, - Modified { - path: PathBuf, - previous_oid: gix::ObjectId, - oid: gix::ObjectId, - }, - Renamed { - path: PathBuf, - source_path: PathBuf, - previous_oid: gix::ObjectId, - oid: gix::ObjectId, - }, -} - -/// The result of a tree-to-tree diff: analyzable blob changes with -/// renames joined, plus changed non-blob leaf entries for coupling. -pub(crate) struct TreeChanges { - pub(crate) changes: Vec, - pub(crate) non_blob_changes: usize, - /// Rename destinations whose source path cannot be represented on - /// this platform. Their earlier lineage cannot be published safely. - pub(crate) truncated_lineages: Vec, -} - -#[derive(Clone)] -struct RenameSide { - path: gix::bstr::BString, - oid: gix::ObjectId, - mode: EntryMode, - /// Index of the same-path modification split by the `-B` pass. - broken: Option, -} - -struct BlobModification { - path: gix::bstr::BString, - previous_oid: gix::ObjectId, - previous_mode: EntryMode, - oid: gix::ObjectId, - mode: EntryMode, -} - -struct BrokenPair { - path: gix::bstr::BString, - previous_oid: gix::ObjectId, - oid: gix::ObjectId, -} - -#[derive(Clone)] -struct TrackedChange { - kind: ChangeKind, - side: RenameSide, -} - -struct RewriteMatches { - renames: Vec<(RenameSide, RenameSide)>, - added: Vec, - deleted: Vec, -} - -impl gix::diff::rewrites::tracker::Change for TrackedChange { - fn id(&self) -> &gix::oid { - &self.side.oid - } - - fn relation(&self) -> Option { - None - } - - fn kind(&self) -> ChangeKind { - self.kind - } - - fn entry_mode(&self) -> EntryMode { - self.side.mode - } - - fn id_and_entry_mode(&self) -> (&gix::oid, EntryMode) { - (&self.side.oid, self.side.mode) - } -} - -/// Blob-to-blob modifications between two trees, with no rename -/// detection or blob loads. -pub(crate) fn blob_modifications_between_trees( - repo: &gix::Repository, - base: &gix::Tree<'_>, - current: &gix::Tree<'_>, -) -> Result, GitError> { - let mut recorder = gix::diff::tree::Recorder::default(); - gix::diff::tree( - TreeRefIter::from_bytes(&base.data, base.id.kind()), - TreeRefIter::from_bytes(¤t.data, current.id.kind()), - gix::diff::tree::State::default(), - repo.objects.clone(), - &mut recorder, - ) - .map_err(|e| GitError::Internal(e.to_string()))?; - - let mut modifications = Vec::new(); - for change in recorder.records { - if let TreeRecord::Modification { - previous_entry_mode, - entry_mode, - oid, - path, - .. - } = change - && previous_entry_mode.is_blob() - && entry_mode.is_blob() - && let Some(path) = path_from_git(&path) - { - modifications.push((path, oid)); - } - } - Ok(modifications) -} - -/// Diff two trees (blob entries only, renames joined). `parent` of -/// `None` means the empty tree. -pub(crate) fn changes_between_trees( - repo: &gix::Repository, - parent: Option<&gix::Tree<'_>>, - current: &gix::Tree<'_>, -) -> Result { - let (parent_data, parent_kind) = match parent { - Some(tree) => (tree.data.as_slice(), tree.id.kind()), - None => ([].as_slice(), current.id.kind()), - }; - - let mut recorder = gix::diff::tree::Recorder::default(); - gix::diff::tree( - TreeRefIter::from_bytes(parent_data, parent_kind), - TreeRefIter::from_bytes(¤t.data, current.id.kind()), - gix::diff::tree::State::default(), - repo.objects.clone(), - &mut recorder, - ) - .map_err(|e| GitError::Internal(e.to_string()))?; - - let mut added = Vec::new(); - let mut deleted = Vec::new(); - let mut modified = Vec::new(); - let mut changes = Vec::new(); - let mut non_blob_changes = 0; - let mut truncated_lineages = Vec::new(); - let mut non_blob_added: HashMap<(gix::objs::tree::EntryKind, gix::ObjectId), usize> = - HashMap::new(); - let mut non_blob_deleted: HashMap<(gix::objs::tree::EntryKind, gix::ObjectId), usize> = - HashMap::new(); - - for change in recorder.records { - match change { - TreeRecord::Addition { - entry_mode, - oid, - path, - .. - } => { - if entry_mode.is_blob() { - added.push(RenameSide { - path, - oid, - mode: entry_mode, - broken: None, - }); - } else { - *non_blob_added.entry((entry_mode.kind(), oid)).or_insert(0) += 1; - } - } - TreeRecord::Deletion { - entry_mode, - oid, - path, - .. - } => { - if entry_mode.is_blob() { - deleted.push(RenameSide { - path, - oid, - mode: entry_mode, - broken: None, - }); - } else { - *non_blob_deleted - .entry((entry_mode.kind(), oid)) - .or_insert(0) += 1; - } - } - TreeRecord::Modification { - previous_entry_mode, - previous_oid, - entry_mode, - oid, - path, - } => match (previous_entry_mode.is_blob(), entry_mode.is_blob()) { - (true, true) => modified.push(BlobModification { - path, - previous_oid, - previous_mode: previous_entry_mode, - oid, - mode: entry_mode, - }), - (true, false) => match path_from_git(&path) { - Some(path) => changes.push(TreeChange::Deleted { - path, - oid: previous_oid, - }), - None => non_blob_changes += 1, - }, - (false, true) => match path_from_git(&path) { - Some(path) => changes.push(TreeChange::Added { path, oid }), - None => non_blob_changes += 1, - }, - (false, false) => non_blob_changes += 1, - }, - } - } - - // An exact non-blob move is one changed identity, not a deletion - // plus an addition. Only the count is needed by coupling. - for (key, added_count) in non_blob_added { - let deleted_count = non_blob_deleted.remove(&key).unwrap_or(0); - non_blob_changes += added_count.max(deleted_count); - } - non_blob_changes += non_blob_deleted.into_values().sum::(); - - let mut broken_pairs = Vec::new(); - let modified_previous_oids: HashSet = modified - .iter() - .filter(|change| change.previous_oid != change.oid) - .map(|change| change.previous_oid) - .collect(); - let modified_new_oids: HashSet = modified - .iter() - .filter(|change| change.previous_oid != change.oid) - .map(|change| change.oid) - .collect(); - let has_loose_ends = !added.is_empty() || !deleted.is_empty(); - let small_swap_scan = - !has_loose_ends && modified.len() >= 2 && modified.len() <= SWAP_SCAN_MAX_MODIFICATIONS; - - modified.sort_by(|a, b| git_path_order(a.path.as_ref(), b.path.as_ref())); - let mut break_budget = BREAK_TOTAL_BYTE_BUDGET; - for modification in modified { - let cross_matched = modified_new_oids.contains(&modification.previous_oid) - || modified_previous_oids.contains(&modification.oid); - let should_scan = (has_loose_ends || cross_matched || small_swap_scan) - && modification.previous_oid != modification.oid; - - if should_scan { - let old_size = blob_size(repo, &modification.previous_oid)?; - let new_size = blob_size(repo, &modification.oid)?; - let bytes = old_size.saturating_add(new_size); - if old_size <= FUZZY_MAX_BLOB_BYTES - && new_size <= FUZZY_MAX_BLOB_BYTES - && bytes <= break_budget - { - break_budget -= bytes; - let old_data = read_blob_data(repo, &modification.previous_oid)?; - let new_data = read_blob_data(repo, &modification.oid)?; - if spanhash_similarity(&old_data, &new_data) < RENAME_SIMILARITY { - let pair = broken_pairs.len(); - broken_pairs.push(BrokenPair { - path: modification.path.clone(), - previous_oid: modification.previous_oid, - oid: modification.oid, - }); - deleted.push(RenameSide { - path: modification.path.clone(), - oid: modification.previous_oid, - mode: modification.previous_mode, - broken: Some(pair), - }); - added.push(RenameSide { - path: modification.path, - oid: modification.oid, - mode: modification.mode, - broken: Some(pair), - }); - continue; - } - } - } - - match path_from_git(&modification.path) { - Some(path) => changes.push(TreeChange::Modified { - path, - previous_oid: modification.previous_oid, - oid: modification.oid, - }), - None => non_blob_changes += 1, - } - } - - detect_renames( - repo, - &mut changes, - added, - deleted, - &broken_pairs, - &mut non_blob_changes, - &mut truncated_lineages, - )?; - - Ok(TreeChanges { - changes, - non_blob_changes, - truncated_lineages, - }) -} - -/// Match additions and deletions with `gix`'s deterministic rewrite -/// tracker over a raw-object, attribute-free diff platform. -#[allow(clippy::too_many_arguments)] -fn detect_renames( - repo: &gix::Repository, - changes: &mut Vec, - added: Vec, - deleted: Vec, - broken_pairs: &[BrokenPair], - non_blob_changes: &mut usize, - truncated_lineages: &mut Vec, -) -> Result<(), GitError> { - let mut diff_cache = raw_diff_platform(repo); - - // Exact matching is cheap and never materializes blob content, so - // every candidate participates regardless of size or count. - let exact = run_rewrite_tracker(repo, &mut diff_cache, added, deleted, None)?; - for (source, destination) in exact.renames { - push_renamed( - changes, - non_blob_changes, - truncated_lineages, - &source, - &destination, - ); - } - - // `gix` caches resources for matrix matching. Select a bounded, - // deterministic subset per side before enabling fuzzy similarity - // so the cache cannot grow with the repository's total blob volume. - let (fuzzy_added, mut remaining_added) = - partition_fuzzy_budget(repo, exact.added, FUZZY_TOTAL_BYTE_BUDGET)?; - let (fuzzy_deleted, mut remaining_deleted) = - partition_fuzzy_budget(repo, exact.deleted, FUZZY_TOTAL_BYTE_BUDGET)?; - let fuzzy = if fuzzy_pairs_within_limit(fuzzy_added.len(), fuzzy_deleted.len()) { - run_rewrite_tracker( - repo, - &mut diff_cache, - fuzzy_added, - fuzzy_deleted, - Some(RENAME_SIMILARITY as f32), - )? - } else { - RewriteMatches { - renames: Vec::new(), - added: fuzzy_added, - deleted: fuzzy_deleted, - } - }; - for (source, destination) in fuzzy.renames { - push_renamed( - changes, - non_blob_changes, - truncated_lineages, - &source, - &destination, - ); - } - remaining_added.extend(fuzzy.added); - remaining_deleted.extend(fuzzy.deleted); - drop(diff_cache); - - // `gix` tokenizes similarity by lines. Preserve rename identity - // for edited one-line/minified files with a bounded raw-byte pass - // over only the entries it left unmatched. - match_remaining_by_spanhash( - repo, - changes, - &mut remaining_added, - &mut remaining_deleted, - non_blob_changes, - truncated_lineages, - )?; - - reassemble_broken_pairs( - changes, - remaining_added, - remaining_deleted, - broken_pairs, - non_blob_changes, - ); - Ok(()) -} - -fn run_rewrite_tracker( - repo: &gix::Repository, - diff_cache: &mut gix::diff::blob::Platform, - added: Vec, - deleted: Vec, - percentage: Option, -) -> Result { - let mut tracker = gix::diff::rewrites::Tracker::new(gix::diff::Rewrites { - copies: None, - percentage, - // The public docs and gix-diff 0.66 implementation disagree - // about whether this value bounds files or permutations. The - // caller enforces our pair budget before enabling similarity, - // so disable this version-dependent internal limit. - limit: 0, - track_empty: false, - }); - - for (kind, sides) in [ - (ChangeKind::Addition, added), - (ChangeKind::Deletion, deleted), - ] { - for side in sides { - // The tracker copies the location into its own backing. - let location = side.path.clone(); - let rejected = tracker.try_push_change( - TrackedChange { kind, side }, - location.as_ref() as &gix::bstr::BStr, - ); - debug_assert!(rejected.is_none()); - } - } - - let mut matches = RewriteMatches { - renames: Vec::new(), - added: Vec::new(), - deleted: Vec::new(), - }; - tracker - .emit( - |destination, source| { - if let Some(source) = source { - let source_side = &source.change.side; - let destination_side = &destination.change.side; - // A speculative `-B` split must not pair back onto - // itself. Keep both halves for the fallback/reassembly. - if source_side.broken.is_some() && source_side.broken == destination_side.broken - { - matches.deleted.push(source_side.clone()); - matches.added.push(destination_side.clone()); - } else { - matches - .renames - .push((source_side.clone(), destination_side.clone())); - } - } else { - match destination.change.kind { - ChangeKind::Addition => { - matches.added.push(destination.change.side); - } - ChangeKind::Deletion => { - matches.deleted.push(destination.change.side); - } - ChangeKind::Modification => { - unreachable!("copy tracking is disabled") - } - } - } - std::ops::ControlFlow::Continue(()) - }, - diff_cache, - &repo.objects, - |_| Ok::<(), Infallible>(()), - ) - .map_err(|e| GitError::Internal(e.to_string()))?; - - Ok(matches) -} - -/// Build a `gix` blob platform whose similarity input is exactly the -/// object database bytes. The empty attribute stack has no index or -/// worktree mappings, and the pipeline has no drivers or filters. -fn raw_diff_platform(repo: &gix::Repository) -> gix::diff::blob::Platform { - let attributes = gix::worktree::stack::state::Attributes::new( - gix::attrs::Search::default(), - None, - gix::worktree::stack::state::attributes::Source::IdMapping, - gix::attrs::search::MetadataCollection::default(), - ); - let attr_stack = gix::worktree::Stack::new( - repo.git_dir(), - gix::worktree::stack::State::AttributesStack(attributes), - gix::glob::pattern::Case::Sensitive, - Vec::with_capacity(512), - Vec::new(), - ); - - let mut worktree_filter = gix::filter::plumbing::Pipeline::default(); - worktree_filter.options_mut().object_hash = repo.object_hash(); - let pipeline = gix::diff::blob::Pipeline::new( - Default::default(), - worktree_filter, - Vec::new(), - gix::diff::blob::pipeline::Options { - large_file_threshold_bytes: FUZZY_MAX_BLOB_BYTES, - fs: Default::default(), - }, - ); - - gix::diff::blob::Platform::new( - gix::diff::blob::platform::Options { - algorithm: Some(Algorithm::Histogram), - skip_internal_diff_if_external_is_configured: false, - }, - pipeline, - gix::diff::blob::pipeline::Mode::ToGit, - attr_stack, - ) -} - -fn partition_fuzzy_budget( - repo: &gix::Repository, - entries: Vec, - budget: u64, -) -> Result<(Vec, Vec), GitError> { - let mut sizes = Vec::with_capacity(entries.len()); - for side in &entries { - sizes.push(blob_size(repo, &side.oid)?); - } - let mut order: Vec = (0..entries.len()).collect(); - order.sort_by(|&a, &b| fuzzy_budget_order(&sizes, &entries, a, b)); - - let mut remaining = budget; - let mut selected = vec![false; entries.len()]; - for index in order { - let size = sizes[index]; - if size > FUZZY_MAX_BLOB_BYTES || size > remaining { - continue; - } - remaining -= size; - selected[index] = true; - } - - let mut within_budget = Vec::new(); - let mut deferred = Vec::new(); - for (entry, selected) in entries.into_iter().zip(selected) { - if selected { - within_budget.push(entry); - } else { - deferred.push(entry); - } - } - Ok((within_budget, deferred)) -} - -fn match_remaining_by_spanhash( - repo: &gix::Repository, - changes: &mut Vec, - added: &mut Vec, - deleted: &mut Vec, - non_blob_changes: &mut usize, - truncated_lineages: &mut Vec, -) -> Result<(), GitError> { - if added.is_empty() - || deleted.is_empty() - || !fuzzy_pairs_within_limit(added.len(), deleted.len()) - { - return Ok(()); - } - - added.sort_by(|a, b| git_path_order(a.path.as_ref(), b.path.as_ref())); - deleted.sort_by(|a, b| git_path_order(a.path.as_ref(), b.path.as_ref())); - - let deleted_blobs = load_fuzzy_blobs(repo, deleted, FUZZY_TOTAL_BYTE_BUDGET)?; - let mut added_sizes = Vec::with_capacity(added.len()); - for side in added.iter() { - added_sizes.push(blob_size(repo, &side.oid)?); - } - let mut added_order: Vec = (0..added.len()).collect(); - added_order.sort_by(|&a, &b| fuzzy_budget_order(&added_sizes, added, a, b)); - - let mut candidates = Vec::new(); - let mut stream_budget = FUZZY_TOTAL_BYTE_BUDGET; - for added_index in added_order { - let size = added_sizes[added_index]; - if size > FUZZY_MAX_BLOB_BYTES || size > stream_budget { - continue; - } - stream_budget -= size; - let new_blob = read_blob_data(repo, &added[added_index].oid)?; - for (deleted_index, old_blob) in deleted_blobs.iter().enumerate() { - let Some(old_blob) = old_blob else { continue }; - if deleted[deleted_index].broken.is_some() - && deleted[deleted_index].broken == added[added_index].broken - { - continue; - } - if let Some(similarity) = spanhash_candidate(old_blob, &new_blob) { - candidates.push((similarity, deleted_index, added_index)); - } - } - } - - candidates.sort_by(|a, b| { - b.0.total_cmp(&a.0) - .then_with(|| git_path_order(deleted[a.1].path.as_ref(), deleted[b.1].path.as_ref())) - .then_with(|| git_path_order(added[a.2].path.as_ref(), added[b.2].path.as_ref())) - }); - - let mut added_taken = vec![false; added.len()]; - let mut deleted_taken = vec![false; deleted.len()]; - for (_, deleted_index, added_index) in candidates { - if added_taken[added_index] || deleted_taken[deleted_index] { - continue; - } - added_taken[added_index] = true; - deleted_taken[deleted_index] = true; - push_renamed( - changes, - non_blob_changes, - truncated_lineages, - &deleted[deleted_index], - &added[added_index], - ); - } - - *added = std::mem::take(added) - .into_iter() - .zip(added_taken) - .filter_map(|(side, taken)| (!taken).then_some(side)) - .collect(); - *deleted = std::mem::take(deleted) - .into_iter() - .zip(deleted_taken) - .filter_map(|(side, taken)| (!taken).then_some(side)) - .collect(); - Ok(()) -} - -fn fuzzy_pairs_within_limit(added: usize, deleted: usize) -> bool { - added - .checked_mul(deleted) - .is_some_and(|pairs| pairs <= RENAME_FUZZY_PAIR_LIMIT) -} - -fn reassemble_broken_pairs( - changes: &mut Vec, - remaining_added: Vec, - remaining_deleted: Vec, - broken_pairs: &[BrokenPair], - non_blob_changes: &mut usize, -) { - let unpaired_deleted: HashSet = remaining_deleted - .iter() - .filter_map(|side| side.broken) - .collect(); - let mut reassembled = vec![false; broken_pairs.len()]; - - for side in &remaining_added { - if let Some(pair) = side.broken - && unpaired_deleted.contains(&pair) - { - let broken = &broken_pairs[pair]; - match path_from_git(&broken.path) { - Some(path) => changes.push(TreeChange::Modified { - path, - previous_oid: broken.previous_oid, - oid: broken.oid, - }), - None => *non_blob_changes += 1, - } - reassembled[pair] = true; - } - } - - for side in remaining_added { - if side.broken.is_some_and(|pair| reassembled[pair]) { - continue; - } - match path_from_git(&side.path) { - Some(path) => changes.push(TreeChange::Added { - path, - oid: side.oid, - }), - None => *non_blob_changes += 1, - } - } - for side in remaining_deleted { - if side.broken.is_some_and(|pair| reassembled[pair]) { - continue; - } - match path_from_git(&side.path) { - Some(path) => changes.push(TreeChange::Deleted { - path, - oid: side.oid, - }), - None => *non_blob_changes += 1, - } - } -} - -/// Emit a paired rename, degrading consistently when either path is -/// not representable on this platform. -fn push_renamed( - changes: &mut Vec, - non_blob_changes: &mut usize, - truncated_lineages: &mut Vec, - source: &RenameSide, - destination: &RenameSide, -) { - match ( - path_from_git(&destination.path), - path_from_git(&source.path), - ) { - (Some(path), Some(source_path)) => changes.push(TreeChange::Renamed { - path, - source_path, - previous_oid: source.oid, - oid: destination.oid, - }), - (Some(path), None) => { - truncated_lineages.push(path.clone()); - changes.push(TreeChange::Added { - path, - oid: destination.oid, - }); - } - (None, Some(source_path)) => changes.push(TreeChange::Deleted { - path: source_path, - oid: source.oid, - }), - (None, None) => *non_blob_changes += 1, - } -} - -fn git_path_order(a: &[u8], b: &[u8]) -> std::cmp::Ordering { - a.cmp(b) -} - -fn fuzzy_budget_order( - sizes: &[u64], - entries: &[RenameSide], - a: usize, - b: usize, -) -> std::cmp::Ordering { - fn basename(path: &gix::bstr::BString) -> &[u8] { - let bytes: &[u8] = path.as_ref(); - bytes.rsplit(|&c| c == b'/').next().unwrap_or(bytes) - } - - basename(&entries[a].path) - .cmp(basename(&entries[b].path)) - .then_with(|| sizes[a].cmp(&sizes[b])) - .then_with(|| git_path_order(entries[a].path.as_ref(), entries[b].path.as_ref())) -} - -fn load_fuzzy_blobs( - repo: &gix::Repository, - entries: &[RenameSide], - budget: u64, -) -> Result>>, GitError> { - let mut sizes = Vec::with_capacity(entries.len()); - for side in entries { - sizes.push(blob_size(repo, &side.oid)?); - } - let mut order: Vec = (0..entries.len()).collect(); - order.sort_by(|&a, &b| fuzzy_budget_order(&sizes, entries, a, b)); - - let mut remaining = budget; - let mut blobs: Vec>> = (0..entries.len()).map(|_| None).collect(); - for index in order { - let size = sizes[index]; - if size > FUZZY_MAX_BLOB_BYTES || size > remaining { - continue; - } - remaining -= size; - blobs[index] = Some(read_blob_data(repo, &entries[index].oid)?); - } - Ok(blobs) -} - -fn spanhash_candidate(old: &[u8], new: &[u8]) -> Option { - if old.is_empty() && new.is_empty() { - return None; - } - let similarity = spanhash_similarity(old, new); - (similarity >= RENAME_SIMILARITY).then_some(similarity) -} - -/// Byte-weighted similarity scored under fixed and content-defined -/// chunking, taking the stronger result. -fn spanhash_similarity(old: &[u8], new: &[u8]) -> f64 { - let fixed = span_multiset_similarity(old, new, fixed_spans); - if fixed >= 1.0 { - return fixed; - } - fixed.max(span_multiset_similarity(old, new, gear_spans)) -} - -fn span_multiset_similarity(old: &[u8], new: &[u8], chunk: fn(&[u8]) -> Vec<&[u8]>) -> f64 { - let longest = old.len().max(new.len()); - if longest == 0 { - return 0.0; - } - - let mut available: HashMap = HashMap::new(); - for span in chunk(old) { - *available.entry(fnv1a(span)).or_insert(0) += span.len() as u64; - } - let mut common = 0; - for span in chunk(new) { - if let Some(bytes) = available.get_mut(&fnv1a(span)) { - let take = (span.len() as u64).min(*bytes); - *bytes -= take; - common += take; - } - } - common as f64 / longest as f64 -} - -fn fixed_spans(data: &[u8]) -> Vec<&[u8]> { - let mut rest = data; - let mut out = Vec::new(); - while !rest.is_empty() { - let end = match rest.iter().take(SPAN_FIXED_BYTES).position(|&b| b == b'\n') { - Some(newline) => newline + 1, - None => SPAN_FIXED_BYTES.min(rest.len()), - }; - let (span, tail) = rest.split_at(end); - out.push(span); - rest = tail; - } - out -} - -fn gear_spans(data: &[u8]) -> Vec<&[u8]> { - let mut rest = data; - let mut out = Vec::new(); - while !rest.is_empty() { - let mut gear = 0u64; - let mut end = rest.len().min(SPAN_MAX_BYTES); - for (i, &byte) in rest.iter().take(SPAN_MAX_BYTES).enumerate() { - if byte == b'\n' { - end = i + 1; - break; - } - gear = (gear << 1).wrapping_add(GEAR[byte as usize]); - if i + 1 >= SPAN_MIN_BYTES && gear & SPAN_CUT_MASK == SPAN_CUT_MASK { - end = i + 1; - break; - } - } - let (span, tail) = rest.split_at(end); - out.push(span); - rest = tail; - } - out -} - -const GEAR: [u64; 256] = build_gear_table(); - -const fn build_gear_table() -> [u64; 256] { - let mut table = [0u64; 256]; - let mut state = 0x9E37_79B9_7F4A_7C15u64; - let mut i = 0; - while i < 256 { - state = state.wrapping_add(0x9E37_79B9_7F4A_7C15); - let mut z = state; - z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9); - z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB); - table[i] = z ^ (z >> 31); - i += 1; - } - table -} - -fn fnv1a(data: &[u8]) -> u64 { - let mut hash = 0xcbf2_9ce4_8422_2325u64; - for &byte in data { - hash ^= u64::from(byte); - hash = hash.wrapping_mul(0x0000_0100_0000_01b3); - } - hash -} - -/// A blob's size from its object header, without loading the payload. -pub(crate) fn blob_size(repo: &gix::Repository, oid: &gix::ObjectId) -> Result { - Ok(repo - .find_header(*oid) - .map_err(|e| GitError::Internal(e.to_string()))? - .size()) -} - -/// Whether content is binary by git's NUL-sniff heuristic. -pub(crate) fn is_binary(data: &[u8]) -> bool { - data.iter().take(BINARY_SNIFF_BYTES).any(|&b| b == 0) -} - -/// Line-level (added, removed) counts using histogram diff. -pub(crate) fn line_diff_counts(old_data: &[u8], new_data: &[u8]) -> (u64, u64) { - let input = InternedInput::new(byte_lines(old_data), byte_lines(new_data)); - let diff = Diff::compute(Algorithm::Histogram, &input); - ( - u64::from(diff.count_additions()), - u64::from(diff.count_removals()), - ) -} - -pub(crate) fn read_blob_data( - repo: &gix::Repository, - oid: &gix::ObjectId, -) -> Result, GitError> { - let object = repo - .find_object(*oid) - .map_err(|e| GitError::Internal(e.to_string()))?; - Ok(object.detach().data) -} - -/// Number of lines in a blob (a trailing fragment counts as a line). -pub(crate) fn count_lines(data: &[u8]) -> u64 { - if data.is_empty() { - return 0; - } - let newlines = data.iter().filter(|&&b| b == b'\n').count() as u64; - if data.ends_with(b"\n") { - newlines - } else { - newlines + 1 - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn count_lines_handles_trailing_newline_variants() { - assert_eq!(count_lines(b""), 0); - assert_eq!(count_lines(b"one\n"), 1); - assert_eq!(count_lines(b"one\ntwo\n"), 2); - assert_eq!(count_lines(b"one\ntwo"), 2); - assert_eq!(count_lines(b"no newline"), 1); - } - - #[test] - fn line_diff_counts_are_line_based_not_byte_based() { - let old = b"fn a() {}\nfn b() {}\n"; - let new = b"fn a_renamed_with_many_bytes() {}\nfn b() {}\n"; - assert_eq!(line_diff_counts(old, new), (1, 1)); - } - - #[test] - fn spanhash_recognizes_edited_single_line_files() { - let old = format!("export const x = [{}];", "1, ".repeat(200)); - let new = old.replace("const x", "const y"); - let similarity = spanhash_candidate(old.as_bytes(), new.as_bytes()) - .expect("one-line edit should stay above the rename threshold"); - assert!(similarity >= RENAME_SIMILARITY, "got {similarity}"); - } - - #[test] - fn spanhash_rejects_dissimilar_single_line_files() { - let old = b"export const alpha_configuration_value = 1;"; - let new = b"#!/bin/sh @@ ~~ [[ ]] %% ^^ && || ;; :: ??"; - assert_eq!(spanhash_candidate(old, new), None); - } - - #[test] - fn spanhash_ignores_empty_blobs() { - assert_eq!(spanhash_candidate(b"", b""), None); - } - - #[test] - fn spanhash_similarity_is_byte_weighted_not_line_weighted() { - let shared = "# generated\n"; - let old = format!("{shared}{}\n", "A".repeat(4000)); - let new = format!("{shared}{}\n", "B".repeat(4000)); - let similarity = spanhash_similarity(old.as_bytes(), new.as_bytes()); - assert!( - similarity < RENAME_SIMILARITY, - "a rewritten dominant line must not pass: {similarity}" - ); - } - - #[test] - fn is_binary_detects_nul_in_sniff_window() { - assert!(is_binary(b"PK\x03\x04\x00binary")); - assert!(!is_binary(b"plain text\nwith lines\n")); - } - - #[test] - fn fuzzy_pair_budget_is_explicit_and_overflow_safe() { - assert!(fuzzy_pairs_within_limit(100, 100)); - assert!(!fuzzy_pairs_within_limit(101, 100)); - assert!(!fuzzy_pairs_within_limit(usize::MAX, 2)); - } -} diff --git a/crates/mehen-git/tests/history.rs b/crates/mehen-git/tests/history.rs deleted file mode 100644 index 321d294d..00000000 --- a/crates/mehen-git/tests/history.rs +++ /dev/null @@ -1,5636 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Integration tests for the history-walk subsystem against a real, -//! fully deterministic fixture repository (pinned author identities -//! and commit timestamps). - -use std::path::Path; - -use mehen_git::collect_history; - -// Fixture timestamps (seconds since epoch, first-of-month UTC 2026). -const T_JAN: i64 = 1_767_225_600; -const T_FEB: i64 = 1_769_904_000; -const T_MAR: i64 = 1_772_323_200; -const T_APR: i64 = 1_775_001_600; -const T_MAY: i64 = 1_777_593_600; -const T_JUN: i64 = 1_780_272_000; - -/// Average Gregorian month in seconds — must match -/// `mehen_git::history::SECONDS_PER_MONTH`. -const SECONDS_PER_MONTH: f64 = 2_629_746.0; - -fn git(repo: &Path, args: &[&str], author: (&str, &str), seconds: i64) { - let date = format!("{seconds} +0000"); - let output = std::process::Command::new("git") - .current_dir(repo) - .args(args) - .env("GIT_AUTHOR_NAME", author.0) - .env("GIT_AUTHOR_EMAIL", author.1) - .env("GIT_COMMITTER_NAME", author.0) - .env("GIT_COMMITTER_EMAIL", author.1) - .env("GIT_AUTHOR_DATE", &date) - .env("GIT_COMMITTER_DATE", &date) - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); -} - -const ALICE: (&str, &str) = ("Alice", "alice@mehen.invalid"); -const BOB: (&str, &str) = ("Bob", "bob@mehen.invalid"); -const CAROL: (&str, &str) = ("Carol", "carol@mehen.invalid"); - -/// Time-Weighted Risk term for one bug-fixing commit at `seconds`, -/// normalized over `[first, head]` (Lewis et al. logistic, ω = 12). -fn twr_term(seconds: i64, first: i64, head: i64) -> f64 { - let t = (seconds - first) as f64 / (head - first) as f64; - 1.0 / (1.0 + (-12.0 * t + 12.0).exp()) -} - -/// Fixture: -/// Jan (alice): add a.rs (3 lines) + b.rs (2 lines) "initial import" -/// Feb (alice): a.rs +2 lines "feat: expand a" -/// Mar (bob): a.rs rewrite 1 line (+1/−1) "fix: bug in a" -/// Apr (alice): b.rs +1 line "feat: more b" -/// May (carol): add c.rs (2 lines) on branch topic "fix typo" -/// Jun (alice): merge topic --no-ff "merge topic branch" -fn build_fixture(dir: &Path) { - git(dir, &["init", "-q", "-b", "main"], ALICE, T_JAN); - git(dir, &["config", "commit.gpgsign", "false"], ALICE, T_JAN); - - std::fs::write(dir.join("a.rs"), "fn a() {}\nfn b() {}\nfn c() {}\n").unwrap(); - std::fs::write(dir.join("b.rs"), "fn x() {}\nfn y() {}\n").unwrap(); - git(dir, &["add", "-A"], ALICE, T_JAN); - git(dir, &["commit", "-q", "-m", "initial import"], ALICE, T_JAN); - - std::fs::write( - dir.join("a.rs"), - "fn a() {}\nfn b() {}\nfn c() {}\nfn d() {}\nfn e() {}\n", - ) - .unwrap(); - git( - dir, - &["commit", "-q", "-am", "feat: expand a"], - ALICE, - T_FEB, - ); - - std::fs::write( - dir.join("a.rs"), - "fn a() {}\nfn b() {}\nfn c() {}\nfn d() {}\nfn e_fixed() {}\n", - ) - .unwrap(); - git(dir, &["commit", "-q", "-am", "fix: bug in a"], BOB, T_MAR); - - std::fs::write(dir.join("b.rs"), "fn x() {}\nfn y() {}\nfn z() {}\n").unwrap(); - git(dir, &["commit", "-q", "-am", "feat: more b"], ALICE, T_APR); - - git(dir, &["checkout", "-q", "-b", "topic"], CAROL, T_MAY); - std::fs::write(dir.join("c.rs"), "fn m() {}\nfn n() {}\n").unwrap(); - git(dir, &["add", "c.rs"], CAROL, T_MAY); - git(dir, &["commit", "-q", "-m", "fix typo"], CAROL, T_MAY); - - git(dir, &["checkout", "-q", "main"], ALICE, T_JUN); - git( - dir, - &[ - "merge", - "-q", - "--no-ff", - "--no-edit", - "-m", - "merge topic branch", - "topic", - ], - ALICE, - T_JUN, - ); -} - -#[test] -fn collect_history_computes_all_per_file_statistics() { - let dir = tempfile::tempdir().unwrap(); - build_fixture(dir.path()); - let repo = gix::discover(dir.path()).unwrap(); - - let history = collect_history(&repo, "HEAD").unwrap(); - - // "Now" is the head (merge) commit's committer time, not wall clock. - assert_eq!(history.head_seconds, T_JUN); - // a.rs, b.rs, c.rs — the merge commit itself contributes nothing. - assert_eq!(history.len(), 3); - - let a = history.file(Path::new("a.rs")).expect("a.rs history"); - assert_eq!(a.commit_frequency, 3); - assert_eq!(a.churn_added, 6); // 3 (add) + 2 (expand) + 1 (fix) - assert_eq!(a.churn_removed, 1); // 1 (fix) - assert_eq!(a.churn_abs(), 7); - assert_eq!(a.authors, 2); // alice, bob - // alice wrote 5 of 6 added lines (83%), bob 1 of 6 (17%): no minors. - // (Authorship counts added lines only — deletions aren't writing.) - assert_eq!(a.minor_contributors, 0); - assert!((a.ownership - 5.0 / 6.0).abs() < 1e-9); - assert_eq!(a.last_change_seconds, T_MAR); - // Only the initial 2-file commit couples a.rs with another file. - assert_eq!(a.sum_of_coupling, 1); - assert_eq!(a.bugfix_commits, 1); // "fix: bug in a" - let expected_twr = twr_term(T_MAR, T_JAN, T_JUN); - // TWR is quantized to 1e-9 before publication. - assert!((a.twr - expected_twr).abs() < 1e-9); - let expected_age = (T_JUN - T_MAR) as f64 / SECONDS_PER_MONTH; - assert!((a.age_months(history.head_seconds) - expected_age).abs() < 1e-9); - - let b = history.file(Path::new("b.rs")).expect("b.rs history"); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 3); // 2 (add) + 1 (more b) - assert_eq!(b.churn_removed, 0); - assert_eq!(b.authors, 1); - assert_eq!(b.minor_contributors, 0); - assert!((b.ownership - 1.0).abs() < 1e-9); - assert_eq!(b.last_change_seconds, T_APR); - assert_eq!(b.sum_of_coupling, 1); - assert_eq!(b.bugfix_commits, 0); - assert_eq!(b.twr, 0.0); - - let c = history.file(Path::new("c.rs")).expect("c.rs history"); - assert_eq!(c.commit_frequency, 1); - assert_eq!(c.churn_added, 2); - assert_eq!(c.churn_removed, 0); - assert_eq!(c.authors, 1); - assert!((c.ownership - 1.0).abs() < 1e-9); - assert_eq!(c.last_change_seconds, T_MAY); - assert_eq!(c.sum_of_coupling, 0); - assert_eq!(c.bugfix_commits, 1); // "fix typo" - let expected_twr = twr_term(T_MAY, T_JAN, T_JUN); - assert!((c.twr - expected_twr).abs() < 1e-9); -} - -#[test] -fn collect_history_is_rev_scoped_and_deterministic() { - let dir = tempfile::tempdir().unwrap(); - build_fixture(dir.path()); - let repo = gix::discover(dir.path()).unwrap(); - - // Walking an older rev must only see history up to that rev. - let at_march = collect_history(&repo, "HEAD~1^").unwrap(); - // HEAD~1 is the Apr commit (first parent of the merge); its parent - // is the Mar fix. c.rs does not exist there and b.rs has one commit. - assert_eq!(at_march.head_seconds, T_MAR); - assert!(at_march.file(Path::new("c.rs")).is_none()); - let b = at_march.file(Path::new("b.rs")).expect("b.rs history"); - assert_eq!(b.commit_frequency, 1); - - // Two walks of the same rev produce identical values. - let one = collect_history(&repo, "HEAD").unwrap(); - let two = collect_history(&repo, "HEAD").unwrap(); - for path in ["a.rs", "b.rs", "c.rs"] { - assert_eq!(one.file(Path::new(path)), two.file(Path::new(path))); - } -} - -#[test] -fn oversized_changesets_do_not_contribute_to_coupling() { - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - // Commit 1: hub.rs plus 31 filler files — a 32-file changeset, - // above the 30-file coupling noise threshold. - std::fs::write(dir.path().join("hub.rs"), "fn hub() {}\n").unwrap(); - for i in 0..31 { - std::fs::write(dir.path().join(format!("filler{i:02}.rs")), "fn f() {}\n").unwrap(); - } - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git( - dir.path(), - &["commit", "-q", "-m", "bulk import"], - ALICE, - T_JAN, - ); - - // Commit 2: hub.rs plus one filler — a qualifying 2-file changeset. - std::fs::write(dir.path().join("hub.rs"), "fn hub() {}\nfn spoke() {}\n").unwrap(); - std::fs::write(dir.path().join("filler00.rs"), "fn f() {}\nfn g() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "grow hub"], - ALICE, - T_FEB, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - let hub = history.file(Path::new("hub.rs")).expect("hub history"); - // The 32-file bulk import is ignored for coupling; only the 2-file - // commit counts (1 other file). Churn still counts both commits. - assert_eq!(hub.sum_of_coupling, 1); - assert_eq!(hub.commit_frequency, 2); - assert_eq!(hub.churn_added, 2); -} - -#[test] -fn blob_to_gitlink_type_change_does_not_fail_the_walk() { - // A checked-in file replaced by a submodule produces a - // `Modification` whose new mode is a gitlink (commit) pointing at - // an object that only exists in the submodule. Reading it as a - // blob would fail the whole walk; it must count as the old blob's - // deletion instead. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write(dir.path().join("dep"), "line one\nline two\n").unwrap(); - git(dir.path(), &["add", "dep"], ALICE, T_JAN); - git( - dir.path(), - &["commit", "-q", "-m", "vendor dep"], - ALICE, - T_JAN, - ); - - // Replace the blob with a gitlink to a commit absent from this - // repository's object database (the normal submodule situation). - std::fs::remove_file(dir.path().join("dep")).unwrap(); - git(dir.path(), &["rm", "-q", "--cached", "dep"], ALICE, T_FEB); - git( - dir.path(), - &[ - "update-index", - "--add", - "--cacheinfo", - "160000,1111111111111111111111111111111111111111,dep", - ], - ALICE, - T_FEB, - ); - git( - dir.path(), - &["commit", "-q", "-m", "switch dep to submodule"], - ALICE, - T_FEB, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").expect("walk must survive gitlink type change"); - - let dep = history.file(Path::new("dep")).expect("dep history"); - assert_eq!(dep.commit_frequency, 2); - assert_eq!(dep.churn_added, 2); // initial blob - assert_eq!(dep.churn_removed, 2); // blob → gitlink counts as its deletion - assert_eq!(dep.last_change_seconds, T_FEB); -} - -#[test] -fn renames_preserve_file_identity_and_history() { - // A rename must not split the file's history: the head-relative - // path keeps the pre-rename commits/churn/authors, a pure rename - // churns nothing, and a rename-with-edit churns only the edit. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - // pure.rs: 4 lines by alice, then renamed untouched by bob. - std::fs::write( - dir.path().join("pure.rs"), - "fn a() {}\nfn b() {}\nfn c() {}\nfn d() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "pure.rs"], ALICE, T_JAN); - git( - dir.path(), - &["commit", "-q", "-m", "add pure"], - ALICE, - T_JAN, - ); - git( - dir.path(), - &["mv", "pure.rs", "renamed_pure.rs"], - BOB, - T_FEB, - ); - git( - dir.path(), - &["commit", "-q", "-m", "rename pure"], - BOB, - T_FEB, - ); - - // edited.rs: 10 lines by alice, then renamed *and* edited (2 lines - // rewritten) by bob — 80% similar, above the 50% threshold. - let lines: Vec = (0..10).map(|i| format!("fn f{i}() {{}}")).collect(); - std::fs::write(dir.path().join("edited.rs"), lines.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "edited.rs"], ALICE, T_MAR); - git( - dir.path(), - &["commit", "-q", "-m", "add edited"], - ALICE, - T_MAR, - ); - let mut edited: Vec = lines.clone(); - edited[0] = "fn f0_changed() {}".to_string(); - edited[9] = "fn f9_changed() {}".to_string(); - std::fs::remove_file(dir.path().join("edited.rs")).unwrap(); - std::fs::write( - dir.path().join("renamed_edited.rs"), - edited.join("\n") + "\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, T_APR); - git( - dir.path(), - &["commit", "-q", "-m", "rename and tweak edited"], - BOB, - T_APR, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // No stale entries under the pre-rename paths. - assert!(history.file(Path::new("pure.rs")).is_none()); - assert!(history.file(Path::new("edited.rs")).is_none()); - - let pure = history - .file(Path::new("renamed_pure.rs")) - .expect("renamed_pure history"); - // Pre-rename history is carried over; the pure rename churns nothing. - assert_eq!(pure.commit_frequency, 2); - assert_eq!(pure.churn_added, 4); - assert_eq!(pure.churn_removed, 0); - assert_eq!(pure.authors, 2); // alice (4 lines) + bob (0 lines) - assert!((pure.ownership - 1.0).abs() < 1e-9); - assert_eq!(pure.last_change_seconds, T_FEB); - - let edited = history - .file(Path::new("renamed_edited.rs")) - .expect("renamed_edited history"); - // Creation (10 lines) plus only the two rewritten lines. - assert_eq!(edited.commit_frequency, 2); - assert_eq!(edited.churn_added, 12); - assert_eq!(edited.churn_removed, 2); - assert_eq!(edited.last_change_seconds, T_APR); -} - -#[test] -fn changed_files_joins_rename_pairs() { - // A rename between `from` and `to` must surface as one `Modified` - // entry carrying `source_path`, not a deletion + addition pair — - // otherwise diff consumers lose the baseline for both metric and - // history comparison. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write( - dir.path().join("before.rs"), - "fn a() {}\nfn b() {}\nfn c() {}\nfn d() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "rename-base"], ALICE, T_JAN); - - git(dir.path(), &["mv", "before.rs", "after.rs"], ALICE, T_FEB); - git(dir.path(), &["commit", "-q", "-m", "rename"], ALICE, T_FEB); - git(dir.path(), &["tag", "rename-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "rename-base", "rename-head").unwrap(); - - assert_eq!( - changed.len(), - 1, - "rename must be a single entry: {changed:?}" - ); - let cf = &changed[0]; - assert_eq!(cf.path, Path::new("after.rs")); - assert_eq!(cf.status, mehen_git::ChangeStatus::Modified); - assert_eq!(cf.source_path.as_deref(), Some(Path::new("before.rs"))); -} - -#[test] -fn rename_detection_ignores_diff_configuration_and_attributes() { - // Explicit rewrite options and a raw-object resource cache must - // make the result independent of repository/user diff settings. - // Marking Rust files as binary through attributes would suppress - // fuzzy matching in the porcelain-style resource pipeline. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - git( - dir.path(), - &["config", "diff.renames", "false"], - ALICE, - T_JAN, - ); - git( - dir.path(), - &["config", "diff.renameLimit", "1"], - ALICE, - T_JAN, - ); - git( - dir.path(), - &["config", "diff.algorithm", "minimal"], - ALICE, - T_JAN, - ); - - std::fs::write(dir.path().join(".gitattributes"), "*.rs -diff\n").unwrap(); - let lines: Vec = (0..10).map(|i| format!("fn f{i}() {{}}")).collect(); - std::fs::write(dir.path().join("before.rs"), lines.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "raw-diff-base"], ALICE, T_JAN); - - let mut edited = lines; - edited[0] = "fn f0_changed() {}".to_string(); - edited[9] = "fn f9_changed() {}".to_string(); - std::fs::remove_file(dir.path().join("before.rs")).unwrap(); - std::fs::write(dir.path().join("after.rs"), edited.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "rename and edit"], - ALICE, - T_FEB, - ); - git(dir.path(), &["tag", "raw-diff-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "raw-diff-base", "raw-diff-head").unwrap(); - - assert_eq!(changed.len(), 1, "rename must stay joined: {changed:?}"); - assert_eq!(changed[0].path, Path::new("after.rs")); - assert_eq!(changed[0].status, mehen_git::ChangeStatus::Modified); - assert_eq!( - changed[0].source_path.as_deref(), - Some(Path::new("before.rs")) - ); -} - -#[test] -fn changed_files_reports_type_changes_from_the_blob_side() { - // A blob replaced by a gitlink must surface as the blob's - // *deletion*, not a `Modified` row whose baseline/head reads would - // hit a gitlink OID absent from the superproject odb. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write(dir.path().join("dep.py"), "d = 1\nd2 = 2\n").unwrap(); - git(dir.path(), &["add", "dep.py"], ALICE, T_JAN); - git( - dir.path(), - &["commit", "-q", "-m", "vendor dep"], - ALICE, - T_JAN, - ); - git(dir.path(), &["tag", "type-base"], ALICE, T_JAN); - - std::fs::remove_file(dir.path().join("dep.py")).unwrap(); - git( - dir.path(), - &["rm", "-q", "--cached", "dep.py"], - ALICE, - T_FEB, - ); - git( - dir.path(), - &[ - "update-index", - "--add", - "--cacheinfo", - "160000,1111111111111111111111111111111111111111,dep.py", - ], - ALICE, - T_FEB, - ); - git( - dir.path(), - &["commit", "-q", "-m", "switch dep to submodule"], - ALICE, - T_FEB, - ); - git(dir.path(), &["tag", "type-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "type-base", "type-head").unwrap(); - - assert_eq!(changed.len(), 1, "one blob-side entry: {changed:?}"); - assert_eq!(changed[0].path, Path::new("dep.py")); - assert_eq!(changed[0].status, mehen_git::ChangeStatus::Deleted); - assert!(changed[0].source_path.is_none()); -} - -#[test] -fn parallel_branch_edits_before_a_rename_are_merged_into_the_survivor() { - // Branches diverge after a.rs is created; the side branch edits - // a.rs with a *later* timestamp than main's rename to b.rs. The - // newest-first walk therefore accumulates the edit under a.rs - // before it learns about the rename — that stranded accumulator - // must be folded into b.rs, not left behind. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "a.rs"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "add a"], ALICE, T_JAN); - - // Side branch: edit a.rs at T_MAR (after main's rename time). - git(dir.path(), &["checkout", "-q", "-b", "side"], BOB, T_MAR); - std::fs::write( - dir.path().join("a.rs"), - "fn a0_edited() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "edit a"], BOB, T_MAR); - - // Main: rename a.rs -> b.rs at T_FEB (before the side edit's time). - git(dir.path(), &["checkout", "-q", "main"], ALICE, T_FEB); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "rename a"], - ALICE, - T_FEB, - ); - - // Merge (git's own rename detection applies the edit to b.rs). - git( - dir.path(), - &[ - "merge", - "-q", - "--no-edit", - "-m", - "merge side branch", - "side", - ], - ALICE, - T_APR, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // No stranded entry under the pre-rename path. - assert!(history.file(Path::new("a.rs")).is_none()); - - let b = history.file(Path::new("b.rs")).expect("b.rs history"); - // Creation (4 lines, alice) + side edit (+1/−1, bob) + rename (0). - assert_eq!(b.commit_frequency, 3); - assert_eq!(b.churn_added, 5); - assert_eq!(b.churn_removed, 1); - assert_eq!(b.authors, 2); - assert_eq!(b.last_change_seconds, T_MAR); -} - -#[test] -fn changed_files_joins_renames_that_also_change_content() { - // Rename tracking must hold at the pinned 50% similarity - // threshold, not just for identical blobs: a rename that also - // edits a minority of lines stays a joined `Modified` row. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let lines: Vec = (0..10).map(|i| format!("fn f{i}() {{}}")).collect(); - std::fs::write(dir.path().join("orig.rs"), lines.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "edit-rename-base"], ALICE, T_JAN); - - // Rename plus a 2-of-10-line edit — 80% similar, above 50%. - let mut edited = lines.clone(); - edited[0] = "fn f0_changed() {}".to_string(); - edited[9] = "fn f9_changed() {}".to_string(); - std::fs::remove_file(dir.path().join("orig.rs")).unwrap(); - std::fs::write(dir.path().join("moved.rs"), edited.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "rename and edit"], - ALICE, - T_FEB, - ); - git(dir.path(), &["tag", "edit-rename-head"], ALICE, T_FEB); - - // A rewrite below 50% similarity must NOT pair: replace a second - // file wholesale under a new name. - std::fs::write(dir.path().join("old_impl.rs"), "fn tiny() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_MAR); - git(dir.path(), &["commit", "-q", "-m", "tiny"], ALICE, T_MAR); - git(dir.path(), &["tag", "dissimilar-base"], ALICE, T_MAR); - std::fs::remove_file(dir.path().join("old_impl.rs")).unwrap(); - std::fs::write( - dir.path().join("new_impl.rs"), - "fn completely() {}\nfn different() {}\nfn content() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_APR); - git(dir.path(), &["commit", "-q", "-m", "replace"], ALICE, T_APR); - git(dir.path(), &["tag", "dissimilar-head"], ALICE, T_APR); - - let repo = gix::discover(dir.path()).unwrap(); - - let changed = mehen_git::changed_files(&repo, "edit-rename-base", "edit-rename-head").unwrap(); - assert_eq!(changed.len(), 1, "80%-similar rename joins: {changed:?}"); - assert_eq!(changed[0].path, Path::new("moved.rs")); - assert_eq!(changed[0].status, mehen_git::ChangeStatus::Modified); - assert_eq!( - changed[0].source_path.as_deref(), - Some(Path::new("orig.rs")) - ); - - let changed = mehen_git::changed_files(&repo, "dissimilar-base", "dissimilar-head").unwrap(); - let mut statuses: Vec<(String, mehen_git::ChangeStatus)> = changed - .iter() - .map(|cf| (cf.path.display().to_string(), cf.status)) - .collect(); - statuses.sort_by(|a, b| a.0.cmp(&b.0)); - assert_eq!( - statuses, - vec![ - ("new_impl.rs".to_string(), mehen_git::ChangeStatus::Added), - ("old_impl.rs".to_string(), mehen_git::ChangeStatus::Deleted), - ], - "below-threshold rewrite must stay a deletion + addition" - ); -} - -#[test] -fn reused_source_path_keeps_its_own_history_after_a_rename() { - // Commit 1 adds a.rs, commit 2 renames it to b.rs, commit 3 adds a - // brand-new unrelated a.rs. The new a.rs must keep its own history - // instead of being folded into b.rs by the rename alias. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write( - dir.path().join("a.rs"), - "fn one() {}\nfn two() {}\nfn three() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "a.rs"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "add a"], ALICE, T_JAN); - - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "rename a"], - ALICE, - T_FEB, - ); - - std::fs::write(dir.path().join("a.rs"), "fn brand_new() {}\n").unwrap(); - git(dir.path(), &["add", "a.rs"], BOB, T_MAR); - git(dir.path(), &["commit", "-q", "-m", "new a"], BOB, T_MAR); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // The re-created a.rs keeps its own single-commit history. - let a = history.file(Path::new("a.rs")).expect("new a.rs history"); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 1); - assert_eq!(a.authors, 1); - assert_eq!(a.last_change_seconds, T_MAR); - - // b.rs carries the renamed lineage: the original creation (walked - // after the rename, redirected by the alias) plus the rename. - let b = history.file(Path::new("b.rs")).expect("b.rs history"); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 3); - assert_eq!(b.last_change_seconds, T_FEB); -} - -#[test] -fn single_line_file_renames_with_edits_stay_joined() { - // A one-line file has zero common *lines* after any edit; the - // byte-level similarity fallback must still join the rename so the - // diff keeps its baseline and history keeps its lineage. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let one_liner = format!("export const table = [{}];", "1, ".repeat(100)); - std::fs::write(dir.path().join("bundle.js"), &one_liner).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "oneline-base"], ALICE, T_JAN); - - // Rename plus a small in-line edit. - std::fs::remove_file(dir.path().join("bundle.js")).unwrap(); - std::fs::write( - dir.path().join("bundle.min.js"), - one_liner.replace("const table", "const lookup"), - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "rename bundle"], - ALICE, - T_FEB, - ); - git(dir.path(), &["tag", "oneline-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "oneline-base", "oneline-head").unwrap(); - assert_eq!(changed.len(), 1, "one-line rename joins: {changed:?}"); - assert_eq!(changed[0].path, Path::new("bundle.min.js")); - assert_eq!(changed[0].status, mehen_git::ChangeStatus::Modified); - assert_eq!( - changed[0].source_path.as_deref(), - Some(Path::new("bundle.js")) - ); -} - -#[test] -fn deletion_only_commits_do_not_create_minor_contributors() { - // bob's only touch is deleting lines: he counts as an author but - // must not appear as a sub-5% minor contributor, and ownership - // stays with the writer. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let lines: Vec = (0..10).map(|i| format!("fn f{i}() {{}}")).collect(); - std::fs::write(dir.path().join("code.rs"), lines.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git( - dir.path(), - &["commit", "-q", "-m", "write it"], - ALICE, - T_JAN, - ); - - // bob deletes the last four functions, adds nothing. - std::fs::write(dir.path().join("code.rs"), lines[..6].join("\n") + "\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "prune dead code"], - BOB, - T_FEB, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - let code = history.file(Path::new("code.rs")).expect("code history"); - assert_eq!(code.authors, 2); // alice wrote, bob touched - assert_eq!(code.minor_contributors, 0); // bob wrote nothing — not "minor" - assert!((code.ownership - 1.0).abs() < 1e-9); // alice owns all added lines - assert_eq!(code.churn_added, 10); - assert_eq!(code.churn_removed, 4); -} - -#[test] -fn changed_files_recovers_renames_hidden_behind_path_reuse() { - // Between base and head, a.rs was renamed to b.rs and an unrelated - // new a.rs was created. The endpoint tree diff sees Modified(a.rs) - // + Added(b.rs); break-rewrite detection must recover the real - // shape: b.rs is the rename of the old a.rs, the new a.rs is an - // addition. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let original: Vec = (0..8).map(|i| format!("fn original_{i}() {{}}")).collect(); - std::fs::write(dir.path().join("a.rs"), original.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "add a"], ALICE, T_JAN); - git(dir.path(), &["tag", "reuse-base"], ALICE, T_JAN); - - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "rename a"], - ALICE, - T_FEB, - ); - - std::fs::write( - dir.path().join("a.rs"), - "const REPLACEMENT: &str = \"totally unrelated\";\n", - ) - .unwrap(); - git(dir.path(), &["add", "a.rs"], BOB, T_MAR); - git(dir.path(), &["commit", "-q", "-m", "new a"], BOB, T_MAR); - git(dir.path(), &["tag", "reuse-head"], ALICE, T_MAR); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "reuse-base", "reuse-head").unwrap(); - - let mut summary: Vec<(String, mehen_git::ChangeStatus, Option)> = changed - .iter() - .map(|cf| { - ( - cf.path.display().to_string(), - cf.status, - cf.source_path.as_ref().map(|p| p.display().to_string()), - ) - }) - .collect(); - summary.sort_by(|a, b| a.0.cmp(&b.0)); - assert_eq!( - summary, - vec![ - ( - "a.rs".to_string(), - mehen_git::ChangeStatus::Added, - None // the new a.rs is genuinely new content - ), - ( - "b.rs".to_string(), - mehen_git::ChangeStatus::Modified, - Some("a.rs".to_string()) // carries the old lineage - ), - ] - ); -} - -#[test] -fn heavily_rewritten_files_stay_modified_when_nothing_pairs() { - // A same-path full rewrite with no rename candidates around must - // stay a single Modified row (the speculative break-rewrite is - // reassembled), not degrade into a deletion + addition. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write(dir.path().join("config.rs"), "fn old_world() {}\n").unwrap(); - // An unrelated addition so the break pass is actually exercised - // (it is skipped entirely when there is nothing to pair with). - std::fs::write(dir.path().join("unrelated.txt"), "notes\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "rewrite-base"], ALICE, T_JAN); - - std::fs::write( - dir.path().join("config.rs"), - "const COMPLETELY_DIFFERENT: u32 = 42;\n", - ) - .unwrap(); - std::fs::write(dir.path().join("second.txt"), "more notes\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git(dir.path(), &["commit", "-q", "-m", "rewrite"], ALICE, T_FEB); - git(dir.path(), &["tag", "rewrite-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "rewrite-base", "rewrite-head").unwrap(); - - let config: Vec<_> = changed - .iter() - .filter(|cf| cf.path == Path::new("config.rs")) - .collect(); - assert_eq!(config.len(), 1, "one row for config.rs: {changed:?}"); - assert_eq!(config[0].status, mehen_git::ChangeStatus::Modified); - assert!(config[0].source_path.is_none()); -} - -#[test] -fn identical_blob_renames_prefer_matching_basenames() { - // Two identical files swapped between directories: src/foo.rs → - // tests/foo.rs and tests/bar.rs → src/bar.rs. Pairing by - // lexicographic order would cross the lineages; gix's matching - // basename preference keeps each file with its own history. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let same_content = "fn shared() {}\nfn helper() {}\n"; - std::fs::create_dir_all(dir.path().join("src")).unwrap(); - std::fs::create_dir_all(dir.path().join("tests")).unwrap(); - std::fs::write(dir.path().join("src/foo.rs"), same_content).unwrap(); - std::fs::write(dir.path().join("tests/bar.rs"), same_content).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "swap-base"], ALICE, T_JAN); - - git( - dir.path(), - &["mv", "src/foo.rs", "tests/foo.rs"], - ALICE, - T_FEB, - ); - git( - dir.path(), - &["mv", "tests/bar.rs", "src/bar.rs"], - ALICE, - T_FEB, - ); - git(dir.path(), &["commit", "-q", "-m", "swap"], ALICE, T_FEB); - git(dir.path(), &["tag", "swap-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "swap-base", "swap-head").unwrap(); - - let source_of = |dest: &str| -> String { - changed - .iter() - .find(|cf| cf.path == Path::new(dest)) - .unwrap_or_else(|| panic!("missing {dest} in {changed:?}")) - .source_path - .as_ref() - .expect("rename must carry a source") - .display() - .to_string() - }; - assert_eq!(source_of("tests/foo.rs"), "src/foo.rs"); - assert_eq!(source_of("src/bar.rs"), "tests/bar.rs"); -} - -#[test] -fn binary_revisions_of_source_paths_churn_zero_lines() { - // A sub-cap binary revision (NUL bytes) of a tracked source path - // must not count its bytes as added/removed source lines. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write(dir.path().join("gen.rs"), "fn text() {}\nfn more() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "text"], ALICE, T_JAN); - - // Binary interlude: NUL-containing generated revision. - std::fs::write(dir.path().join("gen.rs"), b"\x00\x01\x02binary\ngarbage\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "binary blob"], - ALICE, - T_FEB, - ); - - // Back to parseable text. - std::fs::write(dir.path().join("gen.rs"), "fn text() {}\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "text again"], - ALICE, - T_MAR, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - let generated = history.file(Path::new("gen.rs")).expect("gen history"); - assert_eq!(generated.commit_frequency, 3); - // Only the initial text creation (2 lines) counts as added source; - // both binary-involving diffs churn zero (numstat-style). - assert_eq!(generated.churn_added, 2); - assert_eq!(generated.churn_removed, 0); -} - -#[test] -fn dead_path_reuse_after_rename_stays_out_of_the_lineage() { - // a.rs is renamed to b.rs; later an unrelated a.rs is created and - // deleted again before head. The temporary file's history must not - // be folded into b.rs even though a.rs is absent from the head - // tree. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write( - dir.path().join("a.rs"), - "fn one() {}\nfn two() {}\nfn three() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "a.rs"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "add a"], ALICE, T_JAN); - - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "rename a"], - ALICE, - T_FEB, - ); - - // Temporary unrelated reuse of the a.rs path, dead before head. - std::fs::write(dir.path().join("a.rs"), "fn temporary() {}\n").unwrap(); - git(dir.path(), &["add", "a.rs"], BOB, T_MAR); - git(dir.path(), &["commit", "-q", "-m", "temp a"], BOB, T_MAR); - git(dir.path(), &["rm", "-q", "a.rs"], BOB, T_APR); - git( - dir.path(), - &["commit", "-q", "-m", "remove temp a"], - BOB, - T_APR, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // b.rs carries only its own lineage: creation + rename by alice. - let b = history.file(Path::new("b.rs")).expect("b.rs history"); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 3); - assert_eq!(b.churn_removed, 0); - assert_eq!(b.authors, 1, "bob's dead temp file must not leak in"); - assert_eq!(b.last_change_seconds, T_FEB); -} - -#[test] -fn empty_blob_additions_and_deletions_do_not_pair_as_renames() { - // Deleting an empty old/a.rs while independently adding an empty - // new/b.rs must stay a deletion + addition: an empty blob carries - // no identity signal, and pairing would hand the new path the old - // path's baseline and history. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::create_dir_all(dir.path().join("old")).unwrap(); - std::fs::write(dir.path().join("old/a.rs"), "").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "empty-base"], ALICE, T_JAN); - - std::fs::remove_file(dir.path().join("old/a.rs")).unwrap(); - std::fs::create_dir_all(dir.path().join("new")).unwrap(); - std::fs::write(dir.path().join("new/b.rs"), "").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git(dir.path(), &["commit", "-q", "-m", "shuffle"], ALICE, T_FEB); - git(dir.path(), &["tag", "empty-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "empty-base", "empty-head").unwrap(); - - let mut summary: Vec<(String, mehen_git::ChangeStatus)> = changed - .iter() - .map(|cf| (cf.path.display().to_string(), cf.status)) - .collect(); - summary.sort_by(|a, b| a.0.cmp(&b.0)); - assert_eq!( - summary, - vec![ - ("new/b.rs".to_string(), mehen_git::ChangeStatus::Added), - ("old/a.rs".to_string(), mehen_git::ChangeStatus::Deleted), - ], - "empty blobs must not pair as renames" - ); - assert!(changed.iter().all(|cf| cf.source_path.is_none())); -} - -#[test] -fn exact_rename_ties_follow_gix_path_order() { - // Every source and destination has identical content and basename, - // so repository data cannot identify a uniquely correct pairing. - // Keep the deterministic path-order tie-break supplied by gix - // instead of layering a project-specific directory heuristic on it. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let same_content = "fn identical_everywhere() {}\n"; - for parent in ["src/a", "tests/b"] { - std::fs::create_dir_all(dir.path().join(parent)).unwrap(); - std::fs::write(dir.path().join(parent).join("foo.rs"), same_content).unwrap(); - } - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "affinity-base"], ALICE, T_JAN); - - for parent in ["src/a", "tests/b"] { - std::fs::remove_file(dir.path().join(parent).join("foo.rs")).unwrap(); - } - for parent in ["new", "src/c"] { - std::fs::create_dir_all(dir.path().join(parent)).unwrap(); - std::fs::write(dir.path().join(parent).join("foo.rs"), same_content).unwrap(); - } - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "reshuffle"], - ALICE, - T_FEB, - ); - git(dir.path(), &["tag", "affinity-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "affinity-base", "affinity-head").unwrap(); - - let source_of = |dest: &str| -> String { - changed - .iter() - .find(|cf| cf.path == Path::new(dest)) - .unwrap_or_else(|| panic!("missing {dest} in {changed:?}")) - .source_path - .as_ref() - .expect("rename must carry a source") - .display() - .to_string() - }; - assert_eq!(source_of("new/foo.rs"), "src/a/foo.rs"); - assert_eq!(source_of("src/c/foo.rs"), "tests/b/foo.rs"); -} - -#[test] -fn prior_occupants_of_a_rename_destination_stay_out_of_the_lineage() { - // An old b.rs existed and was deleted; later an unrelated a.rs is - // renamed onto the b.rs path. The current b.rs must carry only the - // a.rs lineage — not the dead prior occupant's commits. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - // Prior occupant of b.rs, by bob, dead by T_FEB. - std::fs::write(dir.path().join("b.rs"), "fn prior() {}\nfn occupant() {}\n").unwrap(); - git(dir.path(), &["add", "b.rs"], BOB, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "old b"], BOB, T_JAN); - git(dir.path(), &["rm", "-q", "b.rs"], BOB, T_FEB); - git( - dir.path(), - &["commit", "-q", "-m", "drop old b"], - BOB, - T_FEB, - ); - - // Unrelated a.rs lineage by alice, renamed onto the b.rs path. - std::fs::write( - dir.path().join("a.rs"), - "fn one() {}\nfn two() {}\nfn three() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "a.rs"], ALICE, T_MAR); - git(dir.path(), &["commit", "-q", "-m", "add a"], ALICE, T_MAR); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, T_APR); - git( - dir.path(), - &["commit", "-q", "-m", "rename a onto b"], - ALICE, - T_APR, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - let b = history.file(Path::new("b.rs")).expect("b.rs history"); - // Only the a.rs lineage: creation + rename, alice alone; bob's - // dead prior occupant (2 commits, 2 added + 2 removed lines) must - // not leak into the surviving file. - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 3); - assert_eq!(b.churn_removed, 0); - assert_eq!(b.authors, 1, "prior occupant's author must not leak in"); - assert_eq!(b.last_change_seconds, T_APR); -} - -#[test] -fn same_commit_content_swaps_are_reported_as_renames() { - // Swapping two files through a temporary name leaves the endpoint - // tree with two dissimilar Modified entries and no additions or - // deletions; the exact cross-match of their blobs must still be - // recovered as a pair of renames. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let first = "fn first_impl() {}\nfn first_helper() {}\n"; - let second = "const SECOND: &str = \"completely different\";\n"; - std::fs::write(dir.path().join("first.rs"), first).unwrap(); - std::fs::write(dir.path().join("second.rs"), second).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "content-swap-base"], ALICE, T_JAN); - - // Swap the contents (as `git mv` through a temp name would). - std::fs::write(dir.path().join("first.rs"), second).unwrap(); - std::fs::write(dir.path().join("second.rs"), first).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_FEB); - git(dir.path(), &["commit", "-q", "-m", "swap"], ALICE, T_FEB); - git(dir.path(), &["tag", "content-swap-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = - mehen_git::changed_files(&repo, "content-swap-base", "content-swap-head").unwrap(); - - let source_of = |dest: &str| -> String { - changed - .iter() - .find(|cf| cf.path == Path::new(dest)) - .unwrap_or_else(|| panic!("missing {dest} in {changed:?}")) - .source_path - .as_ref() - .unwrap_or_else(|| panic!("{dest} must be a rename in {changed:?}")) - .display() - .to_string() - }; - assert_eq!(source_of("first.rs"), "second.rs"); - assert_eq!(source_of("second.rs"), "first.rs"); -} - -#[test] -fn delete_then_recreate_without_rename_splits_the_lineage() { - // x.rs is written and edited by bob, deleted, then an unrelated - // x.rs is created by alice. The current file must not inherit the - // dead prior occupant's churn, authors, or commit count. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write(dir.path().join("x.rs"), "fn old() {}\n").unwrap(); - git(dir.path(), &["add", "x.rs"], BOB, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "old x"], BOB, T_JAN); - std::fs::write(dir.path().join("x.rs"), "fn old() {}\nfn more() {}\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow old x"], - BOB, - T_FEB, - ); - git(dir.path(), &["rm", "-q", "x.rs"], BOB, T_MAR); - git( - dir.path(), - &["commit", "-q", "-m", "drop old x"], - BOB, - T_MAR, - ); - - std::fs::write(dir.path().join("x.rs"), "const NEW_WORLD: u8 = 1;\n").unwrap(); - git(dir.path(), &["add", "x.rs"], ALICE, T_APR); - git(dir.path(), &["commit", "-q", "-m", "new x"], ALICE, T_APR); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - let x = history.file(Path::new("x.rs")).expect("x.rs history"); - assert_eq!(x.commit_frequency, 1); - assert_eq!(x.churn_added, 1); - assert_eq!(x.churn_removed, 0); - assert_eq!(x.authors, 1, "bob's dead occupant must not leak in"); - assert_eq!(x.last_change_seconds, T_APR); -} - -#[test] -fn same_commit_swaps_keep_each_lineage_with_its_content() { - // first.rs and second.rs exchange contents in one commit. Each - // current path must carry the history of the content now living - // there — and neither may end up empty or double-counted. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - // first.rs: 2 commits by alice; second.rs: 1 commit by bob. - std::fs::write(dir.path().join("first.rs"), "fn first() {}\n").unwrap(); - std::fs::write( - dir.path().join("second.rs"), - "const SECOND: &str = \"other\";\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - std::fs::write( - dir.path().join("first.rs"), - "fn first() {}\nfn first_more() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow first"], - ALICE, - T_FEB, - ); - - // Swap contents in one commit (as `git mv` via a temp name would). - let first_content = std::fs::read(dir.path().join("first.rs")).unwrap(); - let second_content = std::fs::read(dir.path().join("second.rs")).unwrap(); - std::fs::write(dir.path().join("first.rs"), &second_content).unwrap(); - std::fs::write(dir.path().join("second.rs"), &first_content).unwrap(); - git(dir.path(), &["commit", "-q", "-am", "swap"], BOB, T_MAR); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // second.rs now hosts the old first.rs content: 2 pre-swap commits - // + the swap = 3, with both authors. - let second = history.file(Path::new("second.rs")).expect("second"); - assert_eq!(second.commit_frequency, 3); - assert_eq!(second.authors, 2); - // first.rs now hosts the old second.rs content: 1 pre-swap commit - // + the swap = 2. - let first = history.file(Path::new("first.rs")).expect("first"); - assert_eq!(first.commit_frequency, 2); - assert_eq!(first.authors, 2); -} - -#[test] -fn renaming_back_to_an_old_path_reconnects_the_lineage() { - // a.rs → b.rs → a.rs: the file returns to its original path. The - // destination boundary installed by the return rename must not - // fence off the file's own pre-rename history. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write( - dir.path().join("a.rs"), - "fn one() {}\nfn two() {}\nfn three() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "a.rs"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "add a"], ALICE, T_JAN); - - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, T_FEB); - git(dir.path(), &["commit", "-q", "-m", "to b"], ALICE, T_FEB); - - git(dir.path(), &["mv", "b.rs", "a.rs"], BOB, T_MAR); - git(dir.path(), &["commit", "-q", "-m", "back to a"], BOB, T_MAR); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - let a = history.file(Path::new("a.rs")).expect("a.rs history"); - // Full lineage: creation + both renames. - assert_eq!(a.commit_frequency, 3); - assert_eq!(a.churn_added, 3, "the original creation must survive"); - assert_eq!(a.authors, 2); - assert_eq!(a.last_change_seconds, T_MAR); - assert!(history.file(Path::new("b.rs")).is_none()); -} - -#[test] -fn edited_swaps_are_recovered_as_renames() { - // Two files exchange paths *and* each picks up a small edit in the - // same commit — no exact OID cross-match exists, but each new blob - // is far more similar to the other path's baseline than to its - // own. Both must be reported as renames. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - let alpha: Vec = (0..10).map(|i| format!("fn alpha_{i}() {{}}")).collect(); - let omega: Vec = (0..10) - .map(|i| format!("const OMEGA_{i}: u8 = {i};")) - .collect(); - std::fs::write(dir.path().join("alpha.rs"), alpha.join("\n") + "\n").unwrap(); - std::fs::write(dir.path().join("omega.rs"), omega.join("\n") + "\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, T_JAN); - git(dir.path(), &["tag", "edited-swap-base"], ALICE, T_JAN); - - // Swap the contents and edit one line on each side. - let mut alpha_edited = alpha.clone(); - alpha_edited[0] = "fn alpha_0_edited() {}".to_string(); - let mut omega_edited = omega.clone(); - omega_edited[0] = "const OMEGA_0_EDITED: u8 = 0;".to_string(); - std::fs::write(dir.path().join("alpha.rs"), omega_edited.join("\n") + "\n").unwrap(); - std::fs::write(dir.path().join("omega.rs"), alpha_edited.join("\n") + "\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "edited swap"], - ALICE, - T_FEB, - ); - git(dir.path(), &["tag", "edited-swap-head"], ALICE, T_FEB); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "edited-swap-base", "edited-swap-head").unwrap(); - - let source_of = |dest: &str| -> String { - changed - .iter() - .find(|cf| cf.path == Path::new(dest)) - .unwrap_or_else(|| panic!("missing {dest} in {changed:?}")) - .source_path - .as_ref() - .unwrap_or_else(|| panic!("{dest} must be a rename in {changed:?}")) - .display() - .to_string() - }; - assert_eq!(source_of("alpha.rs"), "omega.rs"); - assert_eq!(source_of("omega.rs"), "alpha.rs"); -} - -#[test] -fn open_repo_at_reports_repo_not_found_only_outside_repositories() { - let dir = tempfile::tempdir().unwrap(); - match mehen_git::open_repo_at(dir.path()) { - Err(mehen_git::GitError::RepoNotFound) => {} - other => panic!("expected RepoNotFound outside a repository, got {other:?}"), - } -} - -#[test] -fn parallel_branch_deletion_does_not_split_a_surviving_lineage() { - // One branch edits x.rs (later timestamp) while another deletes it - // (earlier timestamp); the merge keeps the file. The newest-first - // walk sees the edit before the deletion — that deletion must not - // be mistaken for a delete-then-recreate boundary, or the shared - // creation and older edits would be fenced off the survivor. - let dir = tempfile::tempdir().unwrap(); - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, T_JAN); - git( - dir.path(), - &["config", "commit.gpgsign", "false"], - ALICE, - T_JAN, - ); - - std::fs::write( - dir.path().join("x.rs"), - "fn one() {}\nfn two() {}\nfn three() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "x.rs"], ALICE, T_JAN); - git(dir.path(), &["commit", "-q", "-m", "add x"], ALICE, T_JAN); - - // Side branch deletes x.rs at T_FEB (earlier timestamp). - git(dir.path(), &["checkout", "-q", "-b", "side"], BOB, T_FEB); - git(dir.path(), &["rm", "-q", "x.rs"], BOB, T_FEB); - git(dir.path(), &["commit", "-q", "-m", "drop x"], BOB, T_FEB); - - // Main edits x.rs at T_MAR (later timestamp, walked first). - git(dir.path(), &["checkout", "-q", "main"], ALICE, T_MAR); - std::fs::write( - dir.path().join("x.rs"), - "fn one_edited() {}\nfn two() {}\nfn three() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "edit x"], ALICE, T_MAR); - - // Merge keeps main's edited file (resolve the delete/modify - // conflict in favor of the surviving file). - let merge = std::process::Command::new("git") - .current_dir(dir.path()) - .args(["merge", "--no-commit", "side"]) - .env("GIT_AUTHOR_NAME", ALICE.0) - .env("GIT_AUTHOR_EMAIL", ALICE.1) - .env("GIT_COMMITTER_NAME", ALICE.0) - .env("GIT_COMMITTER_EMAIL", ALICE.1) - .env("GIT_AUTHOR_DATE", format!("{T_APR} +0000")) - .env("GIT_COMMITTER_DATE", format!("{T_APR} +0000")) - .output() - .expect("failed to run git merge"); - // The delete/modify conflict is expected; keep the modified file. - drop(merge); - git( - dir.path(), - &["checkout", "HEAD", "--", "x.rs"], - ALICE, - T_APR, - ); - git(dir.path(), &["add", "x.rs"], ALICE, T_APR); - git( - dir.path(), - &["commit", "-q", "-m", "merge side keeping x"], - ALICE, - T_APR, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - let x = history.file(Path::new("x.rs")).expect("x.rs history"); - // The survivor keeps its creation and edit; the parallel-branch - // deletion touch is also attributed here (it is lineage, not a - // boundary). Crucially the creation's 3 added lines survive. - assert!( - x.churn_added >= 4, - "creation (3) + edit (1) must survive, got {}", - x.churn_added - ); - assert!(x.commit_frequency >= 3); - assert_eq!(x.last_change_seconds, T_MAR); -} - -/// Tombstone identities live outside the path namespace: a real -/// repository file whose name matches the old in-namespace sentinel -/// (`\x01tombstone\x011`) must keep its own history even when the walk -/// fences off a dead prior occupant with tombstone #1. -#[test] -#[cfg(unix)] -fn tombstones_cannot_collide_with_real_control_byte_paths() { - let dir = tempfile::tempdir().unwrap(); - let weird = "\u{1}tombstone\u{1}1"; - git( - dir.path(), - &["init", "-q", "-b", "main"], - ALICE, - 1_700_000_000, - ); - - // c1: the control-byte-named file, plus a prior occupant of the - // future rename destination, plus the future rename source. - std::fs::write(dir.path().join(weird), "fn w0() {}\nfn w1() {}\n").unwrap(); - std::fs::write( - dir.path().join("dest.rs"), - "fn d0() {}\nfn d1() {}\nfn d2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("old.rs"), "fn o0() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, 1_700_000_000); - git( - dir.path(), - &["commit", "-q", "-m", "init"], - ALICE, - 1_700_000_000, - ); - - // c2: edit the control-byte file; remove the prior occupant. - std::fs::write( - dir.path().join(weird), - "fn w0() {}\nfn w1() {}\nfn w2() {}\n", - ) - .unwrap(); - git(dir.path(), &["rm", "-q", "dest.rs"], BOB, 1_700_100_000); - git(dir.path(), &["add", "-A"], BOB, 1_700_100_000); - git( - dir.path(), - &["commit", "-q", "-m", "edit and drop"], - BOB, - 1_700_100_000, - ); - - // c3: rename onto the freed path — installs a destination - // boundary, which allocates tombstone #1. - git( - dir.path(), - &["mv", "old.rs", "dest.rs"], - ALICE, - 1_700_200_000, - ); - git( - dir.path(), - &["commit", "-q", "-m", "rename"], - ALICE, - 1_700_200_000, - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // The control-byte file saw exactly its own two commits; with the - // old sentinel scheme the fenced-off `dest.rs` occupant (creation - // + deletion) would have been merged into it. - let weird_history = history.file(Path::new(weird)).unwrap(); - assert_eq!(weird_history.commit_frequency, 2); - assert_eq!(weird_history.churn_added, 3); - assert_eq!(weird_history.churn_removed, 0); - - // The survivor carries the rename-source lineage only. - let dest = history.file(Path::new("dest.rs")).unwrap(); - assert_eq!(dest.commit_frequency, 2); - assert_eq!(dest.churn_added, 1); -} - -/// A source path reused and renamed *again*: `a.rs → b.rs`, then an -/// unrelated `a.rs` is created and renamed to `c.rs`. The newest -/// rename's alias is consumed once the walk accumulates the reused -/// file's creation, so the older `a.rs → b.rs` rename must take the -/// alias over — the original lineage belongs to `b.rs`, not `c.rs`. -#[test] -fn older_rename_reclaims_a_source_path_reused_by_a_newer_rename() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1: the original file. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // c2: edit the original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - - // c3: the original moves to b.rs. - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "move to b"], - ALICE, - t(2), - ); - - // c4: an unrelated file reuses the a.rs path. - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "new a"], CAROL, t(3)); - - // c5: the reuse moves to c.rs. - git(dir.path(), &["mv", "a.rs", "c.rs"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "move to c"], - CAROL, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // b.rs carries the original lineage: creation, edit, rename. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 3); - assert_eq!(b.churn_added, 4); - - // c.rs carries only the reuse: creation and rename. - let c = history.file(Path::new("c.rs")).unwrap(); - assert_eq!(c.commit_frequency, 2); - assert_eq!(c.churn_added, 1); -} - -/// Delete, recreate, rename: the deletion (and everything older) at -/// the reused path belongs to a dead prior occupant and must not leak -/// into the rename survivor through the (already consumed) alias. -#[test] -fn deleted_occupant_of_a_reused_then_renamed_path_stays_fenced_off() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1 + c2: a prior occupant lives and grows at a.rs. - std::fs::write(dir.path().join("a.rs"), "fn old0() {}\nfn old1() {}\n").unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - std::fs::write( - dir.path().join("a.rs"), - "fn old0() {}\nfn old1() {}\nfn old2() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow old a"], - BOB, - t(1), - ); - - // c3: the occupant dies. - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], ALICE, t(2)); - - // c4: an unrelated file reuses the path. - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "new a"], CAROL, t(3)); - - // c5: the reuse moves to c.rs. - git(dir.path(), &["mv", "a.rs", "c.rs"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "move to c"], - CAROL, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // The survivor sees only the reuse's creation and rename — not - // the dead occupant's creation, edit, or deletion. - let c = history.file(Path::new("c.rs")).unwrap(); - assert_eq!(c.commit_frequency, 2); - assert_eq!(c.churn_added, 1); - assert_eq!(c.churn_removed, 0); - assert_eq!(c.authors, 1); - - // The dead occupant's history is fenced off behind a tombstone, - // not reported under the vacated path. - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// Run git and capture trimmed stdout (for plumbing that returns ids). -fn git_out(repo: &Path, args: &[&str], author: (&str, &str), seconds: i64) -> String { - let date = format!("{seconds} +0000"); - let output = std::process::Command::new("git") - .current_dir(repo) - .args(args) - .env("GIT_AUTHOR_NAME", author.0) - .env("GIT_AUTHOR_EMAIL", author.1) - .env("GIT_COMMITTER_NAME", author.0) - .env("GIT_COMMITTER_EMAIL", author.1) - .env("GIT_AUTHOR_DATE", &date) - .env("GIT_COMMITTER_DATE", &date) - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - String::from_utf8(output.stdout).unwrap().trim().to_string() -} - -/// One branch renames `a.rs → b.rs` and re-creates an unrelated -/// `a.rs`; a parallel branch edits the *original* `a.rs` before the -/// merge. Date order can walk both the re-creation and the parallel -/// edit before the rename — ancestry must split them: the re-creation -/// (a descendant of the rename) stays at `a.rs`, the concurrent edit -/// belongs to the renamed lineage at `b.rs`. -#[test] -fn parallel_edits_are_split_from_a_reused_rename_source() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1 (main): the original file. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - let c1 = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - // feature branch: rename a.rs → b.rs, then reuse the a.rs path. - git( - dir.path(), - &["checkout", "-q", "-b", "feature"], - ALICE, - t(1), - ); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "move to b"], - ALICE, - t(1), - ); - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git(dir.path(), &["commit", "-q", "-m", "reuse a"], CAROL, t(4)); - let feature = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // main (parallel): edit the original a.rs. - git(dir.path(), &["checkout", "-q", "main"], BOB, t(3)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\nfn a4() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(3)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(3)); - let _ = c1; - - // Merged tree, built directly to sidestep the rename/edit - // conflict: b.rs absorbs main's edit, the reused a.rs survives. - git(dir.path(), &["checkout", "-q", "feature"], ALICE, t(5)); - std::fs::write( - dir.path().join("b.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\nfn a4() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &feature, - "-p", - &main, - "-m", - "merge", - ], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = original creation (4 lines) + parallel edit (1 line) + - // the rename itself. The parallel edit must not stick to the - // reused a.rs path. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 3); - assert_eq!(b.churn_added, 5); - assert_eq!(b.authors, 2, "bob's parallel edit belongs to b.rs"); - - // a.rs = only the unrelated re-creation. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 1); - assert_eq!(a.authors, 1); -} - -/// A rename performed *by the merge commit itself* (conflict -/// resolution commits `a.rs` — present in both parents — as `b.rs`) -/// must install identity: without it the older commits accumulate -/// under the vacated `a.rs` while `b.rs` reads an empty history. The -/// merge still contributes no churn of its own. -#[test] -fn merge_commit_renames_establish_file_identity() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1: common ancestor. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // main: edit a.rs. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow on main"], - BOB, - t(1), - ); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // side branch from c1: a different edit to a.rs. - git( - dir.path(), - &["checkout", "-q", "-b", "side", "HEAD~1"], - CAROL, - t(2), - ); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn side() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow on side"], - CAROL, - t(2), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(2)); - - // The merge resolves the conflict by committing the file as b.rs - // (main's blob, so the tree diff sees an exact rename); a.rs is - // gone from the merged tree though both parents contain it. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(3)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(3)); - git(dir.path(), &["add", "-A"], ALICE, t(3)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(3)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(3), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs carries the full a.rs lineage: creation + both edits. The - // merge itself adds no commit and no churn. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 3); - assert_eq!(b.churn_added, 5); - assert_eq!(b.authors, 3); - - // Nothing is reported under the vacated path. - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// A commit that renames one file *over* another (`git mv -f a.rs -/// b.rs`) emits `Renamed(a → b)` plus `Deleted(b)` for the old -/// occupant. The deletion must land behind the destination boundary — -/// not in the surviving lineage, where its removed lines, author, and -/// commit would pollute the new `b.rs` history. -#[test] -fn rename_over_an_existing_file_fences_the_old_occupant() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1: two unrelated files. - std::fs::write( - dir.path().join("a.rs"), - "fn alpha0() {}\nfn alpha1() {}\nfn alpha2() {}\nfn alpha3() {}\nfn alpha4() {}\n", - ) - .unwrap(); - std::fs::write( - dir.path().join("b.rs"), - "fn beta0() {}\nfn beta1() {}\nfn beta2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // c2: a.rs replaces b.rs. - git(dir.path(), &["mv", "-f", "a.rs", "b.rs"], BOB, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "replace b with a"], - BOB, - t(1), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // b.rs = the a.rs lineage: creation (5 lines) + the rename. The - // old occupant's deletion (3 removed lines) is fenced off. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 5); - assert_eq!(b.churn_removed, 0, "old occupant's deletion leaked in"); - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// One branch renames `a.rs → b.rs`; a parallel branch deletes the -/// original `a.rs` and re-creates an unrelated file at that path; the -/// merge keeps both. Whatever the walk order, the surviving `a.rs` -/// must keep (only) its own history and the original lineage must -/// flow to `b.rs`. This variant walks the parallel branch *before* -/// the rename (its timestamps are newer). -#[test] -fn concurrent_delete_and_recreate_walked_before_the_rename() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // feature: the rename, with the *oldest* post-branch timestamp. - git( - dir.path(), - &["checkout", "-q", "-b", "feature"], - ALICE, - t(1), - ); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "move to b"], - ALICE, - t(1), - ); - let feature = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(1)); - - // main (parallel): delete the original, then reuse the path. - git(dir.path(), &["checkout", "-q", "main"], BOB, t(2)); - git(dir.path(), &["rm", "-q", "a.rs"], BOB, t(2)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], BOB, t(2)); - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "reuse a"], CAROL, t(3)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // Merged tree keeps both files. - git(dir.path(), &["checkout", "-q", "feature"], ALICE, t(4)); - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(4)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &feature, - "-p", - &main, - "-m", - "merge", - ], - ALICE, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The surviving a.rs is only the parallel re-creation. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 1); - assert_eq!(a.authors, 1); - - // b.rs owns the original lineage: creation, the parallel branch's - // deletion of the original (reclaimed from its fence when the - // rename explained where the file went), and the rename. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.churn_added, 3); - assert_eq!(b.commit_frequency, 3); -} - -/// Same topology as above, but the rename carries the *newest* -/// timestamp and is walked first — the parallel branch's re-creation -/// must then bypass the already-installed alias (it is concurrent -/// with the rename, not part of its pre-rename lineage). -#[test] -fn concurrent_delete_and_recreate_walked_after_the_rename() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // main (parallel): delete the original, then reuse the path — - // with *older* timestamps than the rename. - git(dir.path(), &["rm", "-q", "a.rs"], BOB, t(1)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], BOB, t(1)); - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(2)); - git(dir.path(), &["commit", "-q", "-m", "reuse a"], CAROL, t(2)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(2)); - - // feature from the root commit: the rename, newest timestamp. - git( - dir.path(), - &["checkout", "-q", "-b", "feature", "HEAD~2"], - ALICE, - t(3), - ); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "move to b"], - ALICE, - t(3), - ); - let feature = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(3)); - - // Merged tree keeps both files. - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(4)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &feature, - "-p", - &main, - "-m", - "merge", - ], - ALICE, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The surviving a.rs is only the parallel re-creation — the - // alias installed by the earlier-walked rename must not swallow - // a concurrent addition. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 1); - assert_eq!(a.authors, 1); - - // b.rs owns the original lineage: creation + rename. The - // concurrent deletion of the original stays fenced in this - // ordering (the fence postdates the already-walked rename). - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.churn_added, 3); - assert_eq!(b.commit_frequency, 2); -} - -/// A merge-introduced rename whose source exists only in a -/// *non-first* parent: the first-parent diff sees the destination as -/// a plain addition, so the merge diff must be taken against every -/// parent to pair the rename and install identity. -#[test] -fn merge_renames_of_non_first_parent_files_establish_identity() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1: common ancestor without the file. - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - // side branch: create and grow a.rs — main never has it. - git(dir.path(), &["checkout", "-q", "-b", "side"], BOB, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(1)); - git(dir.path(), &["commit", "-q", "-m", "add a"], BOB, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], CAROL, t(2)); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(2)); - - // The merge (first parent = main) commits side's file as b.rs; - // neither parent contains b.rs. - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(3)); - git(dir.path(), &["add", "-A"], ALICE, t(3)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(3)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(3), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs carries side's full a.rs lineage. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); - assert_eq!(b.authors, 2); - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// One commit renames `a → b` *and* creates a replacement `a`; the -/// replacement is later deleted and the path re-created. The -/// replacement's creation resolves into the later deletion's fence in -/// the same commit as the rename — that in-use fence must not be -/// reclaimed into `b`, and the fresh `a → b` alias must not be -/// mistaken for the entry the replacement consumed. -#[test] -fn same_commit_replacement_does_not_corrupt_the_rename_alias() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1: the original. - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // c2: rename to b.rs and create a replacement a.rs, one commit. - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(1)); - std::fs::write(dir.path().join("a.rs"), "fn repl0() {}\nfn repl1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "split a into b and new a"], - BOB, - t(1), - ); - - // c3: the replacement dies. - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "drop replacement"], - ALICE, - t(2), - ); - - // c4: an unrelated file re-creates the path. - std::fs::write(dir.path().join("a.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "reuse a"], CAROL, t(3)); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // b.rs = the original lineage only: creation + rename. Neither - // the replacement's churn nor its deletion may leak in. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 3); - assert_eq!(b.churn_removed, 0); - - // The final a.rs is only the last re-creation. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 1); - assert_eq!(a.authors, 1); -} - -/// Two branches rename the same source to different destinations and -/// the merge keeps both: each branch's pre-rename edits must route to -/// that branch's survivor (ancestry-scoped aliases), with the shared -/// pre-branch lineage counted once toward the first-walked rename. -#[test] -fn concurrent_renames_to_different_destinations_both_keep_their_edits() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c1: common ancestor. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // branch one: edit, then rename to b.rs. - git(dir.path(), &["checkout", "-q", "-b", "one"], BOB, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn b_edit() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "edit on one"], - BOB, - t(1), - ); - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(2)); - git(dir.path(), &["commit", "-q", "-m", "move to b"], BOB, t(2)); - let one = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(2)); - - // branch two: a different edit, then rename to c.rs — with newer - // timestamps, so its rename is walked first. - git( - dir.path(), - &["checkout", "-q", "-b", "two", "main"], - CAROL, - t(3), - ); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn c_edit0() {}\nfn c_edit1() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "edit on two"], - CAROL, - t(3), - ); - git(dir.path(), &["mv", "a.rs", "c.rs"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "move to c"], - CAROL, - t(4), - ); - let two = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // Merge keeps both survivors. - git(dir.path(), &["checkout", "-q", "one"], ALICE, t(5)); - std::fs::write( - dir.path().join("c.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn c_edit0() {}\nfn c_edit1() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &["commit-tree", &tree, "-p", &one, "-p", &two, "-m", "merge"], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // First-walked rename (two → c.rs, newest timestamps) gets the - // shared pre-branch lineage plus its own edit. - let c = history.file(Path::new("c.rs")).unwrap(); - assert_eq!(c.commit_frequency, 3); - assert_eq!(c.churn_added, 5); - - // The other survivor still owns its branch's pre-rename edit — - // previously the second-visited rename was rejected outright and - // this edit stayed keyed to the obsolete a.rs. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 1); - - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// Non-UTF-8 paths keep their raw bytes: `x\xff.py` must not collide -/// with a real file literally named `x\u{FFFD}.py` (the lossy -/// replacement of the invalid byte). -#[test] -#[cfg(unix)] -fn non_utf8_paths_do_not_collide_with_replacement_character_paths() { - use std::os::unix::ffi::OsStrExt; - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - git( - dir.path(), - &["config", "core.quotePath", "false"], - ALICE, - t(0), - ); - - let weird = std::ffi::OsStr::from_bytes(b"x\xff.py"); - let lookalike = "x\u{FFFD}.py"; - - // Not every Unix filesystem accepts non-UTF-8 names (macOS APFS - // rejects the invalid byte with EILSEQ): the collision scenario - // cannot exist there, so there is nothing to test. - if std::fs::write(dir.path().join(weird), "w0 = 1\nw1 = 2\n").is_err() { - return; - } - std::fs::write(dir.path().join(lookalike), "l0 = 1\nl1 = 2\nl2 = 3\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - std::fs::write( - dir.path().join(lookalike), - "l0 = 1\nl1 = 2\nl2 = 3\nl3 = 4\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow lookalike"], - BOB, - t(1), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // Each file reports exactly its own history — with lossy path - // conversion both would fold into one identity. - let w = history.file(Path::new(weird)).unwrap(); - assert_eq!(w.commit_frequency, 1); - assert_eq!(w.churn_added, 2); - - let l = history.file(Path::new(lookalike)).unwrap(); - assert_eq!(l.commit_frequency, 2); - assert_eq!(l.churn_added, 4); -} - -/// A merge that *creates* a file at a path absent from every parent -/// (conflict resolution) establishes a fresh identity: a dead prior -/// occupant of that path must stay fenced off instead of donating its -/// creation, edits, and deletion to the merge-created file. -#[test] -fn merge_created_additions_fence_dead_prior_occupants() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // The prior occupant lives and dies on main. - std::fs::write( - dir.path().join("victim.rs"), - "fn v0() {}\nfn v1() {}\nfn v2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - std::fs::write( - dir.path().join("victim.rs"), - "fn v0() {}\nfn v1() {}\nfn v2() {}\nfn v3() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow victim"], - BOB, - t(1), - ); - git(dir.path(), &["rm", "-q", "victim.rs"], ALICE, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "drop victim"], - ALICE, - t(2), - ); - - // A side branch, so the merge has two parents. - git(dir.path(), &["checkout", "-q", "-b", "side"], CAROL, t(3)); - std::fs::write(dir.path().join("side.rs"), "fn side() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "side work"], - CAROL, - t(3), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(4)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow keep"], - ALICE, - t(4), - ); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(4)); - - // The merge re-creates victim.rs — absent from both parents. - std::fs::write(dir.path().join("side.rs"), "fn side() {}\n").unwrap(); - std::fs::write( - dir.path().join("victim.rs"), - "fn reborn0() {}\nfn reborn1() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The dead occupant's creation, edit, and deletion must not be - // attributed to the merge-created file (which itself accumulates - // nothing — merge churn stays excluded). - assert!(history.file(Path::new("victim.rs")).is_none()); - - // Sanity: unrelated files keep their history. - assert_eq!( - history.file(Path::new("side.rs")).unwrap().commit_frequency, - 1 - ); -} - -/// Author identities preserve raw bytes: two emails differing only in -/// an invalid UTF-8 byte must stay two distinct authors — a lossy -/// conversion would collapse both to the same `U+FFFD` string. -#[test] -#[cfg(unix)] -fn non_utf8_author_emails_stay_distinct() { - use std::ffi::OsStr; - use std::os::unix::ffi::OsStrExt; - - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - let commit = |file_content: &str, msg: &str, email: &[u8], seconds: i64| { - std::fs::write(dir.path().join("a.py"), file_content).unwrap(); - let date = format!("{seconds} +0000"); - for args in [vec!["add", "-A"], vec!["commit", "-q", "-m", msg]] { - let output = std::process::Command::new("git") - .current_dir(dir.path()) - .args(&args) - .env("GIT_AUTHOR_NAME", "Weird") - .env("GIT_AUTHOR_EMAIL", OsStr::from_bytes(email)) - .env("GIT_COMMITTER_NAME", "Weird") - .env("GIT_COMMITTER_EMAIL", OsStr::from_bytes(email)) - .env("GIT_AUTHOR_DATE", &date) - .env("GIT_COMMITTER_DATE", &date) - .output() - .expect("failed to run git"); - assert!( - output.status.success(), - "git {args:?} failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - }; - - // Two identities differing only in the invalid byte: lossy - // conversion maps both to "a\u{FFFD}x@example.com". - commit("x = 1\n", "one", b"a\xffx@example.com", t(0)); - commit("x = 1\ny = 2\n", "two", b"a\xfex@example.com", t(1)); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - let a = history.file(Path::new("a.py")).unwrap(); - assert_eq!(a.commit_frequency, 2); - assert_eq!(a.authors, 2, "distinct non-UTF-8 emails collapsed"); - // Each contributed half the added lines: no 100% owner. - assert!( - (a.ownership - 0.5).abs() < 1e-9, - "ownership {}", - a.ownership - ); -} - -/// A merge that resolves a path by *deleting* it must still let the -/// delete-then-recreate boundary fire: when a later commit creates an -/// unrelated file at that path, the pre-merge occupant's history must -/// not leak into it. -#[test] -fn merge_performed_deletions_fence_recreated_paths() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // The occupant lives on main. - std::fs::write( - dir.path().join("p.rs"), - "fn p0() {}\nfn p1() {}\nfn p2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - std::fs::write( - dir.path().join("p.rs"), - "fn p0() {}\nfn p1() {}\nfn p2() {}\nfn p3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow p"], BOB, t(1)); - - // A side branch, so the merge has two parents. - git(dir.path(), &["checkout", "-q", "-b", "side"], CAROL, t(2)); - std::fs::write(dir.path().join("side.rs"), "fn side() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "side work"], - CAROL, - t(2), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(2)); - - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(3)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow keep"], - ALICE, - t(3), - ); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(3)); - - // The merge resolves p.rs away: present in both parents, absent - // from the merged tree. - git(dir.path(), &["rm", "-q", "p.rs"], ALICE, t(4)); - std::fs::write(dir.path().join("side.rs"), "fn side() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(4)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(4), - ); - git( - dir.path(), - &["update-ref", "refs/heads/main", &merge], - ALICE, - t(4), - ); - git(dir.path(), &["checkout", "-q", "-f", "main"], ALICE, t(4)); - - // A later commit reuses the path for an unrelated file. - std::fs::write(dir.path().join("p.rs"), "fn unrelated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(5)); - git(dir.path(), &["commit", "-q", "-m", "reuse p"], CAROL, t(5)); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // Only the re-creation: the pre-merge occupant's creation and - // edit stay fenced behind the merge-performed deletion. - let p = history.file(Path::new("p.rs")).unwrap(); - assert_eq!(p.commit_frequency, 1); - assert_eq!(p.churn_added, 1); - assert_eq!(p.authors, 1); -} - -/// A merge-introduced rename must be scoped to the parents whose -/// trees contain the source: with the merge commit as the scope, an -/// unrelated file that lived and died at the same path on *another* -/// parent's line would resolve through the alias and corrupt the -/// survivor's history. -#[test] -fn merge_rename_aliases_are_scoped_to_the_supplying_parent() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: common ancestor without a.rs. - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: the real file is born and grows (older timestamps, so - // this line is walked *after* the side branch). - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git(dir.path(), &["commit", "-q", "-m", "create a"], ALICE, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\nfn orig3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(2)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(2)); - - // side (from the root): an unrelated a.rs lives and dies — with - // *newer* timestamps, so it is walked before the merge's alias - // would find the real lineage. - git( - dir.path(), - &["checkout", "-q", "-b", "side", "HEAD~2"], - CAROL, - t(3), - ); - std::fs::write(dir.path().join("a.rs"), "fn other0() {}\nfn other1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "unrelated a"], - CAROL, - t(4), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(5)); - git( - dir.path(), - &["commit", "-q", "-m", "drop unrelated a"], - CAROL, - t(5), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(5)); - - // The merge resolves main's a.rs as b.rs (absent from both - // parents); a.rs is gone from the merged tree. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(6)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(6)); - git(dir.path(), &["add", "-A"], ALICE, t(6)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(6)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(6), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = main's lineage only: creation + growth. The side - // branch's unrelated file (2 commits, 2 added, 2 removed, carol) - // must not leak in nor consume the alias. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); - assert_eq!(b.churn_removed, 0); - assert_eq!(b.authors, 2, "only alice and bob touched the lineage"); -} - -/// Coupling cardinality counts every changed leaf path — a commit -/// touching one source file plus a symlink couples them, even though -/// the symlink carries no analyzable text. -#[test] -#[cfg(unix)] -fn coupling_counts_non_blob_changeset_members() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write(dir.path().join("code.rs"), "fn a() {}\n").unwrap(); - std::os::unix::fs::symlink("code.rs", dir.path().join("link")).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - - // Change both the file and the symlink target in one commit. - std::fs::write(dir.path().join("code.rs"), "fn a() {}\nfn b() {}\n").unwrap(); - std::fs::remove_file(dir.path().join("link")).unwrap(); - std::os::unix::fs::symlink("other", dir.path().join("link")).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "grow both"], - ALICE, - t(1), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // Each commit's changeset is {code.rs, link}: one coupled other - // per commit — previously the symlink was invisible and soc was 0. - let code = history.file(Path::new("code.rs")).unwrap(); - assert_eq!(code.sum_of_coupling, 2); -} - -/// A merge retains one parent's *independently created* `a.rs` while -/// moving the other parent's original to `b.rs`. The rename alias -/// must be scoped by lineage, not bare path existence: the retained -/// occupant's commits belong to the surviving `a.rs`, not to `b.rs`. -#[test] -fn merge_rename_scopes_exclude_independently_created_occupants() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: common ancestor without a.rs. - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: the original file (older timestamps — walked last). - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git(dir.path(), &["commit", "-q", "-m", "create a"], ALICE, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\nfn orig3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(2)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(2)); - - // indep (from the root, which never had a.rs): its own a.rs — - // newer timestamps, walked before main's line. - git( - dir.path(), - &["checkout", "-q", "-b", "indep", "HEAD~2"], - CAROL, - t(3), - ); - std::fs::write(dir.path().join("a.rs"), "fn own0() {}\nfn own1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git(dir.path(), &["commit", "-q", "-m", "own a"], CAROL, t(4)); - std::fs::write( - dir.path().join("a.rs"), - "fn own0() {}\nfn own1() {}\nfn own2() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow own a"], - CAROL, - t(5), - ); - let indep = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(5)); - - // The merge keeps indep's a.rs and moves main's original to b.rs. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(6)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(6)); - std::fs::write( - dir.path().join("a.rs"), - "fn own0() {}\nfn own1() {}\nfn own2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(6)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(6)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &indep, - "-m", - "merge", - ], - ALICE, - t(6), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = the original lineage only. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); - assert_eq!(b.authors, 2, "only alice and bob wrote the original"); - - // The surviving a.rs keeps the independent creator's history. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 2); - assert_eq!(a.churn_added, 3); - assert_eq!(a.authors, 1, "carol's file stays carol's"); -} - -/// Merge-only identity changes count as touches: one merge's conflict -/// resolution deletes a tracked path and a later merge restores it -/// with the original blob — the endpoint trees are byte-identical and -/// no non-merge commit touched the path, yet the head history now -/// treats the file as a fresh zero-touch identity with different age, -/// churn, and frequency. `range_touched_files` must surface it. -#[test] -fn range_touched_files_include_merge_only_identity_changes() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write(dir.path().join("a.py"), "x = 1\n").unwrap(); - std::fs::write(dir.path().join("keep.py"), "k = 1\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - let root = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - // First diamond: the merge's tree drops a.py. - git(dir.path(), &["checkout", "-q", "-b", "one"], BOB, t(1)); - std::fs::write(dir.path().join("keep.py"), "k = 1\nk2 = 2\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "side one"], BOB, t(1)); - let side1 = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - git(dir.path(), &["rm", "-q", "a.py"], BOB, t(2)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(2)); - let m1 = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &root, - "-p", - &side1, - "-m", - "resolution drops a.py", - ], - BOB, - t(2), - ); - - // Second diamond off m1: the merge's tree restores a.py verbatim. - git(dir.path(), &["checkout", "-q", &m1], ALICE, t(3)); - git(dir.path(), &["checkout", "-q", "-b", "two"], ALICE, t(3)); - std::fs::write(dir.path().join("f2.py"), "f = 1\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(3)); - git(dir.path(), &["commit", "-q", "-m", "side two"], ALICE, t(3)); - let side2 = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(3)); - std::fs::write(dir.path().join("a.py"), "x = 1\n").unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(4)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(4)); - let m2 = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &m1, - "-p", - &side2, - "-m", - "resolution restores a.py", - ], - BOB, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let touched = mehen_git::range_touched_files(&repo, &root, &m2).unwrap(); - assert!( - touched.contains(&std::path::PathBuf::from("a.py")), - "merge-only identity change must count as a touch: {touched:?}" - ); -} - -/// A transient blob life inside the range must not promote a path -/// that is a symlink at both endpoints: there is no analyzable text -/// to hang a diff row on. -#[test] -#[cfg(unix)] -fn range_touched_files_require_blob_endpoints() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write(dir.path().join("real.py"), "x = 1\n").unwrap(); - std::os::unix::fs::symlink("real.py", dir.path().join("alias.py")).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, t(0)); - git(dir.path(), &["tag", "sym-base"], ALICE, t(0)); - - // The symlink briefly becomes a regular file… - std::fs::remove_file(dir.path().join("alias.py")).unwrap(); - std::fs::write(dir.path().join("alias.py"), "y = 2\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "materialize"], - ALICE, - t(1), - ); - - // …and is restored. - std::fs::remove_file(dir.path().join("alias.py")).unwrap(); - std::os::unix::fs::symlink("real.py", dir.path().join("alias.py")).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(2)); - git(dir.path(), &["commit", "-q", "-m", "restore"], ALICE, t(2)); - git(dir.path(), &["tag", "sym-head"], ALICE, t(2)); - - let repo = gix::discover(dir.path()).unwrap(); - let touched = mehen_git::range_touched_files(&repo, "sym-base", "sym-head").unwrap(); - assert!( - touched.is_empty(), - "symlink-at-both-endpoints paths must not surface: {touched:?}" - ); -} - -/// A parent that deleted and *recreated* the source path after the -/// merge base must be excluded from a merge rename's scopes when the -/// merge retains its recreated version at the path: the retained -/// occupant survives where it is, and its commits must not resolve -/// into the rename target nor consume the alias. -#[test] -fn merge_rename_scopes_exclude_retained_delete_and_recreate_occupants() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original a.rs exists at the (future) merge base. - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: grow the original (older timestamps — walked last). - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\nfn orig3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // dr branch (from the base): delete the original, recreate an - // unrelated file at the path — newer timestamps, walked first. - git( - dir.path(), - &["checkout", "-q", "-b", "dr", "HEAD~1"], - CAROL, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], CAROL, t(3)); - std::fs::write(dir.path().join("a.rs"), "fn own0() {}\nfn own1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate a"], - CAROL, - t(4), - ); - let dr = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge keeps dr's a.rs and moves main's original to b.rs. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(5)); - std::fs::write(dir.path().join("a.rs"), "fn own0() {}\nfn own1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &["commit-tree", &tree, "-p", &main, "-p", &dr, "-m", "merge"], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = the original lineage: root creation + main's growth. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); - assert_eq!(b.churn_removed, 0); - - // The surviving a.rs is only carol's recreation; her deletion of - // the original stays fenced. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 2); - assert_eq!(a.authors, 1); -} - -/// A merge replacing a symlink with a regular blob at the same path -/// creates a *new* file identity: an older regular file that occupied -/// the path before it became a symlink stays fenced instead of -/// donating its history to the merge-created blob. -#[test] -#[cfg(unix)] -fn merge_created_blob_over_symlink_fences_the_old_occupant() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // The old regular occupant lives and grows… - std::fs::write(dir.path().join("alias.py"), "old0 = 1\nold1 = 2\n").unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "init"], ALICE, t(0)); - std::fs::write( - dir.path().join("alias.py"), - "old0 = 1\nold1 = 2\nold2 = 3\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow"], BOB, t(1)); - - // …then the path becomes a symlink. - std::fs::remove_file(dir.path().join("alias.py")).unwrap(); - std::os::unix::fs::symlink("keep.rs", dir.path().join("alias.py")).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "symlinkify"], - ALICE, - t(2), - ); - - // A side branch so the merge has two parents (both hold the - // symlink). - git(dir.path(), &["checkout", "-q", "-b", "side"], CAROL, t(3)); - std::fs::write(dir.path().join("side.rs"), "fn side() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "side"], CAROL, t(3)); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(4)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "grow keep"], - ALICE, - t(4), - ); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(4)); - - // The merge replaces the symlink with a brand-new regular blob. - std::fs::remove_file(dir.path().join("alias.py")).unwrap(); - std::fs::write(dir.path().join("alias.py"), "reborn = 1\n").unwrap(); - std::fs::write(dir.path().join("side.rs"), "fn side() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The merge-created blob inherits nothing from the pre-symlink - // occupant (its creation, growth, and blob-side deletion at the - // symlinkify commit all stay fenced). - assert!(history.file(Path::new("alias.py")).is_none()); - assert_eq!( - history.file(Path::new("side.rs")).unwrap().commit_frequency, - 1 - ); -} - -/// A parent whose delete-and-recreated `a.rs` is retained by the -/// merge *with conflict-resolution edits* (so its blob differs from -/// the parent's) must still be excluded from the rename scopes: a -/// surviving blob at the source path means the moved lineage is the -/// supplier's alone. -#[test] -fn merge_rename_scopes_exclude_edited_retained_occupants() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original a.rs exists at the (future) merge base. - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: grow the original (older timestamps — walked last). - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\nfn orig3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // dr branch: delete + recreate an unrelated file at the path. - git( - dir.path(), - &["checkout", "-q", "-b", "dr", "HEAD~1"], - CAROL, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], CAROL, t(3)); - std::fs::write(dir.path().join("a.rs"), "fn own0() {}\nfn own1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate a"], - CAROL, - t(4), - ); - let dr = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge keeps dr's recreation *with an extra edit* (blob no - // longer byte-identical to dr's) and moves main's original. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(5)); - std::fs::write( - dir.path().join("a.rs"), - "fn own0() {}\nfn own1() {}\nfn merged_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &["commit-tree", &tree, "-p", &main, "-p", &dr, "-m", "merge"], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = the original lineage only. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); - assert_eq!(b.churn_removed, 0); - - // The surviving a.rs keeps carol's recreation. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 2); - assert_eq!(a.authors, 1); -} - -/// Two branches rename the shared base file differently and the merge -/// commits the survivor under a third name: both intermediate-path -/// lineages must converge on the survivor instead of the second -/// pairing being dropped. -#[test] -fn converging_merge_renames_preserve_every_parent_lineage() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the shared original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: rename to x.rs and edit it. - git(dir.path(), &["mv", "a.rs", "x.rs"], ALICE, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "move to x"], - ALICE, - t(1), - ); - std::fs::write( - dir.path().join("x.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn x_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow x"], BOB, t(2)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(2)); - - // side: rename to y.rs and edit it differently. - git( - dir.path(), - &["checkout", "-q", "-b", "side", "HEAD~2"], - CAROL, - t(3), - ); - git(dir.path(), &["mv", "a.rs", "y.rs"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "move to y"], - CAROL, - t(3), - ); - std::fs::write( - dir.path().join("y.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn y_edit0() {}\nfn y_edit1() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow y"], CAROL, t(4)); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge commits the survivor as z.rs (main's blob, exact for - // the x-side pairing; y pairs by similarity). - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - git(dir.path(), &["mv", "x.rs", "z.rs"], ALICE, t(5)); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // z.rs carries the shared creation, both renames, and both - // branches' edits — the y-side lineage must not be stranded. - let z = history.file(Path::new("z.rs")).unwrap(); - assert_eq!(z.commit_frequency, 5); - assert_eq!(z.churn_added, 6); - assert_eq!(z.authors, 3); - assert!(history.file(Path::new("x.rs")).is_none()); - assert!(history.file(Path::new("y.rs")).is_none()); -} - -/// A merge rename onto a destination another parent already owns: -/// conflict resolution carries the `a.rs` lineage into the merged -/// `b.rs` (content from `a.rs`, not the retained parent blob). The -/// alias must install — and without a destination boundary, so the -/// owning parent's legitimate `b.rs` history keeps converging. -#[test] -fn merge_renames_onto_parent_owned_destinations_install_identity() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: common ancestor. - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: a.rs is born and grows. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git(dir.path(), &["commit", "-q", "-m", "create a"], ALICE, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(2)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(2)); - - // side: an unrelated b.rs is born. - git( - dir.path(), - &["checkout", "-q", "-b", "side", "HEAD~2"], - CAROL, - t(3), - ); - std::fs::write(dir.path().join("b.rs"), "fn b_own() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git(dir.path(), &["commit", "-q", "-m", "create b"], CAROL, t(4)); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge resolves a.rs *into* b.rs: the merged b.rs holds - // main's a.rs content (≠ side's b.rs blob), and a.rs is gone. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(5)); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs absorbs both lineages: a.rs's creation + growth (via the - // alias) and side's own b.rs creation (no boundary fences it). - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 3); - assert_eq!(b.churn_added, 5); - assert_eq!(b.authors, 3); - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// A parent that deleted the base file and re-created an unrelated -/// one — whose re-creation the merge then *discards* — must not enter -/// the rename scopes: path existence at the merge base is not -/// lineage continuity. -#[test] -fn merge_rename_scopes_exclude_discarded_recreated_sources() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original a.rs exists at the (future) merge base. - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: grow the original (older timestamps — walked last). - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\nfn orig3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // dr branch: delete + recreate an unrelated file (newer - // timestamps — walked first). - git( - dir.path(), - &["checkout", "-q", "-b", "dr", "HEAD~1"], - CAROL, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], CAROL, t(3)); - std::fs::write(dir.path().join("a.rs"), "fn own0() {}\nfn own1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate a"], - CAROL, - t(4), - ); - let dr = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge discards the recreation entirely and moves main's - // original to b.rs — no blob survives at a.rs. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(5)); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &["commit-tree", &tree, "-p", &main, "-p", &dr, "-m", "merge"], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = the original lineage only: the discarded recreation's - // commits must neither route into it nor consume the alias. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); - assert_eq!(b.churn_removed, 0); - assert_eq!(b.authors, 2); -} - -/// A branch that deletes the base file and re-creates it with -/// byte-identical contents still crossed an identity boundary: -/// endpoint blobs cannot see the interruption, so the range walk -/// must — the parent stays out of the rename scopes. -#[test] -fn merge_rename_scopes_detect_exact_recreations_via_range_boundaries() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - let base_content = "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\n"; - std::fs::write(dir.path().join("a.rs"), base_content).unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: grow the original (older timestamps — walked last). - std::fs::write( - dir.path().join("a.rs"), - "fn orig0() {}\nfn orig1() {}\nfn orig2() {}\nfn orig3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // dr branch: delete, then recreate with the *exact base bytes*. - git( - dir.path(), - &["checkout", "-q", "-b", "dr", "HEAD~1"], - CAROL, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(3)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], CAROL, t(3)); - std::fs::write(dir.path().join("a.rs"), base_content).unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate a exactly"], - CAROL, - t(4), - ); - let dr = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge discards the recreation and moves main's original. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(5)); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &["commit-tree", &tree, "-p", &main, "-p", &dr, "-m", "merge"], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = the original lineage only; the byte-identical recreation - // neither routes into it nor consumes the alias (which would - // strand the shared pre-branch history). - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); - assert_eq!(b.authors, 2); -} - -/// A destination the merge keeps *and edits*: the merged blob is no -/// longer byte-identical to the owning parent's, but it continues -/// that parent's file — a similar discarded source must not be -/// declared the winner and merged into it. -#[test] -fn merge_retention_recognizes_edited_destinations() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: common ancestor. - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: b.rs is born and grows. - std::fs::write( - dir.path().join("b.rs"), - "fn s0() {}\nfn s1() {}\nfn s2() {}\nfn s3() {}\nfn s4() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git(dir.path(), &["commit", "-q", "-m", "create b"], ALICE, t(1)); - std::fs::write( - dir.path().join("b.rs"), - "fn s0() {}\nfn s1() {}\nfn s2() {}\nfn s3() {}\nfn s4() {}\nfn s5() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow b"], BOB, t(2)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(2)); - - // side: a similar a.rs (shares the five s-lines). - git( - dir.path(), - &["checkout", "-q", "-b", "side", "HEAD~2"], - CAROL, - t(3), - ); - std::fs::write( - dir.path().join("a.rs"), - "fn s0() {}\nfn s1() {}\nfn s2() {}\nfn s3() {}\nfn s4() {}\nfn a_extra() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "create similar a"], - CAROL, - t(4), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge keeps main's b.rs with a conflict-resolution edit and - // discards a.rs entirely. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - std::fs::write( - dir.path().join("b.rs"), - "fn s0() {}\nfn s1() {}\nfn s2() {}\nfn s3() {}\nfn s4() {}\nfn s5() {}\nfn merged() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs = its own two commits; the discarded similar a.rs must not - // be merged into it. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.authors, 2, "the discarded a.rs leaked into b.rs"); - - // The discarded file keeps its own record under its own path. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); -} - -/// A merge that renames one parent's `a.rs` *and* deletes another -/// parent's unrelated occupant of the same path: the unscoped -/// parent's deletion still needs its merge-time fence, or a -/// post-merge recreation inherits the dead occupant's history. -#[test] -fn merge_deletions_on_unscoped_parents_still_fence() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: common ancestor without a.rs. - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // main: the real a.rs. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git(dir.path(), &["commit", "-q", "-m", "create a"], ALICE, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(2)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(2)); - - // side (from the root): an unrelated occupant of the same path. - git( - dir.path(), - &["checkout", "-q", "-b", "side", "HEAD~2"], - CAROL, - t(3), - ); - std::fs::write(dir.path().join("a.rs"), "fn other0() {}\nfn other1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "unrelated a"], - CAROL, - t(4), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // The merge moves main's a.rs to b.rs and drops side's occupant. - git(dir.path(), &["checkout", "-q", "main"], ALICE, t(5)); - git(dir.path(), &["mv", "a.rs", "b.rs"], ALICE, t(5)); - git(dir.path(), &["add", "-A"], ALICE, t(5)); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge", - ], - ALICE, - t(5), - ); - git( - dir.path(), - &["update-ref", "refs/heads/main", &merge], - ALICE, - t(5), - ); - git(dir.path(), &["checkout", "-q", "-f", "main"], ALICE, t(5)); - - // A later commit reuses the path. - std::fs::write(dir.path().join("a.rs"), "fn reborn() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(6)); - git(dir.path(), &["commit", "-q", "-m", "reuse a"], ALICE, t(6)); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // The recreated a.rs owns only its own commit — side's dead - // occupant stays fenced behind the merge deletion. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.commit_frequency, 1); - assert_eq!(a.churn_added, 1); - assert_eq!(a.authors, 1); - - // b.rs still owns main's lineage. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.commit_frequency, 2); - assert_eq!(b.churn_added, 4); -} - -/// A candidate parent whose merge *kept* its own uninterrupted copy -/// while a merged-in side branch deleted the path: the side deletion -/// is not the candidate's identity boundary, and the candidate's -/// parallel edits must still follow the rename. -#[test] -fn side_branch_deletions_do_not_disqualify_uninterrupted_parents() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the shared original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Candidate branch P: edit a.rs, then merge a side branch that - // deleted it — resolving to keep P's own copy. - git(dir.path(), &["checkout", "-q", "-b", "p"], CAROL, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "edit on p"], - CAROL, - t(1), - ); - let p_edit = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(1)); - - git( - dir.path(), - &["checkout", "-q", "-b", "s", "main"], - ALICE, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "side deletes a"], - ALICE, - t(2), - ); - let side_del = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(2)); - - // Merge s into p, keeping p's a.rs (first parent = p's edit). - git(dir.path(), &["checkout", "-q", "p"], CAROL, t(3)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - let p_tree = git_out(dir.path(), &["write-tree"], CAROL, t(3)); - let p_tip = git_out( - dir.path(), - &[ - "commit-tree", - &p_tree, - "-p", - &p_edit, - "-p", - &side_del, - "-m", - "keep p's a", - ], - CAROL, - t(3), - ); - - // main (supplier): unrelated work with newer timestamps; the - // rename itself happens in the final merge (conflict resolution). - git(dir.path(), &["checkout", "-q", "main"], BOB, t(4)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow keep"], BOB, t(4)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(4)); - - // Final merge: conflict resolution commits the file as b.rs - // (p's edited content, so the parallel edit visibly survives) and - // vacates a.rs. - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(5)); - std::fs::write( - dir.path().join("b.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(5)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &p_tip, - "-m", - "merge", - ], - BOB, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // Carol's parallel edit belongs to the surviving b.rs: the side - // branch's deletion (kept out by p's merge) must not disqualify - // p from the rename scopes. b.rs = shared creation (3 lines, - // alice) + carol's edit (1 line) + the side deletion touch. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.churn_added, 4, "carol's parallel edit must reach b.rs"); - assert_eq!(b.authors, 2, "alice and carol touched the lineage"); -} - -/// A non-supplier parent that is itself a merge: its first-parent -/// line keeps `a.rs` uninterrupted, but a side branch merged into it -/// deleted and recreated the path. The recreation is an ancestor of -/// the scoped parent, yet it must not resolve through the rename -/// alias (the addition floor keeps additions pre-divergence). -#[test] -fn recreations_on_merged_side_branches_do_not_consume_merge_aliases() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the shared original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Candidate branch P: keeps a.rs on its own line but merges a - // side branch that deleted and recreated it (P's merge keeps P's - // copy). - git(dir.path(), &["checkout", "-q", "-b", "p"], CAROL, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "edit on p"], - CAROL, - t(1), - ); - let p_edit = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(1)); - - git( - dir.path(), - &["checkout", "-q", "-b", "s", "main"], - CAROL, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "s drops a"], - CAROL, - t(2), - ); - std::fs::write(dir.path().join("a.rs"), "fn recreated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "s recreates a"], - CAROL, - t(3), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // P merges s, keeping P's own copy. - git(dir.path(), &["checkout", "-q", "p"], CAROL, t(4)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - let p_tree = git_out(dir.path(), &["write-tree"], CAROL, t(4)); - let p_tip = git_out( - dir.path(), - &[ - "commit-tree", - &p_tree, - "-p", - &p_edit, - "-p", - &side, - "-m", - "keep p's a", - ], - CAROL, - t(4), - ); - - // main: unrelated work; the rename happens in the final merge. - git(dir.path(), &["checkout", "-q", "main"], BOB, t(5)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow keep"], BOB, t(5)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(5)); - - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(6)); - std::fs::write( - dir.path().join("b.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(6)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(6)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &p_tip, - "-m", - "merge", - ], - BOB, - t(6), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs: shared creation (3) + p's edit (1). The side branch's - // recreated file must neither add its churn nor consume the alias - // (which would strand the shared creation under a.rs). The side's - // *deletion* of the original is a lineage touch and legitimately - // counts toward the survivor's removed churn. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.churn_added, 4, "recreation leaked or alias consumed"); - assert_eq!(b.churn_removed, 3); - - // The recreation is a discarded occupant, fenced at the inner - // merge rather than reported under the vacated path. - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// The recreated occupant on a merged side branch was also *edited* -/// before being discarded: those edits are walked before the -/// recreation and initially route through the alias — discovering the -/// floor-gated birth must pull them back to the occupant's identity. -#[test] -fn recreated_occupant_edits_are_pulled_back_from_merge_aliases() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the shared original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Candidate branch P: edits a.rs on its own line. - git(dir.path(), &["checkout", "-q", "-b", "p"], CAROL, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "edit on p"], - CAROL, - t(1), - ); - let p_edit = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(1)); - - // Side branch: delete, recreate, then *edit* the recreation. - git( - dir.path(), - &["checkout", "-q", "-b", "s", "main"], - CAROL, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "s drops a"], - CAROL, - t(2), - ); - std::fs::write(dir.path().join("a.rs"), "fn recreated() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "s recreates a"], - CAROL, - t(3), - ); - std::fs::write( - dir.path().join("a.rs"), - "fn recreated() {}\nfn recreated_more() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "s grows recreation"], - CAROL, - t(4), - ); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(4)); - - // P merges s, keeping P's own copy. - git(dir.path(), &["checkout", "-q", "p"], CAROL, t(5)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(5)); - let p_tree = git_out(dir.path(), &["write-tree"], CAROL, t(5)); - let p_tip = git_out( - dir.path(), - &[ - "commit-tree", - &p_tree, - "-p", - &p_edit, - "-p", - &side, - "-m", - "keep p's a", - ], - CAROL, - t(5), - ); - - // main: unrelated work; the rename happens in the final merge. - git(dir.path(), &["checkout", "-q", "main"], BOB, t(6)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow keep"], BOB, t(6)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(6)); - - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(7)); - std::fs::write( - dir.path().join("b.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(7)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(7)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &p_tip, - "-m", - "merge", - ], - BOB, - t(7), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // b.rs: shared creation (3) + p's edit (1). Neither the recreated - // occupant's birth nor its later edit may stick to the survivor. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!( - b.churn_added, 4, - "the recreated occupant's edits leaked into the survivor" - ); - - // The discarded occupant's whole lineage (recreation + edit) is - // fenced at the inner merge rather than reported under the - // vacated path. - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// A few bytes inserted near the start of a renamed long single-line -/// file: content-defined similarity chunking must keep the rename -/// joined (fixed-offset chunking alone would shift every span -/// boundary and collapse the similarity). -#[test] -fn single_line_renames_survive_small_insertions() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // ~900 bytes of varied single-line content (no newline until the - // end), so gear cuts fire at content-defined positions. - let body: String = (0..100).map(|i| format!("tok{i:04}x")).collect(); - std::fs::write(dir.path().join("bundle.min.js"), format!("{body}\n")).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "base"], ALICE, t(0)); - git(dir.path(), &["tag", "ins-base"], ALICE, t(0)); - - // Rename + insert a few bytes near the beginning. - git( - dir.path(), - &["mv", "bundle.min.js", "bundle.v2.min.js"], - BOB, - t(1), - ); - std::fs::write( - dir.path().join("bundle.v2.min.js"), - format!("INSERTED;{body}\n"), - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "rename + insert"], - BOB, - t(1), - ); - git(dir.path(), &["tag", "ins-head"], BOB, t(1)); - - let repo = gix::discover(dir.path()).unwrap(); - let changed = mehen_git::changed_files(&repo, "ins-base", "ins-head").unwrap(); - assert_eq!(changed.len(), 1, "rename must stay joined: {changed:?}"); - assert_eq!( - changed[0].path, - std::path::PathBuf::from("bundle.v2.min.js") - ); - assert_eq!( - changed[0].source_path.as_deref(), - Some(Path::new("bundle.min.js")) - ); - - // And the history walk keeps one lineage across the rename. - let history = collect_history(&repo, "ins-head").unwrap(); - let fh = history.file(Path::new("bundle.v2.min.js")).unwrap(); - assert_eq!(fh.commit_frequency, 2); -} - -/// A candidate parent that is itself a merge which kept its *second* -/// parent's retained copy while its first-parent line deleted the -/// path: the boundary scan must follow the lineage that supplies the -/// candidate's blob, not blindly the first parent. -#[test] -fn boundary_scan_follows_the_blob_supplying_parent() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the shared original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // p1: deletes a.rs (will be the candidate merge's *first* parent). - git(dir.path(), &["checkout", "-q", "-b", "p1"], CAROL, t(1)); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "p1 drops a"], - CAROL, - t(1), - ); - let p1 = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(1)); - - // p2: retains and edits a.rs. - git( - dir.path(), - &["checkout", "-q", "-b", "p2", "main"], - CAROL, - t(2), - ); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p2_edit() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "p2 edits a"], - CAROL, - t(2), - ); - let p2 = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(2)); - - // The candidate merge keeps p2's blob (first parent = p1!). - git(dir.path(), &["checkout", "-q", "p2"], CAROL, t(3)); - let p_tree = git_out(dir.path(), &["write-tree"], CAROL, t(3)); - let p_tip = git_out( - dir.path(), - &[ - "commit-tree", - &p_tree, - "-p", - &p1, - "-p", - &p2, - "-m", - "keep p2's a", - ], - CAROL, - t(3), - ); - - // main: unrelated work; the rename happens in the final merge. - git(dir.path(), &["checkout", "-q", "main"], BOB, t(4)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow keep"], BOB, t(4)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(4)); - - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(5)); - std::fs::write( - dir.path().join("b.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p2_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(5)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(5)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &p_tip, - "-m", - "merge", - ], - BOB, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // Carol's retained-lineage edit must follow the rename: the first - // parent's deletion is not the supplying lineage's boundary. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!( - b.churn_added, 4, - "the retained second-parent lineage was disqualified" - ); -} - -/// The candidate merge *edits* the blob its second parent supplied -/// (no parent matches exactly), while its first-parent line deleted -/// and re-created the path with unrelated content: the boundary scan -/// must follow the similarity-continuing parent, not the first -/// parent that happens to hold any blob. -#[test] -fn boundary_scan_follows_edited_blobs_by_similarity() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the shared original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // p1 (the candidate merge's *first* parent): delete, then - // recreate with unrelated content. - git(dir.path(), &["checkout", "-q", "-b", "p1"], CAROL, t(1)); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "p1 drops a"], - CAROL, - t(1), - ); - std::fs::write(dir.path().join("a.rs"), "fn own0() {}\nfn own1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "p1 recreates a"], - CAROL, - t(2), - ); - let p1 = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(2)); - - // p2: retains and edits the original. - git( - dir.path(), - &["checkout", "-q", "-b", "p2", "main"], - CAROL, - t(3), - ); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p2_edit() {}\n", - ) - .unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "p2 edits a"], - CAROL, - t(3), - ); - let p2 = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // The candidate merge keeps p2's lineage *with an extra edit* - // (matching no parent blob exactly); first parent is p1. - git(dir.path(), &["checkout", "-q", "p2"], CAROL, t(4)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p2_edit() {}\nfn merge_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(4)); - let p_tree = git_out(dir.path(), &["write-tree"], CAROL, t(4)); - let p_tip = git_out( - dir.path(), - &[ - "commit-tree", - &p_tree, - "-p", - &p1, - "-p", - &p2, - "-m", - "keep p2's a, edited", - ], - CAROL, - t(4), - ); - - // main: unrelated work; the rename happens in the final merge. - git(dir.path(), &["checkout", "-q", "-f", "main"], BOB, t(5)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn more() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow keep"], BOB, t(5)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(5)); - - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(6)); - std::fs::write( - dir.path().join("b.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn p2_edit() {}\nfn merge_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(6)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(6)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &p_tip, - "-m", - "merge", - ], - BOB, - t(6), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // Carol's retained-lineage edit follows the rename: neither p1's - // unrelated recreation nor its deletion flip may disqualify the - // candidate whose blob continues through p2. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!( - b.churn_added, 4, - "the edited merge blob was traced through the wrong parent" - ); -} - -/// A merge keeps one parent's original `a.rs` while another parent's -/// line deleted and recreated an unrelated `a.rs` that the merge -/// discards — with no introduced rename or addition. The discarded -/// occupant still needs a fence: its recreation must not accumulate -/// under the live path, and its deletion must not fence the shared -/// pre-branch creation away from the survivor. -#[test] -fn discarded_same_path_recreations_are_fenced_at_merges() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Retaining branch: grows the original. - git(dir.path(), &["checkout", "-q", "-b", "retain"], BOB, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn kept_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let retain = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // Discard branch: delete, then recreate unrelated content — - // *newer* timestamps, so its commits walk before the retainer's. - git( - dir.path(), - &["checkout", "-q", "-b", "discard", "main"], - ALICE, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], ALICE, t(2)); - std::fs::write(dir.path().join("a.rs"), "fn own0() {}\nfn own1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate a"], - CAROL, - t(3), - ); - let discard = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // The merge keeps the retaining parent's blob at a.rs. - git(dir.path(), &["checkout", "-q", "-f", "retain"], BOB, t(4)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &retain, - "-p", - &discard, - "-m", - "keep the original", - ], - BOB, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The survivor keeps its full lineage — creation, growth, and the - // discard branch's deletion touch — and nothing of the discarded - // recreation (whose author carol must not appear). - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.churn_added, 4, "the shared creation was fenced away"); - assert_eq!(a.commit_frequency, 3); - assert_eq!(a.authors, 2, "the discarded occupant leaked in"); -} - -/// The discarded branch's recreation *resembles* the survivor -/// (≥ 50% similar): endpoint similarity alone would classify it as a -/// continuation, but the deletion on that branch's line is an -/// identity boundary and the fence must still install. -#[test] -fn similar_discarded_recreations_are_still_fenced_at_merges() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Retaining branch: grows the original. - git(dir.path(), &["checkout", "-q", "-b", "retain"], BOB, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\nfn kept_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let retain = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // Discard branch: delete, then recreate with *similar* content - // (three of four original lines survive — well above the rename - // threshold). Newer timestamps: walked before the retainer. - git( - dir.path(), - &["checkout", "-q", "-b", "discard", "main"], - ALICE, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], ALICE, t(2)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn imposter() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate similar a"], - CAROL, - t(3), - ); - let discard = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // The merge keeps the retaining parent's blob. - git(dir.path(), &["checkout", "-q", "-f", "retain"], BOB, t(4)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &retain, - "-p", - &discard, - "-m", - "keep the original", - ], - BOB, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The survivor keeps its full lineage; carol's similar-but- - // recreated file stays fenced (its creation must neither appear - // here nor fence away the shared root creation). - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.churn_added, 5, "the shared creation was fenced away"); - assert_eq!(a.authors, 2, "the similar recreation leaked in"); -} - -/// The discarded branch's recreation is *byte-identical* to the blob -/// the merge keeps: neither parent-to-merge diff mentions the path at -/// all (exact OID equality removes it from both diffs), so no -/// `Modified` entry exists to hang a fence on. The recreated -/// occupant's line still ends at the deletion boundary — its -/// recreation must not accumulate under the survivor, and its -/// deletion must not fence the shared root creation away. -#[test] -fn exact_content_discarded_recreations_are_fenced_at_merges() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Retaining branch: grows the original. - git(dir.path(), &["checkout", "-q", "-b", "retain"], BOB, t(1)); - let grown = "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\nfn kept_edit() {}\n"; - std::fs::write(dir.path().join("a.rs"), grown).unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let retain = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // Discard branch: delete, then recreate with content byte-equal - // to the retainer's grown blob — the exact OID match erases the - // path from both parent-to-merge diffs. Newer timestamps: walked - // before the retainer. - git( - dir.path(), - &["checkout", "-q", "-b", "discard", "main"], - ALICE, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], ALICE, t(2)); - std::fs::write(dir.path().join("a.rs"), grown).unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate a byte-identical"], - CAROL, - t(3), - ); - let discard = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // The merge keeps the retaining parent's blob. - git(dir.path(), &["checkout", "-q", "-f", "retain"], BOB, t(4)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &retain, - "-p", - &discard, - "-m", - "keep the original", - ], - BOB, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The survivor keeps its full lineage; carol's byte-identical - // recreation stays on its own dead line (its creation must - // neither appear here nor fence away the shared root creation). - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.churn_added, 5, "the shared creation was fenced away"); - assert_eq!(a.authors, 2, "the identical recreation leaked in"); -} - -/// The hardest discarded-recreation shape: the surviving parent left -/// the path *untouched* since the divergence, and the discarded -/// branch recreated it byte-identical to that original — base, both -/// parent endpoints, and the merged tree all hold one OID, so no tree -/// pair anywhere can see the recreation. Only the walk knows: the -/// deletion is bypassed by a merge whose other parent carried the -/// blob over an uninterrupted line, so the recreation belongs to a -/// dead occupant and the shared creation stays with the survivor. -#[test] -fn revert_style_discarded_recreations_are_fenced_at_merges() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original. - let original = "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n"; - std::fs::write(dir.path().join("a.rs"), original).unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Retaining branch: unrelated work only — a.rs stays untouched. - git(dir.path(), &["checkout", "-q", "-b", "retain"], BOB, t(1)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn keep2() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow keep"], BOB, t(1)); - let retain = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // Discard branch: delete, then restore the original bytes — - // invisible to every endpoint diff. Newer timestamps: walked - // before the retainer. - git( - dir.path(), - &["checkout", "-q", "-b", "discard", "main"], - ALICE, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], ALICE, t(2)); - std::fs::write(dir.path().join("a.rs"), original).unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "restore a verbatim"], - CAROL, - t(3), - ); - let discard = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // The merge keeps the retaining parent's tree. - git(dir.path(), &["checkout", "-q", "-f", "retain"], BOB, t(4)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &retain, - "-p", - &discard, - "-m", - "keep the original", - ], - BOB, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The survivor keeps the shared creation and the discard branch's - // deletion touch; carol's verbatim restoration stays on its dead - // line. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.churn_added, 4, "the shared creation was fenced away"); - assert_eq!(a.authors, 1, "the verbatim restoration leaked in"); - assert_eq!(a.commit_frequency, 2, "creation + deletion touch"); -} - -/// A merge rename whose *supplier* deleted and recreated the source -/// after the divergence, while another parent retained the original: -/// the alias must stay supplier-only. Widening to the retaining -/// parent (whose endpoint blob does continue the base) would set an -/// addition floor that rejects the supplier's actual recreation — -/// stranding its edits under the vanished source — and route the -/// retained original into the rename target. -#[test] -fn merge_rename_scopes_stay_supplier_only_when_the_supplier_recreated_the_source() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Retaining branch: unrelated work; a.rs keeps the original. - git(dir.path(), &["checkout", "-q", "-b", "retain"], BOB, t(1)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn keep2() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow keep"], BOB, t(1)); - let retain = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // Mover branch: delete the original, recreate something unrelated - // at the same path. Newer timestamps: walked before the retainer. - git( - dir.path(), - &["checkout", "-q", "-b", "mover", "main"], - ALICE, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], ALICE, t(2)); - git(dir.path(), &["commit", "-q", "-m", "drop a"], ALICE, t(2)); - std::fs::write( - dir.path().join("a.rs"), - "fn n0() {}\nfn n1() {}\nfn n2() {}\nfn n3() {}\nfn n4() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "recreate a"], - CAROL, - t(3), - ); - let mover = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // The merge renames the *recreation* to b.rs (the merged tree has - // no a.rs): the mover's diff pairs `a.rs → b.rs` exactly, so the - // mover is the supplier. - git(dir.path(), &["checkout", "-q", "-f", "mover"], BOB, t(4)); - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(4)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(4)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &retain, - "-p", - &mover, - "-m", - "rename the recreation", - ], - BOB, - t(4), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The survivor is carol's recreation, moved: exactly its own - // churn (5 lines) — not the 4-line root creation the retaining - // parent held. - let b = history.file(Path::new("b.rs")).unwrap(); - assert_eq!(b.churn_added, 5, "the recreation's edits were stranded"); - assert_eq!(b.authors, 1, "the retained original leaked into b.rs"); - assert_eq!(b.commit_frequency, 1); - assert!(history.file(Path::new("a.rs")).is_none()); -} - -/// `--allow-unrelated-histories`: the merged parents have no merge -/// base, so two similar same-path blobs cannot share a lineage — -/// endpoint similarity proves nothing. The discarded parent's -/// independently created occupant must be fenced (with no floor: -/// there is no shared pre-branch history to protect). -#[test] -fn unrelated_history_merges_fence_similar_discarded_occupants() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // Main line: the survivor. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - // Orphan line: an unrelated root whose a.rs happens to be ≥50% - // similar. Newer timestamps: walked before the main line. - git( - dir.path(), - &["checkout", "-q", "--orphan", "other"], - CAROL, - t(1), - ); - git(dir.path(), &["rm", "-rfq", "."], CAROL, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn imposter() {}\n", - ) - .unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "unrelated root"], - CAROL, - t(1), - ); - let other = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(1)); - - // The merge keeps the main parent's tree. - git(dir.path(), &["checkout", "-q", "-f", "main"], BOB, t(2)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(2)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &other, - "-m", - "merge unrelated histories", - ], - BOB, - t(2), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The survivor keeps only its own line; carol's independent - // occupant stays fenced despite the endpoint similarity. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.churn_added, 4, "the unrelated occupant leaked in"); - assert_eq!(a.authors, 1, "the unrelated occupant's author leaked in"); - assert_eq!(a.commit_frequency, 1); -} - -/// Unrelated histories whose roots hold *byte-identical* same-path -/// blobs: exact OID equality erases the path from every -/// parent-to-merge diff, and there is no merge base to diff a parent -/// against — only the merged-tree enumeration pass can see the -/// duplicate. Without its fence both root additions would accumulate -/// under the surviving path, doubling churn and frequency and merging -/// unrelated authorship. -#[test] -fn unrelated_history_merges_fence_byte_identical_occupants() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // Main line: the survivor. - let content = "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn a3() {}\n"; - std::fs::write(dir.path().join("a.rs"), content).unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - // Orphan line: an unrelated root with the exact same bytes at the - // same path. Newer timestamp: walked before the main line. - git( - dir.path(), - &["checkout", "-q", "--orphan", "other"], - CAROL, - t(1), - ); - git(dir.path(), &["rm", "-rfq", "."], CAROL, t(1)); - std::fs::write(dir.path().join("a.rs"), content).unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "unrelated identical root"], - CAROL, - t(1), - ); - let other = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(1)); - - // The merge keeps the main parent's tree. - git(dir.path(), &["checkout", "-q", "-f", "main"], BOB, t(2)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(2)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &other, - "-m", - "merge unrelated histories", - ], - BOB, - t(2), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // One creation, one author, one commit — not two of each. - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.churn_added, 4, "the identical unrelated root leaked in"); - assert_eq!(a.authors, 1, "unrelated authorship was merged"); - assert_eq!(a.commit_frequency, 1, "commit frequency was doubled"); -} - -/// A renamed symlink is one changed identity, not two changeset -/// members: the tree diff reports it as a non-blob deletion plus a -/// non-blob addition, and counting both would inflate every other -/// file's coupling in the same commit. -#[test] -#[cfg(unix)] -fn symlink_renames_count_once_in_coupling_cardinality() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write(dir.path().join("a.py"), "x = 1\n").unwrap(); - std::os::unix::fs::symlink("a.py", dir.path().join("alias.py")).unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // One commit: edit a.py and rename the symlink. The changeset has - // two identities (the file, the moved link) — a.py's coupling - // must read 1, not 2. - git(dir.path(), &["mv", "alias.py", "alias2.py"], ALICE, t(1)); - std::fs::write(dir.path().join("a.py"), "x = 1\ny = 2\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "edit + move link"], - ALICE, - t(1), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - let a = history.file(Path::new("a.py")).unwrap(); - // Root commit: a.py + symlink = 1 other; edit commit: a.py + - // moved symlink = 1 other. A double-counted rename would read 3. - assert_eq!( - a.sum_of_coupling, 2, - "the symlink rename was counted as two changeset members" - ); -} - -/// A blob created purely by merge conflict resolution — never touched -/// by any walked non-merge commit — is *tracked with an all-zero -/// history*, not unmeasurable: `tracked_file` must return a zero -/// entry (rankable as legitimately calm) rather than `None` (which -/// reads as an untracked file and renders every history column -/// `n/a`). -#[test] -fn merge_created_untouched_blobs_read_zero_history_not_none() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write(dir.path().join("a.rs"), "fn a() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - let main = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - git(dir.path(), &["checkout", "-q", "-b", "side"], BOB, t(1)); - std::fs::write(dir.path().join("b.rs"), "fn b() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(1)); - git(dir.path(), &["commit", "-q", "-m", "side"], BOB, t(1)); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // The merge tree carries a file absent from both parents — - // conflict-resolution-created. - std::fs::write(dir.path().join("merge_only.rs"), "fn m() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(2)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(2)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &main, - "-p", - &side, - "-m", - "merge with new file", - ], - BOB, - t(2), - ); - - // Advance HEAD past the merge without touching the merge-created - // blob: its age must measure from the *creating merge*, not read - // an eternal zero pinned to whatever HEAD is now. - git(dir.path(), &["checkout", "-q", &merge], ALICE, t(3)); - git(dir.path(), &["checkout", "-q", "-b", "after"], ALICE, t(3)); - std::fs::write(dir.path().join("a.rs"), "fn a() {}\nfn a2() {}\n").unwrap(); - git( - dir.path(), - &["commit", "-q", "-am", "later work"], - ALICE, - t(3), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // No non-merge commit touched it: no accumulator... - assert!(history.file(Path::new("merge_only.rs")).is_none()); - // ...but the blob is tracked, so its history is a measured zero. - let fh = history - .tracked_file(Path::new("merge_only.rs")) - .expect("tracked blob must be history-available"); - assert_eq!(fh.commit_frequency, 0); - assert_eq!(fh.churn_abs(), 0); - assert_eq!(fh.authors, 0); - // Age counts from the creating merge (t2) to HEAD (t3): 100 000 - // seconds, not zero. - let expected_months = 100_000.0 / (30.436875 * 86_400.0); - assert!( - (fh.age_months(history.head_seconds) - expected_months).abs() < 1e-9, - "age must measure from the creating merge, got {}", - fh.age_months(history.head_seconds) - ); -} - -/// Two parallel merges each conflict-create the same path; a later -/// merge keeps one version and fences the other. The surviving -/// zero-touch blob's synthesized age must come from *its* creating -/// merge, not from the discarded occupant's — which the date-order -/// walk visits first here (newer timestamps). -#[test] -fn discarded_parallel_merge_creations_do_not_misdate_the_survivor() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - let root = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - // A tiny two-branch diamond whose merge tree conflict-creates - // `a.rs` with the given content. - let creating_merge = |branch: &str, filler: &str, content: &str, n: i64| -> String { - git( - dir.path(), - &["checkout", "-q", "-b", branch, &root], - ALICE, - t(n), - ); - std::fs::write(dir.path().join(filler), "fn f() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(n)); - git(dir.path(), &["commit", "-q", "-m", "filler"], ALICE, t(n)); - let side = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(n)); - std::fs::write(dir.path().join("a.rs"), content).unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(n + 1)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(n + 1)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &root, - "-p", - &side, - "-m", - "conflict-create a.rs", - ], - BOB, - t(n + 1), - ); - std::fs::remove_file(dir.path().join("a.rs")).unwrap(); - git(dir.path(), &["checkout", "-q", "-f", &root], ALICE, t(n)); - merge - }; - - // Survivor created at t(2); discarded occupant created at t(4) - // (newer — walked first). - let survivor_merge = creating_merge("one", "f1.rs", "fn kept() {}\n", 1); - let discarded_merge = creating_merge("two", "f2.rs", "fn discarded_occupant_content() {}\n", 3); - - // The outer merge keeps the survivor's blob. - git( - dir.path(), - &["checkout", "-q", "-f", &survivor_merge], - ALICE, - t(5), - ); - let tree = git_out(dir.path(), &["write-tree"], ALICE, t(5)); - let outer = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &survivor_merge, - "-p", - &discarded_merge, - "-m", - "keep one version", - ], - ALICE, - t(5), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &outer).unwrap(); - - let fh = history - .tracked_file(Path::new("a.rs")) - .expect("tracked blob must be history-available"); - assert_eq!( - fh.commit_frequency, 0, - "merge-only blob accumulates nothing" - ); - // head = t(5), surviving creation = t(2): 300 000 seconds. The - // discarded occupant's creation (t(4), walked first) must not - // shrink this to 100 000. - let expected_months = 300_000.0 / (30.436875 * 86_400.0); - assert!( - (fh.age_months(history.head_seconds) - expected_months).abs() < 1e-9, - "age must come from the surviving creation, got {} months", - fh.age_months(history.head_seconds) - ); -} - -/// A merge conflict-creates `a.rs`; a later merge's identity-only -/// change renames it to `b.rs`. The creation timestamp must be keyed -/// by the *resolved* live path (`b.rs`) — keying by the addition's -/// own path would leave the zero-touch `b.rs` with no entry and an -/// age fabricated from HEAD. -#[test] -fn merge_created_then_merge_renamed_blobs_keep_their_creation_age() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - let root = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(0)); - - // First diamond: the merge conflict-creates a.rs at t(2). - git(dir.path(), &["checkout", "-q", "-b", "one"], ALICE, t(1)); - std::fs::write(dir.path().join("f1.rs"), "fn f1() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git(dir.path(), &["commit", "-q", "-m", "side one"], ALICE, t(1)); - let side1 = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(1)); - std::fs::write(dir.path().join("a.rs"), "fn created_by_merge() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], BOB, t(2)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(2)); - let m1 = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &root, - "-p", - &side1, - "-m", - "conflict-create a.rs", - ], - BOB, - t(2), - ); - - // Second diamond off m1: the merge renames a.rs → b.rs at t(4). - git(dir.path(), &["checkout", "-q", &m1], ALICE, t(3)); - git(dir.path(), &["checkout", "-q", "-b", "two"], ALICE, t(3)); - std::fs::write(dir.path().join("f2.rs"), "fn f2() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(3)); - git(dir.path(), &["commit", "-q", "-m", "side two"], ALICE, t(3)); - let side2 = git_out(dir.path(), &["rev-parse", "HEAD"], ALICE, t(3)); - git(dir.path(), &["mv", "a.rs", "b.rs"], BOB, t(4)); - git(dir.path(), &["add", "-A"], BOB, t(4)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(4)); - let m2 = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &m1, - "-p", - &side2, - "-m", - "rename a.rs to b.rs", - ], - BOB, - t(4), - ); - - // Advance HEAD one commit past the renaming merge. - git(dir.path(), &["checkout", "-q", &m2], ALICE, t(5)); - git(dir.path(), &["checkout", "-q", "-b", "after"], ALICE, t(5)); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\nfn k2() {}\n").unwrap(); - git(dir.path(), &["commit", "-q", "-am", "later"], ALICE, t(5)); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - let fh = history - .tracked_file(Path::new("b.rs")) - .expect("tracked blob must be history-available"); - // head = t(5), creation = t(2): 300 000 seconds — not zero. - let expected_months = 300_000.0 / (30.436875 * 86_400.0); - assert!( - (fh.age_months(history.head_seconds) - expected_months).abs() < 1e-9, - "age must survive the merge rename, got {} months", - fh.age_months(history.head_seconds) - ); -} - -/// The exact-rename overflow fallback (> 10 000 same-content pairs) -/// must keep basename affinity: a bulk move of identical stubs whose -/// destination directories reverse the path-sorted order would -/// otherwise be paired positionally, silently transferring commit -/// history between files whose basenames match unambiguously. -#[test] -fn exact_rename_overflow_fallback_pairs_by_basename() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // One stub is seeded by a bug-fix commit — the marker that must - // follow its lineage through the move. `f000` sorts first on the - // source side while its destination (`d100/f000.rs`) sorts last, - // so positional pairing is maximally wrong for it. - let stub = "fn stub() {}\n"; - std::fs::create_dir(dir.path().join("s")).unwrap(); - std::fs::write(dir.path().join("s/f000.rs"), stub).unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(0)); - git( - dir.path(), - &["commit", "-q", "-m", "fix: seed f000"], - CAROL, - t(0), - ); - - // 100 more byte-identical stubs: 101 deletions × 101 additions - // in the move commit exceeds the 10 000-pair ranking budget. - for i in 1..101 { - std::fs::write(dir.path().join(format!("s/f{i:03}.rs")), stub).unwrap(); - } - git(dir.path(), &["add", "-A"], ALICE, t(1)); - git( - dir.path(), - &["commit", "-q", "-m", "bulk stubs"], - ALICE, - t(1), - ); - - // Move every stub into its own directory, numbered so the sorted - // destination order *reverses* the source order. - for i in 0..101 { - let dest_dir = dir.path().join(format!("d{:03}", 100 - i)); - std::fs::create_dir(&dest_dir).unwrap(); - std::fs::rename( - dir.path().join(format!("s/f{i:03}.rs")), - dest_dir.join(format!("f{i:03}.rs")), - ) - .unwrap(); - } - git(dir.path(), &["add", "-A"], ALICE, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "bulk move"], - ALICE, - t(2), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, "HEAD").unwrap(); - - // f000's bug-fix creation must have followed *its* basename to - // d100/f000.rs — positional pairing would hand it to d000/f100.rs - // (the first destination in sorted order). - let bugfix_carrier = history.file(Path::new("d100/f000.rs")).unwrap(); - assert_eq!( - bugfix_carrier.bugfix_commits, 1, - "the bug-fix lineage was paired onto the wrong destination" - ); - let other = history.file(Path::new("d000/f100.rs")).unwrap(); - assert_eq!(other.bugfix_commits, 0); -} - -/// An octopus merge discarding *two* parents' independent occupants -/// of the same path: each discarded parent needs its own fence — a -/// per-path dedup would leave the second occupant unfenced. -#[test] -fn octopus_merges_fence_every_discarded_occupant() { - let dir = tempfile::tempdir().unwrap(); - let t = |n: i64| 1_700_000_000 + n * 100_000; - git(dir.path(), &["init", "-q", "-b", "main"], ALICE, t(0)); - - // c0: the original. - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\n", - ) - .unwrap(); - std::fs::write(dir.path().join("keep.rs"), "fn keep() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], ALICE, t(0)); - git(dir.path(), &["commit", "-q", "-m", "root"], ALICE, t(0)); - - // Retaining branch. - git(dir.path(), &["checkout", "-q", "-b", "retain"], BOB, t(1)); - std::fs::write( - dir.path().join("a.rs"), - "fn a0() {}\nfn a1() {}\nfn a2() {}\nfn kept_edit() {}\n", - ) - .unwrap(); - git(dir.path(), &["commit", "-q", "-am", "grow a"], BOB, t(1)); - let retain = git_out(dir.path(), &["rev-parse", "HEAD"], BOB, t(1)); - - // First discarded branch: delete + recreate (newest timestamps). - git( - dir.path(), - &["checkout", "-q", "-b", "d1", "main"], - CAROL, - t(2), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(2)); - git( - dir.path(), - &["commit", "-q", "-m", "d1 drops a"], - CAROL, - t(2), - ); - std::fs::write(dir.path().join("a.rs"), "fn d1_own() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(3)); - git( - dir.path(), - &["commit", "-q", "-m", "d1 recreates a"], - CAROL, - t(3), - ); - let d1 = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(3)); - - // Second discarded branch: another independent occupant. - git( - dir.path(), - &["checkout", "-q", "-b", "d2", "main"], - CAROL, - t(4), - ); - git(dir.path(), &["rm", "-q", "a.rs"], CAROL, t(4)); - git( - dir.path(), - &["commit", "-q", "-m", "d2 drops a"], - CAROL, - t(4), - ); - std::fs::write(dir.path().join("a.rs"), "fn d2_own() {}\nfn d2_more() {}\n").unwrap(); - git(dir.path(), &["add", "-A"], CAROL, t(5)); - git( - dir.path(), - &["commit", "-q", "-m", "d2 recreates a"], - CAROL, - t(5), - ); - let d2 = git_out(dir.path(), &["rev-parse", "HEAD"], CAROL, t(5)); - - // The octopus merge keeps the retaining parent's blob. - git(dir.path(), &["checkout", "-q", "-f", "retain"], BOB, t(6)); - let tree = git_out(dir.path(), &["write-tree"], BOB, t(6)); - let merge = git_out( - dir.path(), - &[ - "commit-tree", - &tree, - "-p", - &retain, - "-p", - &d1, - "-p", - &d2, - "-m", - "octopus keep", - ], - BOB, - t(6), - ); - - let repo = gix::discover(dir.path()).unwrap(); - let history = collect_history(&repo, &merge).unwrap(); - - // The survivor keeps exactly its own lineage plus the two - // deletion touches; neither recreated occupant's lines leak in. - // (carol appears as an author through her deletion touches only — - // zero added lines.) - let a = history.file(Path::new("a.rs")).unwrap(); - assert_eq!(a.churn_added, 4, "a discarded occupant leaked in"); - assert_eq!(a.commit_frequency, 4); - assert_eq!(a.authors, 3); - assert!((a.ownership - 0.75).abs() < 1e-9, "got {}", a.ownership); -} diff --git a/crates/mehen-go/Cargo.toml b/crates/mehen-go/Cargo.toml deleted file mode 100644 index 18ae8e94..00000000 --- a/crates/mehen-go/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "mehen-go" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — Go language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -mehen-tree-sitter = { workspace = true } -num = { workspace = true } -num-derive = { workspace = true } -# Required transitively by `num_derive::FromPrimitive` in `grammar.rs` -# — the derive expansion references `num_traits::FromPrimitive` by -# absolute path. Keep as a direct dependency and silence cargo-machete. -num-traits = { workspace = true } -smol_str = { workspace = true } -tree-sitter = { workspace = true } -# `tree-sitter-go` is pinned here (not in `[workspace.dependencies]`) -# because `mehen-go` is the sole consumer. xtask reaches the grammar -# through `__grammar_language()` exported from this crate, so the -# kind-enum generator and the analyzer parser are guaranteed to link -# the same revision. -tree-sitter-go = "=0.25.0" - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[package.metadata.cargo-machete] -ignored = ["num-traits"] - -[lints] -workspace = true diff --git a/crates/mehen-go/src/lib.rs b/crates/mehen-go/src/lib.rs deleted file mode 100644 index 22055862..00000000 --- a/crates/mehen-go/src/lib.rs +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-go` — Go language analyzer. -//! -//! Phase-3 reorganization complete: the analyzer owns its tree-sitter -//! cursor walk locally (`walker.rs`) and the language-specific kind -//! enum (`grammar.rs`) instead of relying on the shared -//! `mehen-tree-sitter::walker::LanguageRules` plug-in. This mirrors the -//! per-language crate shape used by `mehen-ruby`, `mehen-python`, -//! `mehen-typescript`, and `mehen-php`. Per the rewrite plan §6.1 Go -//! stays on tree-sitter for 1.0 — only the *interpretation* moves. - -#![forbid(unsafe_code)] - -mod grammar; -mod walker; - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, ParseDiagnostic, - Result, SourceFile, SourceSpan, byte_offset_clamped, -}; -use mehen_tree_sitter::{MetricEvidence, TreeSitterParser, collect_recovered_errors, empty_space}; - -/// Tree-sitter `Language` accessor for `xtask tree-sitter generate`. -/// -/// Exposed so the kind-enum generator reaches the grammar through this -/// crate instead of pinning `tree-sitter-go` itself. -#[doc(hidden)] -pub fn __grammar_language() -> tree_sitter::Language { - tree_sitter_go::LANGUAGE.into() -} - -pub struct GoAnalyzer; - -impl GoAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for GoAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for GoAnalyzer { - fn language(&self) -> Language { - Language::Go - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::TreeSitter - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - let parser = match TreeSitterParser::new( - tree_sitter_go::LANGUAGE.into(), - source.text.clone().into_bytes(), - ) { - Ok(p) => p, - Err(e) => { - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: source.line_index.line_count(), - }; - return Ok(LanguageAnalysis { - language: Language::Go, - backend: AnalysisBackend::TreeSitter, - diagnostics: vec![ParseDiagnostic::fatal( - "go.parse_error", - format!("tree-sitter-go failed: {e}"), - )], - root: empty_space(span), - contributions: Vec::new(), - }); - } - }; - - let mut evidence = MetricEvidence::new("go", config.emit_contributions); - let root = walker::walk_program( - parser.root(), - parser.source(), - &source.line_index, - &mut evidence, - ); - // Tree-sitter recovers from syntax errors by inserting ERROR / - // missing nodes; surface them as `error` diagnostics so the - // metric output can't masquerade as clean (plan §9.3). - let diagnostics = collect_recovered_errors(parser.root(), "go.syntax_error", 16); - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::Go, - backend: AnalysisBackend::TreeSitter, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, Language, MetricKey, SourceFile, SpaceKind}; - use mehen_metrics::keys; - - fn analyze(source: &str) -> LanguageAnalysis { - GoAnalyzer::new() - .analyze( - &SourceFile::new("a.go".into(), Language::Go, source.to_string()), - &AnalysisConfig::default(), - ) - .unwrap() - } - - #[test] - fn func_creates_function_space() { - let a = analyze("package main\nfunc Foo() int { return 1 }\n"); - assert!(a.root.spaces.iter().any(|s| s.kind == SpaceKind::Function)); - } - - #[test] - fn cyclomatic_counts_branches() { - let a = analyze( - "package main\nfunc f(x int) int { if x > 0 && x < 10 { return 1 }; return 2 }\n", - ); - let func = a - .root - .spaces - .iter() - .find(|s| s.kind == SpaceKind::Function) - .unwrap(); - let cy = func - .metrics - .get(&MetricKey::new(keys::CYCLOMATIC)) - .unwrap() - .as_f64(); - assert!(cy >= 3.0, "expected >= 3, got {cy}"); - } -} diff --git a/crates/mehen-go/src/walker.rs b/crates/mehen-go/src/walker.rs deleted file mode 100644 index 0a60d11a..00000000 --- a/crates/mehen-go/src/walker.rs +++ /dev/null @@ -1,594 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Tree-sitter-go walker producing per-space metric output that matches -//! the pre-1.0 `legacy::metrics::*::compute for GoCode` arms exactly. -//! -//! The walker drives its own tree-sitter cursor recursion (rather than -//! the generic `mehen-tree-sitter::walker::LanguageRules` plug-in) so it -//! can do parent-aware classification — Go's `is_else_if` and -//! `default_case in select` predicates both inspect the parent node, -//! which the generic walker cannot express. -//! -//! Metric coverage: -//! - **Cyclomatic**: every `if_statement`, `for_statement`, -//! `expression_case`, `type_case`, `communication_case`, every `&&`/`||` -//! token, plus a `default_case` whose parent is `select_statement` -//! (legacy: `Cyclomatic for GoCode`). -//! - **Cognitive**: nesting on `if_statement` (skipping the inner `if` -//! of an `else if`), `for_statement`, -//! `expression_switch_statement`, `type_switch_statement`, -//! `select_statement`; flat `+1` on every `else` keyword; -//! boolean-sequence reset on every statement-shape node; -//! `not_operator("!")` for unary `!` operators; per-`&&`/`||` -//! sequence collapse via the shared `BoolSequence` (legacy: -//! `Cognitive for GoCode`). -//! - **ABC**: assignments via `assignment_statement` / -//! `short_var_declaration` (target count from the `left` field) and -//! `inc_statement` / `dec_statement` (one each), `receive_statement` -//! / `range_clause` only when the `left` field is present, `var_spec` -//! with an `=` token, and `const_spec`. Branches: every -//! `call_expression`. Conditions: `if`, `for`, every `case` arm, -//! plus the comparison + boolean operator tokens. (Legacy: -//! `Abc for GoCode`.) -//! - **NExit**: `return_statement` (legacy: `Exit for GoCode`). -//! - **NArgs**: per-`parameter_declaration` / -//! `variadic_parameter_declaration` count = `max(1, identifier_count)` -//! (legacy: `compute_go_args`). -//! - **NOM**: every `function_declaration` / `method_declaration` → -//! function space; every `func_literal` → closure space. -//! - **LOC**: PLOC (every node default arm), LLOC (the legacy 26-kind -//! set), CLOC (every `comment` node). Legacy: `Loc for GoCode`. -//! - **Halstead**: per-node operator/operand emission using the -//! legacy `Getter::get_op_type for GoCode` table. Operands dedup by -//! text only (kind = `"Operand"`) so semantically-equal text from -//! different identifier-shaped nodes (e.g. `Identifier`, -//! `Identifier2`, `Identifier3`, `BlankIdentifier`, -//! `FieldIdentifier`, `LabelName`, `PackageIdentifier`, -//! `TypeIdentifier`) merges into a single bucket — matching the -//! legacy raw-byte-slice key. -//! - **NPA / NPM / WMC**: Go has no class-like constructs; all three -//! are intentionally no-ops, matching the legacy -//! `impl X for GoCode` empty bodies. - -use mehen_core::{LineIndex, MetricSpace, SpaceKind}; -use mehen_metrics::{HalsteadOperand, HalsteadOperator, MetricEvidence, State}; -use mehen_tree_sitter::{OpenSpaceRequest, WalkerCtx, WalkerHooks, node_span, run, text_of}; -use smol_str::SmolStr; -use tree_sitter::Node; - -use crate::grammar::Go; - -/// Drive the walker over the parsed Go tree and return the populated -/// `MetricSpace`. Plugs Go classification into the shared -/// [`mehen_tree_sitter::run`] scaffold. Contribution evidence is -/// recorded into the caller-owned `evidence` sink (plan §5.4). -pub(crate) fn walk_program( - root: Node<'_>, - source: &[u8], - line_index: &LineIndex, - evidence: &mut MetricEvidence, -) -> MetricSpace { - let mut hooks = GoHooks; - run(&mut hooks, root, source, line_index, evidence) -} - -struct GoHooks; - -impl WalkerHooks for GoHooks { - fn open_space(&mut self, ctx: &mut WalkerCtx<'_>, node: &Node<'_>) -> Option { - match Go::from(node.kind_id()) { - Go::FunctionDeclaration | Go::MethodDeclaration => { - let name = node - .child_by_field_name("name") - .map(|n| text_of(&n, ctx.source).to_string()); - let span = node_span(node, ctx.line_index); - let mut state = State::new(); - state.loc.set_span( - node.start_position().row as u32, - node.end_position().row as u32, - false, - ); - state.nom.record_function(); - let argc = count_go_args(node); - state.nargs.record_function_args(argc); - if ctx.evidence.is_enabled() { - ctx.evidence.function(span, node.kind()); - ctx.evidence.function_args(span, argc, node.kind()); - } - Some(OpenSpaceRequest { - kind: SpaceKind::Function, - name, - span, - state, - }) - } - Go::FuncLiteral => { - let span = node_span(node, ctx.line_index); - let mut state = State::new(); - state.loc.set_span( - node.start_position().row as u32, - node.end_position().row as u32, - false, - ); - state.nom.record_closure(); - let argc = count_go_args(node); - state.nargs.record_closure_args(argc); - if ctx.evidence.is_enabled() { - ctx.evidence.closure(span, node.kind()); - ctx.evidence.closure_args(span, argc, node.kind()); - } - Some(OpenSpaceRequest { - kind: SpaceKind::Closure, - name: None, - span, - state, - }) - } - _ => None, - } - } - - fn on_space_enter(&mut self, ctx: &mut WalkerCtx<'_>, kind: SpaceKind) { - match kind { - SpaceKind::Function => { - // Legacy `Cognitive for GoCode`'s `FunctionDeclaration | MethodDeclaration` - // arm: reset nesting, bump function-depth when nested. - let nested_inside_function = ctx - .ancestor_kinds() - .any(|k| matches!(k, SpaceKind::Function)); - ctx.cognitive.nesting = 0; - if nested_inside_function { - ctx.cognitive.depth = ctx.cognitive.depth.saturating_add(1); - } - } - SpaceKind::Closure => { - // Legacy `FuncLiteral` arm: bump lambda counter only; - // nesting/depth pass through unchanged. - ctx.cognitive.lambda = ctx.cognitive.lambda.saturating_add(1); - } - _ => {} - } - } - - fn before_close(&mut self, state: &mut State, closed_kind: SpaceKind, _parent: SpaceKind) { - if matches!(closed_kind, SpaceKind::Function) { - state.wmc.set_cyclomatic(state.cyclomatic.cyclomatic + 1); - } - } - - fn classify(&mut self, ctx: &mut WalkerCtx<'_>, node: &Node<'_>) { - let kind = Go::from(node.kind_id()); - - // Cyclomatic — legacy `Cyclomatic for GoCode`. `default_case` - // inside a `select` is a real communication branch; inside a - // `switch` it's fallthrough and does not count. - let is_decision = matches!( - kind, - Go::IfStatement - | Go::ForStatement - | Go::ExpressionCase - | Go::TypeCase - | Go::CommunicationCase - | Go::AMPAMP - | Go::PIPEPIPE - ) || (matches!(kind, Go::DefaultCase) - && parent_kind(node) == Some(Go::SelectStatement)); - if is_decision { - ctx.current().cyclomatic.record_decision(); - ctx.record_evidence(node, |e, s| e.decision(s, node.kind())); - } - - classify_cognitive(ctx, node, kind); - classify_abc(ctx, node, kind); - - // NExit — legacy `Exit for GoCode`. - if matches!(kind, Go::ReturnStatement) { - ctx.current().nexit.record_exit(); - ctx.record_evidence(node, |e, s| e.exit(s, node.kind())); - } - - classify_loc(ctx, node, kind); - classify_halstead(ctx, node, kind); - } -} - -fn classify_cognitive(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: Go) { - match kind { - // The else-if form (`IfStatement` whose direct parent is - // also an `IfStatement`) is a no-op in legacy — the outer - // `if` already opened a nesting level and the connecting - // `else` keyword adds the flat `+1`. - Go::IfStatement if !is_else_if(node) => { - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.increase_nesting(effective); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(node, |e, s| e.cognitive(s, delta, node.kind())); - } - Go::IfStatement => {} - Go::ForStatement - | Go::ExpressionSwitchStatement - | Go::TypeSwitchStatement - | Go::SelectStatement => { - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.increase_nesting(effective); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(node, |e, s| e.cognitive(s, delta, node.kind())); - } - Go::Else => { - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.increment_by_one(); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(node, |e, s| e.cognitive(s, delta, node.kind())); - } - Go::ExpressionStatement - | Go::SendStatement - | Go::ReceiveStatement - | Go::IncStatement - | Go::DecStatement - | Go::AssignmentStatement - | Go::ShortVarDeclaration - | Go::VarSpec - | Go::ConstSpec - | Go::ReturnStatement => { - ctx.current().cognitive.boolean_seq.reset(); - } - // Legacy passes the literal node kind_id (the top-level - // `unary_expression` kind, not the operator child) into - // `boolean_seq.not_operator`. We forward a stable `"!"` - // marker — same effect because `eval_based_on_prev` only - // cares whether the recorded last_op equals the new - // boolean operator string. - Go::UnaryExpression if has_child_kind(node, Go::BANG) => { - ctx.current().cognitive.boolean_seq.not_operator("!"); - } - Go::BinaryExpression => { - // Legacy `compute_booleans::`: walk the children; - // for each `&&` / `||` operator child, feed the - // sequence collapser. The actual punctuation is one of - // the binary expression's children. Evidence spans point - // at the operator token; same-operator repeats apply no - // delta and record nothing. - for child in iter_children(node) { - let op = match Go::from(child.kind_id()) { - Go::AMPAMP => "&&", - Go::PIPEPIPE => "||", - _ => continue, - }; - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.observe_boolean(op); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(&child, |e, s| e.cognitive(s, delta, op)); - } - } - _ => {} - } -} - -fn classify_abc(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: Go) { - match kind { - Go::AssignmentStatement | Go::ShortVarDeclaration => { - let count = go_assignment_target_count(node); - ctx.current().abc.assignments = ctx.current().abc.assignments.saturating_add(count); - ctx.record_evidence(node, |e, s| e.abc_assignments_n(s, count, node.kind())); - } - Go::ReceiveStatement | Go::RangeClause if node.child_by_field_name("left").is_some() => { - let count = go_assignment_target_count(node); - ctx.current().abc.assignments = ctx.current().abc.assignments.saturating_add(count); - ctx.record_evidence(node, |e, s| e.abc_assignments_n(s, count, node.kind())); - } - Go::IncStatement | Go::DecStatement => { - ctx.current().abc.record_assignment(); - ctx.record_evidence(node, |e, s| e.abc_assignment(s, node.kind())); - } - Go::ConstSpec => { - let count = go_spec_name_count(node); - ctx.current().abc.assignments = ctx.current().abc.assignments.saturating_add(count); - ctx.record_evidence(node, |e, s| e.abc_assignments_n(s, count, node.kind())); - } - Go::VarSpec if has_child_kind(node, Go::EQ) => { - let count = go_spec_name_count(node); - ctx.current().abc.assignments = ctx.current().abc.assignments.saturating_add(count); - ctx.record_evidence(node, |e, s| e.abc_assignments_n(s, count, node.kind())); - } - Go::CallExpression => { - ctx.current().abc.record_branch(); - ctx.record_evidence(node, |e, s| e.abc_branch(s, node.kind())); - } - Go::IfStatement - | Go::ForStatement - | Go::ExpressionCase - | Go::DefaultCase - | Go::TypeCase - | Go::CommunicationCase - | Go::EQEQ - | Go::BANGEQ - | Go::LT - | Go::LTEQ - | Go::GT - | Go::GTEQ - | Go::AMPAMP - | Go::PIPEPIPE - | Go::BANG => { - ctx.current().abc.record_condition(); - ctx.record_evidence(node, |e, s| e.abc_condition(s, node.kind())); - } - _ => {} - } -} - -fn classify_loc(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: Go) { - match kind { - Go::SourceFile => {} - Go::Comment => { - let start = node.start_position().row as u32; - let end = node.end_position().row as u32; - ctx.current().loc.observe_comment(start, end); - } - Go::ExpressionStatement - | Go::SendStatement - | Go::ReceiveStatement - | Go::IncStatement - | Go::DecStatement - | Go::AssignmentStatement - | Go::ShortVarDeclaration - | Go::ImportSpec - | Go::VarSpec - | Go::ConstSpec - | Go::TypeSpec - | Go::EmptyStatement - | Go::LabeledStatement - | Go::LabeledStatement2 - | Go::GoStatement - | Go::DeferStatement - | Go::ReturnStatement - | Go::BreakStatement - | Go::ContinueStatement - | Go::GotoStatement - | Go::FallthroughStatement - | Go::IfStatement - | Go::ExpressionSwitchStatement - | Go::TypeSwitchStatement - | Go::SelectStatement - | Go::ForStatement => { - ctx.current().loc.observe_lloc(); - } - _ => { - let start = node.start_position().row as u32; - ctx.current().loc.observe_code_line(start); - } - } -} - -fn classify_halstead(ctx: &mut WalkerCtx<'_>, node: &Node<'_>, kind: Go) { - // Halstead routes to the *current* (innermost) space so nested - // function bodies carry their own counts; the close path's - // `merge_child_into_parent` rolls these up into the enclosing - // scope and the unit (set-union for `n1`/`n2`, sum for - // `N1`/`N2`). - match halstead_op_type(kind) { - HalsteadType::Operator => { - let kind_label: &'static str = kind.into(); - ctx.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(kind_label), - text: None, - }); - } - HalsteadType::Operand => { - let text = text_of(node, ctx.source); - ctx.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(SmolStr::new(text)), - }); - } - HalsteadType::Unknown => {} - } -} - -// -------------------------------------------------------------------- -// Halstead classification (legacy `Getter::get_op_type for GoCode`). -// -------------------------------------------------------------------- - -enum HalsteadType { - Operator, - Operand, - Unknown, -} - -fn halstead_op_type(kind: Go) -> HalsteadType { - match kind { - // Operators: keywords and control-flow tokens. - // Note: `Go::Go` is the `go` keyword (goroutine launch), not the - // language identifier. - Go::Func - | Go::Go - | Go::Defer - | Go::Return - | Go::If - | Go::Else - | Go::For - | Go::Range - | Go::Switch - | Go::Select - | Go::Case - | Go::Default - | Go::Break - | Go::Continue - | Go::Goto - | Go::Fallthrough - | Go::Chan - | Go::Map - | Go::Struct - | Go::Interface - | Go::Type - | Go::Var - | Go::Const - | Go::Package - | Go::Import - // Punctuation operators. - | Go::DOT - | Go::COMMA - | Go::SEMI - | Go::COLON - | Go::COLONEQ - | Go::EQ - | Go::PLUSEQ - | Go::DASHEQ - | Go::STAREQ - | Go::SLASHEQ - | Go::PERCENTEQ - | Go::AMPEQ - | Go::PIPEEQ - | Go::CARETEQ - | Go::LTLTEQ - | Go::GTGTEQ - | Go::AMPCARETEQ - // Arithmetic / logic operators. - | Go::PLUS - | Go::DASH - | Go::STAR - | Go::SLASH - | Go::PERCENT - | Go::AMP - | Go::PIPE - | Go::CARET - | Go::LTLT - | Go::GTGT - | Go::AMPAMP - | Go::PIPEPIPE - | Go::AMPCARET - | Go::PLUSPLUS - | Go::DASHDASH - | Go::LTDASH - | Go::TILDE - | Go::EQEQ - | Go::BANGEQ - | Go::LT - | Go::LTEQ - | Go::GT - | Go::GTEQ - | Go::BANG - | Go::LPAREN - | Go::LBRACK - | Go::LBRACE - | Go::DOTDOTDOT => HalsteadType::Operator, - - // Operands: identifiers, type identifiers, and literals. - Go::Identifier - | Go::Identifier2 - | Go::Identifier3 - | Go::BlankIdentifier - | Go::FieldIdentifier - | Go::LabelName - | Go::PackageIdentifier - | Go::TypeIdentifier - | Go::IntLiteral - | Go::FloatLiteral - | Go::ImaginaryLiteral - | Go::RuneLiteral - | Go::RawStringLiteral - | Go::InterpretedStringLiteral - | Go::True - | Go::False - | Go::Nil - | Go::Iota => HalsteadType::Operand, - - _ => HalsteadType::Unknown, - } -} - -// -------------------------------------------------------------------- -// ABC helpers — direct ports of legacy `go_*` helper fns. -// -------------------------------------------------------------------- - -fn go_expression_list_len(node: &Node<'_>) -> u32 { - iter_children(node) - .filter(|child| !matches!(Go::from(child.kind_id()), Go::COMMA | Go::Comment)) - .count() as u32 -} - -fn go_assignment_target_count(node: &Node<'_>) -> u32 { - node.child_by_field_name("left") - .map(|child| go_expression_list_len(&child)) - .unwrap_or(1) -} - -fn go_spec_name_count(node: &Node<'_>) -> u32 { - let mut count: u32 = 0; - for child in iter_children(node) { - match Go::from(child.kind_id()) { - Go::EQ => break, - Go::Identifier | Go::Identifier2 | Go::Identifier3 | Go::BlankIdentifier => { - count = count.saturating_add(1) - } - _ => {} - } - } - count.max(1) -} - -// -------------------------------------------------------------------- -// NArgs helper — direct port of legacy `compute_go_args`. -// -------------------------------------------------------------------- - -fn count_go_args(node: &Node<'_>) -> u32 { - let Some(params) = node.child_by_field_name("parameters") else { - return 0; - }; - let mut total: u32 = 0; - for child in iter_children(¶ms) { - match Go::from(child.kind_id()) { - Go::ParameterDeclaration | Go::VariadicParameterDeclaration => { - let mut names: u32 = 0; - for inner in iter_children(&child) { - if matches!( - Go::from(inner.kind_id()), - Go::Identifier | Go::Identifier2 | Go::Identifier3 | Go::BlankIdentifier - ) { - names = names.saturating_add(1); - } - } - total = total.saturating_add(names.max(1)); - } - _ => {} - } - } - total -} - -// -------------------------------------------------------------------- -// Tree-sitter helpers -// -------------------------------------------------------------------- - -fn parent_kind(node: &Node<'_>) -> Option { - node.parent().map(|p| Go::from(p.kind_id())) -} - -fn is_else_if(node: &Node<'_>) -> bool { - if Go::from(node.kind_id()) != Go::IfStatement { - return false; - } - parent_kind(node) == Some(Go::IfStatement) -} - -fn has_child_kind(node: &Node<'_>, kind: Go) -> bool { - iter_children(node).any(|c| Go::from(c.kind_id()) == kind) -} - -fn iter_children<'tree>(node: &Node<'tree>) -> impl Iterator> { - let mut cursor = node.walk(); - let mut nodes = Vec::new(); - if cursor.goto_first_child() { - loop { - nodes.push(cursor.node()); - if !cursor.goto_next_sibling() { - break; - } - } - } - nodes.into_iter() -} diff --git a/crates/mehen-go/tests/abc.rs b/crates/mehen-go/tests/abc.rs deleted file mode 100644 index ec5751d2..00000000 --- a/crates/mehen-go/tests/abc.rs +++ /dev/null @@ -1,193 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC metric tests for the Go walker. -//! -//! Every legacy `check_metrics::` ABC test from -//! `crates/mehen-engine/src/legacy/metrics/abc.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = GoAnalyzer::new(); - let file = SourceFile::new("foo.go".into(), Language::Go, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn go_abc_basic() { - let a = analyze( - "package main - - func f(a, b int) int { - x, y := a, b - log(x) - if x > y { - return x - } - return y - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 2.0, - "branches": 1.0, - "conditions": 2.0, - "magnitude": 3.0, - "assignments_average": 1.0, - "branches_average": 0.5, - "conditions_average": 1.0, - "assignments_min": 0.0, - "assignments_max": 2.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 2.0 - }"### - ); -} - -#[test] -fn go_abc_comments_in_targets_and_logical_conditions() { - let a = analyze( - "package main - - func f(a, b int) { - x, /* target comment */ y := a, b - _ = !((x > 0 && y > 0) || x == y) - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 3.0, - "branches": 0.0, - "conditions": 6.0, - "magnitude": 6.708203932499369, - "assignments_average": 1.5, - "branches_average": 0.0, - "conditions_average": 3.0, - "assignments_min": 0.0, - "assignments_max": 3.0, - "branches_min": 0.0, - "branches_max": 0.0, - "conditions_min": 0.0, - "conditions_max": 6.0 - }"### - ); -} - -#[test] -fn go_abc_receive_assignments() { - let a = analyze( - "package main - - func f(ch chan int) { - x := <-ch - y, ok := <-ch - <-ch - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 3.0, - "branches": 0.0, - "conditions": 0.0, - "magnitude": 3.0, - "assignments_average": 1.5, - "branches_average": 0.0, - "conditions_average": 0.0, - "assignments_min": 0.0, - "assignments_max": 3.0, - "branches_min": 0.0, - "branches_max": 0.0, - "conditions_min": 0.0, - "conditions_max": 0.0 - }"### - ); -} - -#[test] -fn go_abc_range_clause_assignments() { - let a = analyze( - "package main - - func f(m map[string]int) { - for k, v := range m { - } - for k = range m { - } - for range m { - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 3.0, - "branches": 0.0, - "conditions": 3.0, - "magnitude": 4.242640687119285, - "assignments_average": 1.5, - "branches_average": 0.0, - "conditions_average": 1.5, - "assignments_min": 0.0, - "assignments_max": 3.0, - "branches_min": 0.0, - "branches_max": 0.0, - "conditions_min": 0.0, - "conditions_max": 3.0 - }"### - ); -} - -#[test] -fn go_abc_default_cases() { - let a = analyze( - "package main - - func f(x int) int { - switch x { - case 1: - return 1 - default: - return 0 - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 0.0, - "branches": 0.0, - "conditions": 2.0, - "magnitude": 2.0, - "assignments_average": 0.0, - "branches_average": 0.0, - "conditions_average": 1.0, - "assignments_min": 0.0, - "assignments_max": 0.0, - "branches_min": 0.0, - "branches_max": 0.0, - "conditions_min": 0.0, - "conditions_max": 2.0 - }"### - ); -} diff --git a/crates/mehen-go/tests/cognitive.rs b/crates/mehen-go/tests/cognitive.rs deleted file mode 100644 index ca54fe32..00000000 --- a/crates/mehen-go/tests/cognitive.rs +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity tests for the Go walker. -//! -//! Every legacy `check_metrics::` cognitive test from -//! `crates/mehen-engine/src/legacy/metrics/cognitive.rs` is ported -//! here byte-identical so the parity contract (plan §12.3.1) is -//! visibly maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = GoAnalyzer::new(); - let file = SourceFile::new("foo.go".into(), Language::Go, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn go_no_cognitive() { - // Drift from legacy: legacy serialized `null` when no functions - // were observed (so the average's denominator was zero). The 1.0 - // mehen-metrics `CognitiveStats` defaults the empty average to - // 0.0 — same convention applied in Phase 6 Python and Phase 9 - // Ruby. - let a = analyze( - "package main - - var x = 42", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} - -#[test] -fn go_simple_function() { - let a = analyze( - "package main - - func f() { - if true { // +1 - if false { // +2 (nesting = 1) - println(\"test\") - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn go_for_loop() { - let a = analyze( - "package main - - func f() { - for i := 0; i < 10; i++ { // +1 - if i > 5 { // +2 (nesting = 1) - println(i) - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn go_logical_operators() { - let a = analyze( - "package main - - func f(a, b, c bool) { - if a && b && c { // +1 (if) +1 (sequence of &&) - println(\"all true\") - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn go_logical_operator_sequences_reset_between_statements() { - let a = analyze( - "package main - - func f(a, b, c, d bool) { - _ = a && b - _ = c && d - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn go_logical_operator_sequences_reset_between_declaration_specs() { - let a = analyze( - "package main - - func f(a, b, c, d bool) { - var x = a && b - var y = c && d - const p = true && false - const q = false && true - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} diff --git a/crates/mehen-go/tests/contributions.rs b/crates/mehen-go/tests/contributions.rs deleted file mode 100644 index a8eaa831..00000000 --- a/crates/mehen-go/tests/contributions.rs +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the Go analyzer (plan §5.4). - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - GoAnalyzer::new() - .analyze( - &SourceFile::new("s.go".into(), Language::Go, source.to_string()), - config, - ) - .expect("Go analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -package main - -func classify(a int, b int) int { - if a > 0 && b > 0 { - return 1 - } else if a < 0 { - return -1 - } - total, count := 0, 0 - for i := 0; i < a; i++ { - total += helper(i) - count++ - } - handler := func(x int) int { return x * 2 } - return handler(total + count) -} -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn reasons_are_go_namespaced_with_node_kinds() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "go.cyclomatic.if_statement", - "go.cyclomatic.for_statement", - "go.cyclomatic.&&", - "go.cognitive.if_statement", - "go.cognitive.else", - "go.nexit.return_statement", - "go.abc.assignment.short_var_declaration", - "go.abc.assignment.assignment_statement", - "go.abc.assignment.inc_statement", - "go.abc.branch.call_expression", - "go.abc.condition.if_statement", - "go.nom.function.function_declaration", - "go.nom.closure.func_literal", - "go.nargs.function.function_declaration", - "go.nargs.closure.func_literal", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("go."))); -} - -#[test] -fn multi_target_assignments_carry_their_count() { - // `total, count := 0, 0` is one evidence row with amount 2. - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let short_var: Vec = analysis - .contributions - .iter() - .filter(|item| item.reason.as_str() == "go.abc.assignment.short_var_declaration") - .map(|item| item.amount) - .collect(); - assert!( - short_var.contains(&2.0), - "expected a 2-target short_var_declaration row, got {short_var:?}", - ); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in ["cyclomatic.sum", "cognitive.sum", "nexit.sum", "abc"] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-go/tests/cyclomatic.rs b/crates/mehen-go/tests/cyclomatic.rs deleted file mode 100644 index b0dd4bc9..00000000 --- a/crates/mehen-go/tests/cyclomatic.rs +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity tests for the Go walker. -//! -//! Every legacy `check_metrics::` cyclomatic test from -//! `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs` is ported -//! here byte-identical so the parity contract (plan §12.3.1) is -//! visibly maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = GoAnalyzer::new(); - let file = SourceFile::new("foo.go".into(), Language::Go, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn go_simple_function() { - let a = analyze( - "package main - - func calculate(a, b int) int { // +2 (+1 unit space) - if a > b { // +1 - return a - } - return b - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn go_switch_statement() { - let a = analyze( - "package main - - func grade(score int) string { // +2 (+1 unit space) - switch { // switch itself doesn't add, cases do - case score >= 90: // +1 - return \"A\" - case score >= 80: // +1 - return \"B\" - case score >= 70: // +1 - return \"C\" - default: // default is fallthrough, not a decision point - return \"F\" - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn go_select_default_counts() { - // `default` in a `switch` is fallthrough and should NOT count, - // but `default` in a `select` is an additional executable - // communication branch and SHOULD count. - let a = analyze( - "package main - - func f(ch chan int) { // +2 (+1 unit space) - select { // +1 CommunicationCase - case v := <-ch: - _ = v - default: // +1 default branch of select - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn go_logical_operators() { - let a = analyze( - "package main - - func check(a, b, c bool) bool { // +2 (+1 unit space) - if a && b || c { // +3 (+1 if, +1 &&, +1 ||) - return true - } - return false - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - }"### - ); -} diff --git a/crates/mehen-go/tests/exit.rs b/crates/mehen-go/tests/exit.rs deleted file mode 100644 index a09ebd5c..00000000 --- a/crates/mehen-go/tests/exit.rs +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NExit tests for the Go walker. -//! -//! Every legacy `check_metrics::` exit test from -//! `crates/mehen-engine/src/legacy/metrics/exit.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = GoAnalyzer::new(); - let file = SourceFile::new("foo.go".into(), Language::Go, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn go_no_exit() { - // Drift from legacy: legacy serialized `null` when no functions - // were observed (so the average's denominator was zero). The 1.0 - // mehen-metrics `NexitStats` defaults the empty average to 0.0 — - // same convention applied in Phase 6 Python and Phase 9 Ruby. - let a = analyze("var a = 42"); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} - -#[test] -fn go_simple_function() { - let a = analyze( - "package main - - func max(a, b int) int { - if a > b { - return a - } - return b - }", - ); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - // 2 exits / 1 function - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn go_multiple_functions() { - let a = analyze( - "package main - - func f1() int { - return 1 - } - - func f2() int { - return 2 - }", - ); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - // 2 exits / 2 functions - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 0.0, - "max": 1.0 - }"### - ); -} diff --git a/crates/mehen-go/tests/halstead.rs b/crates/mehen-go/tests/halstead.rs deleted file mode 100644 index 4bcfc815..00000000 --- a/crates/mehen-go/tests/halstead.rs +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Halstead tests for the Go walker. -//! -//! Every legacy `check_metrics::` Halstead test from -//! `crates/mehen-engine/src/legacy/metrics/halstead.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = GoAnalyzer::new(); - let file = SourceFile::new("foo.go".into(), Language::Go, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn go_operators_and_operands() { - let a = analyze( - "package main - - func add(a, b int) int { - return a + b - }", - ); - let halstead = mehen_report::metrics_json::halstead(&a.root.metrics); - insta::assert_json_snapshot!( - halstead, - @r###" - { - "n1": 7.0, - "N1": 7.0, - "n2": 5.0, - "N2": 8.0, - "length": 15.0, - "estimated_program_length": 31.26112492884004, - "purity_ratio": 2.0840749952560027, - "vocabulary": 12.0, - "volume": 53.77443751081734, - "difficulty": 5.6, - "level": 0.17857142857142858, - "effort": 301.1368500605771, - "time": 16.729825003365395, - "bugs": 0.014975730436275946 - }"### - ); -} - -/// Regression: nested function spaces must carry their own Halstead -/// counts in the per-space JSON. PR #95 discussion_r3265658502 flagged -/// this on the Python walker; the Go walker had the same -/// `stack[0]`-only bug. -#[test] -fn go_nested_function_halstead_is_non_zero() { - // Go closures (anonymous funcs) get their own scope inside the - // enclosing function. The closure's body is a nested scope and - // must record its own Halstead. - let a = analyze( - "package main - -func outer() { - inner := func() int { - x := 1 + 2 - return x - } - inner() -}", - ); - assert_eq!(a.root.spaces.len(), 1, "expected outer fn"); - let outer = &a.root.spaces[0]; - assert!(!outer.spaces.is_empty(), "expected nested closure"); - let closure = &outer.spaces[0]; - let closure_h = mehen_report::metrics_json::halstead(&closure.metrics); - assert!( - closure_h.big_n1 > 0.0, - "closure must record `:=`, `+` operators, got {}", - serde_json::to_string(&closure_h).unwrap() - ); - assert!( - closure_h.big_n2 > 0.0, - "closure must record `x`, `1`, `2` operands, got {}", - serde_json::to_string(&closure_h).unwrap() - ); - let outer_h = mehen_report::metrics_json::halstead(&outer.metrics); - assert!( - outer_h.big_n1 >= closure_h.big_n1, - "outer N1 must roll up closure: outer={} closure={}", - serde_json::to_string(&outer_h).unwrap(), - serde_json::to_string(&closure_h).unwrap() - ); -} diff --git a/crates/mehen-go/tests/loc.rs b/crates/mehen-go/tests/loc.rs deleted file mode 100644 index 18193521..00000000 --- a/crates/mehen-go/tests/loc.rs +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC tests for the Go walker. -//! -//! Every legacy `check_metrics::` LOC test from -//! `crates/mehen-engine/src/legacy/metrics/loc.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - // Mirror the legacy `check_func_space` harness: trim trailing - // newlines/whitespace and re-append exactly one `\n`. Without this - // normalization the SLOC differs by ±1 depending on whether the - // raw fixture has a trailing newline. - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = GoAnalyzer::new(); - let file = SourceFile::new("foo.go".into(), Language::Go, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn go_sloc() { - let a = analyze( - "package main - - // A comment - func main() { - x := 1 - } - ", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - loc, - @r###" - { - "sloc": 6.0, - "ploc": 4.0, - "lloc": 1.0, - "cloc": 1.0, - "blank": 1.0, - "sloc_average": 3.0, - "ploc_average": 2.0, - "lloc_average": 0.5, - "cloc_average": 0.5, - "blank_average": 0.5, - "sloc_min": 3.0, - "sloc_max": 3.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 3.0, - "ploc_max": 3.0, - "lloc_min": 1.0, - "lloc_max": 1.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} - -#[test] -fn go_lloc() { - let a = analyze( - "package main - - func main() { - x := 1 - y := 2 - if x > y { - return - } - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - loc, - @r###" - { - "sloc": 9.0, - "ploc": 8.0, - "lloc": 4.0, - "cloc": 0.0, - "blank": 1.0, - "sloc_average": 4.5, - "ploc_average": 4.0, - "lloc_average": 2.0, - "cloc_average": 0.0, - "blank_average": 0.5, - "sloc_min": 7.0, - "sloc_max": 7.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 7.0, - "ploc_max": 7.0, - "lloc_min": 4.0, - "lloc_max": 4.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} - -#[test] -fn go_lloc_counts_go_declaration_specs_and_receive_statements() { - let a = analyze( - "package main - - import ( - \"fmt\" - _ \"net/http\" - ) - - var ( - a = 1 - b = 2 - ) - - func main(ch chan int) { - Loop: - <-ch - fmt.Println(a, b) - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - loc, - @r###" - { - "sloc": 17.0, - "ploc": 14.0, - "lloc": 7.0, - "cloc": 0.0, - "blank": 3.0, - "sloc_average": 8.5, - "ploc_average": 7.0, - "lloc_average": 3.5, - "cloc_average": 0.0, - "blank_average": 1.5, - "sloc_min": 5.0, - "sloc_max": 5.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 5.0, - "ploc_max": 5.0, - "lloc_min": 3.0, - "lloc_max": 3.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} diff --git a/crates/mehen-go/tests/nargs.rs b/crates/mehen-go/tests/nargs.rs deleted file mode 100644 index ebb17717..00000000 --- a/crates/mehen-go/tests/nargs.rs +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NArgs tests for the Go walker. -//! -//! Every legacy `check_metrics::` nargs test from -//! `crates/mehen-engine/src/legacy/metrics/nargs.rs` is ported here -//! byte-identical so the parity contract (plan §12.3.1) is visibly -//! maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_go::GoAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = GoAnalyzer::new(); - let file = SourceFile::new("foo.go".into(), Language::Go, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn go_grouped_and_variadic_parameters() { - // Drift from legacy: legacy reported `functions_min: 0.0` because - // its `compute_minmax` ran unconditionally for every space, so the - // unit space (which has no fn args) pulled the min down to 0. The - // 1.0 mehen-metrics `NargsStats::finalize_minmax` only includes - // a space in the function bounds if `is_function == true`, so the - // unit no longer dilutes the bounds. Result: `functions_min: 3.0` - // — matching the *only* function in this fixture. This drift is - // shared with Phase 6 Python and Phase 9 Ruby. - let a = analyze( - "package main - - func add(a, b int, rest ...string) int { - return a + b - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - nargs, - @r###" - { - "total_functions": 3.0, - "total_closures": 0.0, - "average_functions": 3.0, - "average_closures": 0.0, - "total": 3.0, - "average": 3.0, - "functions_min": 3.0, - "functions_max": 3.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn go_func_literal_parameters_are_counted_as_closures() { - // Drift from legacy: same as `go_grouped_and_variadic_parameters` - // — `closures_min` is now `3.0` because the only closure (the - // `func(x, y int, done chan bool)` literal) carries three - // parameters. Legacy reported `0.0` because the unit space (which - // has no closure args) pulled the bound down. - let a = analyze( - "package main - - func main() { - _ = func(x, y int, done chan bool) { - done <- x > y - } - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - nargs, - @r###" - { - "total_functions": 0.0, - "total_closures": 3.0, - "average_functions": 0.0, - "average_closures": 3.0, - "total": 3.0, - "average": 1.5, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 3.0, - "closures_max": 3.0 - }"### - ); -} diff --git a/crates/mehen-java-parser/Cargo.toml b/crates/mehen-java-parser/Cargo.toml deleted file mode 100644 index 936abf9a..00000000 --- a/crates/mehen-java-parser/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "mehen-java-parser" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -# Generated from `xtask/templates/parser-readme.md` by `cargo xtask antlr -# generate java` — never hand-edit. Named explicitly so it ships on the -# crate's registry page when published. -readme = "README.md" -description = "ANTLR-generated Java lexer and parser (grammars-v4 grammar) on the antlr-rust-runtime." -# Unlike the internal `mehen-*` analyzer crates (`publish = false`), this -# crate ships ONLY the generated lexer/parser so external tools can depend -# on the Java parser alone via a git tag on this repo — the same way -# `mehen` itself consumes ruff/oxc/sqruff parser crates. It carries no -# mehen-specific logic and no dependency on `mehen-core`. -publish = true - -[dependencies] -# The generated modules reference the runtime by its real crate name -# (`use antlr4_runtime::…`). Pinned in exactly one place — the workspace -# `[workspace.dependencies]` `antlr4_runtime` entry — so every consumer -# links the same revision the modules were generated against. Regenerate -# with `cargo xtask antlr generate java` after any bump. -antlr4_runtime = { workspace = true } - -# The generated modules are checked in verbatim and intentionally expose -# their whole surface, so this crate deliberately does NOT opt into the -# workspace `unreachable_pub` lint (`[lints] workspace = true`) that the -# hand-written crates use. diff --git a/crates/mehen-java-parser/README.md b/crates/mehen-java-parser/README.md deleted file mode 100644 index bb2f9912..00000000 --- a/crates/mehen-java-parser/README.md +++ /dev/null @@ -1,81 +0,0 @@ - -# mehen-java-parser - -ANTLR-generated **Java** lexer and parser, running on the -[`antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime) Rust -runtime. - -This crate is produced by the [`mehen`](https://github.com/ophi-dev/mehen) code-metrics tool but -carries **no mehen-specific logic** and **no dependency on `mehen-core`**: it -ships only the machine-generated lexer/parser plus the vendored `.g4` grammar. -That makes it usable on its own — the same way `mehen` itself consumes the -ruff / oxc / sqruff parser crates — so you can parse Java in your -own tool without pulling in an analyzer. - - - -## Add the dependency - -The crate is published from a git tag on the [`mehen` repository](https://github.com/ophi-dev/mehen), -not to crates.io. Depend on it by tag or branch: - -```toml -[dependencies] -# Pin a release tag (recommended) — see the repository's Releases page: -mehen-java-parser = { git = "https://github.com/ophi-dev/mehen", tag = "vX.Y.Z" } -# …or track the default branch: -# mehen-java-parser = { git = "https://github.com/ophi-dev/mehen", branch = "main" } -``` - -You do **not** need to depend on `antlr-rust-runtime` yourself: this crate -re-exports the exact runtime revision the modules were generated against as -`mehen_java_parser::antlr4_runtime`. Reach the runtime types (`ParsedFile`, -`Node`, `TokenView`, …) through that path so your version can never drift from -the generated code. - -## Parse some Java - -The grammar declares helper methods on a superclass (`superClass=…`); this -crate ships exact Rust ports as typed hooks in [`src/hooks.rs`](src/hooks.rs), -and they **must be installed at construction**. The modules are generated -under `--sem-unknown error`, so a lexer/parser built without its hooks -fails loud (`AntlrError::Unsupported`) the moment an input reaches a hooked -predicate or action — it never silently mis-parses. In particular, skip the -hook-less one-call `java_parser::parse` / `parse_with_parser` -helpers and construct with hooks: - -```rust -use mehen_java_parser::hooks::JavaParserBase; -use mehen_java_parser::java_parser::JavaParser; -use mehen_java_parser::java_lexer::JavaLexer; -use mehen_java_parser::antlr4_runtime::{CommonTokenStream, InputStream, Parser}; - -fn main() -> Result<(), mehen_java_parser::antlr4_runtime::AntlrError> { - let input = InputStream::new("class C {}\n"); - let lexer = JavaLexer::new(input); - let tokens = CommonTokenStream::new(lexer); - let mut parser = JavaParser::with_typed_hooks(tokens, JavaParserBase::default()); - let result = parser.compilation_unit()?; - - // Parser diagnostics, then the owned `ParsedFile` (token store + flat CST). - let errors = parser.number_of_syntax_errors(); - let parsed = parser.into_parsed_file(result); - let root = parsed.tree(); - let _ = (errors, root); - Ok(()) -} -``` - -The parse tree has **no parent pointers** (the runtime stores `Node` views in a -flat arena), so thread any parent-dependent context top-down as you walk. - -## Grammar & provenance - -- **Upstream grammar:** [`antlr/grammars-v4`](https://github.com/antlr/grammars-v4) -- **Vendored `.g4` files + any local patches:** [`grammar/`](grammar/) — see [`grammar/PROVENANCE.md`](grammar/PROVENANCE.md) for the exact commit -- **ANTLR Rust runtime + codegen:** [`antlr-rust-runtime`](https://crates.io/crates/antlr-rust-runtime) / [`antlr-rust-codegen`](https://crates.io/crates/antlr-rust-codegen) `v0.33.1` - -## License - -`AGPL-3.0-only`, same as the `mehen` workspace. diff --git a/crates/mehen-java-parser/grammar/JavaLexer.g4 b/crates/mehen-java-parser/grammar/JavaLexer.g4 deleted file mode 100644 index 5325cd18..00000000 --- a/crates/mehen-java-parser/grammar/JavaLexer.g4 +++ /dev/null @@ -1,224 +0,0 @@ -/* - [The "BSD licence"] - Copyright (c) 2013 Terence Parr, Sam Harwell - Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8) - Copyright (c) 2021 Michał Lorek (upgrade to Java 11) - Copyright (c) 2022 Michał Lorek (upgrade to Java 17) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar JavaLexer; - -// Keywords - -ABSTRACT : 'abstract'; -ASSERT : 'assert'; -BOOLEAN : 'boolean'; -BREAK : 'break'; -BYTE : 'byte'; -CASE : 'case'; -CATCH : 'catch'; -CHAR : 'char'; -CLASS : 'class'; -CONST : 'const'; -CONTINUE : 'continue'; -DEFAULT : 'default'; -DO : 'do'; -DOUBLE : 'double'; -ELSE : 'else'; -ENUM : 'enum'; -EXPORTS : 'exports'; -EXTENDS : 'extends'; -FINAL : 'final'; -FINALLY : 'finally'; -FLOAT : 'float'; -FOR : 'for'; -GOTO : 'goto'; -IF : 'if'; -IMPLEMENTS : 'implements'; -IMPORT : 'import'; -INSTANCEOF : 'instanceof'; -INT : 'int'; -INTERFACE : 'interface'; -LONG : 'long'; -MODULE : 'module'; -NATIVE : 'native'; -NEW : 'new'; -NON_SEALED : 'non-sealed'; -OPEN : 'open'; -OPENS : 'opens'; -PACKAGE : 'package'; -PERMITS : 'permits'; -PRIVATE : 'private'; -PROTECTED : 'protected'; -PROVIDES : 'provides'; -PUBLIC : 'public'; -RECORD: 'record'; -REQUIRES : 'requires'; -RETURN : 'return'; -SEALED : 'sealed'; -SHORT : 'short'; -STATIC : 'static'; -STRICTFP : 'strictfp'; -SUPER : 'super'; -SWITCH : 'switch'; -SYNCHRONIZED : 'synchronized'; -THIS : 'this'; -THROW : 'throw'; -THROWS : 'throws'; -TO : 'to'; -TRANSIENT : 'transient'; -TRANSITIVE : 'transitive'; -TRY : 'try'; -USES : 'uses'; -VAR: 'var'; // reserved type name -VOID : 'void'; -VOLATILE : 'volatile'; -WHEN : 'when'; -WHILE : 'while'; -WITH : 'with'; -YIELD: 'yield'; // reserved type name from Java 14 - -// Literals - -DECIMAL_LITERAL : ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?; -HEX_LITERAL : '0' [xX] [0-9a-fA-F] ([0-9a-fA-F_]* [0-9a-fA-F])? [lL]?; -OCT_LITERAL : '0' '_'* [0-7] ([0-7_]* [0-7])? [lL]?; -BINARY_LITERAL : '0' [bB] [01] ([01_]* [01])? [lL]?; - -FLOAT_LITERAL: - (Digits '.' Digits? | '.' Digits) ExponentPart? [fFdD]? - | Digits (ExponentPart [fFdD]? | [fFdD]) -; - -HEX_FLOAT_LITERAL: '0' [xX] (HexDigits '.'? | HexDigits? '.' HexDigits) [pP] [+-]? Digits [fFdD]?; - -BOOL_LITERAL: 'true' | 'false'; - -CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\''; - -STRING_LITERAL: '"' (~["\\\r\n] | EscapeSequence)* '"'; - -TEXT_BLOCK: '"""' [ \t]* [\r\n] (. | EscapeSequence)*? '"""'; - -NULL_LITERAL: 'null'; - -// Separators - -LPAREN : '('; -RPAREN : ')'; -LBRACE : '{'; -RBRACE : '}'; -LBRACK : '['; -RBRACK : ']'; -SEMI : ';'; -COMMA : ','; -DOT : '.'; - -// Operators - -ASSIGN : '='; -GT : '>'; -LT : '<'; -BANG : '!'; -TILDE : '~'; -QUESTION : '?'; -COLON : ':'; -EQUAL : '=='; -LE : '<='; -GE : '>='; -NOTEQUAL : '!='; -AND : '&&'; -OR : '||'; -INC : '++'; -DEC : '--'; -ADD : '+'; -SUB : '-'; -MUL : '*'; -DIV : '/'; -BITAND : '&'; -BITOR : '|'; -CARET : '^'; -MOD : '%'; - -ADD_ASSIGN : '+='; -SUB_ASSIGN : '-='; -MUL_ASSIGN : '*='; -DIV_ASSIGN : '/='; -AND_ASSIGN : '&='; -OR_ASSIGN : '|='; -XOR_ASSIGN : '^='; -MOD_ASSIGN : '%='; -LSHIFT_ASSIGN : '<<='; -RSHIFT_ASSIGN : '>>='; -URSHIFT_ASSIGN : '>>>='; - -// Java 8 tokens - -ARROW : '->'; -COLONCOLON : '::'; - -// Additional symbols not defined in the lexical specification - -AT : '@'; -ELLIPSIS : '...'; - -// Whitespace and comments - -WS : [ \t\r\n\u000C]+ -> channel(HIDDEN); -COMMENT : '/*' .*? '*/' -> channel(HIDDEN); -LINE_COMMENT : '//' ~[\r\n]* -> channel(HIDDEN); - -// Identifiers - -IDENTIFIER: Letter LetterOrDigit*; - -// Fragment rules - -fragment ExponentPart: [eE] [+-]? Digits; - -fragment EscapeSequence: - '\\' 'u005c'? [bstnfr"'\\] - | '\\' 'u005c'? ([0-3]? [0-7])? [0-7] - | '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit -; - -fragment HexDigits: HexDigit ((HexDigit | '_')* HexDigit)?; - -fragment HexDigit: [0-9a-fA-F]; - -fragment Digits: [0-9] ([0-9_]* [0-9])?; - -fragment LetterOrDigit: Letter | [0-9]; - -fragment Letter: - [a-zA-Z$_] // these are the "java letters" below 0x7F - | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate - | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF -; \ No newline at end of file diff --git a/crates/mehen-java-parser/grammar/JavaParser.g4 b/crates/mehen-java-parser/grammar/JavaParser.g4 deleted file mode 100644 index 1309ac21..00000000 --- a/crates/mehen-java-parser/grammar/JavaParser.g4 +++ /dev/null @@ -1,826 +0,0 @@ -/* - [The "BSD licence"] - Copyright (c) 2013 Terence Parr, Sam Harwell - Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8) - Copyright (c) 2021 Michał Lorek (upgrade to Java 11) - Copyright (c) 2022 Michał Lorek (upgrade to Java 17) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar JavaParser; - -options { - tokenVocab = JavaLexer; - superClass = JavaParserBase; -} - -compilationUnit - : packageDeclaration? (importDeclaration | ';')* (typeDeclaration | ';')* EOF - | modularCompulationUnit EOF - ; - -modularCompulationUnit - : importDeclaration* moduleDeclaration - ; - -packageDeclaration - : annotation* PACKAGE qualifiedName ';' - ; - -importDeclaration - : IMPORT STATIC? qualifiedName ('.' '*')? ';' - ; - -typeDeclaration - : classOrInterfaceModifier* ( - classDeclaration - | enumDeclaration - | interfaceDeclaration - | annotationTypeDeclaration - | recordDeclaration - ) - ; - -modifier - : classOrInterfaceModifier - | NATIVE - | SYNCHRONIZED - | TRANSIENT - | VOLATILE - ; - -classOrInterfaceModifier - : annotation - | PUBLIC - | PROTECTED - | PRIVATE - | STATIC - | ABSTRACT - | FINAL // FINAL for class only -- does not apply to interfaces - | STRICTFP - | SEALED - | NON_SEALED - ; - -variableModifier - : FINAL - | annotation - ; - -classDeclaration - : CLASS identifier typeParameters? (EXTENDS typeType)? (IMPLEMENTS typeList)? ( - PERMITS typeList - )? - classBody - ; - -typeParameters - : '<' typeParameter (',' typeParameter)* '>' - ; - -typeParameter - : annotation* identifier (EXTENDS annotation* typeBound)? - ; - -typeBound - : typeType ('&' typeType)* - ; - -enumDeclaration - : ENUM identifier (IMPLEMENTS typeList)? '{' enumConstants? ','? enumBodyDeclarations? '}' - ; - -enumConstants - : enumConstant (',' enumConstant)* - ; - -enumConstant - : annotation* identifier arguments? classBody? - ; - -enumBodyDeclarations - : ';' classBodyDeclaration* - ; - -interfaceDeclaration - : INTERFACE identifier typeParameters? (EXTENDS typeList)? (PERMITS typeList)? interfaceBody - ; - -classBody - : '{' classBodyDeclaration* '}' - ; - -interfaceBody - : '{' interfaceBodyDeclaration* '}' - ; - -classBodyDeclaration - : ';' - | STATIC? block - | modifier* memberDeclaration - ; - -memberDeclaration - : recordDeclaration - | methodDeclaration - | genericMethodDeclaration - | fieldDeclaration - | constructorDeclaration - | genericConstructorDeclaration - | interfaceDeclaration - | annotationTypeDeclaration - | classDeclaration - | enumDeclaration - ; - -/* We use rule this even for void methods which cannot have [] after parameters. - This simplifies grammar and we can consider void to be a type, which - renders the [] matching as a context-sensitive issue or a semantic check - for invalid return type after parsing. - */ -methodDeclaration - : typeTypeOrVoid identifier formalParameters ('[' ']')* (THROWS qualifiedNameList)? methodBody - ; - -methodBody - : block - | ';' - ; - -typeTypeOrVoid - : typeType - | VOID - ; - -genericMethodDeclaration - : typeParameters methodDeclaration - ; - -genericConstructorDeclaration - : typeParameters constructorDeclaration - ; - -constructorDeclaration - : identifier formalParameters (THROWS qualifiedNameList)? constructorBody = block - ; - -compactConstructorDeclaration - : modifier* identifier constructorBody = block - ; - -fieldDeclaration - : typeType variableDeclarators ';' - ; - -interfaceBodyDeclaration - : modifier* interfaceMemberDeclaration - | ';' - ; - -interfaceMemberDeclaration - : recordDeclaration - | constDeclaration - | interfaceMethodDeclaration - | genericInterfaceMethodDeclaration - | interfaceDeclaration - | annotationTypeDeclaration - | classDeclaration - | enumDeclaration - ; - -constDeclaration - : typeType constantDeclarator (',' constantDeclarator)* ';' - ; - -constantDeclarator - : identifier ('[' ']')* '=' variableInitializer - ; - -// Early versions of Java allows brackets after the method name, eg. -// public int[] return2DArray() [] { ... } -// is the same as -// public int[][] return2DArray() { ... } -interfaceMethodDeclaration - : interfaceMethodModifier* interfaceCommonBodyDeclaration - ; - -interfaceMethodModifier - : annotation - | PUBLIC - | ABSTRACT - | DEFAULT - | STATIC - | STRICTFP - ; - -genericInterfaceMethodDeclaration - : interfaceMethodModifier* typeParameters interfaceCommonBodyDeclaration - ; - -interfaceCommonBodyDeclaration - : annotation* typeTypeOrVoid identifier formalParameters ('[' ']')* (THROWS qualifiedNameList)? methodBody - ; - -variableDeclarators - : variableDeclarator (',' variableDeclarator)* - ; - -variableDeclarator - : variableDeclaratorId ('=' variableInitializer)? - ; - -variableDeclaratorId - : identifier ('[' ']')* - ; - -variableInitializer - : arrayInitializer - | expression - ; - -arrayInitializer - : '{' (variableInitializer (',' variableInitializer)* ','?)? '}' - ; - -classType: - ( - ( packageName '.' annotation* )? typeIdentifier typeArguments? - )+ ( '.' annotation* typeIdentifier typeArguments? )* - ; - -packageName: - identifier ('.' identifier)* - ; - -typeArgument - : typeType - | annotation* '?' ((EXTENDS | SUPER) typeType)? - ; - -qualifiedNameList - : qualifiedName (',' qualifiedName)* - ; - -formalParameters - : '(' ( - ( receiverParameter | formalParameter ) (',' formalParameterList)* - )? ')' - ; - -receiverParameter - : typeType (identifier '.')* THIS - ; - -formalParameterList - : formalParameter (',' formalParameter)* - ; - -formalParameter - : variableModifier* typeType (annotation* '...')? variableDeclaratorId - ; - -// local variable type inference -lambdaLVTIList - : lambdaLVTIParameter (',' lambdaLVTIParameter)* - ; - -lambdaLVTIParameter - : variableModifier* VAR identifier - ; - -qualifiedName - : identifier ('.' identifier)* - ; - -literal - : integerLiteral - | floatLiteral - | CHAR_LITERAL - | STRING_LITERAL - | BOOL_LITERAL - | NULL_LITERAL - | TEXT_BLOCK - ; - -integerLiteral - : DECIMAL_LITERAL - | HEX_LITERAL - | OCT_LITERAL - | BINARY_LITERAL - ; - -floatLiteral - : FLOAT_LITERAL - | HEX_FLOAT_LITERAL - ; - -// ANNOTATIONS -altAnnotationQualifiedName - : (identifier DOT)* '@' identifier - ; - -//annotation -// : ('@' qualifiedName /* | altAnnotationQualifiedName */) ( '(' ( elementValuePairs | elementValue)? ')')? -// ; - -annotation : - ('@' qualifiedName /* | altAnnotationQualifiedName */) annotationFieldValues? - ; - -annotationFieldValues: - '(' ( annotationFieldValue ( ',' annotationFieldValue )* )? ')' - ; - -annotationFieldValue: - { this.IsNotIdentifierAssign() }? annotationValue - | identifier '=' annotationValue - ; - -annotationValue: - expression //conditionalExpression - | annotation - | '{' ( annotationValue ( ',' annotationValue )* )? ','? '}' - ; - -//elementValuePairs -// : elementValuePair (',' elementValuePair)* -// ; - -//elementValuePair -// : identifier '=' elementValue -// ; - -elementValue - : expression - | annotation - | elementValueArrayInitializer - ; - -elementValueArrayInitializer - : '{' (elementValue (',' elementValue)*)? ','? '}' - ; - -annotationTypeDeclaration - : '@' INTERFACE identifier annotationTypeBody - ; - -annotationTypeBody - : '{' annotationTypeElementDeclaration* '}' - ; - -annotationTypeElementDeclaration - : modifier* annotationTypeElementRest - | ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler - ; - -annotationTypeElementRest - : typeType annotationMethodOrConstantRest ';' - | classDeclaration ';'? - | interfaceDeclaration ';'? - | enumDeclaration ';'? - | annotationTypeDeclaration ';'? - | recordDeclaration ';'? - ; - -annotationMethodOrConstantRest - : annotationMethodRest - | annotationConstantRest - ; - -annotationMethodRest - : identifier '(' ')' defaultValue? - ; - -annotationConstantRest - : variableDeclarators - ; - -defaultValue - : DEFAULT elementValue - ; - -moduleDeclaration - : annotation* OPEN? MODULE qualifiedName '{' moduleDirective* '}' - ; - -moduleDirective - : REQUIRES requiresModifier* qualifiedName ';' - | EXPORTS qualifiedName (TO qualifiedName (',' qualifiedName)* )? ';' - | OPENS qualifiedName (TO qualifiedName (',' qualifiedName)* )? ';' - | USES qualifiedName ';' - | PROVIDES qualifiedName WITH qualifiedName (',' qualifiedName)* ';' - ; - -requiresModifier - : TRANSITIVE - | STATIC - ; - -recordDeclaration - : RECORD identifier typeParameters? recordHeader (IMPLEMENTS typeList)? recordBody - ; - -recordHeader - : '(' recordComponentList? ')' - ; - -recordComponentList - : recordComponent (',' recordComponent)* { this.DoLastRecordComponent() }? - ; - -recordComponent - : annotation* typeType (annotation* ELLIPSIS)? identifier - ; - -recordBody - : '{' (classBodyDeclaration | compactConstructorDeclaration)* '}' - ; - -// STATEMENTS / BLOCKS - -block - : '{' blockStatement* '}' - ; - -blockStatement - : localVariableDeclaration ';' - | localTypeDeclaration - | statement - ; - -localVariableDeclaration - : variableModifier* (VAR identifier '=' expression | typeType variableDeclarators) - ; - -identifier - : IDENTIFIER - | MODULE - | OPEN - | REQUIRES - | EXPORTS - | OPENS - | TO - | USES - | PROVIDES - | WHEN - | WITH - | TRANSITIVE - | YIELD - | SEALED - | PERMITS - | RECORD - | VAR - ; - -typeIdentifier // Identifiers that are not restricted for type declarations - : IDENTIFIER - | MODULE - | OPEN - | REQUIRES - | EXPORTS - | OPENS - | TO - | USES - | PROVIDES - | WITH - | TRANSITIVE - | SEALED - ; - -localTypeDeclaration - : classOrInterfaceModifier* (classDeclaration | interfaceDeclaration | recordDeclaration | enumDeclaration) - ; - -statement - : blockLabel = block - | ASSERT expression (':' expression)? ';' - | IF '(' expression ')' statement (ELSE statement)? - | FOR '(' forControl ')' statement - | WHILE '(' expression ')' statement - | DO statement WHILE '(' expression ')' ';' - | TRY block (catchClause+ finallyBlock? | finallyBlock) - | TRY resourceSpecification block catchClause* finallyBlock? - | SWITCH '(' expression ')' '{' switchBlockStatementGroup* switchLabel* '}' - | SYNCHRONIZED '(' expression ')' block - | RETURN expression? ';' - | THROW expression ';' - | BREAK identifier? ';' - | CONTINUE identifier? ';' - | YIELD expression ';' - | SEMI - | statementExpression = expression ';' - | switchExpression ';'? - | identifierLabel = identifier ':' statement - ; - -catchClause - : CATCH '(' variableModifier* catchType identifier ')' block - ; - -catchType - : qualifiedName ('|' qualifiedName)* - ; - -finallyBlock - : FINALLY block - ; - -resourceSpecification - : '(' resources ';'? ')' - ; - -resources - : resource (';' resource)* - ; - -resource - : variableModifier* (classOrInterfaceType variableDeclaratorId | VAR identifier) '=' expression - | qualifiedName - ; - -/** Matches cases then statements, both of which are mandatory. - * To handle empty cases at the end, we add switchLabel* to statement. - */ -switchBlockStatementGroup - : (switchLabel ':')+ blockStatement+ - ; - -switchLabel - : CASE ( - constantExpression = expression - | enumConstantName = IDENTIFIER - | typeType varName = identifier - ) - | DEFAULT - ; - -forControl - : enhancedForControl - | forInit? ';' expression? ';' forUpdate = expressionList? - ; - -forInit - : localVariableDeclaration - | expressionList - ; - -enhancedForControl - : variableModifier* (typeType | VAR) variableDeclaratorId ':' expression - ; - -// EXPRESSIONS - -expressionList - : expression (',' expression)* - ; - -methodCall - : (identifier | THIS | SUPER) arguments - ; - -expression - // Expression order in accordance with https://introcs.cs.princeton.edu/java/11precedence/ - // Level 16, Primary, array and member access - : primary #PrimaryExpression - | expression '[' expression ']' #SquareBracketExpression - | expression bop = '.' ( - identifier - | methodCall - | THIS - | NEW nonWildcardTypeArguments? innerCreator - | SUPER superSuffix - | explicitGenericInvocation - ) #MemberReferenceExpression - // Method calls and method references are part of primary, and hence level 16 precedence - | methodCall #MethodCallExpression - | expression '::' typeArguments? identifier #MethodReferenceExpression - | typeType '::' (typeArguments? identifier | NEW) #MethodReferenceExpression - | classType '::' typeArguments? NEW #MethodReferenceExpression - - | switchExpression #ExpressionSwitch - - // Level 15 Post-increment/decrement operators - | expression postfix = ('++' | '--') #PostIncrementDecrementOperatorExpression - - // Level 14, Unary operators - | prefix = ('+' | '-' | '++' | '--' | '~' | '!') expression #UnaryOperatorExpression - - // Level 13 Cast and object creation - | '(' annotation* typeType ('&' typeType)* ')' expression #CastExpression - | NEW creator #ObjectCreationExpression - - // Level 12 to 1, Remaining operators - // Level 12, Multiplicative operators - | expression bop = ('*' | '/' | '%') expression #BinaryOperatorExpression - // Level 11, Additive operators - | expression bop = ('+' | '-') expression #BinaryOperatorExpression - // Level 10, Shift operators - | expression ('<' '<' | '>' '>' '>' | '>' '>') expression #BinaryOperatorExpression - // Level 9, Relational operators - | expression bop = ('<=' | '>=' | '>' | '<') expression #BinaryOperatorExpression - | expression bop = INSTANCEOF (typeType | pattern) #InstanceOfOperatorExpression - // Level 8, Equality Operators - | expression bop = ('==' | '!=') expression #BinaryOperatorExpression - // Level 7, Bitwise AND - | expression bop = '&' expression #BinaryOperatorExpression - // Level 6, Bitwise XOR - | expression bop = '^' expression #BinaryOperatorExpression - // Level 5, Bitwise OR - | expression bop = '|' expression #BinaryOperatorExpression - // Level 4, Logic AND - | expression bop = '&&' expression #BinaryOperatorExpression - // Level 3, Logic OR - | expression bop = '||' expression #BinaryOperatorExpression - // Level 2, Ternary - | expression bop = '?' expression ':' expression #TernaryExpression - // Level 1, Assignment - | expression bop = ( - '=' - | '+=' - | '-=' - | '*=' - | '/=' - | '&=' - | '|=' - | '^=' - | '>>=' - | '>>>=' - | '<<=' - | '%=' - ) expression #BinaryOperatorExpression - - // Level 0, Lambda Expression - | lambdaExpression #ExpressionLambda - ; - -pattern - : variableModifier* typeType annotation* variableDeclarators - | typeType '(' componentPatternList? ')' - ; - -componentPatternList : - componentPattern ( ',' componentPattern )* - ; - -componentPattern : - pattern - ; - -lambdaExpression - : lambdaParameters '->' lambdaBody - ; - -lambdaParameters - : identifier - | '(' formalParameterList? ')' - | '(' identifier (',' identifier)* ')' - | '(' lambdaLVTIList? ')' - ; - -lambdaBody - : expression - | block - ; - -primary - : '(' expression ')' - | THIS - | SUPER - | literal - | identifier - | typeTypeOrVoid '.' CLASS - | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments) - ; - -switchExpression - : SWITCH '(' expression ')' '{' switchLabeledRule* '}' - ; - -switchLabeledRule - : CASE ( - expressionList - | NULL_LITERAL (',' DEFAULT)? - | casePattern (',' casePattern)* guard? - ) (ARROW | COLON) switchRuleOutcome - | DEFAULT (ARROW | COLON) switchRuleOutcome - ; - -guard - : 'when' expression - ; - -casePattern - : pattern - ; - -switchRuleOutcome - : block - | blockStatement* // is *-operator correct??? I don't think so. https://docs.oracle.com/javase/specs/jls/se24/html/jls-14.html#jls-BlockStatements - ; - -classOrInterfaceType - : classType // classType, interfaceType are all essentially identical to classOrInterfaceType because of no symbol table. - ; - -creator - : nonWildcardTypeArguments? createdName classCreatorRest - | createdName arrayCreatorRest - ; - -createdName - : identifier typeArgumentsOrDiamond? ('.' identifier typeArgumentsOrDiamond?)* - | primitiveType - ; - -innerCreator - : identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest - ; - -arrayCreatorRest - : ('[' ']')+ arrayInitializer - | ('[' expression ']')+ ('[' ']')* - ; - -classCreatorRest - : arguments classBody? - ; - -explicitGenericInvocation - : nonWildcardTypeArguments explicitGenericInvocationSuffix - ; - -typeArgumentsOrDiamond - : '<' '>' - | typeArguments - ; - -nonWildcardTypeArgumentsOrDiamond - : '<' '>' - | nonWildcardTypeArguments - ; - -nonWildcardTypeArguments - : '<' typeList '>' - ; - -typeList - : typeType (',' typeType)* - ; - -typeType - : annotation* (classOrInterfaceType | primitiveType) (annotation* '[' ']')* - ; - -primitiveType - : BOOLEAN - | CHAR - | BYTE - | SHORT - | INT - | LONG - | FLOAT - | DOUBLE - ; - -typeArguments - : '<' typeArgument (',' typeArgument)* '>' - ; - -superSuffix - : arguments - | '.' typeArguments? identifier arguments? - ; - -explicitGenericInvocationSuffix - : SUPER superSuffix - | identifier arguments - ; - -arguments - : '(' expressionList? ')' - ; diff --git a/crates/mehen-java-parser/grammar/PROVENANCE.md b/crates/mehen-java-parser/grammar/PROVENANCE.md deleted file mode 100644 index 889a4bbc..00000000 --- a/crates/mehen-java-parser/grammar/PROVENANCE.md +++ /dev/null @@ -1,97 +0,0 @@ -# Java ANTLR grammar — provenance - -These `.g4` files are the **source of truth** for the Java analyzer's parser. -They are vendored verbatim from upstream (no local patches — see "Local -patches" below); the generated Rust modules in `../src/generated/` are -produced from them by `cargo run -p xtask -- antlr generate java`. - -## Source - -| Field | Value | -|---|---| -| Upstream | [`antlr/grammars-v4`](https://github.com/antlr/grammars-v4) — the community-maintained ANTLR v4 grammar collection | -| Path | `java/java/{JavaLexer,JavaParser}.g4` | -| Branch | `master` | -| Commit | `37146747969be81255787b80d476873ec24d2626` (last change to `java/java/JavaParser.g4`, 2025-08-31) | - -`JavaLexer.g4` and `JavaParser.g4` are self-contained — neither `import`s -another grammar (unlike the Kotlin grammar's `UnicodeClasses`), so no extra -`.g4` files are vendored. - -## Known upstream issue: one unreachable rule (pruned) - -Generation reports, then removes, one unreachable rule: - -```text -warning[G4S078]: JavaParser.g4:343:0: parser rule altAnnotationQualifiedName -is unreachable from entry rule compilationUnit -pruned: JavaParser.g4:343:0: unreachable parser rule JavaParser.altAnnotationQualifiedName -``` - -It is a real upstream defect, not a false positive: the rule's only two call -sites (lines 348 and 352) both have it **commented out**, so nothing can reach -it. The grammar is still vendored verbatim — the rule is dropped during -generation, not edited out of the `.g4` — so fixing it properly remains -upstream's call in `antlr/grammars-v4`. - -Both steps need `--entry-rule compilationUnit`, which generation passes: without -it the generator conservatively treats every top-level rule that reaches `EOF` as -its own entry, so no rule can ever be unreachable. `--prune-unreachable` then -removes exactly the reported set (upstream #262/#264); pruning saved ~19 KB of -generated Rust here. - -## Local patches - -**None.** Unlike the Kotlin grammar (which needs a `RCURL` mode-pop patch), -the Java grammar is vendored unmodified. Its two Java-target semantic -predicates are routed to hand-written hooks, not dropped and not patched -out of the grammar: - -- `JavaParser.g4` declares `options { superClass = JavaParserBase; }` and uses - two host-language (Java) semantic predicates: - - `{ this.IsNotIdentifierAssign() }?` (annotation `key = value` - disambiguation), and - - `{ this.DoLastRecordComponent() }?` (varargs record component must be - last). - - `patterns.toml` (this directory) lowers both helper calls to **typed - hooks**, and `../src/hooks.rs` ports the upstream - `Java/JavaParserBase.java` semantics exactly (`JavaParserBase`, installed - via `JavaParser::with_typed_hooks`). Generation runs with `--sem-unknown - error --require-full-semantics`, so any *new* helper appearing in a future - grammar update fails `cargo xtask antlr generate java` instead of silently - degrading parse fidelity; the same policy makes a hook-less parser - (`JavaParser::new`) fail loud at the first hooked predicate rather than - mis-parse. The upstream `Java/JavaParserBase.java` file itself is **not** - vendored — it is Java-only; `src/hooks.rs` is its Rust counterpart. - - The `precpred(...)` calls in the generated parser are *precedence* - predicates for left-recursive expression rules; the runtime evaluates those - automatically and they are unrelated to the two hooked predicates. - -## Toolchain - -| Tool | Version | -|---|---| -| Rust runtime + codegen | [`ophi-dev/antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime) `v0.29.0` | - -## Regenerating - -Never hand-edit the files in `../src/generated/`. To regenerate after bumping -the grammar or the runtime: - -```bash -cargo run -p xtask -- antlr generate java -``` - -That command configures `antlr_rust_codegen::Builder` with the equivalent of: - -```rust -Builder::new() - .grammar("JavaLexer.g4") - .grammar("JavaParser.g4") - .out_dir("../src/generated") -``` - -The analyzer parses via the generated `compilationUnit` -(`JavaParser::compilation_unit()`) entry rule. diff --git a/crates/mehen-java-parser/grammar/patterns.toml b/crates/mehen-java-parser/grammar/patterns.toml deleted file mode 100644 index 05f79721..00000000 --- a/crates/mehen-java-parser/grammar/patterns.toml +++ /dev/null @@ -1,37 +0,0 @@ -version = 1 - -# Semantic-helper lowerings for the grammars-v4 Java grammar (loaded through -# `antlr_rust_codegen::Builder::semantic_patterns` by -# `cargo xtask antlr generate java`). -# -# The grammar's `superClass = JavaParserBase` declares two `this.…()` helper -# predicates whose reference implementation lives in the upstream Java class -# `java/java/Java/JavaParserBase.java`. Neither is expressible in the pure -# pattern DSL (one needs a 17-token set membership test plus a second -# lookahead, the other iterates the current rule context's children), so both -# lower to typed hooks; the exact Rust port lives in this crate's -# `src/hooks.rs` (`JavaParserBase`) and MUST be installed via -# `JavaParser::with_typed_hooks` — a hook predicate evaluated without hooks -# fails the parse under the `--sem-unknown error` policy instead of silently -# assuming `true`. - -# `annotationFieldValue: { this.IsNotIdentifierAssign() }? annotationValue -# | identifier '=' annotationValue` -# True unless the lookahead is ` =`, steering `name = value` -# annotation arguments to the explicit `identifier '=' annotationValue` -# alternative instead of parsing them as an assignment *expression*. -[[helper]] -kind = "parser-predicate" -name = "IsNotIdentifierAssign" -returns = "bool" -lower = "hook" - -# `recordComponentList: recordComponent (',' recordComponent)* -# { this.DoLastRecordComponent() }?` -# False when a varargs (`...`) record component is followed by another -# component, rejecting `record R(int... xs, int y)` at parse time. -[[helper]] -kind = "parser-predicate" -name = "DoLastRecordComponent" -returns = "bool" -lower = "hook" diff --git a/crates/mehen-java-parser/src/generated/README.md b/crates/mehen-java-parser/src/generated/README.md deleted file mode 100644 index 00a548b9..00000000 --- a/crates/mehen-java-parser/src/generated/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Generated ANTLR modules — DO NOT EDIT - -`java_lexer.rs`, `java_parser.rs`, `decisions.json`, and `semantics.json` are -generated from the vendored grammar in `../../grammar/` by -`cargo xtask antlr generate java`. They are checked in (like the tree-sitter -`grammar.rs` kind enums), so a normal `cargo build` uses them without compiling -xtask's `antlr-rust-codegen` dependency. All four artifacts are drift-checked by -`cargo xtask antlr check-generated`. - -Regenerate — never hand-edit — via `cargo xtask antlr generate java`. See -`../../grammar/PROVENANCE.md` for the exact grammar commit and runtime/codegen -versions. `cargo xtask antlr check-generated` guards against drift in CI. diff --git a/crates/mehen-java-parser/src/generated/decisions.json b/crates/mehen-java-parser/src/generated/decisions.json deleted file mode 100644 index 4c97a0a1..00000000 --- a/crates/mehen-java-parser/src/generated/decisions.json +++ /dev/null @@ -1,1795 +0,0 @@ -{ - "version": 2, - "fixedLookahead": null, - "grammars": [ - { - "name": "JavaParser", - "summary": { - "total": 230, - "ll1": 146, - "fixed": 0, - "adaptive": 84 - }, - "decisions": [ - { - "decision": 0, - "rule": "compilationUnit", - "state": 257, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 1, - "rule": "compilationUnit", - "state": 261, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 2, - "rule": "compilationUnit", - "state": 263, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 3, - "rule": "compilationUnit", - "state": 268, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 4, - "rule": "compilationUnit", - "state": 270, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 5, - "rule": "compilationUnit", - "state": 277, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 6, - "rule": "modularCompulationUnit", - "state": 282, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 7, - "rule": "packageDeclaration", - "state": 290, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 8, - "rule": "importDeclaration", - "state": 299, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 9, - "rule": "importDeclaration", - "state": 304, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 10, - "rule": "typeDeclaration", - "state": 311, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 11, - "rule": "typeDeclaration", - "state": 319, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 12, - "rule": "modifier", - "state": 326, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 13, - "rule": "classOrInterfaceModifier", - "state": 338, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 14, - "rule": "variableModifier", - "state": 342, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 15, - "rule": "classDeclaration", - "state": 347, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 16, - "rule": "classDeclaration", - "state": 351, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 17, - "rule": "classDeclaration", - "state": 355, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 18, - "rule": "classDeclaration", - "state": 359, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 19, - "rule": "typeParameters", - "state": 369, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 20, - "rule": "typeParameter", - "state": 377, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 21, - "rule": "typeParameter", - "state": 385, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 22, - "rule": "typeParameter", - "state": 389, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 23, - "rule": "typeBound", - "state": 396, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 24, - "rule": "enumDeclaration", - "state": 403, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 25, - "rule": "enumDeclaration", - "state": 407, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 26, - "rule": "enumDeclaration", - "state": 410, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 27, - "rule": "enumDeclaration", - "state": 413, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 28, - "rule": "enumConstants", - "state": 422, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 29, - "rule": "enumConstant", - "state": 428, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 30, - "rule": "enumConstant", - "state": 433, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 31, - "rule": "enumConstant", - "state": 436, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 32, - "rule": "enumBodyDeclarations", - "state": 442, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 33, - "rule": "interfaceDeclaration", - "state": 448, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 34, - "rule": "interfaceDeclaration", - "state": 452, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 35, - "rule": "interfaceDeclaration", - "state": 456, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 36, - "rule": "classBody", - "state": 464, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 37, - "rule": "interfaceBody", - "state": 473, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 38, - "rule": "classBodyDeclaration", - "state": 480, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 39, - "rule": "classBodyDeclaration", - "state": 486, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 40, - "rule": "classBodyDeclaration", - "state": 490, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 41, - "rule": "memberDeclaration", - "state": 502, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 42, - "rule": "methodDeclaration", - "state": 511, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 43, - "rule": "methodDeclaration", - "state": 516, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 44, - "rule": "methodBody", - "state": 522, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 45, - "rule": "typeTypeOrVoid", - "state": 526, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 46, - "rule": "constructorDeclaration", - "state": 538, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 47, - "rule": "compactConstructorDeclaration", - "state": 545, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 48, - "rule": "interfaceBodyDeclaration", - "state": 558, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 49, - "rule": "interfaceBodyDeclaration", - "state": 563, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 50, - "rule": "interfaceMemberDeclaration", - "state": 573, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 51, - "rule": "constDeclaration", - "state": 581, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 52, - "rule": "constantDeclarator", - "state": 591, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 53, - "rule": "interfaceMethodDeclaration", - "state": 600, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 54, - "rule": "interfaceMethodModifier", - "state": 611, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 55, - "rule": "genericInterfaceMethodDeclaration", - "state": 616, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 56, - "rule": "interfaceCommonBodyDeclaration", - "state": 625, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 57, - "rule": "interfaceCommonBodyDeclaration", - "state": 635, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 58, - "rule": "interfaceCommonBodyDeclaration", - "state": 640, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 59, - "rule": "variableDeclarators", - "state": 649, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 60, - "rule": "variableDeclarator", - "state": 655, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 61, - "rule": "variableDeclaratorId", - "state": 662, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 62, - "rule": "variableInitializer", - "state": 667, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 63, - "rule": "arrayInitializer", - "state": 675, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 64, - "rule": "arrayInitializer", - "state": 679, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 65, - "rule": "arrayInitializer", - "state": 681, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 66, - "rule": "classType", - "state": 690, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 67, - "rule": "classType", - "state": 693, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 68, - "rule": "classType", - "state": 697, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 69, - "rule": "classType", - "state": 701, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 70, - "rule": "classType", - "state": 707, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 71, - "rule": "classType", - "state": 712, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 72, - "rule": "classType", - "state": 716, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 73, - "rule": "packageName", - "state": 724, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 74, - "rule": "typeArgument", - "state": 731, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 75, - "rule": "typeArgument", - "state": 737, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 76, - "rule": "typeArgument", - "state": 739, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 77, - "rule": "qualifiedNameList", - "state": 746, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 78, - "rule": "formalParameters", - "state": 752, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 79, - "rule": "formalParameters", - "state": 758, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 80, - "rule": "formalParameters", - "state": 761, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 81, - "rule": "receiverParameter", - "state": 771, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 82, - "rule": "formalParameterList", - "state": 781, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 83, - "rule": "formalParameter", - "state": 787, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 84, - "rule": "formalParameter", - "state": 794, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 85, - "rule": "formalParameter", - "state": 798, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 86, - "rule": "lambdaLVTIList", - "state": 807, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 87, - "rule": "lambdaLVTIParameter", - "state": 813, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 88, - "rule": "qualifiedName", - "state": 824, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 89, - "rule": "literal", - "state": 834, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 90, - "rule": "annotation", - "state": 844, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 91, - "rule": "annotationFieldValues", - "state": 852, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 92, - "rule": "annotationFieldValues", - "state": 855, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 93, - "rule": "annotationFieldValue", - "state": 865, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 94, - "rule": "annotationValue", - "state": 875, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 95, - "rule": "annotationValue", - "state": 878, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 96, - "rule": "annotationValue", - "state": 881, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 97, - "rule": "annotationValue", - "state": 884, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 98, - "rule": "elementValue", - "state": 889, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 99, - "rule": "elementValueArrayInitializer", - "state": 897, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 100, - "rule": "elementValueArrayInitializer", - "state": 900, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 101, - "rule": "elementValueArrayInitializer", - "state": 903, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 102, - "rule": "annotationTypeBody", - "state": 916, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 103, - "rule": "annotationTypeElementDeclaration", - "state": 924, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 104, - "rule": "annotationTypeElementDeclaration", - "state": 929, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 105, - "rule": "annotationTypeElementRest", - "state": 937, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 106, - "rule": "annotationTypeElementRest", - "state": 941, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 107, - "rule": "annotationTypeElementRest", - "state": 945, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 108, - "rule": "annotationTypeElementRest", - "state": 949, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 109, - "rule": "annotationTypeElementRest", - "state": 953, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 110, - "rule": "annotationTypeElementRest", - "state": 955, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 111, - "rule": "annotationMethodOrConstantRest", - "state": 959, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 112, - "rule": "annotationMethodRest", - "state": 965, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 113, - "rule": "moduleDeclaration", - "state": 975, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 114, - "rule": "moduleDeclaration", - "state": 979, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 115, - "rule": "moduleDeclaration", - "state": 987, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 116, - "rule": "moduleDirective", - "state": 996, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 117, - "rule": "moduleDirective", - "state": 1010, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 118, - "rule": "moduleDirective", - "state": 1013, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 119, - "rule": "moduleDirective", - "state": 1025, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 120, - "rule": "moduleDirective", - "state": 1028, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 121, - "rule": "moduleDirective", - "state": 1044, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 122, - "rule": "moduleDirective", - "state": 1049, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 123, - "rule": "recordDeclaration", - "state": 1056, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 124, - "rule": "recordDeclaration", - "state": 1061, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 125, - "rule": "recordHeader", - "state": 1067, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 126, - "rule": "recordComponentList", - "state": 1076, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 127, - "rule": "recordComponent", - "state": 1084, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 128, - "rule": "recordComponent", - "state": 1091, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 129, - "rule": "recordComponent", - "state": 1095, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 130, - "rule": "recordBody", - "state": 1102, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 131, - "rule": "recordBody", - "state": 1104, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 132, - "rule": "block", - "state": 1113, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 133, - "rule": "blockStatement", - "state": 1123, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 134, - "rule": "localVariableDeclaration", - "state": 1128, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 135, - "rule": "localVariableDeclaration", - "state": 1139, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 136, - "rule": "localTypeDeclaration", - "state": 1148, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 137, - "rule": "localTypeDeclaration", - "state": 1155, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 138, - "rule": "statement", - "state": 1162, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 139, - "rule": "statement", - "state": 1173, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 140, - "rule": "statement", - "state": 1200, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 141, - "rule": "statement", - "state": 1203, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 142, - "rule": "statement", - "state": 1206, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 143, - "rule": "statement", - "state": 1214, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 144, - "rule": "statement", - "state": 1218, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 145, - "rule": "statement", - "state": 1228, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 146, - "rule": "statement", - "state": 1234, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 147, - "rule": "statement", - "state": 1247, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 148, - "rule": "statement", - "state": 1256, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 149, - "rule": "statement", - "state": 1261, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 150, - "rule": "statement", - "state": 1274, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 151, - "rule": "statement", - "state": 1280, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 152, - "rule": "catchClause", - "state": 1287, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 153, - "rule": "catchType", - "state": 1300, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 154, - "rule": "resourceSpecification", - "state": 1309, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 155, - "rule": "resources", - "state": 1318, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 156, - "rule": "resource", - "state": 1324, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 157, - "rule": "resource", - "state": 1332, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 158, - "rule": "resource", - "state": 1338, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 159, - "rule": "switchBlockStatementGroup", - "state": 1345, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 160, - "rule": "switchBlockStatementGroup", - "state": 1350, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 161, - "rule": "switchLabel", - "state": 1358, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 162, - "rule": "switchLabel", - "state": 1361, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 163, - "rule": "forControl", - "state": 1365, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 164, - "rule": "forControl", - "state": 1369, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 165, - "rule": "forControl", - "state": 1373, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 166, - "rule": "forControl", - "state": 1375, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 167, - "rule": "forInit", - "state": 1379, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 168, - "rule": "enhancedForControl", - "state": 1384, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 169, - "rule": "enhancedForControl", - "state": 1389, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 170, - "rule": "expressionList", - "state": 1400, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 171, - "rule": "methodCall", - "state": 1406, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 172, - "rule": "expression", - "state": 1416, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 173, - "rule": "expression", - "state": 1420, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 174, - "rule": "expression", - "state": 1425, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 175, - "rule": "expression", - "state": 1436, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 176, - "rule": "expression", - "state": 1444, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 177, - "rule": "expression", - "state": 1453, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 178, - "rule": "expression", - "state": 1467, - "canDefer": true, - "tier": "ll1" - }, - { - "decision": 179, - "rule": "expression", - "state": 1473, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 180, - "rule": "expression", - "state": 1478, - "canDefer": true, - "tier": "ll1" - }, - { - "decision": 181, - "rule": "expression", - "state": 1497, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 182, - "rule": "expression", - "state": 1507, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 183, - "rule": "expression", - "state": 1536, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 184, - "rule": "expression", - "state": 1538, - "canDefer": true, - "tier": "adaptive", - "reason": "precedence", - "probedLookahead": 0 - }, - { - "decision": 185, - "rule": "pattern", - "state": 1544, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 186, - "rule": "pattern", - "state": 1551, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 187, - "rule": "pattern", - "state": 1559, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 188, - "rule": "pattern", - "state": 1563, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 189, - "rule": "componentPatternList", - "state": 1570, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 190, - "rule": "lambdaParameters", - "state": 1582, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 191, - "rule": "lambdaParameters", - "state": 1591, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 192, - "rule": "lambdaParameters", - "state": 1598, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 193, - "rule": "lambdaParameters", - "state": 1601, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 194, - "rule": "lambdaBody", - "state": 1605, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 195, - "rule": "primary", - "state": 1623, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 196, - "rule": "primary", - "state": 1625, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 197, - "rule": "switchExpression", - "state": 1635, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 198, - "rule": "switchLabeledRule", - "state": 1645, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 199, - "rule": "switchLabeledRule", - "state": 1652, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 200, - "rule": "switchLabeledRule", - "state": 1656, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 201, - "rule": "switchLabeledRule", - "state": 1658, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 202, - "rule": "switchLabeledRule", - "state": 1665, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 203, - "rule": "switchRuleOutcome", - "state": 1676, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 204, - "rule": "switchRuleOutcome", - "state": 1679, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 205, - "rule": "creator", - "state": 1684, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 206, - "rule": "creator", - "state": 1692, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 207, - "rule": "createdName", - "state": 1696, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 208, - "rule": "createdName", - "state": 1701, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 209, - "rule": "createdName", - "state": 1705, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 210, - "rule": "createdName", - "state": 1709, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 211, - "rule": "innerCreator", - "state": 1713, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 212, - "rule": "arrayCreatorRest", - "state": 1721, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 213, - "rule": "arrayCreatorRest", - "state": 1730, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 214, - "rule": "arrayCreatorRest", - "state": 1736, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 215, - "rule": "arrayCreatorRest", - "state": 1739, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 216, - "rule": "classCreatorRest", - "state": 1743, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 217, - "rule": "typeArgumentsOrDiamond", - "state": 1751, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 218, - "rule": "nonWildcardTypeArgumentsOrDiamond", - "state": 1756, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 219, - "rule": "typeList", - "state": 1767, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 220, - "rule": "typeType", - "state": 1773, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 221, - "rule": "typeType", - "state": 1778, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 222, - "rule": "typeType", - "state": 1783, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 223, - "rule": "typeType", - "state": 1790, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 224, - "rule": "typeArguments", - "state": 1801, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 225, - "rule": "superSuffix", - "state": 1809, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 226, - "rule": "superSuffix", - "state": 1813, - "canDefer": true, - "tier": "adaptive", - "reason": "predicate", - "probedLookahead": 1 - }, - { - "decision": 227, - "rule": "superSuffix", - "state": 1815, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 228, - "rule": "explicitGenericInvocationSuffix", - "state": 1822, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 229, - "rule": "arguments", - "state": 1826, - "canDefer": false, - "tier": "ll1" - } - ] - } - ] -} diff --git a/crates/mehen-java-parser/src/generated/java_lexer.rs b/crates/mehen-java-parser/src/generated/java_lexer.rs deleted file mode 100644 index 9b656072..00000000 --- a/crates/mehen-java-parser/src/generated/java_lexer.rs +++ /dev/null @@ -1,252 +0,0 @@ -// @generated by antlr-rust-codegen v0.33.1 - do not edit -// project: https://github.com/ophi-dev/antlr-rust-runtime -antlr4_runtime::__antlr4_rust_require_codegen_api!(14, "0.33.1"); -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -#[rustfmt::skip] -mod __antlr4_rust_generated { - -use antlr4_runtime::char_stream::CharStream; -use antlr4_runtime::atn::LexerAtn; -use antlr4_runtime::atn::lexer_dfa::CompiledLexerDfa; -use antlr4_runtime::atn::serialized::AtnDeserializer; -use antlr4_runtime::{BaseLexer, GrammarMetadata, Lexer}; -use std::sync::OnceLock; - -pub const EOF: i32 = antlr4_runtime::TOKEN_EOF; -pub const ABSTRACT: i32 = 1; -pub const ASSERT: i32 = 2; -pub const BOOLEAN: i32 = 3; -pub const BREAK: i32 = 4; -pub const BYTE: i32 = 5; -pub const CASE: i32 = 6; -pub const CATCH: i32 = 7; -pub const CHAR: i32 = 8; -pub const CLASS: i32 = 9; -pub const CONST: i32 = 10; -pub const CONTINUE: i32 = 11; -pub const DEFAULT: i32 = 12; -pub const DO: i32 = 13; -pub const DOUBLE: i32 = 14; -pub const ELSE: i32 = 15; -pub const ENUM: i32 = 16; -pub const EXPORTS: i32 = 17; -pub const EXTENDS: i32 = 18; -pub const FINAL: i32 = 19; -pub const FINALLY: i32 = 20; -pub const FLOAT: i32 = 21; -pub const FOR: i32 = 22; -pub const GOTO: i32 = 23; -pub const IF: i32 = 24; -pub const IMPLEMENTS: i32 = 25; -pub const IMPORT: i32 = 26; -pub const INSTANCEOF: i32 = 27; -pub const INT: i32 = 28; -pub const INTERFACE: i32 = 29; -pub const LONG: i32 = 30; -pub const MODULE: i32 = 31; -pub const NATIVE: i32 = 32; -pub const NEW: i32 = 33; -pub const NON_SEALED: i32 = 34; -pub const OPEN: i32 = 35; -pub const OPENS: i32 = 36; -pub const PACKAGE: i32 = 37; -pub const PERMITS: i32 = 38; -pub const PRIVATE: i32 = 39; -pub const PROTECTED: i32 = 40; -pub const PROVIDES: i32 = 41; -pub const PUBLIC: i32 = 42; -pub const RECORD: i32 = 43; -pub const REQUIRES: i32 = 44; -pub const RETURN: i32 = 45; -pub const SEALED: i32 = 46; -pub const SHORT: i32 = 47; -pub const STATIC: i32 = 48; -pub const STRICTFP: i32 = 49; -pub const SUPER: i32 = 50; -pub const SWITCH: i32 = 51; -pub const SYNCHRONIZED: i32 = 52; -pub const THIS: i32 = 53; -pub const THROW: i32 = 54; -pub const THROWS: i32 = 55; -pub const TO: i32 = 56; -pub const TRANSIENT: i32 = 57; -pub const TRANSITIVE: i32 = 58; -pub const TRY: i32 = 59; -pub const USES: i32 = 60; -pub const VAR: i32 = 61; -pub const VOID: i32 = 62; -pub const VOLATILE: i32 = 63; -pub const WHEN: i32 = 64; -pub const WHILE: i32 = 65; -pub const WITH: i32 = 66; -pub const YIELD: i32 = 67; -pub const DECIMAL_LITERAL: i32 = 68; -pub const HEX_LITERAL: i32 = 69; -pub const OCT_LITERAL: i32 = 70; -pub const BINARY_LITERAL: i32 = 71; -pub const FLOAT_LITERAL: i32 = 72; -pub const HEX_FLOAT_LITERAL: i32 = 73; -pub const BOOL_LITERAL: i32 = 74; -pub const CHAR_LITERAL: i32 = 75; -pub const STRING_LITERAL: i32 = 76; -pub const TEXT_BLOCK: i32 = 77; -pub const NULL_LITERAL: i32 = 78; -pub const LPAREN: i32 = 79; -pub const RPAREN: i32 = 80; -pub const LBRACE: i32 = 81; -pub const RBRACE: i32 = 82; -pub const LBRACK: i32 = 83; -pub const RBRACK: i32 = 84; -pub const SEMI: i32 = 85; -pub const COMMA: i32 = 86; -pub const DOT: i32 = 87; -pub const ASSIGN: i32 = 88; -pub const GT: i32 = 89; -pub const LT: i32 = 90; -pub const BANG: i32 = 91; -pub const TILDE: i32 = 92; -pub const QUESTION: i32 = 93; -pub const COLON: i32 = 94; -pub const EQUAL: i32 = 95; -pub const LE: i32 = 96; -pub const GE: i32 = 97; -pub const NOTEQUAL: i32 = 98; -pub const AND: i32 = 99; -pub const OR: i32 = 100; -pub const INC: i32 = 101; -pub const DEC: i32 = 102; -pub const ADD: i32 = 103; -pub const SUB: i32 = 104; -pub const MUL: i32 = 105; -pub const DIV: i32 = 106; -pub const BITAND: i32 = 107; -pub const BITOR: i32 = 108; -pub const CARET: i32 = 109; -pub const MOD: i32 = 110; -pub const ADD_ASSIGN: i32 = 111; -pub const SUB_ASSIGN: i32 = 112; -pub const MUL_ASSIGN: i32 = 113; -pub const DIV_ASSIGN: i32 = 114; -pub const AND_ASSIGN: i32 = 115; -pub const OR_ASSIGN: i32 = 116; -pub const XOR_ASSIGN: i32 = 117; -pub const MOD_ASSIGN: i32 = 118; -pub const LSHIFT_ASSIGN: i32 = 119; -pub const RSHIFT_ASSIGN: i32 = 120; -pub const URSHIFT_ASSIGN: i32 = 121; -pub const ARROW: i32 = 122; -pub const COLONCOLON: i32 = 123; -pub const AT: i32 = 124; -pub const ELLIPSIS: i32 = 125; -pub const WS: i32 = 126; -pub const COMMENT: i32 = 127; -pub const LINE_COMMENT: i32 = 128; -pub const IDENTIFIER: i32 = 129; - -pub const CHANNEL_DEFAULT_TOKEN_CHANNEL: i32 = 0; -pub const CHANNEL_HIDDEN: i32 = 1; -pub const MODE_DEFAULT_MODE: i32 = 0; - -pub static METADATA: GrammarMetadata = GrammarMetadata::new( - "JavaLexer", - &["ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", "CATCH", "CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", "ELSE", "ENUM", "EXPORTS", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "GOTO", "IF", "IMPLEMENTS", "IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", "MODULE", "NATIVE", "NEW", "NON_SEALED", "OPEN", "OPENS", "PACKAGE", "PERMITS", "PRIVATE", "PROTECTED", "PROVIDES", "PUBLIC", "RECORD", "REQUIRES", "RETURN", "SEALED", "SHORT", "STATIC", "STRICTFP", "SUPER", "SWITCH", "SYNCHRONIZED", "THIS", "THROW", "THROWS", "TO", "TRANSIENT", "TRANSITIVE", "TRY", "USES", "VAR", "VOID", "VOLATILE", "WHEN", "WHILE", "WITH", "YIELD", "DECIMAL_LITERAL", "HEX_LITERAL", "OCT_LITERAL", "BINARY_LITERAL", "FLOAT_LITERAL", "HEX_FLOAT_LITERAL", "BOOL_LITERAL", "CHAR_LITERAL", "STRING_LITERAL", "TEXT_BLOCK", "NULL_LITERAL", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", "SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", "COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", "ADD", "SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ADD_ASSIGN", "SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", "AND_ASSIGN", "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN", "LSHIFT_ASSIGN", "RSHIFT_ASSIGN", "URSHIFT_ASSIGN", "ARROW", "COLONCOLON", "AT", "ELLIPSIS", "WS", "COMMENT", "LINE_COMMENT", "IDENTIFIER", "ExponentPart", "EscapeSequence", "HexDigits", "HexDigit", "Digits", "LetterOrDigit", "Letter"], - &[None, Some("\'abstract\'"), Some("\'assert\'"), Some("\'boolean\'"), Some("\'break\'"), Some("\'byte\'"), Some("\'case\'"), Some("\'catch\'"), Some("\'char\'"), Some("\'class\'"), Some("\'const\'"), Some("\'continue\'"), Some("\'default\'"), Some("\'do\'"), Some("\'double\'"), Some("\'else\'"), Some("\'enum\'"), Some("\'exports\'"), Some("\'extends\'"), Some("\'final\'"), Some("\'finally\'"), Some("\'float\'"), Some("\'for\'"), Some("\'goto\'"), Some("\'if\'"), Some("\'implements\'"), Some("\'import\'"), Some("\'instanceof\'"), Some("\'int\'"), Some("\'interface\'"), Some("\'long\'"), Some("\'module\'"), Some("\'native\'"), Some("\'new\'"), Some("\'non-sealed\'"), Some("\'open\'"), Some("\'opens\'"), Some("\'package\'"), Some("\'permits\'"), Some("\'private\'"), Some("\'protected\'"), Some("\'provides\'"), Some("\'public\'"), Some("\'record\'"), Some("\'requires\'"), Some("\'return\'"), Some("\'sealed\'"), Some("\'short\'"), Some("\'static\'"), Some("\'strictfp\'"), Some("\'super\'"), Some("\'switch\'"), Some("\'synchronized\'"), Some("\'this\'"), Some("\'throw\'"), Some("\'throws\'"), Some("\'to\'"), Some("\'transient\'"), Some("\'transitive\'"), Some("\'try\'"), Some("\'uses\'"), Some("\'var\'"), Some("\'void\'"), Some("\'volatile\'"), Some("\'when\'"), Some("\'while\'"), Some("\'with\'"), Some("\'yield\'"), None, None, None, None, None, None, None, None, None, None, Some("\'null\'"), Some("\'(\'"), Some("\')\'"), Some("\'{\'"), Some("\'}\'"), Some("\'[\'"), Some("\']\'"), Some("\';\'"), Some("\',\'"), Some("\'.\'"), Some("\'=\'"), Some("\'>\'"), Some("\'<\'"), Some("\'!\'"), Some("\'~\'"), Some("\'?\'"), Some("\':\'"), Some("\'==\'"), Some("\'<=\'"), Some("\'>=\'"), Some("\'!=\'"), Some("\'&&\'"), Some("\'||\'"), Some("\'++\'"), Some("\'--\'"), Some("\'+\'"), Some("\'-\'"), Some("\'*\'"), Some("\'/\'"), Some("\'&\'"), Some("\'|\'"), Some("\'^\'"), Some("\'%\'"), Some("\'+=\'"), Some("\'-=\'"), Some("\'*=\'"), Some("\'/=\'"), Some("\'&=\'"), Some("\'|=\'"), Some("\'^=\'"), Some("\'%=\'"), Some("\'<<=\'"), Some("\'>>=\'"), Some("\'>>>=\'"), Some("\'->\'"), Some("\'::\'"), Some("\'@\'"), Some("\'...\'"), None, None, None, None], - &[None, Some("ABSTRACT"), Some("ASSERT"), Some("BOOLEAN"), Some("BREAK"), Some("BYTE"), Some("CASE"), Some("CATCH"), Some("CHAR"), Some("CLASS"), Some("CONST"), Some("CONTINUE"), Some("DEFAULT"), Some("DO"), Some("DOUBLE"), Some("ELSE"), Some("ENUM"), Some("EXPORTS"), Some("EXTENDS"), Some("FINAL"), Some("FINALLY"), Some("FLOAT"), Some("FOR"), Some("GOTO"), Some("IF"), Some("IMPLEMENTS"), Some("IMPORT"), Some("INSTANCEOF"), Some("INT"), Some("INTERFACE"), Some("LONG"), Some("MODULE"), Some("NATIVE"), Some("NEW"), Some("NON_SEALED"), Some("OPEN"), Some("OPENS"), Some("PACKAGE"), Some("PERMITS"), Some("PRIVATE"), Some("PROTECTED"), Some("PROVIDES"), Some("PUBLIC"), Some("RECORD"), Some("REQUIRES"), Some("RETURN"), Some("SEALED"), Some("SHORT"), Some("STATIC"), Some("STRICTFP"), Some("SUPER"), Some("SWITCH"), Some("SYNCHRONIZED"), Some("THIS"), Some("THROW"), Some("THROWS"), Some("TO"), Some("TRANSIENT"), Some("TRANSITIVE"), Some("TRY"), Some("USES"), Some("VAR"), Some("VOID"), Some("VOLATILE"), Some("WHEN"), Some("WHILE"), Some("WITH"), Some("YIELD"), Some("DECIMAL_LITERAL"), Some("HEX_LITERAL"), Some("OCT_LITERAL"), Some("BINARY_LITERAL"), Some("FLOAT_LITERAL"), Some("HEX_FLOAT_LITERAL"), Some("BOOL_LITERAL"), Some("CHAR_LITERAL"), Some("STRING_LITERAL"), Some("TEXT_BLOCK"), Some("NULL_LITERAL"), Some("LPAREN"), Some("RPAREN"), Some("LBRACE"), Some("RBRACE"), Some("LBRACK"), Some("RBRACK"), Some("SEMI"), Some("COMMA"), Some("DOT"), Some("ASSIGN"), Some("GT"), Some("LT"), Some("BANG"), Some("TILDE"), Some("QUESTION"), Some("COLON"), Some("EQUAL"), Some("LE"), Some("GE"), Some("NOTEQUAL"), Some("AND"), Some("OR"), Some("INC"), Some("DEC"), Some("ADD"), Some("SUB"), Some("MUL"), Some("DIV"), Some("BITAND"), Some("BITOR"), Some("CARET"), Some("MOD"), Some("ADD_ASSIGN"), Some("SUB_ASSIGN"), Some("MUL_ASSIGN"), Some("DIV_ASSIGN"), Some("AND_ASSIGN"), Some("OR_ASSIGN"), Some("XOR_ASSIGN"), Some("MOD_ASSIGN"), Some("LSHIFT_ASSIGN"), Some("RSHIFT_ASSIGN"), Some("URSHIFT_ASSIGN"), Some("ARROW"), Some("COLONCOLON"), Some("AT"), Some("ELLIPSIS"), Some("WS"), Some("COMMENT"), Some("LINE_COMMENT"), Some("IDENTIFIER")], - &[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &["DEFAULT_TOKEN_CHANNEL", "HIDDEN"], - &["DEFAULT_MODE"], - &[4, 0, 129, 1133, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 3, 67, 732, 8, 67, 1, 67, 4, 67, 735, 8, 67, 11, 67, 12, 67, 736, 1, 67, 3, 67, 740, 8, 67, 3, 67, 742, 8, 67, 1, 67, 3, 67, 745, 8, 67, 1, 68, 1, 68, 1, 68, 1, 68, 5, 68, 751, 8, 68, 10, 68, 12, 68, 754, 9, 68, 1, 68, 3, 68, 757, 8, 68, 1, 68, 3, 68, 760, 8, 68, 1, 69, 1, 69, 5, 69, 764, 8, 69, 10, 69, 12, 69, 767, 9, 69, 1, 69, 1, 69, 5, 69, 771, 8, 69, 10, 69, 12, 69, 774, 9, 69, 1, 69, 3, 69, 777, 8, 69, 1, 69, 3, 69, 780, 8, 69, 1, 70, 1, 70, 1, 70, 1, 70, 5, 70, 786, 8, 70, 10, 70, 12, 70, 789, 9, 70, 1, 70, 3, 70, 792, 8, 70, 1, 70, 3, 70, 795, 8, 70, 1, 71, 1, 71, 1, 71, 3, 71, 800, 8, 71, 1, 71, 1, 71, 3, 71, 804, 8, 71, 1, 71, 3, 71, 807, 8, 71, 1, 71, 3, 71, 810, 8, 71, 1, 71, 1, 71, 1, 71, 3, 71, 815, 8, 71, 1, 71, 3, 71, 818, 8, 71, 3, 71, 820, 8, 71, 1, 72, 1, 72, 1, 72, 1, 72, 3, 72, 826, 8, 72, 1, 72, 3, 72, 829, 8, 72, 1, 72, 1, 72, 3, 72, 833, 8, 72, 1, 72, 1, 72, 3, 72, 837, 8, 72, 1, 72, 1, 72, 3, 72, 841, 8, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 3, 73, 852, 8, 73, 1, 74, 1, 74, 1, 74, 3, 74, 857, 8, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 5, 75, 864, 8, 75, 10, 75, 12, 75, 867, 9, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 5, 76, 876, 8, 76, 10, 76, 12, 76, 879, 9, 76, 1, 76, 1, 76, 1, 76, 5, 76, 884, 8, 76, 10, 76, 12, 76, 887, 9, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 81, 1, 81, 1, 82, 1, 82, 1, 83, 1, 83, 1, 84, 1, 84, 1, 85, 1, 85, 1, 86, 1, 86, 1, 87, 1, 87, 1, 88, 1, 88, 1, 89, 1, 89, 1, 90, 1, 90, 1, 91, 1, 91, 1, 92, 1, 92, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 103, 1, 103, 1, 104, 1, 104, 1, 105, 1, 105, 1, 106, 1, 106, 1, 107, 1, 107, 1, 108, 1, 108, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 4, 125, 1020, 8, 125, 11, 125, 12, 125, 1021, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 5, 126, 1030, 8, 126, 10, 126, 12, 126, 1033, 9, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 5, 127, 1044, 8, 127, 10, 127, 12, 127, 1047, 9, 127, 1, 127, 1, 127, 1, 128, 1, 128, 5, 128, 1053, 8, 128, 10, 128, 12, 128, 1056, 9, 128, 1, 129, 1, 129, 3, 129, 1060, 8, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 3, 130, 1070, 8, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 3, 130, 1079, 8, 130, 1, 130, 3, 130, 1082, 8, 130, 1, 130, 3, 130, 1085, 8, 130, 1, 130, 1, 130, 1, 130, 4, 130, 1090, 8, 130, 11, 130, 12, 130, 1091, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 3, 130, 1099, 8, 130, 1, 131, 1, 131, 1, 131, 5, 131, 1104, 8, 131, 10, 131, 12, 131, 1107, 9, 131, 1, 131, 3, 131, 1110, 8, 131, 1, 132, 1, 132, 1, 133, 1, 133, 5, 133, 1116, 8, 133, 10, 133, 12, 133, 1119, 9, 133, 1, 133, 3, 133, 1122, 8, 133, 1, 134, 1, 134, 3, 134, 1126, 8, 134, 1, 135, 1, 135, 1, 135, 1, 135, 3, 135, 1132, 8, 135, 2, 885, 1031, 0, 136, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, 141, 71, 143, 72, 145, 73, 147, 74, 149, 75, 151, 76, 153, 77, 155, 78, 157, 79, 159, 80, 161, 81, 163, 82, 165, 83, 167, 84, 169, 85, 171, 86, 173, 87, 175, 88, 177, 89, 179, 90, 181, 91, 183, 92, 185, 93, 187, 94, 189, 95, 191, 96, 193, 97, 195, 98, 197, 99, 199, 100, 201, 101, 203, 102, 205, 103, 207, 104, 209, 105, 211, 106, 213, 107, 215, 108, 217, 109, 219, 110, 221, 111, 223, 112, 225, 113, 227, 114, 229, 115, 231, 116, 233, 117, 235, 118, 237, 119, 239, 120, 241, 121, 243, 122, 245, 123, 247, 124, 249, 125, 251, 126, 253, 127, 255, 128, 257, 129, 259, 0, 261, 0, 263, 0, 265, 0, 267, 0, 269, 0, 271, 0, 1, 0, 27, 1, 0, 49, 57, 2, 0, 76, 76, 108, 108, 2, 0, 88, 88, 120, 120, 3, 0, 48, 57, 65, 70, 97, 102, 4, 0, 48, 57, 65, 70, 95, 95, 97, 102, 1, 0, 48, 55, 2, 0, 48, 55, 95, 95, 2, 0, 66, 66, 98, 98, 1, 0, 48, 49, 2, 0, 48, 49, 95, 95, 4, 0, 68, 68, 70, 70, 100, 100, 102, 102, 2, 0, 80, 80, 112, 112, 2, 0, 43, 43, 45, 45, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 9, 9, 32, 32, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 12, 13, 32, 32, 2, 0, 69, 69, 101, 101, 7, 0, 34, 34, 39, 39, 92, 92, 98, 98, 102, 102, 110, 110, 114, 116, 1, 0, 48, 51, 1, 0, 48, 57, 2, 0, 48, 57, 95, 95, 4, 0, 36, 36, 65, 90, 95, 95, 97, 122, 2, 0, 0, 127, 55296, 56319, 1, 0, 55296, 56319, 1, 0, 56320, 57343, 1179, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, 0, 0, 0, 0, 169, 1, 0, 0, 0, 0, 171, 1, 0, 0, 0, 0, 173, 1, 0, 0, 0, 0, 175, 1, 0, 0, 0, 0, 177, 1, 0, 0, 0, 0, 179, 1, 0, 0, 0, 0, 181, 1, 0, 0, 0, 0, 183, 1, 0, 0, 0, 0, 185, 1, 0, 0, 0, 0, 187, 1, 0, 0, 0, 0, 189, 1, 0, 0, 0, 0, 191, 1, 0, 0, 0, 0, 193, 1, 0, 0, 0, 0, 195, 1, 0, 0, 0, 0, 197, 1, 0, 0, 0, 0, 199, 1, 0, 0, 0, 0, 201, 1, 0, 0, 0, 0, 203, 1, 0, 0, 0, 0, 205, 1, 0, 0, 0, 0, 207, 1, 0, 0, 0, 0, 209, 1, 0, 0, 0, 0, 211, 1, 0, 0, 0, 0, 213, 1, 0, 0, 0, 0, 215, 1, 0, 0, 0, 0, 217, 1, 0, 0, 0, 0, 219, 1, 0, 0, 0, 0, 221, 1, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 225, 1, 0, 0, 0, 0, 227, 1, 0, 0, 0, 0, 229, 1, 0, 0, 0, 0, 231, 1, 0, 0, 0, 0, 233, 1, 0, 0, 0, 0, 235, 1, 0, 0, 0, 0, 237, 1, 0, 0, 0, 0, 239, 1, 0, 0, 0, 0, 241, 1, 0, 0, 0, 0, 243, 1, 0, 0, 0, 0, 245, 1, 0, 0, 0, 0, 247, 1, 0, 0, 0, 0, 249, 1, 0, 0, 0, 0, 251, 1, 0, 0, 0, 0, 253, 1, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 257, 1, 0, 0, 0, 1, 273, 1, 0, 0, 0, 3, 282, 1, 0, 0, 0, 5, 289, 1, 0, 0, 0, 7, 297, 1, 0, 0, 0, 9, 303, 1, 0, 0, 0, 11, 308, 1, 0, 0, 0, 13, 313, 1, 0, 0, 0, 15, 319, 1, 0, 0, 0, 17, 324, 1, 0, 0, 0, 19, 330, 1, 0, 0, 0, 21, 336, 1, 0, 0, 0, 23, 345, 1, 0, 0, 0, 25, 353, 1, 0, 0, 0, 27, 356, 1, 0, 0, 0, 29, 363, 1, 0, 0, 0, 31, 368, 1, 0, 0, 0, 33, 373, 1, 0, 0, 0, 35, 381, 1, 0, 0, 0, 37, 389, 1, 0, 0, 0, 39, 395, 1, 0, 0, 0, 41, 403, 1, 0, 0, 0, 43, 409, 1, 0, 0, 0, 45, 413, 1, 0, 0, 0, 47, 418, 1, 0, 0, 0, 49, 421, 1, 0, 0, 0, 51, 432, 1, 0, 0, 0, 53, 439, 1, 0, 0, 0, 55, 450, 1, 0, 0, 0, 57, 454, 1, 0, 0, 0, 59, 464, 1, 0, 0, 0, 61, 469, 1, 0, 0, 0, 63, 476, 1, 0, 0, 0, 65, 483, 1, 0, 0, 0, 67, 487, 1, 0, 0, 0, 69, 498, 1, 0, 0, 0, 71, 503, 1, 0, 0, 0, 73, 509, 1, 0, 0, 0, 75, 517, 1, 0, 0, 0, 77, 525, 1, 0, 0, 0, 79, 533, 1, 0, 0, 0, 81, 543, 1, 0, 0, 0, 83, 552, 1, 0, 0, 0, 85, 559, 1, 0, 0, 0, 87, 566, 1, 0, 0, 0, 89, 575, 1, 0, 0, 0, 91, 582, 1, 0, 0, 0, 93, 589, 1, 0, 0, 0, 95, 595, 1, 0, 0, 0, 97, 602, 1, 0, 0, 0, 99, 611, 1, 0, 0, 0, 101, 617, 1, 0, 0, 0, 103, 624, 1, 0, 0, 0, 105, 637, 1, 0, 0, 0, 107, 642, 1, 0, 0, 0, 109, 648, 1, 0, 0, 0, 111, 655, 1, 0, 0, 0, 113, 658, 1, 0, 0, 0, 115, 668, 1, 0, 0, 0, 117, 679, 1, 0, 0, 0, 119, 683, 1, 0, 0, 0, 121, 688, 1, 0, 0, 0, 123, 692, 1, 0, 0, 0, 125, 697, 1, 0, 0, 0, 127, 706, 1, 0, 0, 0, 129, 711, 1, 0, 0, 0, 131, 717, 1, 0, 0, 0, 133, 722, 1, 0, 0, 0, 135, 741, 1, 0, 0, 0, 137, 746, 1, 0, 0, 0, 139, 761, 1, 0, 0, 0, 141, 781, 1, 0, 0, 0, 143, 819, 1, 0, 0, 0, 145, 821, 1, 0, 0, 0, 147, 851, 1, 0, 0, 0, 149, 853, 1, 0, 0, 0, 151, 860, 1, 0, 0, 0, 153, 870, 1, 0, 0, 0, 155, 892, 1, 0, 0, 0, 157, 897, 1, 0, 0, 0, 159, 899, 1, 0, 0, 0, 161, 901, 1, 0, 0, 0, 163, 903, 1, 0, 0, 0, 165, 905, 1, 0, 0, 0, 167, 907, 1, 0, 0, 0, 169, 909, 1, 0, 0, 0, 171, 911, 1, 0, 0, 0, 173, 913, 1, 0, 0, 0, 175, 915, 1, 0, 0, 0, 177, 917, 1, 0, 0, 0, 179, 919, 1, 0, 0, 0, 181, 921, 1, 0, 0, 0, 183, 923, 1, 0, 0, 0, 185, 925, 1, 0, 0, 0, 187, 927, 1, 0, 0, 0, 189, 929, 1, 0, 0, 0, 191, 932, 1, 0, 0, 0, 193, 935, 1, 0, 0, 0, 195, 938, 1, 0, 0, 0, 197, 941, 1, 0, 0, 0, 199, 944, 1, 0, 0, 0, 201, 947, 1, 0, 0, 0, 203, 950, 1, 0, 0, 0, 205, 953, 1, 0, 0, 0, 207, 955, 1, 0, 0, 0, 209, 957, 1, 0, 0, 0, 211, 959, 1, 0, 0, 0, 213, 961, 1, 0, 0, 0, 215, 963, 1, 0, 0, 0, 217, 965, 1, 0, 0, 0, 219, 967, 1, 0, 0, 0, 221, 969, 1, 0, 0, 0, 223, 972, 1, 0, 0, 0, 225, 975, 1, 0, 0, 0, 227, 978, 1, 0, 0, 0, 229, 981, 1, 0, 0, 0, 231, 984, 1, 0, 0, 0, 233, 987, 1, 0, 0, 0, 235, 990, 1, 0, 0, 0, 237, 993, 1, 0, 0, 0, 239, 997, 1, 0, 0, 0, 241, 1001, 1, 0, 0, 0, 243, 1006, 1, 0, 0, 0, 245, 1009, 1, 0, 0, 0, 247, 1012, 1, 0, 0, 0, 249, 1014, 1, 0, 0, 0, 251, 1019, 1, 0, 0, 0, 253, 1025, 1, 0, 0, 0, 255, 1039, 1, 0, 0, 0, 257, 1050, 1, 0, 0, 0, 259, 1057, 1, 0, 0, 0, 261, 1098, 1, 0, 0, 0, 263, 1100, 1, 0, 0, 0, 265, 1111, 1, 0, 0, 0, 267, 1113, 1, 0, 0, 0, 269, 1125, 1, 0, 0, 0, 271, 1131, 1, 0, 0, 0, 273, 274, 5, 97, 0, 0, 274, 275, 5, 98, 0, 0, 275, 276, 5, 115, 0, 0, 276, 277, 5, 116, 0, 0, 277, 278, 5, 114, 0, 0, 278, 279, 5, 97, 0, 0, 279, 280, 5, 99, 0, 0, 280, 281, 5, 116, 0, 0, 281, 2, 1, 0, 0, 0, 282, 283, 5, 97, 0, 0, 283, 284, 5, 115, 0, 0, 284, 285, 5, 115, 0, 0, 285, 286, 5, 101, 0, 0, 286, 287, 5, 114, 0, 0, 287, 288, 5, 116, 0, 0, 288, 4, 1, 0, 0, 0, 289, 290, 5, 98, 0, 0, 290, 291, 5, 111, 0, 0, 291, 292, 5, 111, 0, 0, 292, 293, 5, 108, 0, 0, 293, 294, 5, 101, 0, 0, 294, 295, 5, 97, 0, 0, 295, 296, 5, 110, 0, 0, 296, 6, 1, 0, 0, 0, 297, 298, 5, 98, 0, 0, 298, 299, 5, 114, 0, 0, 299, 300, 5, 101, 0, 0, 300, 301, 5, 97, 0, 0, 301, 302, 5, 107, 0, 0, 302, 8, 1, 0, 0, 0, 303, 304, 5, 98, 0, 0, 304, 305, 5, 121, 0, 0, 305, 306, 5, 116, 0, 0, 306, 307, 5, 101, 0, 0, 307, 10, 1, 0, 0, 0, 308, 309, 5, 99, 0, 0, 309, 310, 5, 97, 0, 0, 310, 311, 5, 115, 0, 0, 311, 312, 5, 101, 0, 0, 312, 12, 1, 0, 0, 0, 313, 314, 5, 99, 0, 0, 314, 315, 5, 97, 0, 0, 315, 316, 5, 116, 0, 0, 316, 317, 5, 99, 0, 0, 317, 318, 5, 104, 0, 0, 318, 14, 1, 0, 0, 0, 319, 320, 5, 99, 0, 0, 320, 321, 5, 104, 0, 0, 321, 322, 5, 97, 0, 0, 322, 323, 5, 114, 0, 0, 323, 16, 1, 0, 0, 0, 324, 325, 5, 99, 0, 0, 325, 326, 5, 108, 0, 0, 326, 327, 5, 97, 0, 0, 327, 328, 5, 115, 0, 0, 328, 329, 5, 115, 0, 0, 329, 18, 1, 0, 0, 0, 330, 331, 5, 99, 0, 0, 331, 332, 5, 111, 0, 0, 332, 333, 5, 110, 0, 0, 333, 334, 5, 115, 0, 0, 334, 335, 5, 116, 0, 0, 335, 20, 1, 0, 0, 0, 336, 337, 5, 99, 0, 0, 337, 338, 5, 111, 0, 0, 338, 339, 5, 110, 0, 0, 339, 340, 5, 116, 0, 0, 340, 341, 5, 105, 0, 0, 341, 342, 5, 110, 0, 0, 342, 343, 5, 117, 0, 0, 343, 344, 5, 101, 0, 0, 344, 22, 1, 0, 0, 0, 345, 346, 5, 100, 0, 0, 346, 347, 5, 101, 0, 0, 347, 348, 5, 102, 0, 0, 348, 349, 5, 97, 0, 0, 349, 350, 5, 117, 0, 0, 350, 351, 5, 108, 0, 0, 351, 352, 5, 116, 0, 0, 352, 24, 1, 0, 0, 0, 353, 354, 5, 100, 0, 0, 354, 355, 5, 111, 0, 0, 355, 26, 1, 0, 0, 0, 356, 357, 5, 100, 0, 0, 357, 358, 5, 111, 0, 0, 358, 359, 5, 117, 0, 0, 359, 360, 5, 98, 0, 0, 360, 361, 5, 108, 0, 0, 361, 362, 5, 101, 0, 0, 362, 28, 1, 0, 0, 0, 363, 364, 5, 101, 0, 0, 364, 365, 5, 108, 0, 0, 365, 366, 5, 115, 0, 0, 366, 367, 5, 101, 0, 0, 367, 30, 1, 0, 0, 0, 368, 369, 5, 101, 0, 0, 369, 370, 5, 110, 0, 0, 370, 371, 5, 117, 0, 0, 371, 372, 5, 109, 0, 0, 372, 32, 1, 0, 0, 0, 373, 374, 5, 101, 0, 0, 374, 375, 5, 120, 0, 0, 375, 376, 5, 112, 0, 0, 376, 377, 5, 111, 0, 0, 377, 378, 5, 114, 0, 0, 378, 379, 5, 116, 0, 0, 379, 380, 5, 115, 0, 0, 380, 34, 1, 0, 0, 0, 381, 382, 5, 101, 0, 0, 382, 383, 5, 120, 0, 0, 383, 384, 5, 116, 0, 0, 384, 385, 5, 101, 0, 0, 385, 386, 5, 110, 0, 0, 386, 387, 5, 100, 0, 0, 387, 388, 5, 115, 0, 0, 388, 36, 1, 0, 0, 0, 389, 390, 5, 102, 0, 0, 390, 391, 5, 105, 0, 0, 391, 392, 5, 110, 0, 0, 392, 393, 5, 97, 0, 0, 393, 394, 5, 108, 0, 0, 394, 38, 1, 0, 0, 0, 395, 396, 5, 102, 0, 0, 396, 397, 5, 105, 0, 0, 397, 398, 5, 110, 0, 0, 398, 399, 5, 97, 0, 0, 399, 400, 5, 108, 0, 0, 400, 401, 5, 108, 0, 0, 401, 402, 5, 121, 0, 0, 402, 40, 1, 0, 0, 0, 403, 404, 5, 102, 0, 0, 404, 405, 5, 108, 0, 0, 405, 406, 5, 111, 0, 0, 406, 407, 5, 97, 0, 0, 407, 408, 5, 116, 0, 0, 408, 42, 1, 0, 0, 0, 409, 410, 5, 102, 0, 0, 410, 411, 5, 111, 0, 0, 411, 412, 5, 114, 0, 0, 412, 44, 1, 0, 0, 0, 413, 414, 5, 103, 0, 0, 414, 415, 5, 111, 0, 0, 415, 416, 5, 116, 0, 0, 416, 417, 5, 111, 0, 0, 417, 46, 1, 0, 0, 0, 418, 419, 5, 105, 0, 0, 419, 420, 5, 102, 0, 0, 420, 48, 1, 0, 0, 0, 421, 422, 5, 105, 0, 0, 422, 423, 5, 109, 0, 0, 423, 424, 5, 112, 0, 0, 424, 425, 5, 108, 0, 0, 425, 426, 5, 101, 0, 0, 426, 427, 5, 109, 0, 0, 427, 428, 5, 101, 0, 0, 428, 429, 5, 110, 0, 0, 429, 430, 5, 116, 0, 0, 430, 431, 5, 115, 0, 0, 431, 50, 1, 0, 0, 0, 432, 433, 5, 105, 0, 0, 433, 434, 5, 109, 0, 0, 434, 435, 5, 112, 0, 0, 435, 436, 5, 111, 0, 0, 436, 437, 5, 114, 0, 0, 437, 438, 5, 116, 0, 0, 438, 52, 1, 0, 0, 0, 439, 440, 5, 105, 0, 0, 440, 441, 5, 110, 0, 0, 441, 442, 5, 115, 0, 0, 442, 443, 5, 116, 0, 0, 443, 444, 5, 97, 0, 0, 444, 445, 5, 110, 0, 0, 445, 446, 5, 99, 0, 0, 446, 447, 5, 101, 0, 0, 447, 448, 5, 111, 0, 0, 448, 449, 5, 102, 0, 0, 449, 54, 1, 0, 0, 0, 450, 451, 5, 105, 0, 0, 451, 452, 5, 110, 0, 0, 452, 453, 5, 116, 0, 0, 453, 56, 1, 0, 0, 0, 454, 455, 5, 105, 0, 0, 455, 456, 5, 110, 0, 0, 456, 457, 5, 116, 0, 0, 457, 458, 5, 101, 0, 0, 458, 459, 5, 114, 0, 0, 459, 460, 5, 102, 0, 0, 460, 461, 5, 97, 0, 0, 461, 462, 5, 99, 0, 0, 462, 463, 5, 101, 0, 0, 463, 58, 1, 0, 0, 0, 464, 465, 5, 108, 0, 0, 465, 466, 5, 111, 0, 0, 466, 467, 5, 110, 0, 0, 467, 468, 5, 103, 0, 0, 468, 60, 1, 0, 0, 0, 469, 470, 5, 109, 0, 0, 470, 471, 5, 111, 0, 0, 471, 472, 5, 100, 0, 0, 472, 473, 5, 117, 0, 0, 473, 474, 5, 108, 0, 0, 474, 475, 5, 101, 0, 0, 475, 62, 1, 0, 0, 0, 476, 477, 5, 110, 0, 0, 477, 478, 5, 97, 0, 0, 478, 479, 5, 116, 0, 0, 479, 480, 5, 105, 0, 0, 480, 481, 5, 118, 0, 0, 481, 482, 5, 101, 0, 0, 482, 64, 1, 0, 0, 0, 483, 484, 5, 110, 0, 0, 484, 485, 5, 101, 0, 0, 485, 486, 5, 119, 0, 0, 486, 66, 1, 0, 0, 0, 487, 488, 5, 110, 0, 0, 488, 489, 5, 111, 0, 0, 489, 490, 5, 110, 0, 0, 490, 491, 5, 45, 0, 0, 491, 492, 5, 115, 0, 0, 492, 493, 5, 101, 0, 0, 493, 494, 5, 97, 0, 0, 494, 495, 5, 108, 0, 0, 495, 496, 5, 101, 0, 0, 496, 497, 5, 100, 0, 0, 497, 68, 1, 0, 0, 0, 498, 499, 5, 111, 0, 0, 499, 500, 5, 112, 0, 0, 500, 501, 5, 101, 0, 0, 501, 502, 5, 110, 0, 0, 502, 70, 1, 0, 0, 0, 503, 504, 5, 111, 0, 0, 504, 505, 5, 112, 0, 0, 505, 506, 5, 101, 0, 0, 506, 507, 5, 110, 0, 0, 507, 508, 5, 115, 0, 0, 508, 72, 1, 0, 0, 0, 509, 510, 5, 112, 0, 0, 510, 511, 5, 97, 0, 0, 511, 512, 5, 99, 0, 0, 512, 513, 5, 107, 0, 0, 513, 514, 5, 97, 0, 0, 514, 515, 5, 103, 0, 0, 515, 516, 5, 101, 0, 0, 516, 74, 1, 0, 0, 0, 517, 518, 5, 112, 0, 0, 518, 519, 5, 101, 0, 0, 519, 520, 5, 114, 0, 0, 520, 521, 5, 109, 0, 0, 521, 522, 5, 105, 0, 0, 522, 523, 5, 116, 0, 0, 523, 524, 5, 115, 0, 0, 524, 76, 1, 0, 0, 0, 525, 526, 5, 112, 0, 0, 526, 527, 5, 114, 0, 0, 527, 528, 5, 105, 0, 0, 528, 529, 5, 118, 0, 0, 529, 530, 5, 97, 0, 0, 530, 531, 5, 116, 0, 0, 531, 532, 5, 101, 0, 0, 532, 78, 1, 0, 0, 0, 533, 534, 5, 112, 0, 0, 534, 535, 5, 114, 0, 0, 535, 536, 5, 111, 0, 0, 536, 537, 5, 116, 0, 0, 537, 538, 5, 101, 0, 0, 538, 539, 5, 99, 0, 0, 539, 540, 5, 116, 0, 0, 540, 541, 5, 101, 0, 0, 541, 542, 5, 100, 0, 0, 542, 80, 1, 0, 0, 0, 543, 544, 5, 112, 0, 0, 544, 545, 5, 114, 0, 0, 545, 546, 5, 111, 0, 0, 546, 547, 5, 118, 0, 0, 547, 548, 5, 105, 0, 0, 548, 549, 5, 100, 0, 0, 549, 550, 5, 101, 0, 0, 550, 551, 5, 115, 0, 0, 551, 82, 1, 0, 0, 0, 552, 553, 5, 112, 0, 0, 553, 554, 5, 117, 0, 0, 554, 555, 5, 98, 0, 0, 555, 556, 5, 108, 0, 0, 556, 557, 5, 105, 0, 0, 557, 558, 5, 99, 0, 0, 558, 84, 1, 0, 0, 0, 559, 560, 5, 114, 0, 0, 560, 561, 5, 101, 0, 0, 561, 562, 5, 99, 0, 0, 562, 563, 5, 111, 0, 0, 563, 564, 5, 114, 0, 0, 564, 565, 5, 100, 0, 0, 565, 86, 1, 0, 0, 0, 566, 567, 5, 114, 0, 0, 567, 568, 5, 101, 0, 0, 568, 569, 5, 113, 0, 0, 569, 570, 5, 117, 0, 0, 570, 571, 5, 105, 0, 0, 571, 572, 5, 114, 0, 0, 572, 573, 5, 101, 0, 0, 573, 574, 5, 115, 0, 0, 574, 88, 1, 0, 0, 0, 575, 576, 5, 114, 0, 0, 576, 577, 5, 101, 0, 0, 577, 578, 5, 116, 0, 0, 578, 579, 5, 117, 0, 0, 579, 580, 5, 114, 0, 0, 580, 581, 5, 110, 0, 0, 581, 90, 1, 0, 0, 0, 582, 583, 5, 115, 0, 0, 583, 584, 5, 101, 0, 0, 584, 585, 5, 97, 0, 0, 585, 586, 5, 108, 0, 0, 586, 587, 5, 101, 0, 0, 587, 588, 5, 100, 0, 0, 588, 92, 1, 0, 0, 0, 589, 590, 5, 115, 0, 0, 590, 591, 5, 104, 0, 0, 591, 592, 5, 111, 0, 0, 592, 593, 5, 114, 0, 0, 593, 594, 5, 116, 0, 0, 594, 94, 1, 0, 0, 0, 595, 596, 5, 115, 0, 0, 596, 597, 5, 116, 0, 0, 597, 598, 5, 97, 0, 0, 598, 599, 5, 116, 0, 0, 599, 600, 5, 105, 0, 0, 600, 601, 5, 99, 0, 0, 601, 96, 1, 0, 0, 0, 602, 603, 5, 115, 0, 0, 603, 604, 5, 116, 0, 0, 604, 605, 5, 114, 0, 0, 605, 606, 5, 105, 0, 0, 606, 607, 5, 99, 0, 0, 607, 608, 5, 116, 0, 0, 608, 609, 5, 102, 0, 0, 609, 610, 5, 112, 0, 0, 610, 98, 1, 0, 0, 0, 611, 612, 5, 115, 0, 0, 612, 613, 5, 117, 0, 0, 613, 614, 5, 112, 0, 0, 614, 615, 5, 101, 0, 0, 615, 616, 5, 114, 0, 0, 616, 100, 1, 0, 0, 0, 617, 618, 5, 115, 0, 0, 618, 619, 5, 119, 0, 0, 619, 620, 5, 105, 0, 0, 620, 621, 5, 116, 0, 0, 621, 622, 5, 99, 0, 0, 622, 623, 5, 104, 0, 0, 623, 102, 1, 0, 0, 0, 624, 625, 5, 115, 0, 0, 625, 626, 5, 121, 0, 0, 626, 627, 5, 110, 0, 0, 627, 628, 5, 99, 0, 0, 628, 629, 5, 104, 0, 0, 629, 630, 5, 114, 0, 0, 630, 631, 5, 111, 0, 0, 631, 632, 5, 110, 0, 0, 632, 633, 5, 105, 0, 0, 633, 634, 5, 122, 0, 0, 634, 635, 5, 101, 0, 0, 635, 636, 5, 100, 0, 0, 636, 104, 1, 0, 0, 0, 637, 638, 5, 116, 0, 0, 638, 639, 5, 104, 0, 0, 639, 640, 5, 105, 0, 0, 640, 641, 5, 115, 0, 0, 641, 106, 1, 0, 0, 0, 642, 643, 5, 116, 0, 0, 643, 644, 5, 104, 0, 0, 644, 645, 5, 114, 0, 0, 645, 646, 5, 111, 0, 0, 646, 647, 5, 119, 0, 0, 647, 108, 1, 0, 0, 0, 648, 649, 5, 116, 0, 0, 649, 650, 5, 104, 0, 0, 650, 651, 5, 114, 0, 0, 651, 652, 5, 111, 0, 0, 652, 653, 5, 119, 0, 0, 653, 654, 5, 115, 0, 0, 654, 110, 1, 0, 0, 0, 655, 656, 5, 116, 0, 0, 656, 657, 5, 111, 0, 0, 657, 112, 1, 0, 0, 0, 658, 659, 5, 116, 0, 0, 659, 660, 5, 114, 0, 0, 660, 661, 5, 97, 0, 0, 661, 662, 5, 110, 0, 0, 662, 663, 5, 115, 0, 0, 663, 664, 5, 105, 0, 0, 664, 665, 5, 101, 0, 0, 665, 666, 5, 110, 0, 0, 666, 667, 5, 116, 0, 0, 667, 114, 1, 0, 0, 0, 668, 669, 5, 116, 0, 0, 669, 670, 5, 114, 0, 0, 670, 671, 5, 97, 0, 0, 671, 672, 5, 110, 0, 0, 672, 673, 5, 115, 0, 0, 673, 674, 5, 105, 0, 0, 674, 675, 5, 116, 0, 0, 675, 676, 5, 105, 0, 0, 676, 677, 5, 118, 0, 0, 677, 678, 5, 101, 0, 0, 678, 116, 1, 0, 0, 0, 679, 680, 5, 116, 0, 0, 680, 681, 5, 114, 0, 0, 681, 682, 5, 121, 0, 0, 682, 118, 1, 0, 0, 0, 683, 684, 5, 117, 0, 0, 684, 685, 5, 115, 0, 0, 685, 686, 5, 101, 0, 0, 686, 687, 5, 115, 0, 0, 687, 120, 1, 0, 0, 0, 688, 689, 5, 118, 0, 0, 689, 690, 5, 97, 0, 0, 690, 691, 5, 114, 0, 0, 691, 122, 1, 0, 0, 0, 692, 693, 5, 118, 0, 0, 693, 694, 5, 111, 0, 0, 694, 695, 5, 105, 0, 0, 695, 696, 5, 100, 0, 0, 696, 124, 1, 0, 0, 0, 697, 698, 5, 118, 0, 0, 698, 699, 5, 111, 0, 0, 699, 700, 5, 108, 0, 0, 700, 701, 5, 97, 0, 0, 701, 702, 5, 116, 0, 0, 702, 703, 5, 105, 0, 0, 703, 704, 5, 108, 0, 0, 704, 705, 5, 101, 0, 0, 705, 126, 1, 0, 0, 0, 706, 707, 5, 119, 0, 0, 707, 708, 5, 104, 0, 0, 708, 709, 5, 101, 0, 0, 709, 710, 5, 110, 0, 0, 710, 128, 1, 0, 0, 0, 711, 712, 5, 119, 0, 0, 712, 713, 5, 104, 0, 0, 713, 714, 5, 105, 0, 0, 714, 715, 5, 108, 0, 0, 715, 716, 5, 101, 0, 0, 716, 130, 1, 0, 0, 0, 717, 718, 5, 119, 0, 0, 718, 719, 5, 105, 0, 0, 719, 720, 5, 116, 0, 0, 720, 721, 5, 104, 0, 0, 721, 132, 1, 0, 0, 0, 722, 723, 5, 121, 0, 0, 723, 724, 5, 105, 0, 0, 724, 725, 5, 101, 0, 0, 725, 726, 5, 108, 0, 0, 726, 727, 5, 100, 0, 0, 727, 134, 1, 0, 0, 0, 728, 742, 5, 48, 0, 0, 729, 739, 7, 0, 0, 0, 730, 732, 3, 267, 133, 0, 731, 730, 1, 0, 0, 0, 731, 732, 1, 0, 0, 0, 732, 740, 1, 0, 0, 0, 733, 735, 5, 95, 0, 0, 734, 733, 1, 0, 0, 0, 735, 736, 1, 0, 0, 0, 736, 734, 1, 0, 0, 0, 736, 737, 1, 0, 0, 0, 737, 738, 1, 0, 0, 0, 738, 740, 3, 267, 133, 0, 739, 731, 1, 0, 0, 0, 739, 734, 1, 0, 0, 0, 740, 742, 1, 0, 0, 0, 741, 728, 1, 0, 0, 0, 741, 729, 1, 0, 0, 0, 742, 744, 1, 0, 0, 0, 743, 745, 7, 1, 0, 0, 744, 743, 1, 0, 0, 0, 744, 745, 1, 0, 0, 0, 745, 136, 1, 0, 0, 0, 746, 747, 5, 48, 0, 0, 747, 748, 7, 2, 0, 0, 748, 756, 7, 3, 0, 0, 749, 751, 7, 4, 0, 0, 750, 749, 1, 0, 0, 0, 751, 754, 1, 0, 0, 0, 752, 750, 1, 0, 0, 0, 752, 753, 1, 0, 0, 0, 753, 755, 1, 0, 0, 0, 754, 752, 1, 0, 0, 0, 755, 757, 7, 3, 0, 0, 756, 752, 1, 0, 0, 0, 756, 757, 1, 0, 0, 0, 757, 759, 1, 0, 0, 0, 758, 760, 7, 1, 0, 0, 759, 758, 1, 0, 0, 0, 759, 760, 1, 0, 0, 0, 760, 138, 1, 0, 0, 0, 761, 765, 5, 48, 0, 0, 762, 764, 5, 95, 0, 0, 763, 762, 1, 0, 0, 0, 764, 767, 1, 0, 0, 0, 765, 763, 1, 0, 0, 0, 765, 766, 1, 0, 0, 0, 766, 768, 1, 0, 0, 0, 767, 765, 1, 0, 0, 0, 768, 776, 7, 5, 0, 0, 769, 771, 7, 6, 0, 0, 770, 769, 1, 0, 0, 0, 771, 774, 1, 0, 0, 0, 772, 770, 1, 0, 0, 0, 772, 773, 1, 0, 0, 0, 773, 775, 1, 0, 0, 0, 774, 772, 1, 0, 0, 0, 775, 777, 7, 5, 0, 0, 776, 772, 1, 0, 0, 0, 776, 777, 1, 0, 0, 0, 777, 779, 1, 0, 0, 0, 778, 780, 7, 1, 0, 0, 779, 778, 1, 0, 0, 0, 779, 780, 1, 0, 0, 0, 780, 140, 1, 0, 0, 0, 781, 782, 5, 48, 0, 0, 782, 783, 7, 7, 0, 0, 783, 791, 7, 8, 0, 0, 784, 786, 7, 9, 0, 0, 785, 784, 1, 0, 0, 0, 786, 789, 1, 0, 0, 0, 787, 785, 1, 0, 0, 0, 787, 788, 1, 0, 0, 0, 788, 790, 1, 0, 0, 0, 789, 787, 1, 0, 0, 0, 790, 792, 7, 8, 0, 0, 791, 787, 1, 0, 0, 0, 791, 792, 1, 0, 0, 0, 792, 794, 1, 0, 0, 0, 793, 795, 7, 1, 0, 0, 794, 793, 1, 0, 0, 0, 794, 795, 1, 0, 0, 0, 795, 142, 1, 0, 0, 0, 796, 797, 3, 267, 133, 0, 797, 799, 5, 46, 0, 0, 798, 800, 3, 267, 133, 0, 799, 798, 1, 0, 0, 0, 799, 800, 1, 0, 0, 0, 800, 804, 1, 0, 0, 0, 801, 802, 5, 46, 0, 0, 802, 804, 3, 267, 133, 0, 803, 796, 1, 0, 0, 0, 803, 801, 1, 0, 0, 0, 804, 806, 1, 0, 0, 0, 805, 807, 3, 259, 129, 0, 806, 805, 1, 0, 0, 0, 806, 807, 1, 0, 0, 0, 807, 809, 1, 0, 0, 0, 808, 810, 7, 10, 0, 0, 809, 808, 1, 0, 0, 0, 809, 810, 1, 0, 0, 0, 810, 820, 1, 0, 0, 0, 811, 817, 3, 267, 133, 0, 812, 814, 3, 259, 129, 0, 813, 815, 7, 10, 0, 0, 814, 813, 1, 0, 0, 0, 814, 815, 1, 0, 0, 0, 815, 818, 1, 0, 0, 0, 816, 818, 7, 10, 0, 0, 817, 812, 1, 0, 0, 0, 817, 816, 1, 0, 0, 0, 818, 820, 1, 0, 0, 0, 819, 803, 1, 0, 0, 0, 819, 811, 1, 0, 0, 0, 820, 144, 1, 0, 0, 0, 821, 822, 5, 48, 0, 0, 822, 832, 7, 2, 0, 0, 823, 825, 3, 263, 131, 0, 824, 826, 5, 46, 0, 0, 825, 824, 1, 0, 0, 0, 825, 826, 1, 0, 0, 0, 826, 833, 1, 0, 0, 0, 827, 829, 3, 263, 131, 0, 828, 827, 1, 0, 0, 0, 828, 829, 1, 0, 0, 0, 829, 830, 1, 0, 0, 0, 830, 831, 5, 46, 0, 0, 831, 833, 3, 263, 131, 0, 832, 823, 1, 0, 0, 0, 832, 828, 1, 0, 0, 0, 833, 834, 1, 0, 0, 0, 834, 836, 7, 11, 0, 0, 835, 837, 7, 12, 0, 0, 836, 835, 1, 0, 0, 0, 836, 837, 1, 0, 0, 0, 837, 838, 1, 0, 0, 0, 838, 840, 3, 267, 133, 0, 839, 841, 7, 10, 0, 0, 840, 839, 1, 0, 0, 0, 840, 841, 1, 0, 0, 0, 841, 146, 1, 0, 0, 0, 842, 843, 5, 116, 0, 0, 843, 844, 5, 114, 0, 0, 844, 845, 5, 117, 0, 0, 845, 852, 5, 101, 0, 0, 846, 847, 5, 102, 0, 0, 847, 848, 5, 97, 0, 0, 848, 849, 5, 108, 0, 0, 849, 850, 5, 115, 0, 0, 850, 852, 5, 101, 0, 0, 851, 842, 1, 0, 0, 0, 851, 846, 1, 0, 0, 0, 852, 148, 1, 0, 0, 0, 853, 856, 5, 39, 0, 0, 854, 857, 8, 13, 0, 0, 855, 857, 3, 261, 130, 0, 856, 854, 1, 0, 0, 0, 856, 855, 1, 0, 0, 0, 857, 858, 1, 0, 0, 0, 858, 859, 5, 39, 0, 0, 859, 150, 1, 0, 0, 0, 860, 865, 5, 34, 0, 0, 861, 864, 8, 14, 0, 0, 862, 864, 3, 261, 130, 0, 863, 861, 1, 0, 0, 0, 863, 862, 1, 0, 0, 0, 864, 867, 1, 0, 0, 0, 865, 863, 1, 0, 0, 0, 865, 866, 1, 0, 0, 0, 866, 868, 1, 0, 0, 0, 867, 865, 1, 0, 0, 0, 868, 869, 5, 34, 0, 0, 869, 152, 1, 0, 0, 0, 870, 871, 5, 34, 0, 0, 871, 872, 5, 34, 0, 0, 872, 873, 5, 34, 0, 0, 873, 877, 1, 0, 0, 0, 874, 876, 7, 15, 0, 0, 875, 874, 1, 0, 0, 0, 876, 879, 1, 0, 0, 0, 877, 875, 1, 0, 0, 0, 877, 878, 1, 0, 0, 0, 878, 880, 1, 0, 0, 0, 879, 877, 1, 0, 0, 0, 880, 885, 7, 16, 0, 0, 881, 884, 9, 0, 0, 0, 882, 884, 3, 261, 130, 0, 883, 881, 1, 0, 0, 0, 883, 882, 1, 0, 0, 0, 884, 887, 1, 0, 0, 0, 885, 886, 1, 0, 0, 0, 885, 883, 1, 0, 0, 0, 886, 888, 1, 0, 0, 0, 887, 885, 1, 0, 0, 0, 888, 889, 5, 34, 0, 0, 889, 890, 5, 34, 0, 0, 890, 891, 5, 34, 0, 0, 891, 154, 1, 0, 0, 0, 892, 893, 5, 110, 0, 0, 893, 894, 5, 117, 0, 0, 894, 895, 5, 108, 0, 0, 895, 896, 5, 108, 0, 0, 896, 156, 1, 0, 0, 0, 897, 898, 5, 40, 0, 0, 898, 158, 1, 0, 0, 0, 899, 900, 5, 41, 0, 0, 900, 160, 1, 0, 0, 0, 901, 902, 5, 123, 0, 0, 902, 162, 1, 0, 0, 0, 903, 904, 5, 125, 0, 0, 904, 164, 1, 0, 0, 0, 905, 906, 5, 91, 0, 0, 906, 166, 1, 0, 0, 0, 907, 908, 5, 93, 0, 0, 908, 168, 1, 0, 0, 0, 909, 910, 5, 59, 0, 0, 910, 170, 1, 0, 0, 0, 911, 912, 5, 44, 0, 0, 912, 172, 1, 0, 0, 0, 913, 914, 5, 46, 0, 0, 914, 174, 1, 0, 0, 0, 915, 916, 5, 61, 0, 0, 916, 176, 1, 0, 0, 0, 917, 918, 5, 62, 0, 0, 918, 178, 1, 0, 0, 0, 919, 920, 5, 60, 0, 0, 920, 180, 1, 0, 0, 0, 921, 922, 5, 33, 0, 0, 922, 182, 1, 0, 0, 0, 923, 924, 5, 126, 0, 0, 924, 184, 1, 0, 0, 0, 925, 926, 5, 63, 0, 0, 926, 186, 1, 0, 0, 0, 927, 928, 5, 58, 0, 0, 928, 188, 1, 0, 0, 0, 929, 930, 5, 61, 0, 0, 930, 931, 5, 61, 0, 0, 931, 190, 1, 0, 0, 0, 932, 933, 5, 60, 0, 0, 933, 934, 5, 61, 0, 0, 934, 192, 1, 0, 0, 0, 935, 936, 5, 62, 0, 0, 936, 937, 5, 61, 0, 0, 937, 194, 1, 0, 0, 0, 938, 939, 5, 33, 0, 0, 939, 940, 5, 61, 0, 0, 940, 196, 1, 0, 0, 0, 941, 942, 5, 38, 0, 0, 942, 943, 5, 38, 0, 0, 943, 198, 1, 0, 0, 0, 944, 945, 5, 124, 0, 0, 945, 946, 5, 124, 0, 0, 946, 200, 1, 0, 0, 0, 947, 948, 5, 43, 0, 0, 948, 949, 5, 43, 0, 0, 949, 202, 1, 0, 0, 0, 950, 951, 5, 45, 0, 0, 951, 952, 5, 45, 0, 0, 952, 204, 1, 0, 0, 0, 953, 954, 5, 43, 0, 0, 954, 206, 1, 0, 0, 0, 955, 956, 5, 45, 0, 0, 956, 208, 1, 0, 0, 0, 957, 958, 5, 42, 0, 0, 958, 210, 1, 0, 0, 0, 959, 960, 5, 47, 0, 0, 960, 212, 1, 0, 0, 0, 961, 962, 5, 38, 0, 0, 962, 214, 1, 0, 0, 0, 963, 964, 5, 124, 0, 0, 964, 216, 1, 0, 0, 0, 965, 966, 5, 94, 0, 0, 966, 218, 1, 0, 0, 0, 967, 968, 5, 37, 0, 0, 968, 220, 1, 0, 0, 0, 969, 970, 5, 43, 0, 0, 970, 971, 5, 61, 0, 0, 971, 222, 1, 0, 0, 0, 972, 973, 5, 45, 0, 0, 973, 974, 5, 61, 0, 0, 974, 224, 1, 0, 0, 0, 975, 976, 5, 42, 0, 0, 976, 977, 5, 61, 0, 0, 977, 226, 1, 0, 0, 0, 978, 979, 5, 47, 0, 0, 979, 980, 5, 61, 0, 0, 980, 228, 1, 0, 0, 0, 981, 982, 5, 38, 0, 0, 982, 983, 5, 61, 0, 0, 983, 230, 1, 0, 0, 0, 984, 985, 5, 124, 0, 0, 985, 986, 5, 61, 0, 0, 986, 232, 1, 0, 0, 0, 987, 988, 5, 94, 0, 0, 988, 989, 5, 61, 0, 0, 989, 234, 1, 0, 0, 0, 990, 991, 5, 37, 0, 0, 991, 992, 5, 61, 0, 0, 992, 236, 1, 0, 0, 0, 993, 994, 5, 60, 0, 0, 994, 995, 5, 60, 0, 0, 995, 996, 5, 61, 0, 0, 996, 238, 1, 0, 0, 0, 997, 998, 5, 62, 0, 0, 998, 999, 5, 62, 0, 0, 999, 1000, 5, 61, 0, 0, 1000, 240, 1, 0, 0, 0, 1001, 1002, 5, 62, 0, 0, 1002, 1003, 5, 62, 0, 0, 1003, 1004, 5, 62, 0, 0, 1004, 1005, 5, 61, 0, 0, 1005, 242, 1, 0, 0, 0, 1006, 1007, 5, 45, 0, 0, 1007, 1008, 5, 62, 0, 0, 1008, 244, 1, 0, 0, 0, 1009, 1010, 5, 58, 0, 0, 1010, 1011, 5, 58, 0, 0, 1011, 246, 1, 0, 0, 0, 1012, 1013, 5, 64, 0, 0, 1013, 248, 1, 0, 0, 0, 1014, 1015, 5, 46, 0, 0, 1015, 1016, 5, 46, 0, 0, 1016, 1017, 5, 46, 0, 0, 1017, 250, 1, 0, 0, 0, 1018, 1020, 7, 17, 0, 0, 1019, 1018, 1, 0, 0, 0, 1020, 1021, 1, 0, 0, 0, 1021, 1019, 1, 0, 0, 0, 1021, 1022, 1, 0, 0, 0, 1022, 1023, 1, 0, 0, 0, 1023, 1024, 6, 125, 0, 0, 1024, 252, 1, 0, 0, 0, 1025, 1026, 5, 47, 0, 0, 1026, 1027, 5, 42, 0, 0, 1027, 1031, 1, 0, 0, 0, 1028, 1030, 9, 0, 0, 0, 1029, 1028, 1, 0, 0, 0, 1030, 1033, 1, 0, 0, 0, 1031, 1032, 1, 0, 0, 0, 1031, 1029, 1, 0, 0, 0, 1032, 1034, 1, 0, 0, 0, 1033, 1031, 1, 0, 0, 0, 1034, 1035, 5, 42, 0, 0, 1035, 1036, 5, 47, 0, 0, 1036, 1037, 1, 0, 0, 0, 1037, 1038, 6, 126, 0, 0, 1038, 254, 1, 0, 0, 0, 1039, 1040, 5, 47, 0, 0, 1040, 1041, 5, 47, 0, 0, 1041, 1045, 1, 0, 0, 0, 1042, 1044, 8, 16, 0, 0, 1043, 1042, 1, 0, 0, 0, 1044, 1047, 1, 0, 0, 0, 1045, 1043, 1, 0, 0, 0, 1045, 1046, 1, 0, 0, 0, 1046, 1048, 1, 0, 0, 0, 1047, 1045, 1, 0, 0, 0, 1048, 1049, 6, 127, 0, 0, 1049, 256, 1, 0, 0, 0, 1050, 1054, 3, 271, 135, 0, 1051, 1053, 3, 269, 134, 0, 1052, 1051, 1, 0, 0, 0, 1053, 1056, 1, 0, 0, 0, 1054, 1052, 1, 0, 0, 0, 1054, 1055, 1, 0, 0, 0, 1055, 258, 1, 0, 0, 0, 1056, 1054, 1, 0, 0, 0, 1057, 1059, 7, 18, 0, 0, 1058, 1060, 7, 12, 0, 0, 1059, 1058, 1, 0, 0, 0, 1059, 1060, 1, 0, 0, 0, 1060, 1061, 1, 0, 0, 0, 1061, 1062, 3, 267, 133, 0, 1062, 260, 1, 0, 0, 0, 1063, 1069, 5, 92, 0, 0, 1064, 1065, 5, 117, 0, 0, 1065, 1066, 5, 48, 0, 0, 1066, 1067, 5, 48, 0, 0, 1067, 1068, 5, 53, 0, 0, 1068, 1070, 5, 99, 0, 0, 1069, 1064, 1, 0, 0, 0, 1069, 1070, 1, 0, 0, 0, 1070, 1071, 1, 0, 0, 0, 1071, 1099, 7, 19, 0, 0, 1072, 1078, 5, 92, 0, 0, 1073, 1074, 5, 117, 0, 0, 1074, 1075, 5, 48, 0, 0, 1075, 1076, 5, 48, 0, 0, 1076, 1077, 5, 53, 0, 0, 1077, 1079, 5, 99, 0, 0, 1078, 1073, 1, 0, 0, 0, 1078, 1079, 1, 0, 0, 0, 1079, 1084, 1, 0, 0, 0, 1080, 1082, 7, 20, 0, 0, 1081, 1080, 1, 0, 0, 0, 1081, 1082, 1, 0, 0, 0, 1082, 1083, 1, 0, 0, 0, 1083, 1085, 7, 5, 0, 0, 1084, 1081, 1, 0, 0, 0, 1084, 1085, 1, 0, 0, 0, 1085, 1086, 1, 0, 0, 0, 1086, 1099, 7, 5, 0, 0, 1087, 1089, 5, 92, 0, 0, 1088, 1090, 5, 117, 0, 0, 1089, 1088, 1, 0, 0, 0, 1090, 1091, 1, 0, 0, 0, 1091, 1089, 1, 0, 0, 0, 1091, 1092, 1, 0, 0, 0, 1092, 1093, 1, 0, 0, 0, 1093, 1094, 3, 265, 132, 0, 1094, 1095, 3, 265, 132, 0, 1095, 1096, 3, 265, 132, 0, 1096, 1097, 3, 265, 132, 0, 1097, 1099, 1, 0, 0, 0, 1098, 1063, 1, 0, 0, 0, 1098, 1072, 1, 0, 0, 0, 1098, 1087, 1, 0, 0, 0, 1099, 262, 1, 0, 0, 0, 1100, 1109, 3, 265, 132, 0, 1101, 1104, 3, 265, 132, 0, 1102, 1104, 5, 95, 0, 0, 1103, 1101, 1, 0, 0, 0, 1103, 1102, 1, 0, 0, 0, 1104, 1107, 1, 0, 0, 0, 1105, 1103, 1, 0, 0, 0, 1105, 1106, 1, 0, 0, 0, 1106, 1108, 1, 0, 0, 0, 1107, 1105, 1, 0, 0, 0, 1108, 1110, 3, 265, 132, 0, 1109, 1105, 1, 0, 0, 0, 1109, 1110, 1, 0, 0, 0, 1110, 264, 1, 0, 0, 0, 1111, 1112, 7, 3, 0, 0, 1112, 266, 1, 0, 0, 0, 1113, 1121, 7, 21, 0, 0, 1114, 1116, 7, 22, 0, 0, 1115, 1114, 1, 0, 0, 0, 1116, 1119, 1, 0, 0, 0, 1117, 1115, 1, 0, 0, 0, 1117, 1118, 1, 0, 0, 0, 1118, 1120, 1, 0, 0, 0, 1119, 1117, 1, 0, 0, 0, 1120, 1122, 7, 21, 0, 0, 1121, 1117, 1, 0, 0, 0, 1121, 1122, 1, 0, 0, 0, 1122, 268, 1, 0, 0, 0, 1123, 1126, 3, 271, 135, 0, 1124, 1126, 7, 21, 0, 0, 1125, 1123, 1, 0, 0, 0, 1125, 1124, 1, 0, 0, 0, 1126, 270, 1, 0, 0, 0, 1127, 1132, 7, 23, 0, 0, 1128, 1132, 8, 24, 0, 0, 1129, 1130, 7, 25, 0, 0, 1130, 1132, 7, 26, 0, 0, 1131, 1127, 1, 0, 0, 0, 1131, 1128, 1, 0, 0, 0, 1131, 1129, 1, 0, 0, 0, 1132, 272, 1, 0, 0, 0, 53, 0, 731, 736, 739, 741, 744, 752, 756, 759, 765, 772, 776, 779, 787, 791, 794, 799, 803, 806, 809, 814, 817, 819, 825, 828, 832, 836, 840, 851, 856, 863, 865, 877, 883, 885, 1021, 1031, 1045, 1054, 1059, 1069, 1078, 1081, 1084, 1091, 1098, 1103, 1105, 1109, 1117, 1121, 1125, 1131, 1, 0, 1, 0], -); - -pub fn metadata() -> &'static GrammarMetadata { - &METADATA -} - -pub fn rule_names() -> &'static [&'static str] { - METADATA.rule_names() -} - -pub use antlr4_runtime::generated::{lex, lex_stream}; - - -static ATN_CELL: OnceLock = OnceLock::new(); - -/// Deserializes and caches the grammar ATN for all lexer instances. -fn atn() -> &'static LexerAtn { - ATN_CELL.get_or_init(|| { - let serialized = metadata().serialized_atn(); - AtnDeserializer::new(&serialized) - .deserialize() - .expect("generated lexer contains a valid ANTLR serialized ATN") - }) -} - -static LEXER_DFA_DATA: &[u32] = &[1280852999,1,0,491,0,0,65535,4294967295,1,1,65535,0,2,1,65535,1,3,2,65535,4294967295,4,3,65535,2,5,1,65535,3,6,1,65535,4,7,4,65535,4294967295,8,1,65535,5,8,1,65535,6,9,1,65535,7,10,1,65535,8,8,1,65535,9,11,1,65535,10,12,1,65535,11,13,1,65535,12,14,1,65535,13,15,1,65535,14,16,1,65535,15,8,1,65535,16,17,1,65535,17,18,1,65535,18,19,1,65535,19,8,1,65535,20,8,1,65535,21,8,1,65535,22,8,1,65535,23,20,1,65535,24,21,3,65535,25,22,3,65535,26,23,3,65535,27,24,3,65535,28,25,3,65535,29,26,3,65535,30,27,3,65535,31,28,3,65535,32,29,3,65535,33,30,3,65535,34,31,3,65535,35,32,3,65535,36,33,3,65535,37,34,3,65535,38,35,3,65535,39,36,3,65535,40,37,3,65535,41,38,3,65535,42,39,3,65535,43,40,3,65535,44,8,1,65535,45,41,1,65535,46,8,1,65535,47,8,1,65535,48,8,5,65535,4294967295,8,1,65535,49,42,2,65535,4294967295,43,1,65535,50,44,1,65535,4294967295,8,5,65535,4294967295,8,1,65535,51,8,1,65535,52,8,1,65535,53,45,1,65535,4294967295,46,1,65535,4294967295,8,1,65535,54,8,1,65535,55,8,1,65535,56,8,1,65535,57,8,1,65535,58,8,1,65535,59,47,1,65535,4294967295,48,1,65535,60,49,6,65535,4294967295,50,7,65535,61,8,1,65535,62,51,1,65535,63,52,1,65535,64,53,1,65535,4294967295,54,1,65535,4294967295,8,1,65535,65,55,1,65535,4294967295,8,1,65535,66,56,1,65535,4294967295,57,1,65535,4294967295,58,1,65535,67,59,1,65535,4294967295,8,1,65535,68,60,1,65535,4294967295,8,1,65535,69,8,1,65535,70,8,1,65535,71,61,1,65535,4294967295,8,1,65535,72,62,3,65535,73,63,3,65535,74,64,3,65535,75,65,3,65535,76,66,3,65535,77,67,3,65535,78,68,3,65535,79,69,3,65535,80,70,3,65535,81,71,3,65535,82,72,3,65535,83,73,3,65535,84,74,3,65535,85,75,3,65535,86,76,3,65535,87,77,3,65535,88,78,3,65535,89,79,3,65535,90,80,3,65535,91,4,3,65535,92,81,3,65535,93,82,3,65535,94,83,3,65535,95,84,3,65535,96,85,3,65535,97,86,3,65535,98,87,3,65535,99,88,3,65535,100,89,3,65535,101,90,3,65535,102,91,3,65535,103,92,3,65535,104,93,3,65535,105,94,3,65535,106,95,3,65535,107,96,3,65535,108,97,3,65535,109,98,3,65535,110,99,3,65535,111,100,3,65535,112,101,3,65535,113,4,3,65535,114,102,3,65535,115,103,3,65535,116,104,3,65535,117,105,3,65535,118,106,3,65535,119,107,3,65535,120,108,3,65535,121,8,1,65535,122,8,1,65535,123,8,1,65535,124,109,1,65535,4294967295,110,2,65535,4294967295,42,2,65535,4294967295,111,1,65535,4294967295,8,1,65535,125,112,1,65535,4294967295,113,1,65535,4294967295,114,1,65535,4294967295,8,1,65535,126,115,1,65535,4294967295,116,1,65535,4294967295,117,6,65535,4294967295,118,1,65535,127,8,1,65535,128,119,1,65535,4294967295,120,1,65535,4294967295,121,1,65535,129,122,1,65535,4294967295,123,1,65535,130,124,1,65535,4294967295,125,1,65535,131,126,1,65535,4294967295,127,1,65535,132,8,1,65535,133,8,1,65535,134,128,1,65535,4294967295,129,3,65535,135,130,3,65535,136,131,3,65535,137,132,3,65535,138,133,3,65535,139,134,3,65535,140,135,3,65535,141,136,3,65535,142,137,3,65535,143,138,3,65535,144,139,3,65535,145,140,3,65535,146,141,3,65535,147,142,3,65535,148,143,3,65535,149,144,3,65535,150,145,3,65535,151,146,3,65535,152,147,3,65535,153,4,3,65535,154,148,3,65535,155,149,3,65535,156,150,3,65535,157,151,3,65535,158,152,3,65535,159,153,3,65535,160,154,3,65535,161,4,3,65535,162,155,3,65535,163,156,3,65535,164,157,3,65535,165,158,3,65535,166,159,3,65535,167,160,3,65535,168,161,3,65535,169,162,3,65535,170,163,3,65535,171,164,3,65535,172,165,3,65535,173,166,3,65535,174,167,3,65535,175,168,3,65535,176,169,3,65535,177,170,3,65535,178,171,3,65535,179,172,3,65535,180,173,3,65535,181,174,3,65535,182,175,3,65535,183,176,3,65535,184,4,3,65535,185,177,3,65535,186,4,3,65535,187,178,3,65535,188,179,3,65535,189,180,3,65535,190,181,3,65535,191,182,3,65535,192,183,3,65535,193,184,8,65535,4294967295,185,1,65535,4294967295,186,1,65535,4294967295,187,1,65535,4294967295,188,1,65535,4294967295,189,1,65535,4294967295,190,1,65535,4294967295,191,1,65535,4294967295,192,1,65535,194,8,1,65535,195,193,1,65535,4294967295,8,1,65535,196,194,1,65535,4294967295,195,1,65535,4294967295,196,1,65535,4294967295,197,1,65535,4294967295,8,1,65535,197,198,1,65535,4294967295,199,1,65535,4294967295,200,1,65535,4294967295,8,1,65535,198,201,3,65535,199,202,3,65535,200,203,3,65535,201,204,3,65535,202,4,3,65535,203,4,3,65535,204,205,3,65535,205,4,3,65535,206,206,3,65535,207,207,3,65535,208,208,3,65535,209,209,3,65535,210,210,3,65535,211,4,3,65535,212,4,3,65535,213,211,3,65535,214,212,3,65535,215,176,3,65535,216,213,3,65535,217,214,3,65535,218,4,3,65535,219,215,3,65535,220,216,3,65535,221,217,3,65535,222,218,3,65535,223,4,3,65535,224,219,3,65535,225,220,3,65535,226,221,1,65535,4294967295,4,3,65535,227,222,3,65535,228,223,3,65535,229,224,3,65535,230,225,3,65535,231,226,3,65535,232,227,3,65535,233,228,3,65535,234,229,3,65535,235,230,3,65535,236,231,3,65535,237,232,3,65535,238,233,3,65535,239,234,3,65535,240,235,3,65535,241,236,3,65535,242,237,3,65535,243,238,3,65535,244,4,3,65535,245,239,3,65535,246,240,3,65535,247,4,3,65535,248,4,3,65535,249,4,3,65535,250,241,3,65535,251,4,3,65535,252,242,3,65535,253,4,3,65535,254,243,3,65535,255,244,8,65535,4294967295,245,8,65535,4294967295,246,1,65535,4294967295,247,1,65535,4294967295,248,1,65535,4294967295,249,1,65535,4294967295,250,1,65535,4294967295,251,1,65535,4294967295,252,1,65535,4294967295,253,1,65535,256,254,1,65535,257,255,3,65535,258,256,3,65535,259,257,3,65535,260,4,3,65535,261,4,3,65535,262,4,3,65535,263,4,3,65535,264,258,3,65535,265,259,3,65535,266,260,3,65535,267,261,3,65535,268,262,3,65535,269,263,3,65535,270,4,3,65535,271,264,3,65535,272,265,3,65535,273,266,3,65535,274,267,3,65535,275,268,3,65535,276,269,3,65535,277,270,1,65535,4294967295,4,3,65535,278,271,3,65535,279,272,3,65535,280,273,3,65535,281,274,3,65535,282,275,3,65535,283,276,3,65535,284,277,3,65535,285,278,3,65535,286,279,3,65535,287,280,3,65535,288,4,3,65535,289,281,3,65535,290,282,3,65535,291,4,3,65535,292,283,3,65535,293,284,3,65535,294,285,3,65535,295,286,3,65535,296,287,3,65535,297,4,3,65535,298,4,3,65535,299,288,8,65535,4294967295,289,8,65535,4294967295,184,8,65535,4294967295,290,8,65535,4294967295,291,1,65535,4294967295,292,1,65535,4294967295,293,1,65535,4294967295,294,1,65535,4294967295,8,1,65535,300,295,1,65535,4294967295,296,3,65535,301,4,3,65535,302,297,3,65535,303,298,3,65535,304,299,3,65535,305,4,3,65535,306,300,3,65535,307,301,3,65535,308,302,3,65535,309,303,3,65535,310,4,3,65535,311,304,3,65535,312,305,3,65535,313,4,3,65535,314,4,3,65535,315,306,1,65535,4294967295,307,3,65535,316,308,3,65535,317,309,3,65535,318,310,3,65535,319,311,3,65535,320,4,3,65535,321,4,3,65535,322,312,3,65535,323,4,3,65535,324,4,3,65535,325,4,3,65535,326,313,3,65535,327,4,3,65535,328,314,3,65535,329,4,3,65535,330,315,3,65535,331,316,3,65535,332,8,1,65535,333,317,8,65535,4294967295,318,8,65535,4294967295,319,8,65535,4294967295,320,2,65535,4294967295,321,1,65535,4294967295,322,3,65535,334,4,3,65535,335,323,3,65535,336,4,3,65535,337,4,3,65535,338,4,3,65535,339,4,3,65535,340,324,3,65535,341,325,3,65535,342,326,3,65535,343,327,1,65535,4294967295,4,3,65535,344,4,3,65535,345,4,3,65535,346,328,3,65535,347,329,3,65535,348,330,3,65535,349,331,3,65535,350,332,3,65535,351,333,3,65535,352,334,3,65535,353,335,3,65535,354,336,8,65535,4294967295,337,8,65535,4294967295,42,2,65535,355,338,2,65535,4294967295,45,1,65535,356,4,3,65535,357,4,3,65535,358,339,3,65535,359,340,3,65535,360,341,3,65535,361,342,1,65535,4294967295,343,3,65535,362,4,3,65535,363,4,3,65535,364,4,3,65535,365,344,3,65535,366,345,3,65535,367,346,3,65535,368,4,3,65535,369,184,8,65535,4294967295,347,8,65535,4294967295,42,2,65535,370,348,2,65535,4294967295,42,2,65535,4294967295,349,2,65535,4294967295,350,2,65535,4294967295,351,3,65535,371,352,3,65535,372,4,3,65535,373,353,1,65535,4294967295,4,3,65535,374,354,3,65535,375,4,3,65535,376,355,3,65535,377,356,8,65535,4294967295,357,2,65535,4294967295,358,2,65535,4294967295,359,2,65535,4294967295,360,2,65535,4294967295,4,3,65535,378,4,3,65535,379,8,1,65535,380,361,3,65535,381,4,3,65535,382,362,2,65535,4294967295,363,2,65535,4294967295,364,2,65535,4294967295,365,2,65535,4294967295,366,2,65535,4294967295,367,3,65535,383,368,2,65535,4294967295,369,2,65535,4294967295,42,2,65535,4294967295,370,2,65535,4294967295,4,3,65535,384,42,2,65535,4294967295,371,2,65535,4294967295,372,2,65535,4294967295,491,0,773,218892809,8224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,14640,0,10754,854531,0,0,261,14128,0,261,14640,0,0,0,0,0,0,261,24415,0,261,14640,0,261,24415,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,517,538970377,0,0,0,0,0,0,0,0,0,0,261,24415,0,261,10794,0,261,14640,0,0,261,24415,0,261,24415,0,261,12592,0,0,261,14640,0,0,773,1178679600,26209,261,24415,0,261,14640,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6038019,0,0,261,30069,0,0,0,261,30069,0,0,261,14640,0,0,261,24415,0,0,261,24415,0,261,24415,0,773,1178679600,26209,0,0,0,261,24415,0,261,24415,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,23644,0,0,0,0,0,261,24415,0,261,24415,0,0,261,14640,0,773,1178679600,26209,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,24415,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,30069,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,30069,0,0,0,0,0,0,0,0,261,30069,0,0,0,0,0,0,0,0,0,0,0,0,373,4294967295,4294967295,4294967295,4294967295,131071,4294901761,65537,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,131073,4294901763,327684,458758,589832,720906,851980,983054,1114128,1114129,1114129,1114129,1114129,1245202,1376276,1507350,262168,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,1638404,1769471,262171,1900543,1966109,2097183,2228257,2293764,262148,2424868,2555942,262184,2752553,2883627,3014701,3080196,3145732,3276849,4294901811,4294967295,4294967295,4294967295,4294967295,131071,4294901761,65537,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901761,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3538943,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538999,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3866623,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901819,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3997695,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3997757,3997757,3997757,3997757,3997757,4063231,4294901821,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,4294901821,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997758,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,3997757,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4194303,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4259839,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325375,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4390911,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4456447,4294901828,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901829,4587590,4587590,4587590,4587590,4587590,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901831,4294967295,4784127,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4849663,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901834,4915275,4915275,4915275,4915275,4980812,4294967295,4294967295,4294967295,4294967295,4294901837,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294901841,4294967295,4294967295,5439487,4294967295,4294901837,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294901841,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901834,5439571,5439571,5439571,5439571,5439571,4294967295,4294967295,4294967295,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5570559,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901845,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5701718,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5832703,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5898239,4294901850,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6029311,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262236,262148,262148,262148,262148,262148,262148,262148,6094852,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,6160388,262148,262239,262148,262148,6291460,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,6422527,262148,262148,262148,262242,262148,262243,6553604,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,6619140,262148,262148,262148,262148,6684676,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262247,262248,262148,262148,262148,262148,262249,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,7012351,262148,262148,262148,7012356,262148,262252,7143428,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,7208964,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262255,262148,262148,7340036,262257,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,7471108,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,7536644,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,7667711,262148,7667716,262148,262148,262148,262148,7733252,262148,262148,7798788,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262264,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,7995391,262148,7995396,262148,262148,262148,262148,262148,262148,262267,8126468,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,8192004,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,8257540,262148,262271,262148,262148,262148,262148,262148,8454272,8519684,8585220,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262276,262148,262148,8716292,262148,262278,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,8847364,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,8978431,262148,262148,262148,262148,262148,262148,8978436,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,9109642,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,9175044,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,9306111,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901902,4294967295,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901904,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901814,4294967295,3604479,4294967295,4294967295,4294967295,4294967295,9502865,9502865,9568402,9568402,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901814,4294967295,4294967295,4294901814,4294967295,4294901814,4294967295,4294967295,4294967295,4294901814,4294967295,3538998,9633846,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,9764863,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901821,4294967295,4063231,4294967295,4294967295,4294967295,4294967295,9765013,9765013,9830550,9830550,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901821,4294967295,4294967295,4294901821,4294967295,4294901821,4294967295,4294967295,4294967295,4294901821,4294967295,3997757,9895997,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901912,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4587590,4587590,4587590,4587590,4587590,4294967295,4294967295,4294967295,4294967295,4294967295,10027086,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10158079,4294967295,4294967295,10027086,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653211,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4718664,4718664,4718664,4718664,4718664,4784127,4294901832,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4718664,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10223772,10223772,10223772,10223772,10223772,4294967295,4294967295,4294967295,4294967295,4294967295,10027086,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10027086,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901834,4915275,4915275,4915275,4915275,4980812,4294967295,4294967295,4294967295,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901917,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10420223,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901917,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901834,4980812,4980812,4980812,4980812,4980812,4294967295,4294967295,4294967295,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10485759,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10485920,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10616831,10616831,4294967295,10616994,10616994,10616994,10616994,10616994,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901923,10748068,10748068,10748068,10748068,10748068,4294967295,4294967295,4294967295,10813439,10748068,10748068,4294901924,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10813439,10748068,10748068,4294901924,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4915275,4915275,4915275,4915275,4980812,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5439487,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901834,5439571,5439571,5439571,5439571,5439571,4294967295,4294967295,4294967295,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10878975,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10879142,10879142,10879142,10879142,10879142,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5570559,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,11010047,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,11075583,4294901929,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,11141124,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,11206660,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,11272196,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,11337732,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262318,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,11468804,262320,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,11665407,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,11730943,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262323,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262324,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,11862020,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,11927556,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,11993092,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262328,262148,262329,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262330,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262331,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,12320772,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262333,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262334,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262335,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,12582916,262337,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262338,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262339,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262340,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,12910596,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262342,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262343,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,13107204,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,13172740,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262346,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,13303812,262148,262148,13369348,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262349,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,13500420,262148,262148,262148,262148,262148,262148,13565956,262148,262352,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,13762559,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,13762564,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,13893631,262148,262148,262148,262148,262148,262148,262148,262148,262356,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262357,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,14024708,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262359,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,14155780,262148,262148,262148,262148,262361,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,14352383,262148,262148,262148,262148,262148,262148,262148,262148,262148,14352388,262148,14417924,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,14483460,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262366,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,14614532,262148,262368,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,14745604,262148,14811140,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262371,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,14942212,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,9502719,4294901989,15073279,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901904,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,9568402,9568402,9568402,9568402,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15139046,15139047,15139047,15139047,15139047,4294967295,4294967295,4294967295,15204351,15139047,15139047,4294901991,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15204351,15139047,15139047,4294901991,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15269887,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,9764863,4294967295,4294967295,4294967295,4294967295,9830550,9830550,9830550,9830550,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,9764863,4294967295,4294967295,4294967295,4294967295,3997757,3997757,3997757,3997757,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15335657,15335658,15335658,15335658,15335658,4294967295,4294967295,4294967295,15400959,15335658,15335658,4294901994,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15400959,15335658,15335658,4294901994,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15466495,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15532031,15532031,4294967295,15532269,15532269,15532269,15532269,15532269,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4587590,4587590,4587590,4587590,4587590,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10158079,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653211,4653127,15597639,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4653127,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10223772,10223772,10223772,10223772,10223772,4294967295,4294967295,4294967295,4294967295,4294967295,10027086,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15728639,4294967295,4294967295,10027086,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4915275,4915275,4915275,4915275,4980812,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10420223,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4980812,4980812,4980812,4980812,4980812,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10485759,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10485920,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902000,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15859711,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902000,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10616994,10616994,10616994,10616994,10616994,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10616994,10616994,10616994,10616994,10616994,4294967295,4294967295,4294967295,4294967295,4294967295,4294901838,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15925247,4294967295,4294967295,4294901838,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15925491,15925491,15925491,15925491,15925491,4294967295,4294967295,4294967295,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902004,10748068,10748068,10748068,10748068,10748068,4294967295,4294967295,4294967295,10813439,10748068,10748068,4294901924,4294967295,4294967295,4294902005,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,16252927,10813439,10748068,10748068,4294901924,4294967295,4294967295,4294902005,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5439571,5439571,5439571,5439571,5439571,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10878975,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901834,10879142,10879142,10879142,10879142,10879142,4294967295,4294967295,4294967295,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,16318463,4294967295,4294967295,5177422,4294901838,4294967295,4294967295,4294901840,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,16383999,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262394,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,16449540,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262396,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,16646143,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,16646148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,16711684,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,16777220,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262401,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,16908292,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,16973828,262404,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,17170431,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262406,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,17235972,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,17301508,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,17367044,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,17432580,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,17498116,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,17629183,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,17694719,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,17694724,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262415,17825796,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262417,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,17956868,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,18022404,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,18087940,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,18153476,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,18284543,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262423,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262424,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,18415620,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,18481156,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262427,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262428,262429,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262430,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,18808836,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,18874372,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,18939908,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262434,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262435,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262436,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,19202052,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,19267588,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262439,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,19398660,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,19464196,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,19529732,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262443,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,19660804,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,19726340,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262446,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,19922943,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262448,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262449,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262450,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262451,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20382006,20382007,20382007,20382007,20382007,4294967295,4294967295,4294967295,20447231,20382007,20382007,4294902071,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20447231,20382007,20382007,4294902071,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20382007,20382007,20382007,20382007,20382007,4294967295,4294967295,4294967295,20447231,20382007,20382007,4294902071,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20447231,20382007,20382007,4294902071,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15139047,15139047,15139047,15139047,15139047,4294967295,4294967295,4294967295,15204351,15139047,15139047,4294901991,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15204351,15139047,15139047,4294901991,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15269887,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20513080,20513081,20513081,20513081,20513081,4294967295,4294967295,4294967295,20578303,20513081,20513081,4294902073,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20578303,20513081,20513081,4294902073,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20513081,20513081,20513081,20513081,20513081,4294967295,4294967295,4294967295,20578303,20513081,20513081,4294902073,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20578303,20513081,20513081,4294902073,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15335658,15335658,15335658,15335658,15335658,4294967295,4294967295,4294967295,15400959,15335658,15335658,4294901994,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15400959,15335658,15335658,4294901994,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15466495,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15532269,15532269,15532269,15532269,15532269,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15532269,15532269,15532269,15532269,15532269,4294967295,4294967295,4294967295,4294967295,4294967295,4294901838,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20643839,4294967295,4294967295,4294901838,4294901838,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10223772,10223772,10223772,10223772,10223772,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15728639,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10485920,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15859711,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10616994,10616994,10616994,10616994,10616994,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15925247,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15925491,15925491,15925491,15925491,15925491,4294967295,4294967295,4294967295,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20709375,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15925491,15925491,15925491,15925491,15925491,4294967295,4294967295,4294967295,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20774911,20774911,4294967295,20775229,20775229,20775229,20775229,20775229,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20840766,20840766,20840766,20840766,20840766,4294967295,4294967295,4294967295,20905983,20840766,20840766,4294902078,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,16252927,20905983,20840766,20840766,4294902078,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,10879142,10879142,10879142,10879142,10879142,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,16318463,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262463,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262464,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,21037060,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,21102596,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262467,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,21233668,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262469,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,21364740,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,21430276,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262472,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262473,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262474,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262475,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262476,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,21823492,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262478,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,22020095,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262480,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262481,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262482,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22282239,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,22282244,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,22413311,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,22413316,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,22544383,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,22544388,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,22609924,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,22675460,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262491,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,22806532,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262493,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,22937604,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262495,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,23068676,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,23134212,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262498,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,23265284,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262500,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,23396356,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,23461892,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262503,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,23592964,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262505,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008106,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,23789931,23789931,23855468,23855468,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,23920869,15007973,15007973,15007973,15007973,15007973,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,23986542,23986542,24052078,23986542,23986542,4294967295,4294967295,4294967295,24051711,23986542,23986542,4294902126,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24051711,23986542,23986542,4294902126,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,23986542,23986542,23986542,23986542,23986542,4294967295,4294967295,4294967295,24051711,23986542,23986542,4294902126,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24051711,23986542,23986542,4294902126,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24117616,24117616,24183152,24117616,24117616,4294967295,4294967295,4294967295,24182783,24117616,24117616,4294902128,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24182783,24117616,24117616,4294902128,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24117616,24117616,24117616,24117616,24117616,4294967295,4294967295,4294967295,24182783,24117616,24117616,4294902128,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24182783,24117616,24117616,4294902128,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15532269,15532269,15532269,15532269,15532269,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20643839,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,15925491,15925491,15925491,15925491,15925491,4294967295,4294967295,4294967295,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20709375,15990783,15925491,15925491,4294902003,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20775229,20775229,20775229,20775229,20775229,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20775229,20775229,20775229,20775229,20775229,4294967295,4294967295,4294967295,4294967295,4294967295,4294902130,4294902130,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24379391,4294967295,4294967295,4294902130,4294902130,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902004,20840766,20840766,20840766,20840766,20840766,4294967295,4294967295,4294967295,20905983,20840766,20840766,4294902078,4294967295,4294967295,4294902005,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,16252927,20905983,20840766,20840766,4294902078,4294967295,4294967295,4294902005,4294967295,4294902006,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,24444927,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262517,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,24575999,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262519,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262520,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,24707076,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262522,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262523,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262524,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,24969220,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262526,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262527,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262528,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,25231364,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,25296900,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,25427967,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,25427972,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262533,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262534,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,25624580,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262536,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,25755652,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262538,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262539,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262540,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262541,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,26083332,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262543,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262544,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262545,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,26345476,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,26411012,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,26476548,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008149,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,23855468,23855468,23855468,23855468,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,26673558,26673559,26673559,26673559,26673559,15007973,15007973,15007973,26673381,26673559,26673559,15008151,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,26673381,26673559,26673559,15008151,15007973,15007973,15007973,15007973,15007973,15007973,26738917,15007973,15007973,15007973,15007973,15007973,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,3604479,3538998,3538998,4294901814,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3604479,3538998,3538998,4294901814,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,3604479,3538998,3538998,4294901814,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3604479,26804278,3538998,4294901814,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3997757,3997757,3997757,3997757,3997757,4294967295,4294967295,4294967295,4063231,3997757,3997757,4294901821,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4063231,3997757,3997757,4294901821,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3997757,3997757,3997757,3997757,3997757,4294967295,4294967295,4294967295,4063231,3997757,3997757,4294901821,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4063231,26869821,3997757,4294901821,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,20775229,20775229,20775229,20775229,20775229,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,24379391,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,26935300,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262556,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,27066372,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262558,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,27197444,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,27262980,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,27328516,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,27394052,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,27459588,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,27590655,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,27656191,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,27656196,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,27721732,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,27787268,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262569,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,27918340,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,27983876,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262572,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,28114948,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,28180484,262148,262148,262148,262148,262148,262148,262148,262575,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262576,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,28443057,28443058,28443058,28443058,28443058,15007973,15007973,15007973,28442853,28443058,28443058,15008178,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,28442853,28443058,28443058,15008178,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,28443058,28443058,28443058,28443058,28443058,15007973,15007973,15007973,28442853,28443058,28443058,15008178,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,28442853,28443058,28443058,15008178,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,26673559,26673559,26673559,26673559,26673559,15007973,15007973,15007973,26673381,26673559,26673559,15008151,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,26673381,26673559,26673559,15008151,15007973,15007973,15007973,15007973,15007973,15007973,26738917,15007973,15007973,15007973,15007973,15007973,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539379,3538998,3538998,3538998,3538998,3538998,3538998,9502865,9502865,9568402,9568402,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539380,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901821,4294967295,28704767,4294967295,4294967295,4294967295,4294967295,9765013,9765013,9830550,9830550,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901821,4294967295,4294967295,4294901821,4294967295,4294901821,4294967295,4294967295,4294967295,4294901821,4294967295,3997757,4294901821,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262582,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,28770308,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262584,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,28901380,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,28966916,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902203,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,29097988,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,29163524,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,29229060,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262591,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262592,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262593,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,29491204,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,29556740,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,29622724,29622724,29688260,29622724,29622724,15007973,15007973,15007973,29622501,29622724,29622724,15008196,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,29622501,29622724,29622724,15008196,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,29622724,29622724,29622724,29622724,29622724,15007973,15007973,15007973,29622501,29622724,29622724,15008196,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,29622501,29622724,29622724,15008196,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539398,3538998,3538998,3538998,3538998,3538998,3538998,29819335,29819335,29884872,29884872,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539401,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,30015542,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262603,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,30146564,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,30212100,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,30343167,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262607,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,30408708,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262609,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262610,262148,4294901764,4294967295,4294967295,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,15007973,30605541,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,29884872,29884872,29884872,29884872,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539379,3538998,3538998,3538998,3538998,3538998,3538998,9502865,9502865,9568402,9568402,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539380,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,30670902,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,30802389,30802390,30802390,30802390,30802390,3538998,3538998,3538998,30801974,30802390,30802390,3539414,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,30801974,30802390,30802390,3539414,3538998,3538998,3538998,3538998,3538998,3538998,30867510,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,30932996,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262617,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902234,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294902235,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,31195140,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008052,15007973,15007973,15007973,15007973,15007973,15007973,23789931,23789931,23855468,23855468,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15008053,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,15007973,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31326685,31326686,31326686,31326686,31326686,3538998,3538998,3538998,31326262,31326686,31326686,3539422,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31326262,31326686,31326686,3539422,3538998,3538998,3538998,3538998,3538998,3538998,31391798,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31523296,31523297,31523297,31523297,31523297,3538998,3538998,3538998,31522870,31523297,31523297,3539425,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31522870,31523297,31523297,3539425,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31523297,31523297,31523297,31523297,31523297,3538998,3538998,3538998,31522870,31523297,31523297,3539425,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31522870,31523297,31523297,3539425,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,30802390,30802390,30802390,30802390,30802390,3538998,3538998,3538998,30801974,30802390,30802390,3539414,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,30801974,30802390,30802390,3539414,3538998,3538998,3538998,3538998,3538998,3538998,30867510,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,31588356,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31719907,31719908,31719908,31719908,31719908,3538998,3538998,3538998,31719478,31719908,31719908,3539428,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31719478,31719908,31719908,3539428,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31719908,31719908,31719908,31719908,31719908,3538998,3538998,3538998,31719478,31719908,31719908,3539428,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31719478,31719908,31719908,3539428,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31326686,31326686,31326686,31326686,31326686,3538998,3538998,3538998,31326262,31326686,31326686,3539422,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31326262,31326686,31326686,3539422,3538998,3538998,3538998,3538998,3538998,3538998,31391798,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31785445,31785445,31850981,31785445,31785445,3538998,3538998,3538998,31785014,31785445,31785445,3539429,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31785014,31785445,31785445,3539429,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31785445,31785445,31785445,31785445,31785445,3538998,3538998,3538998,31785014,31785445,31785445,3539429,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31785014,31785445,31785445,3539429,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901764,4294967295,4294967295,4294967295,4294967295,4294967295,262148,262148,262148,262148,262148,4294967295,4294967295,4294967295,327679,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,327679,327679,262148,262631,262148,262148,262148,262148,262148,262148,262148,262148,262148,262148,4294901764,4294967295,4294967295,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31982056,31982056,32047592,31982056,31982056,3538998,3538998,3538998,31981622,31982056,31982056,3539432,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31981622,31982056,31982056,3539432,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,31982056,31982056,31982056,31982056,31982056,3538998,3538998,3538998,31981622,31982056,31982056,3539432,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,31981622,31982056,31982056,3539432,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,3538998,32112694,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539087,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539000,3538998,3538998,26804278,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3604479,4294901814,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539398,3538998,3538998,3538998,3538998,3538998,3538998,29819335,29819335,29884872,29884872,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3539401,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,3538998,9,3,128,55295,4,55296,56319,52,56320,1114111,4,0,1,128,1114111,54,3,128,55295,4,55296,56319,57,56320,1114111,4,1,128,1114111,61,1,56320,57343,4,1,128,1114111,71,1,128,1114111,72,1,128,1114111,229,385,125,0,1,0,125,0,90,0,0,128,0,0,109,0,0,106,0,0,78,0,0,79,0,0,104,0,0,102,0,0,85,0,0,103,0,0,86,0,0,105,0,0,67,0,0,67,0,0,93,0,0,84,0,0,89,0,0,87,0,0,88,0,0,92,0,0,123,0,0,82,0,0,83,0,0,108,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,80,0,0,107,0,0,81,0,0,91,0,0,97,0,0,75,0,0,117,0,0,98,0,0,114,0,0,112,0,0,100,0,0,110,0,0,101,0,0,111,0,0,121,0,0,71,0,0,127,0,1,0,127,0,113,0,0,71,0,0,69,0,0,71,0,0,67,0,0,67,0,0,122,0,0,95,0,0,94,0,0,96,0,0,116,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,12,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,23,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,55,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,115,0,0,99,0,0,75,0,0,74,0,0,124,0,0,71,0,0,69,0,0,70,0,0,71,0,0,68,0,0,67,0,0,118,0,0,119,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,21,0,0,128,0,0,128,0,0,128,0,0,27,0,0,128,0,0,128,0,0,128,0,0,32,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,58,0,0,128,0,0,60,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,71,0,0,126,0,1,0,126,0,70,0,0,68,0,0,120,0,0,128,0,0,128,0,0,128,0,0,128,0,0,4,0,0,5,0,0,128,0,0,7,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,14,0,0,15,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,22,0,0,128,0,0,128,0,0,128,0,0,128,0,0,29,0,0,128,0,0,128,0,0,77,0,0,34,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,52,0,0,128,0,0,128,0,0,73,0,0,59,0,0,61,0,0,128,0,0,63,0,0,128,0,0,65,0,0,128,0,0,72,0,0,68,0,0,128,0,0,128,0,0,128,0,0,3,0,0,6,0,0,8,0,0,9,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,18,0,0,20,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,35,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,46,0,0,128,0,0,128,0,0,49,0,0,128,0,0,128,0,0,53,0,0,128,0,0,128,0,0,64,0,0,66,0,0,72,0,0,128,0,0,1,0,0,128,0,0,128,0,0,128,0,0,13,0,0,128,0,0,128,0,0,128,0,0,128,0,0,25,0,0,128,0,0,128,0,0,30,0,0,31,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,41,0,0,42,0,0,128,0,0,44,0,0,45,0,0,47,0,0,128,0,0,50,0,0,128,0,0,54,0,0,128,0,0,128,0,0,76,0,0,128,0,0,2,0,0,128,0,0,11,0,0,16,0,0,17,0,0,19,0,0,128,0,0,128,0,0,128,0,0,36,0,0,37,0,0,38,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128,0,0,75,0,0,74,0,0,0,0,0,10,0,0,128,0,0,128,0,0,128,0,0,128,0,0,40,0,0,43,0,0,48,0,0,128,0,0,128,0,0,128,0,0,62,0,0,75,0,0,128,0,0,128,0,0,28,0,0,39,0,0,128,0,0,56,0,0,128,0,0,24,0,0,26,0,0,33,0,0,128,0,0,57,0,0,128,0,0,51,0,0,491,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,0]; - -static LEXER_DFA_CELL: OnceLock = OnceLock::new(); - -/// Ahead-of-time lexer DFA tables compiled by antlr4-rust-gen, embedded so -/// runtime startup only deserializes them. Rebuilt from the ATN instead when -/// the embedded stream comes from a different runtime version. -fn lexer_dfa() -> &'static CompiledLexerDfa { - LEXER_DFA_CELL.get_or_init(|| { - CompiledLexerDfa::from_serialized(LEXER_DFA_DATA) - .unwrap_or_else(|| CompiledLexerDfa::compile(atn())) - }) -} - -#[derive(Clone, Debug)] -pub struct JavaLexer -where - I: CharStream, - H: antlr4_runtime::SemanticHooks, -{ - base: BaseLexer, - hooks: H, -} - -impl JavaLexer -where - I: CharStream, -{ - pub fn new(input: I) -> Self { - Self::with_hooks(input, antlr4_runtime::NoSemanticHooks) - } -} - -impl JavaLexer -where - I: CharStream, - H: antlr4_runtime::SemanticHooks, -{ - pub fn with_hooks(input: I, hooks: H) -> Self { - let grammar_metadata = metadata(); - let data = grammar_metadata.recognizer_data(); - Self { base: BaseLexer::new(input, data).with_shared_dfa(atn()), hooks } - } - - - -} - - - -antlr4_runtime::__antlr4_rust_lexer_facade! { - type: JavaLexer, - fields: { - base: base, - hooks: hooks, - }, - metadata: metadata, - next_token(lexer, sink) { - if H::ENABLES_LEXER_LIFECYCLE { - antlr4_runtime::atn::lexer::next_token_compiled_with_semantic_dispatch(&mut lexer.base, sink, atn(), lexer_dfa(), &mut lexer.hooks, |_, _| false, |_, _| None, antlr4_runtime::UnknownSemanticPolicy::Error, |_, _, _| {}) - } else { - antlr4_runtime::atn::lexer::next_token_compiled(&mut lexer.base, sink, atn(), lexer_dfa()) - } - } -} -} - -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -pub use self::__antlr4_rust_generated::*; diff --git a/crates/mehen-java-parser/src/generated/java_parser.rs b/crates/mehen-java-parser/src/generated/java_parser.rs deleted file mode 100644 index 5ae46cea..00000000 --- a/crates/mehen-java-parser/src/generated/java_parser.rs +++ /dev/null @@ -1,18525 +0,0 @@ -// @generated by antlr-rust-codegen v0.33.1 - do not edit -// project: https://github.com/ophi-dev/antlr-rust-runtime -antlr4_runtime::__antlr4_rust_require_codegen_api!(14, "0.33.1"); -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -#[rustfmt::skip] -mod __antlr4_rust_generated { - -use antlr4_runtime::token::TokenSource; -use antlr4_runtime::token_stream::CommonTokenStream; -use antlr4_runtime::atn::parser_atn::ParserAtn; -use antlr4_runtime::generated::GeneratedRuleError; -use antlr4_runtime::{BaseParser, GrammarMetadata, Parser, Recognizer}; -use std::sync::OnceLock; -#[allow(unused_imports)] -use std::io::Write as _; -#[allow(unused_imports)] -use antlr4_runtime::{java_style_list, PredictionMode, BailErrorStrategy, TerminalNodeView as RuntimeTerminalNode, ErrorNodeView as RuntimeErrorNode, RuleNodeView, AsRuleNode, FromRuleNode, MissingChildError, Token as _}; -pub use antlr4_runtime::generated::{ErrorNode, StoredTreeContext, TerminalNode, __GeneratedInput, __GeneratedTokenView}; -#[allow(unused_imports)] -use antlr4_runtime::generated::{__ActiveParserContext, __FromActiveRuleContext, __GeneratedRuleContext, __RecoveryContextState, __active_context_view, __active_context_view_with_attrs, __context_children, __labeled_token_children, __labeled_token_children_matching, __rule_children, __terminal_children, __token_children, __token_children_matching, __write_invocation_states}; - - -pub const EOF: i32 = antlr4_runtime::TOKEN_EOF; -pub const ABSTRACT: i32 = 1; -pub const ASSERT: i32 = 2; -pub const BOOLEAN: i32 = 3; -pub const BREAK: i32 = 4; -pub const BYTE: i32 = 5; -pub const CASE: i32 = 6; -pub const CATCH: i32 = 7; -pub const CHAR: i32 = 8; -pub const CLASS: i32 = 9; -pub const CONST: i32 = 10; -pub const CONTINUE: i32 = 11; -pub const DEFAULT: i32 = 12; -pub const DO: i32 = 13; -pub const DOUBLE: i32 = 14; -pub const ELSE: i32 = 15; -pub const ENUM: i32 = 16; -pub const EXPORTS: i32 = 17; -pub const EXTENDS: i32 = 18; -pub const FINAL: i32 = 19; -pub const FINALLY: i32 = 20; -pub const FLOAT: i32 = 21; -pub const FOR: i32 = 22; -pub const GOTO: i32 = 23; -pub const IF: i32 = 24; -pub const IMPLEMENTS: i32 = 25; -pub const IMPORT: i32 = 26; -pub const INSTANCEOF: i32 = 27; -pub const INT: i32 = 28; -pub const INTERFACE: i32 = 29; -pub const LONG: i32 = 30; -pub const MODULE: i32 = 31; -pub const NATIVE: i32 = 32; -pub const NEW: i32 = 33; -pub const NON_SEALED: i32 = 34; -pub const OPEN: i32 = 35; -pub const OPENS: i32 = 36; -pub const PACKAGE: i32 = 37; -pub const PERMITS: i32 = 38; -pub const PRIVATE: i32 = 39; -pub const PROTECTED: i32 = 40; -pub const PROVIDES: i32 = 41; -pub const PUBLIC: i32 = 42; -pub const RECORD: i32 = 43; -pub const REQUIRES: i32 = 44; -pub const RETURN: i32 = 45; -pub const SEALED: i32 = 46; -pub const SHORT: i32 = 47; -pub const STATIC: i32 = 48; -pub const STRICTFP: i32 = 49; -pub const SUPER: i32 = 50; -pub const SWITCH: i32 = 51; -pub const SYNCHRONIZED: i32 = 52; -pub const THIS: i32 = 53; -pub const THROW: i32 = 54; -pub const THROWS: i32 = 55; -pub const TO: i32 = 56; -pub const TRANSIENT: i32 = 57; -pub const TRANSITIVE: i32 = 58; -pub const TRY: i32 = 59; -pub const USES: i32 = 60; -pub const VAR: i32 = 61; -pub const VOID: i32 = 62; -pub const VOLATILE: i32 = 63; -pub const WHEN: i32 = 64; -pub const WHILE: i32 = 65; -pub const WITH: i32 = 66; -pub const YIELD: i32 = 67; -pub const DECIMAL_LITERAL: i32 = 68; -pub const HEX_LITERAL: i32 = 69; -pub const OCT_LITERAL: i32 = 70; -pub const BINARY_LITERAL: i32 = 71; -pub const FLOAT_LITERAL: i32 = 72; -pub const HEX_FLOAT_LITERAL: i32 = 73; -pub const BOOL_LITERAL: i32 = 74; -pub const CHAR_LITERAL: i32 = 75; -pub const STRING_LITERAL: i32 = 76; -pub const TEXT_BLOCK: i32 = 77; -pub const NULL_LITERAL: i32 = 78; -pub const LPAREN: i32 = 79; -pub const RPAREN: i32 = 80; -pub const LBRACE: i32 = 81; -pub const RBRACE: i32 = 82; -pub const LBRACK: i32 = 83; -pub const RBRACK: i32 = 84; -pub const SEMI: i32 = 85; -pub const COMMA: i32 = 86; -pub const DOT: i32 = 87; -pub const ASSIGN: i32 = 88; -pub const GT: i32 = 89; -pub const LT: i32 = 90; -pub const BANG: i32 = 91; -pub const TILDE: i32 = 92; -pub const QUESTION: i32 = 93; -pub const COLON: i32 = 94; -pub const EQUAL: i32 = 95; -pub const LE: i32 = 96; -pub const GE: i32 = 97; -pub const NOTEQUAL: i32 = 98; -pub const AND: i32 = 99; -pub const OR: i32 = 100; -pub const INC: i32 = 101; -pub const DEC: i32 = 102; -pub const ADD: i32 = 103; -pub const SUB: i32 = 104; -pub const MUL: i32 = 105; -pub const DIV: i32 = 106; -pub const BITAND: i32 = 107; -pub const BITOR: i32 = 108; -pub const CARET: i32 = 109; -pub const MOD: i32 = 110; -pub const ADD_ASSIGN: i32 = 111; -pub const SUB_ASSIGN: i32 = 112; -pub const MUL_ASSIGN: i32 = 113; -pub const DIV_ASSIGN: i32 = 114; -pub const AND_ASSIGN: i32 = 115; -pub const OR_ASSIGN: i32 = 116; -pub const XOR_ASSIGN: i32 = 117; -pub const MOD_ASSIGN: i32 = 118; -pub const LSHIFT_ASSIGN: i32 = 119; -pub const RSHIFT_ASSIGN: i32 = 120; -pub const URSHIFT_ASSIGN: i32 = 121; -pub const ARROW: i32 = 122; -pub const COLONCOLON: i32 = 123; -pub const AT: i32 = 124; -pub const ELLIPSIS: i32 = 125; -pub const WS: i32 = 126; -pub const COMMENT: i32 = 127; -pub const LINE_COMMENT: i32 = 128; -pub const IDENTIFIER: i32 = 129; - -pub const RULE_COMPILATION_UNIT: usize = 0; -pub const RULE_MODULAR_COMPULATION_UNIT: usize = 1; -pub const RULE_PACKAGE_DECLARATION: usize = 2; -pub const RULE_IMPORT_DECLARATION: usize = 3; -pub const RULE_TYPE_DECLARATION: usize = 4; -pub const RULE_MODIFIER: usize = 5; -pub const RULE_CLASS_OR_INTERFACE_MODIFIER: usize = 6; -pub const RULE_VARIABLE_MODIFIER: usize = 7; -pub const RULE_CLASS_DECLARATION: usize = 8; -pub const RULE_TYPE_PARAMETERS: usize = 9; -pub const RULE_TYPE_PARAMETER: usize = 10; -pub const RULE_TYPE_BOUND: usize = 11; -pub const RULE_ENUM_DECLARATION: usize = 12; -pub const RULE_ENUM_CONSTANTS: usize = 13; -pub const RULE_ENUM_CONSTANT: usize = 14; -pub const RULE_ENUM_BODY_DECLARATIONS: usize = 15; -pub const RULE_INTERFACE_DECLARATION: usize = 16; -pub const RULE_CLASS_BODY: usize = 17; -pub const RULE_INTERFACE_BODY: usize = 18; -pub const RULE_CLASS_BODY_DECLARATION: usize = 19; -pub const RULE_MEMBER_DECLARATION: usize = 20; -pub const RULE_METHOD_DECLARATION: usize = 21; -pub const RULE_METHOD_BODY: usize = 22; -pub const RULE_TYPE_TYPE_OR_VOID: usize = 23; -pub const RULE_GENERIC_METHOD_DECLARATION: usize = 24; -pub const RULE_GENERIC_CONSTRUCTOR_DECLARATION: usize = 25; -pub const RULE_CONSTRUCTOR_DECLARATION: usize = 26; -pub const RULE_COMPACT_CONSTRUCTOR_DECLARATION: usize = 27; -pub const RULE_FIELD_DECLARATION: usize = 28; -pub const RULE_INTERFACE_BODY_DECLARATION: usize = 29; -pub const RULE_INTERFACE_MEMBER_DECLARATION: usize = 30; -pub const RULE_CONST_DECLARATION: usize = 31; -pub const RULE_CONSTANT_DECLARATOR: usize = 32; -pub const RULE_INTERFACE_METHOD_DECLARATION: usize = 33; -pub const RULE_INTERFACE_METHOD_MODIFIER: usize = 34; -pub const RULE_GENERIC_INTERFACE_METHOD_DECLARATION: usize = 35; -pub const RULE_INTERFACE_COMMON_BODY_DECLARATION: usize = 36; -pub const RULE_VARIABLE_DECLARATORS: usize = 37; -pub const RULE_VARIABLE_DECLARATOR: usize = 38; -pub const RULE_VARIABLE_DECLARATOR_ID: usize = 39; -pub const RULE_VARIABLE_INITIALIZER: usize = 40; -pub const RULE_ARRAY_INITIALIZER: usize = 41; -pub const RULE_CLASS_TYPE: usize = 42; -pub const RULE_PACKAGE_NAME: usize = 43; -pub const RULE_TYPE_ARGUMENT: usize = 44; -pub const RULE_QUALIFIED_NAME_LIST: usize = 45; -pub const RULE_FORMAL_PARAMETERS: usize = 46; -pub const RULE_RECEIVER_PARAMETER: usize = 47; -pub const RULE_FORMAL_PARAMETER_LIST: usize = 48; -pub const RULE_FORMAL_PARAMETER: usize = 49; -pub const RULE_LAMBDA_LVTI_LIST: usize = 50; -pub const RULE_LAMBDA_LVTI_PARAMETER: usize = 51; -pub const RULE_QUALIFIED_NAME: usize = 52; -pub const RULE_LITERAL: usize = 53; -pub const RULE_INTEGER_LITERAL: usize = 54; -pub const RULE_FLOAT_LITERAL: usize = 55; -pub const RULE_ANNOTATION: usize = 56; -pub const RULE_ANNOTATION_FIELD_VALUES: usize = 57; -pub const RULE_ANNOTATION_FIELD_VALUE: usize = 58; -pub const RULE_ANNOTATION_VALUE: usize = 59; -pub const RULE_ELEMENT_VALUE: usize = 60; -pub const RULE_ELEMENT_VALUE_ARRAY_INITIALIZER: usize = 61; -pub const RULE_ANNOTATION_TYPE_DECLARATION: usize = 62; -pub const RULE_ANNOTATION_TYPE_BODY: usize = 63; -pub const RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION: usize = 64; -pub const RULE_ANNOTATION_TYPE_ELEMENT_REST: usize = 65; -pub const RULE_ANNOTATION_METHOD_OR_CONSTANT_REST: usize = 66; -pub const RULE_ANNOTATION_METHOD_REST: usize = 67; -pub const RULE_ANNOTATION_CONSTANT_REST: usize = 68; -pub const RULE_DEFAULT_VALUE: usize = 69; -pub const RULE_MODULE_DECLARATION: usize = 70; -pub const RULE_MODULE_DIRECTIVE: usize = 71; -pub const RULE_REQUIRES_MODIFIER: usize = 72; -pub const RULE_RECORD_DECLARATION: usize = 73; -pub const RULE_RECORD_HEADER: usize = 74; -pub const RULE_RECORD_COMPONENT_LIST: usize = 75; -pub const RULE_RECORD_COMPONENT: usize = 76; -pub const RULE_RECORD_BODY: usize = 77; -pub const RULE_BLOCK: usize = 78; -pub const RULE_BLOCK_STATEMENT: usize = 79; -pub const RULE_LOCAL_VARIABLE_DECLARATION: usize = 80; -pub const RULE_IDENTIFIER: usize = 81; -pub const RULE_TYPE_IDENTIFIER: usize = 82; -pub const RULE_LOCAL_TYPE_DECLARATION: usize = 83; -pub const RULE_STATEMENT: usize = 84; -pub const RULE_CATCH_CLAUSE: usize = 85; -pub const RULE_CATCH_TYPE: usize = 86; -pub const RULE_FINALLY_BLOCK: usize = 87; -pub const RULE_RESOURCE_SPECIFICATION: usize = 88; -pub const RULE_RESOURCES: usize = 89; -pub const RULE_RESOURCE: usize = 90; -pub const RULE_SWITCH_BLOCK_STATEMENT_GROUP: usize = 91; -pub const RULE_SWITCH_LABEL: usize = 92; -pub const RULE_FOR_CONTROL: usize = 93; -pub const RULE_FOR_INIT: usize = 94; -pub const RULE_ENHANCED_FOR_CONTROL: usize = 95; -pub const RULE_EXPRESSION_LIST: usize = 96; -pub const RULE_METHOD_CALL: usize = 97; -pub const RULE_EXPRESSION: usize = 98; -pub const RULE_PATTERN: usize = 99; -pub const RULE_COMPONENT_PATTERN_LIST: usize = 100; -pub const RULE_COMPONENT_PATTERN: usize = 101; -pub const RULE_LAMBDA_EXPRESSION: usize = 102; -pub const RULE_LAMBDA_PARAMETERS: usize = 103; -pub const RULE_LAMBDA_BODY: usize = 104; -pub const RULE_PRIMARY: usize = 105; -pub const RULE_SWITCH_EXPRESSION: usize = 106; -pub const RULE_SWITCH_LABELED_RULE: usize = 107; -pub const RULE_GUARD: usize = 108; -pub const RULE_CASE_PATTERN: usize = 109; -pub const RULE_SWITCH_RULE_OUTCOME: usize = 110; -pub const RULE_CLASS_OR_INTERFACE_TYPE: usize = 111; -pub const RULE_CREATOR: usize = 112; -pub const RULE_CREATED_NAME: usize = 113; -pub const RULE_INNER_CREATOR: usize = 114; -pub const RULE_ARRAY_CREATOR_REST: usize = 115; -pub const RULE_CLASS_CREATOR_REST: usize = 116; -pub const RULE_EXPLICIT_GENERIC_INVOCATION: usize = 117; -pub const RULE_TYPE_ARGUMENTS_OR_DIAMOND: usize = 118; -pub const RULE_NON_WILDCARD_TYPE_ARGUMENTS_OR_DIAMOND: usize = 119; -pub const RULE_NON_WILDCARD_TYPE_ARGUMENTS: usize = 120; -pub const RULE_TYPE_LIST: usize = 121; -pub const RULE_TYPE_TYPE: usize = 122; -pub const RULE_PRIMITIVE_TYPE: usize = 123; -pub const RULE_TYPE_ARGUMENTS: usize = 124; -pub const RULE_SUPER_SUFFIX: usize = 125; -pub const RULE_EXPLICIT_GENERIC_INVOCATION_SUFFIX: usize = 126; -pub const RULE_ARGUMENTS: usize = 127; - -pub static METADATA: GrammarMetadata = GrammarMetadata::new( - "JavaParser", - &["compilationUnit", "modularCompulationUnit", "packageDeclaration", "importDeclaration", "typeDeclaration", "modifier", "classOrInterfaceModifier", "variableModifier", "classDeclaration", "typeParameters", "typeParameter", "typeBound", "enumDeclaration", "enumConstants", "enumConstant", "enumBodyDeclarations", "interfaceDeclaration", "classBody", "interfaceBody", "classBodyDeclaration", "memberDeclaration", "methodDeclaration", "methodBody", "typeTypeOrVoid", "genericMethodDeclaration", "genericConstructorDeclaration", "constructorDeclaration", "compactConstructorDeclaration", "fieldDeclaration", "interfaceBodyDeclaration", "interfaceMemberDeclaration", "constDeclaration", "constantDeclarator", "interfaceMethodDeclaration", "interfaceMethodModifier", "genericInterfaceMethodDeclaration", "interfaceCommonBodyDeclaration", "variableDeclarators", "variableDeclarator", "variableDeclaratorId", "variableInitializer", "arrayInitializer", "classType", "packageName", "typeArgument", "qualifiedNameList", "formalParameters", "receiverParameter", "formalParameterList", "formalParameter", "lambdaLVTIList", "lambdaLVTIParameter", "qualifiedName", "literal", "integerLiteral", "floatLiteral", "annotation", "annotationFieldValues", "annotationFieldValue", "annotationValue", "elementValue", "elementValueArrayInitializer", "annotationTypeDeclaration", "annotationTypeBody", "annotationTypeElementDeclaration", "annotationTypeElementRest", "annotationMethodOrConstantRest", "annotationMethodRest", "annotationConstantRest", "defaultValue", "moduleDeclaration", "moduleDirective", "requiresModifier", "recordDeclaration", "recordHeader", "recordComponentList", "recordComponent", "recordBody", "block", "blockStatement", "localVariableDeclaration", "identifier", "typeIdentifier", "localTypeDeclaration", "statement", "catchClause", "catchType", "finallyBlock", "resourceSpecification", "resources", "resource", "switchBlockStatementGroup", "switchLabel", "forControl", "forInit", "enhancedForControl", "expressionList", "methodCall", "expression", "pattern", "componentPatternList", "componentPattern", "lambdaExpression", "lambdaParameters", "lambdaBody", "primary", "switchExpression", "switchLabeledRule", "guard", "casePattern", "switchRuleOutcome", "classOrInterfaceType", "creator", "createdName", "innerCreator", "arrayCreatorRest", "classCreatorRest", "explicitGenericInvocation", "typeArgumentsOrDiamond", "nonWildcardTypeArgumentsOrDiamond", "nonWildcardTypeArguments", "typeList", "typeType", "primitiveType", "typeArguments", "superSuffix", "explicitGenericInvocationSuffix", "arguments"], - &[None, Some("\'abstract\'"), Some("\'assert\'"), Some("\'boolean\'"), Some("\'break\'"), Some("\'byte\'"), Some("\'case\'"), Some("\'catch\'"), Some("\'char\'"), Some("\'class\'"), Some("\'const\'"), Some("\'continue\'"), Some("\'default\'"), Some("\'do\'"), Some("\'double\'"), Some("\'else\'"), Some("\'enum\'"), Some("\'exports\'"), Some("\'extends\'"), Some("\'final\'"), Some("\'finally\'"), Some("\'float\'"), Some("\'for\'"), Some("\'goto\'"), Some("\'if\'"), Some("\'implements\'"), Some("\'import\'"), Some("\'instanceof\'"), Some("\'int\'"), Some("\'interface\'"), Some("\'long\'"), Some("\'module\'"), Some("\'native\'"), Some("\'new\'"), Some("\'non-sealed\'"), Some("\'open\'"), Some("\'opens\'"), Some("\'package\'"), Some("\'permits\'"), Some("\'private\'"), Some("\'protected\'"), Some("\'provides\'"), Some("\'public\'"), Some("\'record\'"), Some("\'requires\'"), Some("\'return\'"), Some("\'sealed\'"), Some("\'short\'"), Some("\'static\'"), Some("\'strictfp\'"), Some("\'super\'"), Some("\'switch\'"), Some("\'synchronized\'"), Some("\'this\'"), Some("\'throw\'"), Some("\'throws\'"), Some("\'to\'"), Some("\'transient\'"), Some("\'transitive\'"), Some("\'try\'"), Some("\'uses\'"), Some("\'var\'"), Some("\'void\'"), Some("\'volatile\'"), Some("\'when\'"), Some("\'while\'"), Some("\'with\'"), Some("\'yield\'"), None, None, None, None, None, None, None, None, None, None, Some("\'null\'"), Some("\'(\'"), Some("\')\'"), Some("\'{\'"), Some("\'}\'"), Some("\'[\'"), Some("\']\'"), Some("\';\'"), Some("\',\'"), Some("\'.\'"), Some("\'=\'"), Some("\'>\'"), Some("\'<\'"), Some("\'!\'"), Some("\'~\'"), Some("\'?\'"), Some("\':\'"), Some("\'==\'"), Some("\'<=\'"), Some("\'>=\'"), Some("\'!=\'"), Some("\'&&\'"), Some("\'||\'"), Some("\'++\'"), Some("\'--\'"), Some("\'+\'"), Some("\'-\'"), Some("\'*\'"), Some("\'/\'"), Some("\'&\'"), Some("\'|\'"), Some("\'^\'"), Some("\'%\'"), Some("\'+=\'"), Some("\'-=\'"), Some("\'*=\'"), Some("\'/=\'"), Some("\'&=\'"), Some("\'|=\'"), Some("\'^=\'"), Some("\'%=\'"), Some("\'<<=\'"), Some("\'>>=\'"), Some("\'>>>=\'"), Some("\'->\'"), Some("\'::\'"), Some("\'@\'"), Some("\'...\'"), None, None, None, None], - &[None, Some("ABSTRACT"), Some("ASSERT"), Some("BOOLEAN"), Some("BREAK"), Some("BYTE"), Some("CASE"), Some("CATCH"), Some("CHAR"), Some("CLASS"), Some("CONST"), Some("CONTINUE"), Some("DEFAULT"), Some("DO"), Some("DOUBLE"), Some("ELSE"), Some("ENUM"), Some("EXPORTS"), Some("EXTENDS"), Some("FINAL"), Some("FINALLY"), Some("FLOAT"), Some("FOR"), Some("GOTO"), Some("IF"), Some("IMPLEMENTS"), Some("IMPORT"), Some("INSTANCEOF"), Some("INT"), Some("INTERFACE"), Some("LONG"), Some("MODULE"), Some("NATIVE"), Some("NEW"), Some("NON_SEALED"), Some("OPEN"), Some("OPENS"), Some("PACKAGE"), Some("PERMITS"), Some("PRIVATE"), Some("PROTECTED"), Some("PROVIDES"), Some("PUBLIC"), Some("RECORD"), Some("REQUIRES"), Some("RETURN"), Some("SEALED"), Some("SHORT"), Some("STATIC"), Some("STRICTFP"), Some("SUPER"), Some("SWITCH"), Some("SYNCHRONIZED"), Some("THIS"), Some("THROW"), Some("THROWS"), Some("TO"), Some("TRANSIENT"), Some("TRANSITIVE"), Some("TRY"), Some("USES"), Some("VAR"), Some("VOID"), Some("VOLATILE"), Some("WHEN"), Some("WHILE"), Some("WITH"), Some("YIELD"), Some("DECIMAL_LITERAL"), Some("HEX_LITERAL"), Some("OCT_LITERAL"), Some("BINARY_LITERAL"), Some("FLOAT_LITERAL"), Some("HEX_FLOAT_LITERAL"), Some("BOOL_LITERAL"), Some("CHAR_LITERAL"), Some("STRING_LITERAL"), Some("TEXT_BLOCK"), Some("NULL_LITERAL"), Some("LPAREN"), Some("RPAREN"), Some("LBRACE"), Some("RBRACE"), Some("LBRACK"), Some("RBRACK"), Some("SEMI"), Some("COMMA"), Some("DOT"), Some("ASSIGN"), Some("GT"), Some("LT"), Some("BANG"), Some("TILDE"), Some("QUESTION"), Some("COLON"), Some("EQUAL"), Some("LE"), Some("GE"), Some("NOTEQUAL"), Some("AND"), Some("OR"), Some("INC"), Some("DEC"), Some("ADD"), Some("SUB"), Some("MUL"), Some("DIV"), Some("BITAND"), Some("BITOR"), Some("CARET"), Some("MOD"), Some("ADD_ASSIGN"), Some("SUB_ASSIGN"), Some("MUL_ASSIGN"), Some("DIV_ASSIGN"), Some("AND_ASSIGN"), Some("OR_ASSIGN"), Some("XOR_ASSIGN"), Some("MOD_ASSIGN"), Some("LSHIFT_ASSIGN"), Some("RSHIFT_ASSIGN"), Some("URSHIFT_ASSIGN"), Some("ARROW"), Some("COLONCOLON"), Some("AT"), Some("ELLIPSIS"), Some("WS"), Some("COMMENT"), Some("LINE_COMMENT"), Some("IDENTIFIER")], - &[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &[], - &[], - &[], -); - -pub fn metadata() -> &'static GrammarMetadata { - &METADATA -} - -pub fn rule_names() -> &'static [&'static str] { - METADATA.rule_names() -} - -fn parser_semantics() -> &'static antlr4_runtime::ParserSemantics { - static SEMANTICS_CELL: OnceLock = OnceLock::new(); - SEMANTICS_CELL.get_or_init(|| { - let mut ir = antlr4_runtime::semir::SemIr::new(); - let mut predicates = Vec::new(); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::Hook(antlr4_runtime::semir::HookId::new(0))); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 58, pred_index: 0, expr: __expr, failure_message: None }); - let __expr = ir.expr(antlr4_runtime::semir::PExpr::Hook(antlr4_runtime::semir::HookId::new(0))); - predicates.push(antlr4_runtime::ParserSemanticPredicate { rule_index: 75, pred_index: 1, expr: __expr, failure_message: None }); - - let actions = Vec::new(); - antlr4_runtime::ParserSemantics { ir, predicates, actions } - }) -} - -pub trait JavaParserHooks: Sized { - fn do_last_record_component(&mut self, ctx: &mut antlr4_runtime::ParserSemCtx<'_, L>) -> bool - where - L: TokenSource; - - fn is_not_identifier_assign(&mut self, ctx: &mut antlr4_runtime::ParserSemCtx<'_, L>) -> bool - where - L: TokenSource; - - /// Handles a committed parser action routed to the typed hook. Return - /// `true` when the action is handled so it satisfies a `hook`/`error` - /// unknown-semantic policy; the default no-op returns `false` (unhandled), - /// which fails loud under those policies. - fn custom_action(&mut self, _ctx: &mut antlr4_runtime::ParserSemCtx<'_, L>, _action: antlr4_runtime::ParserAction) -> bool - where - L: TokenSource, - { - false - } -} - -#[derive(Clone, Copy, Debug, Default)] -pub struct JavaParserTypedHooks(pub T); - -impl JavaParserTypedHooks { - pub const fn new(inner: T) -> Self { Self(inner) } -} - -impl antlr4_runtime::SemanticHooks for JavaParserTypedHooks -where - T: JavaParserHooks, -{ - fn sempred(&mut self, ctx: &mut antlr4_runtime::ParserSemCtx<'_, L>, rule_index: usize, pred_index: usize) -> Option - where - L: TokenSource, - { - match (rule_index, pred_index) { - (58, 0) => Some(self.0.is_not_identifier_assign(ctx)), - (75, 1) => Some(self.0.do_last_record_component(ctx)), - _ => None, - } - } - - fn action(&mut self, ctx: &mut antlr4_runtime::ParserSemCtx<'_, L>, action: antlr4_runtime::ParserAction) -> bool - where - L: TokenSource, - { - self.0.custom_action(ctx, action) - } -} - - -/// Marker carried by generated contexts whose required-child -/// invariants were checked after a syntax-clean parse, and grammar brand of -/// this module's validated tree and rule-node types. -/// -/// This marker stays module-local (unlike the runtime-owned support items) -/// so rustc can prove it never implements the runtime's -/// `__RecoveryContextState`, keeping the recovery-oriented and validated -/// accessor impls coherent — and so the runtime's branded validated types -/// stay nominally distinct per grammar. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct ValidatedTreeContext { - __private: (), -} - -/// A completed, syntax-clean parse tree whose generated child cardinalities -/// have been structurally validated. -/// -/// Alias of the runtime's grammar-agnostic `antlr4_runtime::ValidatedTree` -/// branded with this module's [`ValidatedTreeContext`] marker, so validated -/// trees of different grammars remain distinct types. -pub type JavaValidatedTree = antlr4_runtime::ValidatedTree; - -/// A rule node borrowed from a [`JavaValidatedTree`]. -/// -/// Alias of the runtime's `antlr4_runtime::ValidatedRuleNode` branded with -/// this module's [`ValidatedTreeContext`] marker. -pub type ValidatedRuleNode<'a> = antlr4_runtime::ValidatedRuleNode<'a, ValidatedTreeContext>; - -pub use antlr4_runtime::FromValidatedRuleNode; - -/// Failure to recognize or validate a strict generated parse. -/// -/// Alias of the grammar-agnostic `antlr4_runtime::ValidationError`; unlike -/// the branded tree types, the validation errors of every generated parser -/// are deliberately one shared type. -pub type JavaValidationError = antlr4_runtime::ValidationError; - -#[allow(dead_code)] -fn __context_kind(context: RuleNodeView<'_>) -> usize { - match context.rule_index() { - 0 => { - 0 - }, - 1 => { - 1 - }, - 2 => { - 2 - }, - 3 => { - 3 - }, - 4 => { - 4 - }, - 5 => { - 5 - }, - 6 => { - 6 - }, - 7 => { - 7 - }, - 8 => { - 8 - }, - 9 => { - 9 - }, - 10 => { - 10 - }, - 11 => { - 11 - }, - 12 => { - 12 - }, - 13 => { - 13 - }, - 14 => { - 14 - }, - 15 => { - 15 - }, - 16 => { - 16 - }, - 17 => { - 17 - }, - 18 => { - 18 - }, - 19 => { - 19 - }, - 20 => { - 20 - }, - 21 => { - 21 - }, - 22 => { - 22 - }, - 23 => { - 23 - }, - 24 => { - 24 - }, - 25 => { - 25 - }, - 26 => { - 26 - }, - 27 => { - 27 - }, - 28 => { - 28 - }, - 29 => { - 29 - }, - 30 => { - 30 - }, - 31 => { - 31 - }, - 32 => { - 32 - }, - 33 => { - 33 - }, - 34 => { - 34 - }, - 35 => { - 35 - }, - 36 => { - 36 - }, - 37 => { - 37 - }, - 38 => { - 38 - }, - 39 => { - 39 - }, - 40 => { - 40 - }, - 41 => { - 41 - }, - 42 => { - 42 - }, - 43 => { - 43 - }, - 44 => { - 44 - }, - 45 => { - 45 - }, - 46 => { - 46 - }, - 47 => { - 47 - }, - 48 => { - 48 - }, - 49 => { - 49 - }, - 50 => { - 50 - }, - 51 => { - 51 - }, - 52 => { - 52 - }, - 53 => { - 53 - }, - 54 => { - 54 - }, - 55 => { - 55 - }, - 56 => { - 56 - }, - 57 => { - 57 - }, - 58 => { - 58 - }, - 59 => { - 59 - }, - 60 => { - 60 - }, - 61 => { - 61 - }, - 62 => { - 62 - }, - 63 => { - 63 - }, - 64 => { - 64 - }, - 65 => { - 65 - }, - 66 => { - 66 - }, - 67 => { - 67 - }, - 68 => { - 68 - }, - 69 => { - 69 - }, - 70 => { - 70 - }, - 71 => { - 71 - }, - 72 => { - 72 - }, - 73 => { - 73 - }, - 74 => { - 74 - }, - 75 => { - 75 - }, - 76 => { - 76 - }, - 77 => { - 77 - }, - 78 => { - 78 - }, - 79 => { - 79 - }, - 80 => { - 80 - }, - 81 => { - 81 - }, - 82 => { - 82 - }, - 83 => { - 83 - }, - 84 => { - 84 - }, - 85 => { - 85 - }, - 86 => { - 86 - }, - 87 => { - 87 - }, - 88 => { - 88 - }, - 89 => { - 89 - }, - 90 => { - 90 - }, - 91 => { - 91 - }, - 92 => { - 92 - }, - 93 => { - 93 - }, - 94 => { - 94 - }, - 95 => { - 95 - }, - 96 => { - 96 - }, - 97 => { - 97 - }, - 98 => { - let operator = context.children().next().and_then(antlr4_runtime::Node::as_rule).is_some_and(|child| child.rule_index() == 98); - if operator { - match context.context_alt_number() { - 1 => 100, - 2 => 101, - 3 => 103, - 4 => 105, - 5 => 109, - 6 => 109, - 7 => 109, - 8 => 109, - 9 => 110, - 10 => 109, - 11 => 109, - 12 => 109, - 13 => 109, - 14 => 109, - 15 => 109, - 16 => 111, - 17 => 109, - _ => 98, - } - } else { - match context.context_alt_number() { - 1 => 99, - 2 => 102, - 3 => 103, - 4 => 103, - 5 => 104, - 6 => 106, - 7 => 107, - 8 => 108, - 9 => 112, - _ => 98, - } - } - }, - 99 => { - 113 - }, - 100 => { - 114 - }, - 101 => { - 115 - }, - 102 => { - 116 - }, - 103 => { - 117 - }, - 104 => { - 118 - }, - 105 => { - 119 - }, - 106 => { - 120 - }, - 107 => { - 121 - }, - 108 => { - 122 - }, - 109 => { - 123 - }, - 110 => { - 124 - }, - 111 => { - 125 - }, - 112 => { - 126 - }, - 113 => { - 127 - }, - 114 => { - 128 - }, - 115 => { - 129 - }, - 116 => { - 130 - }, - 117 => { - 131 - }, - 118 => { - 132 - }, - 119 => { - 133 - }, - 120 => { - 134 - }, - 121 => { - 135 - }, - 122 => { - 136 - }, - 123 => { - 137 - }, - 124 => { - 138 - }, - 125 => { - 139 - }, - 126 => { - 140 - }, - 127 => { - 141 - }, - _ => usize::MAX, - } -} - -#[allow(dead_code)] -fn __active_context_kind( - context: &antlr4_runtime::ParserRuleContext, - storage: &antlr4_runtime::ParseTreeStorage, - tokens: &antlr4_runtime::TokenStore, -) -> usize { - match context.rule_index() { - 0 => { - 0 - }, - 1 => { - 1 - }, - 2 => { - 2 - }, - 3 => { - 3 - }, - 4 => { - 4 - }, - 5 => { - 5 - }, - 6 => { - 6 - }, - 7 => { - 7 - }, - 8 => { - 8 - }, - 9 => { - 9 - }, - 10 => { - 10 - }, - 11 => { - 11 - }, - 12 => { - 12 - }, - 13 => { - 13 - }, - 14 => { - 14 - }, - 15 => { - 15 - }, - 16 => { - 16 - }, - 17 => { - 17 - }, - 18 => { - 18 - }, - 19 => { - 19 - }, - 20 => { - 20 - }, - 21 => { - 21 - }, - 22 => { - 22 - }, - 23 => { - 23 - }, - 24 => { - 24 - }, - 25 => { - 25 - }, - 26 => { - 26 - }, - 27 => { - 27 - }, - 28 => { - 28 - }, - 29 => { - 29 - }, - 30 => { - 30 - }, - 31 => { - 31 - }, - 32 => { - 32 - }, - 33 => { - 33 - }, - 34 => { - 34 - }, - 35 => { - 35 - }, - 36 => { - 36 - }, - 37 => { - 37 - }, - 38 => { - 38 - }, - 39 => { - 39 - }, - 40 => { - 40 - }, - 41 => { - 41 - }, - 42 => { - 42 - }, - 43 => { - 43 - }, - 44 => { - 44 - }, - 45 => { - 45 - }, - 46 => { - 46 - }, - 47 => { - 47 - }, - 48 => { - 48 - }, - 49 => { - 49 - }, - 50 => { - 50 - }, - 51 => { - 51 - }, - 52 => { - 52 - }, - 53 => { - 53 - }, - 54 => { - 54 - }, - 55 => { - 55 - }, - 56 => { - 56 - }, - 57 => { - 57 - }, - 58 => { - 58 - }, - 59 => { - 59 - }, - 60 => { - 60 - }, - 61 => { - 61 - }, - 62 => { - 62 - }, - 63 => { - 63 - }, - 64 => { - 64 - }, - 65 => { - 65 - }, - 66 => { - 66 - }, - 67 => { - 67 - }, - 68 => { - 68 - }, - 69 => { - 69 - }, - 70 => { - 70 - }, - 71 => { - 71 - }, - 72 => { - 72 - }, - 73 => { - 73 - }, - 74 => { - 74 - }, - 75 => { - 75 - }, - 76 => { - 76 - }, - 77 => { - 77 - }, - 78 => { - 78 - }, - 79 => { - 79 - }, - 80 => { - 80 - }, - 81 => { - 81 - }, - 82 => { - 82 - }, - 83 => { - 83 - }, - 84 => { - 84 - }, - 85 => { - 85 - }, - 86 => { - 86 - }, - 87 => { - 87 - }, - 88 => { - 88 - }, - 89 => { - 89 - }, - 90 => { - 90 - }, - 91 => { - 91 - }, - 92 => { - 92 - }, - 93 => { - 93 - }, - 94 => { - 94 - }, - 95 => { - 95 - }, - 96 => { - 96 - }, - 97 => { - 97 - }, - 98 => { - let operator = context.child_nodes(storage, tokens).next().and_then(antlr4_runtime::Node::as_rule).is_some_and(|child| child.rule_index() == 98); - if operator { - match context.context_alt_number() { - 1 => 100, - 2 => 101, - 3 => 103, - 4 => 105, - 5 => 109, - 6 => 109, - 7 => 109, - 8 => 109, - 9 => 110, - 10 => 109, - 11 => 109, - 12 => 109, - 13 => 109, - 14 => 109, - 15 => 109, - 16 => 111, - 17 => 109, - _ => 98, - } - } else { - match context.context_alt_number() { - 1 => 99, - 2 => 102, - 3 => 103, - 4 => 103, - 5 => 104, - 6 => 106, - 7 => 107, - 8 => 108, - 9 => 112, - _ => 98, - } - } - }, - 99 => { - 113 - }, - 100 => { - 114 - }, - 101 => { - 115 - }, - 102 => { - 116 - }, - 103 => { - 117 - }, - 104 => { - 118 - }, - 105 => { - 119 - }, - 106 => { - 120 - }, - 107 => { - 121 - }, - 108 => { - 122 - }, - 109 => { - 123 - }, - 110 => { - 124 - }, - 111 => { - 125 - }, - 112 => { - 126 - }, - 113 => { - 127 - }, - 114 => { - 128 - }, - 115 => { - 129 - }, - 116 => { - 130 - }, - 117 => { - 131 - }, - 118 => { - 132 - }, - 119 => { - 133 - }, - 120 => { - 134 - }, - 121 => { - 135 - }, - 122 => { - 136 - }, - 123 => { - 137 - }, - 124 => { - 138 - }, - 125 => { - 139 - }, - 126 => { - 140 - }, - 127 => { - 141 - }, - _ => usize::MAX, - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CompilationUnitContext { - rule_index: 0, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CompilationUnitContext { - rule modular_compulation_unit: optional(ModularCompulationUnitContext[1]), - rule package_declaration: optional(PackageDeclarationContext[2]), - rule import_declaration_children: many(ImportDeclarationContext[3]), - rule type_declaration_children: many(TypeDeclarationContext[4]), - token eof_token: required(-1, "EOF"), - token semi_tokens: many(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ModularCompulationUnitContext { - rule_index: 1, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ModularCompulationUnitContext { - rule import_declaration_children: many(ImportDeclarationContext[3]), - rule module_declaration: required(ModuleDeclarationContext[70], "moduleDeclaration"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PackageDeclarationContext { - rule_index: 2, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PackageDeclarationContext { - rule qualified_name: required(QualifiedNameContext[52], "qualifiedName"), - rule annotation_children: many(AnnotationContext[56]), - token package_token: required(37, "PACKAGE"), - token semi_token: required(85, "SEMI"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImportDeclarationContext { - rule_index: 3, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImportDeclarationContext { - rule qualified_name: required(QualifiedNameContext[52], "qualifiedName"), - token import_token: required(26, "IMPORT"), - token static_token: optional(48), - token semi_token: required(85, "SEMI"), - token dot_token: optional(87), - token mul_token: optional(105), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeDeclarationContext { - rule_index: 4, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeDeclarationContext { - rule class_or_interface_modifier_children: many(ClassOrInterfaceModifierContext[6]), - rule class_declaration: optional(ClassDeclarationContext[8]), - rule enum_declaration: optional(EnumDeclarationContext[12]), - rule interface_declaration: optional(InterfaceDeclarationContext[16]), - rule annotation_type_declaration: optional(AnnotationTypeDeclarationContext[62]), - rule record_declaration: optional(RecordDeclarationContext[73]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ModifierContext { - rule_index: 5, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ModifierContext { - rule class_or_interface_modifier: optional(ClassOrInterfaceModifierContext[6]), - token native_token: optional(32), - token synchronized_token: optional(52), - token transient_token: optional(57), - token volatile_token: optional(63), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassOrInterfaceModifierContext { - rule_index: 6, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassOrInterfaceModifierContext { - rule annotation: optional(AnnotationContext[56]), - token abstract_token: optional(1), - token final_token: optional(19), - token non_sealed_token: optional(34), - token private_token: optional(39), - token protected_token: optional(40), - token public_token: optional(42), - token sealed_token: optional(46), - token static_token: optional(48), - token strictfp_token: optional(49), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableModifierContext { - rule_index: 7, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableModifierContext { - rule annotation: optional(AnnotationContext[56]), - token final_token: optional(19), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassDeclarationContext { - rule_index: 8, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassDeclarationContext { - rule type_parameters: optional(TypeParametersContext[9]), - rule class_body: required(ClassBodyContext[17], "classBody"), - rule identifier: required(IdentifierContext[81], "identifier"), - rule type_list_children: many(TypeListContext[121]), - rule type_type: optional(TypeTypeContext[122]), - token class_token: required(9, "CLASS"), - token extends_token: optional(18), - token implements_token: optional(25), - token permits_token: optional(38), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParametersContext { - rule_index: 9, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParametersContext { - rule type_parameter_children: many(TypeParameterContext[10]), - token comma_tokens: many(86), - token gt_token: required(89, "GT"), - token lt_token: required(90, "LT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterContext { - rule_index: 10, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterContext { - rule type_bound: optional(TypeBoundContext[11]), - rule annotation_children: many(AnnotationContext[56]), - rule identifier: required(IdentifierContext[81], "identifier"), - token extends_token: optional(18), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeBoundContext { - rule_index: 11, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeBoundContext { - rule type_type_children: many(TypeTypeContext[122]), - token bitand_tokens: many(107), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumDeclarationContext { - rule_index: 12, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumDeclarationContext { - rule enum_constants: optional(EnumConstantsContext[13]), - rule enum_body_declarations: optional(EnumBodyDeclarationsContext[15]), - rule identifier: required(IdentifierContext[81], "identifier"), - rule type_list: optional(TypeListContext[121]), - token enum_token: required(16, "ENUM"), - token implements_token: optional(25), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - token comma_token: optional(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumConstantsContext { - rule_index: 13, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumConstantsContext { - rule enum_constant_children: many(EnumConstantContext[14]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumConstantContext { - rule_index: 14, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumConstantContext { - rule class_body: optional(ClassBodyContext[17]), - rule annotation_children: many(AnnotationContext[56]), - rule identifier: required(IdentifierContext[81], "identifier"), - rule arguments: optional(ArgumentsContext[127]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumBodyDeclarationsContext { - rule_index: 15, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumBodyDeclarationsContext { - rule class_body_declaration_children: many(ClassBodyDeclarationContext[19]), - token semi_token: required(85, "SEMI"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceDeclarationContext { - rule_index: 16, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceDeclarationContext { - rule type_parameters: optional(TypeParametersContext[9]), - rule interface_body: required(InterfaceBodyContext[18], "interfaceBody"), - rule identifier: required(IdentifierContext[81], "identifier"), - rule type_list_children: many(TypeListContext[121]), - token extends_token: optional(18), - token interface_token: required(29, "INTERFACE"), - token permits_token: optional(38), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassBodyContext { - rule_index: 17, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassBodyContext { - rule class_body_declaration_children: many(ClassBodyDeclarationContext[19]), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceBodyContext { - rule_index: 18, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceBodyContext { - rule interface_body_declaration_children: many(InterfaceBodyDeclarationContext[29]), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassBodyDeclarationContext { - rule_index: 19, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassBodyDeclarationContext { - rule modifier_children: many(ModifierContext[5]), - rule member_declaration: optional(MemberDeclarationContext[20]), - rule block: optional(BlockContext[78]), - token static_token: optional(48), - token semi_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MemberDeclarationContext { - rule_index: 20, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MemberDeclarationContext { - rule class_declaration: optional(ClassDeclarationContext[8]), - rule enum_declaration: optional(EnumDeclarationContext[12]), - rule interface_declaration: optional(InterfaceDeclarationContext[16]), - rule method_declaration: optional(MethodDeclarationContext[21]), - rule generic_method_declaration: optional(GenericMethodDeclarationContext[24]), - rule generic_constructor_declaration: optional(GenericConstructorDeclarationContext[25]), - rule constructor_declaration: optional(ConstructorDeclarationContext[26]), - rule field_declaration: optional(FieldDeclarationContext[28]), - rule annotation_type_declaration: optional(AnnotationTypeDeclarationContext[62]), - rule record_declaration: optional(RecordDeclarationContext[73]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MethodDeclarationContext { - rule_index: 21, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MethodDeclarationContext { - rule method_body: required(MethodBodyContext[22], "methodBody"), - rule type_type_or_void: required(TypeTypeOrVoidContext[23], "typeTypeOrVoid"), - rule qualified_name_list: optional(QualifiedNameListContext[45]), - rule formal_parameters: required(FormalParametersContext[46], "formalParameters"), - rule identifier: required(IdentifierContext[81], "identifier"), - token throws_token: optional(55), - token lbrack_tokens: many(83), - token rbrack_tokens: many(84), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MethodBodyContext { - rule_index: 22, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MethodBodyContext { - rule block: optional(BlockContext[78]), - token semi_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeTypeOrVoidContext { - rule_index: 23, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeTypeOrVoidContext { - rule type_type: optional(TypeTypeContext[122]), - token void_token: optional(62), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GenericMethodDeclarationContext { - rule_index: 24, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GenericMethodDeclarationContext { - rule type_parameters: required(TypeParametersContext[9], "typeParameters"), - rule method_declaration: required(MethodDeclarationContext[21], "methodDeclaration"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GenericConstructorDeclarationContext { - rule_index: 25, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GenericConstructorDeclarationContext { - rule type_parameters: required(TypeParametersContext[9], "typeParameters"), - rule constructor_declaration: required(ConstructorDeclarationContext[26], "constructorDeclaration"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstructorDeclarationContext { - rule_index: 26, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstructorDeclarationContext { - rule qualified_name_list: optional(QualifiedNameListContext[45]), - rule formal_parameters: required(FormalParametersContext[46], "formalParameters"), - rule block: required(BlockContext[78], "block"), - rule identifier: required(IdentifierContext[81], "identifier"), - token throws_token: optional(55), - label_rule constructor_body: required(nth(0), BlockContext[78], "constructorBody"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CompactConstructorDeclarationContext { - rule_index: 27, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CompactConstructorDeclarationContext { - rule modifier_children: many(ModifierContext[5]), - rule block: required(BlockContext[78], "block"), - rule identifier: required(IdentifierContext[81], "identifier"), - label_rule constructor_body: required(nth(0), BlockContext[78], "constructorBody"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FieldDeclarationContext { - rule_index: 28, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FieldDeclarationContext { - rule variable_declarators: required(VariableDeclaratorsContext[37], "variableDeclarators"), - rule type_type: required(TypeTypeContext[122], "typeType"), - token semi_token: required(85, "SEMI"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceBodyDeclarationContext { - rule_index: 29, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceBodyDeclarationContext { - rule modifier_children: many(ModifierContext[5]), - rule interface_member_declaration: optional(InterfaceMemberDeclarationContext[30]), - token semi_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceMemberDeclarationContext { - rule_index: 30, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceMemberDeclarationContext { - rule class_declaration: optional(ClassDeclarationContext[8]), - rule enum_declaration: optional(EnumDeclarationContext[12]), - rule interface_declaration: optional(InterfaceDeclarationContext[16]), - rule const_declaration: optional(ConstDeclarationContext[31]), - rule interface_method_declaration: optional(InterfaceMethodDeclarationContext[33]), - rule generic_interface_method_declaration: optional(GenericInterfaceMethodDeclarationContext[35]), - rule annotation_type_declaration: optional(AnnotationTypeDeclarationContext[62]), - rule record_declaration: optional(RecordDeclarationContext[73]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstDeclarationContext { - rule_index: 31, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstDeclarationContext { - rule constant_declarator_children: many(ConstantDeclaratorContext[32]), - rule type_type: required(TypeTypeContext[122], "typeType"), - token semi_token: required(85, "SEMI"), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstantDeclaratorContext { - rule_index: 32, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstantDeclaratorContext { - rule variable_initializer: required(VariableInitializerContext[40], "variableInitializer"), - rule identifier: required(IdentifierContext[81], "identifier"), - token lbrack_tokens: many(83), - token rbrack_tokens: many(84), - token assign_token: required(88, "ASSIGN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceMethodDeclarationContext { - rule_index: 33, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceMethodDeclarationContext { - rule interface_method_modifier_children: many(InterfaceMethodModifierContext[34]), - rule interface_common_body_declaration: required(InterfaceCommonBodyDeclarationContext[36], "interfaceCommonBodyDeclaration"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceMethodModifierContext { - rule_index: 34, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceMethodModifierContext { - rule annotation: optional(AnnotationContext[56]), - token abstract_token: optional(1), - token default_token: optional(12), - token public_token: optional(42), - token static_token: optional(48), - token strictfp_token: optional(49), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GenericInterfaceMethodDeclarationContext { - rule_index: 35, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GenericInterfaceMethodDeclarationContext { - rule type_parameters: required(TypeParametersContext[9], "typeParameters"), - rule interface_method_modifier_children: many(InterfaceMethodModifierContext[34]), - rule interface_common_body_declaration: required(InterfaceCommonBodyDeclarationContext[36], "interfaceCommonBodyDeclaration"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InterfaceCommonBodyDeclarationContext { - rule_index: 36, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InterfaceCommonBodyDeclarationContext { - rule method_body: required(MethodBodyContext[22], "methodBody"), - rule type_type_or_void: required(TypeTypeOrVoidContext[23], "typeTypeOrVoid"), - rule qualified_name_list: optional(QualifiedNameListContext[45]), - rule formal_parameters: required(FormalParametersContext[46], "formalParameters"), - rule annotation_children: many(AnnotationContext[56]), - rule identifier: required(IdentifierContext[81], "identifier"), - token throws_token: optional(55), - token lbrack_tokens: many(83), - token rbrack_tokens: many(84), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableDeclaratorsContext { - rule_index: 37, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableDeclaratorsContext { - rule variable_declarator_children: many(VariableDeclaratorContext[38]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableDeclaratorContext { - rule_index: 38, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableDeclaratorContext { - rule variable_declarator_id: required(VariableDeclaratorIdContext[39], "variableDeclaratorId"), - rule variable_initializer: optional(VariableInitializerContext[40]), - token assign_token: optional(88), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableDeclaratorIdContext { - rule_index: 39, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableDeclaratorIdContext { - rule identifier: required(IdentifierContext[81], "identifier"), - token lbrack_tokens: many(83), - token rbrack_tokens: many(84), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableInitializerContext { - rule_index: 40, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableInitializerContext { - rule array_initializer: optional(ArrayInitializerContext[41]), - rule expression: optional(ExpressionContext[98]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArrayInitializerContext { - rule_index: 41, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArrayInitializerContext { - rule variable_initializer_children: many(VariableInitializerContext[40]), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassTypeContext { - rule_index: 42, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassTypeContext { - rule package_name_children: many(PackageNameContext[43]), - rule annotation_children: many(AnnotationContext[56]), - rule type_identifier_children: many(TypeIdentifierContext[82]), - rule type_arguments_children: many(TypeArgumentsContext[124]), - token dot_tokens: many(87), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PackageNameContext { - rule_index: 43, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PackageNameContext { - rule identifier_children: many(IdentifierContext[81]), - token dot_tokens: many(87), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeArgumentContext { - rule_index: 44, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeArgumentContext { - rule annotation_children: many(AnnotationContext[56]), - rule type_type: optional(TypeTypeContext[122]), - token extends_token: optional(18), - token super__token: optional(50), - token question_token: optional(93), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct QualifiedNameListContext { - rule_index: 45, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - QualifiedNameListContext { - rule qualified_name_children: many(QualifiedNameContext[52]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FormalParametersContext { - rule_index: 46, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FormalParametersContext { - rule receiver_parameter: optional(ReceiverParameterContext[47]), - rule formal_parameter_list_children: many(FormalParameterListContext[48]), - rule formal_parameter: optional(FormalParameterContext[49]), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ReceiverParameterContext { - rule_index: 47, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ReceiverParameterContext { - rule identifier_children: many(IdentifierContext[81]), - rule type_type: required(TypeTypeContext[122], "typeType"), - token this_token: required(53, "THIS"), - token dot_tokens: many(87), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FormalParameterListContext { - rule_index: 48, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FormalParameterListContext { - rule formal_parameter_children: many(FormalParameterContext[49]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FormalParameterContext { - rule_index: 49, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FormalParameterContext { - rule variable_modifier_children: many(VariableModifierContext[7]), - rule variable_declarator_id: required(VariableDeclaratorIdContext[39], "variableDeclaratorId"), - rule annotation_children: many(AnnotationContext[56]), - rule type_type: required(TypeTypeContext[122], "typeType"), - token ellipsis_token: optional(125), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaLvtiListContext { - rule_index: 50, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaLvtiListContext { - rule lambda_lvti_parameter_children: many(LambdaLvtiParameterContext[51]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaLvtiParameterContext { - rule_index: 51, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaLvtiParameterContext { - rule variable_modifier_children: many(VariableModifierContext[7]), - rule identifier: required(IdentifierContext[81], "identifier"), - token var_token: required(61, "VAR"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct QualifiedNameContext { - rule_index: 52, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - QualifiedNameContext { - rule identifier_children: many(IdentifierContext[81]), - token dot_tokens: many(87), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LiteralContext { - rule_index: 53, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LiteralContext { - rule integer_literal: optional(IntegerLiteralContext[54]), - rule float_literal: optional(FloatLiteralContext[55]), - token bool_literal_token: optional(74), - token char_literal_token: optional(75), - token string_literal_token: optional(76), - token text_block_token: optional(77), - token null_literal_token: optional(78), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IntegerLiteralContext { - rule_index: 54, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IntegerLiteralContext { - token decimal_literal_token: optional(68), - token hex_literal_token: optional(69), - token oct_literal_token: optional(70), - token binary_literal_token: optional(71), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FloatLiteralContext { - rule_index: 55, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FloatLiteralContext { - token float_literal_token: optional(72), - token hex_float_literal_token: optional(73), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationContext { - rule_index: 56, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationContext { - rule qualified_name: required(QualifiedNameContext[52], "qualifiedName"), - rule annotation_field_values: optional(AnnotationFieldValuesContext[57]), - token at_token: required(124, "AT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationFieldValuesContext { - rule_index: 57, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationFieldValuesContext { - rule annotation_field_value_children: many(AnnotationFieldValueContext[58]), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationFieldValueContext { - rule_index: 58, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationFieldValueContext { - rule annotation_value: required(AnnotationValueContext[59], "annotationValue"), - rule identifier: optional(IdentifierContext[81]), - token assign_token: optional(88), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationValueContext { - rule_index: 59, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationValueContext { - rule annotation: optional(AnnotationContext[56]), - rule annotation_value_children: many(AnnotationValueContext[59]), - rule expression: optional(ExpressionContext[98]), - token lbrace_token: optional(81), - token rbrace_token: optional(82), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ElementValueContext { - rule_index: 60, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ElementValueContext { - rule annotation: optional(AnnotationContext[56]), - rule element_value_array_initializer: optional(ElementValueArrayInitializerContext[61]), - rule expression: optional(ExpressionContext[98]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ElementValueArrayInitializerContext { - rule_index: 61, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ElementValueArrayInitializerContext { - rule element_value_children: many(ElementValueContext[60]), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationTypeDeclarationContext { - rule_index: 62, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationTypeDeclarationContext { - rule annotation_type_body: required(AnnotationTypeBodyContext[63], "annotationTypeBody"), - rule identifier: required(IdentifierContext[81], "identifier"), - token interface_token: required(29, "INTERFACE"), - token at_token: required(124, "AT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationTypeBodyContext { - rule_index: 63, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationTypeBodyContext { - rule annotation_type_element_declaration_children: many(AnnotationTypeElementDeclarationContext[64]), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationTypeElementDeclarationContext { - rule_index: 64, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationTypeElementDeclarationContext { - rule modifier_children: many(ModifierContext[5]), - rule annotation_type_element_rest: optional(AnnotationTypeElementRestContext[65]), - token semi_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationTypeElementRestContext { - rule_index: 65, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationTypeElementRestContext { - rule class_declaration: optional(ClassDeclarationContext[8]), - rule enum_declaration: optional(EnumDeclarationContext[12]), - rule interface_declaration: optional(InterfaceDeclarationContext[16]), - rule annotation_type_declaration: optional(AnnotationTypeDeclarationContext[62]), - rule annotation_method_or_constant_rest: optional(AnnotationMethodOrConstantRestContext[66]), - rule record_declaration: optional(RecordDeclarationContext[73]), - rule type_type: optional(TypeTypeContext[122]), - token semi_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationMethodOrConstantRestContext { - rule_index: 66, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationMethodOrConstantRestContext { - rule annotation_method_rest: optional(AnnotationMethodRestContext[67]), - rule annotation_constant_rest: optional(AnnotationConstantRestContext[68]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationMethodRestContext { - rule_index: 67, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationMethodRestContext { - rule default_value: optional(DefaultValueContext[69]), - rule identifier: required(IdentifierContext[81], "identifier"), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationConstantRestContext { - rule_index: 68, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationConstantRestContext { - rule variable_declarators: required(VariableDeclaratorsContext[37], "variableDeclarators"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DefaultValueContext { - rule_index: 69, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DefaultValueContext { - rule element_value: required(ElementValueContext[60], "elementValue"), - token default_token: required(12, "DEFAULT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ModuleDeclarationContext { - rule_index: 70, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ModuleDeclarationContext { - rule qualified_name: required(QualifiedNameContext[52], "qualifiedName"), - rule annotation_children: many(AnnotationContext[56]), - rule module_directive_children: many(ModuleDirectiveContext[71]), - token module_token: required(31, "MODULE"), - token open_token: optional(35), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ModuleDirectiveContext { - rule_index: 71, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ModuleDirectiveContext { - rule qualified_name_children: many(QualifiedNameContext[52]), - rule requires_modifier_children: many(RequiresModifierContext[72]), - token exports_token: optional(17), - token opens_token: optional(36), - token provides_token: optional(41), - token requires_token: optional(44), - token to_token: optional(56), - token uses_token: optional(60), - token with_token: optional(66), - token semi_token: required(85, "SEMI"), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RequiresModifierContext { - rule_index: 72, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RequiresModifierContext { - token static_token: optional(48), - token transitive_token: optional(58), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecordDeclarationContext { - rule_index: 73, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecordDeclarationContext { - rule type_parameters: optional(TypeParametersContext[9]), - rule record_header: required(RecordHeaderContext[74], "recordHeader"), - rule record_body: required(RecordBodyContext[77], "recordBody"), - rule identifier: required(IdentifierContext[81], "identifier"), - rule type_list: optional(TypeListContext[121]), - token implements_token: optional(25), - token record_token: required(43, "RECORD"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecordHeaderContext { - rule_index: 74, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecordHeaderContext { - rule record_component_list: optional(RecordComponentListContext[75]), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecordComponentListContext { - rule_index: 75, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecordComponentListContext { - rule record_component_children: many(RecordComponentContext[76]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecordComponentContext { - rule_index: 76, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecordComponentContext { - rule annotation_children: many(AnnotationContext[56]), - rule identifier: required(IdentifierContext[81], "identifier"), - rule type_type: required(TypeTypeContext[122], "typeType"), - token ellipsis_token: optional(125), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RecordBodyContext { - rule_index: 77, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RecordBodyContext { - rule class_body_declaration_children: many(ClassBodyDeclarationContext[19]), - rule compact_constructor_declaration_children: many(CompactConstructorDeclarationContext[27]), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BlockContext { - rule_index: 78, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BlockContext { - rule block_statement_children: many(BlockStatementContext[79]), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BlockStatementContext { - rule_index: 79, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BlockStatementContext { - rule local_variable_declaration: optional(LocalVariableDeclarationContext[80]), - rule local_type_declaration: optional(LocalTypeDeclarationContext[83]), - rule statement: optional(StatementContext[84]), - token semi_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LocalVariableDeclarationContext { - rule_index: 80, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LocalVariableDeclarationContext { - rule variable_modifier_children: many(VariableModifierContext[7]), - rule variable_declarators: optional(VariableDeclaratorsContext[37]), - rule identifier: optional(IdentifierContext[81]), - rule expression: optional(ExpressionContext[98]), - rule type_type: optional(TypeTypeContext[122]), - token var_token: optional(61), - token assign_token: optional(88), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IdentifierContext { - rule_index: 81, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IdentifierContext { - token exports_token: optional(17), - token module_token: optional(31), - token open_token: optional(35), - token opens_token: optional(36), - token permits_token: optional(38), - token provides_token: optional(41), - token record_token: optional(43), - token requires_token: optional(44), - token sealed_token: optional(46), - token to_token: optional(56), - token transitive_token: optional(58), - token uses_token: optional(60), - token var_token: optional(61), - token when_token: optional(64), - token with_token: optional(66), - token yield_token: optional(67), - token identifier_token: optional(129), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeIdentifierContext { - rule_index: 82, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeIdentifierContext { - token exports_token: optional(17), - token module_token: optional(31), - token open_token: optional(35), - token opens_token: optional(36), - token provides_token: optional(41), - token requires_token: optional(44), - token sealed_token: optional(46), - token to_token: optional(56), - token transitive_token: optional(58), - token uses_token: optional(60), - token with_token: optional(66), - token identifier_token: optional(129), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LocalTypeDeclarationContext { - rule_index: 83, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LocalTypeDeclarationContext { - rule class_or_interface_modifier_children: many(ClassOrInterfaceModifierContext[6]), - rule class_declaration: optional(ClassDeclarationContext[8]), - rule enum_declaration: optional(EnumDeclarationContext[12]), - rule interface_declaration: optional(InterfaceDeclarationContext[16]), - rule record_declaration: optional(RecordDeclarationContext[73]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StatementContext { - rule_index: 84, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StatementContext { - rule block: optional(BlockContext[78]), - rule identifier: optional(IdentifierContext[81]), - rule statement_children: many(StatementContext[84]), - rule catch_clause_children: many(CatchClauseContext[85]), - rule finally_block: optional(FinallyBlockContext[87]), - rule resource_specification: optional(ResourceSpecificationContext[88]), - rule switch_block_statement_group_children: many(SwitchBlockStatementGroupContext[91]), - rule switch_label_children: many(SwitchLabelContext[92]), - rule for_control: optional(ForControlContext[93]), - rule expression_children: many(ExpressionContext[98]), - rule switch_expression: optional(SwitchExpressionContext[106]), - token assert_token: optional(2), - token break_token: optional(4), - token continue_token: optional(11), - token do_token: optional(13), - token else_token: optional(15), - token for_token: optional(22), - token if_token: optional(24), - token return_token: optional(45), - token switch_token: optional(51), - token synchronized_token: optional(52), - token throw_token: optional(54), - token try_token: optional(59), - token while_token: optional(65), - token yield_token: optional(67), - token lparen_token: optional(79), - token rparen_token: optional(80), - token lbrace_token: optional(81), - token rbrace_token: optional(82), - token semi_token: optional(85), - token colon_token: optional(94), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CatchClauseContext { - rule_index: 85, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CatchClauseContext { - rule variable_modifier_children: many(VariableModifierContext[7]), - rule block: required(BlockContext[78], "block"), - rule identifier: required(IdentifierContext[81], "identifier"), - rule catch_type: required(CatchTypeContext[86], "catchType"), - token catch_token: required(7, "CATCH"), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CatchTypeContext { - rule_index: 86, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CatchTypeContext { - rule qualified_name_children: many(QualifiedNameContext[52]), - token bitor_tokens: many(108), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FinallyBlockContext { - rule_index: 87, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FinallyBlockContext { - rule block: required(BlockContext[78], "block"), - token finally_token: required(20, "FINALLY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ResourceSpecificationContext { - rule_index: 88, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ResourceSpecificationContext { - rule resources: required(ResourcesContext[89], "resources"), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - token semi_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ResourcesContext { - rule_index: 89, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ResourcesContext { - rule resource_children: many(ResourceContext[90]), - token semi_tokens: many(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ResourceContext { - rule_index: 90, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ResourceContext { - rule variable_modifier_children: many(VariableModifierContext[7]), - rule variable_declarator_id: optional(VariableDeclaratorIdContext[39]), - rule qualified_name: optional(QualifiedNameContext[52]), - rule identifier: optional(IdentifierContext[81]), - rule expression: optional(ExpressionContext[98]), - rule class_or_interface_type: optional(ClassOrInterfaceTypeContext[111]), - token var_token: optional(61), - token assign_token: optional(88), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchBlockStatementGroupContext { - rule_index: 91, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchBlockStatementGroupContext { - rule block_statement_children: many(BlockStatementContext[79]), - rule switch_label_children: many(SwitchLabelContext[92]), - token colon_tokens: many(94), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchLabelContext { - rule_index: 92, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchLabelContext { - rule identifier: optional(IdentifierContext[81]), - rule expression: optional(ExpressionContext[98]), - rule type_type: optional(TypeTypeContext[122]), - token case_token: optional(6), - token default_token: optional(12), - token identifier_token: optional(129), - label_rule constant_expression: optional(nth(0), ExpressionContext[98]), - label_token enum_constant_name: optional(nth(0), [129]), - label_rule var_name: optional(nth(0), IdentifierContext[81]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ForControlContext { - rule_index: 93, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ForControlContext { - rule for_init: optional(ForInitContext[94]), - rule enhanced_for_control: optional(EnhancedForControlContext[95]), - rule expression_list: optional(ExpressionListContext[96]), - rule expression: optional(ExpressionContext[98]), - token semi_tokens: many(85), - label_rule for_update: optional(nth(0), ExpressionListContext[96]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ForInitContext { - rule_index: 94, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ForInitContext { - rule local_variable_declaration: optional(LocalVariableDeclarationContext[80]), - rule expression_list: optional(ExpressionListContext[96]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnhancedForControlContext { - rule_index: 95, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnhancedForControlContext { - rule variable_modifier_children: many(VariableModifierContext[7]), - rule variable_declarator_id: required(VariableDeclaratorIdContext[39], "variableDeclaratorId"), - rule expression: required(ExpressionContext[98], "expression"), - rule type_type: optional(TypeTypeContext[122]), - token var_token: optional(61), - token colon_token: required(94, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionListContext { - rule_index: 96, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionListContext { - rule expression_children: many(ExpressionContext[98]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MethodCallContext { - rule_index: 97, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MethodCallContext { - rule identifier: optional(IdentifierContext[81]), - rule arguments: required(ArgumentsContext[127], "arguments"), - token super__token: optional(50), - token this_token: optional(53), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionContext { - rule_index: 98, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionContext { - rule class_type: optional(ClassTypeContext[42]), - rule annotation_children: many(AnnotationContext[56]), - rule identifier: optional(IdentifierContext[81]), - rule method_call: optional(MethodCallContext[97]), - rule expression_children: many(ExpressionContext[98]), - rule pattern: optional(PatternContext[99]), - rule lambda_expression: optional(LambdaExpressionContext[102]), - rule primary: optional(PrimaryContext[105]), - rule switch_expression: optional(SwitchExpressionContext[106]), - rule creator: optional(CreatorContext[112]), - rule inner_creator: optional(InnerCreatorContext[114]), - rule explicit_generic_invocation: optional(ExplicitGenericInvocationContext[117]), - rule non_wildcard_type_arguments: optional(NonWildcardTypeArgumentsContext[120]), - rule type_type_children: many(TypeTypeContext[122]), - rule type_arguments: optional(TypeArgumentsContext[124]), - rule super_suffix: optional(SuperSuffixContext[125]), - token instanceof_token: optional(27), - token new_token: optional(33), - token super__token: optional(50), - token this_token: optional(53), - token lparen_token: optional(79), - token rparen_token: optional(80), - token lbrack_token: optional(83), - token rbrack_token: optional(84), - token dot_token: optional(87), - token assign_token: optional(88), - token gt_tokens: many(89), - token lt_tokens: many(90), - token bang_token: optional(91), - token tilde_token: optional(92), - token question_token: optional(93), - token colon_token: optional(94), - token equal_token: optional(95), - token le_token: optional(96), - token ge_token: optional(97), - token notequal_token: optional(98), - token and_token: optional(99), - token or_token: optional(100), - token inc_token: optional(101), - token dec_token: optional(102), - token add_token: optional(103), - token sub_token: optional(104), - token mul_token: optional(105), - token div_token: optional(106), - token bitand_tokens: many(107), - token bitor_token: optional(108), - token caret_token: optional(109), - token mod_token: optional(110), - token add_assign_token: optional(111), - token sub_assign_token: optional(112), - token mul_assign_token: optional(113), - token div_assign_token: optional(114), - token and_assign_token: optional(115), - token or_assign_token: optional(116), - token xor_assign_token: optional(117), - token mod_assign_token: optional(118), - token lshift_assign_token: optional(119), - token rshift_assign_token: optional(120), - token urshift_assign_token: optional(121), - token coloncolon_token: optional(123), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrimaryExpressionLabelContext { - rule_index: 98, - context_kind: exact(99), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrimaryExpressionLabelContext { - rule primary: required(PrimaryContext[105], "primary"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SquareBracketExpressionLabelContext { - rule_index: 98, - context_kind: exact(100), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SquareBracketExpressionLabelContext { - rule expression_children: many(ExpressionContext[98]), - token lbrack_token: required(83, "LBRACK"), - token rbrack_token: required(84, "RBRACK"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MemberReferenceExpressionLabelContext { - rule_index: 98, - context_kind: exact(101), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MemberReferenceExpressionLabelContext { - rule identifier: optional(IdentifierContext[81]), - rule method_call: optional(MethodCallContext[97]), - rule expression: required(ExpressionContext[98], "expression"), - rule inner_creator: optional(InnerCreatorContext[114]), - rule explicit_generic_invocation: optional(ExplicitGenericInvocationContext[117]), - rule non_wildcard_type_arguments: optional(NonWildcardTypeArgumentsContext[120]), - rule super_suffix: optional(SuperSuffixContext[125]), - token new_token: optional(33), - token super__token: optional(50), - token this_token: optional(53), - token dot_token: required(87, "DOT"), - label_token bop: required(nth(0), [87], "bop"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MethodCallExpressionLabelContext { - rule_index: 98, - context_kind: exact(102), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MethodCallExpressionLabelContext { - rule method_call: required(MethodCallContext[97], "methodCall"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MethodReferenceExpressionLabelContext { - rule_index: 98, - context_kind: exact(103), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MethodReferenceExpressionLabelContext { - rule class_type: optional(ClassTypeContext[42]), - rule identifier: optional(IdentifierContext[81]), - rule expression: optional(ExpressionContext[98]), - rule type_type: optional(TypeTypeContext[122]), - rule type_arguments: optional(TypeArgumentsContext[124]), - token new_token: optional(33), - token coloncolon_token: required(123, "COLONCOLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionSwitchLabelContext { - rule_index: 98, - context_kind: exact(104), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionSwitchLabelContext { - rule switch_expression: required(SwitchExpressionContext[106], "switchExpression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PostIncrementDecrementOperatorExpressionLabelContext { - rule_index: 98, - context_kind: exact(105), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PostIncrementDecrementOperatorExpressionLabelContext { - rule expression: required(ExpressionContext[98], "expression"), - token inc_token: optional(101), - token dec_token: optional(102), - label_token postfix: required(nth(0), [101, 102], "postfix"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnaryOperatorExpressionLabelContext { - rule_index: 98, - context_kind: exact(106), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnaryOperatorExpressionLabelContext { - rule expression: required(ExpressionContext[98], "expression"), - token bang_token: optional(91), - token tilde_token: optional(92), - token inc_token: optional(101), - token dec_token: optional(102), - token add_token: optional(103), - token sub_token: optional(104), - label_token prefix: required(nth(0), [91, 92, 101, 102, 103, 104], "prefix"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CastExpressionLabelContext { - rule_index: 98, - context_kind: exact(107), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CastExpressionLabelContext { - rule annotation_children: many(AnnotationContext[56]), - rule expression: required(ExpressionContext[98], "expression"), - rule type_type_children: many(TypeTypeContext[122]), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - token bitand_tokens: many(107), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ObjectCreationExpressionLabelContext { - rule_index: 98, - context_kind: exact(108), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ObjectCreationExpressionLabelContext { - rule creator: required(CreatorContext[112], "creator"), - token new_token: required(33, "NEW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BinaryOperatorExpressionLabelContext { - rule_index: 98, - context_kind: exact(109), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BinaryOperatorExpressionLabelContext { - rule expression_children: many(ExpressionContext[98]), - token assign_token: optional(88), - token gt_tokens: many(89), - token lt_tokens: many(90), - token equal_token: optional(95), - token le_token: optional(96), - token ge_token: optional(97), - token notequal_token: optional(98), - token and_token: optional(99), - token or_token: optional(100), - token add_token: optional(103), - token sub_token: optional(104), - token mul_token: optional(105), - token div_token: optional(106), - token bitand_token: optional(107), - token bitor_token: optional(108), - token caret_token: optional(109), - token mod_token: optional(110), - token add_assign_token: optional(111), - token sub_assign_token: optional(112), - token mul_assign_token: optional(113), - token div_assign_token: optional(114), - token and_assign_token: optional(115), - token or_assign_token: optional(116), - token xor_assign_token: optional(117), - token mod_assign_token: optional(118), - token lshift_assign_token: optional(119), - token rshift_assign_token: optional(120), - token urshift_assign_token: optional(121), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InstanceOfOperatorExpressionLabelContext { - rule_index: 98, - context_kind: exact(110), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InstanceOfOperatorExpressionLabelContext { - rule expression: required(ExpressionContext[98], "expression"), - rule pattern: optional(PatternContext[99]), - rule type_type: optional(TypeTypeContext[122]), - token instanceof_token: required(27, "INSTANCEOF"), - label_token bop: required(nth(0), [27], "bop"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TernaryExpressionLabelContext { - rule_index: 98, - context_kind: exact(111), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TernaryExpressionLabelContext { - rule expression_children: many(ExpressionContext[98]), - token question_token: required(93, "QUESTION"), - token colon_token: required(94, "COLON"), - label_token bop: required(nth(0), [93], "bop"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionLambdaLabelContext { - rule_index: 98, - context_kind: exact(112), - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionLambdaLabelContext { - rule lambda_expression: required(LambdaExpressionContext[102], "lambdaExpression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PatternContext { - rule_index: 99, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PatternContext { - rule variable_modifier_children: many(VariableModifierContext[7]), - rule variable_declarators: optional(VariableDeclaratorsContext[37]), - rule annotation_children: many(AnnotationContext[56]), - rule component_pattern_list: optional(ComponentPatternListContext[100]), - rule type_type: required(TypeTypeContext[122], "typeType"), - token lparen_token: optional(79), - token rparen_token: optional(80), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ComponentPatternListContext { - rule_index: 100, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ComponentPatternListContext { - rule component_pattern_children: many(ComponentPatternContext[101]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ComponentPatternContext { - rule_index: 101, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ComponentPatternContext { - rule pattern: required(PatternContext[99], "pattern"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaExpressionContext { - rule_index: 102, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaExpressionContext { - rule lambda_parameters: required(LambdaParametersContext[103], "lambdaParameters"), - rule lambda_body: required(LambdaBodyContext[104], "lambdaBody"), - token arrow_token: required(122, "ARROW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaParametersContext { - rule_index: 103, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaParametersContext { - rule formal_parameter_list: optional(FormalParameterListContext[48]), - rule lambda_lvti_list: optional(LambdaLvtiListContext[50]), - rule identifier_children: many(IdentifierContext[81]), - token lparen_token: optional(79), - token rparen_token: optional(80), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaBodyContext { - rule_index: 104, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaBodyContext { - rule block: optional(BlockContext[78]), - rule expression: optional(ExpressionContext[98]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrimaryContext { - rule_index: 105, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrimaryContext { - rule type_type_or_void: optional(TypeTypeOrVoidContext[23]), - rule literal: optional(LiteralContext[53]), - rule identifier: optional(IdentifierContext[81]), - rule expression: optional(ExpressionContext[98]), - rule non_wildcard_type_arguments: optional(NonWildcardTypeArgumentsContext[120]), - rule explicit_generic_invocation_suffix: optional(ExplicitGenericInvocationSuffixContext[126]), - rule arguments: optional(ArgumentsContext[127]), - token class_token: optional(9), - token super__token: optional(50), - token this_token: optional(53), - token lparen_token: optional(79), - token rparen_token: optional(80), - token dot_token: optional(87), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchExpressionContext { - rule_index: 106, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchExpressionContext { - rule expression: required(ExpressionContext[98], "expression"), - rule switch_labeled_rule_children: many(SwitchLabeledRuleContext[107]), - token switch_token: required(51, "SWITCH"), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - token lbrace_token: required(81, "LBRACE"), - token rbrace_token: required(82, "RBRACE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchLabeledRuleContext { - rule_index: 107, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchLabeledRuleContext { - rule expression_list: optional(ExpressionListContext[96]), - rule guard: optional(GuardContext[108]), - rule case_pattern_children: many(CasePatternContext[109]), - rule switch_rule_outcome: required(SwitchRuleOutcomeContext[110], "switchRuleOutcome"), - token case_token: optional(6), - token default_token: optional(12), - token null_literal_token: optional(78), - token comma_tokens: many(86), - token colon_token: optional(94), - token arrow_token: optional(122), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GuardContext { - rule_index: 108, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GuardContext { - rule expression: required(ExpressionContext[98], "expression"), - token when_token: required(64, "WHEN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CasePatternContext { - rule_index: 109, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CasePatternContext { - rule pattern: required(PatternContext[99], "pattern"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SwitchRuleOutcomeContext { - rule_index: 110, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SwitchRuleOutcomeContext { - rule block: optional(BlockContext[78]), - rule block_statement_children: many(BlockStatementContext[79]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassOrInterfaceTypeContext { - rule_index: 111, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassOrInterfaceTypeContext { - rule class_type: required(ClassTypeContext[42], "classType"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CreatorContext { - rule_index: 112, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CreatorContext { - rule created_name: required(CreatedNameContext[113], "createdName"), - rule array_creator_rest: optional(ArrayCreatorRestContext[115]), - rule class_creator_rest: optional(ClassCreatorRestContext[116]), - rule non_wildcard_type_arguments: optional(NonWildcardTypeArgumentsContext[120]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CreatedNameContext { - rule_index: 113, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CreatedNameContext { - rule identifier_children: many(IdentifierContext[81]), - rule type_arguments_or_diamond_children: many(TypeArgumentsOrDiamondContext[118]), - rule primitive_type: optional(PrimitiveTypeContext[123]), - token dot_tokens: many(87), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InnerCreatorContext { - rule_index: 114, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InnerCreatorContext { - rule identifier: required(IdentifierContext[81], "identifier"), - rule class_creator_rest: required(ClassCreatorRestContext[116], "classCreatorRest"), - rule non_wildcard_type_arguments_or_diamond: optional(NonWildcardTypeArgumentsOrDiamondContext[119]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArrayCreatorRestContext { - rule_index: 115, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArrayCreatorRestContext { - rule array_initializer: optional(ArrayInitializerContext[41]), - rule expression_children: many(ExpressionContext[98]), - token lbrack_tokens: many(83), - token rbrack_tokens: many(84), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassCreatorRestContext { - rule_index: 116, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassCreatorRestContext { - rule class_body: optional(ClassBodyContext[17]), - rule arguments: required(ArgumentsContext[127], "arguments"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExplicitGenericInvocationContext { - rule_index: 117, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExplicitGenericInvocationContext { - rule non_wildcard_type_arguments: required(NonWildcardTypeArgumentsContext[120], "nonWildcardTypeArguments"), - rule explicit_generic_invocation_suffix: required(ExplicitGenericInvocationSuffixContext[126], "explicitGenericInvocationSuffix"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeArgumentsOrDiamondContext { - rule_index: 118, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeArgumentsOrDiamondContext { - rule type_arguments: optional(TypeArgumentsContext[124]), - token gt_token: optional(89), - token lt_token: optional(90), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NonWildcardTypeArgumentsOrDiamondContext { - rule_index: 119, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NonWildcardTypeArgumentsOrDiamondContext { - rule non_wildcard_type_arguments: optional(NonWildcardTypeArgumentsContext[120]), - token gt_token: optional(89), - token lt_token: optional(90), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NonWildcardTypeArgumentsContext { - rule_index: 120, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NonWildcardTypeArgumentsContext { - rule type_list: required(TypeListContext[121], "typeList"), - token gt_token: required(89, "GT"), - token lt_token: required(90, "LT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeListContext { - rule_index: 121, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeListContext { - rule type_type_children: many(TypeTypeContext[122]), - token comma_tokens: many(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeTypeContext { - rule_index: 122, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeTypeContext { - rule annotation_children: many(AnnotationContext[56]), - rule class_or_interface_type: optional(ClassOrInterfaceTypeContext[111]), - rule primitive_type: optional(PrimitiveTypeContext[123]), - token lbrack_tokens: many(83), - token rbrack_tokens: many(84), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrimitiveTypeContext { - rule_index: 123, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrimitiveTypeContext { - token boolean_token: optional(3), - token byte_token: optional(5), - token char_token: optional(8), - token double_token: optional(14), - token float_token: optional(21), - token int_token: optional(28), - token long_token: optional(30), - token short_token: optional(47), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeArgumentsContext { - rule_index: 124, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeArgumentsContext { - rule type_argument_children: many(TypeArgumentContext[44]), - token comma_tokens: many(86), - token gt_token: required(89, "GT"), - token lt_token: required(90, "LT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SuperSuffixContext { - rule_index: 125, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SuperSuffixContext { - rule identifier: optional(IdentifierContext[81]), - rule type_arguments: optional(TypeArgumentsContext[124]), - rule arguments: optional(ArgumentsContext[127]), - token dot_token: optional(87), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExplicitGenericInvocationSuffixContext { - rule_index: 126, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExplicitGenericInvocationSuffixContext { - rule identifier: optional(IdentifierContext[81]), - rule super_suffix: optional(SuperSuffixContext[125]), - rule arguments: optional(ArgumentsContext[127]), - token super__token: optional(50), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ArgumentsContext { - rule_index: 127, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ArgumentsContext { - rule expression_list: optional(ExpressionListContext[96]), - token lparen_token: required(79, "LPAREN"), - token rparen_token: required(80, "RPAREN"), - } -} - -/// Checks generated required-child invariants without changing the -/// recovery-oriented tree's type. -/// -/// Strict parsing calls this after proving that lexer and parser syntax-error -/// counts are both zero. It is public so structural runtime/codegen invariant -/// failures can be diagnosed independently. -pub fn validate_tree_structure( - parsed: &antlr4_runtime::ParsedFile, -) -> Result<(), JavaValidationError> { - let tree = parsed.tree(); - if tree.as_rule().is_none() { - return Err(JavaValidationError::InvalidRoot); - } - for node in tree.descendants() { - match node.kind() { - antlr4_runtime::NodeKind::Terminal => {} - antlr4_runtime::NodeKind::Error => { - let symbol = node - .as_error() - .expect("error node kind checked") - .symbol(); - return Err(JavaValidationError::RecoveredErrorNode { - line: symbol.line(), - column: symbol.column(), - text: symbol.text_or_empty().to_owned(), - }); - } - antlr4_runtime::NodeKind::Rule => { - let context = node.as_rule().expect("rule node kind checked"); - match __context_kind(context) { - 0 => { - let context = CompilationUnitContext::__from_listener_node(context, None); - context.eof_token()?; - }, - 1 => { - let context = ModularCompulationUnitContext::__from_listener_node(context, None); - context.module_declaration()?; - }, - 2 => { - let context = PackageDeclarationContext::__from_listener_node(context, None); - context.qualified_name()?; - context.package_token()?; - context.semi_token()?; - }, - 3 => { - let context = ImportDeclarationContext::__from_listener_node(context, None); - context.qualified_name()?; - context.import_token()?; - context.semi_token()?; - }, - 4 => { - }, - 5 => { - }, - 6 => { - }, - 7 => { - }, - 8 => { - let context = ClassDeclarationContext::__from_listener_node(context, None); - context.class_body()?; - context.identifier()?; - context.class_token()?; - }, - 9 => { - let context = TypeParametersContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_parameter_children().count(), 1, "TypeParametersContext", "typeParameter")?; - context.gt_token()?; - context.lt_token()?; - }, - 10 => { - let context = TypeParameterContext::__from_listener_node(context, None); - context.identifier()?; - }, - 11 => { - let context = TypeBoundContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_type_children().count(), 1, "TypeBoundContext", "typeType")?; - }, - 12 => { - let context = EnumDeclarationContext::__from_listener_node(context, None); - context.identifier()?; - context.enum_token()?; - context.lbrace_token()?; - context.rbrace_token()?; - }, - 13 => { - let context = EnumConstantsContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.enum_constant_children().count(), 1, "EnumConstantsContext", "enumConstant")?; - }, - 14 => { - let context = EnumConstantContext::__from_listener_node(context, None); - context.identifier()?; - }, - 15 => { - let context = EnumBodyDeclarationsContext::__from_listener_node(context, None); - context.semi_token()?; - }, - 16 => { - let context = InterfaceDeclarationContext::__from_listener_node(context, None); - context.interface_body()?; - context.identifier()?; - context.interface_token()?; - }, - 17 => { - let context = ClassBodyContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 18 => { - let context = InterfaceBodyContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 19 => { - }, - 20 => { - }, - 21 => { - let context = MethodDeclarationContext::__from_listener_node(context, None); - context.method_body()?; - context.type_type_or_void()?; - context.formal_parameters()?; - context.identifier()?; - }, - 22 => { - }, - 23 => { - }, - 24 => { - let context = GenericMethodDeclarationContext::__from_listener_node(context, None); - context.type_parameters()?; - context.method_declaration()?; - }, - 25 => { - let context = GenericConstructorDeclarationContext::__from_listener_node(context, None); - context.type_parameters()?; - context.constructor_declaration()?; - }, - 26 => { - let context = ConstructorDeclarationContext::__from_listener_node(context, None); - context.formal_parameters()?; - context.block()?; - context.identifier()?; - context.constructor_body()?; - }, - 27 => { - let context = CompactConstructorDeclarationContext::__from_listener_node(context, None); - context.block()?; - context.identifier()?; - context.constructor_body()?; - }, - 28 => { - let context = FieldDeclarationContext::__from_listener_node(context, None); - context.variable_declarators()?; - context.type_type()?; - context.semi_token()?; - }, - 29 => { - }, - 30 => { - }, - 31 => { - let context = ConstDeclarationContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.constant_declarator_children().count(), 1, "ConstDeclarationContext", "constantDeclarator")?; - context.type_type()?; - context.semi_token()?; - }, - 32 => { - let context = ConstantDeclaratorContext::__from_listener_node(context, None); - context.variable_initializer()?; - context.identifier()?; - context.assign_token()?; - }, - 33 => { - let context = InterfaceMethodDeclarationContext::__from_listener_node(context, None); - context.interface_common_body_declaration()?; - }, - 34 => { - }, - 35 => { - let context = GenericInterfaceMethodDeclarationContext::__from_listener_node(context, None); - context.type_parameters()?; - context.interface_common_body_declaration()?; - }, - 36 => { - let context = InterfaceCommonBodyDeclarationContext::__from_listener_node(context, None); - context.method_body()?; - context.type_type_or_void()?; - context.formal_parameters()?; - context.identifier()?; - }, - 37 => { - let context = VariableDeclaratorsContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.variable_declarator_children().count(), 1, "VariableDeclaratorsContext", "variableDeclarator")?; - }, - 38 => { - let context = VariableDeclaratorContext::__from_listener_node(context, None); - context.variable_declarator_id()?; - }, - 39 => { - let context = VariableDeclaratorIdContext::__from_listener_node(context, None); - context.identifier()?; - }, - 40 => { - }, - 41 => { - let context = ArrayInitializerContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 42 => { - let context = ClassTypeContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_identifier_children().count(), 1, "ClassTypeContext", "typeIdentifier")?; - }, - 43 => { - let context = PackageNameContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.identifier_children().count(), 1, "PackageNameContext", "identifier")?; - }, - 44 => { - }, - 45 => { - let context = QualifiedNameListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.qualified_name_children().count(), 1, "QualifiedNameListContext", "qualifiedName")?; - }, - 46 => { - let context = FormalParametersContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 47 => { - let context = ReceiverParameterContext::__from_listener_node(context, None); - context.type_type()?; - context.this_token()?; - }, - 48 => { - let context = FormalParameterListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.formal_parameter_children().count(), 1, "FormalParameterListContext", "formalParameter")?; - }, - 49 => { - let context = FormalParameterContext::__from_listener_node(context, None); - context.variable_declarator_id()?; - context.type_type()?; - }, - 50 => { - let context = LambdaLvtiListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.lambda_lvti_parameter_children().count(), 1, "LambdaLvtiListContext", "lambdaLVTIParameter")?; - }, - 51 => { - let context = LambdaLvtiParameterContext::__from_listener_node(context, None); - context.identifier()?; - context.var_token()?; - }, - 52 => { - let context = QualifiedNameContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.identifier_children().count(), 1, "QualifiedNameContext", "identifier")?; - }, - 53 => { - }, - 54 => { - }, - 55 => { - }, - 56 => { - let context = AnnotationContext::__from_listener_node(context, None); - context.qualified_name()?; - context.at_token()?; - }, - 57 => { - let context = AnnotationFieldValuesContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 58 => { - let context = AnnotationFieldValueContext::__from_listener_node(context, None); - context.annotation_value()?; - }, - 59 => { - }, - 60 => { - }, - 61 => { - let context = ElementValueArrayInitializerContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 62 => { - let context = AnnotationTypeDeclarationContext::__from_listener_node(context, None); - context.annotation_type_body()?; - context.identifier()?; - context.interface_token()?; - context.at_token()?; - }, - 63 => { - let context = AnnotationTypeBodyContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 64 => { - }, - 65 => { - }, - 66 => { - }, - 67 => { - let context = AnnotationMethodRestContext::__from_listener_node(context, None); - context.identifier()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 68 => { - let context = AnnotationConstantRestContext::__from_listener_node(context, None); - context.variable_declarators()?; - }, - 69 => { - let context = DefaultValueContext::__from_listener_node(context, None); - context.element_value()?; - context.default_token()?; - }, - 70 => { - let context = ModuleDeclarationContext::__from_listener_node(context, None); - context.qualified_name()?; - context.module_token()?; - context.lbrace_token()?; - context.rbrace_token()?; - }, - 71 => { - let context = ModuleDirectiveContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.qualified_name_children().count(), 1, "ModuleDirectiveContext", "qualifiedName")?; - context.semi_token()?; - }, - 72 => { - }, - 73 => { - let context = RecordDeclarationContext::__from_listener_node(context, None); - context.record_header()?; - context.record_body()?; - context.identifier()?; - context.record_token()?; - }, - 74 => { - let context = RecordHeaderContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 75 => { - let context = RecordComponentListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.record_component_children().count(), 1, "RecordComponentListContext", "recordComponent")?; - }, - 76 => { - let context = RecordComponentContext::__from_listener_node(context, None); - context.identifier()?; - context.type_type()?; - }, - 77 => { - let context = RecordBodyContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 78 => { - let context = BlockContext::__from_listener_node(context, None); - context.lbrace_token()?; - context.rbrace_token()?; - }, - 79 => { - }, - 80 => { - }, - 81 => { - }, - 82 => { - }, - 83 => { - }, - 84 => { - }, - 85 => { - let context = CatchClauseContext::__from_listener_node(context, None); - context.block()?; - context.identifier()?; - context.catch_type()?; - context.catch_token()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 86 => { - let context = CatchTypeContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.qualified_name_children().count(), 1, "CatchTypeContext", "qualifiedName")?; - }, - 87 => { - let context = FinallyBlockContext::__from_listener_node(context, None); - context.block()?; - context.finally_token()?; - }, - 88 => { - let context = ResourceSpecificationContext::__from_listener_node(context, None); - context.resources()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 89 => { - let context = ResourcesContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.resource_children().count(), 1, "ResourcesContext", "resource")?; - }, - 90 => { - }, - 91 => { - let context = SwitchBlockStatementGroupContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.block_statement_children().count(), 1, "SwitchBlockStatementGroupContext", "blockStatement")?; - antlr4_runtime::require_min_count(context.switch_label_children().count(), 1, "SwitchBlockStatementGroupContext", "switchLabel")?; - antlr4_runtime::require_min_count(context.colon_tokens().count(), 1, "SwitchBlockStatementGroupContext", "COLON")?; - }, - 92 => { - }, - 93 => { - }, - 94 => { - }, - 95 => { - let context = EnhancedForControlContext::__from_listener_node(context, None); - context.variable_declarator_id()?; - context.expression()?; - context.colon_token()?; - }, - 96 => { - let context = ExpressionListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.expression_children().count(), 1, "ExpressionListContext", "expression")?; - }, - 97 => { - let context = MethodCallContext::__from_listener_node(context, None); - context.arguments()?; - }, - 98 => { - }, - 99 => { - let context = PrimaryExpressionLabelContext::__from_listener_node(context, None); - context.primary()?; - }, - 100 => { - let context = SquareBracketExpressionLabelContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.expression_children().count(), 2, "SquareBracketExpressionLabelContext", "expression")?; - context.lbrack_token()?; - context.rbrack_token()?; - }, - 101 => { - let context = MemberReferenceExpressionLabelContext::__from_listener_node(context, None); - context.expression()?; - context.dot_token()?; - context.bop()?; - }, - 102 => { - let context = MethodCallExpressionLabelContext::__from_listener_node(context, None); - context.method_call()?; - }, - 103 => { - let context = MethodReferenceExpressionLabelContext::__from_listener_node(context, None); - context.coloncolon_token()?; - }, - 104 => { - let context = ExpressionSwitchLabelContext::__from_listener_node(context, None); - context.switch_expression()?; - }, - 105 => { - let context = PostIncrementDecrementOperatorExpressionLabelContext::__from_listener_node(context, None); - context.expression()?; - context.postfix()?; - }, - 106 => { - let context = UnaryOperatorExpressionLabelContext::__from_listener_node(context, None); - context.expression()?; - context.prefix()?; - }, - 107 => { - let context = CastExpressionLabelContext::__from_listener_node(context, None); - context.expression()?; - antlr4_runtime::require_min_count(context.type_type_children().count(), 1, "CastExpressionLabelContext", "typeType")?; - context.lparen_token()?; - context.rparen_token()?; - }, - 108 => { - let context = ObjectCreationExpressionLabelContext::__from_listener_node(context, None); - context.creator()?; - context.new_token()?; - }, - 109 => { - let context = BinaryOperatorExpressionLabelContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.expression_children().count(), 2, "BinaryOperatorExpressionLabelContext", "expression")?; - }, - 110 => { - let context = InstanceOfOperatorExpressionLabelContext::__from_listener_node(context, None); - context.expression()?; - context.instanceof_token()?; - context.bop()?; - }, - 111 => { - let context = TernaryExpressionLabelContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.expression_children().count(), 3, "TernaryExpressionLabelContext", "expression")?; - context.question_token()?; - context.colon_token()?; - context.bop()?; - }, - 112 => { - let context = ExpressionLambdaLabelContext::__from_listener_node(context, None); - context.lambda_expression()?; - }, - 113 => { - let context = PatternContext::__from_listener_node(context, None); - context.type_type()?; - }, - 114 => { - let context = ComponentPatternListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.component_pattern_children().count(), 1, "ComponentPatternListContext", "componentPattern")?; - }, - 115 => { - let context = ComponentPatternContext::__from_listener_node(context, None); - context.pattern()?; - }, - 116 => { - let context = LambdaExpressionContext::__from_listener_node(context, None); - context.lambda_parameters()?; - context.lambda_body()?; - context.arrow_token()?; - }, - 117 => { - }, - 118 => { - }, - 119 => { - }, - 120 => { - let context = SwitchExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.switch_token()?; - context.lparen_token()?; - context.rparen_token()?; - context.lbrace_token()?; - context.rbrace_token()?; - }, - 121 => { - let context = SwitchLabeledRuleContext::__from_listener_node(context, None); - context.switch_rule_outcome()?; - }, - 122 => { - let context = GuardContext::__from_listener_node(context, None); - context.expression()?; - context.when_token()?; - }, - 123 => { - let context = CasePatternContext::__from_listener_node(context, None); - context.pattern()?; - }, - 124 => { - }, - 125 => { - let context = ClassOrInterfaceTypeContext::__from_listener_node(context, None); - context.class_type()?; - }, - 126 => { - let context = CreatorContext::__from_listener_node(context, None); - context.created_name()?; - }, - 127 => { - }, - 128 => { - let context = InnerCreatorContext::__from_listener_node(context, None); - context.identifier()?; - context.class_creator_rest()?; - }, - 129 => { - let context = ArrayCreatorRestContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.lbrack_tokens().count(), 1, "ArrayCreatorRestContext", "LBRACK")?; - antlr4_runtime::require_min_count(context.rbrack_tokens().count(), 1, "ArrayCreatorRestContext", "RBRACK")?; - }, - 130 => { - let context = ClassCreatorRestContext::__from_listener_node(context, None); - context.arguments()?; - }, - 131 => { - let context = ExplicitGenericInvocationContext::__from_listener_node(context, None); - context.non_wildcard_type_arguments()?; - context.explicit_generic_invocation_suffix()?; - }, - 132 => { - }, - 133 => { - }, - 134 => { - let context = NonWildcardTypeArgumentsContext::__from_listener_node(context, None); - context.type_list()?; - context.gt_token()?; - context.lt_token()?; - }, - 135 => { - let context = TypeListContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_type_children().count(), 1, "TypeListContext", "typeType")?; - }, - 136 => { - }, - 137 => { - }, - 138 => { - let context = TypeArgumentsContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_argument_children().count(), 1, "TypeArgumentsContext", "typeArgument")?; - context.gt_token()?; - context.lt_token()?; - }, - 139 => { - }, - 140 => { - }, - 141 => { - let context = ArgumentsContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - _ => { - return Err(JavaValidationError::UnknownRule { - rule_index: context.rule_index(), - }); - } - } - } - } - } - Ok(()) -} - -#[allow(dead_code, unused_variables)] -pub trait JavaListener { - fn walk(&mut self, tree: antlr4_runtime::Node<'_>) -> Result<(), E> - where - Self: Sized, - { - JavaTreeWalker::walk(self, tree) - } - - fn enter_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), E> { Ok(()) } - fn exit_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), E> { Ok(()) } - - fn enter_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn exit_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn enter_modular_compulation_unit(&mut self, _ctx: &ModularCompulationUnitContext) -> Result<(), E> { Ok(()) } - fn exit_modular_compulation_unit(&mut self, _ctx: &ModularCompulationUnitContext) -> Result<(), E> { Ok(()) } - fn enter_package_declaration(&mut self, _ctx: &PackageDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_package_declaration(&mut self, _ctx: &PackageDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_import_declaration(&mut self, _ctx: &ImportDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_import_declaration(&mut self, _ctx: &ImportDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn exit_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn enter_class_or_interface_modifier(&mut self, _ctx: &ClassOrInterfaceModifierContext) -> Result<(), E> { Ok(()) } - fn exit_class_or_interface_modifier(&mut self, _ctx: &ClassOrInterfaceModifierContext) -> Result<(), E> { Ok(()) } - fn enter_variable_modifier(&mut self, _ctx: &VariableModifierContext) -> Result<(), E> { Ok(()) } - fn exit_variable_modifier(&mut self, _ctx: &VariableModifierContext) -> Result<(), E> { Ok(()) } - fn enter_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn enter_type_bound(&mut self, _ctx: &TypeBoundContext) -> Result<(), E> { Ok(()) } - fn exit_type_bound(&mut self, _ctx: &TypeBoundContext) -> Result<(), E> { Ok(()) } - fn enter_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_enum_constants(&mut self, _ctx: &EnumConstantsContext) -> Result<(), E> { Ok(()) } - fn exit_enum_constants(&mut self, _ctx: &EnumConstantsContext) -> Result<(), E> { Ok(()) } - fn enter_enum_constant(&mut self, _ctx: &EnumConstantContext) -> Result<(), E> { Ok(()) } - fn exit_enum_constant(&mut self, _ctx: &EnumConstantContext) -> Result<(), E> { Ok(()) } - fn enter_enum_body_declarations(&mut self, _ctx: &EnumBodyDeclarationsContext) -> Result<(), E> { Ok(()) } - fn exit_enum_body_declarations(&mut self, _ctx: &EnumBodyDeclarationsContext) -> Result<(), E> { Ok(()) } - fn enter_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn exit_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn enter_interface_body(&mut self, _ctx: &InterfaceBodyContext) -> Result<(), E> { Ok(()) } - fn exit_interface_body(&mut self, _ctx: &InterfaceBodyContext) -> Result<(), E> { Ok(()) } - fn enter_class_body_declaration(&mut self, _ctx: &ClassBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_body_declaration(&mut self, _ctx: &ClassBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_method_body(&mut self, _ctx: &MethodBodyContext) -> Result<(), E> { Ok(()) } - fn exit_method_body(&mut self, _ctx: &MethodBodyContext) -> Result<(), E> { Ok(()) } - fn enter_type_type_or_void(&mut self, _ctx: &TypeTypeOrVoidContext) -> Result<(), E> { Ok(()) } - fn exit_type_type_or_void(&mut self, _ctx: &TypeTypeOrVoidContext) -> Result<(), E> { Ok(()) } - fn enter_generic_method_declaration(&mut self, _ctx: &GenericMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_generic_method_declaration(&mut self, _ctx: &GenericMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_generic_constructor_declaration(&mut self, _ctx: &GenericConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_generic_constructor_declaration(&mut self, _ctx: &GenericConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_compact_constructor_declaration(&mut self, _ctx: &CompactConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_compact_constructor_declaration(&mut self, _ctx: &CompactConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_body_declaration(&mut self, _ctx: &InterfaceBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_body_declaration(&mut self, _ctx: &InterfaceBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_member_declaration(&mut self, _ctx: &InterfaceMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_member_declaration(&mut self, _ctx: &InterfaceMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_const_declaration(&mut self, _ctx: &ConstDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_const_declaration(&mut self, _ctx: &ConstDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_constant_declarator(&mut self, _ctx: &ConstantDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_constant_declarator(&mut self, _ctx: &ConstantDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_interface_method_declaration(&mut self, _ctx: &InterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_method_declaration(&mut self, _ctx: &InterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_method_modifier(&mut self, _ctx: &InterfaceMethodModifierContext) -> Result<(), E> { Ok(()) } - fn exit_interface_method_modifier(&mut self, _ctx: &InterfaceMethodModifierContext) -> Result<(), E> { Ok(()) } - fn enter_generic_interface_method_declaration(&mut self, _ctx: &GenericInterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_generic_interface_method_declaration(&mut self, _ctx: &GenericInterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_common_body_declaration(&mut self, _ctx: &InterfaceCommonBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_common_body_declaration(&mut self, _ctx: &InterfaceCommonBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarators(&mut self, _ctx: &VariableDeclaratorsContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarators(&mut self, _ctx: &VariableDeclaratorsContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarator_id(&mut self, _ctx: &VariableDeclaratorIdContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarator_id(&mut self, _ctx: &VariableDeclaratorIdContext) -> Result<(), E> { Ok(()) } - fn enter_variable_initializer(&mut self, _ctx: &VariableInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_variable_initializer(&mut self, _ctx: &VariableInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_array_initializer(&mut self, _ctx: &ArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_array_initializer(&mut self, _ctx: &ArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_class_type(&mut self, _ctx: &ClassTypeContext) -> Result<(), E> { Ok(()) } - fn exit_class_type(&mut self, _ctx: &ClassTypeContext) -> Result<(), E> { Ok(()) } - fn enter_package_name(&mut self, _ctx: &PackageNameContext) -> Result<(), E> { Ok(()) } - fn exit_package_name(&mut self, _ctx: &PackageNameContext) -> Result<(), E> { Ok(()) } - fn enter_type_argument(&mut self, _ctx: &TypeArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_type_argument(&mut self, _ctx: &TypeArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_qualified_name_list(&mut self, _ctx: &QualifiedNameListContext) -> Result<(), E> { Ok(()) } - fn exit_qualified_name_list(&mut self, _ctx: &QualifiedNameListContext) -> Result<(), E> { Ok(()) } - fn enter_formal_parameters(&mut self, _ctx: &FormalParametersContext) -> Result<(), E> { Ok(()) } - fn exit_formal_parameters(&mut self, _ctx: &FormalParametersContext) -> Result<(), E> { Ok(()) } - fn enter_receiver_parameter(&mut self, _ctx: &ReceiverParameterContext) -> Result<(), E> { Ok(()) } - fn exit_receiver_parameter(&mut self, _ctx: &ReceiverParameterContext) -> Result<(), E> { Ok(()) } - fn enter_formal_parameter_list(&mut self, _ctx: &FormalParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_formal_parameter_list(&mut self, _ctx: &FormalParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_formal_parameter(&mut self, _ctx: &FormalParameterContext) -> Result<(), E> { Ok(()) } - fn exit_formal_parameter(&mut self, _ctx: &FormalParameterContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_lvti_list(&mut self, _ctx: &LambdaLvtiListContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_lvti_list(&mut self, _ctx: &LambdaLvtiListContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_lvti_parameter(&mut self, _ctx: &LambdaLvtiParameterContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_lvti_parameter(&mut self, _ctx: &LambdaLvtiParameterContext) -> Result<(), E> { Ok(()) } - fn enter_qualified_name(&mut self, _ctx: &QualifiedNameContext) -> Result<(), E> { Ok(()) } - fn exit_qualified_name(&mut self, _ctx: &QualifiedNameContext) -> Result<(), E> { Ok(()) } - fn enter_literal(&mut self, _ctx: &LiteralContext) -> Result<(), E> { Ok(()) } - fn exit_literal(&mut self, _ctx: &LiteralContext) -> Result<(), E> { Ok(()) } - fn enter_integer_literal(&mut self, _ctx: &IntegerLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_integer_literal(&mut self, _ctx: &IntegerLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_float_literal(&mut self, _ctx: &FloatLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_float_literal(&mut self, _ctx: &FloatLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_field_values(&mut self, _ctx: &AnnotationFieldValuesContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_field_values(&mut self, _ctx: &AnnotationFieldValuesContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_field_value(&mut self, _ctx: &AnnotationFieldValueContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_field_value(&mut self, _ctx: &AnnotationFieldValueContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_value(&mut self, _ctx: &AnnotationValueContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_value(&mut self, _ctx: &AnnotationValueContext) -> Result<(), E> { Ok(()) } - fn enter_element_value(&mut self, _ctx: &ElementValueContext) -> Result<(), E> { Ok(()) } - fn exit_element_value(&mut self, _ctx: &ElementValueContext) -> Result<(), E> { Ok(()) } - fn enter_element_value_array_initializer(&mut self, _ctx: &ElementValueArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_element_value_array_initializer(&mut self, _ctx: &ElementValueArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_declaration(&mut self, _ctx: &AnnotationTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_declaration(&mut self, _ctx: &AnnotationTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_body(&mut self, _ctx: &AnnotationTypeBodyContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_body(&mut self, _ctx: &AnnotationTypeBodyContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_element_declaration(&mut self, _ctx: &AnnotationTypeElementDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_element_declaration(&mut self, _ctx: &AnnotationTypeElementDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_element_rest(&mut self, _ctx: &AnnotationTypeElementRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_element_rest(&mut self, _ctx: &AnnotationTypeElementRestContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_method_or_constant_rest(&mut self, _ctx: &AnnotationMethodOrConstantRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_method_or_constant_rest(&mut self, _ctx: &AnnotationMethodOrConstantRestContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_method_rest(&mut self, _ctx: &AnnotationMethodRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_method_rest(&mut self, _ctx: &AnnotationMethodRestContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_constant_rest(&mut self, _ctx: &AnnotationConstantRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_constant_rest(&mut self, _ctx: &AnnotationConstantRestContext) -> Result<(), E> { Ok(()) } - fn enter_default_value(&mut self, _ctx: &DefaultValueContext) -> Result<(), E> { Ok(()) } - fn exit_default_value(&mut self, _ctx: &DefaultValueContext) -> Result<(), E> { Ok(()) } - fn enter_module_declaration(&mut self, _ctx: &ModuleDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_module_declaration(&mut self, _ctx: &ModuleDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_module_directive(&mut self, _ctx: &ModuleDirectiveContext) -> Result<(), E> { Ok(()) } - fn exit_module_directive(&mut self, _ctx: &ModuleDirectiveContext) -> Result<(), E> { Ok(()) } - fn enter_requires_modifier(&mut self, _ctx: &RequiresModifierContext) -> Result<(), E> { Ok(()) } - fn exit_requires_modifier(&mut self, _ctx: &RequiresModifierContext) -> Result<(), E> { Ok(()) } - fn enter_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_record_header(&mut self, _ctx: &RecordHeaderContext) -> Result<(), E> { Ok(()) } - fn exit_record_header(&mut self, _ctx: &RecordHeaderContext) -> Result<(), E> { Ok(()) } - fn enter_record_component_list(&mut self, _ctx: &RecordComponentListContext) -> Result<(), E> { Ok(()) } - fn exit_record_component_list(&mut self, _ctx: &RecordComponentListContext) -> Result<(), E> { Ok(()) } - fn enter_record_component(&mut self, _ctx: &RecordComponentContext) -> Result<(), E> { Ok(()) } - fn exit_record_component(&mut self, _ctx: &RecordComponentContext) -> Result<(), E> { Ok(()) } - fn enter_record_body(&mut self, _ctx: &RecordBodyContext) -> Result<(), E> { Ok(()) } - fn exit_record_body(&mut self, _ctx: &RecordBodyContext) -> Result<(), E> { Ok(()) } - fn enter_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn exit_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn enter_block_statement(&mut self, _ctx: &BlockStatementContext) -> Result<(), E> { Ok(()) } - fn exit_block_statement(&mut self, _ctx: &BlockStatementContext) -> Result<(), E> { Ok(()) } - fn enter_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn enter_type_identifier(&mut self, _ctx: &TypeIdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_identifier(&mut self, _ctx: &TypeIdentifierContext) -> Result<(), E> { Ok(()) } - fn enter_local_type_declaration(&mut self, _ctx: &LocalTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_local_type_declaration(&mut self, _ctx: &LocalTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn exit_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn enter_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn exit_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn enter_catch_type(&mut self, _ctx: &CatchTypeContext) -> Result<(), E> { Ok(()) } - fn exit_catch_type(&mut self, _ctx: &CatchTypeContext) -> Result<(), E> { Ok(()) } - fn enter_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn exit_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn enter_resource_specification(&mut self, _ctx: &ResourceSpecificationContext) -> Result<(), E> { Ok(()) } - fn exit_resource_specification(&mut self, _ctx: &ResourceSpecificationContext) -> Result<(), E> { Ok(()) } - fn enter_resources(&mut self, _ctx: &ResourcesContext) -> Result<(), E> { Ok(()) } - fn exit_resources(&mut self, _ctx: &ResourcesContext) -> Result<(), E> { Ok(()) } - fn enter_resource(&mut self, _ctx: &ResourceContext) -> Result<(), E> { Ok(()) } - fn exit_resource(&mut self, _ctx: &ResourceContext) -> Result<(), E> { Ok(()) } - fn enter_switch_block_statement_group(&mut self, _ctx: &SwitchBlockStatementGroupContext) -> Result<(), E> { Ok(()) } - fn exit_switch_block_statement_group(&mut self, _ctx: &SwitchBlockStatementGroupContext) -> Result<(), E> { Ok(()) } - fn enter_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_for_control(&mut self, _ctx: &ForControlContext) -> Result<(), E> { Ok(()) } - fn exit_for_control(&mut self, _ctx: &ForControlContext) -> Result<(), E> { Ok(()) } - fn enter_for_init(&mut self, _ctx: &ForInitContext) -> Result<(), E> { Ok(()) } - fn exit_for_init(&mut self, _ctx: &ForInitContext) -> Result<(), E> { Ok(()) } - fn enter_enhanced_for_control(&mut self, _ctx: &EnhancedForControlContext) -> Result<(), E> { Ok(()) } - fn exit_enhanced_for_control(&mut self, _ctx: &EnhancedForControlContext) -> Result<(), E> { Ok(()) } - fn enter_expression_list(&mut self, _ctx: &ExpressionListContext) -> Result<(), E> { Ok(()) } - fn exit_expression_list(&mut self, _ctx: &ExpressionListContext) -> Result<(), E> { Ok(()) } - fn enter_method_call(&mut self, _ctx: &MethodCallContext) -> Result<(), E> { Ok(()) } - fn exit_method_call(&mut self, _ctx: &MethodCallContext) -> Result<(), E> { Ok(()) } - fn enter_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_primary_expression_label(&mut self, _ctx: &PrimaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_primary_expression_label(&mut self, _ctx: &PrimaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_square_bracket_expression_label(&mut self, _ctx: &SquareBracketExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_square_bracket_expression_label(&mut self, _ctx: &SquareBracketExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_member_reference_expression_label(&mut self, _ctx: &MemberReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_member_reference_expression_label(&mut self, _ctx: &MemberReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_method_call_expression_label(&mut self, _ctx: &MethodCallExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_method_call_expression_label(&mut self, _ctx: &MethodCallExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_method_reference_expression_label(&mut self, _ctx: &MethodReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_method_reference_expression_label(&mut self, _ctx: &MethodReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_expression_switch_label(&mut self, _ctx: &ExpressionSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_expression_switch_label(&mut self, _ctx: &ExpressionSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_post_increment_decrement_operator_expression_label(&mut self, _ctx: &PostIncrementDecrementOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_post_increment_decrement_operator_expression_label(&mut self, _ctx: &PostIncrementDecrementOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_unary_operator_expression_label(&mut self, _ctx: &UnaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_unary_operator_expression_label(&mut self, _ctx: &UnaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_cast_expression_label(&mut self, _ctx: &CastExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_cast_expression_label(&mut self, _ctx: &CastExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_object_creation_expression_label(&mut self, _ctx: &ObjectCreationExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_object_creation_expression_label(&mut self, _ctx: &ObjectCreationExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_binary_operator_expression_label(&mut self, _ctx: &BinaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_binary_operator_expression_label(&mut self, _ctx: &BinaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_instance_of_operator_expression_label(&mut self, _ctx: &InstanceOfOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_instance_of_operator_expression_label(&mut self, _ctx: &InstanceOfOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_ternary_expression_label(&mut self, _ctx: &TernaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_ternary_expression_label(&mut self, _ctx: &TernaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_expression_lambda_label(&mut self, _ctx: &ExpressionLambdaLabelContext) -> Result<(), E> { Ok(()) } - fn exit_expression_lambda_label(&mut self, _ctx: &ExpressionLambdaLabelContext) -> Result<(), E> { Ok(()) } - fn enter_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn exit_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn enter_component_pattern_list(&mut self, _ctx: &ComponentPatternListContext) -> Result<(), E> { Ok(()) } - fn exit_component_pattern_list(&mut self, _ctx: &ComponentPatternListContext) -> Result<(), E> { Ok(()) } - fn enter_component_pattern(&mut self, _ctx: &ComponentPatternContext) -> Result<(), E> { Ok(()) } - fn exit_component_pattern(&mut self, _ctx: &ComponentPatternContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_body(&mut self, _ctx: &LambdaBodyContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_body(&mut self, _ctx: &LambdaBodyContext) -> Result<(), E> { Ok(()) } - fn enter_primary(&mut self, _ctx: &PrimaryContext) -> Result<(), E> { Ok(()) } - fn exit_primary(&mut self, _ctx: &PrimaryContext) -> Result<(), E> { Ok(()) } - fn enter_switch_expression(&mut self, _ctx: &SwitchExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_switch_expression(&mut self, _ctx: &SwitchExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_switch_labeled_rule(&mut self, _ctx: &SwitchLabeledRuleContext) -> Result<(), E> { Ok(()) } - fn exit_switch_labeled_rule(&mut self, _ctx: &SwitchLabeledRuleContext) -> Result<(), E> { Ok(()) } - fn enter_guard(&mut self, _ctx: &GuardContext) -> Result<(), E> { Ok(()) } - fn exit_guard(&mut self, _ctx: &GuardContext) -> Result<(), E> { Ok(()) } - fn enter_case_pattern(&mut self, _ctx: &CasePatternContext) -> Result<(), E> { Ok(()) } - fn exit_case_pattern(&mut self, _ctx: &CasePatternContext) -> Result<(), E> { Ok(()) } - fn enter_switch_rule_outcome(&mut self, _ctx: &SwitchRuleOutcomeContext) -> Result<(), E> { Ok(()) } - fn exit_switch_rule_outcome(&mut self, _ctx: &SwitchRuleOutcomeContext) -> Result<(), E> { Ok(()) } - fn enter_class_or_interface_type(&mut self, _ctx: &ClassOrInterfaceTypeContext) -> Result<(), E> { Ok(()) } - fn exit_class_or_interface_type(&mut self, _ctx: &ClassOrInterfaceTypeContext) -> Result<(), E> { Ok(()) } - fn enter_creator(&mut self, _ctx: &CreatorContext) -> Result<(), E> { Ok(()) } - fn exit_creator(&mut self, _ctx: &CreatorContext) -> Result<(), E> { Ok(()) } - fn enter_created_name(&mut self, _ctx: &CreatedNameContext) -> Result<(), E> { Ok(()) } - fn exit_created_name(&mut self, _ctx: &CreatedNameContext) -> Result<(), E> { Ok(()) } - fn enter_inner_creator(&mut self, _ctx: &InnerCreatorContext) -> Result<(), E> { Ok(()) } - fn exit_inner_creator(&mut self, _ctx: &InnerCreatorContext) -> Result<(), E> { Ok(()) } - fn enter_array_creator_rest(&mut self, _ctx: &ArrayCreatorRestContext) -> Result<(), E> { Ok(()) } - fn exit_array_creator_rest(&mut self, _ctx: &ArrayCreatorRestContext) -> Result<(), E> { Ok(()) } - fn enter_class_creator_rest(&mut self, _ctx: &ClassCreatorRestContext) -> Result<(), E> { Ok(()) } - fn exit_class_creator_rest(&mut self, _ctx: &ClassCreatorRestContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_generic_invocation(&mut self, _ctx: &ExplicitGenericInvocationContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_generic_invocation(&mut self, _ctx: &ExplicitGenericInvocationContext) -> Result<(), E> { Ok(()) } - fn enter_type_arguments_or_diamond(&mut self, _ctx: &TypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn exit_type_arguments_or_diamond(&mut self, _ctx: &TypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn enter_non_wildcard_type_arguments_or_diamond(&mut self, _ctx: &NonWildcardTypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn exit_non_wildcard_type_arguments_or_diamond(&mut self, _ctx: &NonWildcardTypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn enter_non_wildcard_type_arguments(&mut self, _ctx: &NonWildcardTypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_non_wildcard_type_arguments(&mut self, _ctx: &NonWildcardTypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_type_list(&mut self, _ctx: &TypeListContext) -> Result<(), E> { Ok(()) } - fn exit_type_list(&mut self, _ctx: &TypeListContext) -> Result<(), E> { Ok(()) } - fn enter_type_type(&mut self, _ctx: &TypeTypeContext) -> Result<(), E> { Ok(()) } - fn exit_type_type(&mut self, _ctx: &TypeTypeContext) -> Result<(), E> { Ok(()) } - fn enter_primitive_type(&mut self, _ctx: &PrimitiveTypeContext) -> Result<(), E> { Ok(()) } - fn exit_primitive_type(&mut self, _ctx: &PrimitiveTypeContext) -> Result<(), E> { Ok(()) } - fn enter_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_super_suffix(&mut self, _ctx: &SuperSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_super_suffix(&mut self, _ctx: &SuperSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_generic_invocation_suffix(&mut self, _ctx: &ExplicitGenericInvocationSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_generic_invocation_suffix(&mut self, _ctx: &ExplicitGenericInvocationSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_arguments(&mut self, _ctx: &ArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_arguments(&mut self, _ctx: &ArgumentsContext) -> Result<(), E> { Ok(()) } - fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), E> { Ok(()) } - fn visit_error_node(&mut self, _node: &ErrorNode) -> Result<(), E> { Ok(()) } - fn output(&mut self) -> std::io::Stdout { std::io::stdout() } -} - -antlr4_runtime::__antlr4_rust_generated_walk_callbacks! { - callbacks: __JavaTreeWalkerCallbacks, - listener: JavaListener, - enter: |listener, context, invocation_states| { - listener.enter_every_rule(context)?; - match __context_kind(context) { - 0 => listener.enter_compilation_unit(&CompilationUnitContext::__from_listener_node(context, invocation_states))?, - 1 => listener.enter_modular_compulation_unit(&ModularCompulationUnitContext::__from_listener_node(context, invocation_states))?, - 2 => listener.enter_package_declaration(&PackageDeclarationContext::__from_listener_node(context, invocation_states))?, - 3 => listener.enter_import_declaration(&ImportDeclarationContext::__from_listener_node(context, invocation_states))?, - 4 => listener.enter_type_declaration(&TypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 5 => listener.enter_modifier(&ModifierContext::__from_listener_node(context, invocation_states))?, - 6 => listener.enter_class_or_interface_modifier(&ClassOrInterfaceModifierContext::__from_listener_node(context, invocation_states))?, - 7 => listener.enter_variable_modifier(&VariableModifierContext::__from_listener_node(context, invocation_states))?, - 8 => listener.enter_class_declaration(&ClassDeclarationContext::__from_listener_node(context, invocation_states))?, - 9 => listener.enter_type_parameters(&TypeParametersContext::__from_listener_node(context, invocation_states))?, - 10 => listener.enter_type_parameter(&TypeParameterContext::__from_listener_node(context, invocation_states))?, - 11 => listener.enter_type_bound(&TypeBoundContext::__from_listener_node(context, invocation_states))?, - 12 => listener.enter_enum_declaration(&EnumDeclarationContext::__from_listener_node(context, invocation_states))?, - 13 => listener.enter_enum_constants(&EnumConstantsContext::__from_listener_node(context, invocation_states))?, - 14 => listener.enter_enum_constant(&EnumConstantContext::__from_listener_node(context, invocation_states))?, - 15 => listener.enter_enum_body_declarations(&EnumBodyDeclarationsContext::__from_listener_node(context, invocation_states))?, - 16 => listener.enter_interface_declaration(&InterfaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 17 => listener.enter_class_body(&ClassBodyContext::__from_listener_node(context, invocation_states))?, - 18 => listener.enter_interface_body(&InterfaceBodyContext::__from_listener_node(context, invocation_states))?, - 19 => listener.enter_class_body_declaration(&ClassBodyDeclarationContext::__from_listener_node(context, invocation_states))?, - 20 => listener.enter_member_declaration(&MemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 21 => listener.enter_method_declaration(&MethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 22 => listener.enter_method_body(&MethodBodyContext::__from_listener_node(context, invocation_states))?, - 23 => listener.enter_type_type_or_void(&TypeTypeOrVoidContext::__from_listener_node(context, invocation_states))?, - 24 => listener.enter_generic_method_declaration(&GenericMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 25 => listener.enter_generic_constructor_declaration(&GenericConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 26 => listener.enter_constructor_declaration(&ConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 27 => listener.enter_compact_constructor_declaration(&CompactConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 28 => listener.enter_field_declaration(&FieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 29 => listener.enter_interface_body_declaration(&InterfaceBodyDeclarationContext::__from_listener_node(context, invocation_states))?, - 30 => listener.enter_interface_member_declaration(&InterfaceMemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 31 => listener.enter_const_declaration(&ConstDeclarationContext::__from_listener_node(context, invocation_states))?, - 32 => listener.enter_constant_declarator(&ConstantDeclaratorContext::__from_listener_node(context, invocation_states))?, - 33 => listener.enter_interface_method_declaration(&InterfaceMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 34 => listener.enter_interface_method_modifier(&InterfaceMethodModifierContext::__from_listener_node(context, invocation_states))?, - 35 => listener.enter_generic_interface_method_declaration(&GenericInterfaceMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 36 => listener.enter_interface_common_body_declaration(&InterfaceCommonBodyDeclarationContext::__from_listener_node(context, invocation_states))?, - 37 => listener.enter_variable_declarators(&VariableDeclaratorsContext::__from_listener_node(context, invocation_states))?, - 38 => listener.enter_variable_declarator(&VariableDeclaratorContext::__from_listener_node(context, invocation_states))?, - 39 => listener.enter_variable_declarator_id(&VariableDeclaratorIdContext::__from_listener_node(context, invocation_states))?, - 40 => listener.enter_variable_initializer(&VariableInitializerContext::__from_listener_node(context, invocation_states))?, - 41 => listener.enter_array_initializer(&ArrayInitializerContext::__from_listener_node(context, invocation_states))?, - 42 => listener.enter_class_type(&ClassTypeContext::__from_listener_node(context, invocation_states))?, - 43 => listener.enter_package_name(&PackageNameContext::__from_listener_node(context, invocation_states))?, - 44 => listener.enter_type_argument(&TypeArgumentContext::__from_listener_node(context, invocation_states))?, - 45 => listener.enter_qualified_name_list(&QualifiedNameListContext::__from_listener_node(context, invocation_states))?, - 46 => listener.enter_formal_parameters(&FormalParametersContext::__from_listener_node(context, invocation_states))?, - 47 => listener.enter_receiver_parameter(&ReceiverParameterContext::__from_listener_node(context, invocation_states))?, - 48 => listener.enter_formal_parameter_list(&FormalParameterListContext::__from_listener_node(context, invocation_states))?, - 49 => listener.enter_formal_parameter(&FormalParameterContext::__from_listener_node(context, invocation_states))?, - 50 => listener.enter_lambda_lvti_list(&LambdaLvtiListContext::__from_listener_node(context, invocation_states))?, - 51 => listener.enter_lambda_lvti_parameter(&LambdaLvtiParameterContext::__from_listener_node(context, invocation_states))?, - 52 => listener.enter_qualified_name(&QualifiedNameContext::__from_listener_node(context, invocation_states))?, - 53 => listener.enter_literal(&LiteralContext::__from_listener_node(context, invocation_states))?, - 54 => listener.enter_integer_literal(&IntegerLiteralContext::__from_listener_node(context, invocation_states))?, - 55 => listener.enter_float_literal(&FloatLiteralContext::__from_listener_node(context, invocation_states))?, - 56 => listener.enter_annotation(&AnnotationContext::__from_listener_node(context, invocation_states))?, - 57 => listener.enter_annotation_field_values(&AnnotationFieldValuesContext::__from_listener_node(context, invocation_states))?, - 58 => listener.enter_annotation_field_value(&AnnotationFieldValueContext::__from_listener_node(context, invocation_states))?, - 59 => listener.enter_annotation_value(&AnnotationValueContext::__from_listener_node(context, invocation_states))?, - 60 => listener.enter_element_value(&ElementValueContext::__from_listener_node(context, invocation_states))?, - 61 => listener.enter_element_value_array_initializer(&ElementValueArrayInitializerContext::__from_listener_node(context, invocation_states))?, - 62 => listener.enter_annotation_type_declaration(&AnnotationTypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 63 => listener.enter_annotation_type_body(&AnnotationTypeBodyContext::__from_listener_node(context, invocation_states))?, - 64 => listener.enter_annotation_type_element_declaration(&AnnotationTypeElementDeclarationContext::__from_listener_node(context, invocation_states))?, - 65 => listener.enter_annotation_type_element_rest(&AnnotationTypeElementRestContext::__from_listener_node(context, invocation_states))?, - 66 => listener.enter_annotation_method_or_constant_rest(&AnnotationMethodOrConstantRestContext::__from_listener_node(context, invocation_states))?, - 67 => listener.enter_annotation_method_rest(&AnnotationMethodRestContext::__from_listener_node(context, invocation_states))?, - 68 => listener.enter_annotation_constant_rest(&AnnotationConstantRestContext::__from_listener_node(context, invocation_states))?, - 69 => listener.enter_default_value(&DefaultValueContext::__from_listener_node(context, invocation_states))?, - 70 => listener.enter_module_declaration(&ModuleDeclarationContext::__from_listener_node(context, invocation_states))?, - 71 => listener.enter_module_directive(&ModuleDirectiveContext::__from_listener_node(context, invocation_states))?, - 72 => listener.enter_requires_modifier(&RequiresModifierContext::__from_listener_node(context, invocation_states))?, - 73 => listener.enter_record_declaration(&RecordDeclarationContext::__from_listener_node(context, invocation_states))?, - 74 => listener.enter_record_header(&RecordHeaderContext::__from_listener_node(context, invocation_states))?, - 75 => listener.enter_record_component_list(&RecordComponentListContext::__from_listener_node(context, invocation_states))?, - 76 => listener.enter_record_component(&RecordComponentContext::__from_listener_node(context, invocation_states))?, - 77 => listener.enter_record_body(&RecordBodyContext::__from_listener_node(context, invocation_states))?, - 78 => listener.enter_block(&BlockContext::__from_listener_node(context, invocation_states))?, - 79 => listener.enter_block_statement(&BlockStatementContext::__from_listener_node(context, invocation_states))?, - 80 => listener.enter_local_variable_declaration(&LocalVariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 81 => listener.enter_identifier(&IdentifierContext::__from_listener_node(context, invocation_states))?, - 82 => listener.enter_type_identifier(&TypeIdentifierContext::__from_listener_node(context, invocation_states))?, - 83 => listener.enter_local_type_declaration(&LocalTypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 84 => listener.enter_statement(&StatementContext::__from_listener_node(context, invocation_states))?, - 85 => listener.enter_catch_clause(&CatchClauseContext::__from_listener_node(context, invocation_states))?, - 86 => listener.enter_catch_type(&CatchTypeContext::__from_listener_node(context, invocation_states))?, - 87 => listener.enter_finally_block(&FinallyBlockContext::__from_listener_node(context, invocation_states))?, - 88 => listener.enter_resource_specification(&ResourceSpecificationContext::__from_listener_node(context, invocation_states))?, - 89 => listener.enter_resources(&ResourcesContext::__from_listener_node(context, invocation_states))?, - 90 => listener.enter_resource(&ResourceContext::__from_listener_node(context, invocation_states))?, - 91 => listener.enter_switch_block_statement_group(&SwitchBlockStatementGroupContext::__from_listener_node(context, invocation_states))?, - 92 => listener.enter_switch_label(&SwitchLabelContext::__from_listener_node(context, invocation_states))?, - 93 => listener.enter_for_control(&ForControlContext::__from_listener_node(context, invocation_states))?, - 94 => listener.enter_for_init(&ForInitContext::__from_listener_node(context, invocation_states))?, - 95 => listener.enter_enhanced_for_control(&EnhancedForControlContext::__from_listener_node(context, invocation_states))?, - 96 => listener.enter_expression_list(&ExpressionListContext::__from_listener_node(context, invocation_states))?, - 97 => listener.enter_method_call(&MethodCallContext::__from_listener_node(context, invocation_states))?, - 98 => listener.enter_expression(&ExpressionContext::__from_listener_node(context, invocation_states))?, - 99 => listener.enter_primary_expression_label(&PrimaryExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 100 => listener.enter_square_bracket_expression_label(&SquareBracketExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 101 => listener.enter_member_reference_expression_label(&MemberReferenceExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 102 => listener.enter_method_call_expression_label(&MethodCallExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 103 => listener.enter_method_reference_expression_label(&MethodReferenceExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 104 => listener.enter_expression_switch_label(&ExpressionSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 105 => listener.enter_post_increment_decrement_operator_expression_label(&PostIncrementDecrementOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 106 => listener.enter_unary_operator_expression_label(&UnaryOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 107 => listener.enter_cast_expression_label(&CastExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 108 => listener.enter_object_creation_expression_label(&ObjectCreationExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 109 => listener.enter_binary_operator_expression_label(&BinaryOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 110 => listener.enter_instance_of_operator_expression_label(&InstanceOfOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 111 => listener.enter_ternary_expression_label(&TernaryExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 112 => listener.enter_expression_lambda_label(&ExpressionLambdaLabelContext::__from_listener_node(context, invocation_states))?, - 113 => listener.enter_pattern(&PatternContext::__from_listener_node(context, invocation_states))?, - 114 => listener.enter_component_pattern_list(&ComponentPatternListContext::__from_listener_node(context, invocation_states))?, - 115 => listener.enter_component_pattern(&ComponentPatternContext::__from_listener_node(context, invocation_states))?, - 116 => listener.enter_lambda_expression(&LambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 117 => listener.enter_lambda_parameters(&LambdaParametersContext::__from_listener_node(context, invocation_states))?, - 118 => listener.enter_lambda_body(&LambdaBodyContext::__from_listener_node(context, invocation_states))?, - 119 => listener.enter_primary(&PrimaryContext::__from_listener_node(context, invocation_states))?, - 120 => listener.enter_switch_expression(&SwitchExpressionContext::__from_listener_node(context, invocation_states))?, - 121 => listener.enter_switch_labeled_rule(&SwitchLabeledRuleContext::__from_listener_node(context, invocation_states))?, - 122 => listener.enter_guard(&GuardContext::__from_listener_node(context, invocation_states))?, - 123 => listener.enter_case_pattern(&CasePatternContext::__from_listener_node(context, invocation_states))?, - 124 => listener.enter_switch_rule_outcome(&SwitchRuleOutcomeContext::__from_listener_node(context, invocation_states))?, - 125 => listener.enter_class_or_interface_type(&ClassOrInterfaceTypeContext::__from_listener_node(context, invocation_states))?, - 126 => listener.enter_creator(&CreatorContext::__from_listener_node(context, invocation_states))?, - 127 => listener.enter_created_name(&CreatedNameContext::__from_listener_node(context, invocation_states))?, - 128 => listener.enter_inner_creator(&InnerCreatorContext::__from_listener_node(context, invocation_states))?, - 129 => listener.enter_array_creator_rest(&ArrayCreatorRestContext::__from_listener_node(context, invocation_states))?, - 130 => listener.enter_class_creator_rest(&ClassCreatorRestContext::__from_listener_node(context, invocation_states))?, - 131 => listener.enter_explicit_generic_invocation(&ExplicitGenericInvocationContext::__from_listener_node(context, invocation_states))?, - 132 => listener.enter_type_arguments_or_diamond(&TypeArgumentsOrDiamondContext::__from_listener_node(context, invocation_states))?, - 133 => listener.enter_non_wildcard_type_arguments_or_diamond(&NonWildcardTypeArgumentsOrDiamondContext::__from_listener_node(context, invocation_states))?, - 134 => listener.enter_non_wildcard_type_arguments(&NonWildcardTypeArgumentsContext::__from_listener_node(context, invocation_states))?, - 135 => listener.enter_type_list(&TypeListContext::__from_listener_node(context, invocation_states))?, - 136 => listener.enter_type_type(&TypeTypeContext::__from_listener_node(context, invocation_states))?, - 137 => listener.enter_primitive_type(&PrimitiveTypeContext::__from_listener_node(context, invocation_states))?, - 138 => listener.enter_type_arguments(&TypeArgumentsContext::__from_listener_node(context, invocation_states))?, - 139 => listener.enter_super_suffix(&SuperSuffixContext::__from_listener_node(context, invocation_states))?, - 140 => listener.enter_explicit_generic_invocation_suffix(&ExplicitGenericInvocationSuffixContext::__from_listener_node(context, invocation_states))?, - 141 => listener.enter_arguments(&ArgumentsContext::__from_listener_node(context, invocation_states))?, - _ => {} - } - Ok(()) - }, - exit: |listener, context, invocation_states| { - match __context_kind(context) { - 0 => listener.exit_compilation_unit(&CompilationUnitContext::__from_listener_node(context, invocation_states))?, - 1 => listener.exit_modular_compulation_unit(&ModularCompulationUnitContext::__from_listener_node(context, invocation_states))?, - 2 => listener.exit_package_declaration(&PackageDeclarationContext::__from_listener_node(context, invocation_states))?, - 3 => listener.exit_import_declaration(&ImportDeclarationContext::__from_listener_node(context, invocation_states))?, - 4 => listener.exit_type_declaration(&TypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 5 => listener.exit_modifier(&ModifierContext::__from_listener_node(context, invocation_states))?, - 6 => listener.exit_class_or_interface_modifier(&ClassOrInterfaceModifierContext::__from_listener_node(context, invocation_states))?, - 7 => listener.exit_variable_modifier(&VariableModifierContext::__from_listener_node(context, invocation_states))?, - 8 => listener.exit_class_declaration(&ClassDeclarationContext::__from_listener_node(context, invocation_states))?, - 9 => listener.exit_type_parameters(&TypeParametersContext::__from_listener_node(context, invocation_states))?, - 10 => listener.exit_type_parameter(&TypeParameterContext::__from_listener_node(context, invocation_states))?, - 11 => listener.exit_type_bound(&TypeBoundContext::__from_listener_node(context, invocation_states))?, - 12 => listener.exit_enum_declaration(&EnumDeclarationContext::__from_listener_node(context, invocation_states))?, - 13 => listener.exit_enum_constants(&EnumConstantsContext::__from_listener_node(context, invocation_states))?, - 14 => listener.exit_enum_constant(&EnumConstantContext::__from_listener_node(context, invocation_states))?, - 15 => listener.exit_enum_body_declarations(&EnumBodyDeclarationsContext::__from_listener_node(context, invocation_states))?, - 16 => listener.exit_interface_declaration(&InterfaceDeclarationContext::__from_listener_node(context, invocation_states))?, - 17 => listener.exit_class_body(&ClassBodyContext::__from_listener_node(context, invocation_states))?, - 18 => listener.exit_interface_body(&InterfaceBodyContext::__from_listener_node(context, invocation_states))?, - 19 => listener.exit_class_body_declaration(&ClassBodyDeclarationContext::__from_listener_node(context, invocation_states))?, - 20 => listener.exit_member_declaration(&MemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 21 => listener.exit_method_declaration(&MethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 22 => listener.exit_method_body(&MethodBodyContext::__from_listener_node(context, invocation_states))?, - 23 => listener.exit_type_type_or_void(&TypeTypeOrVoidContext::__from_listener_node(context, invocation_states))?, - 24 => listener.exit_generic_method_declaration(&GenericMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 25 => listener.exit_generic_constructor_declaration(&GenericConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 26 => listener.exit_constructor_declaration(&ConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 27 => listener.exit_compact_constructor_declaration(&CompactConstructorDeclarationContext::__from_listener_node(context, invocation_states))?, - 28 => listener.exit_field_declaration(&FieldDeclarationContext::__from_listener_node(context, invocation_states))?, - 29 => listener.exit_interface_body_declaration(&InterfaceBodyDeclarationContext::__from_listener_node(context, invocation_states))?, - 30 => listener.exit_interface_member_declaration(&InterfaceMemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 31 => listener.exit_const_declaration(&ConstDeclarationContext::__from_listener_node(context, invocation_states))?, - 32 => listener.exit_constant_declarator(&ConstantDeclaratorContext::__from_listener_node(context, invocation_states))?, - 33 => listener.exit_interface_method_declaration(&InterfaceMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 34 => listener.exit_interface_method_modifier(&InterfaceMethodModifierContext::__from_listener_node(context, invocation_states))?, - 35 => listener.exit_generic_interface_method_declaration(&GenericInterfaceMethodDeclarationContext::__from_listener_node(context, invocation_states))?, - 36 => listener.exit_interface_common_body_declaration(&InterfaceCommonBodyDeclarationContext::__from_listener_node(context, invocation_states))?, - 37 => listener.exit_variable_declarators(&VariableDeclaratorsContext::__from_listener_node(context, invocation_states))?, - 38 => listener.exit_variable_declarator(&VariableDeclaratorContext::__from_listener_node(context, invocation_states))?, - 39 => listener.exit_variable_declarator_id(&VariableDeclaratorIdContext::__from_listener_node(context, invocation_states))?, - 40 => listener.exit_variable_initializer(&VariableInitializerContext::__from_listener_node(context, invocation_states))?, - 41 => listener.exit_array_initializer(&ArrayInitializerContext::__from_listener_node(context, invocation_states))?, - 42 => listener.exit_class_type(&ClassTypeContext::__from_listener_node(context, invocation_states))?, - 43 => listener.exit_package_name(&PackageNameContext::__from_listener_node(context, invocation_states))?, - 44 => listener.exit_type_argument(&TypeArgumentContext::__from_listener_node(context, invocation_states))?, - 45 => listener.exit_qualified_name_list(&QualifiedNameListContext::__from_listener_node(context, invocation_states))?, - 46 => listener.exit_formal_parameters(&FormalParametersContext::__from_listener_node(context, invocation_states))?, - 47 => listener.exit_receiver_parameter(&ReceiverParameterContext::__from_listener_node(context, invocation_states))?, - 48 => listener.exit_formal_parameter_list(&FormalParameterListContext::__from_listener_node(context, invocation_states))?, - 49 => listener.exit_formal_parameter(&FormalParameterContext::__from_listener_node(context, invocation_states))?, - 50 => listener.exit_lambda_lvti_list(&LambdaLvtiListContext::__from_listener_node(context, invocation_states))?, - 51 => listener.exit_lambda_lvti_parameter(&LambdaLvtiParameterContext::__from_listener_node(context, invocation_states))?, - 52 => listener.exit_qualified_name(&QualifiedNameContext::__from_listener_node(context, invocation_states))?, - 53 => listener.exit_literal(&LiteralContext::__from_listener_node(context, invocation_states))?, - 54 => listener.exit_integer_literal(&IntegerLiteralContext::__from_listener_node(context, invocation_states))?, - 55 => listener.exit_float_literal(&FloatLiteralContext::__from_listener_node(context, invocation_states))?, - 56 => listener.exit_annotation(&AnnotationContext::__from_listener_node(context, invocation_states))?, - 57 => listener.exit_annotation_field_values(&AnnotationFieldValuesContext::__from_listener_node(context, invocation_states))?, - 58 => listener.exit_annotation_field_value(&AnnotationFieldValueContext::__from_listener_node(context, invocation_states))?, - 59 => listener.exit_annotation_value(&AnnotationValueContext::__from_listener_node(context, invocation_states))?, - 60 => listener.exit_element_value(&ElementValueContext::__from_listener_node(context, invocation_states))?, - 61 => listener.exit_element_value_array_initializer(&ElementValueArrayInitializerContext::__from_listener_node(context, invocation_states))?, - 62 => listener.exit_annotation_type_declaration(&AnnotationTypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 63 => listener.exit_annotation_type_body(&AnnotationTypeBodyContext::__from_listener_node(context, invocation_states))?, - 64 => listener.exit_annotation_type_element_declaration(&AnnotationTypeElementDeclarationContext::__from_listener_node(context, invocation_states))?, - 65 => listener.exit_annotation_type_element_rest(&AnnotationTypeElementRestContext::__from_listener_node(context, invocation_states))?, - 66 => listener.exit_annotation_method_or_constant_rest(&AnnotationMethodOrConstantRestContext::__from_listener_node(context, invocation_states))?, - 67 => listener.exit_annotation_method_rest(&AnnotationMethodRestContext::__from_listener_node(context, invocation_states))?, - 68 => listener.exit_annotation_constant_rest(&AnnotationConstantRestContext::__from_listener_node(context, invocation_states))?, - 69 => listener.exit_default_value(&DefaultValueContext::__from_listener_node(context, invocation_states))?, - 70 => listener.exit_module_declaration(&ModuleDeclarationContext::__from_listener_node(context, invocation_states))?, - 71 => listener.exit_module_directive(&ModuleDirectiveContext::__from_listener_node(context, invocation_states))?, - 72 => listener.exit_requires_modifier(&RequiresModifierContext::__from_listener_node(context, invocation_states))?, - 73 => listener.exit_record_declaration(&RecordDeclarationContext::__from_listener_node(context, invocation_states))?, - 74 => listener.exit_record_header(&RecordHeaderContext::__from_listener_node(context, invocation_states))?, - 75 => listener.exit_record_component_list(&RecordComponentListContext::__from_listener_node(context, invocation_states))?, - 76 => listener.exit_record_component(&RecordComponentContext::__from_listener_node(context, invocation_states))?, - 77 => listener.exit_record_body(&RecordBodyContext::__from_listener_node(context, invocation_states))?, - 78 => listener.exit_block(&BlockContext::__from_listener_node(context, invocation_states))?, - 79 => listener.exit_block_statement(&BlockStatementContext::__from_listener_node(context, invocation_states))?, - 80 => listener.exit_local_variable_declaration(&LocalVariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 81 => listener.exit_identifier(&IdentifierContext::__from_listener_node(context, invocation_states))?, - 82 => listener.exit_type_identifier(&TypeIdentifierContext::__from_listener_node(context, invocation_states))?, - 83 => listener.exit_local_type_declaration(&LocalTypeDeclarationContext::__from_listener_node(context, invocation_states))?, - 84 => listener.exit_statement(&StatementContext::__from_listener_node(context, invocation_states))?, - 85 => listener.exit_catch_clause(&CatchClauseContext::__from_listener_node(context, invocation_states))?, - 86 => listener.exit_catch_type(&CatchTypeContext::__from_listener_node(context, invocation_states))?, - 87 => listener.exit_finally_block(&FinallyBlockContext::__from_listener_node(context, invocation_states))?, - 88 => listener.exit_resource_specification(&ResourceSpecificationContext::__from_listener_node(context, invocation_states))?, - 89 => listener.exit_resources(&ResourcesContext::__from_listener_node(context, invocation_states))?, - 90 => listener.exit_resource(&ResourceContext::__from_listener_node(context, invocation_states))?, - 91 => listener.exit_switch_block_statement_group(&SwitchBlockStatementGroupContext::__from_listener_node(context, invocation_states))?, - 92 => listener.exit_switch_label(&SwitchLabelContext::__from_listener_node(context, invocation_states))?, - 93 => listener.exit_for_control(&ForControlContext::__from_listener_node(context, invocation_states))?, - 94 => listener.exit_for_init(&ForInitContext::__from_listener_node(context, invocation_states))?, - 95 => listener.exit_enhanced_for_control(&EnhancedForControlContext::__from_listener_node(context, invocation_states))?, - 96 => listener.exit_expression_list(&ExpressionListContext::__from_listener_node(context, invocation_states))?, - 97 => listener.exit_method_call(&MethodCallContext::__from_listener_node(context, invocation_states))?, - 98 => listener.exit_expression(&ExpressionContext::__from_listener_node(context, invocation_states))?, - 99 => listener.exit_primary_expression_label(&PrimaryExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 100 => listener.exit_square_bracket_expression_label(&SquareBracketExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 101 => listener.exit_member_reference_expression_label(&MemberReferenceExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 102 => listener.exit_method_call_expression_label(&MethodCallExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 103 => listener.exit_method_reference_expression_label(&MethodReferenceExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 104 => listener.exit_expression_switch_label(&ExpressionSwitchLabelContext::__from_listener_node(context, invocation_states))?, - 105 => listener.exit_post_increment_decrement_operator_expression_label(&PostIncrementDecrementOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 106 => listener.exit_unary_operator_expression_label(&UnaryOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 107 => listener.exit_cast_expression_label(&CastExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 108 => listener.exit_object_creation_expression_label(&ObjectCreationExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 109 => listener.exit_binary_operator_expression_label(&BinaryOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 110 => listener.exit_instance_of_operator_expression_label(&InstanceOfOperatorExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 111 => listener.exit_ternary_expression_label(&TernaryExpressionLabelContext::__from_listener_node(context, invocation_states))?, - 112 => listener.exit_expression_lambda_label(&ExpressionLambdaLabelContext::__from_listener_node(context, invocation_states))?, - 113 => listener.exit_pattern(&PatternContext::__from_listener_node(context, invocation_states))?, - 114 => listener.exit_component_pattern_list(&ComponentPatternListContext::__from_listener_node(context, invocation_states))?, - 115 => listener.exit_component_pattern(&ComponentPatternContext::__from_listener_node(context, invocation_states))?, - 116 => listener.exit_lambda_expression(&LambdaExpressionContext::__from_listener_node(context, invocation_states))?, - 117 => listener.exit_lambda_parameters(&LambdaParametersContext::__from_listener_node(context, invocation_states))?, - 118 => listener.exit_lambda_body(&LambdaBodyContext::__from_listener_node(context, invocation_states))?, - 119 => listener.exit_primary(&PrimaryContext::__from_listener_node(context, invocation_states))?, - 120 => listener.exit_switch_expression(&SwitchExpressionContext::__from_listener_node(context, invocation_states))?, - 121 => listener.exit_switch_labeled_rule(&SwitchLabeledRuleContext::__from_listener_node(context, invocation_states))?, - 122 => listener.exit_guard(&GuardContext::__from_listener_node(context, invocation_states))?, - 123 => listener.exit_case_pattern(&CasePatternContext::__from_listener_node(context, invocation_states))?, - 124 => listener.exit_switch_rule_outcome(&SwitchRuleOutcomeContext::__from_listener_node(context, invocation_states))?, - 125 => listener.exit_class_or_interface_type(&ClassOrInterfaceTypeContext::__from_listener_node(context, invocation_states))?, - 126 => listener.exit_creator(&CreatorContext::__from_listener_node(context, invocation_states))?, - 127 => listener.exit_created_name(&CreatedNameContext::__from_listener_node(context, invocation_states))?, - 128 => listener.exit_inner_creator(&InnerCreatorContext::__from_listener_node(context, invocation_states))?, - 129 => listener.exit_array_creator_rest(&ArrayCreatorRestContext::__from_listener_node(context, invocation_states))?, - 130 => listener.exit_class_creator_rest(&ClassCreatorRestContext::__from_listener_node(context, invocation_states))?, - 131 => listener.exit_explicit_generic_invocation(&ExplicitGenericInvocationContext::__from_listener_node(context, invocation_states))?, - 132 => listener.exit_type_arguments_or_diamond(&TypeArgumentsOrDiamondContext::__from_listener_node(context, invocation_states))?, - 133 => listener.exit_non_wildcard_type_arguments_or_diamond(&NonWildcardTypeArgumentsOrDiamondContext::__from_listener_node(context, invocation_states))?, - 134 => listener.exit_non_wildcard_type_arguments(&NonWildcardTypeArgumentsContext::__from_listener_node(context, invocation_states))?, - 135 => listener.exit_type_list(&TypeListContext::__from_listener_node(context, invocation_states))?, - 136 => listener.exit_type_type(&TypeTypeContext::__from_listener_node(context, invocation_states))?, - 137 => listener.exit_primitive_type(&PrimitiveTypeContext::__from_listener_node(context, invocation_states))?, - 138 => listener.exit_type_arguments(&TypeArgumentsContext::__from_listener_node(context, invocation_states))?, - 139 => listener.exit_super_suffix(&SuperSuffixContext::__from_listener_node(context, invocation_states))?, - 140 => listener.exit_explicit_generic_invocation_suffix(&ExplicitGenericInvocationSuffixContext::__from_listener_node(context, invocation_states))?, - 141 => listener.exit_arguments(&ArgumentsContext::__from_listener_node(context, invocation_states))?, - _ => {} - } - listener.exit_every_rule(context) - }, - terminal: |listener, node| { - listener.visit_terminal(&TerminalNode::new(node)) - }, - error: |listener, node| { - listener.visit_error_node(&ErrorNode::new(node)) - }, -} - -#[allow(dead_code)] -pub struct JavaTreeWalker; - -#[allow(dead_code)] -impl JavaTreeWalker { - pub fn walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - ) -> Result<(), E> { - Self::__walk(listener, tree, None) - } - - pub fn walk_with_invocation_states>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - parent_invocation_states: Vec, - ) -> Result<(), E> { - Self::__walk(listener, tree, Some(parent_invocation_states)) - } - - fn __walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - invocation_states: Option>, - ) -> Result<(), E> { - let mut callbacks = __JavaTreeWalkerCallbacks(listener); - antlr4_runtime::generated::walk_generated(tree, invocation_states, &mut callbacks) - } -} - -pub type ParseTreeWalker = JavaTreeWalker; - -#[allow(dead_code, unused_variables)] -pub trait JavaValidatedListener { - fn walk(&mut self, tree: ValidatedRuleNode<'_>) -> Result<(), E> - where - Self: Sized, - { - JavaValidatedTreeWalker::walk(self, tree) - } - - fn enter_every_rule(&mut self, _ctx: ValidatedRuleNode<'_>) -> Result<(), E> { Ok(()) } - fn exit_every_rule(&mut self, _ctx: ValidatedRuleNode<'_>) -> Result<(), E> { Ok(()) } - - fn enter_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn exit_compilation_unit(&mut self, _ctx: &CompilationUnitContext) -> Result<(), E> { Ok(()) } - fn enter_modular_compulation_unit(&mut self, _ctx: &ModularCompulationUnitContext) -> Result<(), E> { Ok(()) } - fn exit_modular_compulation_unit(&mut self, _ctx: &ModularCompulationUnitContext) -> Result<(), E> { Ok(()) } - fn enter_package_declaration(&mut self, _ctx: &PackageDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_package_declaration(&mut self, _ctx: &PackageDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_import_declaration(&mut self, _ctx: &ImportDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_import_declaration(&mut self, _ctx: &ImportDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_type_declaration(&mut self, _ctx: &TypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn exit_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn enter_class_or_interface_modifier(&mut self, _ctx: &ClassOrInterfaceModifierContext) -> Result<(), E> { Ok(()) } - fn exit_class_or_interface_modifier(&mut self, _ctx: &ClassOrInterfaceModifierContext) -> Result<(), E> { Ok(()) } - fn enter_variable_modifier(&mut self, _ctx: &VariableModifierContext) -> Result<(), E> { Ok(()) } - fn exit_variable_modifier(&mut self, _ctx: &VariableModifierContext) -> Result<(), E> { Ok(()) } - fn enter_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn enter_type_bound(&mut self, _ctx: &TypeBoundContext) -> Result<(), E> { Ok(()) } - fn exit_type_bound(&mut self, _ctx: &TypeBoundContext) -> Result<(), E> { Ok(()) } - fn enter_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_enum_declaration(&mut self, _ctx: &EnumDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_enum_constants(&mut self, _ctx: &EnumConstantsContext) -> Result<(), E> { Ok(()) } - fn exit_enum_constants(&mut self, _ctx: &EnumConstantsContext) -> Result<(), E> { Ok(()) } - fn enter_enum_constant(&mut self, _ctx: &EnumConstantContext) -> Result<(), E> { Ok(()) } - fn exit_enum_constant(&mut self, _ctx: &EnumConstantContext) -> Result<(), E> { Ok(()) } - fn enter_enum_body_declarations(&mut self, _ctx: &EnumBodyDeclarationsContext) -> Result<(), E> { Ok(()) } - fn exit_enum_body_declarations(&mut self, _ctx: &EnumBodyDeclarationsContext) -> Result<(), E> { Ok(()) } - fn enter_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_declaration(&mut self, _ctx: &InterfaceDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn exit_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn enter_interface_body(&mut self, _ctx: &InterfaceBodyContext) -> Result<(), E> { Ok(()) } - fn exit_interface_body(&mut self, _ctx: &InterfaceBodyContext) -> Result<(), E> { Ok(()) } - fn enter_class_body_declaration(&mut self, _ctx: &ClassBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_body_declaration(&mut self, _ctx: &ClassBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_member_declaration(&mut self, _ctx: &MemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_method_declaration(&mut self, _ctx: &MethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_method_body(&mut self, _ctx: &MethodBodyContext) -> Result<(), E> { Ok(()) } - fn exit_method_body(&mut self, _ctx: &MethodBodyContext) -> Result<(), E> { Ok(()) } - fn enter_type_type_or_void(&mut self, _ctx: &TypeTypeOrVoidContext) -> Result<(), E> { Ok(()) } - fn exit_type_type_or_void(&mut self, _ctx: &TypeTypeOrVoidContext) -> Result<(), E> { Ok(()) } - fn enter_generic_method_declaration(&mut self, _ctx: &GenericMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_generic_method_declaration(&mut self, _ctx: &GenericMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_generic_constructor_declaration(&mut self, _ctx: &GenericConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_generic_constructor_declaration(&mut self, _ctx: &GenericConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_declaration(&mut self, _ctx: &ConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_compact_constructor_declaration(&mut self, _ctx: &CompactConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_compact_constructor_declaration(&mut self, _ctx: &CompactConstructorDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_field_declaration(&mut self, _ctx: &FieldDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_body_declaration(&mut self, _ctx: &InterfaceBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_body_declaration(&mut self, _ctx: &InterfaceBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_member_declaration(&mut self, _ctx: &InterfaceMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_member_declaration(&mut self, _ctx: &InterfaceMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_const_declaration(&mut self, _ctx: &ConstDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_const_declaration(&mut self, _ctx: &ConstDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_constant_declarator(&mut self, _ctx: &ConstantDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_constant_declarator(&mut self, _ctx: &ConstantDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_interface_method_declaration(&mut self, _ctx: &InterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_method_declaration(&mut self, _ctx: &InterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_method_modifier(&mut self, _ctx: &InterfaceMethodModifierContext) -> Result<(), E> { Ok(()) } - fn exit_interface_method_modifier(&mut self, _ctx: &InterfaceMethodModifierContext) -> Result<(), E> { Ok(()) } - fn enter_generic_interface_method_declaration(&mut self, _ctx: &GenericInterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_generic_interface_method_declaration(&mut self, _ctx: &GenericInterfaceMethodDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_interface_common_body_declaration(&mut self, _ctx: &InterfaceCommonBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_interface_common_body_declaration(&mut self, _ctx: &InterfaceCommonBodyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarators(&mut self, _ctx: &VariableDeclaratorsContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarators(&mut self, _ctx: &VariableDeclaratorsContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarator(&mut self, _ctx: &VariableDeclaratorContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declarator_id(&mut self, _ctx: &VariableDeclaratorIdContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declarator_id(&mut self, _ctx: &VariableDeclaratorIdContext) -> Result<(), E> { Ok(()) } - fn enter_variable_initializer(&mut self, _ctx: &VariableInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_variable_initializer(&mut self, _ctx: &VariableInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_array_initializer(&mut self, _ctx: &ArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_array_initializer(&mut self, _ctx: &ArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_class_type(&mut self, _ctx: &ClassTypeContext) -> Result<(), E> { Ok(()) } - fn exit_class_type(&mut self, _ctx: &ClassTypeContext) -> Result<(), E> { Ok(()) } - fn enter_package_name(&mut self, _ctx: &PackageNameContext) -> Result<(), E> { Ok(()) } - fn exit_package_name(&mut self, _ctx: &PackageNameContext) -> Result<(), E> { Ok(()) } - fn enter_type_argument(&mut self, _ctx: &TypeArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_type_argument(&mut self, _ctx: &TypeArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_qualified_name_list(&mut self, _ctx: &QualifiedNameListContext) -> Result<(), E> { Ok(()) } - fn exit_qualified_name_list(&mut self, _ctx: &QualifiedNameListContext) -> Result<(), E> { Ok(()) } - fn enter_formal_parameters(&mut self, _ctx: &FormalParametersContext) -> Result<(), E> { Ok(()) } - fn exit_formal_parameters(&mut self, _ctx: &FormalParametersContext) -> Result<(), E> { Ok(()) } - fn enter_receiver_parameter(&mut self, _ctx: &ReceiverParameterContext) -> Result<(), E> { Ok(()) } - fn exit_receiver_parameter(&mut self, _ctx: &ReceiverParameterContext) -> Result<(), E> { Ok(()) } - fn enter_formal_parameter_list(&mut self, _ctx: &FormalParameterListContext) -> Result<(), E> { Ok(()) } - fn exit_formal_parameter_list(&mut self, _ctx: &FormalParameterListContext) -> Result<(), E> { Ok(()) } - fn enter_formal_parameter(&mut self, _ctx: &FormalParameterContext) -> Result<(), E> { Ok(()) } - fn exit_formal_parameter(&mut self, _ctx: &FormalParameterContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_lvti_list(&mut self, _ctx: &LambdaLvtiListContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_lvti_list(&mut self, _ctx: &LambdaLvtiListContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_lvti_parameter(&mut self, _ctx: &LambdaLvtiParameterContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_lvti_parameter(&mut self, _ctx: &LambdaLvtiParameterContext) -> Result<(), E> { Ok(()) } - fn enter_qualified_name(&mut self, _ctx: &QualifiedNameContext) -> Result<(), E> { Ok(()) } - fn exit_qualified_name(&mut self, _ctx: &QualifiedNameContext) -> Result<(), E> { Ok(()) } - fn enter_literal(&mut self, _ctx: &LiteralContext) -> Result<(), E> { Ok(()) } - fn exit_literal(&mut self, _ctx: &LiteralContext) -> Result<(), E> { Ok(()) } - fn enter_integer_literal(&mut self, _ctx: &IntegerLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_integer_literal(&mut self, _ctx: &IntegerLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_float_literal(&mut self, _ctx: &FloatLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_float_literal(&mut self, _ctx: &FloatLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_field_values(&mut self, _ctx: &AnnotationFieldValuesContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_field_values(&mut self, _ctx: &AnnotationFieldValuesContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_field_value(&mut self, _ctx: &AnnotationFieldValueContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_field_value(&mut self, _ctx: &AnnotationFieldValueContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_value(&mut self, _ctx: &AnnotationValueContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_value(&mut self, _ctx: &AnnotationValueContext) -> Result<(), E> { Ok(()) } - fn enter_element_value(&mut self, _ctx: &ElementValueContext) -> Result<(), E> { Ok(()) } - fn exit_element_value(&mut self, _ctx: &ElementValueContext) -> Result<(), E> { Ok(()) } - fn enter_element_value_array_initializer(&mut self, _ctx: &ElementValueArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_element_value_array_initializer(&mut self, _ctx: &ElementValueArrayInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_declaration(&mut self, _ctx: &AnnotationTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_declaration(&mut self, _ctx: &AnnotationTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_body(&mut self, _ctx: &AnnotationTypeBodyContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_body(&mut self, _ctx: &AnnotationTypeBodyContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_element_declaration(&mut self, _ctx: &AnnotationTypeElementDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_element_declaration(&mut self, _ctx: &AnnotationTypeElementDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_type_element_rest(&mut self, _ctx: &AnnotationTypeElementRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_type_element_rest(&mut self, _ctx: &AnnotationTypeElementRestContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_method_or_constant_rest(&mut self, _ctx: &AnnotationMethodOrConstantRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_method_or_constant_rest(&mut self, _ctx: &AnnotationMethodOrConstantRestContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_method_rest(&mut self, _ctx: &AnnotationMethodRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_method_rest(&mut self, _ctx: &AnnotationMethodRestContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_constant_rest(&mut self, _ctx: &AnnotationConstantRestContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_constant_rest(&mut self, _ctx: &AnnotationConstantRestContext) -> Result<(), E> { Ok(()) } - fn enter_default_value(&mut self, _ctx: &DefaultValueContext) -> Result<(), E> { Ok(()) } - fn exit_default_value(&mut self, _ctx: &DefaultValueContext) -> Result<(), E> { Ok(()) } - fn enter_module_declaration(&mut self, _ctx: &ModuleDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_module_declaration(&mut self, _ctx: &ModuleDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_module_directive(&mut self, _ctx: &ModuleDirectiveContext) -> Result<(), E> { Ok(()) } - fn exit_module_directive(&mut self, _ctx: &ModuleDirectiveContext) -> Result<(), E> { Ok(()) } - fn enter_requires_modifier(&mut self, _ctx: &RequiresModifierContext) -> Result<(), E> { Ok(()) } - fn exit_requires_modifier(&mut self, _ctx: &RequiresModifierContext) -> Result<(), E> { Ok(()) } - fn enter_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_record_declaration(&mut self, _ctx: &RecordDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_record_header(&mut self, _ctx: &RecordHeaderContext) -> Result<(), E> { Ok(()) } - fn exit_record_header(&mut self, _ctx: &RecordHeaderContext) -> Result<(), E> { Ok(()) } - fn enter_record_component_list(&mut self, _ctx: &RecordComponentListContext) -> Result<(), E> { Ok(()) } - fn exit_record_component_list(&mut self, _ctx: &RecordComponentListContext) -> Result<(), E> { Ok(()) } - fn enter_record_component(&mut self, _ctx: &RecordComponentContext) -> Result<(), E> { Ok(()) } - fn exit_record_component(&mut self, _ctx: &RecordComponentContext) -> Result<(), E> { Ok(()) } - fn enter_record_body(&mut self, _ctx: &RecordBodyContext) -> Result<(), E> { Ok(()) } - fn exit_record_body(&mut self, _ctx: &RecordBodyContext) -> Result<(), E> { Ok(()) } - fn enter_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn exit_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn enter_block_statement(&mut self, _ctx: &BlockStatementContext) -> Result<(), E> { Ok(()) } - fn exit_block_statement(&mut self, _ctx: &BlockStatementContext) -> Result<(), E> { Ok(()) } - fn enter_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_local_variable_declaration(&mut self, _ctx: &LocalVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn enter_type_identifier(&mut self, _ctx: &TypeIdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_identifier(&mut self, _ctx: &TypeIdentifierContext) -> Result<(), E> { Ok(()) } - fn enter_local_type_declaration(&mut self, _ctx: &LocalTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_local_type_declaration(&mut self, _ctx: &LocalTypeDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn exit_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn enter_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn exit_catch_clause(&mut self, _ctx: &CatchClauseContext) -> Result<(), E> { Ok(()) } - fn enter_catch_type(&mut self, _ctx: &CatchTypeContext) -> Result<(), E> { Ok(()) } - fn exit_catch_type(&mut self, _ctx: &CatchTypeContext) -> Result<(), E> { Ok(()) } - fn enter_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn exit_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn enter_resource_specification(&mut self, _ctx: &ResourceSpecificationContext) -> Result<(), E> { Ok(()) } - fn exit_resource_specification(&mut self, _ctx: &ResourceSpecificationContext) -> Result<(), E> { Ok(()) } - fn enter_resources(&mut self, _ctx: &ResourcesContext) -> Result<(), E> { Ok(()) } - fn exit_resources(&mut self, _ctx: &ResourcesContext) -> Result<(), E> { Ok(()) } - fn enter_resource(&mut self, _ctx: &ResourceContext) -> Result<(), E> { Ok(()) } - fn exit_resource(&mut self, _ctx: &ResourceContext) -> Result<(), E> { Ok(()) } - fn enter_switch_block_statement_group(&mut self, _ctx: &SwitchBlockStatementGroupContext) -> Result<(), E> { Ok(()) } - fn exit_switch_block_statement_group(&mut self, _ctx: &SwitchBlockStatementGroupContext) -> Result<(), E> { Ok(()) } - fn enter_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_switch_label(&mut self, _ctx: &SwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_for_control(&mut self, _ctx: &ForControlContext) -> Result<(), E> { Ok(()) } - fn exit_for_control(&mut self, _ctx: &ForControlContext) -> Result<(), E> { Ok(()) } - fn enter_for_init(&mut self, _ctx: &ForInitContext) -> Result<(), E> { Ok(()) } - fn exit_for_init(&mut self, _ctx: &ForInitContext) -> Result<(), E> { Ok(()) } - fn enter_enhanced_for_control(&mut self, _ctx: &EnhancedForControlContext) -> Result<(), E> { Ok(()) } - fn exit_enhanced_for_control(&mut self, _ctx: &EnhancedForControlContext) -> Result<(), E> { Ok(()) } - fn enter_expression_list(&mut self, _ctx: &ExpressionListContext) -> Result<(), E> { Ok(()) } - fn exit_expression_list(&mut self, _ctx: &ExpressionListContext) -> Result<(), E> { Ok(()) } - fn enter_method_call(&mut self, _ctx: &MethodCallContext) -> Result<(), E> { Ok(()) } - fn exit_method_call(&mut self, _ctx: &MethodCallContext) -> Result<(), E> { Ok(()) } - fn enter_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_primary_expression_label(&mut self, _ctx: &PrimaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_primary_expression_label(&mut self, _ctx: &PrimaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_square_bracket_expression_label(&mut self, _ctx: &SquareBracketExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_square_bracket_expression_label(&mut self, _ctx: &SquareBracketExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_member_reference_expression_label(&mut self, _ctx: &MemberReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_member_reference_expression_label(&mut self, _ctx: &MemberReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_method_call_expression_label(&mut self, _ctx: &MethodCallExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_method_call_expression_label(&mut self, _ctx: &MethodCallExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_method_reference_expression_label(&mut self, _ctx: &MethodReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_method_reference_expression_label(&mut self, _ctx: &MethodReferenceExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_expression_switch_label(&mut self, _ctx: &ExpressionSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn exit_expression_switch_label(&mut self, _ctx: &ExpressionSwitchLabelContext) -> Result<(), E> { Ok(()) } - fn enter_post_increment_decrement_operator_expression_label(&mut self, _ctx: &PostIncrementDecrementOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_post_increment_decrement_operator_expression_label(&mut self, _ctx: &PostIncrementDecrementOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_unary_operator_expression_label(&mut self, _ctx: &UnaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_unary_operator_expression_label(&mut self, _ctx: &UnaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_cast_expression_label(&mut self, _ctx: &CastExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_cast_expression_label(&mut self, _ctx: &CastExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_object_creation_expression_label(&mut self, _ctx: &ObjectCreationExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_object_creation_expression_label(&mut self, _ctx: &ObjectCreationExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_binary_operator_expression_label(&mut self, _ctx: &BinaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_binary_operator_expression_label(&mut self, _ctx: &BinaryOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_instance_of_operator_expression_label(&mut self, _ctx: &InstanceOfOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_instance_of_operator_expression_label(&mut self, _ctx: &InstanceOfOperatorExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_ternary_expression_label(&mut self, _ctx: &TernaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn exit_ternary_expression_label(&mut self, _ctx: &TernaryExpressionLabelContext) -> Result<(), E> { Ok(()) } - fn enter_expression_lambda_label(&mut self, _ctx: &ExpressionLambdaLabelContext) -> Result<(), E> { Ok(()) } - fn exit_expression_lambda_label(&mut self, _ctx: &ExpressionLambdaLabelContext) -> Result<(), E> { Ok(()) } - fn enter_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn exit_pattern(&mut self, _ctx: &PatternContext) -> Result<(), E> { Ok(()) } - fn enter_component_pattern_list(&mut self, _ctx: &ComponentPatternListContext) -> Result<(), E> { Ok(()) } - fn exit_component_pattern_list(&mut self, _ctx: &ComponentPatternListContext) -> Result<(), E> { Ok(()) } - fn enter_component_pattern(&mut self, _ctx: &ComponentPatternContext) -> Result<(), E> { Ok(()) } - fn exit_component_pattern(&mut self, _ctx: &ComponentPatternContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_expression(&mut self, _ctx: &LambdaExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_body(&mut self, _ctx: &LambdaBodyContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_body(&mut self, _ctx: &LambdaBodyContext) -> Result<(), E> { Ok(()) } - fn enter_primary(&mut self, _ctx: &PrimaryContext) -> Result<(), E> { Ok(()) } - fn exit_primary(&mut self, _ctx: &PrimaryContext) -> Result<(), E> { Ok(()) } - fn enter_switch_expression(&mut self, _ctx: &SwitchExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_switch_expression(&mut self, _ctx: &SwitchExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_switch_labeled_rule(&mut self, _ctx: &SwitchLabeledRuleContext) -> Result<(), E> { Ok(()) } - fn exit_switch_labeled_rule(&mut self, _ctx: &SwitchLabeledRuleContext) -> Result<(), E> { Ok(()) } - fn enter_guard(&mut self, _ctx: &GuardContext) -> Result<(), E> { Ok(()) } - fn exit_guard(&mut self, _ctx: &GuardContext) -> Result<(), E> { Ok(()) } - fn enter_case_pattern(&mut self, _ctx: &CasePatternContext) -> Result<(), E> { Ok(()) } - fn exit_case_pattern(&mut self, _ctx: &CasePatternContext) -> Result<(), E> { Ok(()) } - fn enter_switch_rule_outcome(&mut self, _ctx: &SwitchRuleOutcomeContext) -> Result<(), E> { Ok(()) } - fn exit_switch_rule_outcome(&mut self, _ctx: &SwitchRuleOutcomeContext) -> Result<(), E> { Ok(()) } - fn enter_class_or_interface_type(&mut self, _ctx: &ClassOrInterfaceTypeContext) -> Result<(), E> { Ok(()) } - fn exit_class_or_interface_type(&mut self, _ctx: &ClassOrInterfaceTypeContext) -> Result<(), E> { Ok(()) } - fn enter_creator(&mut self, _ctx: &CreatorContext) -> Result<(), E> { Ok(()) } - fn exit_creator(&mut self, _ctx: &CreatorContext) -> Result<(), E> { Ok(()) } - fn enter_created_name(&mut self, _ctx: &CreatedNameContext) -> Result<(), E> { Ok(()) } - fn exit_created_name(&mut self, _ctx: &CreatedNameContext) -> Result<(), E> { Ok(()) } - fn enter_inner_creator(&mut self, _ctx: &InnerCreatorContext) -> Result<(), E> { Ok(()) } - fn exit_inner_creator(&mut self, _ctx: &InnerCreatorContext) -> Result<(), E> { Ok(()) } - fn enter_array_creator_rest(&mut self, _ctx: &ArrayCreatorRestContext) -> Result<(), E> { Ok(()) } - fn exit_array_creator_rest(&mut self, _ctx: &ArrayCreatorRestContext) -> Result<(), E> { Ok(()) } - fn enter_class_creator_rest(&mut self, _ctx: &ClassCreatorRestContext) -> Result<(), E> { Ok(()) } - fn exit_class_creator_rest(&mut self, _ctx: &ClassCreatorRestContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_generic_invocation(&mut self, _ctx: &ExplicitGenericInvocationContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_generic_invocation(&mut self, _ctx: &ExplicitGenericInvocationContext) -> Result<(), E> { Ok(()) } - fn enter_type_arguments_or_diamond(&mut self, _ctx: &TypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn exit_type_arguments_or_diamond(&mut self, _ctx: &TypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn enter_non_wildcard_type_arguments_or_diamond(&mut self, _ctx: &NonWildcardTypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn exit_non_wildcard_type_arguments_or_diamond(&mut self, _ctx: &NonWildcardTypeArgumentsOrDiamondContext) -> Result<(), E> { Ok(()) } - fn enter_non_wildcard_type_arguments(&mut self, _ctx: &NonWildcardTypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_non_wildcard_type_arguments(&mut self, _ctx: &NonWildcardTypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_type_list(&mut self, _ctx: &TypeListContext) -> Result<(), E> { Ok(()) } - fn exit_type_list(&mut self, _ctx: &TypeListContext) -> Result<(), E> { Ok(()) } - fn enter_type_type(&mut self, _ctx: &TypeTypeContext) -> Result<(), E> { Ok(()) } - fn exit_type_type(&mut self, _ctx: &TypeTypeContext) -> Result<(), E> { Ok(()) } - fn enter_primitive_type(&mut self, _ctx: &PrimitiveTypeContext) -> Result<(), E> { Ok(()) } - fn exit_primitive_type(&mut self, _ctx: &PrimitiveTypeContext) -> Result<(), E> { Ok(()) } - fn enter_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_super_suffix(&mut self, _ctx: &SuperSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_super_suffix(&mut self, _ctx: &SuperSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_generic_invocation_suffix(&mut self, _ctx: &ExplicitGenericInvocationSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_generic_invocation_suffix(&mut self, _ctx: &ExplicitGenericInvocationSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_arguments(&mut self, _ctx: &ArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_arguments(&mut self, _ctx: &ArgumentsContext) -> Result<(), E> { Ok(()) } - fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), E> { Ok(()) } - fn output(&mut self) -> std::io::Stdout { std::io::stdout() } -} - -antlr4_runtime::__antlr4_rust_generated_walk_callbacks! { - callbacks: __JavaValidatedTreeWalkerCallbacks, - listener: JavaValidatedListener, - enter: |listener, context, invocation_states| { - listener.enter_every_rule(ValidatedRuleNode::__new(context))?; - match __context_kind(context) { - 0 => listener.enter_compilation_unit(&CompilationUnitContext::::__from_validated_listener_node(context, invocation_states))?, - 1 => listener.enter_modular_compulation_unit(&ModularCompulationUnitContext::::__from_validated_listener_node(context, invocation_states))?, - 2 => listener.enter_package_declaration(&PackageDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 3 => listener.enter_import_declaration(&ImportDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 4 => listener.enter_type_declaration(&TypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 5 => listener.enter_modifier(&ModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 6 => listener.enter_class_or_interface_modifier(&ClassOrInterfaceModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 7 => listener.enter_variable_modifier(&VariableModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 8 => listener.enter_class_declaration(&ClassDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 9 => listener.enter_type_parameters(&TypeParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 10 => listener.enter_type_parameter(&TypeParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 11 => listener.enter_type_bound(&TypeBoundContext::::__from_validated_listener_node(context, invocation_states))?, - 12 => listener.enter_enum_declaration(&EnumDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 13 => listener.enter_enum_constants(&EnumConstantsContext::::__from_validated_listener_node(context, invocation_states))?, - 14 => listener.enter_enum_constant(&EnumConstantContext::::__from_validated_listener_node(context, invocation_states))?, - 15 => listener.enter_enum_body_declarations(&EnumBodyDeclarationsContext::::__from_validated_listener_node(context, invocation_states))?, - 16 => listener.enter_interface_declaration(&InterfaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 17 => listener.enter_class_body(&ClassBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 18 => listener.enter_interface_body(&InterfaceBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 19 => listener.enter_class_body_declaration(&ClassBodyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 20 => listener.enter_member_declaration(&MemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 21 => listener.enter_method_declaration(&MethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 22 => listener.enter_method_body(&MethodBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 23 => listener.enter_type_type_or_void(&TypeTypeOrVoidContext::::__from_validated_listener_node(context, invocation_states))?, - 24 => listener.enter_generic_method_declaration(&GenericMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 25 => listener.enter_generic_constructor_declaration(&GenericConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 26 => listener.enter_constructor_declaration(&ConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 27 => listener.enter_compact_constructor_declaration(&CompactConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 28 => listener.enter_field_declaration(&FieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 29 => listener.enter_interface_body_declaration(&InterfaceBodyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 30 => listener.enter_interface_member_declaration(&InterfaceMemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 31 => listener.enter_const_declaration(&ConstDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 32 => listener.enter_constant_declarator(&ConstantDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 33 => listener.enter_interface_method_declaration(&InterfaceMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 34 => listener.enter_interface_method_modifier(&InterfaceMethodModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 35 => listener.enter_generic_interface_method_declaration(&GenericInterfaceMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 36 => listener.enter_interface_common_body_declaration(&InterfaceCommonBodyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 37 => listener.enter_variable_declarators(&VariableDeclaratorsContext::::__from_validated_listener_node(context, invocation_states))?, - 38 => listener.enter_variable_declarator(&VariableDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 39 => listener.enter_variable_declarator_id(&VariableDeclaratorIdContext::::__from_validated_listener_node(context, invocation_states))?, - 40 => listener.enter_variable_initializer(&VariableInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 41 => listener.enter_array_initializer(&ArrayInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 42 => listener.enter_class_type(&ClassTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 43 => listener.enter_package_name(&PackageNameContext::::__from_validated_listener_node(context, invocation_states))?, - 44 => listener.enter_type_argument(&TypeArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 45 => listener.enter_qualified_name_list(&QualifiedNameListContext::::__from_validated_listener_node(context, invocation_states))?, - 46 => listener.enter_formal_parameters(&FormalParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 47 => listener.enter_receiver_parameter(&ReceiverParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 48 => listener.enter_formal_parameter_list(&FormalParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 49 => listener.enter_formal_parameter(&FormalParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 50 => listener.enter_lambda_lvti_list(&LambdaLvtiListContext::::__from_validated_listener_node(context, invocation_states))?, - 51 => listener.enter_lambda_lvti_parameter(&LambdaLvtiParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 52 => listener.enter_qualified_name(&QualifiedNameContext::::__from_validated_listener_node(context, invocation_states))?, - 53 => listener.enter_literal(&LiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 54 => listener.enter_integer_literal(&IntegerLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 55 => listener.enter_float_literal(&FloatLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 56 => listener.enter_annotation(&AnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 57 => listener.enter_annotation_field_values(&AnnotationFieldValuesContext::::__from_validated_listener_node(context, invocation_states))?, - 58 => listener.enter_annotation_field_value(&AnnotationFieldValueContext::::__from_validated_listener_node(context, invocation_states))?, - 59 => listener.enter_annotation_value(&AnnotationValueContext::::__from_validated_listener_node(context, invocation_states))?, - 60 => listener.enter_element_value(&ElementValueContext::::__from_validated_listener_node(context, invocation_states))?, - 61 => listener.enter_element_value_array_initializer(&ElementValueArrayInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 62 => listener.enter_annotation_type_declaration(&AnnotationTypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 63 => listener.enter_annotation_type_body(&AnnotationTypeBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 64 => listener.enter_annotation_type_element_declaration(&AnnotationTypeElementDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 65 => listener.enter_annotation_type_element_rest(&AnnotationTypeElementRestContext::::__from_validated_listener_node(context, invocation_states))?, - 66 => listener.enter_annotation_method_or_constant_rest(&AnnotationMethodOrConstantRestContext::::__from_validated_listener_node(context, invocation_states))?, - 67 => listener.enter_annotation_method_rest(&AnnotationMethodRestContext::::__from_validated_listener_node(context, invocation_states))?, - 68 => listener.enter_annotation_constant_rest(&AnnotationConstantRestContext::::__from_validated_listener_node(context, invocation_states))?, - 69 => listener.enter_default_value(&DefaultValueContext::::__from_validated_listener_node(context, invocation_states))?, - 70 => listener.enter_module_declaration(&ModuleDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 71 => listener.enter_module_directive(&ModuleDirectiveContext::::__from_validated_listener_node(context, invocation_states))?, - 72 => listener.enter_requires_modifier(&RequiresModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 73 => listener.enter_record_declaration(&RecordDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 74 => listener.enter_record_header(&RecordHeaderContext::::__from_validated_listener_node(context, invocation_states))?, - 75 => listener.enter_record_component_list(&RecordComponentListContext::::__from_validated_listener_node(context, invocation_states))?, - 76 => listener.enter_record_component(&RecordComponentContext::::__from_validated_listener_node(context, invocation_states))?, - 77 => listener.enter_record_body(&RecordBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 78 => listener.enter_block(&BlockContext::::__from_validated_listener_node(context, invocation_states))?, - 79 => listener.enter_block_statement(&BlockStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 80 => listener.enter_local_variable_declaration(&LocalVariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 81 => listener.enter_identifier(&IdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - 82 => listener.enter_type_identifier(&TypeIdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - 83 => listener.enter_local_type_declaration(&LocalTypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 84 => listener.enter_statement(&StatementContext::::__from_validated_listener_node(context, invocation_states))?, - 85 => listener.enter_catch_clause(&CatchClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 86 => listener.enter_catch_type(&CatchTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 87 => listener.enter_finally_block(&FinallyBlockContext::::__from_validated_listener_node(context, invocation_states))?, - 88 => listener.enter_resource_specification(&ResourceSpecificationContext::::__from_validated_listener_node(context, invocation_states))?, - 89 => listener.enter_resources(&ResourcesContext::::__from_validated_listener_node(context, invocation_states))?, - 90 => listener.enter_resource(&ResourceContext::::__from_validated_listener_node(context, invocation_states))?, - 91 => listener.enter_switch_block_statement_group(&SwitchBlockStatementGroupContext::::__from_validated_listener_node(context, invocation_states))?, - 92 => listener.enter_switch_label(&SwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 93 => listener.enter_for_control(&ForControlContext::::__from_validated_listener_node(context, invocation_states))?, - 94 => listener.enter_for_init(&ForInitContext::::__from_validated_listener_node(context, invocation_states))?, - 95 => listener.enter_enhanced_for_control(&EnhancedForControlContext::::__from_validated_listener_node(context, invocation_states))?, - 96 => listener.enter_expression_list(&ExpressionListContext::::__from_validated_listener_node(context, invocation_states))?, - 97 => listener.enter_method_call(&MethodCallContext::::__from_validated_listener_node(context, invocation_states))?, - 98 => listener.enter_expression(&ExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 99 => listener.enter_primary_expression_label(&PrimaryExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 100 => listener.enter_square_bracket_expression_label(&SquareBracketExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 101 => listener.enter_member_reference_expression_label(&MemberReferenceExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 102 => listener.enter_method_call_expression_label(&MethodCallExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 103 => listener.enter_method_reference_expression_label(&MethodReferenceExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 104 => listener.enter_expression_switch_label(&ExpressionSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 105 => listener.enter_post_increment_decrement_operator_expression_label(&PostIncrementDecrementOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 106 => listener.enter_unary_operator_expression_label(&UnaryOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 107 => listener.enter_cast_expression_label(&CastExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 108 => listener.enter_object_creation_expression_label(&ObjectCreationExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 109 => listener.enter_binary_operator_expression_label(&BinaryOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 110 => listener.enter_instance_of_operator_expression_label(&InstanceOfOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 111 => listener.enter_ternary_expression_label(&TernaryExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 112 => listener.enter_expression_lambda_label(&ExpressionLambdaLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 113 => listener.enter_pattern(&PatternContext::::__from_validated_listener_node(context, invocation_states))?, - 114 => listener.enter_component_pattern_list(&ComponentPatternListContext::::__from_validated_listener_node(context, invocation_states))?, - 115 => listener.enter_component_pattern(&ComponentPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 116 => listener.enter_lambda_expression(&LambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 117 => listener.enter_lambda_parameters(&LambdaParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 118 => listener.enter_lambda_body(&LambdaBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 119 => listener.enter_primary(&PrimaryContext::::__from_validated_listener_node(context, invocation_states))?, - 120 => listener.enter_switch_expression(&SwitchExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 121 => listener.enter_switch_labeled_rule(&SwitchLabeledRuleContext::::__from_validated_listener_node(context, invocation_states))?, - 122 => listener.enter_guard(&GuardContext::::__from_validated_listener_node(context, invocation_states))?, - 123 => listener.enter_case_pattern(&CasePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 124 => listener.enter_switch_rule_outcome(&SwitchRuleOutcomeContext::::__from_validated_listener_node(context, invocation_states))?, - 125 => listener.enter_class_or_interface_type(&ClassOrInterfaceTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 126 => listener.enter_creator(&CreatorContext::::__from_validated_listener_node(context, invocation_states))?, - 127 => listener.enter_created_name(&CreatedNameContext::::__from_validated_listener_node(context, invocation_states))?, - 128 => listener.enter_inner_creator(&InnerCreatorContext::::__from_validated_listener_node(context, invocation_states))?, - 129 => listener.enter_array_creator_rest(&ArrayCreatorRestContext::::__from_validated_listener_node(context, invocation_states))?, - 130 => listener.enter_class_creator_rest(&ClassCreatorRestContext::::__from_validated_listener_node(context, invocation_states))?, - 131 => listener.enter_explicit_generic_invocation(&ExplicitGenericInvocationContext::::__from_validated_listener_node(context, invocation_states))?, - 132 => listener.enter_type_arguments_or_diamond(&TypeArgumentsOrDiamondContext::::__from_validated_listener_node(context, invocation_states))?, - 133 => listener.enter_non_wildcard_type_arguments_or_diamond(&NonWildcardTypeArgumentsOrDiamondContext::::__from_validated_listener_node(context, invocation_states))?, - 134 => listener.enter_non_wildcard_type_arguments(&NonWildcardTypeArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 135 => listener.enter_type_list(&TypeListContext::::__from_validated_listener_node(context, invocation_states))?, - 136 => listener.enter_type_type(&TypeTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 137 => listener.enter_primitive_type(&PrimitiveTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 138 => listener.enter_type_arguments(&TypeArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 139 => listener.enter_super_suffix(&SuperSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 140 => listener.enter_explicit_generic_invocation_suffix(&ExplicitGenericInvocationSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 141 => listener.enter_arguments(&ArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - _ => {} - } - Ok(()) - }, - exit: |listener, context, invocation_states| { - match __context_kind(context) { - 0 => listener.exit_compilation_unit(&CompilationUnitContext::::__from_validated_listener_node(context, invocation_states))?, - 1 => listener.exit_modular_compulation_unit(&ModularCompulationUnitContext::::__from_validated_listener_node(context, invocation_states))?, - 2 => listener.exit_package_declaration(&PackageDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 3 => listener.exit_import_declaration(&ImportDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 4 => listener.exit_type_declaration(&TypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 5 => listener.exit_modifier(&ModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 6 => listener.exit_class_or_interface_modifier(&ClassOrInterfaceModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 7 => listener.exit_variable_modifier(&VariableModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 8 => listener.exit_class_declaration(&ClassDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 9 => listener.exit_type_parameters(&TypeParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 10 => listener.exit_type_parameter(&TypeParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 11 => listener.exit_type_bound(&TypeBoundContext::::__from_validated_listener_node(context, invocation_states))?, - 12 => listener.exit_enum_declaration(&EnumDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 13 => listener.exit_enum_constants(&EnumConstantsContext::::__from_validated_listener_node(context, invocation_states))?, - 14 => listener.exit_enum_constant(&EnumConstantContext::::__from_validated_listener_node(context, invocation_states))?, - 15 => listener.exit_enum_body_declarations(&EnumBodyDeclarationsContext::::__from_validated_listener_node(context, invocation_states))?, - 16 => listener.exit_interface_declaration(&InterfaceDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 17 => listener.exit_class_body(&ClassBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 18 => listener.exit_interface_body(&InterfaceBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 19 => listener.exit_class_body_declaration(&ClassBodyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 20 => listener.exit_member_declaration(&MemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 21 => listener.exit_method_declaration(&MethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 22 => listener.exit_method_body(&MethodBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 23 => listener.exit_type_type_or_void(&TypeTypeOrVoidContext::::__from_validated_listener_node(context, invocation_states))?, - 24 => listener.exit_generic_method_declaration(&GenericMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 25 => listener.exit_generic_constructor_declaration(&GenericConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 26 => listener.exit_constructor_declaration(&ConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 27 => listener.exit_compact_constructor_declaration(&CompactConstructorDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 28 => listener.exit_field_declaration(&FieldDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 29 => listener.exit_interface_body_declaration(&InterfaceBodyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 30 => listener.exit_interface_member_declaration(&InterfaceMemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 31 => listener.exit_const_declaration(&ConstDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 32 => listener.exit_constant_declarator(&ConstantDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 33 => listener.exit_interface_method_declaration(&InterfaceMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 34 => listener.exit_interface_method_modifier(&InterfaceMethodModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 35 => listener.exit_generic_interface_method_declaration(&GenericInterfaceMethodDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 36 => listener.exit_interface_common_body_declaration(&InterfaceCommonBodyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 37 => listener.exit_variable_declarators(&VariableDeclaratorsContext::::__from_validated_listener_node(context, invocation_states))?, - 38 => listener.exit_variable_declarator(&VariableDeclaratorContext::::__from_validated_listener_node(context, invocation_states))?, - 39 => listener.exit_variable_declarator_id(&VariableDeclaratorIdContext::::__from_validated_listener_node(context, invocation_states))?, - 40 => listener.exit_variable_initializer(&VariableInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 41 => listener.exit_array_initializer(&ArrayInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 42 => listener.exit_class_type(&ClassTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 43 => listener.exit_package_name(&PackageNameContext::::__from_validated_listener_node(context, invocation_states))?, - 44 => listener.exit_type_argument(&TypeArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 45 => listener.exit_qualified_name_list(&QualifiedNameListContext::::__from_validated_listener_node(context, invocation_states))?, - 46 => listener.exit_formal_parameters(&FormalParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 47 => listener.exit_receiver_parameter(&ReceiverParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 48 => listener.exit_formal_parameter_list(&FormalParameterListContext::::__from_validated_listener_node(context, invocation_states))?, - 49 => listener.exit_formal_parameter(&FormalParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 50 => listener.exit_lambda_lvti_list(&LambdaLvtiListContext::::__from_validated_listener_node(context, invocation_states))?, - 51 => listener.exit_lambda_lvti_parameter(&LambdaLvtiParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 52 => listener.exit_qualified_name(&QualifiedNameContext::::__from_validated_listener_node(context, invocation_states))?, - 53 => listener.exit_literal(&LiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 54 => listener.exit_integer_literal(&IntegerLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 55 => listener.exit_float_literal(&FloatLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 56 => listener.exit_annotation(&AnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 57 => listener.exit_annotation_field_values(&AnnotationFieldValuesContext::::__from_validated_listener_node(context, invocation_states))?, - 58 => listener.exit_annotation_field_value(&AnnotationFieldValueContext::::__from_validated_listener_node(context, invocation_states))?, - 59 => listener.exit_annotation_value(&AnnotationValueContext::::__from_validated_listener_node(context, invocation_states))?, - 60 => listener.exit_element_value(&ElementValueContext::::__from_validated_listener_node(context, invocation_states))?, - 61 => listener.exit_element_value_array_initializer(&ElementValueArrayInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 62 => listener.exit_annotation_type_declaration(&AnnotationTypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 63 => listener.exit_annotation_type_body(&AnnotationTypeBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 64 => listener.exit_annotation_type_element_declaration(&AnnotationTypeElementDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 65 => listener.exit_annotation_type_element_rest(&AnnotationTypeElementRestContext::::__from_validated_listener_node(context, invocation_states))?, - 66 => listener.exit_annotation_method_or_constant_rest(&AnnotationMethodOrConstantRestContext::::__from_validated_listener_node(context, invocation_states))?, - 67 => listener.exit_annotation_method_rest(&AnnotationMethodRestContext::::__from_validated_listener_node(context, invocation_states))?, - 68 => listener.exit_annotation_constant_rest(&AnnotationConstantRestContext::::__from_validated_listener_node(context, invocation_states))?, - 69 => listener.exit_default_value(&DefaultValueContext::::__from_validated_listener_node(context, invocation_states))?, - 70 => listener.exit_module_declaration(&ModuleDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 71 => listener.exit_module_directive(&ModuleDirectiveContext::::__from_validated_listener_node(context, invocation_states))?, - 72 => listener.exit_requires_modifier(&RequiresModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 73 => listener.exit_record_declaration(&RecordDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 74 => listener.exit_record_header(&RecordHeaderContext::::__from_validated_listener_node(context, invocation_states))?, - 75 => listener.exit_record_component_list(&RecordComponentListContext::::__from_validated_listener_node(context, invocation_states))?, - 76 => listener.exit_record_component(&RecordComponentContext::::__from_validated_listener_node(context, invocation_states))?, - 77 => listener.exit_record_body(&RecordBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 78 => listener.exit_block(&BlockContext::::__from_validated_listener_node(context, invocation_states))?, - 79 => listener.exit_block_statement(&BlockStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 80 => listener.exit_local_variable_declaration(&LocalVariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 81 => listener.exit_identifier(&IdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - 82 => listener.exit_type_identifier(&TypeIdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - 83 => listener.exit_local_type_declaration(&LocalTypeDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 84 => listener.exit_statement(&StatementContext::::__from_validated_listener_node(context, invocation_states))?, - 85 => listener.exit_catch_clause(&CatchClauseContext::::__from_validated_listener_node(context, invocation_states))?, - 86 => listener.exit_catch_type(&CatchTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 87 => listener.exit_finally_block(&FinallyBlockContext::::__from_validated_listener_node(context, invocation_states))?, - 88 => listener.exit_resource_specification(&ResourceSpecificationContext::::__from_validated_listener_node(context, invocation_states))?, - 89 => listener.exit_resources(&ResourcesContext::::__from_validated_listener_node(context, invocation_states))?, - 90 => listener.exit_resource(&ResourceContext::::__from_validated_listener_node(context, invocation_states))?, - 91 => listener.exit_switch_block_statement_group(&SwitchBlockStatementGroupContext::::__from_validated_listener_node(context, invocation_states))?, - 92 => listener.exit_switch_label(&SwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 93 => listener.exit_for_control(&ForControlContext::::__from_validated_listener_node(context, invocation_states))?, - 94 => listener.exit_for_init(&ForInitContext::::__from_validated_listener_node(context, invocation_states))?, - 95 => listener.exit_enhanced_for_control(&EnhancedForControlContext::::__from_validated_listener_node(context, invocation_states))?, - 96 => listener.exit_expression_list(&ExpressionListContext::::__from_validated_listener_node(context, invocation_states))?, - 97 => listener.exit_method_call(&MethodCallContext::::__from_validated_listener_node(context, invocation_states))?, - 98 => listener.exit_expression(&ExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 99 => listener.exit_primary_expression_label(&PrimaryExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 100 => listener.exit_square_bracket_expression_label(&SquareBracketExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 101 => listener.exit_member_reference_expression_label(&MemberReferenceExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 102 => listener.exit_method_call_expression_label(&MethodCallExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 103 => listener.exit_method_reference_expression_label(&MethodReferenceExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 104 => listener.exit_expression_switch_label(&ExpressionSwitchLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 105 => listener.exit_post_increment_decrement_operator_expression_label(&PostIncrementDecrementOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 106 => listener.exit_unary_operator_expression_label(&UnaryOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 107 => listener.exit_cast_expression_label(&CastExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 108 => listener.exit_object_creation_expression_label(&ObjectCreationExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 109 => listener.exit_binary_operator_expression_label(&BinaryOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 110 => listener.exit_instance_of_operator_expression_label(&InstanceOfOperatorExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 111 => listener.exit_ternary_expression_label(&TernaryExpressionLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 112 => listener.exit_expression_lambda_label(&ExpressionLambdaLabelContext::::__from_validated_listener_node(context, invocation_states))?, - 113 => listener.exit_pattern(&PatternContext::::__from_validated_listener_node(context, invocation_states))?, - 114 => listener.exit_component_pattern_list(&ComponentPatternListContext::::__from_validated_listener_node(context, invocation_states))?, - 115 => listener.exit_component_pattern(&ComponentPatternContext::::__from_validated_listener_node(context, invocation_states))?, - 116 => listener.exit_lambda_expression(&LambdaExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 117 => listener.exit_lambda_parameters(&LambdaParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 118 => listener.exit_lambda_body(&LambdaBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 119 => listener.exit_primary(&PrimaryContext::::__from_validated_listener_node(context, invocation_states))?, - 120 => listener.exit_switch_expression(&SwitchExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 121 => listener.exit_switch_labeled_rule(&SwitchLabeledRuleContext::::__from_validated_listener_node(context, invocation_states))?, - 122 => listener.exit_guard(&GuardContext::::__from_validated_listener_node(context, invocation_states))?, - 123 => listener.exit_case_pattern(&CasePatternContext::::__from_validated_listener_node(context, invocation_states))?, - 124 => listener.exit_switch_rule_outcome(&SwitchRuleOutcomeContext::::__from_validated_listener_node(context, invocation_states))?, - 125 => listener.exit_class_or_interface_type(&ClassOrInterfaceTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 126 => listener.exit_creator(&CreatorContext::::__from_validated_listener_node(context, invocation_states))?, - 127 => listener.exit_created_name(&CreatedNameContext::::__from_validated_listener_node(context, invocation_states))?, - 128 => listener.exit_inner_creator(&InnerCreatorContext::::__from_validated_listener_node(context, invocation_states))?, - 129 => listener.exit_array_creator_rest(&ArrayCreatorRestContext::::__from_validated_listener_node(context, invocation_states))?, - 130 => listener.exit_class_creator_rest(&ClassCreatorRestContext::::__from_validated_listener_node(context, invocation_states))?, - 131 => listener.exit_explicit_generic_invocation(&ExplicitGenericInvocationContext::::__from_validated_listener_node(context, invocation_states))?, - 132 => listener.exit_type_arguments_or_diamond(&TypeArgumentsOrDiamondContext::::__from_validated_listener_node(context, invocation_states))?, - 133 => listener.exit_non_wildcard_type_arguments_or_diamond(&NonWildcardTypeArgumentsOrDiamondContext::::__from_validated_listener_node(context, invocation_states))?, - 134 => listener.exit_non_wildcard_type_arguments(&NonWildcardTypeArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 135 => listener.exit_type_list(&TypeListContext::::__from_validated_listener_node(context, invocation_states))?, - 136 => listener.exit_type_type(&TypeTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 137 => listener.exit_primitive_type(&PrimitiveTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 138 => listener.exit_type_arguments(&TypeArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 139 => listener.exit_super_suffix(&SuperSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 140 => listener.exit_explicit_generic_invocation_suffix(&ExplicitGenericInvocationSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 141 => listener.exit_arguments(&ArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - _ => {} - } - listener.exit_every_rule(ValidatedRuleNode::__new(context)) - }, - terminal: |listener, node| { - listener.visit_terminal(&TerminalNode::new(node)) - }, - error: |_listener, _node| { - unreachable!("validated parse tree contains an error node") - }, -} - -#[allow(dead_code)] -pub struct JavaValidatedTreeWalker; - -#[allow(dead_code)] -impl JavaValidatedTreeWalker { - pub fn walk>( - listener: &mut T, - tree: ValidatedRuleNode<'_>, - ) -> Result<(), E> { - Self::__walk(listener, tree.node(), None) - } - - pub fn walk_with_invocation_states>( - listener: &mut T, - tree: ValidatedRuleNode<'_>, - parent_invocation_states: Vec, - ) -> Result<(), E> { - Self::__walk(listener, tree.node(), Some(parent_invocation_states)) - } - - fn __walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - invocation_states: Option>, - ) -> Result<(), E> { - let mut callbacks = __JavaValidatedTreeWalkerCallbacks(listener); - antlr4_runtime::generated::walk_generated(tree, invocation_states, &mut callbacks) - } -} - -pub type ValidatedParseTreeWalker = JavaValidatedTreeWalker; - - - -static PARSER_ATN_DATA: &[u32] = &[1346458702, 3, 16909060, 29, 129, 1831, 2438, 15, 52, 230, 128, 29, 12817, 12846, 12190, 25036, 75, 25111, 104, 25279, 230, 25509, 128, 25637, 128, 25765, 32, 25215, 64, 2, 0, 8, 0, 1, 4294967295, 4294967295, 7, 0, 16, 1, 0, 4294967295, 4294967295, 2, 1, 8, 1, 1, 4294967295, 4294967295, 7, 1, 24, 2, 1, 4294967295, 4294967295, 2, 2, 8, 3, 1, 4294967295, 4294967295, 7, 2, 24, 4, 1, 4294967295, 4294967295, 2, 3, 8, 5, 1, 4294967295, 4294967295, 7, 3, 24, 6, 2, 4294967295, 4294967295, 2, 4, 8, 8, 1, 4294967295, 4294967295, 7, 4, 24, 9, 1, 4294967295, 4294967295, 2, 5, 8, 10, 1, 4294967295, 4294967295, 7, 5, 24, 11, 4, 4294967295, 4294967295, 2, 6, 8, 15, 1, 4294967295, 4294967295, 7, 6, 24, 16, 3, 4294967295, 4294967295, 2, 7, 8, 19, 1, 4294967295, 4294967295, 7, 7, 24, 20, 7, 4294967295, 4294967295, 2, 8, 8, 27, 1, 4294967295, 4294967295, 7, 8, 24, 28, 5, 4294967295, 4294967295, 2, 9, 8, 33, 1, 4294967295, 4294967295, 7, 9, 24, 34, 6, 4294967295, 4294967295, 2, 10, 8, 40, 1, 4294967295, 4294967295, 7, 10, 24, 41, 2, 4294967295, 4294967295, 2, 11, 8, 43, 1, 4294967295, 4294967295, 7, 11, 24, 44, 1, 4294967295, 4294967295, 2, 12, 8, 45, 1, 4294967295, 4294967295, 7, 12, 24, 46, 5, 4294967295, 4294967295, 2, 13, 8, 51, 1, 4294967295, 4294967295, 7, 13, 24, 52, 1, 4294967295, 4294967295, 2, 14, 8, 53, 1, 4294967295, 4294967295, 7, 14, 24, 54, 2, 4294967295, 4294967295, 2, 15, 8, 56, 1, 4294967295, 4294967295, 7, 15, 24, 57, 1, 4294967295, 4294967295, 2, 16, 8, 58, 1, 4294967295, 4294967295, 7, 16, 24, 59, 5, 4294967295, 4294967295, 2, 17, 8, 64, 1, 4294967295, 4294967295, 7, 17, 24, 65, 3, 4294967295, 4294967295, 2, 18, 8, 68, 1, 4294967295, 4294967295, 7, 18, 24, 69, 1, 4294967295, 4294967295, 2, 19, 8, 70, 1, 4294967295, 4294967295, 7, 19, 24, 71, 3, 4294967295, 4294967295, 2, 20, 8, 74, 1, 4294967295, 4294967295, 7, 20, 24, 75, 1, 4294967295, 4294967295, 2, 21, 8, 76, 1, 4294967295, 4294967295, 7, 21, 24, 77, 2, 4294967295, 4294967295, 2, 22, 8, 79, 1, 4294967295, 4294967295, 7, 22, 24, 80, 2, 4294967295, 4294967295, 2, 23, 8, 82, 1, 4294967295, 4294967295, 7, 23, 24, 83, 3, 4294967295, 4294967295, 2, 24, 8, 86, 1, 4294967295, 4294967295, 7, 24, 24, 87, 1, 4294967295, 4294967295, 2, 25, 8, 88, 1, 4294967295, 4294967295, 7, 25, 24, 89, 1, 4294967295, 4294967295, 2, 26, 8, 90, 1, 4294967295, 4294967295, 7, 26, 24, 91, 2, 4294967295, 4294967295, 2, 27, 8, 93, 1, 4294967295, 4294967295, 7, 27, 24, 94, 1, 4294967295, 4294967295, 2, 28, 8, 95, 1, 4294967295, 4294967295, 7, 28, 24, 96, 1, 4294967295, 4294967295, 2, 29, 8, 97, 1, 4294967295, 4294967295, 7, 29, 24, 98, 1, 4294967295, 4294967295, 2, 30, 8, 99, 1, 4294967295, 4294967295, 7, 30, 24, 100, 1, 4294967295, 4294967295, 2, 31, 8, 101, 1, 4294967295, 4294967295, 7, 31, 24, 102, 1, 4294967295, 4294967295, 2, 32, 8, 103, 1, 4294967295, 4294967295, 7, 32, 24, 104, 2, 4294967295, 4294967295, 2, 33, 8, 106, 1, 4294967295, 4294967295, 7, 33, 24, 107, 1, 4294967295, 4294967295, 2, 34, 8, 108, 1, 4294967295, 4294967295, 7, 34, 24, 109, 2, 4294967295, 4294967295, 2, 35, 8, 111, 1, 4294967295, 4294967295, 7, 35, 24, 112, 1, 4294967295, 4294967295, 2, 36, 8, 113, 1, 4294967295, 4294967295, 7, 36, 24, 114, 2, 4294967295, 4294967295, 2, 37, 8, 116, 1, 4294967295, 4294967295, 7, 37, 24, 117, 4, 4294967295, 4294967295, 2, 38, 8, 121, 1, 4294967295, 4294967295, 7, 38, 24, 122, 2, 4294967295, 4294967295, 2, 39, 8, 124, 1, 4294967295, 4294967295, 7, 39, 24, 125, 4, 4294967295, 4294967295, 2, 40, 8, 129, 1, 4294967295, 4294967295, 7, 40, 24, 130, 4, 4294967295, 4294967295, 2, 41, 8, 134, 1, 4294967295, 4294967295, 7, 41, 24, 135, 2, 4294967295, 4294967295, 2, 42, 8, 137, 1, 4294967295, 4294967295, 7, 42, 24, 138, 2, 4294967295, 4294967295, 2, 43, 8, 140, 1, 4294967295, 4294967295, 7, 43, 24, 141, 1, 4294967295, 4294967295, 2, 44, 8, 142, 1, 4294967295, 4294967295, 7, 44, 24, 143, 2, 4294967295, 4294967295, 2, 45, 8, 145, 1, 4294967295, 4294967295, 7, 45, 24, 146, 3, 4294967295, 4294967295, 2, 46, 8, 149, 1, 4294967295, 4294967295, 7, 46, 24, 150, 3, 4294967295, 4294967295, 2, 47, 8, 153, 1, 4294967295, 4294967295, 7, 47, 24, 154, 1, 4294967295, 4294967295, 2, 48, 8, 155, 1, 4294967295, 4294967295, 7, 48, 24, 156, 2, 4294967295, 4294967295, 2, 49, 8, 158, 1, 4294967295, 4294967295, 7, 49, 24, 159, 3, 4294967295, 4294967295, 2, 50, 8, 162, 1, 4294967295, 4294967295, 7, 50, 24, 163, 1, 4294967295, 4294967295, 2, 51, 8, 164, 1, 4294967295, 4294967295, 7, 51, 24, 165, 2, 4294967295, 4294967295, 2, 52, 8, 167, 1, 4294967295, 4294967295, 7, 52, 24, 168, 20, 4294967295, 4294967295, 2, 53, 8, 188, 1, 4294967295, 4294967295, 7, 53, 24, 189, 1, 4294967295, 4294967295, 2, 54, 8, 190, 1, 4294967295, 4294967295, 7, 54, 24, 191, 1, 4294967295, 4294967295, 2, 55, 8, 192, 1, 4294967295, 4294967295, 7, 55, 24, 193, 1, 4294967295, 4294967295, 2, 56, 8, 194, 1, 4294967295, 4294967295, 7, 56, 24, 195, 21, 4294967295, 4294967295, 2, 57, 8, 216, 1, 4294967295, 4294967295, 7, 57, 24, 217, 1, 4294967295, 4294967295, 2, 58, 8, 218, 1, 4294967295, 4294967295, 7, 58, 24, 219, 2, 4294967295, 4294967295, 2, 59, 8, 221, 1, 4294967295, 4294967295, 7, 59, 24, 222, 4, 4294967295, 4294967295, 2, 60, 8, 226, 1, 4294967295, 4294967295, 7, 60, 24, 227, 3, 4294967295, 4294967295, 2, 61, 8, 230, 1, 4294967295, 4294967295, 7, 61, 24, 231, 1, 4294967295, 4294967295, 2, 62, 8, 232, 1, 4294967295, 4294967295, 7, 62, 24, 233, 4, 4294967295, 4294967295, 2, 63, 8, 237, 1, 4294967295, 4294967295, 7, 63, 24, 238, 1, 4294967295, 4294967295, 2, 64, 8, 239, 1, 4294967295, 4294967295, 7, 64, 24, 240, 1, 4294967295, 4294967295, 2, 65, 8, 241, 1, 4294967295, 4294967295, 7, 65, 24, 242, 1, 4294967295, 4294967295, 2, 66, 8, 243, 1, 4294967295, 4294967295, 7, 66, 24, 244, 1, 4294967295, 4294967295, 2, 67, 8, 245, 1, 4294967295, 4294967295, 7, 67, 24, 246, 1, 4294967295, 4294967295, 2, 68, 8, 247, 1, 4294967295, 4294967295, 7, 68, 24, 248, 1, 4294967295, 4294967295, 2, 69, 8, 249, 1, 4294967295, 4294967295, 7, 69, 24, 250, 1, 4294967295, 4294967295, 2, 70, 8, 251, 1, 4294967295, 4294967295, 7, 70, 24, 252, 1, 4294967295, 4294967295, 2, 71, 8, 253, 1, 4294967295, 4294967295, 7, 71, 24, 254, 1, 4294967295, 4294967295, 2, 72, 8, 255, 1, 4294967295, 4294967295, 7, 72, 24, 256, 1, 4294967295, 4294967295, 2, 73, 8, 257, 1, 4294967295, 4294967295, 7, 73, 24, 258, 5, 4294967295, 4294967295, 2, 74, 8, 263, 1, 4294967295, 4294967295, 7, 74, 24, 264, 1, 4294967295, 4294967295, 2, 75, 8, 265, 1, 4294967295, 4294967295, 7, 75, 24, 266, 1, 4294967295, 4294967295, 2, 76, 8, 267, 1, 4294967295, 4294967295, 7, 76, 24, 268, 2, 4294967295, 4294967295, 2, 77, 8, 270, 1, 4294967295, 4294967295, 7, 77, 24, 271, 1, 4294967295, 4294967295, 2, 78, 8, 272, 1, 4294967295, 4294967295, 7, 78, 24, 273, 12, 4294967295, 4294967295, 2, 79, 8, 285, 1, 4294967295, 4294967295, 7, 79, 24, 286, 3, 4294967295, 4294967295, 2, 80, 8, 289, 1, 4294967295, 4294967295, 7, 80, 24, 290, 2, 4294967295, 4294967295, 2, 81, 8, 292, 1, 4294967295, 4294967295, 7, 81, 24, 293, 42, 4294967295, 4294967295, 2, 82, 8, 335, 1, 4294967295, 4294967295, 7, 82, 24, 336, 2, 4294967295, 4294967295, 2, 83, 8, 338, 1, 4294967295, 4294967295, 7, 83, 24, 339, 1, 4294967295, 4294967295, 2, 84, 8, 340, 1, 4294967295, 4294967295, 7, 84, 24, 341, 7, 4294967295, 4294967295, 2, 85, 8, 348, 1, 4294967295, 4294967295, 7, 85, 24, 349, 2, 4294967295, 4294967295, 2, 86, 8, 351, 1, 4294967295, 4294967295, 7, 86, 24, 352, 1, 4294967295, 4294967295, 2, 87, 8, 353, 1, 4294967295, 4294967295, 7, 87, 24, 354, 3, 4294967295, 4294967295, 2, 88, 8, 357, 1, 4294967295, 4294967295, 7, 88, 24, 358, 1, 4294967295, 4294967295, 2, 89, 8, 359, 1, 4294967295, 4294967295, 7, 89, 24, 360, 1, 4294967295, 4294967295, 2, 90, 8, 361, 1, 4294967295, 4294967295, 7, 90, 24, 362, 2, 4294967295, 4294967295, 2, 91, 8, 364, 1, 4294967295, 4294967295, 7, 91, 24, 365, 1, 4294967295, 4294967295, 2, 92, 8, 366, 1, 4294967295, 4294967295, 7, 92, 24, 367, 2, 4294967295, 4294967295, 2, 93, 8, 369, 1, 4294967295, 4294967295, 7, 93, 24, 370, 1, 4294967295, 4294967295, 2, 94, 8, 371, 1, 4294967295, 4294967295, 7, 94, 24, 372, 1, 4294967295, 4294967295, 2, 95, 8, 373, 1, 4294967295, 4294967295, 7, 95, 24, 374, 1, 4294967295, 4294967295, 2, 96, 8, 375, 1, 4294967295, 4294967295, 7, 96, 24, 376, 4, 4294967295, 4294967295, 2, 97, 8, 380, 1, 4294967295, 4294967295, 7, 97, 24, 381, 2, 4294967295, 4294967295, 2, 98, 12, 383, 1, 4294967295, 4294967295, 7, 98, 24, 384, 32, 4294967295, 4294967295, 2, 99, 8, 416, 1, 4294967295, 4294967295, 7, 99, 24, 417, 3, 4294967295, 4294967295, 2, 100, 8, 420, 1, 4294967295, 4294967295, 7, 100, 24, 421, 1, 4294967295, 4294967295, 2, 101, 8, 422, 1, 4294967295, 4294967295, 7, 101, 24, 423, 2, 4294967295, 4294967295, 2, 102, 8, 425, 1, 4294967295, 4294967295, 7, 102, 24, 426, 1, 4294967295, 4294967295, 2, 103, 8, 427, 1, 4294967295, 4294967295, 7, 103, 24, 428, 1, 4294967295, 4294967295, 2, 104, 8, 429, 1, 4294967295, 4294967295, 7, 104, 24, 430, 1, 4294967295, 4294967295, 2, 105, 8, 431, 1, 4294967295, 4294967295, 7, 105, 24, 432, 1, 4294967295, 4294967295, 2, 106, 8, 433, 1, 4294967295, 4294967295, 7, 106, 24, 434, 2, 4294967295, 4294967295, 2, 107, 8, 436, 1, 4294967295, 4294967295, 7, 107, 24, 437, 1, 4294967295, 4294967295, 2, 108, 8, 438, 1, 4294967295, 4294967295, 7, 108, 24, 439, 1, 4294967295, 4294967295, 2, 109, 8, 440, 1, 4294967295, 4294967295, 7, 109, 24, 441, 2, 4294967295, 4294967295, 2, 110, 8, 443, 1, 4294967295, 4294967295, 7, 110, 24, 444, 1, 4294967295, 4294967295, 2, 111, 8, 445, 1, 4294967295, 4294967295, 7, 111, 24, 446, 2, 4294967295, 4294967295, 2, 112, 8, 448, 1, 4294967295, 4294967295, 7, 112, 24, 449, 1, 4294967295, 4294967295, 2, 113, 8, 450, 1, 4294967295, 4294967295, 7, 113, 24, 451, 2, 4294967295, 4294967295, 2, 114, 8, 453, 1, 4294967295, 4294967295, 7, 114, 24, 454, 1, 4294967295, 4294967295, 2, 115, 8, 455, 1, 4294967295, 4294967295, 7, 115, 24, 456, 1, 4294967295, 4294967295, 2, 116, 8, 457, 1, 4294967295, 4294967295, 7, 116, 24, 458, 2, 4294967295, 4294967295, 2, 117, 8, 460, 1, 4294967295, 4294967295, 7, 117, 24, 461, 1, 4294967295, 4294967295, 2, 118, 8, 462, 1, 4294967295, 4294967295, 7, 118, 24, 463, 2, 4294967295, 4294967295, 2, 119, 8, 465, 1, 4294967295, 4294967295, 7, 119, 24, 466, 1, 4294967295, 4294967295, 2, 120, 8, 467, 1, 4294967295, 4294967295, 7, 120, 24, 468, 5, 4294967295, 4294967295, 2, 121, 8, 473, 1, 4294967295, 4294967295, 7, 121, 24, 474, 7, 4294967295, 4294967295, 2, 122, 8, 481, 1, 4294967295, 4294967295, 7, 122, 24, 482, 23, 4294967295, 4294967295, 2, 123, 8, 505, 1, 4294967295, 4294967295, 7, 123, 24, 506, 2, 4294967295, 4294967295, 2, 124, 8, 508, 1, 4294967295, 4294967295, 7, 124, 24, 509, 7, 4294967295, 4294967295, 2, 125, 8, 516, 1, 4294967295, 4294967295, 7, 125, 24, 517, 2, 4294967295, 4294967295, 2, 126, 8, 519, 1, 4294967295, 4294967295, 7, 126, 24, 520, 2, 4294967295, 4294967295, 2, 127, 8, 522, 1, 4294967295, 4294967295, 7, 127, 24, 523, 7, 4294967295, 4294967295, 1, 0, 8, 530, 1, 4294967295, 4294967295, 3, 0, 8, 531, 2, 258, 4294967295, 8, 0, 8, 533, 1, 4294967295, 4294967295, 1, 0, 8, 534, 1, 4294967295, 4294967295, 1, 0, 32, 535, 1, 4294967295, 4294967295, 5, 0, 8, 536, 2, 262, 4294967295, 8, 0, 8, 538, 1, 4294967295, 4294967295, 10, 0, 8, 539, 2, 4294967295, 4294967295, 12, 0, 8, 541, 1, 4294967295, 265, 9, 0, 8, 542, 1, 4294967295, 4294967295, 1, 0, 8, 543, 1, 4294967295, 4294967295, 1, 0, 32, 544, 1, 4294967295, 4294967295, 5, 0, 8, 545, 2, 269, 4294967295, 8, 0, 8, 547, 1, 4294967295, 4294967295, 10, 0, 8, 548, 2, 4294967295, 4294967295, 12, 0, 8, 550, 1, 4294967295, 272, 9, 0, 8, 551, 1, 4294967295, 4294967295, 1, 0, 32, 552, 1, 4294967295, 4294967295, 1, 0, 8, 553, 1, 4294967295, 4294967295, 1, 0, 32, 554, 1, 4294967295, 4294967295, 1, 0, 8, 555, 1, 4294967295, 4294967295, 3, 0, 8, 556, 2, 278, 4294967295, 8, 0, 8, 558, 1, 4294967295, 4294967295, 1, 1, 8, 559, 1, 4294967295, 4294967295, 5, 1, 8, 560, 1, 281, 4294967295, 8, 1, 8, 561, 1, 4294967295, 4294967295, 10, 1, 8, 562, 2, 4294967295, 4294967295, 12, 1, 8, 564, 1, 4294967295, 284, 9, 1, 8, 565, 1, 4294967295, 4294967295, 1, 1, 8, 566, 1, 4294967295, 4294967295, 1, 1, 8, 567, 1, 4294967295, 4294967295, 1, 2, 8, 568, 1, 4294967295, 4294967295, 5, 2, 8, 569, 1, 289, 4294967295, 8, 2, 8, 570, 1, 4294967295, 4294967295, 10, 2, 8, 571, 2, 4294967295, 4294967295, 12, 2, 8, 573, 1, 4294967295, 292, 9, 2, 8, 574, 1, 4294967295, 4294967295, 1, 2, 32, 575, 1, 4294967295, 4294967295, 1, 2, 8, 576, 1, 4294967295, 4294967295, 1, 2, 32, 577, 1, 4294967295, 4294967295, 1, 2, 8, 578, 1, 4294967295, 4294967295, 1, 3, 32, 579, 1, 4294967295, 4294967295, 1, 3, 32, 580, 1, 4294967295, 4294967295, 3, 3, 8, 581, 2, 300, 4294967295, 8, 3, 8, 583, 1, 4294967295, 4294967295, 1, 3, 8, 584, 1, 4294967295, 4294967295, 1, 3, 32, 585, 1, 4294967295, 4294967295, 1, 3, 32, 586, 1, 4294967295, 4294967295, 3, 3, 8, 587, 2, 305, 4294967295, 8, 3, 8, 589, 1, 4294967295, 4294967295, 1, 3, 32, 590, 1, 4294967295, 4294967295, 1, 3, 8, 591, 1, 4294967295, 4294967295, 1, 4, 8, 592, 1, 4294967295, 4294967295, 5, 4, 8, 593, 1, 310, 4294967295, 8, 4, 8, 594, 1, 4294967295, 4294967295, 10, 4, 8, 595, 2, 4294967295, 4294967295, 12, 4, 8, 597, 1, 4294967295, 313, 9, 4, 8, 598, 1, 4294967295, 4294967295, 1, 4, 8, 599, 1, 4294967295, 4294967295, 1, 4, 8, 600, 1, 4294967295, 4294967295, 1, 4, 8, 601, 1, 4294967295, 4294967295, 1, 4, 8, 602, 1, 4294967295, 4294967295, 1, 4, 8, 603, 1, 4294967295, 4294967295, 3, 4, 8, 604, 5, 320, 4294967295, 8, 4, 8, 609, 1, 4294967295, 4294967295, 1, 5, 8, 610, 1, 4294967295, 4294967295, 1, 5, 32, 611, 1, 4294967295, 4294967295, 1, 5, 32, 612, 1, 4294967295, 4294967295, 1, 5, 32, 613, 1, 4294967295, 4294967295, 1, 5, 32, 614, 1, 4294967295, 4294967295, 3, 5, 8, 615, 5, 327, 4294967295, 8, 5, 8, 620, 1, 4294967295, 4294967295, 1, 6, 8, 621, 1, 4294967295, 4294967295, 1, 6, 32, 622, 1, 4294967295, 4294967295, 1, 6, 32, 623, 1, 4294967295, 4294967295, 1, 6, 32, 624, 1, 4294967295, 4294967295, 1, 6, 32, 625, 1, 4294967295, 4294967295, 1, 6, 32, 626, 1, 4294967295, 4294967295, 1, 6, 32, 627, 1, 4294967295, 4294967295, 1, 6, 32, 628, 1, 4294967295, 4294967295, 1, 6, 32, 629, 1, 4294967295, 4294967295, 1, 6, 32, 630, 1, 4294967295, 4294967295, 3, 6, 8, 631, 10, 339, 4294967295, 8, 6, 8, 641, 1, 4294967295, 4294967295, 1, 7, 32, 642, 1, 4294967295, 4294967295, 1, 7, 8, 643, 1, 4294967295, 4294967295, 3, 7, 8, 644, 2, 343, 4294967295, 8, 7, 8, 646, 1, 4294967295, 4294967295, 1, 8, 32, 647, 1, 4294967295, 4294967295, 1, 8, 8, 648, 1, 4294967295, 4294967295, 1, 8, 8, 649, 1, 4294967295, 4294967295, 3, 8, 8, 650, 2, 348, 4294967295, 8, 8, 8, 652, 1, 4294967295, 4294967295, 1, 8, 32, 653, 1, 4294967295, 4294967295, 1, 8, 8, 654, 1, 4294967295, 4294967295, 3, 8, 8, 655, 2, 352, 4294967295, 8, 8, 8, 657, 1, 4294967295, 4294967295, 1, 8, 32, 658, 1, 4294967295, 4294967295, 1, 8, 8, 659, 1, 4294967295, 4294967295, 3, 8, 8, 660, 2, 356, 4294967295, 8, 8, 8, 662, 1, 4294967295, 4294967295, 1, 8, 32, 663, 1, 4294967295, 4294967295, 1, 8, 8, 664, 1, 4294967295, 4294967295, 3, 8, 8, 665, 2, 360, 4294967295, 8, 8, 8, 667, 1, 4294967295, 4294967295, 1, 8, 8, 668, 1, 4294967295, 4294967295, 1, 8, 8, 669, 1, 4294967295, 4294967295, 1, 9, 32, 670, 1, 4294967295, 4294967295, 1, 9, 8, 671, 1, 4294967295, 4294967295, 1, 9, 32, 672, 1, 4294967295, 4294967295, 1, 9, 8, 673, 1, 4294967295, 4294967295, 5, 9, 8, 674, 1, 368, 4294967295, 8, 9, 8, 675, 1, 4294967295, 4294967295, 10, 9, 8, 676, 2, 4294967295, 4294967295, 12, 9, 8, 678, 1, 4294967295, 371, 9, 9, 8, 679, 1, 4294967295, 4294967295, 1, 9, 32, 680, 1, 4294967295, 4294967295, 1, 9, 8, 681, 1, 4294967295, 4294967295, 1, 10, 8, 682, 1, 4294967295, 4294967295, 5, 10, 8, 683, 1, 376, 4294967295, 8, 10, 8, 684, 1, 4294967295, 4294967295, 10, 10, 8, 685, 2, 4294967295, 4294967295, 12, 10, 8, 687, 1, 4294967295, 379, 9, 10, 8, 688, 1, 4294967295, 4294967295, 1, 10, 8, 689, 1, 4294967295, 4294967295, 1, 10, 32, 690, 1, 4294967295, 4294967295, 1, 10, 8, 691, 1, 4294967295, 4294967295, 5, 10, 8, 692, 1, 384, 4294967295, 8, 10, 8, 693, 1, 4294967295, 4294967295, 10, 10, 8, 694, 2, 4294967295, 4294967295, 12, 10, 8, 696, 1, 4294967295, 387, 9, 10, 8, 697, 1, 4294967295, 4294967295, 1, 10, 8, 698, 1, 4294967295, 4294967295, 3, 10, 8, 699, 2, 390, 4294967295, 8, 10, 8, 701, 1, 4294967295, 4294967295, 1, 11, 8, 702, 1, 4294967295, 4294967295, 1, 11, 32, 703, 1, 4294967295, 4294967295, 1, 11, 8, 704, 1, 4294967295, 4294967295, 5, 11, 8, 705, 1, 395, 4294967295, 8, 11, 8, 706, 1, 4294967295, 4294967295, 10, 11, 8, 707, 2, 4294967295, 4294967295, 12, 11, 8, 709, 1, 4294967295, 398, 9, 11, 8, 710, 1, 4294967295, 4294967295, 1, 12, 32, 711, 1, 4294967295, 4294967295, 1, 12, 8, 712, 1, 4294967295, 4294967295, 1, 12, 32, 713, 1, 4294967295, 4294967295, 1, 12, 8, 714, 1, 4294967295, 4294967295, 3, 12, 8, 715, 2, 404, 4294967295, 8, 12, 8, 717, 1, 4294967295, 4294967295, 1, 12, 32, 718, 1, 4294967295, 4294967295, 1, 12, 8, 719, 1, 4294967295, 4294967295, 3, 12, 8, 720, 2, 408, 4294967295, 8, 12, 8, 722, 1, 4294967295, 4294967295, 1, 12, 32, 723, 1, 4294967295, 4294967295, 3, 12, 8, 724, 2, 411, 4294967295, 8, 12, 8, 726, 1, 4294967295, 4294967295, 1, 12, 8, 727, 1, 4294967295, 4294967295, 3, 12, 8, 728, 2, 414, 4294967295, 8, 12, 8, 730, 1, 4294967295, 4294967295, 1, 12, 32, 731, 1, 4294967295, 4294967295, 1, 12, 8, 732, 1, 4294967295, 4294967295, 1, 13, 8, 733, 1, 4294967295, 4294967295, 1, 13, 32, 734, 1, 4294967295, 4294967295, 1, 13, 8, 735, 1, 4294967295, 4294967295, 5, 13, 8, 736, 1, 421, 4294967295, 8, 13, 8, 737, 1, 4294967295, 4294967295, 10, 13, 8, 738, 2, 4294967295, 4294967295, 12, 13, 8, 740, 1, 4294967295, 424, 9, 13, 8, 741, 1, 4294967295, 4294967295, 1, 14, 8, 742, 1, 4294967295, 4294967295, 5, 14, 8, 743, 1, 427, 4294967295, 8, 14, 8, 744, 1, 4294967295, 4294967295, 10, 14, 8, 745, 2, 4294967295, 4294967295, 12, 14, 8, 747, 1, 4294967295, 430, 9, 14, 8, 748, 1, 4294967295, 4294967295, 1, 14, 8, 749, 1, 4294967295, 4294967295, 1, 14, 8, 750, 1, 4294967295, 4294967295, 3, 14, 8, 751, 2, 434, 4294967295, 8, 14, 8, 753, 1, 4294967295, 4294967295, 1, 14, 8, 754, 1, 4294967295, 4294967295, 3, 14, 8, 755, 2, 437, 4294967295, 8, 14, 8, 757, 1, 4294967295, 4294967295, 1, 15, 32, 758, 1, 4294967295, 4294967295, 1, 15, 8, 759, 1, 4294967295, 4294967295, 5, 15, 8, 760, 1, 441, 4294967295, 8, 15, 8, 761, 1, 4294967295, 4294967295, 10, 15, 8, 762, 2, 4294967295, 4294967295, 12, 15, 8, 764, 1, 4294967295, 444, 9, 15, 8, 765, 1, 4294967295, 4294967295, 1, 16, 32, 766, 1, 4294967295, 4294967295, 1, 16, 8, 767, 1, 4294967295, 4294967295, 1, 16, 8, 768, 1, 4294967295, 4294967295, 3, 16, 8, 769, 2, 449, 4294967295, 8, 16, 8, 771, 1, 4294967295, 4294967295, 1, 16, 32, 772, 1, 4294967295, 4294967295, 1, 16, 8, 773, 1, 4294967295, 4294967295, 3, 16, 8, 774, 2, 453, 4294967295, 8, 16, 8, 776, 1, 4294967295, 4294967295, 1, 16, 32, 777, 1, 4294967295, 4294967295, 1, 16, 8, 778, 1, 4294967295, 4294967295, 3, 16, 8, 779, 2, 457, 4294967295, 8, 16, 8, 781, 1, 4294967295, 4294967295, 1, 16, 8, 782, 1, 4294967295, 4294967295, 1, 16, 8, 783, 1, 4294967295, 4294967295, 1, 17, 32, 784, 1, 4294967295, 4294967295, 1, 17, 8, 785, 1, 4294967295, 4294967295, 5, 17, 8, 786, 1, 463, 4294967295, 8, 17, 8, 787, 1, 4294967295, 4294967295, 10, 17, 8, 788, 2, 4294967295, 4294967295, 12, 17, 8, 790, 1, 4294967295, 466, 9, 17, 8, 791, 1, 4294967295, 4294967295, 1, 17, 32, 792, 1, 4294967295, 4294967295, 1, 17, 8, 793, 1, 4294967295, 4294967295, 1, 18, 32, 794, 1, 4294967295, 4294967295, 1, 18, 8, 795, 1, 4294967295, 4294967295, 5, 18, 8, 796, 1, 472, 4294967295, 8, 18, 8, 797, 1, 4294967295, 4294967295, 10, 18, 8, 798, 2, 4294967295, 4294967295, 12, 18, 8, 800, 1, 4294967295, 475, 9, 18, 8, 801, 1, 4294967295, 4294967295, 1, 18, 32, 802, 1, 4294967295, 4294967295, 1, 18, 8, 803, 1, 4294967295, 4294967295, 1, 19, 32, 804, 1, 4294967295, 4294967295, 1, 19, 32, 805, 1, 4294967295, 4294967295, 3, 19, 8, 806, 2, 481, 4294967295, 8, 19, 8, 808, 1, 4294967295, 4294967295, 1, 19, 8, 809, 1, 4294967295, 4294967295, 1, 19, 8, 810, 1, 4294967295, 4294967295, 5, 19, 8, 811, 1, 485, 4294967295, 8, 19, 8, 812, 1, 4294967295, 4294967295, 10, 19, 8, 813, 2, 4294967295, 4294967295, 12, 19, 8, 815, 1, 4294967295, 488, 9, 19, 8, 816, 1, 4294967295, 4294967295, 1, 19, 8, 817, 1, 4294967295, 4294967295, 3, 19, 8, 818, 3, 491, 4294967295, 8, 19, 8, 821, 1, 4294967295, 4294967295, 1, 20, 8, 822, 1, 4294967295, 4294967295, 1, 20, 8, 823, 1, 4294967295, 4294967295, 1, 20, 8, 824, 1, 4294967295, 4294967295, 1, 20, 8, 825, 1, 4294967295, 4294967295, 1, 20, 8, 826, 1, 4294967295, 4294967295, 1, 20, 8, 827, 1, 4294967295, 4294967295, 1, 20, 8, 828, 1, 4294967295, 4294967295, 1, 20, 8, 829, 1, 4294967295, 4294967295, 1, 20, 8, 830, 1, 4294967295, 4294967295, 1, 20, 8, 831, 1, 4294967295, 4294967295, 3, 20, 8, 832, 10, 503, 4294967295, 8, 20, 8, 842, 1, 4294967295, 4294967295, 1, 21, 8, 843, 1, 4294967295, 4294967295, 1, 21, 8, 844, 1, 4294967295, 4294967295, 1, 21, 8, 845, 1, 4294967295, 4294967295, 1, 21, 32, 846, 1, 4294967295, 4294967295, 1, 21, 32, 847, 1, 4294967295, 4294967295, 5, 21, 8, 848, 1, 510, 4294967295, 8, 21, 8, 849, 1, 4294967295, 4294967295, 10, 21, 8, 850, 2, 4294967295, 4294967295, 12, 21, 8, 852, 1, 4294967295, 513, 9, 21, 8, 853, 1, 4294967295, 4294967295, 1, 21, 32, 854, 1, 4294967295, 4294967295, 1, 21, 8, 855, 1, 4294967295, 4294967295, 3, 21, 8, 856, 2, 517, 4294967295, 8, 21, 8, 858, 1, 4294967295, 4294967295, 1, 21, 8, 859, 1, 4294967295, 4294967295, 1, 21, 8, 860, 1, 4294967295, 4294967295, 1, 22, 8, 861, 1, 4294967295, 4294967295, 1, 22, 32, 862, 1, 4294967295, 4294967295, 3, 22, 8, 863, 2, 523, 4294967295, 8, 22, 8, 865, 1, 4294967295, 4294967295, 1, 23, 8, 866, 1, 4294967295, 4294967295, 1, 23, 32, 867, 1, 4294967295, 4294967295, 3, 23, 8, 868, 2, 527, 4294967295, 8, 23, 8, 870, 1, 4294967295, 4294967295, 1, 24, 8, 871, 1, 4294967295, 4294967295, 1, 24, 8, 872, 1, 4294967295, 4294967295, 1, 24, 8, 873, 1, 4294967295, 4294967295, 1, 25, 8, 874, 1, 4294967295, 4294967295, 1, 25, 8, 875, 1, 4294967295, 4294967295, 1, 25, 8, 876, 1, 4294967295, 4294967295, 1, 26, 8, 877, 1, 4294967295, 4294967295, 1, 26, 8, 878, 1, 4294967295, 4294967295, 1, 26, 32, 879, 1, 4294967295, 4294967295, 1, 26, 8, 880, 1, 4294967295, 4294967295, 3, 26, 8, 881, 2, 539, 4294967295, 8, 26, 8, 883, 1, 4294967295, 4294967295, 1, 26, 8, 884, 1, 4294967295, 4294967295, 1, 26, 8, 885, 1, 4294967295, 4294967295, 1, 27, 8, 886, 1, 4294967295, 4294967295, 5, 27, 8, 887, 1, 544, 4294967295, 8, 27, 8, 888, 1, 4294967295, 4294967295, 10, 27, 8, 889, 2, 4294967295, 4294967295, 12, 27, 8, 891, 1, 4294967295, 547, 9, 27, 8, 892, 1, 4294967295, 4294967295, 1, 27, 8, 893, 1, 4294967295, 4294967295, 1, 27, 8, 894, 1, 4294967295, 4294967295, 1, 27, 8, 895, 1, 4294967295, 4294967295, 1, 28, 8, 896, 1, 4294967295, 4294967295, 1, 28, 8, 897, 1, 4294967295, 4294967295, 1, 28, 32, 898, 1, 4294967295, 4294967295, 1, 28, 8, 899, 1, 4294967295, 4294967295, 1, 29, 8, 900, 1, 4294967295, 4294967295, 5, 29, 8, 901, 1, 557, 4294967295, 8, 29, 8, 902, 1, 4294967295, 4294967295, 10, 29, 8, 903, 2, 4294967295, 4294967295, 12, 29, 8, 905, 1, 4294967295, 560, 9, 29, 8, 906, 1, 4294967295, 4294967295, 1, 29, 8, 907, 1, 4294967295, 4294967295, 1, 29, 32, 908, 1, 4294967295, 4294967295, 3, 29, 8, 909, 2, 564, 4294967295, 8, 29, 8, 911, 1, 4294967295, 4294967295, 1, 30, 8, 912, 1, 4294967295, 4294967295, 1, 30, 8, 913, 1, 4294967295, 4294967295, 1, 30, 8, 914, 1, 4294967295, 4294967295, 1, 30, 8, 915, 1, 4294967295, 4294967295, 1, 30, 8, 916, 1, 4294967295, 4294967295, 1, 30, 8, 917, 1, 4294967295, 4294967295, 1, 30, 8, 918, 1, 4294967295, 4294967295, 1, 30, 8, 919, 1, 4294967295, 4294967295, 3, 30, 8, 920, 8, 574, 4294967295, 8, 30, 8, 928, 1, 4294967295, 4294967295, 1, 31, 8, 929, 1, 4294967295, 4294967295, 1, 31, 8, 930, 1, 4294967295, 4294967295, 1, 31, 32, 931, 1, 4294967295, 4294967295, 1, 31, 8, 932, 1, 4294967295, 4294967295, 5, 31, 8, 933, 1, 580, 4294967295, 8, 31, 8, 934, 1, 4294967295, 4294967295, 10, 31, 8, 935, 2, 4294967295, 4294967295, 12, 31, 8, 937, 1, 4294967295, 583, 9, 31, 8, 938, 1, 4294967295, 4294967295, 1, 31, 32, 939, 1, 4294967295, 4294967295, 1, 31, 8, 940, 1, 4294967295, 4294967295, 1, 32, 8, 941, 1, 4294967295, 4294967295, 1, 32, 32, 942, 1, 4294967295, 4294967295, 1, 32, 32, 943, 1, 4294967295, 4294967295, 5, 32, 8, 944, 1, 590, 4294967295, 8, 32, 8, 945, 1, 4294967295, 4294967295, 10, 32, 8, 946, 2, 4294967295, 4294967295, 12, 32, 8, 948, 1, 4294967295, 593, 9, 32, 8, 949, 1, 4294967295, 4294967295, 1, 32, 32, 950, 1, 4294967295, 4294967295, 1, 32, 8, 951, 1, 4294967295, 4294967295, 1, 32, 8, 952, 1, 4294967295, 4294967295, 1, 33, 8, 953, 1, 4294967295, 4294967295, 5, 33, 8, 954, 1, 599, 4294967295, 8, 33, 8, 955, 1, 4294967295, 4294967295, 10, 33, 8, 956, 2, 4294967295, 4294967295, 12, 33, 8, 958, 1, 4294967295, 602, 9, 33, 8, 959, 1, 4294967295, 4294967295, 1, 33, 8, 960, 1, 4294967295, 4294967295, 1, 33, 8, 961, 1, 4294967295, 4294967295, 1, 34, 8, 962, 1, 4294967295, 4294967295, 1, 34, 32, 963, 1, 4294967295, 4294967295, 1, 34, 32, 964, 1, 4294967295, 4294967295, 1, 34, 32, 965, 1, 4294967295, 4294967295, 1, 34, 32, 966, 1, 4294967295, 4294967295, 1, 34, 32, 967, 1, 4294967295, 4294967295, 3, 34, 8, 968, 6, 612, 4294967295, 8, 34, 8, 974, 1, 4294967295, 4294967295, 1, 35, 8, 975, 1, 4294967295, 4294967295, 5, 35, 8, 976, 1, 615, 4294967295, 8, 35, 8, 977, 1, 4294967295, 4294967295, 10, 35, 8, 978, 2, 4294967295, 4294967295, 12, 35, 8, 980, 1, 4294967295, 618, 9, 35, 8, 981, 1, 4294967295, 4294967295, 1, 35, 8, 982, 1, 4294967295, 4294967295, 1, 35, 8, 983, 1, 4294967295, 4294967295, 1, 35, 8, 984, 1, 4294967295, 4294967295, 1, 36, 8, 985, 1, 4294967295, 4294967295, 5, 36, 8, 986, 1, 624, 4294967295, 8, 36, 8, 987, 1, 4294967295, 4294967295, 10, 36, 8, 988, 2, 4294967295, 4294967295, 12, 36, 8, 990, 1, 4294967295, 627, 9, 36, 8, 991, 1, 4294967295, 4294967295, 1, 36, 8, 992, 1, 4294967295, 4294967295, 1, 36, 8, 993, 1, 4294967295, 4294967295, 1, 36, 8, 994, 1, 4294967295, 4294967295, 1, 36, 32, 995, 1, 4294967295, 4294967295, 1, 36, 32, 996, 1, 4294967295, 4294967295, 5, 36, 8, 997, 1, 634, 4294967295, 8, 36, 8, 998, 1, 4294967295, 4294967295, 10, 36, 8, 999, 2, 4294967295, 4294967295, 12, 36, 8, 1001, 1, 4294967295, 637, 9, 36, 8, 1002, 1, 4294967295, 4294967295, 1, 36, 32, 1003, 1, 4294967295, 4294967295, 1, 36, 8, 1004, 1, 4294967295, 4294967295, 3, 36, 8, 1005, 2, 641, 4294967295, 8, 36, 8, 1007, 1, 4294967295, 4294967295, 1, 36, 8, 1008, 1, 4294967295, 4294967295, 1, 36, 8, 1009, 1, 4294967295, 4294967295, 1, 37, 8, 1010, 1, 4294967295, 4294967295, 1, 37, 32, 1011, 1, 4294967295, 4294967295, 1, 37, 8, 1012, 1, 4294967295, 4294967295, 5, 37, 8, 1013, 1, 648, 4294967295, 8, 37, 8, 1014, 1, 4294967295, 4294967295, 10, 37, 8, 1015, 2, 4294967295, 4294967295, 12, 37, 8, 1017, 1, 4294967295, 651, 9, 37, 8, 1018, 1, 4294967295, 4294967295, 1, 38, 8, 1019, 1, 4294967295, 4294967295, 1, 38, 32, 1020, 1, 4294967295, 4294967295, 1, 38, 8, 1021, 1, 4294967295, 4294967295, 3, 38, 8, 1022, 2, 656, 4294967295, 8, 38, 8, 1024, 1, 4294967295, 4294967295, 1, 39, 8, 1025, 1, 4294967295, 4294967295, 1, 39, 32, 1026, 1, 4294967295, 4294967295, 1, 39, 32, 1027, 1, 4294967295, 4294967295, 5, 39, 8, 1028, 1, 661, 4294967295, 8, 39, 8, 1029, 1, 4294967295, 4294967295, 10, 39, 8, 1030, 2, 4294967295, 4294967295, 12, 39, 8, 1032, 1, 4294967295, 664, 9, 39, 8, 1033, 1, 4294967295, 4294967295, 1, 40, 8, 1034, 1, 4294967295, 4294967295, 1, 40, 8, 1035, 1, 4294967295, 4294967295, 3, 40, 8, 1036, 2, 668, 4294967295, 8, 40, 8, 1038, 1, 4294967295, 4294967295, 1, 41, 32, 1039, 1, 4294967295, 4294967295, 1, 41, 8, 1040, 1, 4294967295, 4294967295, 1, 41, 32, 1041, 1, 4294967295, 4294967295, 1, 41, 8, 1042, 1, 4294967295, 4294967295, 5, 41, 8, 1043, 1, 674, 4294967295, 8, 41, 8, 1044, 1, 4294967295, 4294967295, 10, 41, 8, 1045, 2, 4294967295, 4294967295, 12, 41, 8, 1047, 1, 4294967295, 677, 9, 41, 8, 1048, 1, 4294967295, 4294967295, 1, 41, 32, 1049, 1, 4294967295, 4294967295, 3, 41, 8, 1050, 2, 680, 4294967295, 8, 41, 8, 1052, 1, 4294967295, 4294967295, 3, 41, 8, 1053, 2, 682, 4294967295, 8, 41, 8, 1055, 1, 4294967295, 4294967295, 1, 41, 32, 1056, 1, 4294967295, 4294967295, 1, 41, 8, 1057, 1, 4294967295, 4294967295, 1, 42, 8, 1058, 1, 4294967295, 4294967295, 1, 42, 32, 1059, 1, 4294967295, 4294967295, 1, 42, 8, 1060, 1, 4294967295, 4294967295, 5, 42, 8, 1061, 1, 689, 4294967295, 8, 42, 8, 1062, 1, 4294967295, 4294967295, 10, 42, 8, 1063, 2, 4294967295, 4294967295, 12, 42, 8, 1065, 1, 4294967295, 692, 9, 42, 8, 1066, 1, 4294967295, 4294967295, 3, 42, 8, 1067, 2, 694, 4294967295, 8, 42, 8, 1069, 1, 4294967295, 4294967295, 1, 42, 8, 1070, 1, 4294967295, 4294967295, 1, 42, 8, 1071, 1, 4294967295, 4294967295, 3, 42, 8, 1072, 2, 698, 4294967295, 8, 42, 8, 1074, 1, 4294967295, 4294967295, 4, 42, 8, 1075, 1, 700, 4294967295, 8, 42, 8, 1076, 1, 4294967295, 4294967295, 11, 42, 8, 1077, 2, 4294967295, 4294967295, 12, 42, 8, 1079, 1, 4294967295, 701, 1, 42, 32, 1080, 1, 4294967295, 4294967295, 1, 42, 8, 1081, 1, 4294967295, 4294967295, 5, 42, 8, 1082, 1, 706, 4294967295, 8, 42, 8, 1083, 1, 4294967295, 4294967295, 10, 42, 8, 1084, 2, 4294967295, 4294967295, 12, 42, 8, 1086, 1, 4294967295, 709, 9, 42, 8, 1087, 1, 4294967295, 4294967295, 1, 42, 8, 1088, 1, 4294967295, 4294967295, 1, 42, 8, 1089, 1, 4294967295, 4294967295, 3, 42, 8, 1090, 2, 713, 4294967295, 8, 42, 8, 1092, 1, 4294967295, 4294967295, 5, 42, 8, 1093, 1, 715, 4294967295, 8, 42, 8, 1094, 1, 4294967295, 4294967295, 10, 42, 8, 1095, 2, 4294967295, 4294967295, 12, 42, 8, 1097, 1, 4294967295, 718, 9, 42, 8, 1098, 1, 4294967295, 4294967295, 1, 43, 8, 1099, 1, 4294967295, 4294967295, 1, 43, 32, 1100, 1, 4294967295, 4294967295, 1, 43, 8, 1101, 1, 4294967295, 4294967295, 5, 43, 8, 1102, 1, 723, 4294967295, 8, 43, 8, 1103, 1, 4294967295, 4294967295, 10, 43, 8, 1104, 2, 4294967295, 4294967295, 12, 43, 8, 1106, 1, 4294967295, 726, 9, 43, 8, 1107, 1, 4294967295, 4294967295, 1, 44, 8, 1108, 1, 4294967295, 4294967295, 1, 44, 8, 1109, 1, 4294967295, 4294967295, 5, 44, 8, 1110, 1, 730, 4294967295, 8, 44, 8, 1111, 1, 4294967295, 4294967295, 10, 44, 8, 1112, 2, 4294967295, 4294967295, 12, 44, 8, 1114, 1, 4294967295, 733, 9, 44, 8, 1115, 1, 4294967295, 4294967295, 1, 44, 32, 1116, 1, 4294967295, 4294967295, 1, 44, 32, 1117, 1, 4294967295, 4294967295, 1, 44, 8, 1118, 1, 4294967295, 4294967295, 3, 44, 8, 1119, 2, 738, 4294967295, 8, 44, 8, 1121, 1, 4294967295, 4294967295, 3, 44, 8, 1122, 2, 740, 4294967295, 8, 44, 8, 1124, 1, 4294967295, 4294967295, 1, 45, 8, 1125, 1, 4294967295, 4294967295, 1, 45, 32, 1126, 1, 4294967295, 4294967295, 1, 45, 8, 1127, 1, 4294967295, 4294967295, 5, 45, 8, 1128, 1, 745, 4294967295, 8, 45, 8, 1129, 1, 4294967295, 4294967295, 10, 45, 8, 1130, 2, 4294967295, 4294967295, 12, 45, 8, 1132, 1, 4294967295, 748, 9, 45, 8, 1133, 1, 4294967295, 4294967295, 1, 46, 32, 1134, 1, 4294967295, 4294967295, 1, 46, 8, 1135, 1, 4294967295, 4294967295, 1, 46, 8, 1136, 1, 4294967295, 4294967295, 3, 46, 8, 1137, 2, 753, 4294967295, 8, 46, 8, 1139, 1, 4294967295, 4294967295, 1, 46, 32, 1140, 1, 4294967295, 4294967295, 1, 46, 8, 1141, 1, 4294967295, 4294967295, 5, 46, 8, 1142, 1, 757, 4294967295, 8, 46, 8, 1143, 1, 4294967295, 4294967295, 10, 46, 8, 1144, 2, 4294967295, 4294967295, 12, 46, 8, 1146, 1, 4294967295, 760, 9, 46, 8, 1147, 1, 4294967295, 4294967295, 3, 46, 8, 1148, 2, 762, 4294967295, 8, 46, 8, 1150, 1, 4294967295, 4294967295, 1, 46, 32, 1151, 1, 4294967295, 4294967295, 1, 46, 8, 1152, 1, 4294967295, 4294967295, 1, 47, 8, 1153, 1, 4294967295, 4294967295, 1, 47, 8, 1154, 1, 4294967295, 4294967295, 1, 47, 32, 1155, 1, 4294967295, 4294967295, 1, 47, 8, 1156, 1, 4294967295, 4294967295, 5, 47, 8, 1157, 1, 770, 4294967295, 8, 47, 8, 1158, 1, 4294967295, 4294967295, 10, 47, 8, 1159, 2, 4294967295, 4294967295, 12, 47, 8, 1161, 1, 4294967295, 773, 9, 47, 8, 1162, 1, 4294967295, 4294967295, 1, 47, 32, 1163, 1, 4294967295, 4294967295, 1, 47, 8, 1164, 1, 4294967295, 4294967295, 1, 48, 8, 1165, 1, 4294967295, 4294967295, 1, 48, 32, 1166, 1, 4294967295, 4294967295, 1, 48, 8, 1167, 1, 4294967295, 4294967295, 5, 48, 8, 1168, 1, 780, 4294967295, 8, 48, 8, 1169, 1, 4294967295, 4294967295, 10, 48, 8, 1170, 2, 4294967295, 4294967295, 12, 48, 8, 1172, 1, 4294967295, 783, 9, 48, 8, 1173, 1, 4294967295, 4294967295, 1, 49, 8, 1174, 1, 4294967295, 4294967295, 5, 49, 8, 1175, 1, 786, 4294967295, 8, 49, 8, 1176, 1, 4294967295, 4294967295, 10, 49, 8, 1177, 2, 4294967295, 4294967295, 12, 49, 8, 1179, 1, 4294967295, 789, 9, 49, 8, 1180, 1, 4294967295, 4294967295, 1, 49, 8, 1181, 1, 4294967295, 4294967295, 1, 49, 8, 1182, 1, 4294967295, 4294967295, 5, 49, 8, 1183, 1, 793, 4294967295, 8, 49, 8, 1184, 1, 4294967295, 4294967295, 10, 49, 8, 1185, 2, 4294967295, 4294967295, 12, 49, 8, 1187, 1, 4294967295, 796, 9, 49, 8, 1188, 1, 4294967295, 4294967295, 1, 49, 32, 1189, 1, 4294967295, 4294967295, 3, 49, 8, 1190, 2, 799, 4294967295, 8, 49, 8, 1192, 1, 4294967295, 4294967295, 1, 49, 8, 1193, 1, 4294967295, 4294967295, 1, 49, 8, 1194, 1, 4294967295, 4294967295, 1, 50, 8, 1195, 1, 4294967295, 4294967295, 1, 50, 32, 1196, 1, 4294967295, 4294967295, 1, 50, 8, 1197, 1, 4294967295, 4294967295, 5, 50, 8, 1198, 1, 806, 4294967295, 8, 50, 8, 1199, 1, 4294967295, 4294967295, 10, 50, 8, 1200, 2, 4294967295, 4294967295, 12, 50, 8, 1202, 1, 4294967295, 809, 9, 50, 8, 1203, 1, 4294967295, 4294967295, 1, 51, 8, 1204, 1, 4294967295, 4294967295, 5, 51, 8, 1205, 1, 812, 4294967295, 8, 51, 8, 1206, 1, 4294967295, 4294967295, 10, 51, 8, 1207, 2, 4294967295, 4294967295, 12, 51, 8, 1209, 1, 4294967295, 815, 9, 51, 8, 1210, 1, 4294967295, 4294967295, 1, 51, 32, 1211, 1, 4294967295, 4294967295, 1, 51, 8, 1212, 1, 4294967295, 4294967295, 1, 51, 8, 1213, 1, 4294967295, 4294967295, 1, 52, 8, 1214, 1, 4294967295, 4294967295, 1, 52, 32, 1215, 1, 4294967295, 4294967295, 1, 52, 8, 1216, 1, 4294967295, 4294967295, 5, 52, 8, 1217, 1, 823, 4294967295, 8, 52, 8, 1218, 1, 4294967295, 4294967295, 10, 52, 8, 1219, 2, 4294967295, 4294967295, 12, 52, 8, 1221, 1, 4294967295, 826, 9, 52, 8, 1222, 1, 4294967295, 4294967295, 1, 53, 8, 1223, 1, 4294967295, 4294967295, 1, 53, 8, 1224, 1, 4294967295, 4294967295, 1, 53, 32, 1225, 1, 4294967295, 4294967295, 1, 53, 32, 1226, 1, 4294967295, 4294967295, 1, 53, 32, 1227, 1, 4294967295, 4294967295, 1, 53, 32, 1228, 1, 4294967295, 4294967295, 1, 53, 32, 1229, 1, 4294967295, 4294967295, 3, 53, 8, 1230, 7, 835, 4294967295, 8, 53, 8, 1237, 1, 4294967295, 4294967295, 1, 54, 32, 1238, 1, 4294967295, 4294967295, 1, 54, 8, 1239, 1, 4294967295, 4294967295, 1, 55, 32, 1240, 1, 4294967295, 4294967295, 1, 55, 8, 1241, 1, 4294967295, 4294967295, 1, 56, 32, 1242, 1, 4294967295, 4294967295, 1, 56, 8, 1243, 1, 4294967295, 4294967295, 1, 56, 8, 1244, 1, 4294967295, 4294967295, 1, 56, 8, 1245, 1, 4294967295, 4294967295, 3, 56, 8, 1246, 2, 845, 4294967295, 8, 56, 8, 1248, 1, 4294967295, 4294967295, 1, 57, 32, 1249, 1, 4294967295, 4294967295, 1, 57, 8, 1250, 1, 4294967295, 4294967295, 1, 57, 32, 1251, 1, 4294967295, 4294967295, 1, 57, 8, 1252, 1, 4294967295, 4294967295, 5, 57, 8, 1253, 1, 851, 4294967295, 8, 57, 8, 1254, 1, 4294967295, 4294967295, 10, 57, 8, 1255, 2, 4294967295, 4294967295, 12, 57, 8, 1257, 1, 4294967295, 854, 9, 57, 8, 1258, 1, 4294967295, 4294967295, 3, 57, 8, 1259, 2, 856, 4294967295, 8, 57, 8, 1261, 1, 4294967295, 4294967295, 1, 57, 32, 1262, 1, 4294967295, 4294967295, 1, 57, 8, 1263, 1, 4294967295, 4294967295, 1, 58, 72, 1264, 1, 4294967295, 4294967295, 1, 58, 8, 1265, 1, 4294967295, 4294967295, 1, 58, 8, 1266, 1, 4294967295, 4294967295, 1, 58, 32, 1267, 1, 4294967295, 4294967295, 1, 58, 8, 1268, 1, 4294967295, 4294967295, 1, 58, 8, 1269, 1, 4294967295, 4294967295, 3, 58, 8, 1270, 2, 866, 4294967295, 8, 58, 8, 1272, 1, 4294967295, 4294967295, 1, 59, 8, 1273, 1, 4294967295, 4294967295, 1, 59, 8, 1274, 1, 4294967295, 4294967295, 1, 59, 32, 1275, 1, 4294967295, 4294967295, 1, 59, 8, 1276, 1, 4294967295, 4294967295, 1, 59, 32, 1277, 1, 4294967295, 4294967295, 1, 59, 8, 1278, 1, 4294967295, 4294967295, 5, 59, 8, 1279, 1, 874, 4294967295, 8, 59, 8, 1280, 1, 4294967295, 4294967295, 10, 59, 8, 1281, 2, 4294967295, 4294967295, 12, 59, 8, 1283, 1, 4294967295, 877, 9, 59, 8, 1284, 1, 4294967295, 4294967295, 3, 59, 8, 1285, 2, 879, 4294967295, 8, 59, 8, 1287, 1, 4294967295, 4294967295, 1, 59, 32, 1288, 1, 4294967295, 4294967295, 3, 59, 8, 1289, 2, 882, 4294967295, 8, 59, 8, 1291, 1, 4294967295, 4294967295, 1, 59, 32, 1292, 1, 4294967295, 4294967295, 3, 59, 8, 1293, 3, 885, 4294967295, 8, 59, 8, 1296, 1, 4294967295, 4294967295, 1, 60, 8, 1297, 1, 4294967295, 4294967295, 1, 60, 8, 1298, 1, 4294967295, 4294967295, 1, 60, 8, 1299, 1, 4294967295, 4294967295, 3, 60, 8, 1300, 3, 890, 4294967295, 8, 60, 8, 1303, 1, 4294967295, 4294967295, 1, 61, 32, 1304, 1, 4294967295, 4294967295, 1, 61, 8, 1305, 1, 4294967295, 4294967295, 1, 61, 32, 1306, 1, 4294967295, 4294967295, 1, 61, 8, 1307, 1, 4294967295, 4294967295, 5, 61, 8, 1308, 1, 896, 4294967295, 8, 61, 8, 1309, 1, 4294967295, 4294967295, 10, 61, 8, 1310, 2, 4294967295, 4294967295, 12, 61, 8, 1312, 1, 4294967295, 899, 9, 61, 8, 1313, 1, 4294967295, 4294967295, 3, 61, 8, 1314, 2, 901, 4294967295, 8, 61, 8, 1316, 1, 4294967295, 4294967295, 1, 61, 32, 1317, 1, 4294967295, 4294967295, 3, 61, 8, 1318, 2, 904, 4294967295, 8, 61, 8, 1320, 1, 4294967295, 4294967295, 1, 61, 32, 1321, 1, 4294967295, 4294967295, 1, 61, 8, 1322, 1, 4294967295, 4294967295, 1, 62, 32, 1323, 1, 4294967295, 4294967295, 1, 62, 32, 1324, 1, 4294967295, 4294967295, 1, 62, 8, 1325, 1, 4294967295, 4294967295, 1, 62, 8, 1326, 1, 4294967295, 4294967295, 1, 62, 8, 1327, 1, 4294967295, 4294967295, 1, 63, 32, 1328, 1, 4294967295, 4294967295, 1, 63, 8, 1329, 1, 4294967295, 4294967295, 5, 63, 8, 1330, 1, 915, 4294967295, 8, 63, 8, 1331, 1, 4294967295, 4294967295, 10, 63, 8, 1332, 2, 4294967295, 4294967295, 12, 63, 8, 1334, 1, 4294967295, 918, 9, 63, 8, 1335, 1, 4294967295, 4294967295, 1, 63, 32, 1336, 1, 4294967295, 4294967295, 1, 63, 8, 1337, 1, 4294967295, 4294967295, 1, 64, 8, 1338, 1, 4294967295, 4294967295, 5, 64, 8, 1339, 1, 923, 4294967295, 8, 64, 8, 1340, 1, 4294967295, 4294967295, 10, 64, 8, 1341, 2, 4294967295, 4294967295, 12, 64, 8, 1343, 1, 4294967295, 926, 9, 64, 8, 1344, 1, 4294967295, 4294967295, 1, 64, 8, 1345, 1, 4294967295, 4294967295, 1, 64, 32, 1346, 1, 4294967295, 4294967295, 3, 64, 8, 1347, 2, 930, 4294967295, 8, 64, 8, 1349, 1, 4294967295, 4294967295, 1, 65, 8, 1350, 1, 4294967295, 4294967295, 1, 65, 8, 1351, 1, 4294967295, 4294967295, 1, 65, 32, 1352, 1, 4294967295, 4294967295, 1, 65, 8, 1353, 1, 4294967295, 4294967295, 1, 65, 8, 1354, 1, 4294967295, 4294967295, 1, 65, 32, 1355, 1, 4294967295, 4294967295, 3, 65, 8, 1356, 2, 938, 4294967295, 8, 65, 8, 1358, 1, 4294967295, 4294967295, 1, 65, 8, 1359, 1, 4294967295, 4294967295, 1, 65, 32, 1360, 1, 4294967295, 4294967295, 3, 65, 8, 1361, 2, 942, 4294967295, 8, 65, 8, 1363, 1, 4294967295, 4294967295, 1, 65, 8, 1364, 1, 4294967295, 4294967295, 1, 65, 32, 1365, 1, 4294967295, 4294967295, 3, 65, 8, 1366, 2, 946, 4294967295, 8, 65, 8, 1368, 1, 4294967295, 4294967295, 1, 65, 8, 1369, 1, 4294967295, 4294967295, 1, 65, 32, 1370, 1, 4294967295, 4294967295, 3, 65, 8, 1371, 2, 950, 4294967295, 8, 65, 8, 1373, 1, 4294967295, 4294967295, 1, 65, 8, 1374, 1, 4294967295, 4294967295, 1, 65, 32, 1375, 1, 4294967295, 4294967295, 3, 65, 8, 1376, 2, 954, 4294967295, 8, 65, 8, 1378, 1, 4294967295, 4294967295, 3, 65, 8, 1379, 6, 956, 4294967295, 8, 65, 8, 1385, 1, 4294967295, 4294967295, 1, 66, 8, 1386, 1, 4294967295, 4294967295, 1, 66, 8, 1387, 1, 4294967295, 4294967295, 3, 66, 8, 1388, 2, 960, 4294967295, 8, 66, 8, 1390, 1, 4294967295, 4294967295, 1, 67, 8, 1391, 1, 4294967295, 4294967295, 1, 67, 32, 1392, 1, 4294967295, 4294967295, 1, 67, 32, 1393, 1, 4294967295, 4294967295, 1, 67, 8, 1394, 1, 4294967295, 4294967295, 3, 67, 8, 1395, 2, 966, 4294967295, 8, 67, 8, 1397, 1, 4294967295, 4294967295, 1, 68, 8, 1398, 1, 4294967295, 4294967295, 1, 68, 8, 1399, 1, 4294967295, 4294967295, 1, 69, 32, 1400, 1, 4294967295, 4294967295, 1, 69, 8, 1401, 1, 4294967295, 4294967295, 1, 69, 8, 1402, 1, 4294967295, 4294967295, 1, 70, 8, 1403, 1, 4294967295, 4294967295, 5, 70, 8, 1404, 1, 974, 4294967295, 8, 70, 8, 1405, 1, 4294967295, 4294967295, 10, 70, 8, 1406, 2, 4294967295, 4294967295, 12, 70, 8, 1408, 1, 4294967295, 977, 9, 70, 8, 1409, 1, 4294967295, 4294967295, 1, 70, 32, 1410, 1, 4294967295, 4294967295, 3, 70, 8, 1411, 2, 980, 4294967295, 8, 70, 8, 1413, 1, 4294967295, 4294967295, 1, 70, 32, 1414, 1, 4294967295, 4294967295, 1, 70, 8, 1415, 1, 4294967295, 4294967295, 1, 70, 32, 1416, 1, 4294967295, 4294967295, 1, 70, 8, 1417, 1, 4294967295, 4294967295, 5, 70, 8, 1418, 1, 986, 4294967295, 8, 70, 8, 1419, 1, 4294967295, 4294967295, 10, 70, 8, 1420, 2, 4294967295, 4294967295, 12, 70, 8, 1422, 1, 4294967295, 989, 9, 70, 8, 1423, 1, 4294967295, 4294967295, 1, 70, 32, 1424, 1, 4294967295, 4294967295, 1, 70, 8, 1425, 1, 4294967295, 4294967295, 1, 71, 32, 1426, 1, 4294967295, 4294967295, 1, 71, 8, 1427, 1, 4294967295, 4294967295, 5, 71, 8, 1428, 1, 995, 4294967295, 8, 71, 8, 1429, 1, 4294967295, 4294967295, 10, 71, 8, 1430, 2, 4294967295, 4294967295, 12, 71, 8, 1432, 1, 4294967295, 998, 9, 71, 8, 1433, 1, 4294967295, 4294967295, 1, 71, 8, 1434, 1, 4294967295, 4294967295, 1, 71, 32, 1435, 1, 4294967295, 4294967295, 1, 71, 8, 1436, 1, 4294967295, 4294967295, 1, 71, 32, 1437, 1, 4294967295, 4294967295, 1, 71, 8, 1438, 1, 4294967295, 4294967295, 1, 71, 32, 1439, 1, 4294967295, 4294967295, 1, 71, 8, 1440, 1, 4294967295, 4294967295, 1, 71, 32, 1441, 1, 4294967295, 4294967295, 1, 71, 8, 1442, 1, 4294967295, 4294967295, 5, 71, 8, 1443, 1, 1009, 4294967295, 8, 71, 8, 1444, 1, 4294967295, 4294967295, 10, 71, 8, 1445, 2, 4294967295, 4294967295, 12, 71, 8, 1447, 1, 4294967295, 1012, 9, 71, 8, 1448, 1, 4294967295, 4294967295, 3, 71, 8, 1449, 2, 1014, 4294967295, 8, 71, 8, 1451, 1, 4294967295, 4294967295, 1, 71, 32, 1452, 1, 4294967295, 4294967295, 1, 71, 8, 1453, 1, 4294967295, 4294967295, 1, 71, 32, 1454, 1, 4294967295, 4294967295, 1, 71, 8, 1455, 1, 4294967295, 4294967295, 1, 71, 32, 1456, 1, 4294967295, 4294967295, 1, 71, 8, 1457, 1, 4294967295, 4294967295, 1, 71, 32, 1458, 1, 4294967295, 4294967295, 1, 71, 8, 1459, 1, 4294967295, 4294967295, 5, 71, 8, 1460, 1, 1024, 4294967295, 8, 71, 8, 1461, 1, 4294967295, 4294967295, 10, 71, 8, 1462, 2, 4294967295, 4294967295, 12, 71, 8, 1464, 1, 4294967295, 1027, 9, 71, 8, 1465, 1, 4294967295, 4294967295, 3, 71, 8, 1466, 2, 1029, 4294967295, 8, 71, 8, 1468, 1, 4294967295, 4294967295, 1, 71, 32, 1469, 1, 4294967295, 4294967295, 1, 71, 8, 1470, 1, 4294967295, 4294967295, 1, 71, 32, 1471, 1, 4294967295, 4294967295, 1, 71, 8, 1472, 1, 4294967295, 4294967295, 1, 71, 32, 1473, 1, 4294967295, 4294967295, 1, 71, 8, 1474, 1, 4294967295, 4294967295, 1, 71, 32, 1475, 1, 4294967295, 4294967295, 1, 71, 8, 1476, 1, 4294967295, 4294967295, 1, 71, 32, 1477, 1, 4294967295, 4294967295, 1, 71, 8, 1478, 1, 4294967295, 4294967295, 1, 71, 32, 1479, 1, 4294967295, 4294967295, 1, 71, 8, 1480, 1, 4294967295, 4294967295, 5, 71, 8, 1481, 1, 1043, 4294967295, 8, 71, 8, 1482, 1, 4294967295, 4294967295, 10, 71, 8, 1483, 2, 4294967295, 4294967295, 12, 71, 8, 1485, 1, 4294967295, 1046, 9, 71, 8, 1486, 1, 4294967295, 4294967295, 1, 71, 32, 1487, 1, 4294967295, 4294967295, 1, 71, 8, 1488, 1, 4294967295, 4294967295, 3, 71, 8, 1489, 5, 1050, 4294967295, 8, 71, 8, 1494, 1, 4294967295, 4294967295, 1, 72, 32, 1495, 1, 4294967295, 4294967295, 1, 72, 8, 1496, 1, 4294967295, 4294967295, 1, 73, 32, 1497, 1, 4294967295, 4294967295, 1, 73, 8, 1498, 1, 4294967295, 4294967295, 1, 73, 8, 1499, 1, 4294967295, 4294967295, 3, 73, 8, 1500, 2, 1057, 4294967295, 8, 73, 8, 1502, 1, 4294967295, 4294967295, 1, 73, 8, 1503, 1, 4294967295, 4294967295, 1, 73, 32, 1504, 1, 4294967295, 4294967295, 1, 73, 8, 1505, 1, 4294967295, 4294967295, 3, 73, 8, 1506, 2, 1062, 4294967295, 8, 73, 8, 1508, 1, 4294967295, 4294967295, 1, 73, 8, 1509, 1, 4294967295, 4294967295, 1, 73, 8, 1510, 1, 4294967295, 4294967295, 1, 74, 32, 1511, 1, 4294967295, 4294967295, 1, 74, 8, 1512, 1, 4294967295, 4294967295, 3, 74, 8, 1513, 2, 1068, 4294967295, 8, 74, 8, 1515, 1, 4294967295, 4294967295, 1, 74, 32, 1516, 1, 4294967295, 4294967295, 1, 74, 8, 1517, 1, 4294967295, 4294967295, 1, 75, 8, 1518, 1, 4294967295, 4294967295, 1, 75, 32, 1519, 1, 4294967295, 4294967295, 1, 75, 8, 1520, 1, 4294967295, 4294967295, 5, 75, 8, 1521, 1, 1075, 4294967295, 8, 75, 8, 1522, 1, 4294967295, 4294967295, 10, 75, 8, 1523, 2, 4294967295, 4294967295, 12, 75, 8, 1525, 1, 4294967295, 1078, 9, 75, 8, 1526, 1, 4294967295, 4294967295, 1, 75, 72, 1527, 1, 4294967295, 4294967295, 1, 75, 8, 1528, 1, 4294967295, 4294967295, 1, 76, 8, 1529, 1, 4294967295, 4294967295, 5, 76, 8, 1530, 1, 1083, 4294967295, 8, 76, 8, 1531, 1, 4294967295, 4294967295, 10, 76, 8, 1532, 2, 4294967295, 4294967295, 12, 76, 8, 1534, 1, 4294967295, 1086, 9, 76, 8, 1535, 1, 4294967295, 4294967295, 1, 76, 8, 1536, 1, 4294967295, 4294967295, 1, 76, 8, 1537, 1, 4294967295, 4294967295, 5, 76, 8, 1538, 1, 1090, 4294967295, 8, 76, 8, 1539, 1, 4294967295, 4294967295, 10, 76, 8, 1540, 2, 4294967295, 4294967295, 12, 76, 8, 1542, 1, 4294967295, 1093, 9, 76, 8, 1543, 1, 4294967295, 4294967295, 1, 76, 32, 1544, 1, 4294967295, 4294967295, 3, 76, 8, 1545, 2, 1096, 4294967295, 8, 76, 8, 1547, 1, 4294967295, 4294967295, 1, 76, 8, 1548, 1, 4294967295, 4294967295, 1, 76, 8, 1549, 1, 4294967295, 4294967295, 1, 77, 32, 1550, 1, 4294967295, 4294967295, 1, 77, 8, 1551, 1, 4294967295, 4294967295, 1, 77, 8, 1552, 1, 4294967295, 4294967295, 5, 77, 8, 1553, 2, 1103, 4294967295, 8, 77, 8, 1555, 1, 4294967295, 4294967295, 10, 77, 8, 1556, 2, 4294967295, 4294967295, 12, 77, 8, 1558, 1, 4294967295, 1106, 9, 77, 8, 1559, 1, 4294967295, 4294967295, 1, 77, 32, 1560, 1, 4294967295, 4294967295, 1, 77, 8, 1561, 1, 4294967295, 4294967295, 1, 78, 32, 1562, 1, 4294967295, 4294967295, 1, 78, 8, 1563, 1, 4294967295, 4294967295, 5, 78, 8, 1564, 1, 1112, 4294967295, 8, 78, 8, 1565, 1, 4294967295, 4294967295, 10, 78, 8, 1566, 2, 4294967295, 4294967295, 12, 78, 8, 1568, 1, 4294967295, 1115, 9, 78, 8, 1569, 1, 4294967295, 4294967295, 1, 78, 32, 1570, 1, 4294967295, 4294967295, 1, 78, 8, 1571, 1, 4294967295, 4294967295, 1, 79, 8, 1572, 1, 4294967295, 4294967295, 1, 79, 32, 1573, 1, 4294967295, 4294967295, 1, 79, 8, 1574, 1, 4294967295, 4294967295, 1, 79, 8, 1575, 1, 4294967295, 4294967295, 1, 79, 8, 1576, 1, 4294967295, 4294967295, 3, 79, 8, 1577, 3, 1124, 4294967295, 8, 79, 8, 1580, 1, 4294967295, 4294967295, 1, 80, 8, 1581, 1, 4294967295, 4294967295, 5, 80, 8, 1582, 1, 1127, 4294967295, 8, 80, 8, 1583, 1, 4294967295, 4294967295, 10, 80, 8, 1584, 2, 4294967295, 4294967295, 12, 80, 8, 1586, 1, 4294967295, 1130, 9, 80, 8, 1587, 1, 4294967295, 4294967295, 1, 80, 32, 1588, 1, 4294967295, 4294967295, 1, 80, 8, 1589, 1, 4294967295, 4294967295, 1, 80, 32, 1590, 1, 4294967295, 4294967295, 1, 80, 8, 1591, 1, 4294967295, 4294967295, 1, 80, 8, 1592, 1, 4294967295, 4294967295, 1, 80, 8, 1593, 1, 4294967295, 4294967295, 1, 80, 8, 1594, 1, 4294967295, 4294967295, 1, 80, 8, 1595, 1, 4294967295, 4294967295, 3, 80, 8, 1596, 2, 1140, 4294967295, 8, 80, 8, 1598, 1, 4294967295, 4294967295, 1, 81, 32, 1599, 1, 4294967295, 4294967295, 1, 81, 8, 1600, 1, 4294967295, 4294967295, 1, 82, 32, 1601, 1, 4294967295, 4294967295, 1, 82, 8, 1602, 1, 4294967295, 4294967295, 1, 83, 8, 1603, 1, 4294967295, 4294967295, 5, 83, 8, 1604, 1, 1147, 4294967295, 8, 83, 8, 1605, 1, 4294967295, 4294967295, 10, 83, 8, 1606, 2, 4294967295, 4294967295, 12, 83, 8, 1608, 1, 4294967295, 1150, 9, 83, 8, 1609, 1, 4294967295, 4294967295, 1, 83, 8, 1610, 1, 4294967295, 4294967295, 1, 83, 8, 1611, 1, 4294967295, 4294967295, 1, 83, 8, 1612, 1, 4294967295, 4294967295, 1, 83, 8, 1613, 1, 4294967295, 4294967295, 3, 83, 8, 1614, 4, 1156, 4294967295, 8, 83, 8, 1618, 1, 4294967295, 4294967295, 1, 84, 8, 1619, 1, 4294967295, 4294967295, 1, 84, 32, 1620, 1, 4294967295, 4294967295, 1, 84, 8, 1621, 1, 4294967295, 4294967295, 1, 84, 32, 1622, 1, 4294967295, 4294967295, 1, 84, 8, 1623, 1, 4294967295, 4294967295, 3, 84, 8, 1624, 2, 1163, 4294967295, 8, 84, 8, 1626, 1, 4294967295, 4294967295, 1, 84, 32, 1627, 1, 4294967295, 4294967295, 1, 84, 8, 1628, 1, 4294967295, 4294967295, 1, 84, 32, 1629, 1, 4294967295, 4294967295, 1, 84, 32, 1630, 1, 4294967295, 4294967295, 1, 84, 8, 1631, 1, 4294967295, 4294967295, 1, 84, 32, 1632, 1, 4294967295, 4294967295, 1, 84, 8, 1633, 1, 4294967295, 4294967295, 1, 84, 32, 1634, 1, 4294967295, 4294967295, 1, 84, 8, 1635, 1, 4294967295, 4294967295, 3, 84, 8, 1636, 2, 1174, 4294967295, 8, 84, 8, 1638, 1, 4294967295, 4294967295, 1, 84, 32, 1639, 1, 4294967295, 4294967295, 1, 84, 32, 1640, 1, 4294967295, 4294967295, 1, 84, 8, 1641, 1, 4294967295, 4294967295, 1, 84, 32, 1642, 1, 4294967295, 4294967295, 1, 84, 8, 1643, 1, 4294967295, 4294967295, 1, 84, 8, 1644, 1, 4294967295, 4294967295, 1, 84, 32, 1645, 1, 4294967295, 4294967295, 1, 84, 32, 1646, 1, 4294967295, 4294967295, 1, 84, 8, 1647, 1, 4294967295, 4294967295, 1, 84, 32, 1648, 1, 4294967295, 4294967295, 1, 84, 8, 1649, 1, 4294967295, 4294967295, 1, 84, 8, 1650, 1, 4294967295, 4294967295, 1, 84, 32, 1651, 1, 4294967295, 4294967295, 1, 84, 8, 1652, 1, 4294967295, 4294967295, 1, 84, 32, 1653, 1, 4294967295, 4294967295, 1, 84, 32, 1654, 1, 4294967295, 4294967295, 1, 84, 8, 1655, 1, 4294967295, 4294967295, 1, 84, 32, 1656, 1, 4294967295, 4294967295, 1, 84, 32, 1657, 1, 4294967295, 4294967295, 1, 84, 8, 1658, 1, 4294967295, 4294967295, 1, 84, 32, 1659, 1, 4294967295, 4294967295, 1, 84, 8, 1660, 1, 4294967295, 4294967295, 1, 84, 8, 1661, 1, 4294967295, 4294967295, 4, 84, 8, 1662, 1, 1199, 4294967295, 8, 84, 8, 1663, 1, 4294967295, 4294967295, 11, 84, 8, 1664, 2, 4294967295, 4294967295, 12, 84, 8, 1666, 1, 4294967295, 1200, 1, 84, 8, 1667, 1, 4294967295, 4294967295, 3, 84, 8, 1668, 2, 1204, 4294967295, 8, 84, 8, 1670, 1, 4294967295, 4294967295, 1, 84, 8, 1671, 1, 4294967295, 4294967295, 3, 84, 8, 1672, 2, 1207, 4294967295, 8, 84, 8, 1674, 1, 4294967295, 4294967295, 1, 84, 32, 1675, 1, 4294967295, 4294967295, 1, 84, 8, 1676, 1, 4294967295, 4294967295, 1, 84, 8, 1677, 1, 4294967295, 4294967295, 1, 84, 8, 1678, 1, 4294967295, 4294967295, 5, 84, 8, 1679, 1, 1213, 4294967295, 8, 84, 8, 1680, 1, 4294967295, 4294967295, 10, 84, 8, 1681, 2, 4294967295, 4294967295, 12, 84, 8, 1683, 1, 4294967295, 1216, 9, 84, 8, 1684, 1, 4294967295, 4294967295, 1, 84, 8, 1685, 1, 4294967295, 4294967295, 3, 84, 8, 1686, 2, 1219, 4294967295, 8, 84, 8, 1688, 1, 4294967295, 4294967295, 1, 84, 32, 1689, 1, 4294967295, 4294967295, 1, 84, 32, 1690, 1, 4294967295, 4294967295, 1, 84, 8, 1691, 1, 4294967295, 4294967295, 1, 84, 32, 1692, 1, 4294967295, 4294967295, 1, 84, 32, 1693, 1, 4294967295, 4294967295, 1, 84, 8, 1694, 1, 4294967295, 4294967295, 5, 84, 8, 1695, 1, 1227, 4294967295, 8, 84, 8, 1696, 1, 4294967295, 4294967295, 10, 84, 8, 1697, 2, 4294967295, 4294967295, 12, 84, 8, 1699, 1, 4294967295, 1230, 9, 84, 8, 1700, 1, 4294967295, 4294967295, 1, 84, 8, 1701, 1, 4294967295, 4294967295, 5, 84, 8, 1702, 1, 1233, 4294967295, 8, 84, 8, 1703, 1, 4294967295, 4294967295, 10, 84, 8, 1704, 2, 4294967295, 4294967295, 12, 84, 8, 1706, 1, 4294967295, 1236, 9, 84, 8, 1707, 1, 4294967295, 4294967295, 1, 84, 32, 1708, 1, 4294967295, 4294967295, 1, 84, 8, 1709, 1, 4294967295, 4294967295, 1, 84, 32, 1710, 1, 4294967295, 4294967295, 1, 84, 32, 1711, 1, 4294967295, 4294967295, 1, 84, 8, 1712, 1, 4294967295, 4294967295, 1, 84, 32, 1713, 1, 4294967295, 4294967295, 1, 84, 8, 1714, 1, 4294967295, 4294967295, 1, 84, 8, 1715, 1, 4294967295, 4294967295, 1, 84, 32, 1716, 1, 4294967295, 4294967295, 1, 84, 8, 1717, 1, 4294967295, 4294967295, 3, 84, 8, 1718, 2, 1248, 4294967295, 8, 84, 8, 1720, 1, 4294967295, 4294967295, 1, 84, 32, 1721, 1, 4294967295, 4294967295, 1, 84, 32, 1722, 1, 4294967295, 4294967295, 1, 84, 8, 1723, 1, 4294967295, 4294967295, 1, 84, 32, 1724, 1, 4294967295, 4294967295, 1, 84, 8, 1725, 1, 4294967295, 4294967295, 1, 84, 32, 1726, 1, 4294967295, 4294967295, 1, 84, 8, 1727, 1, 4294967295, 4294967295, 3, 84, 8, 1728, 2, 1257, 4294967295, 8, 84, 8, 1730, 1, 4294967295, 4294967295, 1, 84, 32, 1731, 1, 4294967295, 4294967295, 1, 84, 32, 1732, 1, 4294967295, 4294967295, 1, 84, 8, 1733, 1, 4294967295, 4294967295, 3, 84, 8, 1734, 2, 1262, 4294967295, 8, 84, 8, 1736, 1, 4294967295, 4294967295, 1, 84, 32, 1737, 1, 4294967295, 4294967295, 1, 84, 32, 1738, 1, 4294967295, 4294967295, 1, 84, 8, 1739, 1, 4294967295, 4294967295, 1, 84, 32, 1740, 1, 4294967295, 4294967295, 1, 84, 8, 1741, 1, 4294967295, 4294967295, 1, 84, 32, 1742, 1, 4294967295, 4294967295, 1, 84, 8, 1743, 1, 4294967295, 4294967295, 1, 84, 32, 1744, 1, 4294967295, 4294967295, 1, 84, 8, 1745, 1, 4294967295, 4294967295, 1, 84, 8, 1746, 1, 4294967295, 4294967295, 1, 84, 32, 1747, 1, 4294967295, 4294967295, 3, 84, 8, 1748, 2, 1275, 4294967295, 8, 84, 8, 1750, 1, 4294967295, 4294967295, 1, 84, 8, 1751, 1, 4294967295, 4294967295, 1, 84, 32, 1752, 1, 4294967295, 4294967295, 1, 84, 8, 1753, 1, 4294967295, 4294967295, 1, 84, 8, 1754, 1, 4294967295, 4294967295, 3, 84, 8, 1755, 19, 1281, 4294967295, 8, 84, 8, 1774, 1, 4294967295, 4294967295, 1, 85, 32, 1775, 1, 4294967295, 4294967295, 1, 85, 32, 1776, 1, 4294967295, 4294967295, 1, 85, 8, 1777, 1, 4294967295, 4294967295, 5, 85, 8, 1778, 1, 1286, 4294967295, 8, 85, 8, 1779, 1, 4294967295, 4294967295, 10, 85, 8, 1780, 2, 4294967295, 4294967295, 12, 85, 8, 1782, 1, 4294967295, 1289, 9, 85, 8, 1783, 1, 4294967295, 4294967295, 1, 85, 8, 1784, 1, 4294967295, 4294967295, 1, 85, 8, 1785, 1, 4294967295, 4294967295, 1, 85, 32, 1786, 1, 4294967295, 4294967295, 1, 85, 8, 1787, 1, 4294967295, 4294967295, 1, 85, 8, 1788, 1, 4294967295, 4294967295, 1, 86, 8, 1789, 1, 4294967295, 4294967295, 1, 86, 32, 1790, 1, 4294967295, 4294967295, 1, 86, 8, 1791, 1, 4294967295, 4294967295, 5, 86, 8, 1792, 1, 1299, 4294967295, 8, 86, 8, 1793, 1, 4294967295, 4294967295, 10, 86, 8, 1794, 2, 4294967295, 4294967295, 12, 86, 8, 1796, 1, 4294967295, 1302, 9, 86, 8, 1797, 1, 4294967295, 4294967295, 1, 87, 32, 1798, 1, 4294967295, 4294967295, 1, 87, 8, 1799, 1, 4294967295, 4294967295, 1, 87, 8, 1800, 1, 4294967295, 4294967295, 1, 88, 32, 1801, 1, 4294967295, 4294967295, 1, 88, 8, 1802, 1, 4294967295, 4294967295, 1, 88, 32, 1803, 1, 4294967295, 4294967295, 3, 88, 8, 1804, 2, 1310, 4294967295, 8, 88, 8, 1806, 1, 4294967295, 4294967295, 1, 88, 32, 1807, 1, 4294967295, 4294967295, 1, 88, 8, 1808, 1, 4294967295, 4294967295, 1, 89, 8, 1809, 1, 4294967295, 4294967295, 1, 89, 32, 1810, 1, 4294967295, 4294967295, 1, 89, 8, 1811, 1, 4294967295, 4294967295, 5, 89, 8, 1812, 1, 1317, 4294967295, 8, 89, 8, 1813, 1, 4294967295, 4294967295, 10, 89, 8, 1814, 2, 4294967295, 4294967295, 12, 89, 8, 1816, 1, 4294967295, 1320, 9, 89, 8, 1817, 1, 4294967295, 4294967295, 1, 90, 8, 1818, 1, 4294967295, 4294967295, 5, 90, 8, 1819, 1, 1323, 4294967295, 8, 90, 8, 1820, 1, 4294967295, 4294967295, 10, 90, 8, 1821, 2, 4294967295, 4294967295, 12, 90, 8, 1823, 1, 4294967295, 1326, 9, 90, 8, 1824, 1, 4294967295, 4294967295, 1, 90, 8, 1825, 1, 4294967295, 4294967295, 1, 90, 8, 1826, 1, 4294967295, 4294967295, 1, 90, 8, 1827, 1, 4294967295, 4294967295, 1, 90, 32, 1828, 1, 4294967295, 4294967295, 1, 90, 8, 1829, 1, 4294967295, 4294967295, 3, 90, 8, 1830, 2, 1333, 4294967295, 8, 90, 8, 1832, 1, 4294967295, 4294967295, 1, 90, 32, 1833, 1, 4294967295, 4294967295, 1, 90, 8, 1834, 1, 4294967295, 4294967295, 1, 90, 8, 1835, 1, 4294967295, 4294967295, 1, 90, 8, 1836, 1, 4294967295, 4294967295, 3, 90, 8, 1837, 2, 1339, 4294967295, 8, 90, 8, 1839, 1, 4294967295, 4294967295, 1, 91, 8, 1840, 1, 4294967295, 4294967295, 1, 91, 32, 1841, 1, 4294967295, 4294967295, 1, 91, 8, 1842, 1, 4294967295, 4294967295, 4, 91, 8, 1843, 1, 1344, 4294967295, 8, 91, 8, 1844, 1, 4294967295, 4294967295, 11, 91, 8, 1845, 2, 4294967295, 4294967295, 12, 91, 8, 1847, 1, 4294967295, 1345, 1, 91, 8, 1848, 1, 4294967295, 4294967295, 4, 91, 8, 1849, 1, 1349, 4294967295, 8, 91, 8, 1850, 1, 4294967295, 4294967295, 11, 91, 8, 1851, 2, 4294967295, 4294967295, 12, 91, 8, 1853, 1, 4294967295, 1350, 1, 92, 32, 1854, 1, 4294967295, 4294967295, 1, 92, 8, 1855, 1, 4294967295, 4294967295, 1, 92, 32, 1856, 1, 4294967295, 4294967295, 1, 92, 8, 1857, 1, 4294967295, 4294967295, 1, 92, 8, 1858, 1, 4294967295, 4294967295, 1, 92, 8, 1859, 1, 4294967295, 4294967295, 3, 92, 8, 1860, 3, 1359, 4294967295, 8, 92, 8, 1863, 1, 4294967295, 4294967295, 1, 92, 32, 1864, 1, 4294967295, 4294967295, 3, 92, 8, 1865, 2, 1362, 4294967295, 8, 92, 8, 1867, 1, 4294967295, 4294967295, 1, 93, 8, 1868, 1, 4294967295, 4294967295, 1, 93, 8, 1869, 1, 4294967295, 4294967295, 3, 93, 8, 1870, 2, 1366, 4294967295, 8, 93, 8, 1872, 1, 4294967295, 4294967295, 1, 93, 32, 1873, 1, 4294967295, 4294967295, 1, 93, 8, 1874, 1, 4294967295, 4294967295, 3, 93, 8, 1875, 2, 1370, 4294967295, 8, 93, 8, 1877, 1, 4294967295, 4294967295, 1, 93, 32, 1878, 1, 4294967295, 4294967295, 1, 93, 8, 1879, 1, 4294967295, 4294967295, 3, 93, 8, 1880, 2, 1374, 4294967295, 8, 93, 8, 1882, 1, 4294967295, 4294967295, 3, 93, 8, 1883, 2, 1376, 4294967295, 8, 93, 8, 1885, 1, 4294967295, 4294967295, 1, 94, 8, 1886, 1, 4294967295, 4294967295, 1, 94, 8, 1887, 1, 4294967295, 4294967295, 3, 94, 8, 1888, 2, 1380, 4294967295, 8, 94, 8, 1890, 1, 4294967295, 4294967295, 1, 95, 8, 1891, 1, 4294967295, 4294967295, 5, 95, 8, 1892, 1, 1383, 4294967295, 8, 95, 8, 1893, 1, 4294967295, 4294967295, 10, 95, 8, 1894, 2, 4294967295, 4294967295, 12, 95, 8, 1896, 1, 4294967295, 1386, 9, 95, 8, 1897, 1, 4294967295, 4294967295, 1, 95, 8, 1898, 1, 4294967295, 4294967295, 1, 95, 32, 1899, 1, 4294967295, 4294967295, 3, 95, 8, 1900, 2, 1390, 4294967295, 8, 95, 8, 1902, 1, 4294967295, 4294967295, 1, 95, 8, 1903, 1, 4294967295, 4294967295, 1, 95, 32, 1904, 1, 4294967295, 4294967295, 1, 95, 8, 1905, 1, 4294967295, 4294967295, 1, 95, 8, 1906, 1, 4294967295, 4294967295, 1, 96, 8, 1907, 1, 4294967295, 4294967295, 1, 96, 32, 1908, 1, 4294967295, 4294967295, 1, 96, 8, 1909, 1, 4294967295, 4294967295, 5, 96, 8, 1910, 1, 1399, 4294967295, 8, 96, 8, 1911, 1, 4294967295, 4294967295, 10, 96, 8, 1912, 2, 4294967295, 4294967295, 12, 96, 8, 1914, 1, 4294967295, 1402, 9, 96, 8, 1915, 1, 4294967295, 4294967295, 1, 97, 8, 1916, 1, 4294967295, 4294967295, 1, 97, 32, 1917, 1, 4294967295, 4294967295, 1, 97, 32, 1918, 1, 4294967295, 4294967295, 3, 97, 8, 1919, 3, 1407, 4294967295, 8, 97, 8, 1922, 1, 4294967295, 4294967295, 1, 97, 8, 1923, 1, 4294967295, 4294967295, 1, 97, 8, 1924, 1, 4294967295, 4294967295, 1, 98, 72, 1925, 1, 4294967295, 4294967295, 1, 98, 8, 1926, 1, 4294967295, 4294967295, 1, 98, 8, 1927, 1, 4294967295, 4294967295, 1, 98, 8, 1928, 1, 4294967295, 4294967295, 1, 98, 32, 1929, 1, 4294967295, 4294967295, 1, 98, 8, 1930, 1, 4294967295, 4294967295, 3, 98, 8, 1931, 2, 1417, 4294967295, 8, 98, 8, 1933, 1, 4294967295, 4294967295, 1, 98, 8, 1934, 1, 4294967295, 4294967295, 1, 98, 32, 1935, 1, 4294967295, 4294967295, 3, 98, 8, 1936, 2, 1421, 4294967295, 8, 98, 8, 1938, 1, 4294967295, 4294967295, 1, 98, 8, 1939, 1, 4294967295, 4294967295, 1, 98, 32, 1940, 1, 4294967295, 4294967295, 1, 98, 8, 1941, 1, 4294967295, 4294967295, 3, 98, 8, 1942, 2, 1426, 4294967295, 8, 98, 8, 1944, 1, 4294967295, 4294967295, 1, 98, 32, 1945, 1, 4294967295, 4294967295, 1, 98, 8, 1946, 1, 4294967295, 4294967295, 1, 98, 8, 1947, 1, 4294967295, 4294967295, 1, 98, 32, 1948, 1, 4294967295, 4294967295, 1, 98, 8, 1949, 1, 4294967295, 4294967295, 1, 98, 32, 1950, 1, 4294967295, 4294967295, 1, 98, 8, 1951, 1, 4294967295, 4294967295, 5, 98, 8, 1952, 1, 1435, 4294967295, 8, 98, 8, 1953, 1, 4294967295, 4294967295, 10, 98, 8, 1954, 2, 4294967295, 4294967295, 12, 98, 8, 1956, 1, 4294967295, 1438, 9, 98, 8, 1957, 1, 4294967295, 4294967295, 1, 98, 8, 1958, 1, 4294967295, 4294967295, 1, 98, 32, 1959, 1, 4294967295, 4294967295, 1, 98, 8, 1960, 1, 4294967295, 4294967295, 5, 98, 8, 1961, 1, 1443, 4294967295, 8, 98, 8, 1962, 1, 4294967295, 4294967295, 10, 98, 8, 1963, 2, 4294967295, 4294967295, 12, 98, 8, 1965, 1, 4294967295, 1446, 9, 98, 8, 1966, 1, 4294967295, 4294967295, 1, 98, 32, 1967, 1, 4294967295, 4294967295, 1, 98, 8, 1968, 1, 4294967295, 4294967295, 1, 98, 8, 1969, 1, 4294967295, 4294967295, 1, 98, 32, 1970, 1, 4294967295, 4294967295, 1, 98, 8, 1971, 1, 4294967295, 4294967295, 1, 98, 8, 1972, 1, 4294967295, 4294967295, 3, 98, 8, 1973, 9, 1454, 4294967295, 8, 98, 8, 1982, 1, 4294967295, 4294967295, 1, 98, 72, 1983, 1, 4294967295, 4294967295, 1, 98, 32, 1984, 1, 4294967295, 4294967295, 1, 98, 8, 1985, 1, 4294967295, 4294967295, 1, 98, 32, 1986, 1, 4294967295, 4294967295, 1, 98, 8, 1987, 1, 4294967295, 4294967295, 1, 98, 72, 1988, 1, 4294967295, 4294967295, 1, 98, 32, 1989, 1, 4294967295, 4294967295, 1, 98, 8, 1990, 1, 4294967295, 4294967295, 1, 98, 8, 1991, 1, 4294967295, 4294967295, 1, 98, 32, 1992, 1, 4294967295, 4294967295, 1, 98, 32, 1993, 1, 4294967295, 4294967295, 1, 98, 8, 1994, 1, 4294967295, 4294967295, 3, 98, 8, 1995, 2, 1468, 4294967295, 8, 98, 8, 1997, 1, 4294967295, 4294967295, 1, 98, 8, 1998, 1, 4294967295, 4294967295, 1, 98, 32, 1999, 1, 4294967295, 4294967295, 1, 98, 8, 2000, 1, 4294967295, 4294967295, 1, 98, 8, 2001, 1, 4294967295, 4294967295, 3, 98, 8, 2002, 6, 1474, 4294967295, 8, 98, 8, 2008, 1, 4294967295, 4294967295, 1, 98, 72, 2009, 1, 4294967295, 4294967295, 1, 98, 32, 2010, 1, 4294967295, 4294967295, 1, 98, 8, 2011, 1, 4294967295, 4294967295, 3, 98, 8, 2012, 2, 1479, 4294967295, 8, 98, 8, 2014, 1, 4294967295, 4294967295, 1, 98, 8, 2015, 1, 4294967295, 4294967295, 1, 98, 72, 2016, 1, 4294967295, 4294967295, 1, 98, 32, 2017, 1, 4294967295, 4294967295, 1, 98, 72, 2018, 1, 4294967295, 4294967295, 1, 98, 32, 2019, 1, 4294967295, 4294967295, 1, 98, 8, 2020, 1, 4294967295, 4294967295, 1, 98, 72, 2021, 1, 4294967295, 4294967295, 1, 98, 32, 2022, 1, 4294967295, 4294967295, 1, 98, 8, 2023, 1, 4294967295, 4294967295, 1, 98, 72, 2024, 1, 4294967295, 4294967295, 1, 98, 32, 2025, 1, 4294967295, 4294967295, 1, 98, 32, 2026, 1, 4294967295, 4294967295, 1, 98, 32, 2027, 1, 4294967295, 4294967295, 1, 98, 32, 2028, 1, 4294967295, 4294967295, 1, 98, 32, 2029, 1, 4294967295, 4294967295, 1, 98, 32, 2030, 1, 4294967295, 4294967295, 1, 98, 32, 2031, 1, 4294967295, 4294967295, 3, 98, 8, 2032, 3, 1498, 4294967295, 8, 98, 8, 2035, 1, 4294967295, 4294967295, 1, 98, 8, 2036, 1, 4294967295, 4294967295, 1, 98, 72, 2037, 1, 4294967295, 4294967295, 1, 98, 32, 2038, 1, 4294967295, 4294967295, 1, 98, 8, 2039, 1, 4294967295, 4294967295, 1, 98, 72, 2040, 1, 4294967295, 4294967295, 1, 98, 32, 2041, 1, 4294967295, 4294967295, 1, 98, 8, 2042, 1, 4294967295, 4294967295, 1, 98, 8, 2043, 1, 4294967295, 4294967295, 3, 98, 8, 2044, 2, 1508, 4294967295, 8, 98, 8, 2046, 1, 4294967295, 4294967295, 1, 98, 72, 2047, 1, 4294967295, 4294967295, 1, 98, 32, 2048, 1, 4294967295, 4294967295, 1, 98, 8, 2049, 1, 4294967295, 4294967295, 1, 98, 72, 2050, 1, 4294967295, 4294967295, 1, 98, 32, 2051, 1, 4294967295, 4294967295, 1, 98, 8, 2052, 1, 4294967295, 4294967295, 1, 98, 72, 2053, 1, 4294967295, 4294967295, 1, 98, 32, 2054, 1, 4294967295, 4294967295, 1, 98, 8, 2055, 1, 4294967295, 4294967295, 1, 98, 72, 2056, 1, 4294967295, 4294967295, 1, 98, 32, 2057, 1, 4294967295, 4294967295, 1, 98, 8, 2058, 1, 4294967295, 4294967295, 1, 98, 72, 2059, 1, 4294967295, 4294967295, 1, 98, 32, 2060, 1, 4294967295, 4294967295, 1, 98, 8, 2061, 1, 4294967295, 4294967295, 1, 98, 72, 2062, 1, 4294967295, 4294967295, 1, 98, 32, 2063, 1, 4294967295, 4294967295, 1, 98, 8, 2064, 1, 4294967295, 4294967295, 1, 98, 72, 2065, 1, 4294967295, 4294967295, 1, 98, 32, 2066, 1, 4294967295, 4294967295, 1, 98, 8, 2067, 1, 4294967295, 4294967295, 1, 98, 32, 2068, 1, 4294967295, 4294967295, 1, 98, 8, 2069, 1, 4294967295, 4294967295, 1, 98, 8, 2070, 1, 4294967295, 4294967295, 1, 98, 72, 2071, 1, 4294967295, 4294967295, 1, 98, 32, 2072, 1, 4294967295, 4294967295, 1, 98, 8, 2073, 1, 4294967295, 4294967295, 5, 98, 8, 2074, 17, 1537, 4294967295, 8, 98, 8, 2091, 1, 4294967295, 4294967295, 10, 98, 10, 2092, 2, 4294967295, 4294967295, 12, 98, 8, 2094, 1, 4294967295, 1540, 9, 98, 8, 2095, 1, 4294967295, 4294967295, 1, 99, 8, 2096, 1, 4294967295, 4294967295, 5, 99, 8, 2097, 1, 1543, 4294967295, 8, 99, 8, 2098, 1, 4294967295, 4294967295, 10, 99, 8, 2099, 2, 4294967295, 4294967295, 12, 99, 8, 2101, 1, 4294967295, 1546, 9, 99, 8, 2102, 1, 4294967295, 4294967295, 1, 99, 8, 2103, 1, 4294967295, 4294967295, 1, 99, 8, 2104, 1, 4294967295, 4294967295, 5, 99, 8, 2105, 1, 1550, 4294967295, 8, 99, 8, 2106, 1, 4294967295, 4294967295, 10, 99, 8, 2107, 2, 4294967295, 4294967295, 12, 99, 8, 2109, 1, 4294967295, 1553, 9, 99, 8, 2110, 1, 4294967295, 4294967295, 1, 99, 8, 2111, 1, 4294967295, 4294967295, 1, 99, 8, 2112, 1, 4294967295, 4294967295, 1, 99, 8, 2113, 1, 4294967295, 4294967295, 1, 99, 32, 2114, 1, 4294967295, 4294967295, 1, 99, 8, 2115, 1, 4294967295, 4294967295, 3, 99, 8, 2116, 2, 1560, 4294967295, 8, 99, 8, 2118, 1, 4294967295, 4294967295, 1, 99, 32, 2119, 1, 4294967295, 4294967295, 1, 99, 8, 2120, 1, 4294967295, 4294967295, 3, 99, 8, 2121, 2, 1564, 4294967295, 8, 99, 8, 2123, 1, 4294967295, 4294967295, 1, 100, 8, 2124, 1, 4294967295, 4294967295, 1, 100, 32, 2125, 1, 4294967295, 4294967295, 1, 100, 8, 2126, 1, 4294967295, 4294967295, 5, 100, 8, 2127, 1, 1569, 4294967295, 8, 100, 8, 2128, 1, 4294967295, 4294967295, 10, 100, 8, 2129, 2, 4294967295, 4294967295, 12, 100, 8, 2131, 1, 4294967295, 1572, 9, 100, 8, 2132, 1, 4294967295, 4294967295, 1, 101, 8, 2133, 1, 4294967295, 4294967295, 1, 101, 8, 2134, 1, 4294967295, 4294967295, 1, 102, 8, 2135, 1, 4294967295, 4294967295, 1, 102, 32, 2136, 1, 4294967295, 4294967295, 1, 102, 8, 2137, 1, 4294967295, 4294967295, 1, 102, 8, 2138, 1, 4294967295, 4294967295, 1, 103, 8, 2139, 1, 4294967295, 4294967295, 1, 103, 32, 2140, 1, 4294967295, 4294967295, 1, 103, 8, 2141, 1, 4294967295, 4294967295, 3, 103, 8, 2142, 2, 1583, 4294967295, 8, 103, 8, 2144, 1, 4294967295, 4294967295, 1, 103, 32, 2145, 1, 4294967295, 4294967295, 1, 103, 32, 2146, 1, 4294967295, 4294967295, 1, 103, 8, 2147, 1, 4294967295, 4294967295, 1, 103, 32, 2148, 1, 4294967295, 4294967295, 1, 103, 8, 2149, 1, 4294967295, 4294967295, 5, 103, 8, 2150, 1, 1590, 4294967295, 8, 103, 8, 2151, 1, 4294967295, 4294967295, 10, 103, 8, 2152, 2, 4294967295, 4294967295, 12, 103, 8, 2154, 1, 4294967295, 1593, 9, 103, 8, 2155, 1, 4294967295, 4294967295, 1, 103, 32, 2156, 1, 4294967295, 4294967295, 1, 103, 8, 2157, 1, 4294967295, 4294967295, 1, 103, 32, 2158, 1, 4294967295, 4294967295, 1, 103, 8, 2159, 1, 4294967295, 4294967295, 3, 103, 8, 2160, 2, 1599, 4294967295, 8, 103, 8, 2162, 1, 4294967295, 4294967295, 1, 103, 32, 2163, 1, 4294967295, 4294967295, 3, 103, 8, 2164, 4, 1602, 4294967295, 8, 103, 8, 2168, 1, 4294967295, 4294967295, 1, 104, 8, 2169, 1, 4294967295, 4294967295, 1, 104, 8, 2170, 1, 4294967295, 4294967295, 3, 104, 8, 2171, 2, 1606, 4294967295, 8, 104, 8, 2173, 1, 4294967295, 4294967295, 1, 105, 32, 2174, 1, 4294967295, 4294967295, 1, 105, 8, 2175, 1, 4294967295, 4294967295, 1, 105, 32, 2176, 1, 4294967295, 4294967295, 1, 105, 8, 2177, 1, 4294967295, 4294967295, 1, 105, 32, 2178, 1, 4294967295, 4294967295, 1, 105, 32, 2179, 1, 4294967295, 4294967295, 1, 105, 8, 2180, 1, 4294967295, 4294967295, 1, 105, 8, 2181, 1, 4294967295, 4294967295, 1, 105, 8, 2182, 1, 4294967295, 4294967295, 1, 105, 32, 2183, 1, 4294967295, 4294967295, 1, 105, 32, 2184, 1, 4294967295, 4294967295, 1, 105, 8, 2185, 1, 4294967295, 4294967295, 1, 105, 8, 2186, 1, 4294967295, 4294967295, 1, 105, 8, 2187, 1, 4294967295, 4294967295, 1, 105, 32, 2188, 1, 4294967295, 4294967295, 1, 105, 8, 2189, 1, 4294967295, 4294967295, 3, 105, 8, 2190, 2, 1624, 4294967295, 8, 105, 8, 2192, 1, 4294967295, 4294967295, 3, 105, 8, 2193, 7, 1626, 4294967295, 8, 105, 8, 2200, 1, 4294967295, 4294967295, 1, 106, 32, 2201, 1, 4294967295, 4294967295, 1, 106, 32, 2202, 1, 4294967295, 4294967295, 1, 106, 8, 2203, 1, 4294967295, 4294967295, 1, 106, 32, 2204, 1, 4294967295, 4294967295, 1, 106, 32, 2205, 1, 4294967295, 4294967295, 1, 106, 8, 2206, 1, 4294967295, 4294967295, 5, 106, 8, 2207, 1, 1634, 4294967295, 8, 106, 8, 2208, 1, 4294967295, 4294967295, 10, 106, 8, 2209, 2, 4294967295, 4294967295, 12, 106, 8, 2211, 1, 4294967295, 1637, 9, 106, 8, 2212, 1, 4294967295, 4294967295, 1, 106, 32, 2213, 1, 4294967295, 4294967295, 1, 106, 8, 2214, 1, 4294967295, 4294967295, 1, 107, 32, 2215, 1, 4294967295, 4294967295, 1, 107, 8, 2216, 1, 4294967295, 4294967295, 1, 107, 32, 2217, 1, 4294967295, 4294967295, 1, 107, 32, 2218, 1, 4294967295, 4294967295, 1, 107, 32, 2219, 1, 4294967295, 4294967295, 3, 107, 8, 2220, 2, 1646, 4294967295, 8, 107, 8, 2222, 1, 4294967295, 4294967295, 1, 107, 8, 2223, 1, 4294967295, 4294967295, 1, 107, 32, 2224, 1, 4294967295, 4294967295, 1, 107, 8, 2225, 1, 4294967295, 4294967295, 5, 107, 8, 2226, 1, 1651, 4294967295, 8, 107, 8, 2227, 1, 4294967295, 4294967295, 10, 107, 8, 2228, 2, 4294967295, 4294967295, 12, 107, 8, 2230, 1, 4294967295, 1654, 9, 107, 8, 2231, 1, 4294967295, 4294967295, 1, 107, 8, 2232, 1, 4294967295, 4294967295, 3, 107, 8, 2233, 2, 1657, 4294967295, 8, 107, 8, 2235, 1, 4294967295, 4294967295, 3, 107, 8, 2236, 3, 1659, 4294967295, 8, 107, 8, 2239, 1, 4294967295, 4294967295, 1, 107, 32, 2240, 1, 4294967295, 4294967295, 1, 107, 8, 2241, 1, 4294967295, 4294967295, 1, 107, 32, 2242, 1, 4294967295, 4294967295, 1, 107, 32, 2243, 1, 4294967295, 4294967295, 1, 107, 8, 2244, 1, 4294967295, 4294967295, 3, 107, 8, 2245, 2, 1666, 4294967295, 8, 107, 8, 2247, 1, 4294967295, 4294967295, 1, 108, 32, 2248, 1, 4294967295, 4294967295, 1, 108, 8, 2249, 1, 4294967295, 4294967295, 1, 108, 8, 2250, 1, 4294967295, 4294967295, 1, 109, 8, 2251, 1, 4294967295, 4294967295, 1, 109, 8, 2252, 1, 4294967295, 4294967295, 1, 110, 8, 2253, 1, 4294967295, 4294967295, 1, 110, 8, 2254, 1, 4294967295, 4294967295, 5, 110, 8, 2255, 1, 1675, 4294967295, 8, 110, 8, 2256, 1, 4294967295, 4294967295, 10, 110, 8, 2257, 2, 4294967295, 4294967295, 12, 110, 8, 2259, 1, 4294967295, 1678, 9, 110, 8, 2260, 1, 4294967295, 4294967295, 3, 110, 8, 2261, 2, 1680, 4294967295, 8, 110, 8, 2263, 1, 4294967295, 4294967295, 1, 111, 8, 2264, 1, 4294967295, 4294967295, 1, 111, 8, 2265, 1, 4294967295, 4294967295, 1, 112, 8, 2266, 1, 4294967295, 4294967295, 3, 112, 8, 2267, 2, 1685, 4294967295, 8, 112, 8, 2269, 1, 4294967295, 4294967295, 1, 112, 8, 2270, 1, 4294967295, 4294967295, 1, 112, 8, 2271, 1, 4294967295, 4294967295, 1, 112, 8, 2272, 1, 4294967295, 4294967295, 1, 112, 8, 2273, 1, 4294967295, 4294967295, 1, 112, 8, 2274, 1, 4294967295, 4294967295, 1, 112, 8, 2275, 1, 4294967295, 4294967295, 3, 112, 8, 2276, 2, 1693, 4294967295, 8, 112, 8, 2278, 1, 4294967295, 4294967295, 1, 113, 8, 2279, 1, 4294967295, 4294967295, 1, 113, 8, 2280, 1, 4294967295, 4294967295, 3, 113, 8, 2281, 2, 1697, 4294967295, 8, 113, 8, 2283, 1, 4294967295, 4294967295, 1, 113, 32, 2284, 1, 4294967295, 4294967295, 1, 113, 8, 2285, 1, 4294967295, 4294967295, 1, 113, 8, 2286, 1, 4294967295, 4294967295, 3, 113, 8, 2287, 2, 1702, 4294967295, 8, 113, 8, 2289, 1, 4294967295, 4294967295, 5, 113, 8, 2290, 1, 1704, 4294967295, 8, 113, 8, 2291, 1, 4294967295, 4294967295, 10, 113, 8, 2292, 2, 4294967295, 4294967295, 12, 113, 8, 2294, 1, 4294967295, 1707, 9, 113, 8, 2295, 1, 4294967295, 4294967295, 1, 113, 8, 2296, 1, 4294967295, 4294967295, 3, 113, 8, 2297, 2, 1710, 4294967295, 8, 113, 8, 2299, 1, 4294967295, 4294967295, 1, 114, 8, 2300, 1, 4294967295, 4294967295, 1, 114, 8, 2301, 1, 4294967295, 4294967295, 3, 114, 8, 2302, 2, 1714, 4294967295, 8, 114, 8, 2304, 1, 4294967295, 4294967295, 1, 114, 8, 2305, 1, 4294967295, 4294967295, 1, 114, 8, 2306, 1, 4294967295, 4294967295, 1, 115, 32, 2307, 1, 4294967295, 4294967295, 1, 115, 32, 2308, 1, 4294967295, 4294967295, 4, 115, 8, 2309, 1, 1720, 4294967295, 8, 115, 8, 2310, 1, 4294967295, 4294967295, 11, 115, 8, 2311, 2, 4294967295, 4294967295, 12, 115, 8, 2313, 1, 4294967295, 1721, 1, 115, 8, 2314, 1, 4294967295, 4294967295, 1, 115, 32, 2315, 1, 4294967295, 4294967295, 1, 115, 8, 2316, 1, 4294967295, 4294967295, 1, 115, 32, 2317, 1, 4294967295, 4294967295, 1, 115, 8, 2318, 1, 4294967295, 4294967295, 4, 115, 8, 2319, 1, 1729, 4294967295, 8, 115, 8, 2320, 1, 4294967295, 4294967295, 11, 115, 8, 2321, 2, 4294967295, 4294967295, 12, 115, 8, 2323, 1, 4294967295, 1730, 1, 115, 32, 2324, 1, 4294967295, 4294967295, 1, 115, 32, 2325, 1, 4294967295, 4294967295, 5, 115, 8, 2326, 1, 1735, 4294967295, 8, 115, 8, 2327, 1, 4294967295, 4294967295, 10, 115, 8, 2328, 2, 4294967295, 4294967295, 12, 115, 8, 2330, 1, 4294967295, 1738, 9, 115, 8, 2331, 1, 4294967295, 4294967295, 3, 115, 8, 2332, 2, 1740, 4294967295, 8, 115, 8, 2334, 1, 4294967295, 4294967295, 1, 116, 8, 2335, 1, 4294967295, 4294967295, 1, 116, 8, 2336, 1, 4294967295, 4294967295, 3, 116, 8, 2337, 2, 1744, 4294967295, 8, 116, 8, 2339, 1, 4294967295, 4294967295, 1, 117, 8, 2340, 1, 4294967295, 4294967295, 1, 117, 8, 2341, 1, 4294967295, 4294967295, 1, 117, 8, 2342, 1, 4294967295, 4294967295, 1, 118, 32, 2343, 1, 4294967295, 4294967295, 1, 118, 32, 2344, 1, 4294967295, 4294967295, 1, 118, 8, 2345, 1, 4294967295, 4294967295, 3, 118, 8, 2346, 2, 1752, 4294967295, 8, 118, 8, 2348, 1, 4294967295, 4294967295, 1, 119, 32, 2349, 1, 4294967295, 4294967295, 1, 119, 32, 2350, 1, 4294967295, 4294967295, 1, 119, 8, 2351, 1, 4294967295, 4294967295, 3, 119, 8, 2352, 2, 1757, 4294967295, 8, 119, 8, 2354, 1, 4294967295, 4294967295, 1, 120, 32, 2355, 1, 4294967295, 4294967295, 1, 120, 8, 2356, 1, 4294967295, 4294967295, 1, 120, 32, 2357, 1, 4294967295, 4294967295, 1, 120, 8, 2358, 1, 4294967295, 4294967295, 1, 121, 8, 2359, 1, 4294967295, 4294967295, 1, 121, 32, 2360, 1, 4294967295, 4294967295, 1, 121, 8, 2361, 1, 4294967295, 4294967295, 5, 121, 8, 2362, 1, 1766, 4294967295, 8, 121, 8, 2363, 1, 4294967295, 4294967295, 10, 121, 8, 2364, 2, 4294967295, 4294967295, 12, 121, 8, 2366, 1, 4294967295, 1769, 9, 121, 8, 2367, 1, 4294967295, 4294967295, 1, 122, 8, 2368, 1, 4294967295, 4294967295, 5, 122, 8, 2369, 1, 1772, 4294967295, 8, 122, 8, 2370, 1, 4294967295, 4294967295, 10, 122, 8, 2371, 2, 4294967295, 4294967295, 12, 122, 8, 2373, 1, 4294967295, 1775, 9, 122, 8, 2374, 1, 4294967295, 4294967295, 1, 122, 8, 2375, 1, 4294967295, 4294967295, 1, 122, 8, 2376, 1, 4294967295, 4294967295, 3, 122, 8, 2377, 2, 1779, 4294967295, 8, 122, 8, 2379, 1, 4294967295, 4294967295, 1, 122, 8, 2380, 1, 4294967295, 4294967295, 5, 122, 8, 2381, 1, 1782, 4294967295, 8, 122, 8, 2382, 1, 4294967295, 4294967295, 10, 122, 8, 2383, 2, 4294967295, 4294967295, 12, 122, 8, 2385, 1, 4294967295, 1785, 9, 122, 8, 2386, 1, 4294967295, 4294967295, 1, 122, 32, 2387, 1, 4294967295, 4294967295, 1, 122, 32, 2388, 1, 4294967295, 4294967295, 5, 122, 8, 2389, 1, 1789, 4294967295, 8, 122, 8, 2390, 1, 4294967295, 4294967295, 10, 122, 8, 2391, 2, 4294967295, 4294967295, 12, 122, 8, 2393, 1, 4294967295, 1792, 9, 122, 8, 2394, 1, 4294967295, 4294967295, 1, 123, 32, 2395, 1, 4294967295, 4294967295, 1, 123, 8, 2396, 1, 4294967295, 4294967295, 1, 124, 32, 2397, 1, 4294967295, 4294967295, 1, 124, 8, 2398, 1, 4294967295, 4294967295, 1, 124, 32, 2399, 1, 4294967295, 4294967295, 1, 124, 8, 2400, 1, 4294967295, 4294967295, 5, 124, 8, 2401, 1, 1800, 4294967295, 8, 124, 8, 2402, 1, 4294967295, 4294967295, 10, 124, 8, 2403, 2, 4294967295, 4294967295, 12, 124, 8, 2405, 1, 4294967295, 1803, 9, 124, 8, 2406, 1, 4294967295, 4294967295, 1, 124, 32, 2407, 1, 4294967295, 4294967295, 1, 124, 8, 2408, 1, 4294967295, 4294967295, 1, 125, 8, 2409, 1, 4294967295, 4294967295, 1, 125, 32, 2410, 1, 4294967295, 4294967295, 1, 125, 8, 2411, 1, 4294967295, 4294967295, 3, 125, 8, 2412, 2, 1810, 4294967295, 8, 125, 8, 2414, 1, 4294967295, 4294967295, 1, 125, 8, 2415, 1, 4294967295, 4294967295, 1, 125, 8, 2416, 1, 4294967295, 4294967295, 3, 125, 8, 2417, 2, 1814, 4294967295, 8, 125, 8, 2419, 1, 4294967295, 4294967295, 3, 125, 8, 2420, 2, 1816, 4294967295, 8, 125, 8, 2422, 1, 4294967295, 4294967295, 1, 126, 32, 2423, 1, 4294967295, 4294967295, 1, 126, 8, 2424, 1, 4294967295, 4294967295, 1, 126, 8, 2425, 1, 4294967295, 4294967295, 1, 126, 8, 2426, 1, 4294967295, 4294967295, 1, 126, 8, 2427, 1, 4294967295, 4294967295, 3, 126, 8, 2428, 2, 1823, 4294967295, 8, 126, 8, 2430, 1, 4294967295, 4294967295, 1, 127, 32, 2431, 1, 4294967295, 4294967295, 1, 127, 8, 2432, 1, 4294967295, 4294967295, 3, 127, 8, 2433, 2, 1827, 4294967295, 8, 127, 8, 2435, 1, 4294967295, 4294967295, 1, 127, 32, 2436, 1, 4294967295, 4294967295, 1, 127, 8, 2437, 1, 4294967295, 4294967295, 1, 127, 0, 2438, 0, 4294967295, 4294967295, 1, 277, 0, 0, 0, 1, 282, 0, 0, 0, 1, 275, 0, 0, 0, 1, 290, 0, 0, 0, 1, 258, 0, 0, 0, 1, 297, 0, 0, 0, 1, 262, 0, 0, 0, 1, 281, 0, 0, 0, 1, 311, 0, 0, 0, 1, 269, 0, 0, 0, 1, 326, 0, 0, 0, 1, 485, 0, 0, 0, 1, 544, 0, 0, 0, 1, 557, 0, 0, 0, 1, 923, 0, 0, 0, 1, 338, 0, 0, 0, 1, 310, 0, 0, 0, 1, 327, 0, 0, 0, 1, 1147, 0, 0, 0, 1, 342, 0, 0, 0, 1, 786, 0, 0, 0, 1, 812, 0, 0, 0, 1, 1127, 0, 0, 0, 1, 1286, 0, 0, 0, 1, 1323, 0, 0, 0, 1, 1383, 0, 0, 0, 1, 1543, 0, 0, 0, 1, 344, 0, 0, 0, 1, 320, 0, 0, 0, 1, 503, 0, 0, 0, 1, 574, 0, 0, 0, 1, 937, 0, 0, 0, 1, 1156, 0, 0, 0, 1, 363, 0, 0, 0, 1, 348, 0, 0, 0, 1, 449, 0, 0, 0, 1, 529, 0, 0, 0, 1, 532, 0, 0, 0, 1, 620, 0, 0, 0, 1, 1057, 0, 0, 0, 1, 377, 0, 0, 0, 1, 369, 0, 0, 0, 1, 368, 0, 0, 0, 1, 391, 0, 0, 0, 1, 390, 0, 0, 0, 1, 399, 0, 0, 0, 1, 320, 0, 0, 0, 1, 503, 0, 0, 0, 1, 574, 0, 0, 0, 1, 945, 0, 0, 0, 1, 1156, 0, 0, 0, 1, 417, 0, 0, 0, 1, 408, 0, 0, 0, 1, 428, 0, 0, 0, 1, 422, 0, 0, 0, 1, 421, 0, 0, 0, 1, 438, 0, 0, 0, 1, 414, 0, 0, 0, 1, 445, 0, 0, 0, 1, 320, 0, 0, 0, 1, 503, 0, 0, 0, 1, 574, 0, 0, 0, 1, 941, 0, 0, 0, 1, 1156, 0, 0, 0, 1, 460, 0, 0, 0, 1, 362, 0, 0, 0, 1, 437, 0, 0, 0, 1, 1744, 0, 0, 0, 1, 469, 0, 0, 0, 1, 459, 0, 0, 0, 1, 490, 0, 0, 0, 1, 441, 0, 0, 0, 1, 463, 0, 0, 0, 1, 1103, 0, 0, 0, 1, 502, 0, 0, 0, 1, 491, 0, 0, 0, 1, 504, 0, 0, 0, 1, 503, 0, 0, 0, 1, 530, 0, 0, 0, 1, 522, 0, 0, 0, 1, 519, 0, 0, 0, 1, 643, 0, 0, 0, 1, 526, 0, 0, 0, 1, 505, 0, 0, 0, 1, 629, 0, 0, 0, 1, 1616, 0, 0, 0, 1, 528, 0, 0, 0, 1, 503, 0, 0, 0, 1, 531, 0, 0, 0, 1, 503, 0, 0, 0, 1, 534, 0, 0, 0, 1, 503, 0, 0, 0, 1, 533, 0, 0, 0, 1, 545, 0, 0, 0, 1, 1103, 0, 0, 0, 1, 551, 0, 0, 0, 1, 503, 0, 0, 0, 1, 563, 0, 0, 0, 1, 472, 0, 0, 0, 1, 573, 0, 0, 0, 1, 564, 0, 0, 0, 1, 575, 0, 0, 0, 1, 574, 0, 0, 0, 1, 586, 0, 0, 0, 1, 581, 0, 0, 0, 1, 580, 0, 0, 0, 1, 600, 0, 0, 0, 1, 574, 0, 0, 0, 1, 611, 0, 0, 0, 1, 599, 0, 0, 0, 1, 615, 0, 0, 0, 1, 616, 0, 0, 0, 1, 574, 0, 0, 0, 1, 625, 0, 0, 0, 1, 604, 0, 0, 0, 1, 621, 0, 0, 0, 1, 644, 0, 0, 0, 1, 553, 0, 0, 0, 1, 968, 0, 0, 0, 1, 1138, 0, 0, 0, 1, 1555, 0, 0, 0, 1, 652, 0, 0, 0, 1, 649, 0, 0, 0, 1, 648, 0, 0, 0, 1, 657, 0, 0, 0, 1, 655, 0, 0, 0, 1, 801, 0, 0, 0, 1, 1329, 0, 0, 0, 1, 1392, 0, 0, 0, 1, 667, 0, 0, 0, 1, 596, 0, 0, 0, 1, 656, 0, 0, 0, 1, 675, 0, 0, 0, 1, 674, 0, 0, 0, 1, 669, 0, 0, 0, 1, 668, 0, 0, 0, 1, 1740, 0, 0, 0, 1, 699, 0, 0, 0, 1, 1423, 0, 0, 0, 1, 1682, 0, 0, 0, 1, 719, 0, 0, 0, 1, 686, 0, 0, 0, 1, 739, 0, 0, 0, 1, 1801, 0, 0, 0, 1, 1800, 0, 0, 0, 1, 741, 0, 0, 0, 1, 517, 0, 0, 0, 1, 539, 0, 0, 0, 1, 641, 0, 0, 0, 1, 749, 0, 0, 0, 1, 511, 0, 0, 0, 1, 538, 0, 0, 0, 1, 635, 0, 0, 0, 1, 765, 0, 0, 0, 1, 753, 0, 0, 0, 1, 776, 0, 0, 0, 1, 757, 0, 0, 0, 1, 1583, 0, 0, 0, 1, 787, 0, 0, 0, 1, 753, 0, 0, 0, 1, 781, 0, 0, 0, 1, 780, 0, 0, 0, 1, 802, 0, 0, 0, 1, 1599, 0, 0, 0, 1, 813, 0, 0, 0, 1, 807, 0, 0, 0, 1, 806, 0, 0, 0, 1, 819, 0, 0, 0, 1, 295, 0, 0, 0, 1, 304, 0, 0, 0, 1, 746, 0, 0, 0, 1, 745, 0, 0, 0, 1, 842, 0, 0, 0, 1, 983, 0, 0, 0, 1, 1000, 0, 0, 0, 1, 1013, 0, 0, 0, 1, 1010, 0, 0, 0, 1, 1009, 0, 0, 0, 1, 1028, 0, 0, 0, 1, 1025, 0, 0, 0, 1, 1024, 0, 0, 0, 1, 1034, 0, 0, 0, 1, 1038, 0, 0, 0, 1, 1044, 0, 0, 0, 1, 1043, 0, 0, 0, 1, 1300, 0, 0, 0, 1, 1299, 0, 0, 0, 1, 1339, 0, 0, 0, 1, 834, 0, 0, 0, 1, 1626, 0, 0, 0, 1, 836, 0, 0, 0, 1, 835, 0, 0, 0, 1, 838, 0, 0, 0, 1, 835, 0, 0, 0, 1, 840, 0, 0, 0, 1, 289, 0, 0, 0, 1, 339, 0, 0, 0, 1, 343, 0, 0, 0, 1, 376, 0, 0, 0, 1, 384, 0, 0, 0, 1, 427, 0, 0, 0, 1, 612, 0, 0, 0, 1, 624, 0, 0, 0, 1, 689, 0, 0, 0, 1, 706, 0, 0, 0, 1, 730, 0, 0, 0, 1, 793, 0, 0, 0, 1, 885, 0, 0, 0, 1, 890, 0, 0, 0, 1, 974, 0, 0, 0, 1, 1083, 0, 0, 0, 1, 1090, 0, 0, 0, 1, 1435, 0, 0, 0, 1, 1550, 0, 0, 0, 1, 1772, 0, 0, 0, 1, 1782, 0, 0, 0, 1, 846, 0, 0, 0, 1, 845, 0, 0, 0, 1, 865, 0, 0, 0, 1, 852, 0, 0, 0, 1, 851, 0, 0, 0, 1, 884, 0, 0, 0, 1, 866, 0, 0, 0, 1, 864, 0, 0, 0, 1, 875, 0, 0, 0, 1, 874, 0, 0, 0, 1, 889, 0, 0, 0, 1, 897, 0, 0, 0, 1, 896, 0, 0, 0, 1, 971, 0, 0, 0, 1, 891, 0, 0, 0, 1, 890, 0, 0, 0, 1, 907, 0, 0, 0, 1, 320, 0, 0, 0, 1, 503, 0, 0, 0, 1, 574, 0, 0, 0, 1, 949, 0, 0, 0, 1, 912, 0, 0, 0, 1, 911, 0, 0, 0, 1, 929, 0, 0, 0, 1, 915, 0, 0, 0, 1, 955, 0, 0, 0, 1, 930, 0, 0, 0, 1, 959, 0, 0, 0, 1, 933, 0, 0, 0, 1, 961, 0, 0, 0, 1, 960, 0, 0, 0, 1, 967, 0, 0, 0, 1, 960, 0, 0, 0, 1, 969, 0, 0, 0, 1, 966, 0, 0, 0, 1, 975, 0, 0, 0, 1, 286, 0, 0, 0, 1, 1049, 0, 0, 0, 1, 986, 0, 0, 0, 1, 1051, 0, 0, 0, 1, 995, 0, 0, 0, 1, 1053, 0, 0, 0, 1, 320, 0, 0, 0, 1, 503, 0, 0, 0, 1, 574, 0, 0, 0, 1, 953, 0, 0, 0, 1, 1156, 0, 0, 0, 1, 1065, 0, 0, 0, 1, 1061, 0, 0, 0, 1, 1071, 0, 0, 0, 1, 1068, 0, 0, 0, 1, 1084, 0, 0, 0, 1, 1076, 0, 0, 0, 1, 1075, 0, 0, 0, 1, 1099, 0, 0, 0, 1, 1064, 0, 0, 0, 1, 1109, 0, 0, 0, 1, 491, 0, 0, 0, 1, 523, 0, 0, 0, 1, 541, 0, 0, 0, 1, 550, 0, 0, 0, 1, 1281, 0, 0, 0, 1, 1206, 0, 0, 0, 1, 1214, 0, 0, 0, 1, 1244, 0, 0, 0, 1, 1294, 0, 0, 0, 1, 1305, 0, 0, 0, 1, 1606, 0, 0, 0, 1, 1680, 0, 0, 0, 1, 1123, 0, 0, 0, 1, 1112, 0, 0, 0, 1, 1349, 0, 0, 0, 1, 1675, 0, 0, 0, 1, 1128, 0, 0, 0, 1, 1119, 0, 0, 0, 1, 1380, 0, 0, 0, 1, 1141, 0, 0, 0, 1, 347, 0, 0, 0, 1, 389, 0, 0, 0, 1, 403, 0, 0, 0, 1, 433, 0, 0, 0, 1, 448, 0, 0, 0, 1, 506, 0, 0, 0, 1, 535, 0, 0, 0, 1, 549, 0, 0, 0, 1, 591, 0, 0, 0, 1, 630, 0, 0, 0, 1, 662, 0, 0, 0, 1, 724, 0, 0, 0, 1, 723, 0, 0, 0, 1, 767, 0, 0, 0, 1, 818, 0, 0, 0, 1, 824, 0, 0, 0, 1, 823, 0, 0, 0, 1, 862, 0, 0, 0, 1, 910, 0, 0, 0, 1, 962, 0, 0, 0, 1, 1056, 0, 0, 0, 1, 1098, 0, 0, 0, 1, 1133, 0, 0, 0, 1, 1257, 0, 0, 0, 1, 1262, 0, 0, 0, 1, 1277, 0, 0, 0, 1, 1292, 0, 0, 0, 1, 1333, 0, 0, 0, 1, 1357, 0, 0, 0, 1, 1407, 0, 0, 0, 1, 1421, 0, 0, 0, 1, 1474, 0, 0, 0, 1, 1537, 0, 0, 0, 1, 1602, 0, 0, 0, 1, 1591, 0, 0, 0, 1, 1590, 0, 0, 0, 1, 1626, 0, 0, 0, 1, 1696, 0, 0, 0, 1, 1701, 0, 0, 0, 1, 1713, 0, 0, 0, 1, 1813, 0, 0, 0, 1, 1820, 0, 0, 0, 1, 1143, 0, 0, 0, 1, 697, 0, 0, 0, 1, 712, 0, 0, 0, 1, 1148, 0, 0, 0, 1, 1124, 0, 0, 0, 1, 1280, 0, 0, 0, 1, 1124, 0, 0, 0, 1, 1173, 0, 0, 0, 1, 1174, 0, 0, 0, 1, 1180, 0, 0, 0, 1, 1186, 0, 0, 0, 1, 1189, 0, 0, 0, 1, 1279, 0, 0, 0, 1, 1282, 0, 0, 0, 1, 1199, 0, 0, 0, 1, 1213, 0, 0, 0, 1, 1295, 0, 0, 0, 1, 1291, 0, 0, 0, 1, 1303, 0, 0, 0, 1, 1204, 0, 0, 0, 1, 1207, 0, 0, 0, 1, 1219, 0, 0, 0, 1, 1306, 0, 0, 0, 1, 1210, 0, 0, 0, 1, 1313, 0, 0, 0, 1, 1309, 0, 0, 0, 1, 1338, 0, 0, 0, 1, 1318, 0, 0, 0, 1, 1317, 0, 0, 0, 1, 1343, 0, 0, 0, 1, 1227, 0, 0, 0, 1, 1361, 0, 0, 0, 1, 1233, 0, 0, 0, 1, 1341, 0, 0, 0, 1, 1375, 0, 0, 0, 1, 1178, 0, 0, 0, 1, 1379, 0, 0, 0, 1, 1366, 0, 0, 0, 1, 1384, 0, 0, 0, 1, 1376, 0, 0, 0, 1, 1395, 0, 0, 0, 1, 1374, 0, 0, 0, 1, 1380, 0, 0, 0, 1, 1659, 0, 0, 0, 1, 1827, 0, 0, 0, 1, 1406, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1474, 0, 0, 0, 1, 1453, 0, 0, 0, 1, 668, 0, 0, 0, 1, 885, 0, 0, 0, 1, 890, 0, 0, 0, 1, 1135, 0, 0, 0, 1, 1162, 0, 0, 0, 1, 1163, 0, 0, 0, 1, 1169, 0, 0, 0, 1, 1184, 0, 0, 0, 1, 1192, 0, 0, 0, 1, 1223, 0, 0, 0, 1, 1242, 0, 0, 0, 1, 1248, 0, 0, 0, 1, 1252, 0, 0, 0, 1, 1266, 0, 0, 0, 1, 1270, 0, 0, 0, 1, 1336, 0, 0, 0, 1, 1359, 0, 0, 0, 1, 1370, 0, 0, 0, 1, 1394, 0, 0, 0, 1, 1400, 0, 0, 0, 1, 1399, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1449, 0, 0, 0, 1, 1458, 0, 0, 0, 1, 1537, 0, 0, 0, 1, 1530, 0, 0, 0, 1, 1532, 0, 0, 0, 1, 1606, 0, 0, 0, 1, 1609, 0, 0, 0, 1, 1630, 0, 0, 0, 1, 1669, 0, 0, 0, 1, 1726, 0, 0, 0, 1, 1563, 0, 0, 0, 1, 1508, 0, 0, 0, 1, 1574, 0, 0, 0, 1, 1671, 0, 0, 0, 1, 1565, 0, 0, 0, 1, 1560, 0, 0, 0, 1, 1573, 0, 0, 0, 1, 1570, 0, 0, 0, 1, 1569, 0, 0, 0, 1, 1575, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1601, 0, 0, 0, 1, 1576, 0, 0, 0, 1, 1605, 0, 0, 0, 1, 1578, 0, 0, 0, 1, 1625, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1627, 0, 0, 0, 1, 1274, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1665, 0, 0, 0, 1, 1634, 0, 0, 0, 1, 1667, 0, 0, 0, 1, 1657, 0, 0, 0, 1, 1670, 0, 0, 0, 1, 1652, 0, 0, 0, 1, 1651, 0, 0, 0, 1, 1679, 0, 0, 0, 1, 1666, 0, 0, 0, 1, 1681, 0, 0, 0, 1, 1328, 0, 0, 0, 1, 1779, 0, 0, 0, 1, 1692, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1709, 0, 0, 0, 1, 1687, 0, 0, 0, 1, 1690, 0, 0, 0, 1, 1711, 0, 0, 0, 1, 1474, 0, 0, 0, 1, 1739, 0, 0, 0, 1, 1691, 0, 0, 0, 1, 1741, 0, 0, 0, 1, 1688, 0, 0, 0, 1, 1716, 0, 0, 0, 1, 1745, 0, 0, 0, 1, 1474, 0, 0, 0, 1, 1751, 0, 0, 0, 1, 1697, 0, 0, 0, 1, 1702, 0, 0, 0, 1, 1756, 0, 0, 0, 1, 1714, 0, 0, 0, 1, 1758, 0, 0, 0, 1, 1468, 0, 0, 0, 1, 1623, 0, 0, 0, 1, 1685, 0, 0, 0, 1, 1746, 0, 0, 0, 1, 1757, 0, 0, 0, 1, 1762, 0, 0, 0, 1, 356, 0, 0, 0, 1, 360, 0, 0, 0, 1, 404, 0, 0, 0, 1, 453, 0, 0, 0, 1, 457, 0, 0, 0, 1, 1062, 0, 0, 0, 1, 1760, 0, 0, 0, 1, 1773, 0, 0, 0, 1, 352, 0, 0, 0, 1, 396, 0, 0, 0, 1, 395, 0, 0, 0, 1, 527, 0, 0, 0, 1, 552, 0, 0, 0, 1, 576, 0, 0, 0, 1, 740, 0, 0, 0, 1, 738, 0, 0, 0, 1, 771, 0, 0, 0, 1, 798, 0, 0, 0, 1, 932, 0, 0, 0, 1, 1095, 0, 0, 0, 1, 1137, 0, 0, 0, 1, 1356, 0, 0, 0, 1, 1390, 0, 0, 0, 1, 1414, 0, 0, 0, 1, 1444, 0, 0, 0, 1, 1443, 0, 0, 0, 1, 1508, 0, 0, 0, 1, 1551, 0, 0, 0, 1, 1557, 0, 0, 0, 1, 1767, 0, 0, 0, 1, 1766, 0, 0, 0, 1, 1793, 0, 0, 0, 1, 1710, 0, 0, 0, 1, 1779, 0, 0, 0, 1, 1795, 0, 0, 0, 1, 698, 0, 0, 0, 1, 713, 0, 0, 0, 1, 1417, 0, 0, 0, 1, 1426, 0, 0, 0, 1, 1479, 0, 0, 0, 1, 1752, 0, 0, 0, 1, 1810, 0, 0, 0, 1, 1815, 0, 0, 0, 1, 1474, 0, 0, 0, 1, 1823, 0, 0, 0, 1, 1822, 0, 0, 0, 1, 1624, 0, 0, 0, 1, 1747, 0, 0, 0, 1, 1824, 0, 0, 0, 1, 434, 0, 0, 0, 1, 1409, 0, 0, 0, 1, 1624, 0, 0, 0, 1, 1743, 0, 0, 0, 1, 1816, 0, 0, 0, 1, 1814, 0, 0, 0, 1, 1821, 0, 0, 0, 3, 4, 2, 258, 0, 1, 256, 0, 0, 0, 1, 258, 0, 0, 0, 1, 263, 0, 0, 0, 3, 6, 3, 262, 0, 5, 262, 85, 0, 0, 1, 259, 0, 0, 0, 1, 260, 0, 0, 0, 1, 265, 0, 0, 0, 1, 261, 0, 0, 0, 1, 264, 0, 0, 0, 1, 270, 0, 0, 0, 1, 263, 0, 0, 0, 3, 8, 4, 269, 0, 5, 269, 85, 0, 0, 1, 266, 0, 0, 0, 1, 267, 0, 0, 0, 1, 272, 0, 0, 0, 1, 268, 0, 0, 0, 1, 271, 0, 0, 0, 1, 273, 0, 0, 0, 1, 270, 0, 0, 0, 5, 278, 4294967295, 0, 0, 3, 2, 1, 275, 0, 5, 276, 4294967295, 0, 0, 1, 278, 0, 0, 0, 1, 257, 0, 0, 0, 1, 274, 0, 0, 0, 1, 1, 0, 0, 0, 3, 6, 3, 281, 0, 1, 279, 0, 0, 0, 1, 284, 0, 0, 0, 1, 280, 0, 0, 0, 1, 283, 0, 0, 0, 1, 285, 0, 0, 0, 1, 282, 0, 0, 0, 259, 140, 70, 286, 0, 1, 3, 0, 0, 0, 3, 112, 56, 289, 0, 1, 287, 0, 0, 0, 1, 292, 0, 0, 0, 1, 288, 0, 0, 0, 1, 291, 0, 0, 0, 1, 293, 0, 0, 0, 1, 290, 0, 0, 0, 5, 294, 37, 0, 0, 3, 104, 52, 295, 0, 5, 296, 85, 0, 0, 1, 5, 0, 0, 0, 5, 299, 26, 0, 0, 5, 300, 48, 0, 0, 1, 298, 0, 0, 0, 1, 300, 0, 0, 0, 1, 301, 0, 0, 0, 3, 104, 52, 304, 0, 5, 303, 87, 0, 0, 5, 305, 105, 0, 0, 1, 302, 0, 0, 0, 1, 305, 0, 0, 0, 1, 306, 0, 0, 0, 5, 307, 85, 0, 0, 1, 7, 0, 0, 0, 3, 12, 6, 310, 0, 1, 308, 0, 0, 0, 1, 313, 0, 0, 0, 1, 309, 0, 0, 0, 1, 312, 0, 0, 0, 1, 319, 0, 0, 0, 1, 311, 0, 0, 0, 259, 16, 8, 320, 0, 259, 24, 12, 320, 0, 259, 32, 16, 320, 0, 259, 124, 62, 320, 0, 259, 146, 73, 320, 0, 1, 314, 0, 0, 0, 1, 315, 0, 0, 0, 1, 316, 0, 0, 0, 1, 317, 0, 0, 0, 1, 318, 0, 0, 0, 1, 9, 0, 0, 0, 259, 12, 6, 327, 0, 5, 327, 32, 0, 0, 5, 327, 52, 0, 0, 5, 327, 57, 0, 0, 5, 327, 63, 0, 0, 1, 321, 0, 0, 0, 1, 322, 0, 0, 0, 1, 323, 0, 0, 0, 1, 324, 0, 0, 0, 1, 325, 0, 0, 0, 1, 11, 0, 0, 0, 259, 112, 56, 339, 0, 5, 339, 42, 0, 0, 5, 339, 40, 0, 0, 5, 339, 39, 0, 0, 5, 339, 48, 0, 0, 5, 339, 1, 0, 0, 5, 339, 19, 0, 0, 5, 339, 49, 0, 0, 5, 339, 46, 0, 0, 5, 339, 34, 0, 0, 1, 328, 0, 0, 0, 1, 329, 0, 0, 0, 1, 330, 0, 0, 0, 1, 331, 0, 0, 0, 1, 332, 0, 0, 0, 1, 333, 0, 0, 0, 1, 334, 0, 0, 0, 1, 335, 0, 0, 0, 1, 336, 0, 0, 0, 1, 337, 0, 0, 0, 1, 13, 0, 0, 0, 5, 343, 19, 0, 0, 259, 112, 56, 343, 0, 1, 340, 0, 0, 0, 1, 341, 0, 0, 0, 1, 15, 0, 0, 0, 5, 345, 9, 0, 0, 3, 162, 81, 347, 0, 3, 18, 9, 348, 0, 1, 346, 0, 0, 0, 1, 348, 0, 0, 0, 1, 351, 0, 0, 0, 5, 350, 18, 0, 0, 3, 244, 122, 352, 0, 1, 349, 0, 0, 0, 1, 352, 0, 0, 0, 1, 355, 0, 0, 0, 5, 354, 25, 0, 0, 3, 242, 121, 356, 0, 1, 353, 0, 0, 0, 1, 356, 0, 0, 0, 1, 359, 0, 0, 0, 5, 358, 38, 0, 0, 3, 242, 121, 360, 0, 1, 357, 0, 0, 0, 1, 360, 0, 0, 0, 1, 361, 0, 0, 0, 259, 34, 17, 362, 0, 1, 17, 0, 0, 0, 5, 364, 90, 0, 0, 3, 20, 10, 369, 0, 5, 366, 86, 0, 0, 3, 20, 10, 368, 0, 1, 365, 0, 0, 0, 1, 371, 0, 0, 0, 1, 367, 0, 0, 0, 1, 370, 0, 0, 0, 1, 372, 0, 0, 0, 1, 369, 0, 0, 0, 5, 373, 89, 0, 0, 1, 19, 0, 0, 0, 3, 112, 56, 376, 0, 1, 374, 0, 0, 0, 1, 379, 0, 0, 0, 1, 375, 0, 0, 0, 1, 378, 0, 0, 0, 1, 380, 0, 0, 0, 1, 377, 0, 0, 0, 3, 162, 81, 389, 0, 5, 385, 18, 0, 0, 3, 112, 56, 384, 0, 1, 382, 0, 0, 0, 1, 387, 0, 0, 0, 1, 383, 0, 0, 0, 1, 386, 0, 0, 0, 1, 388, 0, 0, 0, 1, 385, 0, 0, 0, 259, 22, 11, 390, 0, 1, 381, 0, 0, 0, 1, 390, 0, 0, 0, 1, 21, 0, 0, 0, 3, 244, 122, 396, 0, 5, 393, 107, 0, 0, 3, 244, 122, 395, 0, 1, 392, 0, 0, 0, 1, 398, 0, 0, 0, 1, 394, 0, 0, 0, 1, 397, 0, 0, 0, 1, 23, 0, 0, 0, 1, 396, 0, 0, 0, 5, 400, 16, 0, 0, 3, 162, 81, 403, 0, 5, 402, 25, 0, 0, 3, 242, 121, 404, 0, 1, 401, 0, 0, 0, 1, 404, 0, 0, 0, 1, 405, 0, 0, 0, 5, 407, 81, 0, 0, 3, 26, 13, 408, 0, 1, 406, 0, 0, 0, 1, 408, 0, 0, 0, 1, 410, 0, 0, 0, 5, 411, 86, 0, 0, 1, 409, 0, 0, 0, 1, 411, 0, 0, 0, 1, 413, 0, 0, 0, 3, 30, 15, 414, 0, 1, 412, 0, 0, 0, 1, 414, 0, 0, 0, 1, 415, 0, 0, 0, 5, 416, 82, 0, 0, 1, 25, 0, 0, 0, 3, 28, 14, 422, 0, 5, 419, 86, 0, 0, 3, 28, 14, 421, 0, 1, 418, 0, 0, 0, 1, 424, 0, 0, 0, 1, 420, 0, 0, 0, 1, 423, 0, 0, 0, 1, 27, 0, 0, 0, 1, 422, 0, 0, 0, 3, 112, 56, 427, 0, 1, 425, 0, 0, 0, 1, 430, 0, 0, 0, 1, 426, 0, 0, 0, 1, 429, 0, 0, 0, 1, 431, 0, 0, 0, 1, 428, 0, 0, 0, 3, 162, 81, 433, 0, 3, 254, 127, 434, 0, 1, 432, 0, 0, 0, 1, 434, 0, 0, 0, 1, 436, 0, 0, 0, 259, 34, 17, 437, 0, 1, 435, 0, 0, 0, 1, 437, 0, 0, 0, 1, 29, 0, 0, 0, 5, 442, 85, 0, 0, 3, 38, 19, 441, 0, 1, 439, 0, 0, 0, 1, 444, 0, 0, 0, 1, 440, 0, 0, 0, 1, 443, 0, 0, 0, 1, 31, 0, 0, 0, 1, 442, 0, 0, 0, 5, 446, 29, 0, 0, 3, 162, 81, 448, 0, 3, 18, 9, 449, 0, 1, 447, 0, 0, 0, 1, 449, 0, 0, 0, 1, 452, 0, 0, 0, 5, 451, 18, 0, 0, 3, 242, 121, 453, 0, 1, 450, 0, 0, 0, 1, 453, 0, 0, 0, 1, 456, 0, 0, 0, 5, 455, 38, 0, 0, 3, 242, 121, 457, 0, 1, 454, 0, 0, 0, 1, 457, 0, 0, 0, 1, 458, 0, 0, 0, 259, 36, 18, 459, 0, 1, 33, 0, 0, 0, 5, 464, 81, 0, 0, 3, 38, 19, 463, 0, 1, 461, 0, 0, 0, 1, 466, 0, 0, 0, 1, 462, 0, 0, 0, 1, 465, 0, 0, 0, 1, 467, 0, 0, 0, 1, 464, 0, 0, 0, 5, 468, 82, 0, 0, 1, 35, 0, 0, 0, 5, 473, 81, 0, 0, 3, 58, 29, 472, 0, 1, 470, 0, 0, 0, 1, 475, 0, 0, 0, 1, 471, 0, 0, 0, 1, 474, 0, 0, 0, 1, 476, 0, 0, 0, 1, 473, 0, 0, 0, 5, 477, 82, 0, 0, 1, 37, 0, 0, 0, 5, 491, 85, 0, 0, 5, 481, 48, 0, 0, 1, 479, 0, 0, 0, 1, 481, 0, 0, 0, 1, 482, 0, 0, 0, 259, 156, 78, 491, 0, 3, 10, 5, 485, 0, 1, 483, 0, 0, 0, 1, 488, 0, 0, 0, 1, 484, 0, 0, 0, 1, 487, 0, 0, 0, 1, 489, 0, 0, 0, 1, 486, 0, 0, 0, 259, 40, 20, 491, 0, 1, 478, 0, 0, 0, 1, 480, 0, 0, 0, 1, 486, 0, 0, 0, 1, 39, 0, 0, 0, 259, 146, 73, 503, 0, 259, 42, 21, 503, 0, 259, 48, 24, 503, 0, 259, 56, 28, 503, 0, 259, 52, 26, 503, 0, 259, 50, 25, 503, 0, 259, 32, 16, 503, 0, 259, 124, 62, 503, 0, 259, 16, 8, 503, 0, 259, 24, 12, 503, 0, 1, 492, 0, 0, 0, 1, 493, 0, 0, 0, 1, 494, 0, 0, 0, 1, 495, 0, 0, 0, 1, 496, 0, 0, 0, 1, 497, 0, 0, 0, 1, 498, 0, 0, 0, 1, 499, 0, 0, 0, 1, 500, 0, 0, 0, 1, 501, 0, 0, 0, 1, 41, 0, 0, 0, 3, 46, 23, 505, 0, 3, 162, 81, 506, 0, 3, 92, 46, 511, 0, 5, 508, 83, 0, 0, 5, 510, 84, 0, 0, 1, 507, 0, 0, 0, 1, 513, 0, 0, 0, 1, 509, 0, 0, 0, 1, 512, 0, 0, 0, 1, 516, 0, 0, 0, 1, 511, 0, 0, 0, 5, 515, 55, 0, 0, 3, 90, 45, 517, 0, 1, 514, 0, 0, 0, 1, 517, 0, 0, 0, 1, 518, 0, 0, 0, 259, 44, 22, 519, 0, 1, 43, 0, 0, 0, 259, 156, 78, 523, 0, 5, 523, 85, 0, 0, 1, 520, 0, 0, 0, 1, 521, 0, 0, 0, 1, 45, 0, 0, 0, 259, 244, 122, 527, 0, 5, 527, 62, 0, 0, 1, 524, 0, 0, 0, 1, 525, 0, 0, 0, 1, 47, 0, 0, 0, 3, 18, 9, 529, 0, 259, 42, 21, 530, 0, 1, 49, 0, 0, 0, 3, 18, 9, 532, 0, 259, 52, 26, 533, 0, 1, 51, 0, 0, 0, 3, 162, 81, 535, 0, 3, 92, 46, 538, 0, 5, 537, 55, 0, 0, 3, 90, 45, 539, 0, 1, 536, 0, 0, 0, 1, 539, 0, 0, 0, 1, 540, 0, 0, 0, 259, 156, 78, 541, 0, 1, 53, 0, 0, 0, 3, 10, 5, 544, 0, 1, 542, 0, 0, 0, 1, 547, 0, 0, 0, 1, 543, 0, 0, 0, 1, 546, 0, 0, 0, 1, 548, 0, 0, 0, 1, 545, 0, 0, 0, 3, 162, 81, 549, 0, 259, 156, 78, 550, 0, 1, 55, 0, 0, 0, 3, 244, 122, 552, 0, 3, 74, 37, 553, 0, 5, 554, 85, 0, 0, 1, 57, 0, 0, 0, 3, 10, 5, 557, 0, 1, 555, 0, 0, 0, 1, 560, 0, 0, 0, 1, 556, 0, 0, 0, 1, 559, 0, 0, 0, 1, 561, 0, 0, 0, 1, 558, 0, 0, 0, 259, 60, 30, 564, 0, 5, 564, 85, 0, 0, 1, 558, 0, 0, 0, 1, 562, 0, 0, 0, 1, 59, 0, 0, 0, 259, 146, 73, 574, 0, 259, 62, 31, 574, 0, 259, 66, 33, 574, 0, 259, 70, 35, 574, 0, 259, 32, 16, 574, 0, 259, 124, 62, 574, 0, 259, 16, 8, 574, 0, 259, 24, 12, 574, 0, 1, 565, 0, 0, 0, 1, 566, 0, 0, 0, 1, 567, 0, 0, 0, 1, 568, 0, 0, 0, 1, 569, 0, 0, 0, 1, 570, 0, 0, 0, 1, 571, 0, 0, 0, 1, 572, 0, 0, 0, 1, 61, 0, 0, 0, 3, 244, 122, 576, 0, 3, 64, 32, 581, 0, 5, 578, 86, 0, 0, 3, 64, 32, 580, 0, 1, 577, 0, 0, 0, 1, 583, 0, 0, 0, 1, 579, 0, 0, 0, 1, 582, 0, 0, 0, 1, 584, 0, 0, 0, 1, 581, 0, 0, 0, 5, 585, 85, 0, 0, 1, 63, 0, 0, 0, 3, 162, 81, 591, 0, 5, 588, 83, 0, 0, 5, 590, 84, 0, 0, 1, 587, 0, 0, 0, 1, 593, 0, 0, 0, 1, 589, 0, 0, 0, 1, 592, 0, 0, 0, 1, 594, 0, 0, 0, 1, 591, 0, 0, 0, 5, 595, 88, 0, 0, 259, 80, 40, 596, 0, 1, 65, 0, 0, 0, 3, 68, 34, 599, 0, 1, 597, 0, 0, 0, 1, 602, 0, 0, 0, 1, 598, 0, 0, 0, 1, 601, 0, 0, 0, 1, 603, 0, 0, 0, 1, 600, 0, 0, 0, 259, 72, 36, 604, 0, 1, 67, 0, 0, 0, 259, 112, 56, 612, 0, 5, 612, 42, 0, 0, 5, 612, 1, 0, 0, 5, 612, 12, 0, 0, 5, 612, 48, 0, 0, 5, 612, 49, 0, 0, 1, 605, 0, 0, 0, 1, 606, 0, 0, 0, 1, 607, 0, 0, 0, 1, 608, 0, 0, 0, 1, 609, 0, 0, 0, 1, 610, 0, 0, 0, 1, 69, 0, 0, 0, 3, 68, 34, 615, 0, 1, 613, 0, 0, 0, 1, 618, 0, 0, 0, 1, 614, 0, 0, 0, 1, 617, 0, 0, 0, 1, 619, 0, 0, 0, 1, 616, 0, 0, 0, 3, 18, 9, 620, 0, 259, 72, 36, 621, 0, 1, 71, 0, 0, 0, 3, 112, 56, 624, 0, 1, 622, 0, 0, 0, 1, 627, 0, 0, 0, 1, 623, 0, 0, 0, 1, 626, 0, 0, 0, 1, 628, 0, 0, 0, 1, 625, 0, 0, 0, 3, 46, 23, 629, 0, 3, 162, 81, 630, 0, 3, 92, 46, 635, 0, 5, 632, 83, 0, 0, 5, 634, 84, 0, 0, 1, 631, 0, 0, 0, 1, 637, 0, 0, 0, 1, 633, 0, 0, 0, 1, 636, 0, 0, 0, 1, 640, 0, 0, 0, 1, 635, 0, 0, 0, 5, 639, 55, 0, 0, 3, 90, 45, 641, 0, 1, 638, 0, 0, 0, 1, 641, 0, 0, 0, 1, 642, 0, 0, 0, 259, 44, 22, 643, 0, 1, 73, 0, 0, 0, 3, 76, 38, 649, 0, 5, 646, 86, 0, 0, 3, 76, 38, 648, 0, 1, 645, 0, 0, 0, 1, 651, 0, 0, 0, 1, 647, 0, 0, 0, 1, 650, 0, 0, 0, 1, 75, 0, 0, 0, 1, 649, 0, 0, 0, 3, 78, 39, 655, 0, 5, 654, 88, 0, 0, 259, 80, 40, 656, 0, 1, 653, 0, 0, 0, 1, 656, 0, 0, 0, 1, 77, 0, 0, 0, 3, 162, 81, 662, 0, 5, 659, 83, 0, 0, 5, 661, 84, 0, 0, 1, 658, 0, 0, 0, 1, 664, 0, 0, 0, 1, 660, 0, 0, 0, 1, 663, 0, 0, 0, 1, 79, 0, 0, 0, 1, 662, 0, 0, 0, 259, 82, 41, 668, 0, 259, 196, 98, 668, 0, 1, 665, 0, 0, 0, 1, 666, 0, 0, 0, 1, 81, 0, 0, 0, 5, 681, 81, 0, 0, 3, 80, 40, 675, 0, 5, 672, 86, 0, 0, 3, 80, 40, 674, 0, 1, 671, 0, 0, 0, 1, 677, 0, 0, 0, 1, 673, 0, 0, 0, 1, 676, 0, 0, 0, 1, 679, 0, 0, 0, 1, 675, 0, 0, 0, 5, 680, 86, 0, 0, 1, 678, 0, 0, 0, 1, 680, 0, 0, 0, 1, 682, 0, 0, 0, 1, 670, 0, 0, 0, 1, 682, 0, 0, 0, 1, 683, 0, 0, 0, 5, 684, 82, 0, 0, 1, 83, 0, 0, 0, 3, 86, 43, 686, 0, 5, 690, 87, 0, 0, 3, 112, 56, 689, 0, 1, 687, 0, 0, 0, 1, 692, 0, 0, 0, 1, 688, 0, 0, 0, 1, 691, 0, 0, 0, 1, 694, 0, 0, 0, 1, 690, 0, 0, 0, 1, 685, 0, 0, 0, 1, 694, 0, 0, 0, 1, 695, 0, 0, 0, 3, 164, 82, 697, 0, 3, 248, 124, 698, 0, 1, 696, 0, 0, 0, 1, 698, 0, 0, 0, 1, 700, 0, 0, 0, 1, 693, 0, 0, 0, 1, 701, 0, 0, 0, 1, 699, 0, 0, 0, 1, 702, 0, 0, 0, 1, 716, 0, 0, 0, 5, 707, 87, 0, 0, 3, 112, 56, 706, 0, 1, 704, 0, 0, 0, 1, 709, 0, 0, 0, 1, 705, 0, 0, 0, 1, 708, 0, 0, 0, 1, 710, 0, 0, 0, 1, 707, 0, 0, 0, 3, 164, 82, 712, 0, 3, 248, 124, 713, 0, 1, 711, 0, 0, 0, 1, 713, 0, 0, 0, 1, 715, 0, 0, 0, 1, 703, 0, 0, 0, 1, 718, 0, 0, 0, 1, 714, 0, 0, 0, 1, 717, 0, 0, 0, 1, 85, 0, 0, 0, 1, 716, 0, 0, 0, 3, 162, 81, 724, 0, 5, 721, 87, 0, 0, 3, 162, 81, 723, 0, 1, 720, 0, 0, 0, 1, 726, 0, 0, 0, 1, 722, 0, 0, 0, 1, 725, 0, 0, 0, 1, 87, 0, 0, 0, 1, 724, 0, 0, 0, 259, 244, 122, 740, 0, 3, 112, 56, 730, 0, 1, 728, 0, 0, 0, 1, 733, 0, 0, 0, 1, 729, 0, 0, 0, 1, 732, 0, 0, 0, 1, 734, 0, 0, 0, 1, 731, 0, 0, 0, 5, 737, 93, 0, 0, 7, 736, 0, 0, 0, 259, 244, 122, 738, 0, 1, 735, 0, 0, 0, 1, 738, 0, 0, 0, 1, 740, 0, 0, 0, 1, 727, 0, 0, 0, 1, 731, 0, 0, 0, 1, 89, 0, 0, 0, 3, 104, 52, 746, 0, 5, 743, 86, 0, 0, 3, 104, 52, 745, 0, 1, 742, 0, 0, 0, 1, 748, 0, 0, 0, 1, 744, 0, 0, 0, 1, 747, 0, 0, 0, 1, 91, 0, 0, 0, 1, 746, 0, 0, 0, 5, 761, 79, 0, 0, 3, 94, 47, 753, 0, 3, 98, 49, 753, 0, 1, 750, 0, 0, 0, 1, 751, 0, 0, 0, 1, 758, 0, 0, 0, 5, 755, 86, 0, 0, 3, 96, 48, 757, 0, 1, 754, 0, 0, 0, 1, 760, 0, 0, 0, 1, 756, 0, 0, 0, 1, 759, 0, 0, 0, 1, 762, 0, 0, 0, 1, 758, 0, 0, 0, 1, 752, 0, 0, 0, 1, 762, 0, 0, 0, 1, 763, 0, 0, 0, 5, 764, 80, 0, 0, 1, 93, 0, 0, 0, 3, 244, 122, 771, 0, 3, 162, 81, 767, 0, 5, 768, 87, 0, 0, 1, 770, 0, 0, 0, 1, 766, 0, 0, 0, 1, 773, 0, 0, 0, 1, 769, 0, 0, 0, 1, 772, 0, 0, 0, 1, 774, 0, 0, 0, 1, 771, 0, 0, 0, 5, 775, 53, 0, 0, 1, 95, 0, 0, 0, 3, 98, 49, 781, 0, 5, 778, 86, 0, 0, 3, 98, 49, 780, 0, 1, 777, 0, 0, 0, 1, 783, 0, 0, 0, 1, 779, 0, 0, 0, 1, 782, 0, 0, 0, 1, 97, 0, 0, 0, 1, 781, 0, 0, 0, 3, 14, 7, 786, 0, 1, 784, 0, 0, 0, 1, 789, 0, 0, 0, 1, 785, 0, 0, 0, 1, 788, 0, 0, 0, 1, 790, 0, 0, 0, 1, 787, 0, 0, 0, 3, 244, 122, 798, 0, 3, 112, 56, 793, 0, 1, 791, 0, 0, 0, 1, 796, 0, 0, 0, 1, 792, 0, 0, 0, 1, 795, 0, 0, 0, 1, 797, 0, 0, 0, 1, 794, 0, 0, 0, 5, 799, 125, 0, 0, 1, 794, 0, 0, 0, 1, 799, 0, 0, 0, 1, 800, 0, 0, 0, 259, 78, 39, 801, 0, 1, 99, 0, 0, 0, 3, 102, 51, 807, 0, 5, 804, 86, 0, 0, 3, 102, 51, 806, 0, 1, 803, 0, 0, 0, 1, 809, 0, 0, 0, 1, 805, 0, 0, 0, 1, 808, 0, 0, 0, 1, 101, 0, 0, 0, 1, 807, 0, 0, 0, 3, 14, 7, 812, 0, 1, 810, 0, 0, 0, 1, 815, 0, 0, 0, 1, 811, 0, 0, 0, 1, 814, 0, 0, 0, 1, 816, 0, 0, 0, 1, 813, 0, 0, 0, 5, 817, 61, 0, 0, 259, 162, 81, 818, 0, 1, 103, 0, 0, 0, 3, 162, 81, 824, 0, 5, 821, 87, 0, 0, 3, 162, 81, 823, 0, 1, 820, 0, 0, 0, 1, 826, 0, 0, 0, 1, 822, 0, 0, 0, 1, 825, 0, 0, 0, 1, 105, 0, 0, 0, 1, 824, 0, 0, 0, 259, 108, 54, 835, 0, 259, 110, 55, 835, 0, 5, 835, 75, 0, 0, 5, 835, 76, 0, 0, 5, 835, 74, 0, 0, 5, 835, 78, 0, 0, 5, 835, 77, 0, 0, 1, 827, 0, 0, 0, 1, 828, 0, 0, 0, 1, 829, 0, 0, 0, 1, 830, 0, 0, 0, 1, 831, 0, 0, 0, 1, 832, 0, 0, 0, 1, 833, 0, 0, 0, 1, 107, 0, 0, 0, 7, 837, 1, 0, 0, 1, 109, 0, 0, 0, 7, 839, 2, 0, 0, 1, 111, 0, 0, 0, 5, 841, 124, 0, 0, 3, 104, 52, 842, 0, 1, 844, 0, 0, 0, 259, 114, 57, 845, 0, 1, 843, 0, 0, 0, 1, 845, 0, 0, 0, 1, 113, 0, 0, 0, 5, 855, 79, 0, 0, 3, 116, 58, 852, 0, 5, 849, 86, 0, 0, 3, 116, 58, 851, 0, 1, 848, 0, 0, 0, 1, 854, 0, 0, 0, 1, 850, 0, 0, 0, 1, 853, 0, 0, 0, 1, 856, 0, 0, 0, 1, 852, 0, 0, 0, 1, 847, 0, 0, 0, 1, 856, 0, 0, 0, 1, 857, 0, 0, 0, 5, 858, 80, 0, 0, 1, 115, 0, 0, 0, 4, 860, 58, 0, 0, 259, 118, 59, 866, 0, 3, 162, 81, 862, 0, 5, 863, 88, 0, 0, 259, 118, 59, 864, 0, 1, 866, 0, 0, 0, 1, 859, 0, 0, 0, 1, 861, 0, 0, 0, 1, 117, 0, 0, 0, 259, 196, 98, 885, 0, 259, 112, 56, 885, 0, 5, 878, 81, 0, 0, 3, 118, 59, 875, 0, 5, 872, 86, 0, 0, 3, 118, 59, 874, 0, 1, 871, 0, 0, 0, 1, 877, 0, 0, 0, 1, 873, 0, 0, 0, 1, 876, 0, 0, 0, 1, 879, 0, 0, 0, 1, 875, 0, 0, 0, 1, 870, 0, 0, 0, 1, 879, 0, 0, 0, 1, 881, 0, 0, 0, 5, 882, 86, 0, 0, 1, 880, 0, 0, 0, 1, 882, 0, 0, 0, 1, 883, 0, 0, 0, 5, 885, 82, 0, 0, 1, 867, 0, 0, 0, 1, 868, 0, 0, 0, 1, 869, 0, 0, 0, 1, 119, 0, 0, 0, 259, 196, 98, 890, 0, 259, 112, 56, 890, 0, 259, 122, 61, 890, 0, 1, 886, 0, 0, 0, 1, 887, 0, 0, 0, 1, 888, 0, 0, 0, 1, 121, 0, 0, 0, 5, 900, 81, 0, 0, 3, 120, 60, 897, 0, 5, 894, 86, 0, 0, 3, 120, 60, 896, 0, 1, 893, 0, 0, 0, 1, 899, 0, 0, 0, 1, 895, 0, 0, 0, 1, 898, 0, 0, 0, 1, 901, 0, 0, 0, 1, 897, 0, 0, 0, 1, 892, 0, 0, 0, 1, 901, 0, 0, 0, 1, 903, 0, 0, 0, 5, 904, 86, 0, 0, 1, 902, 0, 0, 0, 1, 904, 0, 0, 0, 1, 905, 0, 0, 0, 5, 906, 82, 0, 0, 1, 123, 0, 0, 0, 5, 908, 124, 0, 0, 5, 909, 29, 0, 0, 3, 162, 81, 910, 0, 259, 126, 63, 911, 0, 1, 125, 0, 0, 0, 5, 916, 81, 0, 0, 3, 128, 64, 915, 0, 1, 913, 0, 0, 0, 1, 918, 0, 0, 0, 1, 914, 0, 0, 0, 1, 917, 0, 0, 0, 1, 919, 0, 0, 0, 1, 916, 0, 0, 0, 5, 920, 82, 0, 0, 1, 127, 0, 0, 0, 3, 10, 5, 923, 0, 1, 921, 0, 0, 0, 1, 926, 0, 0, 0, 1, 922, 0, 0, 0, 1, 925, 0, 0, 0, 1, 927, 0, 0, 0, 1, 924, 0, 0, 0, 259, 130, 65, 930, 0, 5, 930, 85, 0, 0, 1, 924, 0, 0, 0, 1, 928, 0, 0, 0, 1, 129, 0, 0, 0, 3, 244, 122, 932, 0, 3, 132, 66, 933, 0, 5, 934, 85, 0, 0, 1, 956, 0, 0, 0, 3, 16, 8, 937, 0, 5, 938, 85, 0, 0, 1, 936, 0, 0, 0, 1, 938, 0, 0, 0, 1, 956, 0, 0, 0, 3, 32, 16, 941, 0, 5, 942, 85, 0, 0, 1, 940, 0, 0, 0, 1, 942, 0, 0, 0, 1, 956, 0, 0, 0, 3, 24, 12, 945, 0, 5, 946, 85, 0, 0, 1, 944, 0, 0, 0, 1, 946, 0, 0, 0, 1, 956, 0, 0, 0, 3, 124, 62, 949, 0, 5, 950, 85, 0, 0, 1, 948, 0, 0, 0, 1, 950, 0, 0, 0, 1, 956, 0, 0, 0, 3, 146, 73, 953, 0, 5, 954, 85, 0, 0, 1, 952, 0, 0, 0, 1, 954, 0, 0, 0, 1, 956, 0, 0, 0, 1, 931, 0, 0, 0, 1, 935, 0, 0, 0, 1, 939, 0, 0, 0, 1, 943, 0, 0, 0, 1, 947, 0, 0, 0, 1, 951, 0, 0, 0, 1, 131, 0, 0, 0, 259, 134, 67, 960, 0, 259, 136, 68, 960, 0, 1, 957, 0, 0, 0, 1, 958, 0, 0, 0, 1, 133, 0, 0, 0, 3, 162, 81, 962, 0, 5, 963, 79, 0, 0, 5, 965, 80, 0, 0, 259, 138, 69, 966, 0, 1, 964, 0, 0, 0, 1, 966, 0, 0, 0, 1, 135, 0, 0, 0, 259, 74, 37, 968, 0, 1, 137, 0, 0, 0, 5, 970, 12, 0, 0, 259, 120, 60, 971, 0, 1, 139, 0, 0, 0, 3, 112, 56, 974, 0, 1, 972, 0, 0, 0, 1, 977, 0, 0, 0, 1, 973, 0, 0, 0, 1, 976, 0, 0, 0, 1, 979, 0, 0, 0, 1, 975, 0, 0, 0, 5, 980, 35, 0, 0, 1, 978, 0, 0, 0, 1, 980, 0, 0, 0, 1, 981, 0, 0, 0, 5, 982, 31, 0, 0, 3, 104, 52, 983, 0, 5, 987, 81, 0, 0, 3, 142, 71, 986, 0, 1, 984, 0, 0, 0, 1, 989, 0, 0, 0, 1, 985, 0, 0, 0, 1, 988, 0, 0, 0, 1, 990, 0, 0, 0, 1, 987, 0, 0, 0, 5, 991, 82, 0, 0, 1, 141, 0, 0, 0, 5, 996, 44, 0, 0, 3, 144, 72, 995, 0, 1, 993, 0, 0, 0, 1, 998, 0, 0, 0, 1, 994, 0, 0, 0, 1, 997, 0, 0, 0, 1, 999, 0, 0, 0, 1, 996, 0, 0, 0, 3, 104, 52, 1000, 0, 5, 1001, 85, 0, 0, 1, 1050, 0, 0, 0, 5, 1003, 17, 0, 0, 3, 104, 52, 1013, 0, 5, 1005, 56, 0, 0, 3, 104, 52, 1010, 0, 5, 1007, 86, 0, 0, 3, 104, 52, 1009, 0, 1, 1006, 0, 0, 0, 1, 1012, 0, 0, 0, 1, 1008, 0, 0, 0, 1, 1011, 0, 0, 0, 1, 1014, 0, 0, 0, 1, 1010, 0, 0, 0, 1, 1004, 0, 0, 0, 1, 1014, 0, 0, 0, 1, 1015, 0, 0, 0, 5, 1016, 85, 0, 0, 1, 1050, 0, 0, 0, 5, 1018, 36, 0, 0, 3, 104, 52, 1028, 0, 5, 1020, 56, 0, 0, 3, 104, 52, 1025, 0, 5, 1022, 86, 0, 0, 3, 104, 52, 1024, 0, 1, 1021, 0, 0, 0, 1, 1027, 0, 0, 0, 1, 1023, 0, 0, 0, 1, 1026, 0, 0, 0, 1, 1029, 0, 0, 0, 1, 1025, 0, 0, 0, 1, 1019, 0, 0, 0, 1, 1029, 0, 0, 0, 1, 1030, 0, 0, 0, 5, 1031, 85, 0, 0, 1, 1050, 0, 0, 0, 5, 1033, 60, 0, 0, 3, 104, 52, 1034, 0, 5, 1035, 85, 0, 0, 1, 1050, 0, 0, 0, 5, 1037, 41, 0, 0, 3, 104, 52, 1038, 0, 5, 1039, 66, 0, 0, 3, 104, 52, 1044, 0, 5, 1041, 86, 0, 0, 3, 104, 52, 1043, 0, 1, 1040, 0, 0, 0, 1, 1046, 0, 0, 0, 1, 1042, 0, 0, 0, 1, 1045, 0, 0, 0, 1, 1047, 0, 0, 0, 1, 1044, 0, 0, 0, 5, 1048, 85, 0, 0, 1, 1050, 0, 0, 0, 1, 992, 0, 0, 0, 1, 1002, 0, 0, 0, 1, 1017, 0, 0, 0, 1, 1032, 0, 0, 0, 1, 1036, 0, 0, 0, 1, 143, 0, 0, 0, 7, 1052, 3, 0, 0, 1, 145, 0, 0, 0, 5, 1054, 43, 0, 0, 3, 162, 81, 1056, 0, 3, 18, 9, 1057, 0, 1, 1055, 0, 0, 0, 1, 1057, 0, 0, 0, 1, 1058, 0, 0, 0, 3, 148, 74, 1061, 0, 5, 1060, 25, 0, 0, 3, 242, 121, 1062, 0, 1, 1059, 0, 0, 0, 1, 1062, 0, 0, 0, 1, 1063, 0, 0, 0, 259, 154, 77, 1064, 0, 1, 147, 0, 0, 0, 5, 1067, 79, 0, 0, 3, 150, 75, 1068, 0, 1, 1066, 0, 0, 0, 1, 1068, 0, 0, 0, 1, 1069, 0, 0, 0, 5, 1070, 80, 0, 0, 1, 149, 0, 0, 0, 3, 152, 76, 1076, 0, 5, 1073, 86, 0, 0, 3, 152, 76, 1075, 0, 1, 1072, 0, 0, 0, 1, 1078, 0, 0, 0, 1, 1074, 0, 0, 0, 1, 1077, 0, 0, 0, 1, 1079, 0, 0, 0, 1, 1076, 0, 0, 0, 4, 1080, 75, 1, 0, 1, 151, 0, 0, 0, 3, 112, 56, 1083, 0, 1, 1081, 0, 0, 0, 1, 1086, 0, 0, 0, 1, 1082, 0, 0, 0, 1, 1085, 0, 0, 0, 1, 1087, 0, 0, 0, 1, 1084, 0, 0, 0, 3, 244, 122, 1095, 0, 3, 112, 56, 1090, 0, 1, 1088, 0, 0, 0, 1, 1093, 0, 0, 0, 1, 1089, 0, 0, 0, 1, 1092, 0, 0, 0, 1, 1094, 0, 0, 0, 1, 1091, 0, 0, 0, 5, 1096, 125, 0, 0, 1, 1091, 0, 0, 0, 1, 1096, 0, 0, 0, 1, 1097, 0, 0, 0, 259, 162, 81, 1098, 0, 1, 153, 0, 0, 0, 5, 1104, 81, 0, 0, 3, 38, 19, 1103, 0, 3, 54, 27, 1103, 0, 1, 1100, 0, 0, 0, 1, 1101, 0, 0, 0, 1, 1106, 0, 0, 0, 1, 1102, 0, 0, 0, 1, 1105, 0, 0, 0, 1, 1107, 0, 0, 0, 1, 1104, 0, 0, 0, 5, 1108, 82, 0, 0, 1, 155, 0, 0, 0, 5, 1113, 81, 0, 0, 3, 158, 79, 1112, 0, 1, 1110, 0, 0, 0, 1, 1115, 0, 0, 0, 1, 1111, 0, 0, 0, 1, 1114, 0, 0, 0, 1, 1116, 0, 0, 0, 1, 1113, 0, 0, 0, 5, 1117, 82, 0, 0, 1, 157, 0, 0, 0, 3, 160, 80, 1119, 0, 5, 1120, 85, 0, 0, 1, 1124, 0, 0, 0, 259, 166, 83, 1124, 0, 259, 168, 84, 1124, 0, 1, 1118, 0, 0, 0, 1, 1121, 0, 0, 0, 1, 1122, 0, 0, 0, 1, 159, 0, 0, 0, 3, 14, 7, 1127, 0, 1, 1125, 0, 0, 0, 1, 1130, 0, 0, 0, 1, 1126, 0, 0, 0, 1, 1129, 0, 0, 0, 1, 1139, 0, 0, 0, 1, 1128, 0, 0, 0, 5, 1132, 61, 0, 0, 3, 162, 81, 1133, 0, 5, 1134, 88, 0, 0, 259, 196, 98, 1135, 0, 1, 1140, 0, 0, 0, 3, 244, 122, 1137, 0, 259, 74, 37, 1138, 0, 1, 1140, 0, 0, 0, 1, 1131, 0, 0, 0, 1, 1136, 0, 0, 0, 1, 161, 0, 0, 0, 7, 1142, 4, 0, 0, 1, 163, 0, 0, 0, 7, 1144, 5, 0, 0, 1, 165, 0, 0, 0, 3, 12, 6, 1147, 0, 1, 1145, 0, 0, 0, 1, 1150, 0, 0, 0, 1, 1146, 0, 0, 0, 1, 1149, 0, 0, 0, 1, 1155, 0, 0, 0, 1, 1148, 0, 0, 0, 259, 16, 8, 1156, 0, 259, 32, 16, 1156, 0, 259, 146, 73, 1156, 0, 259, 24, 12, 1156, 0, 1, 1151, 0, 0, 0, 1, 1152, 0, 0, 0, 1, 1153, 0, 0, 0, 1, 1154, 0, 0, 0, 1, 167, 0, 0, 0, 259, 156, 78, 1281, 0, 5, 1159, 2, 0, 0, 3, 196, 98, 1162, 0, 5, 1161, 94, 0, 0, 3, 196, 98, 1163, 0, 1, 1160, 0, 0, 0, 1, 1163, 0, 0, 0, 1, 1164, 0, 0, 0, 5, 1165, 85, 0, 0, 1, 1281, 0, 0, 0, 5, 1167, 24, 0, 0, 5, 1168, 79, 0, 0, 3, 196, 98, 1169, 0, 5, 1170, 80, 0, 0, 3, 168, 84, 1173, 0, 5, 1172, 15, 0, 0, 259, 168, 84, 1174, 0, 1, 1171, 0, 0, 0, 1, 1174, 0, 0, 0, 1, 1281, 0, 0, 0, 5, 1176, 22, 0, 0, 5, 1177, 79, 0, 0, 3, 186, 93, 1178, 0, 5, 1179, 80, 0, 0, 259, 168, 84, 1180, 0, 1, 1281, 0, 0, 0, 5, 1182, 65, 0, 0, 5, 1183, 79, 0, 0, 3, 196, 98, 1184, 0, 5, 1185, 80, 0, 0, 259, 168, 84, 1186, 0, 1, 1281, 0, 0, 0, 5, 1188, 13, 0, 0, 3, 168, 84, 1189, 0, 5, 1190, 65, 0, 0, 5, 1191, 79, 0, 0, 3, 196, 98, 1192, 0, 5, 1193, 80, 0, 0, 5, 1194, 85, 0, 0, 1, 1281, 0, 0, 0, 5, 1196, 59, 0, 0, 3, 156, 78, 1206, 0, 3, 170, 85, 1199, 0, 1, 1197, 0, 0, 0, 1, 1200, 0, 0, 0, 1, 1198, 0, 0, 0, 1, 1201, 0, 0, 0, 1, 1203, 0, 0, 0, 259, 174, 87, 1204, 0, 1, 1202, 0, 0, 0, 1, 1204, 0, 0, 0, 1, 1207, 0, 0, 0, 259, 174, 87, 1207, 0, 1, 1198, 0, 0, 0, 1, 1205, 0, 0, 0, 1, 1281, 0, 0, 0, 5, 1209, 59, 0, 0, 3, 176, 88, 1210, 0, 3, 156, 78, 1214, 0, 3, 170, 85, 1213, 0, 1, 1211, 0, 0, 0, 1, 1216, 0, 0, 0, 1, 1212, 0, 0, 0, 1, 1215, 0, 0, 0, 1, 1218, 0, 0, 0, 1, 1214, 0, 0, 0, 259, 174, 87, 1219, 0, 1, 1217, 0, 0, 0, 1, 1219, 0, 0, 0, 1, 1281, 0, 0, 0, 5, 1221, 51, 0, 0, 5, 1222, 79, 0, 0, 3, 196, 98, 1223, 0, 5, 1224, 80, 0, 0, 5, 1228, 81, 0, 0, 3, 182, 91, 1227, 0, 1, 1225, 0, 0, 0, 1, 1230, 0, 0, 0, 1, 1226, 0, 0, 0, 1, 1229, 0, 0, 0, 1, 1234, 0, 0, 0, 1, 1228, 0, 0, 0, 3, 184, 92, 1233, 0, 1, 1231, 0, 0, 0, 1, 1236, 0, 0, 0, 1, 1232, 0, 0, 0, 1, 1235, 0, 0, 0, 1, 1237, 0, 0, 0, 1, 1234, 0, 0, 0, 5, 1238, 82, 0, 0, 1, 1281, 0, 0, 0, 5, 1240, 52, 0, 0, 5, 1241, 79, 0, 0, 3, 196, 98, 1242, 0, 5, 1243, 80, 0, 0, 259, 156, 78, 1244, 0, 1, 1281, 0, 0, 0, 5, 1247, 45, 0, 0, 3, 196, 98, 1248, 0, 1, 1246, 0, 0, 0, 1, 1248, 0, 0, 0, 1, 1249, 0, 0, 0, 5, 1281, 85, 0, 0, 5, 1251, 54, 0, 0, 3, 196, 98, 1252, 0, 5, 1253, 85, 0, 0, 1, 1281, 0, 0, 0, 5, 1256, 4, 0, 0, 3, 162, 81, 1257, 0, 1, 1255, 0, 0, 0, 1, 1257, 0, 0, 0, 1, 1258, 0, 0, 0, 5, 1281, 85, 0, 0, 5, 1261, 11, 0, 0, 3, 162, 81, 1262, 0, 1, 1260, 0, 0, 0, 1, 1262, 0, 0, 0, 1, 1263, 0, 0, 0, 5, 1281, 85, 0, 0, 5, 1265, 67, 0, 0, 3, 196, 98, 1266, 0, 5, 1267, 85, 0, 0, 1, 1281, 0, 0, 0, 5, 1281, 85, 0, 0, 3, 196, 98, 1270, 0, 5, 1271, 85, 0, 0, 1, 1281, 0, 0, 0, 3, 212, 106, 1274, 0, 5, 1275, 85, 0, 0, 1, 1273, 0, 0, 0, 1, 1275, 0, 0, 0, 1, 1281, 0, 0, 0, 3, 162, 81, 1277, 0, 5, 1278, 94, 0, 0, 259, 168, 84, 1279, 0, 1, 1281, 0, 0, 0, 1, 1157, 0, 0, 0, 1, 1158, 0, 0, 0, 1, 1166, 0, 0, 0, 1, 1175, 0, 0, 0, 1, 1181, 0, 0, 0, 1, 1187, 0, 0, 0, 1, 1195, 0, 0, 0, 1, 1208, 0, 0, 0, 1, 1220, 0, 0, 0, 1, 1239, 0, 0, 0, 1, 1245, 0, 0, 0, 1, 1250, 0, 0, 0, 1, 1254, 0, 0, 0, 1, 1259, 0, 0, 0, 1, 1264, 0, 0, 0, 1, 1268, 0, 0, 0, 1, 1269, 0, 0, 0, 1, 1272, 0, 0, 0, 1, 1276, 0, 0, 0, 1, 169, 0, 0, 0, 5, 1283, 7, 0, 0, 5, 1287, 79, 0, 0, 3, 14, 7, 1286, 0, 1, 1284, 0, 0, 0, 1, 1289, 0, 0, 0, 1, 1285, 0, 0, 0, 1, 1288, 0, 0, 0, 1, 1290, 0, 0, 0, 1, 1287, 0, 0, 0, 3, 172, 86, 1291, 0, 3, 162, 81, 1292, 0, 5, 1293, 80, 0, 0, 259, 156, 78, 1294, 0, 1, 171, 0, 0, 0, 3, 104, 52, 1300, 0, 5, 1297, 108, 0, 0, 3, 104, 52, 1299, 0, 1, 1296, 0, 0, 0, 1, 1302, 0, 0, 0, 1, 1298, 0, 0, 0, 1, 1301, 0, 0, 0, 1, 173, 0, 0, 0, 1, 1300, 0, 0, 0, 5, 1304, 20, 0, 0, 259, 156, 78, 1305, 0, 1, 175, 0, 0, 0, 5, 1307, 79, 0, 0, 3, 178, 89, 1309, 0, 5, 1310, 85, 0, 0, 1, 1308, 0, 0, 0, 1, 1310, 0, 0, 0, 1, 1311, 0, 0, 0, 5, 1312, 80, 0, 0, 1, 177, 0, 0, 0, 3, 180, 90, 1318, 0, 5, 1315, 85, 0, 0, 3, 180, 90, 1317, 0, 1, 1314, 0, 0, 0, 1, 1320, 0, 0, 0, 1, 1316, 0, 0, 0, 1, 1319, 0, 0, 0, 1, 179, 0, 0, 0, 1, 1318, 0, 0, 0, 3, 14, 7, 1323, 0, 1, 1321, 0, 0, 0, 1, 1326, 0, 0, 0, 1, 1322, 0, 0, 0, 1, 1325, 0, 0, 0, 1, 1332, 0, 0, 0, 1, 1324, 0, 0, 0, 3, 222, 111, 1328, 0, 3, 78, 39, 1329, 0, 1, 1333, 0, 0, 0, 5, 1331, 61, 0, 0, 3, 162, 81, 1333, 0, 1, 1327, 0, 0, 0, 1, 1330, 0, 0, 0, 1, 1334, 0, 0, 0, 5, 1335, 88, 0, 0, 259, 196, 98, 1336, 0, 1, 1339, 0, 0, 0, 259, 104, 52, 1339, 0, 1, 1324, 0, 0, 0, 1, 1337, 0, 0, 0, 1, 181, 0, 0, 0, 3, 184, 92, 1341, 0, 5, 1342, 94, 0, 0, 1, 1344, 0, 0, 0, 1, 1340, 0, 0, 0, 1, 1345, 0, 0, 0, 1, 1343, 0, 0, 0, 1, 1346, 0, 0, 0, 1, 1348, 0, 0, 0, 3, 158, 79, 1349, 0, 1, 1347, 0, 0, 0, 1, 1350, 0, 0, 0, 1, 1348, 0, 0, 0, 1, 1351, 0, 0, 0, 1, 183, 0, 0, 0, 5, 1358, 6, 0, 0, 259, 196, 98, 1359, 0, 5, 1359, 129, 0, 0, 3, 244, 122, 1356, 0, 259, 162, 81, 1357, 0, 1, 1359, 0, 0, 0, 1, 1353, 0, 0, 0, 1, 1354, 0, 0, 0, 1, 1355, 0, 0, 0, 1, 1362, 0, 0, 0, 5, 1362, 12, 0, 0, 1, 1352, 0, 0, 0, 1, 1360, 0, 0, 0, 1, 185, 0, 0, 0, 259, 190, 95, 1376, 0, 3, 188, 94, 1366, 0, 1, 1364, 0, 0, 0, 1, 1366, 0, 0, 0, 1, 1367, 0, 0, 0, 5, 1369, 85, 0, 0, 3, 196, 98, 1370, 0, 1, 1368, 0, 0, 0, 1, 1370, 0, 0, 0, 1, 1371, 0, 0, 0, 5, 1373, 85, 0, 0, 259, 192, 96, 1374, 0, 1, 1372, 0, 0, 0, 1, 1374, 0, 0, 0, 1, 1376, 0, 0, 0, 1, 1363, 0, 0, 0, 1, 1365, 0, 0, 0, 1, 187, 0, 0, 0, 259, 160, 80, 1380, 0, 259, 192, 96, 1380, 0, 1, 1377, 0, 0, 0, 1, 1378, 0, 0, 0, 1, 189, 0, 0, 0, 3, 14, 7, 1383, 0, 1, 1381, 0, 0, 0, 1, 1386, 0, 0, 0, 1, 1382, 0, 0, 0, 1, 1385, 0, 0, 0, 1, 1389, 0, 0, 0, 1, 1384, 0, 0, 0, 3, 244, 122, 1390, 0, 5, 1390, 61, 0, 0, 1, 1387, 0, 0, 0, 1, 1388, 0, 0, 0, 1, 1391, 0, 0, 0, 3, 78, 39, 1392, 0, 5, 1393, 94, 0, 0, 259, 196, 98, 1394, 0, 1, 191, 0, 0, 0, 3, 196, 98, 1400, 0, 5, 1397, 86, 0, 0, 3, 196, 98, 1399, 0, 1, 1396, 0, 0, 0, 1, 1402, 0, 0, 0, 1, 1398, 0, 0, 0, 1, 1401, 0, 0, 0, 1, 193, 0, 0, 0, 1, 1400, 0, 0, 0, 3, 162, 81, 1407, 0, 5, 1407, 53, 0, 0, 5, 1407, 50, 0, 0, 1, 1403, 0, 0, 0, 1, 1404, 0, 0, 0, 1, 1405, 0, 0, 0, 1, 1408, 0, 0, 0, 259, 254, 127, 1409, 0, 1, 195, 0, 0, 0, 6, 1411, 98, 4294967295, 0, 3, 210, 105, 1454, 0, 3, 194, 97, 1454, 0, 3, 244, 122, 1414, 0, 5, 1420, 123, 0, 0, 3, 248, 124, 1417, 0, 1, 1415, 0, 0, 0, 1, 1417, 0, 0, 0, 1, 1418, 0, 0, 0, 3, 162, 81, 1421, 0, 5, 1421, 33, 0, 0, 1, 1416, 0, 0, 0, 1, 1419, 0, 0, 0, 1, 1454, 0, 0, 0, 3, 84, 42, 1423, 0, 5, 1425, 123, 0, 0, 3, 248, 124, 1426, 0, 1, 1424, 0, 0, 0, 1, 1426, 0, 0, 0, 1, 1427, 0, 0, 0, 5, 1428, 33, 0, 0, 1, 1454, 0, 0, 0, 3, 212, 106, 1454, 0, 7, 1431, 6, 0, 0, 3, 196, 98, 1454, 17, 5, 1436, 79, 0, 0, 3, 112, 56, 1435, 0, 1, 1433, 0, 0, 0, 1, 1438, 0, 0, 0, 1, 1434, 0, 0, 0, 1, 1437, 0, 0, 0, 1, 1439, 0, 0, 0, 1, 1436, 0, 0, 0, 3, 244, 122, 1444, 0, 5, 1441, 107, 0, 0, 3, 244, 122, 1443, 0, 1, 1440, 0, 0, 0, 1, 1446, 0, 0, 0, 1, 1442, 0, 0, 0, 1, 1445, 0, 0, 0, 1, 1447, 0, 0, 0, 1, 1444, 0, 0, 0, 5, 1448, 80, 0, 0, 3, 196, 98, 1449, 16, 1, 1454, 0, 0, 0, 5, 1451, 33, 0, 0, 3, 224, 112, 1454, 0, 3, 204, 102, 1454, 0, 1, 1410, 0, 0, 0, 1, 1412, 0, 0, 0, 1, 1413, 0, 0, 0, 1, 1422, 0, 0, 0, 1, 1429, 0, 0, 0, 1, 1430, 0, 0, 0, 1, 1432, 0, 0, 0, 1, 1450, 0, 0, 0, 1, 1452, 0, 0, 0, 1, 1538, 0, 0, 0, 10, 1456, 25, 0, 0, 5, 1457, 83, 0, 0, 3, 196, 98, 1458, 0, 5, 1459, 84, 0, 0, 1, 1537, 0, 0, 0, 10, 1461, 24, 0, 0, 5, 1473, 87, 0, 0, 3, 162, 81, 1474, 0, 3, 194, 97, 1474, 0, 5, 1474, 53, 0, 0, 5, 1467, 33, 0, 0, 3, 240, 120, 1468, 0, 1, 1466, 0, 0, 0, 1, 1468, 0, 0, 0, 1, 1469, 0, 0, 0, 3, 228, 114, 1474, 0, 5, 1471, 50, 0, 0, 3, 250, 125, 1474, 0, 3, 234, 117, 1474, 0, 1, 1462, 0, 0, 0, 1, 1463, 0, 0, 0, 1, 1464, 0, 0, 0, 1, 1465, 0, 0, 0, 1, 1470, 0, 0, 0, 1, 1472, 0, 0, 0, 1, 1537, 0, 0, 0, 10, 1476, 22, 0, 0, 5, 1478, 123, 0, 0, 3, 248, 124, 1479, 0, 1, 1477, 0, 0, 0, 1, 1479, 0, 0, 0, 1, 1480, 0, 0, 0, 3, 162, 81, 1537, 0, 10, 1482, 18, 0, 0, 7, 1537, 7, 0, 0, 10, 1484, 14, 0, 0, 7, 1485, 8, 0, 0, 3, 196, 98, 1537, 15, 10, 1487, 13, 0, 0, 7, 1488, 9, 0, 0, 3, 196, 98, 1537, 14, 10, 1497, 12, 0, 0, 5, 1491, 90, 0, 0, 5, 1498, 90, 0, 0, 5, 1493, 89, 0, 0, 5, 1494, 89, 0, 0, 5, 1498, 89, 0, 0, 5, 1496, 89, 0, 0, 5, 1498, 89, 0, 0, 1, 1490, 0, 0, 0, 1, 1492, 0, 0, 0, 1, 1495, 0, 0, 0, 1, 1499, 0, 0, 0, 3, 196, 98, 1537, 13, 10, 1501, 11, 0, 0, 7, 1502, 10, 0, 0, 3, 196, 98, 1537, 12, 10, 1504, 10, 0, 0, 5, 1507, 27, 0, 0, 3, 244, 122, 1508, 0, 3, 198, 99, 1508, 0, 1, 1505, 0, 0, 0, 1, 1506, 0, 0, 0, 1, 1537, 0, 0, 0, 10, 1510, 9, 0, 0, 7, 1511, 11, 0, 0, 3, 196, 98, 1537, 10, 10, 1513, 8, 0, 0, 5, 1514, 107, 0, 0, 3, 196, 98, 1537, 9, 10, 1516, 7, 0, 0, 5, 1517, 109, 0, 0, 3, 196, 98, 1537, 8, 10, 1519, 6, 0, 0, 5, 1520, 108, 0, 0, 3, 196, 98, 1537, 7, 10, 1522, 5, 0, 0, 5, 1523, 99, 0, 0, 3, 196, 98, 1537, 6, 10, 1525, 4, 0, 0, 5, 1526, 100, 0, 0, 3, 196, 98, 1537, 5, 10, 1528, 3, 0, 0, 5, 1529, 93, 0, 0, 3, 196, 98, 1530, 0, 5, 1531, 94, 0, 0, 3, 196, 98, 1532, 3, 1, 1537, 0, 0, 0, 10, 1534, 2, 0, 0, 7, 1535, 12, 0, 0, 3, 196, 98, 1537, 2, 1, 1455, 0, 0, 0, 1, 1460, 0, 0, 0, 1, 1475, 0, 0, 0, 1, 1481, 0, 0, 0, 1, 1483, 0, 0, 0, 1, 1486, 0, 0, 0, 1, 1489, 0, 0, 0, 1, 1500, 0, 0, 0, 1, 1503, 0, 0, 0, 1, 1509, 0, 0, 0, 1, 1512, 0, 0, 0, 1, 1515, 0, 0, 0, 1, 1518, 0, 0, 0, 1, 1521, 0, 0, 0, 1, 1524, 0, 0, 0, 1, 1527, 0, 0, 0, 1, 1533, 0, 0, 0, 1, 1540, 0, 0, 0, 1, 1536, 0, 0, 0, 1, 1539, 0, 0, 0, 1, 197, 0, 0, 0, 1, 1538, 0, 0, 0, 3, 14, 7, 1543, 0, 1, 1541, 0, 0, 0, 1, 1546, 0, 0, 0, 1, 1542, 0, 0, 0, 1, 1545, 0, 0, 0, 1, 1547, 0, 0, 0, 1, 1544, 0, 0, 0, 3, 244, 122, 1551, 0, 3, 112, 56, 1550, 0, 1, 1548, 0, 0, 0, 1, 1553, 0, 0, 0, 1, 1549, 0, 0, 0, 1, 1552, 0, 0, 0, 1, 1554, 0, 0, 0, 1, 1551, 0, 0, 0, 259, 74, 37, 1555, 0, 1, 1564, 0, 0, 0, 3, 244, 122, 1557, 0, 5, 1559, 79, 0, 0, 3, 200, 100, 1560, 0, 1, 1558, 0, 0, 0, 1, 1560, 0, 0, 0, 1, 1561, 0, 0, 0, 5, 1562, 80, 0, 0, 1, 1564, 0, 0, 0, 1, 1544, 0, 0, 0, 1, 1556, 0, 0, 0, 1, 199, 0, 0, 0, 3, 202, 101, 1570, 0, 5, 1567, 86, 0, 0, 3, 202, 101, 1569, 0, 1, 1566, 0, 0, 0, 1, 1572, 0, 0, 0, 1, 1568, 0, 0, 0, 1, 1571, 0, 0, 0, 1, 201, 0, 0, 0, 1, 1570, 0, 0, 0, 259, 198, 99, 1574, 0, 1, 203, 0, 0, 0, 3, 206, 103, 1576, 0, 5, 1577, 122, 0, 0, 259, 208, 104, 1578, 0, 1, 205, 0, 0, 0, 259, 162, 81, 1602, 0, 5, 1582, 79, 0, 0, 3, 96, 48, 1583, 0, 1, 1581, 0, 0, 0, 1, 1583, 0, 0, 0, 1, 1584, 0, 0, 0, 5, 1602, 80, 0, 0, 5, 1586, 79, 0, 0, 3, 162, 81, 1591, 0, 5, 1588, 86, 0, 0, 3, 162, 81, 1590, 0, 1, 1587, 0, 0, 0, 1, 1593, 0, 0, 0, 1, 1589, 0, 0, 0, 1, 1592, 0, 0, 0, 1, 1594, 0, 0, 0, 1, 1591, 0, 0, 0, 5, 1595, 80, 0, 0, 1, 1602, 0, 0, 0, 5, 1598, 79, 0, 0, 3, 100, 50, 1599, 0, 1, 1597, 0, 0, 0, 1, 1599, 0, 0, 0, 1, 1600, 0, 0, 0, 5, 1602, 80, 0, 0, 1, 1579, 0, 0, 0, 1, 1580, 0, 0, 0, 1, 1585, 0, 0, 0, 1, 1596, 0, 0, 0, 1, 207, 0, 0, 0, 259, 196, 98, 1606, 0, 259, 156, 78, 1606, 0, 1, 1603, 0, 0, 0, 1, 1604, 0, 0, 0, 1, 209, 0, 0, 0, 5, 1608, 79, 0, 0, 3, 196, 98, 1609, 0, 5, 1610, 80, 0, 0, 1, 1626, 0, 0, 0, 5, 1626, 53, 0, 0, 5, 1626, 50, 0, 0, 259, 106, 53, 1626, 0, 259, 162, 81, 1626, 0, 3, 46, 23, 1616, 0, 5, 1617, 87, 0, 0, 5, 1618, 9, 0, 0, 1, 1626, 0, 0, 0, 3, 240, 120, 1623, 0, 259, 252, 126, 1624, 0, 5, 1622, 53, 0, 0, 259, 254, 127, 1624, 0, 1, 1620, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 1626, 0, 0, 0, 1, 1607, 0, 0, 0, 1, 1611, 0, 0, 0, 1, 1612, 0, 0, 0, 1, 1613, 0, 0, 0, 1, 1614, 0, 0, 0, 1, 1615, 0, 0, 0, 1, 1619, 0, 0, 0, 1, 211, 0, 0, 0, 5, 1628, 51, 0, 0, 5, 1629, 79, 0, 0, 3, 196, 98, 1630, 0, 5, 1631, 80, 0, 0, 5, 1635, 81, 0, 0, 3, 214, 107, 1634, 0, 1, 1632, 0, 0, 0, 1, 1637, 0, 0, 0, 1, 1633, 0, 0, 0, 1, 1636, 0, 0, 0, 1, 1638, 0, 0, 0, 1, 1635, 0, 0, 0, 5, 1639, 82, 0, 0, 1, 213, 0, 0, 0, 5, 1658, 6, 0, 0, 3, 192, 96, 1659, 0, 5, 1645, 78, 0, 0, 5, 1644, 86, 0, 0, 5, 1646, 12, 0, 0, 1, 1643, 0, 0, 0, 1, 1646, 0, 0, 0, 1, 1659, 0, 0, 0, 3, 218, 109, 1652, 0, 5, 1649, 86, 0, 0, 3, 218, 109, 1651, 0, 1, 1648, 0, 0, 0, 1, 1654, 0, 0, 0, 1, 1650, 0, 0, 0, 1, 1653, 0, 0, 0, 1, 1656, 0, 0, 0, 1, 1652, 0, 0, 0, 3, 216, 108, 1657, 0, 1, 1655, 0, 0, 0, 1, 1657, 0, 0, 0, 1, 1659, 0, 0, 0, 1, 1641, 0, 0, 0, 1, 1642, 0, 0, 0, 1, 1647, 0, 0, 0, 1, 1660, 0, 0, 0, 7, 1661, 13, 0, 0, 259, 220, 110, 1666, 0, 5, 1663, 12, 0, 0, 7, 1664, 13, 0, 0, 259, 220, 110, 1666, 0, 1, 1640, 0, 0, 0, 1, 1662, 0, 0, 0, 1, 215, 0, 0, 0, 5, 1668, 64, 0, 0, 259, 196, 98, 1669, 0, 1, 217, 0, 0, 0, 259, 198, 99, 1671, 0, 1, 219, 0, 0, 0, 259, 156, 78, 1680, 0, 3, 158, 79, 1675, 0, 1, 1673, 0, 0, 0, 1, 1678, 0, 0, 0, 1, 1674, 0, 0, 0, 1, 1677, 0, 0, 0, 1, 1680, 0, 0, 0, 1, 1676, 0, 0, 0, 1, 1672, 0, 0, 0, 1, 1676, 0, 0, 0, 1, 221, 0, 0, 0, 259, 84, 42, 1682, 0, 1, 223, 0, 0, 0, 3, 240, 120, 1685, 0, 1, 1683, 0, 0, 0, 1, 1685, 0, 0, 0, 1, 1686, 0, 0, 0, 3, 226, 113, 1687, 0, 259, 232, 116, 1688, 0, 1, 1693, 0, 0, 0, 3, 226, 113, 1690, 0, 259, 230, 115, 1691, 0, 1, 1693, 0, 0, 0, 1, 1684, 0, 0, 0, 1, 1689, 0, 0, 0, 1, 225, 0, 0, 0, 3, 162, 81, 1696, 0, 3, 236, 118, 1697, 0, 1, 1695, 0, 0, 0, 1, 1697, 0, 0, 0, 1, 1705, 0, 0, 0, 5, 1699, 87, 0, 0, 3, 162, 81, 1701, 0, 3, 236, 118, 1702, 0, 1, 1700, 0, 0, 0, 1, 1702, 0, 0, 0, 1, 1704, 0, 0, 0, 1, 1698, 0, 0, 0, 1, 1707, 0, 0, 0, 1, 1703, 0, 0, 0, 1, 1706, 0, 0, 0, 1, 1710, 0, 0, 0, 1, 1705, 0, 0, 0, 259, 246, 123, 1710, 0, 1, 1694, 0, 0, 0, 1, 1708, 0, 0, 0, 1, 227, 0, 0, 0, 3, 162, 81, 1713, 0, 3, 238, 119, 1714, 0, 1, 1712, 0, 0, 0, 1, 1714, 0, 0, 0, 1, 1715, 0, 0, 0, 259, 232, 116, 1716, 0, 1, 229, 0, 0, 0, 5, 1718, 83, 0, 0, 5, 1720, 84, 0, 0, 1, 1717, 0, 0, 0, 1, 1721, 0, 0, 0, 1, 1719, 0, 0, 0, 1, 1722, 0, 0, 0, 1, 1723, 0, 0, 0, 259, 82, 41, 1740, 0, 5, 1725, 83, 0, 0, 3, 196, 98, 1726, 0, 5, 1727, 84, 0, 0, 1, 1729, 0, 0, 0, 1, 1724, 0, 0, 0, 1, 1730, 0, 0, 0, 1, 1728, 0, 0, 0, 1, 1731, 0, 0, 0, 1, 1736, 0, 0, 0, 5, 1733, 83, 0, 0, 5, 1735, 84, 0, 0, 1, 1732, 0, 0, 0, 1, 1738, 0, 0, 0, 1, 1734, 0, 0, 0, 1, 1737, 0, 0, 0, 1, 1740, 0, 0, 0, 1, 1736, 0, 0, 0, 1, 1719, 0, 0, 0, 1, 1728, 0, 0, 0, 1, 231, 0, 0, 0, 3, 254, 127, 1743, 0, 259, 34, 17, 1744, 0, 1, 1742, 0, 0, 0, 1, 1744, 0, 0, 0, 1, 233, 0, 0, 0, 3, 240, 120, 1746, 0, 259, 252, 126, 1747, 0, 1, 235, 0, 0, 0, 5, 1749, 90, 0, 0, 5, 1752, 89, 0, 0, 259, 248, 124, 1752, 0, 1, 1748, 0, 0, 0, 1, 1750, 0, 0, 0, 1, 237, 0, 0, 0, 5, 1754, 90, 0, 0, 5, 1757, 89, 0, 0, 259, 240, 120, 1757, 0, 1, 1753, 0, 0, 0, 1, 1755, 0, 0, 0, 1, 239, 0, 0, 0, 5, 1759, 90, 0, 0, 3, 242, 121, 1760, 0, 5, 1761, 89, 0, 0, 1, 241, 0, 0, 0, 3, 244, 122, 1767, 0, 5, 1764, 86, 0, 0, 3, 244, 122, 1766, 0, 1, 1763, 0, 0, 0, 1, 1769, 0, 0, 0, 1, 1765, 0, 0, 0, 1, 1768, 0, 0, 0, 1, 243, 0, 0, 0, 1, 1767, 0, 0, 0, 3, 112, 56, 1772, 0, 1, 1770, 0, 0, 0, 1, 1775, 0, 0, 0, 1, 1771, 0, 0, 0, 1, 1774, 0, 0, 0, 1, 1778, 0, 0, 0, 1, 1773, 0, 0, 0, 3, 222, 111, 1779, 0, 3, 246, 123, 1779, 0, 1, 1776, 0, 0, 0, 1, 1777, 0, 0, 0, 1, 1790, 0, 0, 0, 3, 112, 56, 1782, 0, 1, 1780, 0, 0, 0, 1, 1785, 0, 0, 0, 1, 1781, 0, 0, 0, 1, 1784, 0, 0, 0, 1, 1786, 0, 0, 0, 1, 1783, 0, 0, 0, 5, 1787, 83, 0, 0, 5, 1789, 84, 0, 0, 1, 1783, 0, 0, 0, 1, 1792, 0, 0, 0, 1, 1788, 0, 0, 0, 1, 1791, 0, 0, 0, 1, 245, 0, 0, 0, 1, 1790, 0, 0, 0, 7, 1794, 14, 0, 0, 1, 247, 0, 0, 0, 5, 1796, 90, 0, 0, 3, 88, 44, 1801, 0, 5, 1798, 86, 0, 0, 3, 88, 44, 1800, 0, 1, 1797, 0, 0, 0, 1, 1803, 0, 0, 0, 1, 1799, 0, 0, 0, 1, 1802, 0, 0, 0, 1, 1804, 0, 0, 0, 1, 1801, 0, 0, 0, 5, 1805, 89, 0, 0, 1, 249, 0, 0, 0, 259, 254, 127, 1816, 0, 5, 1809, 87, 0, 0, 3, 248, 124, 1810, 0, 1, 1808, 0, 0, 0, 1, 1810, 0, 0, 0, 1, 1811, 0, 0, 0, 3, 162, 81, 1813, 0, 259, 254, 127, 1814, 0, 1, 1812, 0, 0, 0, 1, 1814, 0, 0, 0, 1, 1816, 0, 0, 0, 1, 1806, 0, 0, 0, 1, 1807, 0, 0, 0, 1, 251, 0, 0, 0, 5, 1818, 50, 0, 0, 259, 250, 125, 1823, 0, 3, 162, 81, 1820, 0, 259, 254, 127, 1821, 0, 1, 1823, 0, 0, 0, 1, 1817, 0, 0, 0, 1, 1819, 0, 0, 0, 1, 253, 0, 0, 0, 5, 1826, 79, 0, 0, 3, 192, 96, 1827, 0, 1, 1825, 0, 0, 0, 1, 1827, 0, 0, 0, 1, 1828, 0, 0, 0, 5, 1829, 80, 0, 0, 1, 255, 0, 0, 0, 0, 2, 1, 0, 2, 2, 1, 1, 2, 2, 3, 1, 1, 4, 2, 4, 2, 1, 6, 2, 6, 13, 2, 8, 3, 19, 11, 2, 11, 3, 30, 2, 1, 14, 2, 32, 1, 1, 16, 2, 33, 2, 1, 18, 2, 35, 1, 1, 20, 2, 36, 2, 1, 22, 2, 38, 2, 1, 24, 2, 40, 2, 1, 26, 2, 42, 2, 1, 28, 2, 44, 8, 1, 30, 2, 18, 18, 50, 50, 68, 71, 72, 73, 48, 48, 58, 58, 17, 17, 31, 31, 35, 36, 38, 38, 41, 41, 43, 44, 46, 46, 56, 56, 58, 58, 60, 61, 64, 64, 66, 67, 129, 129, 17, 17, 31, 31, 35, 36, 41, 41, 44, 44, 46, 46, 56, 56, 58, 58, 60, 60, 66, 66, 129, 129, 91, 92, 101, 104, 101, 102, 105, 106, 110, 110, 103, 104, 89, 90, 96, 97, 95, 95, 98, 98, 88, 88, 111, 121, 94, 94, 122, 122, 3, 3, 5, 5, 8, 8, 14, 14, 21, 21, 28, 28, 30, 30, 47, 47, 262144, 262144, 0, 0, 0, 0, 240, 0, 0, 0, 768, 0, 0, 67174400, 0, 0, 2147614720, 889215576, 13, 0, 2, 0, 2147614720, 352342552, 4, 0, 2, 0, 0, 0, 402653184, 480, 0, 0, 0, 96, 0, 0, 0, 17920, 0, 0, 0, 384, 0, 0, 100663296, 3, 0, 0, 2147483648, 4, 0, 0, 16777216, 67076096, 0, 0, 1073741824, 67108864, 1344291112, 32768, 0, 0, 257, 261, 263, 268, 270, 277, 282, 290, 299, 304, 311, 319, 326, 338, 342, 347, 351, 355, 359, 369, 377, 385, 389, 396, 403, 407, 410, 413, 422, 428, 433, 436, 442, 448, 452, 456, 464, 473, 480, 486, 490, 502, 511, 516, 522, 526, 538, 545, 558, 563, 573, 581, 591, 600, 611, 616, 625, 635, 640, 649, 655, 662, 667, 675, 679, 681, 690, 693, 697, 701, 707, 712, 716, 724, 731, 737, 739, 746, 752, 758, 761, 771, 781, 787, 794, 798, 807, 813, 824, 834, 844, 852, 855, 865, 875, 878, 881, 884, 889, 897, 900, 903, 916, 924, 929, 937, 941, 945, 949, 953, 955, 959, 965, 975, 979, 987, 996, 1010, 1013, 1025, 1028, 1044, 1049, 1056, 1061, 1067, 1076, 1084, 1091, 1095, 1102, 1104, 1113, 1123, 1128, 1139, 1148, 1155, 1162, 1173, 1200, 1203, 1206, 1214, 1218, 1228, 1234, 1247, 1256, 1261, 1274, 1280, 1287, 1300, 1309, 1318, 1324, 1332, 1338, 1345, 1350, 1358, 1361, 1365, 1369, 1373, 1375, 1379, 1384, 1389, 1400, 1406, 1416, 1420, 1425, 1436, 1444, 1453, 1467, 1473, 1478, 1497, 1507, 1536, 1538, 1544, 1551, 1559, 1563, 1570, 1582, 1591, 1598, 1601, 1605, 1623, 1625, 1635, 1645, 1652, 1656, 1658, 1665, 1676, 1679, 1684, 1692, 1696, 1701, 1705, 1709, 1713, 1721, 1730, 1736, 1739, 1743, 1751, 1756, 1767, 1773, 1778, 1783, 1790, 1801, 1809, 1813, 1815, 1822, 1826, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255]; -static ATN_CELL: OnceLock = OnceLock::new(); - -/// Validates and caches the packed grammar ATN for all parser instances. -fn atn() -> &'static ParserAtn { - ATN_CELL.get_or_init(|| { - ParserAtn::from_static(PARSER_ATN_DATA) - .unwrap_or_else(|error| panic!("generated parser ATN is incompatible with this runtime: {error}")) - }) -} - -/// Borrows the validated packed parser ATN embedded in this module. -pub fn parser_atn() -> &'static ParserAtn { - atn() -} - -antlr4_runtime::__antlr4_rust_parser_entry_points! { - parser: JavaParser, - output: JavaParserParseOutput, - validated_tree: JavaValidatedTree, - validation_error: JavaValidationError, - validate_tree: validate_tree_structure, -} - -/// Generated parser. Each grammar rule is exposed as a public method. -/// -/// Pick an entry-rule method that matches the grammar's intended -/// top-level construct for the input being parsed. The generator can -/// infer entry candidates from call paths that reach explicit `EOF` -/// matches, from parser rules that no other rule calls, and from -/// configured entry rules. It cannot infer the semantic choice -/// between multiple candidates. -/// -/// Likely parser entry-rule methods: -/// - `compilation_unit()` -/// -/// All parser rule methods: -/// - `compilation_unit()` -/// - `modular_compulation_unit()` -/// - `package_declaration()` -/// - `import_declaration()` -/// - `type_declaration()` -/// - `modifier()` -/// - `class_or_interface_modifier()` -/// - `variable_modifier()` -/// - `class_declaration()` -/// - `type_parameters()` -/// - `type_parameter()` -/// - `type_bound()` -/// - `enum_declaration()` -/// - `enum_constants()` -/// - `enum_constant()` -/// - `enum_body_declarations()` -/// - `interface_declaration()` -/// - `class_body()` -/// - `interface_body()` -/// - `class_body_declaration()` -/// - `member_declaration()` -/// - `method_declaration()` -/// - `method_body()` -/// - `type_type_or_void()` -/// - `generic_method_declaration()` -/// - `generic_constructor_declaration()` -/// - `constructor_declaration()` -/// - `compact_constructor_declaration()` -/// - `field_declaration()` -/// - `interface_body_declaration()` -/// - `interface_member_declaration()` -/// - `const_declaration()` -/// - `constant_declarator()` -/// - `interface_method_declaration()` -/// - `interface_method_modifier()` -/// - `generic_interface_method_declaration()` -/// - `interface_common_body_declaration()` -/// - `variable_declarators()` -/// - `variable_declarator()` -/// - `variable_declarator_id()` -/// - `variable_initializer()` -/// - `array_initializer()` -/// - `class_type()` -/// - `package_name()` -/// - `type_argument()` -/// - `qualified_name_list()` -/// - `formal_parameters()` -/// - `receiver_parameter()` -/// - `formal_parameter_list()` -/// - `formal_parameter()` -/// - `lambda_lvti_list()` -/// - `lambda_lvti_parameter()` -/// - `qualified_name()` -/// - `literal()` -/// - `integer_literal()` -/// - `float_literal()` -/// - `annotation()` -/// - `annotation_field_values()` -/// - `annotation_field_value()` -/// - `annotation_value()` -/// - `element_value()` -/// - `element_value_array_initializer()` -/// - `annotation_type_declaration()` -/// - `annotation_type_body()` -/// - `annotation_type_element_declaration()` -/// - `annotation_type_element_rest()` -/// - `annotation_method_or_constant_rest()` -/// - `annotation_method_rest()` -/// - `annotation_constant_rest()` -/// - `default_value()` -/// - `module_declaration()` -/// - `module_directive()` -/// - `requires_modifier()` -/// - `record_declaration()` -/// - `record_header()` -/// - `record_component_list()` -/// - `record_component()` -/// - `record_body()` -/// - `block()` -/// - `block_statement()` -/// - `local_variable_declaration()` -/// - `identifier()` -/// - `type_identifier()` -/// - `local_type_declaration()` -/// - `statement()` -/// - `catch_clause()` -/// - `catch_type()` -/// - `finally_block()` -/// - `resource_specification()` -/// - `resources()` -/// - `resource()` -/// - `switch_block_statement_group()` -/// - `switch_label()` -/// - `for_control()` -/// - `for_init()` -/// - `enhanced_for_control()` -/// - `expression_list()` -/// - `method_call()` -/// - `expression()` -/// - `pattern()` -/// - `component_pattern_list()` -/// - `component_pattern()` -/// - `lambda_expression()` -/// - `lambda_parameters()` -/// - `lambda_body()` -/// - `primary()` -/// - `switch_expression()` -/// - `switch_labeled_rule()` -/// - `guard()` -/// - `case_pattern()` -/// - `switch_rule_outcome()` -/// - `class_or_interface_type()` -/// - `creator()` -/// - `created_name()` -/// - `inner_creator()` -/// - `array_creator_rest()` -/// - `class_creator_rest()` -/// - `explicit_generic_invocation()` -/// - `type_arguments_or_diamond()` -/// - `non_wildcard_type_arguments_or_diamond()` -/// - `non_wildcard_type_arguments()` -/// - `type_list()` -/// - `type_type()` -/// - `primitive_type()` -/// - `type_arguments()` -/// - `super_suffix()` -/// - `explicit_generic_invocation_suffix()` -/// - `arguments()` -#[derive(Debug)] -pub struct JavaParser -where - L: TokenSource, - H: antlr4_runtime::SemanticHooks, -{ - base: BaseParser, - simulator: Option>, - generated_only: bool, - adaptive_atn: antlr4_runtime::generated::AdaptiveAtnRetryState<2>, -} - -impl JavaParser -where - L: TokenSource, -{ - pub fn new(input: CommonTokenStream) -> Self { - Self::with_hooks(input, antlr4_runtime::NoSemanticHooks) - } -} - -impl JavaParser -where - L: TokenSource, - H: antlr4_runtime::SemanticHooks, -{ - pub fn with_hooks(input: CommonTokenStream, hooks: H) -> Self { - let grammar_metadata = metadata(); - let data = grammar_metadata.recognizer_data(); - let mut base = BaseParser::with_semantic_hooks(input, data, hooks); - base.set_unknown_predicate_policy(antlr4_runtime::UnknownSemanticPolicy::Error); - Self { - base, - simulator: None, - generated_only: std::env::var_os("ANTLR4_RUST_GENERATED_ONLY").is_some(), - adaptive_atn: antlr4_runtime::generated::AdaptiveAtnRetryState::new(), - } - } - - const __GENERATED_RULE_BODIES: [Option>; 128] = [ - Some(Self::parse_generated_rule_0), - Some(Self::parse_generated_rule_1), - Some(Self::parse_generated_rule_2), - Some(Self::parse_generated_rule_3), - Some(Self::parse_generated_rule_4), - Some(Self::parse_generated_rule_5), - Some(Self::parse_generated_rule_6), - Some(Self::parse_generated_rule_7), - Some(Self::parse_generated_rule_8), - Some(Self::parse_generated_rule_9), - Some(Self::parse_generated_rule_10), - Some(Self::parse_generated_rule_11), - Some(Self::parse_generated_rule_12), - Some(Self::parse_generated_rule_13), - Some(Self::parse_generated_rule_14), - Some(Self::parse_generated_rule_15), - Some(Self::parse_generated_rule_16), - Some(Self::parse_generated_rule_17), - Some(Self::parse_generated_rule_18), - Some(Self::parse_generated_rule_19), - Some(Self::parse_generated_rule_20), - Some(Self::parse_generated_rule_21), - Some(Self::parse_generated_rule_22), - Some(Self::parse_generated_rule_23), - Some(Self::parse_generated_rule_24), - Some(Self::parse_generated_rule_25), - Some(Self::parse_generated_rule_26), - Some(Self::parse_generated_rule_27), - Some(Self::parse_generated_rule_28), - Some(Self::parse_generated_rule_29), - Some(Self::parse_generated_rule_30), - Some(Self::parse_generated_rule_31), - Some(Self::parse_generated_rule_32), - Some(Self::parse_generated_rule_33), - Some(Self::parse_generated_rule_34), - Some(Self::parse_generated_rule_35), - Some(Self::parse_generated_rule_36), - Some(Self::parse_generated_rule_37), - Some(Self::parse_generated_rule_38), - Some(Self::parse_generated_rule_39), - Some(Self::parse_generated_rule_40), - Some(Self::parse_generated_rule_41), - Some(Self::parse_generated_rule_42), - Some(Self::parse_generated_rule_43), - Some(Self::parse_generated_rule_44), - Some(Self::parse_generated_rule_45), - Some(Self::parse_generated_rule_46), - Some(Self::parse_generated_rule_47), - Some(Self::parse_generated_rule_48), - Some(Self::parse_generated_rule_49), - Some(Self::parse_generated_rule_50), - Some(Self::parse_generated_rule_51), - Some(Self::parse_generated_rule_52), - Some(Self::parse_generated_rule_53), - Some(Self::parse_generated_rule_54), - Some(Self::parse_generated_rule_55), - Some(Self::parse_generated_rule_56), - Some(Self::parse_generated_rule_57), - Some(Self::parse_generated_rule_58), - Some(Self::parse_generated_rule_59), - Some(Self::parse_generated_rule_60), - Some(Self::parse_generated_rule_61), - Some(Self::parse_generated_rule_62), - Some(Self::parse_generated_rule_63), - Some(Self::parse_generated_rule_64), - Some(Self::parse_generated_rule_65), - Some(Self::parse_generated_rule_66), - Some(Self::parse_generated_rule_67), - Some(Self::parse_generated_rule_68), - Some(Self::parse_generated_rule_69), - Some(Self::parse_generated_rule_70), - Some(Self::parse_generated_rule_71), - Some(Self::parse_generated_rule_72), - Some(Self::parse_generated_rule_73), - Some(Self::parse_generated_rule_74), - Some(Self::parse_generated_rule_75), - Some(Self::parse_generated_rule_76), - Some(Self::parse_generated_rule_77), - Some(Self::parse_generated_rule_78), - Some(Self::parse_generated_rule_79), - Some(Self::parse_generated_rule_80), - Some(Self::parse_generated_rule_81), - Some(Self::parse_generated_rule_82), - Some(Self::parse_generated_rule_83), - Some(Self::parse_generated_rule_84), - Some(Self::parse_generated_rule_85), - Some(Self::parse_generated_rule_86), - Some(Self::parse_generated_rule_87), - Some(Self::parse_generated_rule_88), - Some(Self::parse_generated_rule_89), - Some(Self::parse_generated_rule_90), - Some(Self::parse_generated_rule_91), - Some(Self::parse_generated_rule_92), - Some(Self::parse_generated_rule_93), - Some(Self::parse_generated_rule_94), - Some(Self::parse_generated_rule_95), - Some(Self::parse_generated_rule_96), - Some(Self::parse_generated_rule_97), - Some(Self::parse_generated_rule_98_precedence), - Some(Self::parse_generated_rule_99), - Some(Self::parse_generated_rule_100), - Some(Self::parse_generated_rule_101), - Some(Self::parse_generated_rule_102), - Some(Self::parse_generated_rule_103), - Some(Self::parse_generated_rule_104), - Some(Self::parse_generated_rule_105), - Some(Self::parse_generated_rule_106), - Some(Self::parse_generated_rule_107), - Some(Self::parse_generated_rule_108), - Some(Self::parse_generated_rule_109), - Some(Self::parse_generated_rule_110), - Some(Self::parse_generated_rule_111), - Some(Self::parse_generated_rule_112), - Some(Self::parse_generated_rule_113), - Some(Self::parse_generated_rule_114), - Some(Self::parse_generated_rule_115), - Some(Self::parse_generated_rule_116), - Some(Self::parse_generated_rule_117), - Some(Self::parse_generated_rule_118), - Some(Self::parse_generated_rule_119), - Some(Self::parse_generated_rule_120), - Some(Self::parse_generated_rule_121), - Some(Self::parse_generated_rule_122), - Some(Self::parse_generated_rule_123), - Some(Self::parse_generated_rule_124), - Some(Self::parse_generated_rule_125), - Some(Self::parse_generated_rule_126), - Some(Self::parse_generated_rule_127), - ]; - - #[allow(dead_code)] - #[inline(always)] - fn dispatch_generated_rule(&mut self, rule_index: usize, precedence: i32, allow_fallback: bool) -> Result { - let body = Self::__GENERATED_RULE_BODIES.get(rule_index).copied().flatten().expect("generated rule dispatch target"); - antlr4_runtime::generated::dispatch_generated_rule(self, rule_index, precedence, allow_fallback, body) - } - - #[allow(dead_code)] - fn parse_generated_rule(&mut self, rule_index: usize, precedence: i32, allow_fallback: bool) -> Option> { - let _body = Self::__GENERATED_RULE_BODIES.get(rule_index).copied().flatten()?; - match rule_index { - 84 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() => Some(self.dispatch_generated_rule(84, precedence, allow_fallback)), - 84 if !self.adaptive_atn.preferred_rules[0] => Some(self.parse_generated_rule_84_adaptive_dispatch(precedence, allow_fallback, None)), - 84 => None, - 98 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() => Some(self.dispatch_generated_rule(98, precedence, allow_fallback)), - 98 if !self.adaptive_atn.preferred_rules[1] => Some(self.parse_generated_rule_98_adaptive_dispatch(precedence, allow_fallback, None)), - 98 => None, - _ => Some(self.dispatch_generated_rule(rule_index, precedence, allow_fallback)), - } - } - - #[allow(dead_code)] - fn parse_generated_rule_0(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 0isize, 0, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - -1 | 1 | 9 | 16 | 19 | 29 | 34 | 37 | 39..=40 | 42..=43 | 46 | 48..=49 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 | 35 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 277, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 277) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(5, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(5, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 277, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.sync_into(atn(), 257, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 257) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(0, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(0, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 257, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 256isize, self.dispatch_generated_rule(2, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_263 = false; - loop { - self.base.sync_into(atn(), 263, &mut __ctx, __loop_iter_263, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 263) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(2, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(2, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 263, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_263 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 26 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 261, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 26 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 261, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 259isize, self.dispatch_generated_rule(3, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(85, 262, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_270 = false; - loop { - self.base.sync_into(atn(), 270, &mut __ctx, __loop_iter_270, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 9 | 16 | 19 | 29 | 34 | 39..=40 | 42..=43 | 46 | 48..=49 | 85 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 270, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_270 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 9 | 16 | 19 | 29 | 34 | 39..=40 | 42..=43 | 46 | 48..=49 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 268, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 1 | 9 | 16 | 19 | 29 | 34 | 39..=40 | 42..=43 | 46 | 48..=49 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 268, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 266isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(85, 269, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(-1, 278, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 274isize, self.dispatch_generated_rule(1, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(-1, 276, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_1(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 2isize, 1, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_282 = false; - loop { - self.base.sync_into(atn(), 282, &mut __ctx, __loop_iter_282, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 26 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 | 35 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 282, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_282 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 279isize, self.dispatch_generated_rule(3, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 285isize, self.dispatch_generated_rule(70, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_2(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 4isize, 2, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_290 = false; - loop { - self.base.sync_into(atn(), 290, &mut __ctx, __loop_iter_290, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 37 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 290, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_290 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 287isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(37, 294, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 294isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 296, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_3(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 6isize, 3, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(26, 299, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 299, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 48 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 299, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(48, 300, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 301isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 304, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 87 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 304, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(87, 303, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(105, 305, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 307, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_4(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 8isize, 4, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_311 = false; - loop { - self.base.sync_into(atn(), 311, &mut __ctx, __loop_iter_311, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 311) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(10, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(10, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 311, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_311 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 308isize, self.dispatch_generated_rule(6, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 16 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 43 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 319, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 16 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 43 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 319, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 314isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 315isize, self.dispatch_generated_rule(12, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 316isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 317isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 318isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_5(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 10isize, 5, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 19 | 34 | 39..=40 | 42 | 46 | 48..=49 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 32 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 52 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 57 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 326, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 1 | 19 | 34 | 39..=40 | 42 | 46 | 48..=49 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 32 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 52 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 57 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 326, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 321isize, self.dispatch_generated_rule(6, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(32, 327, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(52, 327, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(57, 327, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - self.base.match_token_into(63, 327, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_6(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 12isize, 6, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 42 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 40 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 39 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 48 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 49 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 46 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 34 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 338, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 42 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 40 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 39 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 48 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 49 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 46 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 34 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 338, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 328isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(42, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(40, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(39, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - self.base.match_token_into(48, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - self.base.match_token_into(1, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - self.base.match_token_into(19, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 8 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(8); - } - self.base.match_token_into(49, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 9 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(9); - } - self.base.match_token_into(46, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(10); - } - self.base.match_token_into(34, 339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_7(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 14isize, 7, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 342, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 19 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 342, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(19, 343, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 341isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_8(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 16isize, 8, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 345, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 345isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 347, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 | 25 | 38 | 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 347, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 346isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 351, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 18 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 25 | 38 | 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 351, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(18, 350, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 350isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 355, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 25 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 38 | 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 355, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(25, 354, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 354isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 359, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 38 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 359, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(38, 358, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 358isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 361isize, self.dispatch_generated_rule(17, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_9(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 18isize, 9, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(90, 364, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 364isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_369 = false; - loop { - self.base.sync_into(atn(), 369, &mut __ctx, __loop_iter_369, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 89 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 369, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_369 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 366, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 366isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(89, 373, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_10(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 20isize, 10, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_377 = false; - loop { - self.base.sync_into(atn(), 377, &mut __ctx, __loop_iter_377, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 377, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_377 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 374isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 380isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 389, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 18 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 86 | 89 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 389, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(18, 385, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_385 = false; - loop { - self.base.sync_into(atn(), 385, &mut __ctx, __loop_iter_385, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 385) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(21, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(21, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 385, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_385 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 382isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 388isize, self.dispatch_generated_rule(11, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_11(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 22isize, 11, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 391isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_396 = false; - loop { - self.base.sync_into(atn(), 396, &mut __ctx, __loop_iter_396, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 107 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 86 | 89 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 396, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_396 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(107, 393, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 393isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_12(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 24isize, 12, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(16, 400, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 400isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 403, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 25 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 403, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(25, 402, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 402isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(81, 407, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 407, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 | 85..=86 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 407, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 406isize, self.dispatch_generated_rule(13, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 410, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 410, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 411, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 413, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 85 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 413, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 412isize, self.dispatch_generated_rule(15, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(82, 416, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_13(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 26isize, 13, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 417isize, self.dispatch_generated_rule(14, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_422 = false; - loop { - self.base.sync_into(atn(), 422, &mut __ctx, __loop_iter_422, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 422) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(28, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(28, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 422, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_422 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 419, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 419isize, self.dispatch_generated_rule(14, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_14(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 28isize, 14, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_428 = false; - loop { - self.base.sync_into(atn(), 428, &mut __ctx, __loop_iter_428, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 428, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_428 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 425isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 431isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 433, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 79 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81..=82 | 85..=86 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 433, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 432isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 436, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 | 85..=86 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 436, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 435isize, self.dispatch_generated_rule(17, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_15(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 30isize, 15, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(85, 442, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_442 = false; - loop { - self.base.sync_into(atn(), 442, &mut __ctx, __loop_iter_442, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=64 | 66..=67 | 81 | 85 | 90 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 442, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_442 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 439isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_16(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 32isize, 16, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(29, 446, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 446isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 448, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 | 38 | 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 448, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 447isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 452, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 18 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 38 | 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 452, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(18, 451, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 451isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 456, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 38 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 456, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(38, 455, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 455isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 458isize, self.dispatch_generated_rule(18, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_17(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 34isize, 17, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 464, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_464 = false; - loop { - self.base.sync_into(atn(), 464, &mut __ctx, __loop_iter_464, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=64 | 66..=67 | 81 | 85 | 90 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 464, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_464 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 461isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 468, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_18(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 36isize, 18, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 473, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_473 = false; - loop { - self.base.sync_into(atn(), 473, &mut __ctx, __loop_iter_473, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 12 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=64 | 66..=67 | 85 | 90 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 473, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_473 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 470isize, self.dispatch_generated_rule(29, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 477, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_19(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 38isize, 19, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 85 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1 | 3 | 5 | 8..=9 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=47 | 49 | 52 | 56..=58 | 60..=64 | 66..=67 | 90 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 490, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 490) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(40, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(40, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 490, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 491, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.sync_into(atn(), 480, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 48 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 480, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(48, 481, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 482isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - let mut __loop_iter_486 = false; - loop { - self.base.sync_into(atn(), 486, &mut __ctx, __loop_iter_486, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 486) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(39, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(39, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 486, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_486 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 483isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 489isize, self.dispatch_generated_rule(20, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_20(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 40isize, 20, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 62 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 16 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 502, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 502) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(41, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(41, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 502, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 492isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 493isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 494isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 495isize, self.dispatch_generated_rule(28, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 496isize, self.dispatch_generated_rule(26, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 497isize, self.dispatch_generated_rule(25, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 498isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(8); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 499isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(9); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 500isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 10 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(10); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 501isize, self.dispatch_generated_rule(12, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_21(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 42isize, 21, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 504isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 505isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 506isize, self.dispatch_generated_rule(46, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_511 = false; - loop { - self.base.sync_into(atn(), 511, &mut __ctx, __loop_iter_511, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 83 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 55 | 81 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 511, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_511 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(83, 508, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 510, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 516, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 55 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 516, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(55, 515, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 515isize, self.dispatch_generated_rule(45, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 518isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_22(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 44isize, 22, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 522, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 522, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 520isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(85, 523, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_23(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 46isize, 23, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 526, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 526, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 524isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(62, 527, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_24(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 48isize, 24, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 528isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 529isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_25(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 50isize, 25, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 531isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 532isize, self.dispatch_generated_rule(26, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_26(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 52isize, 26, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 534isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 535isize, self.dispatch_generated_rule(46, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 538, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 55 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 538, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(55, 537, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 537isize, self.dispatch_generated_rule(45, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 540isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_27(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 54isize, 27, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_545 = false; - loop { - self.base.sync_into(atn(), 545, &mut __ctx, __loop_iter_545, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 545) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(47, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(47, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 545, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_545 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 542isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 548isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 549isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_28(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 56isize, 28, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 551isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 552isize, self.dispatch_generated_rule(37, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 554, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_29(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 58isize, 29, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 12 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=64 | 66..=67 | 90 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 563, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 12 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=64 | 66..=67 | 90 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 563, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __loop_iter_558 = false; - loop { - self.base.sync_into(atn(), 558, &mut __ctx, __loop_iter_558, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 558) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(48, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(48, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 558, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_558 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 555isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 561isize, self.dispatch_generated_rule(30, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(85, 564, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_30(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 60isize, 30, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 62 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 16 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 573, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 573) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(50, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(50, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 573, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 565isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 566isize, self.dispatch_generated_rule(31, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 567isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 568isize, self.dispatch_generated_rule(35, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 569isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 570isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 571isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(8); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 572isize, self.dispatch_generated_rule(12, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_31(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 62isize, 31, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 575isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 576isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_581 = false; - loop { - self.base.sync_into(atn(), 581, &mut __ctx, __loop_iter_581, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 581, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_581 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 578, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 578isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(85, 585, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_32(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 64isize, 32, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 586isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_591 = false; - loop { - self.base.sync_into(atn(), 591, &mut __ctx, __loop_iter_591, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 83 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 88 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 591, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_591 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(83, 588, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 590, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(88, 595, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 595isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_33(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 66isize, 33, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_600 = false; - loop { - self.base.sync_into(atn(), 600, &mut __ctx, __loop_iter_600, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 600) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(53, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(53, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 600, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_600 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 597isize, self.dispatch_generated_rule(34, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 603isize, self.dispatch_generated_rule(36, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_34(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 68isize, 34, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 42 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 48 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 49 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 611, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 42 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 48 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 49 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 611, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 605isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(42, 612, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(1, 612, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(12, 612, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - self.base.match_token_into(48, 612, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - self.base.match_token_into(49, 612, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_35(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 70isize, 35, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_616 = false; - loop { - self.base.sync_into(atn(), 616, &mut __ctx, __loop_iter_616, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 12 | 42 | 48..=49 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 616, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_616 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 613isize, self.dispatch_generated_rule(34, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 619isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 620isize, self.dispatch_generated_rule(36, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_36(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 72isize, 36, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_625 = false; - loop { - self.base.sync_into(atn(), 625, &mut __ctx, __loop_iter_625, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 625) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(56, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(56, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 625, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_625 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 622isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 628isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 629isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 630isize, self.dispatch_generated_rule(46, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_635 = false; - loop { - self.base.sync_into(atn(), 635, &mut __ctx, __loop_iter_635, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 83 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 55 | 81 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 635, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_635 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(83, 632, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 634, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 640, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 55 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 640, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(55, 639, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 639isize, self.dispatch_generated_rule(45, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 642isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_37(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 74isize, 37, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 644isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_649 = false; - loop { - self.base.sync_into(atn(), 649, &mut __ctx, __loop_iter_649, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 649) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(59, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(59, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 649, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_649 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 646, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 646isize, self.dispatch_generated_rule(38, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_38(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 76isize, 38, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 652isize, self.dispatch_generated_rule(39, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 655, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 655) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(60, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(60, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 655, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(88, 654, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 654isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_39(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 78isize, 39, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 657isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_662 = false; - loop { - self.base.sync_into(atn(), 662, &mut __ctx, __loop_iter_662, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 662) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(61, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(61, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 662, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_662 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(83, 659, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 661, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_40(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 80isize, 40, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 667, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 667, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 665isize, self.dispatch_generated_rule(41, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 666isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(666isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_41(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 82isize, 41, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 681, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 681, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 81 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 681, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 670isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_675 = false; - loop { - self.base.sync_into(atn(), 675, &mut __ctx, __loop_iter_675, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 675) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(63, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(63, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 675, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_675 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 672, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 672isize, self.dispatch_generated_rule(40, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 679, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 679, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 680, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(82, 684, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_42(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 84isize, 42, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 693, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 693) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(67, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(67, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 693, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 685isize, self.dispatch_generated_rule(43, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(87, 690, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_690 = false; - loop { - self.base.sync_into(atn(), 690, &mut __ctx, __loop_iter_690, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 41 | 44 | 46 | 56 | 58 | 60 | 66 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 690, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_690 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 687isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 695isize, self.dispatch_generated_rule(82, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 697, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 697) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(68, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(68, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 697, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 696isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_701 = true; - loop { - self.base.sync_into(atn(), 701, &mut __ctx, __loop_iter_701, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 701) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(69, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(69, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 701, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_701 = true; - self.base.sync_into(atn(), 693, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 693) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(67, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(67, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 693, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 685isize, self.dispatch_generated_rule(43, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(87, 690, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_690 = false; - loop { - self.base.sync_into(atn(), 690, &mut __ctx, __loop_iter_690, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 41 | 44 | 46 | 56 | 58 | 60 | 66 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 690, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_690 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 687isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 695isize, self.dispatch_generated_rule(82, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 697, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 697) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(68, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(68, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 697, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 696isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_716 = false; - loop { - self.base.sync_into(atn(), 716, &mut __ctx, __loop_iter_716, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 716) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(72, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(72, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 716, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_716 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(87, 707, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_707 = false; - loop { - self.base.sync_into(atn(), 707, &mut __ctx, __loop_iter_707, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 41 | 44 | 46 | 56 | 58 | 60 | 66 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 707, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_707 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 704isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 710isize, self.dispatch_generated_rule(82, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 712, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 712) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(71, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(71, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 712, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 711isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_43(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 86isize, 43, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 719isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_724 = false; - loop { - self.base.sync_into(atn(), 724, &mut __ctx, __loop_iter_724, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 724) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(73, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(73, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 724, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_724 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(87, 721, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 721isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_44(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 88isize, 44, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 93 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 739, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 739) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(76, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(76, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 739, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 727isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - let mut __loop_iter_731 = false; - loop { - self.base.sync_into(atn(), 731, &mut __ctx, __loop_iter_731, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 93 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 731, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_731 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 728isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(93, 737, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 737, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 18 | 50 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 86 | 89 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 737, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_set_into(&[(18, 18), (50, 50)], 736, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 736isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_45(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 90isize, 45, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 741isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_746 = false; - loop { - self.base.sync_into(atn(), 746, &mut __ctx, __loop_iter_746, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 746, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_746 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 743, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 743isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_46(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 92isize, 46, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(79, 761, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 761, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 19 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 761, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 752, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 752) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(78, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(78, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 752, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 750isize, self.dispatch_generated_rule(47, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 751isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_758 = false; - loop { - self.base.sync_into(atn(), 758, &mut __ctx, __loop_iter_758, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 758, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_758 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 755, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 755isize, self.dispatch_generated_rule(48, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 764, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_47(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 94isize, 47, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 765isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_771 = false; - loop { - self.base.sync_into(atn(), 771, &mut __ctx, __loop_iter_771, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 771, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_771 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 766isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(87, 768, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(53, 775, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_48(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 96isize, 48, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 776isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_781 = false; - loop { - self.base.sync_into(atn(), 781, &mut __ctx, __loop_iter_781, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 781) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(82, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(82, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 781, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_781 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 778, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 778isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_49(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 98isize, 49, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_787 = false; - loop { - self.base.sync_into(atn(), 787, &mut __ctx, __loop_iter_787, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 787) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(83, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(83, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 787, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_787 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 784isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 790isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 798, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124..=125 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 798, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __loop_iter_794 = false; - loop { - self.base.sync_into(atn(), 794, &mut __ctx, __loop_iter_794, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 794, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_794 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 791isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(125, 799, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 800isize, self.dispatch_generated_rule(39, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_50(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 100isize, 50, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 802isize, self.dispatch_generated_rule(51, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_807 = false; - loop { - self.base.sync_into(atn(), 807, &mut __ctx, __loop_iter_807, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 807, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_807 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 804, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 804isize, self.dispatch_generated_rule(51, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_51(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 102isize, 51, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_813 = false; - loop { - self.base.sync_into(atn(), 813, &mut __ctx, __loop_iter_813, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 61 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 813, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_813 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 810isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(61, 817, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 817isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_52(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 104isize, 52, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 819isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_824 = false; - loop { - self.base.sync_into(atn(), 824, &mut __ctx, __loop_iter_824, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 824) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(88, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(88, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 824, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_824 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(87, 821, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 821isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_53(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 106isize, 53, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 68..=71 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 72..=73 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 76 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 834, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 68..=71 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 72..=73 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 76 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 834, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 827isize, self.dispatch_generated_rule(54, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 828isize, self.dispatch_generated_rule(55, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(75, 835, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(76, 835, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - self.base.match_token_into(74, 835, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - self.base.match_token_into(78, 835, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - self.base.match_token_into(77, 835, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_54(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 108isize, 54, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(68, 71)], 837, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_55(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 110isize, 55, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(72, 73)], 839, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_56(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 112isize, 56, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(124, 841, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 841isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 844, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 79 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1 | 3 | 5 | 8..=9 | 12 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=44 | 46..=49 | 52 | 56..=58 | 60..=64 | 66..=67 | 80 | 82..=83 | 85..=86 | 90 | 93 | 124..=125 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 844, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 843isize, self.dispatch_generated_rule(57, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_57(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 114isize, 57, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(79, 855, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 855, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 855) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(92, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(92, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 855, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 847isize, self.dispatch_generated_rule(58, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_852 = false; - loop { - self.base.sync_into(atn(), 852, &mut __ctx, __loop_iter_852, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 852, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_852 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 849, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 849isize, self.dispatch_generated_rule(58, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 858, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_58(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 116isize, 58, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(93, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - let __prediction = if __prediction.has_semantic_context { - let __semantic_la = self.base.la(1); - let __semantic_alt = match __prediction.alt { - 1 if self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 58, 0, &__ctx, __precedence) => Some(1), - 1 => { - if self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 58, 0, &__ctx, __precedence) { - Some(1) - } else - if true { - Some(2) - } else - { None } - } - _ => Some(__prediction.alt), - }; - match __semantic_alt { - Some(__alt) => antlr4_runtime::ParserAtnPrediction { alt: __alt, ..__prediction }, - None => { - let __error = self.base.no_viable_alternative_error(__decision_start); - return Err(__error); - } - } - } else { - __prediction - }; - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 58, 0, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(58, 0, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(58, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 860isize, self.dispatch_generated_rule(59, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 861isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(88, 863, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 863isize, self.dispatch_generated_rule(59, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_59(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 118isize, 59, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 884, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 884) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(97, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(97, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 884, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 867isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(867isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 868isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(81, 878, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 878, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 81 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 | 86 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 878, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 870isize, self.dispatch_generated_rule(59, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_875 = false; - loop { - self.base.sync_into(atn(), 875, &mut __ctx, __loop_iter_875, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 875) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(94, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(94, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 875, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_875 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 872, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 872isize, self.dispatch_generated_rule(59, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 881, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 881, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 882, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(82, 885, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_60(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 120isize, 60, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 889, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 889) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(98, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(98, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 889, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 886isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(886isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 887isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 888isize, self.dispatch_generated_rule(61, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_61(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 122isize, 61, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 900, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 900, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 81 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 | 86 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 900, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 892isize, self.dispatch_generated_rule(60, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_897 = false; - loop { - self.base.sync_into(atn(), 897, &mut __ctx, __loop_iter_897, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 897) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(99, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(99, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 897, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_897 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 894, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 894isize, self.dispatch_generated_rule(60, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 903, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 903, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 904, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(82, 906, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_62(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 124isize, 62, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(124, 908, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(29, 909, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 909isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 910isize, self.dispatch_generated_rule(63, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_63(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 126isize, 63, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 916, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_916 = false; - loop { - self.base.sync_into(atn(), 916, &mut __ctx, __loop_iter_916, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=61 | 63..=64 | 66..=67 | 85 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 916, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_916 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 913isize, self.dispatch_generated_rule(64, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 920, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_64(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 128isize, 64, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=61 | 63..=64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 929, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=61 | 63..=64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 929, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __loop_iter_924 = false; - loop { - self.base.sync_into(atn(), 924, &mut __ctx, __loop_iter_924, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 924) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(103, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(103, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 924, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_924 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 921isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 927isize, self.dispatch_generated_rule(65, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(85, 930, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_65(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 130isize, 65, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 16 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 955, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 955) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(110, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(110, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 955, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 931isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 932isize, self.dispatch_generated_rule(66, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 934, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 935isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 937, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 937) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(105, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(105, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 937, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 938, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 939isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 941, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 941) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(106, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(106, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 941, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 942, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 943isize, self.dispatch_generated_rule(12, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 945, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 945) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(107, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(107, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 945, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 946, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 947isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 949, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 949) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(108, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(108, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 949, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 950, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 951isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 953, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 953) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(109, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(109, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 953, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 954, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_66(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 132isize, 66, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 959, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 959) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(111, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(111, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 959, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 957isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 958isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_67(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 134isize, 67, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 961isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(79, 963, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(80, 965, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 965, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 12 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 965, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 964isize, self.dispatch_generated_rule(69, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_68(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 136isize, 68, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 967isize, self.dispatch_generated_rule(37, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_69(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 138isize, 69, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(12, 970, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 970isize, self.dispatch_generated_rule(60, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_70(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 140isize, 70, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_975 = false; - loop { - self.base.sync_into(atn(), 975, &mut __ctx, __loop_iter_975, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 | 35 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 975, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_975 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 972isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 979, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 35 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 31 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 979, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(35, 980, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(31, 982, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 982isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(81, 987, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_987 = false; - loop { - self.base.sync_into(atn(), 987, &mut __ctx, __loop_iter_987, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 36 | 41 | 44 | 60 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 987, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_987 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 984isize, self.dispatch_generated_rule(71, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 991, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_71(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 142isize, 71, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 44 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 36 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 60 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1049, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 44 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 36 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 60 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1049, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(44, 996, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_996 = false; - loop { - self.base.sync_into(atn(), 996, &mut __ctx, __loop_iter_996, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 996) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(116, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(116, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 996, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_996 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 993isize, self.dispatch_generated_rule(72, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 999isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 1001, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(17, 1003, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1003isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1013, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 56 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1013, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(56, 1005, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1005isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1010 = false; - loop { - self.base.sync_into(atn(), 1010, &mut __ctx, __loop_iter_1010, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1010, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1010 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1007, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1007isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1016, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(36, 1018, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1018isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1028, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 56 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1028, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(56, 1020, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1020isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1025 = false; - loop { - self.base.sync_into(atn(), 1025, &mut __ctx, __loop_iter_1025, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1025, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1025 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1022, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1022isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1031, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(60, 1033, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1033isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 1035, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - self.base.match_token_into(41, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1037isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(66, 1039, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1039isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1044 = false; - loop { - self.base.sync_into(atn(), 1044, &mut __ctx, __loop_iter_1044, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1044, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1044 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1041, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1041isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(85, 1048, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_72(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 144isize, 72, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(48, 48), (58, 58)], 1052, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_73(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 146isize, 73, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(43, 1054, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1054isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1056, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1056, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1055isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1058isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1061, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 25 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1061, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(25, 1060, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1060isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1063isize, self.dispatch_generated_rule(77, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_74(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 148isize, 74, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(79, 1067, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1067, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1067, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1066isize, self.dispatch_generated_rule(75, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 1070, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_75(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 150isize, 75, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1071isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1076 = false; - loop { - self.base.sync_into(atn(), 1076, &mut __ctx, __loop_iter_1076, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1076) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(126, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(126, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1076, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1076 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1073, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1073isize, self.dispatch_generated_rule(76, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - if !self.base.parser_semantic_ir_predicate_matches_with_context_and_local(parser_semantics(), 75, 1, &__ctx, __precedence) { - if let Some(__message) = self.base.parser_semantic_ir_predicate_failure_message(75, 1, parser_semantics()) { - return Err(self.base.failed_predicate_option_error(75, __message)); - } - return Err(self.base.failed_predicate_error("semantic predicate")); - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_76(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 152isize, 76, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1084 = false; - loop { - self.base.sync_into(atn(), 1084, &mut __ctx, __loop_iter_1084, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1084) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(127, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(127, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1084, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1084 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1081isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1087isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1095, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124..=125 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1095, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __loop_iter_1091 = false; - loop { - self.base.sync_into(atn(), 1091, &mut __ctx, __loop_iter_1091, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1091, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1091 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1088isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(125, 1096, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1097isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_77(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 154isize, 77, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 1104, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1104 = false; - loop { - self.base.sync_into(atn(), 1104, &mut __ctx, __loop_iter_1104, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 3 | 5 | 8..=9 | 14 | 16..=17 | 19 | 21 | 28..=32 | 34..=36 | 38..=44 | 46..=49 | 52 | 56..=58 | 60..=64 | 66..=67 | 81 | 85 | 90 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1104, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1104 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8..=9 | 14 | 16 | 21 | 28..=30 | 47 | 62 | 81 | 85 | 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1102, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1102) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(130, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(130, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1102, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1100isize, self.dispatch_generated_rule(19, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1101isize, self.dispatch_generated_rule(27, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 1108, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_78(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 156isize, 78, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(81, 1113, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1113 = false; - loop { - self.base.sync_into(atn(), 1113, &mut __ctx, __loop_iter_1113, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1..=5 | 8..=9 | 11 | 13..=14 | 16..=17 | 19 | 21..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1113, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1113 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1110isize, self.dispatch_generated_rule(79, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 1117, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_79(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 158isize, 79, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 9 | 16 | 29 | 34 | 39..=40 | 42 | 48..=49 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 2 | 4 | 11 | 13 | 22 | 24 | 33 | 45 | 50..=54 | 59 | 62 | 65 | 68..=79 | 81 | 85 | 90..=92 | 101..=104 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1123, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1123) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(133, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(133, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1123, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1118isize, self.dispatch_generated_rule(80, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 1120, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1121isize, self.dispatch_generated_rule(83, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1122isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(84, 0) } else { self.parse_generated_rule_84_adaptive_dispatch(0, false, Some(1122isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_80(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 160isize, 80, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1128 = false; - loop { - self.base.sync_into(atn(), 1128, &mut __ctx, __loop_iter_1128, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1128) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(134, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(134, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1128, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1128 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1125isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1139, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1139) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(135, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(135, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1139, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(61, 1132, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1132isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(88, 1134, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1134isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1134isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1136isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1137isize, self.dispatch_generated_rule(37, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_81(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 162isize, 81, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_set_into(atn().token_set(4).expect("generated parser token-set index"), 1142, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_82(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 164isize, 82, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_set_into(atn().token_set(5).expect("generated parser token-set index"), 1144, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_83(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 166isize, 83, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1148 = false; - loop { - self.base.sync_into(atn(), 1148, &mut __ctx, __loop_iter_1148, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 | 19 | 34 | 39..=40 | 42 | 46 | 48..=49 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 16 | 29 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1148, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1148 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1145isize, self.dispatch_generated_rule(6, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 43 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 16 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1155, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 29 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 43 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 16 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1155, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1151isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1152isize, self.dispatch_generated_rule(16, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1153isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1154isize, self.dispatch_generated_rule(12, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_84_adaptive_dispatch(&mut self, precedence: i32, allow_fallback: bool, invoking_state: Option) -> Result { - if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() { - return self.dispatch_generated_rule(84, precedence, allow_fallback); - } - let __adaptive_outermost = self.adaptive_atn.preference_depths[0] == 0; - let __adaptive_rule_start = antlr4_runtime::IntStream::index(self.base.input()); - let __adaptive_parser_state = self.base.state(); - let __adaptive_diagnostic_marker = self.base.generated_diagnostics_checkpoint(); - if __adaptive_outermost { - self.adaptive_atn.preference_starts[0] = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - .unwrap_or((0, 0)); - self.adaptive_atn.syntax_error_starts[0] = self.base.number_of_syntax_errors(); - } - self.adaptive_atn.preference_depths[0] += 1; - let mut __result = self.dispatch_generated_rule(84, precedence, allow_fallback); - self.adaptive_atn.preference_depths[0] -= 1; - if !self.adaptive_atn.preferred_rules[0] { - if let Some(__adaptive_after) = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - { - let __adaptive_expensive = __result.is_ok() - && self.base.number_of_syntax_errors() == self.adaptive_atn.syntax_error_starts[0] - && antlr4_runtime::ParserAtnSimulator::adaptive_prediction_delta_is_expensive(self.adaptive_atn.preference_starts[0], __adaptive_after); - self.adaptive_atn.preferred_rules[0] = __adaptive_expensive; - if __adaptive_expensive { - self.adaptive_atn.retry_slot = Some(0); - __result = Err(GeneratedRuleError::AdaptiveRetry); - } - } - } - if __adaptive_outermost - && self.adaptive_atn.retry_slot == Some(0) - && matches!(&__result, Err(GeneratedRuleError::AdaptiveRetry)) - { - self.adaptive_atn.retry_slot = None; - self.base.restore_generated_diagnostics(__adaptive_diagnostic_marker); - antlr4_runtime::IntStream::seek(self.base.input(), __adaptive_rule_start); - self.base.set_state(__adaptive_parser_state); - if let Some(invoking_state) = invoking_state { - self.base.push_invoking_state(invoking_state); - } - return self.parse_rule_precedence_from_generated(84, precedence).map_err(GeneratedRuleError::Interpreted); - } - __result - } - - #[allow(dead_code)] - fn parse_generated_rule_84(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 168isize, 84, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 81 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 2 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 24 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 22 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 65 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 52 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 45 => antlr4_runtime::ParserAtnPrediction { alt: 11, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 54 => antlr4_runtime::ParserAtnPrediction { alt: 12, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 4 => antlr4_runtime::ParserAtnPrediction { alt: 13, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 14, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 16, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 21 | 28 | 30 | 33 | 47 | 50 | 53 | 62 | 68..=79 | 90..=92 | 101..=104 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 17, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1280, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1280) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(151, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(151, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1280, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1157isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(2, 1159, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1159isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1162, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 94 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1162, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(94, 1161, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1161isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1165, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(24, 1167, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1168, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1168isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(80, 1170, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1170isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(84, 0) } else { self.parse_generated_rule_84_adaptive_dispatch(0, false, Some(1170isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.sync_into(atn(), 1173, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1173) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(139, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(139, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1173, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(15, 1172, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1172isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(84, 0) } else { self.parse_generated_rule_84_adaptive_dispatch(0, false, Some(1172isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(22, 1176, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1177, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1177isize, self.dispatch_generated_rule(93, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(80, 1179, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1179isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(84, 0) } else { self.parse_generated_rule_84_adaptive_dispatch(0, false, Some(1179isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - self.base.match_token_into(65, 1182, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1183, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1183isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(80, 1185, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1185isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(84, 0) } else { self.parse_generated_rule_84_adaptive_dispatch(0, false, Some(1185isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - self.base.match_token_into(13, 1188, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1188isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(84, 0) } else { self.parse_generated_rule_84_adaptive_dispatch(0, false, Some(1188isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(65, 1190, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1191, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1191isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(80, 1193, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(85, 1194, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - self.base.match_token_into(59, 1196, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1196isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 7 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 20 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1206, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 7 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 20 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1206, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1197isize, self.dispatch_generated_rule(85, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1200 = true; - loop { - self.base.sync_into(atn(), 1200, &mut __ctx, __loop_iter_1200, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 7 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1..=6 | 8..=9 | 11..=17 | 19..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81..=82 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1200, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1200 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1197isize, self.dispatch_generated_rule(85, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1203, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 20 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1..=6 | 8..=9 | 11..=17 | 19 | 21..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81..=82 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1203, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1202isize, self.dispatch_generated_rule(87, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1205isize, self.dispatch_generated_rule(87, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 8 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(8); - } - self.base.match_token_into(59, 1209, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1209isize, self.dispatch_generated_rule(88, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1210isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1214 = false; - loop { - self.base.sync_into(atn(), 1214, &mut __ctx, __loop_iter_1214, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 7 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1..=6 | 8..=9 | 11..=17 | 19..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81..=82 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1214, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1214 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1211isize, self.dispatch_generated_rule(85, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1218, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 20 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1..=6 | 8..=9 | 11..=17 | 19 | 21..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81..=82 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1218, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1217isize, self.dispatch_generated_rule(87, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 9 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(9); - } - self.base.match_token_into(51, 1221, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1222, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1222isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(80, 1224, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(81, 1228, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1228 = false; - loop { - self.base.sync_into(atn(), 1228, &mut __ctx, __loop_iter_1228, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1228) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(145, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(145, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1228, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1228 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1225isize, self.dispatch_generated_rule(91, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1234 = false; - loop { - self.base.sync_into(atn(), 1234, &mut __ctx, __loop_iter_1234, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 6 | 12 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1234, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1234 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1231isize, self.dispatch_generated_rule(92, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 1238, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 10 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(10); - } - self.base.match_token_into(52, 1240, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1241, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1241isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(80, 1243, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1243isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 11 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(11); - } - self.base.match_token_into(45, 1247, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1247, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1247, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1246isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1281, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 12 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(12); - } - self.base.match_token_into(54, 1251, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1251isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 1253, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 13 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(13); - } - self.base.match_token_into(4, 1256, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1256, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1256, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1255isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1281, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 14 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(14); - } - self.base.match_token_into(11, 1261, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1261, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1261, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1260isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1281, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 15 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(15); - } - self.base.match_token_into(67, 1265, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1265isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 1267, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 16 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(16); - } - self.base.match_token_into(85, 1281, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 17 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(17); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1269isize, self.parse_generated_rule_98_adaptive_probe_dispatch(0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(85, 1271, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 18 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(18); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1272isize, self.dispatch_generated_rule(106, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1274, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1274) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(150, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(150, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1274, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 1275, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 19 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(19); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1276isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(94, 1278, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1278isize, if self.adaptive_atn.preferred_rules[0] { self.parse_rule_precedence_from_generated(84, 0) } else { self.parse_generated_rule_84_adaptive_dispatch(0, false, Some(1278isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_85(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 170isize, 85, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(7, 1283, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1287, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1287 = false; - loop { - self.base.sync_into(atn(), 1287, &mut __ctx, __loop_iter_1287, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1287, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1287 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1284isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1290isize, self.dispatch_generated_rule(86, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1291isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(80, 1293, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1293isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_86(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 172isize, 86, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1295isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1300 = false; - loop { - self.base.sync_into(atn(), 1300, &mut __ctx, __loop_iter_1300, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 108 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1300, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1300 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(108, 1297, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1297isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_87(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 174isize, 87, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(20, 1304, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1304isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_88(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 176isize, 88, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(79, 1307, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1307isize, self.dispatch_generated_rule(89, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1309, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 85 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1309, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 1310, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 1312, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_89(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 178isize, 89, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1313isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1318 = false; - loop { - self.base.sync_into(atn(), 1318, &mut __ctx, __loop_iter_1318, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1318) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(155, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(155, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1318, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1318 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(85, 1315, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1315isize, self.dispatch_generated_rule(90, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_90(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 180isize, 90, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1338, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1338) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(158, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(158, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1338, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __loop_iter_1324 = false; - loop { - self.base.sync_into(atn(), 1324, &mut __ctx, __loop_iter_1324, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1324, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1324 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1321isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1332, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1332) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(157, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(157, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1332, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1327isize, self.dispatch_generated_rule(111, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1328isize, self.dispatch_generated_rule(39, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(61, 1331, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1331isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(88, 1335, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1335isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1335isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1337isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_91(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 182isize, 91, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1340isize, self.dispatch_generated_rule(92, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(94, 1342, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1345 = true; - loop { - self.base.sync_into(atn(), 1345, &mut __ctx, __loop_iter_1345, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 6 | 12 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 1..=5 | 8..=9 | 11 | 13..=14 | 16..=17 | 19 | 21..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1345, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1345 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1340isize, self.dispatch_generated_rule(92, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(94, 1342, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1347isize, self.dispatch_generated_rule(79, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1350 = true; - loop { - self.base.sync_into(atn(), 1350, &mut __ctx, __loop_iter_1350, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1..=5 | 8..=9 | 11 | 13..=14 | 16..=17 | 19 | 21..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 6 | 12 | 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1350, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1350 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1347isize, self.dispatch_generated_rule(79, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_92(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 184isize, 92, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 6 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1361, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 6 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1361, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(6, 1358, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 33 | 50..=51 | 53 | 62 | 68..=79 | 90..=92 | 101..=104 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1358, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1358) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(161, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(161, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1358, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1353isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1353isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(129, 1359, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1355isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1356isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(12, 1362, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_93(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 186isize, 93, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 33 | 50..=51 | 53 | 62 | 68..=79 | 85 | 90..=92 | 101..=104 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1375, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1375) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(166, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(166, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1375, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1363isize, self.dispatch_generated_rule(95, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.sync_into(atn(), 1365, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 19 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1365, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1364isize, self.dispatch_generated_rule(94, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1369, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1369, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1369, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1368isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1368isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(85, 1373, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1373, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1373, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1372isize, self.dispatch_generated_rule(96, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_94(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 188isize, 94, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 | 50..=51 | 53 | 62 | 68..=79 | 90..=92 | 101..=104 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1379, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1379) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(167, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(167, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1379, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1377isize, self.dispatch_generated_rule(80, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1378isize, self.dispatch_generated_rule(96, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_95(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 190isize, 95, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1384 = false; - loop { - self.base.sync_into(atn(), 1384, &mut __ctx, __loop_iter_1384, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1384) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(168, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(168, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1384, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1384 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1381isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1389, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1389) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(169, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(169, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1389, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1387isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(61, 1390, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1391isize, self.dispatch_generated_rule(39, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(94, 1393, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1393isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1393isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_96(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 192isize, 96, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1395isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1395isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - let mut __loop_iter_1400 = false; - loop { - self.base.sync_into(atn(), 1400, &mut __ctx, __loop_iter_1400, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 | 85 | 94 | 122 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1400, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1400 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1397, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1397isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1397isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_97(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 194isize, 97, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 50 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1406, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 50 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1406, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1403isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(53, 1407, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(50, 1407, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1408isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_98_adaptive_probe_dispatch(&mut self, precedence: i32, allow_fallback: bool) -> Result { - let __result = self.dispatch_generated_rule(98, precedence, allow_fallback); - if __result.is_ok() && self.adaptive_atn.retry_slot.is_none() { - if let Some(__adaptive_after) = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - { - if self.adaptive_atn.preference_depths[0] != 0 - && !self.adaptive_atn.preferred_rules[0] - && self.base.number_of_syntax_errors() == self.adaptive_atn.syntax_error_starts[0] - && antlr4_runtime::ParserAtnSimulator::adaptive_prediction_delta_is_decisive(self.adaptive_atn.preference_starts[0], __adaptive_after) - { - self.adaptive_atn.preferred_rules[0] = true; - self.adaptive_atn.retry_slot = Some(0); - return Err(GeneratedRuleError::AdaptiveRetry); - } - } - } - __result - } - - #[allow(dead_code)] - fn parse_generated_rule_98_adaptive_dispatch(&mut self, precedence: i32, allow_fallback: bool, invoking_state: Option) -> Result { - if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() || self.base.observes_parser_decisions() { - return self.dispatch_generated_rule(98, precedence, allow_fallback); - } - let __adaptive_outermost = self.adaptive_atn.preference_depths[1] == 0; - let __adaptive_rule_start = antlr4_runtime::IntStream::index(self.base.input()); - let __adaptive_parser_state = self.base.state(); - let __adaptive_diagnostic_marker = self.base.generated_diagnostics_checkpoint(); - if __adaptive_outermost { - self.adaptive_atn.preference_starts[1] = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - .unwrap_or((0, 0)); - self.adaptive_atn.syntax_error_starts[1] = self.base.number_of_syntax_errors(); - } - self.adaptive_atn.preference_depths[1] += 1; - let mut __result = self.dispatch_generated_rule(98, precedence, allow_fallback); - self.adaptive_atn.preference_depths[1] -= 1; - if !self.adaptive_atn.preferred_rules[1] { - if let Some(__adaptive_after) = self.simulator - .as_ref() - .and_then(antlr4_runtime::ParserAtnSimulator::adaptive_prediction_work) - { - let __adaptive_expensive = __result.is_ok() - && self.base.number_of_syntax_errors() == self.adaptive_atn.syntax_error_starts[1] - && antlr4_runtime::ParserAtnSimulator::adaptive_prediction_delta_is_expensive(self.adaptive_atn.preference_starts[1], __adaptive_after); - self.adaptive_atn.preferred_rules[1] = __adaptive_expensive; - if __adaptive_expensive { - self.adaptive_atn.retry_slot = Some(1); - __result = Err(GeneratedRuleError::AdaptiveRetry); - } - } - } - if __adaptive_outermost - && self.adaptive_atn.retry_slot == Some(1) - && matches!(&__result, Err(GeneratedRuleError::AdaptiveRetry)) - { - self.adaptive_atn.retry_slot = None; - self.base.restore_generated_diagnostics(__adaptive_diagnostic_marker); - antlr4_runtime::IntStream::seek(self.base.input(), __adaptive_rule_start); - self.base.set_state(__adaptive_parser_state); - if let Some(invoking_state) = invoking_state { - self.base.push_invoking_state(invoking_state); - } - return self.parse_rule_precedence_from_generated(98, precedence).map_err(GeneratedRuleError::Interpreted); - } - __result - } - - #[allow(dead_code)] - fn parse_generated_rule_98(&mut self, allow_fallback: bool) -> Result { - self.parse_generated_rule_98_precedence(0, allow_fallback) - } - - #[allow(dead_code)] - fn parse_generated_rule_98_precedence(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - antlr4_runtime::__antlr4_rust_generated_rule! { - recursive self, 196isize, 98, __precedence, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 62 | 68..=78 | 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 51 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 91..=92 | 101..=104 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1453, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1453) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(177, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(177, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1453, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let action = self.base.parser_action_at_current_indexed(1410, 98, 0, __rule_start, __consumed_eof); - let _ = action; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1411isize, self.dispatch_generated_rule(105, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1412isize, self.dispatch_generated_rule(97, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1413isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(123, 1420, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 90 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1420, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 90 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1420, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.sync_into(atn(), 1416, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1416, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1415isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1418isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(33, 1421, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1422isize, self.dispatch_generated_rule(42, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(123, 1425, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1425, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 33 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1425, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1424isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(33, 1428, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1429isize, self.dispatch_generated_rule(106, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - self.base.match_set_into(&[(91, 92), (101, 104)], 1431, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1431isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 17) } else { self.parse_generated_rule_98_adaptive_dispatch(17, false, Some(1431isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - self.base.match_token_into(79, 1436, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1436 = false; - loop { - self.base.sync_into(atn(), 1436, &mut __ctx, __loop_iter_1436, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1436) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(175, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(175, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1436, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1436 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1433isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1439isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1444 = false; - loop { - self.base.sync_into(atn(), 1444, &mut __ctx, __loop_iter_1444, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 107 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1444, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1444 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(107, 1441, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1441isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(80, 1448, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1448isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 16) } else { self.parse_generated_rule_98_adaptive_dispatch(16, false, Some(1448isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 8 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(8); - } - self.base.match_token_into(33, 1451, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1451isize, self.dispatch_generated_rule(112, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 9 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(9); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1452isize, self.dispatch_generated_rule(102, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - loop { - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.left_recursive_loop_enter_prediction(atn(), 1538, __precedence) { - Some(true) => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: true, diagnostic: None }, - Some(false) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - None => { - let __prediction_precedence = if __precedence <= 0 { 0 } else { __precedence as usize }; - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - match __simulator.adaptive_predict_stream_info_with_context(184, __prediction_precedence, self.base.input(), __prediction_context) { - Ok(__prediction) => __prediction, - Err(antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { .. }) => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: true, has_semantic_context: false, diagnostic: None }, - Err(_) => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1538, &__prediction); - match __prediction.alt { - 1 => { - self.base.parse_listener_exit_rule(98); - if let Some(__depth_error) = self.base.rule_depth_cap_violation() { - return Err(__depth_error); - } - self.base.push_new_recursion_context_with_previous(196isize, 98, &mut __ctx); - if let Some(__listener_error) = self.base.parse_listener_enter_rule(98) { - return Err(__listener_error); - } - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(183, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - if !self.base.precpred(25) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 25)")); - } - self.base.match_token_into(83, 1457, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1457isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1457isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(84, 1459, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - if !self.base.precpred(24) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 24)")); - } - self.base.match_token_into(87, 1473, atn(), &mut __ctx, &mut __consumed_eof)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(179, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1462isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1463isize, self.dispatch_generated_rule(97, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(53, 1474, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(33, 1467, atn(), &mut __ctx, &mut __consumed_eof)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(178, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1466isize, self.dispatch_generated_rule(120, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1469isize, self.dispatch_generated_rule(114, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - self.base.match_token_into(50, 1471, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1471isize, self.dispatch_generated_rule(125, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1472isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - if !self.base.precpred(22) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 22)")); - } - self.base.match_token_into(123, 1478, atn(), &mut __ctx, &mut __consumed_eof)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(180, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1477isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1480isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - if !self.base.precpred(18) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 18)")); - } - self.base.match_set_into(&[(101, 102)], 1537, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - if !self.base.precpred(14) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 14)")); - } - self.base.match_set_into(&[(105, 106), (110, 110)], 1485, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1485isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 15) } else { self.parse_generated_rule_98_adaptive_dispatch(15, false, Some(1485isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - if !self.base.precpred(13) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 13)")); - } - self.base.match_set_into(&[(103, 104)], 1488, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1488isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 14) } else { self.parse_generated_rule_98_adaptive_dispatch(14, false, Some(1488isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - if !self.base.precpred(12) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 12)")); - } - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(181, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if self.base.report_diagnostic_errors() { - let __diagnostic_la = self.base.la(1); - let mut __diagnostic_alts = Vec::new(); - if __diagnostic_la == 90 { - __diagnostic_alts.push(1); - } - if __diagnostic_la == 89 { - __diagnostic_alts.push(2); - } - if __diagnostic_la == 89 { - __diagnostic_alts.push(3); - } - self.base.record_generated_ambiguity_diagnostic(atn(), 1497, __decision_start, __decision_start, &__diagnostic_alts); - } - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(90, 1491, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(90, 1498, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(89, 1493, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(89, 1494, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(89, 1498, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(89, 1496, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(89, 1498, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1499isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 13) } else { self.parse_generated_rule_98_adaptive_dispatch(13, false, Some(1499isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 8 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(8); - } - if !self.base.precpred(11) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 11)")); - } - self.base.match_set_into(&[(89, 90), (96, 97)], 1502, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1502isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 12) } else { self.parse_generated_rule_98_adaptive_dispatch(12, false, Some(1502isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 9 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(9); - } - if !self.base.precpred(10) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 10)")); - } - self.base.match_token_into(27, 1507, atn(), &mut __ctx, &mut __consumed_eof)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(182, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1505isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1506isize, self.dispatch_generated_rule(99, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 10 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(10); - } - if !self.base.precpred(9) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 9)")); - } - self.base.match_set_into(&[(95, 95), (98, 98)], 1511, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1511isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 10) } else { self.parse_generated_rule_98_adaptive_dispatch(10, false, Some(1511isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 11 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(11); - } - if !self.base.precpred(8) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 8)")); - } - self.base.match_token_into(107, 1514, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1514isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 9) } else { self.parse_generated_rule_98_adaptive_dispatch(9, false, Some(1514isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 12 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(12); - } - if !self.base.precpred(7) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 7)")); - } - self.base.match_token_into(109, 1517, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1517isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 8) } else { self.parse_generated_rule_98_adaptive_dispatch(8, false, Some(1517isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 13 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(13); - } - if !self.base.precpred(6) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 6)")); - } - self.base.match_token_into(108, 1520, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1520isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 7) } else { self.parse_generated_rule_98_adaptive_dispatch(7, false, Some(1520isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 14 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(14); - } - if !self.base.precpred(5) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 5)")); - } - self.base.match_token_into(99, 1523, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1523isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 6) } else { self.parse_generated_rule_98_adaptive_dispatch(6, false, Some(1523isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 15 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(15); - } - if !self.base.precpred(4) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 4)")); - } - self.base.match_token_into(100, 1526, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1526isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 5) } else { self.parse_generated_rule_98_adaptive_dispatch(5, false, Some(1526isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 16 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(16); - } - if !self.base.precpred(3) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 3)")); - } - self.base.match_token_into(93, 1529, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1529isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1529isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(94, 1531, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1531isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 3) } else { self.parse_generated_rule_98_adaptive_dispatch(3, false, Some(1531isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 17 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(17); - } - if !self.base.precpred(2) { - return Err(self.base.failed_predicate_error("precpred(_ctx, 2)")); - } - self.base.match_set_into(&[(88, 88), (111, 121)], 1535, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1535isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 2) } else { self.parse_generated_rule_98_adaptive_dispatch(2, false, Some(1535isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => break, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_99(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 198isize, 99, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1563, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1563) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(188, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(188, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1563, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __loop_iter_1544 = false; - loop { - self.base.sync_into(atn(), 1544, &mut __ctx, __loop_iter_1544, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1544) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(185, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(185, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1544, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1544 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1541isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1547isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1551 = false; - loop { - self.base.sync_into(atn(), 1551, &mut __ctx, __loop_iter_1551, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1551, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1551 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1548isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1554isize, self.dispatch_generated_rule(37, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1556isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(79, 1559, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1559, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 19 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1559, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1558isize, self.dispatch_generated_rule(100, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 1562, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_100(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 200isize, 100, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1565isize, self.dispatch_generated_rule(101, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1570 = false; - loop { - self.base.sync_into(atn(), 1570, &mut __ctx, __loop_iter_1570, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1570, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1570 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1567, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1567isize, self.dispatch_generated_rule(101, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_101(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 202isize, 101, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1573isize, self.dispatch_generated_rule(99, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_102(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 204isize, 102, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1575isize, self.dispatch_generated_rule(103, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(122, 1577, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1577isize, self.dispatch_generated_rule(104, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_103(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 206isize, 103, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1601, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1601) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(193, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(193, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1601, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1579isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(79, 1582, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1582, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 19 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1582, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1581isize, self.dispatch_generated_rule(48, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 1602, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(79, 1586, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1586isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1591 = false; - loop { - self.base.sync_into(atn(), 1591, &mut __ctx, __loop_iter_1591, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1591, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1591 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1588, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1588isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(80, 1595, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - self.base.match_token_into(79, 1598, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1598, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 19 | 61 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1598, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1597isize, self.dispatch_generated_rule(50, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 1602, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_104(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 208isize, 104, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1605, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1605, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1603isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1603isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1604isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_105(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 210isize, 105, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 79 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 50 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 68..=78 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 21 | 28 | 30 | 47 | 62 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1625, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1625) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(196, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(196, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1625, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(79, 1608, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1608isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1608isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(80, 1610, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(53, 1626, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - self.base.match_token_into(50, 1626, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(4); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1613isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(5); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1614isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(6); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1615isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(87, 1617, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(9, 1618, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 7 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(7); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1619isize, self.dispatch_generated_rule(120, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 50 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1623, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 50 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1623, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1620isize, self.dispatch_generated_rule(126, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(53, 1622, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1622isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_106(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 212isize, 106, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(51, 1628, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(79, 1629, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1629isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1629isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(80, 1631, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(81, 1635, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1635 = false; - loop { - self.base.sync_into(atn(), 1635, &mut __ctx, __loop_iter_1635, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 6 | 12 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1635, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1635 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1632isize, self.dispatch_generated_rule(107, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 1639, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_107(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 214isize, 107, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 6 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1665, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 6 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1665, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(6, 1658, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 33 | 50..=51 | 53 | 62 | 68..=77 | 79 | 90..=92 | 101..=104 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1658, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1658) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(201, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(201, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1658, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1641isize, self.dispatch_generated_rule(96, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(78, 1645, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1645, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 | 122 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1645, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1644, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(12, 1646, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 3 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(3); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1647isize, self.dispatch_generated_rule(109, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1652 = false; - loop { - self.base.sync_into(atn(), 1652, &mut __ctx, __loop_iter_1652, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 64 | 94 | 122 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1652, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1652 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1649, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1649isize, self.dispatch_generated_rule(109, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1656, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 64 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 | 122 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1656, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1655isize, self.dispatch_generated_rule(108, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_set_into(&[(94, 94), (122, 122)], 1661, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1661isize, self.dispatch_generated_rule(110, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(12, 1663, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_set_into(&[(94, 94), (122, 122)], 1664, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1664isize, self.dispatch_generated_rule(110, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_108(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 216isize, 108, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(64, 1668, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1668isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1668isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_109(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 218isize, 109, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1670isize, self.dispatch_generated_rule(99, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_110(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 220isize, 110, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1679, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1679) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(204, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(204, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1679, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1672isize, self.dispatch_generated_rule(78, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - let mut __loop_iter_1676 = false; - loop { - self.base.sync_into(atn(), 1676, &mut __ctx, __loop_iter_1676, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1..=5 | 8..=9 | 11 | 13..=14 | 16..=17 | 19 | 21..=22 | 24 | 28..=31 | 33..=36 | 38..=54 | 56 | 58..=62 | 64..=79 | 81 | 85 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 6 | 12 | 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1676, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1676 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1673isize, self.dispatch_generated_rule(79, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_111(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 222isize, 111, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1681isize, self.dispatch_generated_rule(42, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_112(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 224isize, 112, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1692, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1692) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(206, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(206, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1692, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.sync_into(atn(), 1684, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1684, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1683isize, self.dispatch_generated_rule(120, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1686isize, self.dispatch_generated_rule(113, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1687isize, self.dispatch_generated_rule(116, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1689isize, self.dispatch_generated_rule(113, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1690isize, self.dispatch_generated_rule(115, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_113(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 226isize, 113, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 21 | 28 | 30 | 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1709, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 21 | 28 | 30 | 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1709, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1694isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1696, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 | 83 | 87 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1696, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1695isize, self.dispatch_generated_rule(118, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1705 = false; - loop { - self.base.sync_into(atn(), 1705, &mut __ctx, __loop_iter_1705, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 87 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 | 83 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1705, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1705 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(87, 1699, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1699isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1701, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 | 83 | 87 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1701, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1700isize, self.dispatch_generated_rule(118, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1708isize, self.dispatch_generated_rule(123, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_114(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 228isize, 114, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1711isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1713, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 79 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1713, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1712isize, self.dispatch_generated_rule(119, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1715isize, self.dispatch_generated_rule(116, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_115(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 230isize, 115, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1739, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1739) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(215, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(215, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1739, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(83, 1718, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 1720, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1721 = true; - loop { - self.base.sync_into(atn(), 1721, &mut __ctx, __loop_iter_1721, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 83 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1721, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1721 = true; - self.base.match_token_into(83, 1718, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 1720, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1723isize, self.dispatch_generated_rule(41, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(83, 1725, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1725isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1725isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(84, 1727, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1730 = true; - loop { - self.base.sync_into(atn(), 1730, &mut __ctx, __loop_iter_1730, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1730) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(213, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(213, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1730, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1730 = true; - self.base.match_token_into(83, 1725, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1725isize, if self.adaptive_atn.preferred_rules[1] { self.parse_rule_precedence_from_generated(98, 0) } else { self.parse_generated_rule_98_adaptive_dispatch(0, false, Some(1725isize)).map_err(GeneratedRuleError::into_error) }, __ctx); - self.base.match_token_into(84, 1727, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1736 = false; - loop { - self.base.sync_into(atn(), 1736, &mut __ctx, __loop_iter_1736, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1736) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(214, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(214, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1736, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1736 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(83, 1733, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 1735, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_116(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 232isize, 116, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1741isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1743, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1743) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(216, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(216, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1743, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1742isize, self.dispatch_generated_rule(17, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_117(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 234isize, 117, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1745isize, self.dispatch_generated_rule(120, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1746isize, self.dispatch_generated_rule(126, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_118(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 236isize, 118, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1751, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1751) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(217, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(217, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1751, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(90, 1749, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(89, 1752, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1750isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_119(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 238isize, 119, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1756, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1756) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(218, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(218, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1756, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(90, 1754, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(89, 1757, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1755isize, self.dispatch_generated_rule(120, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_120(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 240isize, 120, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(90, 1759, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1759isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(89, 1761, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_121(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 242isize, 121, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1762isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1767 = false; - loop { - self.base.sync_into(atn(), 1767, &mut __ctx, __loop_iter_1767, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 38 | 81 | 89 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1767, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1767 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1764, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1764isize, self.dispatch_generated_rule(122, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_122(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 244isize, 122, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1773 = false; - loop { - self.base.sync_into(atn(), 1773, &mut __ctx, __loop_iter_1773, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1773, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1773 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1770isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 21 | 28 | 30 | 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1778, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 3 | 5 | 8 | 14 | 21 | 28 | 30 | 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1778, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1776isize, self.dispatch_generated_rule(111, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1777isize, self.dispatch_generated_rule(123, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1790 = false; - loop { - self.base.sync_into(atn(), 1790, &mut __ctx, __loop_iter_1790, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1790) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(223, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(223, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1790, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1790 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - let mut __loop_iter_1783 = false; - loop { - self.base.sync_into(atn(), 1783, &mut __ctx, __loop_iter_1783, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 83 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1783, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1783 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1780isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(83, 1787, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(84, 1789, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_123(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 246isize, 123, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(3, 3), (5, 5), (8, 8), (14, 14), (21, 21), (28, 28), (30, 30), (47, 47)], 1794, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_124(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 248isize, 124, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(90, 1796, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1796isize, self.dispatch_generated_rule(44, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1801 = false; - loop { - self.base.sync_into(atn(), 1801, &mut __ctx, __loop_iter_1801, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 89 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1801, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1801 = true; - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(86, 1798, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1798isize, self.dispatch_generated_rule(44, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(89, 1805, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_125(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 250isize, 125, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 79 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 87 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1815, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 79 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 87 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1815, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1806isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - self.base.match_token_into(87, 1809, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1809, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1809, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1808isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1811isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1813, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1813) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(226, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(226, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1813, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1812isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_126(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 252isize, 126, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 50 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1822, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 50 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 17 | 31 | 35..=36 | 38 | 41 | 43..=44 | 46 | 56 | 58 | 60..=61 | 64 | 66..=67 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1822, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - self.base.match_token_into(50, 1818, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1818isize, self.dispatch_generated_rule(125, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1819isize, self.dispatch_generated_rule(81, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1820isize, self.dispatch_generated_rule(127, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_127(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 254isize, 127, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(79, 1826, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1826, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 3 | 5 | 8 | 14 | 17 | 21 | 28 | 30..=31 | 33 | 35..=36 | 38 | 41 | 43..=44 | 46..=47 | 50..=51 | 53 | 56 | 58 | 60..=62 | 64 | 66..=79 | 90..=92 | 101..=104 | 124 | 129 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1826, &__prediction); - match __prediction.alt { - 1 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(1); - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1825isize, self.dispatch_generated_rule(96, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - if __ctx.context_alt_number() == 0 { - __ctx.set_context_alt_number(2); - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 1829, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - - - pub fn compilation_unit(&mut self) -> Result { - self.parse_rule(0) - } - pub fn modular_compulation_unit(&mut self) -> Result { - self.parse_rule(1) - } - pub fn package_declaration(&mut self) -> Result { - self.parse_rule(2) - } - pub fn import_declaration(&mut self) -> Result { - self.parse_rule(3) - } - pub fn type_declaration(&mut self) -> Result { - self.parse_rule(4) - } - pub fn modifier(&mut self) -> Result { - self.parse_rule(5) - } - pub fn class_or_interface_modifier(&mut self) -> Result { - self.parse_rule(6) - } - pub fn variable_modifier(&mut self) -> Result { - self.parse_rule(7) - } - pub fn class_declaration(&mut self) -> Result { - self.parse_rule(8) - } - pub fn type_parameters(&mut self) -> Result { - self.parse_rule(9) - } - pub fn type_parameter(&mut self) -> Result { - self.parse_rule(10) - } - pub fn type_bound(&mut self) -> Result { - self.parse_rule(11) - } - pub fn enum_declaration(&mut self) -> Result { - self.parse_rule(12) - } - pub fn enum_constants(&mut self) -> Result { - self.parse_rule(13) - } - pub fn enum_constant(&mut self) -> Result { - self.parse_rule(14) - } - pub fn enum_body_declarations(&mut self) -> Result { - self.parse_rule(15) - } - pub fn interface_declaration(&mut self) -> Result { - self.parse_rule(16) - } - pub fn class_body(&mut self) -> Result { - self.parse_rule(17) - } - pub fn interface_body(&mut self) -> Result { - self.parse_rule(18) - } - pub fn class_body_declaration(&mut self) -> Result { - self.parse_rule(19) - } - pub fn member_declaration(&mut self) -> Result { - self.parse_rule(20) - } - pub fn method_declaration(&mut self) -> Result { - self.parse_rule(21) - } - pub fn method_body(&mut self) -> Result { - self.parse_rule(22) - } - pub fn type_type_or_void(&mut self) -> Result { - self.parse_rule(23) - } - pub fn generic_method_declaration(&mut self) -> Result { - self.parse_rule(24) - } - pub fn generic_constructor_declaration(&mut self) -> Result { - self.parse_rule(25) - } - pub fn constructor_declaration(&mut self) -> Result { - self.parse_rule(26) - } - pub fn compact_constructor_declaration(&mut self) -> Result { - self.parse_rule(27) - } - pub fn field_declaration(&mut self) -> Result { - self.parse_rule(28) - } - pub fn interface_body_declaration(&mut self) -> Result { - self.parse_rule(29) - } - pub fn interface_member_declaration(&mut self) -> Result { - self.parse_rule(30) - } - pub fn const_declaration(&mut self) -> Result { - self.parse_rule(31) - } - pub fn constant_declarator(&mut self) -> Result { - self.parse_rule(32) - } - pub fn interface_method_declaration(&mut self) -> Result { - self.parse_rule(33) - } - pub fn interface_method_modifier(&mut self) -> Result { - self.parse_rule(34) - } - pub fn generic_interface_method_declaration(&mut self) -> Result { - self.parse_rule(35) - } - pub fn interface_common_body_declaration(&mut self) -> Result { - self.parse_rule(36) - } - pub fn variable_declarators(&mut self) -> Result { - self.parse_rule(37) - } - pub fn variable_declarator(&mut self) -> Result { - self.parse_rule(38) - } - pub fn variable_declarator_id(&mut self) -> Result { - self.parse_rule(39) - } - pub fn variable_initializer(&mut self) -> Result { - self.parse_rule(40) - } - pub fn array_initializer(&mut self) -> Result { - self.parse_rule(41) - } - pub fn class_type(&mut self) -> Result { - self.parse_rule(42) - } - pub fn package_name(&mut self) -> Result { - self.parse_rule(43) - } - pub fn type_argument(&mut self) -> Result { - self.parse_rule(44) - } - pub fn qualified_name_list(&mut self) -> Result { - self.parse_rule(45) - } - pub fn formal_parameters(&mut self) -> Result { - self.parse_rule(46) - } - pub fn receiver_parameter(&mut self) -> Result { - self.parse_rule(47) - } - pub fn formal_parameter_list(&mut self) -> Result { - self.parse_rule(48) - } - pub fn formal_parameter(&mut self) -> Result { - self.parse_rule(49) - } - pub fn lambda_lvti_list(&mut self) -> Result { - self.parse_rule(50) - } - pub fn lambda_lvti_parameter(&mut self) -> Result { - self.parse_rule(51) - } - pub fn qualified_name(&mut self) -> Result { - self.parse_rule(52) - } - pub fn literal(&mut self) -> Result { - self.parse_rule(53) - } - pub fn integer_literal(&mut self) -> Result { - self.parse_rule(54) - } - pub fn float_literal(&mut self) -> Result { - self.parse_rule(55) - } - pub fn annotation(&mut self) -> Result { - self.parse_rule(56) - } - pub fn annotation_field_values(&mut self) -> Result { - self.parse_rule(57) - } - pub fn annotation_field_value(&mut self) -> Result { - self.parse_rule(58) - } - pub fn annotation_value(&mut self) -> Result { - self.parse_rule(59) - } - pub fn element_value(&mut self) -> Result { - self.parse_rule(60) - } - pub fn element_value_array_initializer(&mut self) -> Result { - self.parse_rule(61) - } - pub fn annotation_type_declaration(&mut self) -> Result { - self.parse_rule(62) - } - pub fn annotation_type_body(&mut self) -> Result { - self.parse_rule(63) - } - pub fn annotation_type_element_declaration(&mut self) -> Result { - self.parse_rule(64) - } - pub fn annotation_type_element_rest(&mut self) -> Result { - self.parse_rule(65) - } - pub fn annotation_method_or_constant_rest(&mut self) -> Result { - self.parse_rule(66) - } - pub fn annotation_method_rest(&mut self) -> Result { - self.parse_rule(67) - } - pub fn annotation_constant_rest(&mut self) -> Result { - self.parse_rule(68) - } - pub fn default_value(&mut self) -> Result { - self.parse_rule(69) - } - pub fn module_declaration(&mut self) -> Result { - self.parse_rule(70) - } - pub fn module_directive(&mut self) -> Result { - self.parse_rule(71) - } - pub fn requires_modifier(&mut self) -> Result { - self.parse_rule(72) - } - pub fn record_declaration(&mut self) -> Result { - self.parse_rule(73) - } - pub fn record_header(&mut self) -> Result { - self.parse_rule(74) - } - pub fn record_component_list(&mut self) -> Result { - self.parse_rule(75) - } - pub fn record_component(&mut self) -> Result { - self.parse_rule(76) - } - pub fn record_body(&mut self) -> Result { - self.parse_rule(77) - } - pub fn block(&mut self) -> Result { - self.parse_rule(78) - } - pub fn block_statement(&mut self) -> Result { - self.parse_rule(79) - } - pub fn local_variable_declaration(&mut self) -> Result { - self.parse_rule(80) - } - pub fn identifier(&mut self) -> Result { - self.parse_rule(81) - } - pub fn type_identifier(&mut self) -> Result { - self.parse_rule(82) - } - pub fn local_type_declaration(&mut self) -> Result { - self.parse_rule(83) - } - pub fn statement(&mut self) -> Result { - self.parse_rule(84) - } - pub fn catch_clause(&mut self) -> Result { - self.parse_rule(85) - } - pub fn catch_type(&mut self) -> Result { - self.parse_rule(86) - } - pub fn finally_block(&mut self) -> Result { - self.parse_rule(87) - } - pub fn resource_specification(&mut self) -> Result { - self.parse_rule(88) - } - pub fn resources(&mut self) -> Result { - self.parse_rule(89) - } - pub fn resource(&mut self) -> Result { - self.parse_rule(90) - } - pub fn switch_block_statement_group(&mut self) -> Result { - self.parse_rule(91) - } - pub fn switch_label(&mut self) -> Result { - self.parse_rule(92) - } - pub fn for_control(&mut self) -> Result { - self.parse_rule(93) - } - pub fn for_init(&mut self) -> Result { - self.parse_rule(94) - } - pub fn enhanced_for_control(&mut self) -> Result { - self.parse_rule(95) - } - pub fn expression_list(&mut self) -> Result { - self.parse_rule(96) - } - pub fn method_call(&mut self) -> Result { - self.parse_rule(97) - } - pub fn expression(&mut self) -> Result { - self.parse_rule(98) - } - pub fn pattern(&mut self) -> Result { - self.parse_rule(99) - } - pub fn component_pattern_list(&mut self) -> Result { - self.parse_rule(100) - } - pub fn component_pattern(&mut self) -> Result { - self.parse_rule(101) - } - pub fn lambda_expression(&mut self) -> Result { - self.parse_rule(102) - } - pub fn lambda_parameters(&mut self) -> Result { - self.parse_rule(103) - } - pub fn lambda_body(&mut self) -> Result { - self.parse_rule(104) - } - pub fn primary(&mut self) -> Result { - self.parse_rule(105) - } - pub fn switch_expression(&mut self) -> Result { - self.parse_rule(106) - } - pub fn switch_labeled_rule(&mut self) -> Result { - self.parse_rule(107) - } - pub fn guard(&mut self) -> Result { - self.parse_rule(108) - } - pub fn case_pattern(&mut self) -> Result { - self.parse_rule(109) - } - pub fn switch_rule_outcome(&mut self) -> Result { - self.parse_rule(110) - } - pub fn class_or_interface_type(&mut self) -> Result { - self.parse_rule(111) - } - pub fn creator(&mut self) -> Result { - self.parse_rule(112) - } - pub fn created_name(&mut self) -> Result { - self.parse_rule(113) - } - pub fn inner_creator(&mut self) -> Result { - self.parse_rule(114) - } - pub fn array_creator_rest(&mut self) -> Result { - self.parse_rule(115) - } - pub fn class_creator_rest(&mut self) -> Result { - self.parse_rule(116) - } - pub fn explicit_generic_invocation(&mut self) -> Result { - self.parse_rule(117) - } - pub fn type_arguments_or_diamond(&mut self) -> Result { - self.parse_rule(118) - } - pub fn non_wildcard_type_arguments_or_diamond(&mut self) -> Result { - self.parse_rule(119) - } - pub fn non_wildcard_type_arguments(&mut self) -> Result { - self.parse_rule(120) - } - pub fn type_list(&mut self) -> Result { - self.parse_rule(121) - } - pub fn type_type(&mut self) -> Result { - self.parse_rule(122) - } - pub fn primitive_type(&mut self) -> Result { - self.parse_rule(123) - } - pub fn type_arguments(&mut self) -> Result { - self.parse_rule(124) - } - pub fn super_suffix(&mut self) -> Result { - self.parse_rule(125) - } - pub fn explicit_generic_invocation_suffix(&mut self) -> Result { - self.parse_rule(126) - } - pub fn arguments(&mut self) -> Result { - self.parse_rule(127) - } - - - fn run_action(&mut self, action: antlr4_runtime::ParserAction, tree: antlr4_runtime::ParseTree) { - match action.source_state() { - 1410 => {} - _ => { let _ = self.base.parser_action_hook(action, tree); } - } - } - -} - -antlr4_runtime::__antlr4_rust_parser_driver! { - type: JavaParser, - fields: { - base: base, - simulator: simulator, - }, - atn: atn, - adaptive_direct: false, - fallback(parser, rule_index, precedence) { - parser.base.parse_atn_rule_with_runtime_options_and_precedence(atn(), rule_index, precedence, antlr4_runtime::ParserRuntimeOptions { action_indices: &[], track_alt_numbers: false, track_context_alt_numbers: true, predicates: &[], semantics: Some(parser_semantics()), rule_args: &[], member_actions: &[], return_actions: &[], unknown_predicate_policy: antlr4_runtime::UnknownSemanticPolicy::Error , ..antlr4_runtime::ParserRuntimeOptions::default() }) - } -} - -impl JavaParser> -where - L: TokenSource, - T: JavaParserHooks, -{ - pub fn with_typed_hooks(input: CommonTokenStream, hooks: T) -> Self { - Self::with_hooks(input, JavaParserTypedHooks::new(hooks)) - } -} - - -antlr4_runtime::__antlr4_rust_parser_facade! { - type: JavaParser, - fields: { - base: base, - simulator: simulator, - generated_only: generated_only, - }, - metadata: metadata, - parser_atn: parser_atn, - reset(parser) { - parser.adaptive_atn.reset(); - } -} -} - -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -pub use self::__antlr4_rust_generated::*; diff --git a/crates/mehen-java-parser/src/generated/semantics.json b/crates/mehen-java-parser/src/generated/semantics.json deleted file mode 100644 index d3d81f83..00000000 --- a/crates/mehen-java-parser/src/generated/semantics.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "version": 2, - "policy": "error", - "note": "unknown coordinates currently default to assume-true; a future minor release changes the default to error", - "options": [ - { - "name": "superClass", - "value": "JavaParserBase", - "line": 39, - "column": 4, - "disposition": "hooked" - }, - { - "name": "tokenVocab", - "value": "JavaLexer", - "line": 38, - "column": 4, - "disposition": "metadata" - } - ], - "grammars": [ - { - "kind": "lexer", - "name": "JavaLexer", - "coordinates": [] - }, - { - "kind": "parser", - "name": "JavaParser", - "coordinates": [ - { - "kind": "parser-predicate", - "rule": "annotationFieldValue", - "rule_index": 58, - "index": 0, - "atn_state": null, - "line": 360, - "column": 1, - "body": "this.IsNotIdentifierAssign()", - "disposition": "hooked", - "template": "Hook" - }, - { - "kind": "parser-predicate", - "rule": "recordComponentList", - "rule_index": 75, - "index": 1, - "atn_state": null, - "line": 453, - "column": 45, - "body": "this.DoLastRecordComponent()", - "disposition": "hooked", - "template": "Hook" - }, - { - "kind": "parser-action", - "rule": "expression", - "rule_index": 98, - "index": 0, - "atn_state": 1410, - "line": null, - "column": null, - "body": null, - "disposition": "synthetic", - "template": null - } - ] - } - ] -} diff --git a/crates/mehen-java-parser/src/hooks.rs b/crates/mehen-java-parser/src/hooks.rs deleted file mode 100644 index 47f10ee3..00000000 --- a/crates/mehen-java-parser/src/hooks.rs +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Hand-written Rust port of the upstream `JavaParserBase` helper class. -//! -//! The vendored grammar declares `superClass = JavaParserBase` and calls two -//! of its predicates (`this.IsNotIdentifierAssign()`, -//! `this.DoLastRecordComponent()`). `grammar/patterns.toml` lowers both to -//! typed hooks, and this module supplies the exact semantics — a line-for-line -//! port of `java/java/Java/JavaParserBase.java` from `antlr/grammars-v4` (the -//! commit pinned in `grammar/PROVENANCE.md`). -//! -//! Construct the parser with [`JavaParserBase`] installed: -//! -//! ```ignore -//! let mut parser = JavaParser::with_typed_hooks(tokens, JavaParserBase); -//! ``` -//! -//! The generated modules are produced with `--sem-unknown error`, so a parser -//! built *without* these hooks (e.g. via `JavaParser::new`) fails loud with -//! `AntlrError::Unsupported` the moment an input reaches either predicate — -//! it never silently mis-parses. - -use antlr4_runtime::{ParserSemCtx, TokenSource}; - -use crate::java_lexer::{ - ASSIGN, ELLIPSIS, EXPORTS, IDENTIFIER, MODULE, OPEN, OPENS, PERMITS, PROVIDES, RECORD, - REQUIRES, SEALED, TO, TRANSITIVE, USES, VAR, WHEN, WITH, YIELD, -}; -use crate::java_parser::{JavaParserHooks, RULE_RECORD_COMPONENT, RULE_RECORD_COMPONENT_LIST}; - -/// Rust port of the upstream `JavaParserBase` (see module docs). Stateless: -/// both predicates read only the token stream and the in-flight rule context. -#[derive(Clone, Copy, Debug, Default)] -pub struct JavaParserBase; - -/// Token types that can begin the `identifier` parser rule — `IDENTIFIER` -/// plus every contextual keyword the grammar folds back into identifiers. -/// Mirrors the `switch` arms in the upstream `IsNotIdentifierAssign`. -const IDENTIFIER_LIKE: [i32; 17] = [ - IDENTIFIER, MODULE, OPEN, REQUIRES, EXPORTS, OPENS, TO, USES, PROVIDES, WHEN, WITH, TRANSITIVE, - YIELD, SEALED, PERMITS, RECORD, VAR, -]; - -impl JavaParserHooks for JavaParserBase { - /// `annotationFieldValue: { this.IsNotIdentifierAssign() }? annotationValue - /// | identifier '=' annotationValue` - /// - /// True unless the lookahead is ` =`, steering named - /// annotation arguments (`@Foo(bar = 1)`) to the explicit - /// `identifier '=' annotationValue` alternative instead of parsing - /// `bar = 1` as an assignment *expression*. - fn is_not_identifier_assign(&mut self, ctx: &mut ParserSemCtx<'_, L>) -> bool - where - L: TokenSource, - { - if !IDENTIFIER_LIKE.contains(&ctx.la(1)) { - return true; - } - ctx.la(2) != ASSIGN - } - - /// `recordComponentList: recordComponent (',' recordComponent)* - /// { this.DoLastRecordComponent() }?` - /// - /// False when a varargs component is followed by another component, - /// rejecting `record R(int... xs, int y)` at parse time (only the last - /// record component may be `...`), as `javac` does. - fn do_last_record_component(&mut self, ctx: &mut ParserSemCtx<'_, L>) -> bool - where - L: TokenSource, - { - // Upstream guards `getContext() instanceof RecordComponentListContext` - // and accepts otherwise; an absent context (speculative prediction - // outside the rule) is the same "unexpected state" and also accepts. - let Some(context) = ctx.context() else { - return true; - }; - if context.rule_index() != RULE_RECORD_COMPONENT_LIST { - return true; - } - let storage = ctx.parse_tree_storage(); - let tokens = ctx.token_store(); - let mut components = context - .child_rules(storage, tokens, RULE_RECORD_COMPONENT) - .peekable(); - while let Some(component) = components.next() { - // `rc.ELLIPSIS() != null` upstream: the `...` terminal is a direct - // child of `recordComponent` (`annotation* typeType (annotation* - // ELLIPSIS)? identifier`), so only non-last components matter. - if components.peek().is_some() && component.has_token(ELLIPSIS) { - return false; - } - } - true - } -} diff --git a/crates/mehen-java-parser/src/lib.rs b/crates/mehen-java-parser/src/lib.rs deleted file mode 100644 index 12da24b7..00000000 --- a/crates/mehen-java-parser/src/lib.rs +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-java-parser` — ANTLR-generated Java lexer and parser. -//! -//! This crate holds **only** the machine-generated Java lexer/parser produced -//! from the community-maintained grammars-v4 Java grammar -//! (`antlr/grammars-v4`, vendored in `grammar/`) running on the -//! [`antlr4_runtime`] Rust runtime. It carries no mehen-specific logic and no -//! dependency on `mehen-core`, so it can be consumed on its own — e.g. -//! `mehen-java-parser = { git = "https://github.com/ophi-dev/mehen", tag = "…" }` -//! — the same way this repo consumes the ruff/oxc/sqruff parser crates. -//! -//! (Linked to the repository, not docs.rs: the analyzer crates are -//! `publish = false`, so they have no docs.rs page to link to.) -//! -//! The [`mehen-java`](https://github.com/ophi-dev/mehen/tree/main/crates/mehen-java) analyzer crate depends on -//! this one and walks the resulting [`antlr4_runtime::ParseTree`] to compute -//! metrics. -//! -//! ## Regenerating — never hand-edit -//! -//! The modules are produced by `cargo xtask antlr generate java` from the -//! vendored grammar and checked in verbatim (see `src/generated/README.md` -//! and `grammar/PROVENANCE.md`). `cargo xtask antlr check-generated` guards -//! against drift in CI. -//! -//! ## Semantic predicates — construct with hooks -//! -//! The grammar declares `superClass = JavaParserBase` and calls two of its -//! predicates. [`hooks::JavaParserBase`] is the exact Rust port; install it -//! with `JavaParser::with_typed_hooks` (as the quickstart below does). The -//! modules are generated under `--sem-unknown error`, so a parser built -//! *without* hooks (`JavaParser::new`) fails loud with -//! [`antlr4_runtime::AntlrError::Unsupported`] the moment an input reaches -//! either predicate — it never silently mis-parses. -//! -//! ## Quickstart -//! -//! The hand-rolled lexer/stream/parser setup below is deliberate: the -//! generated one-call drivers (`java_parser::parse_with_parser`, …) always -//! construct the parser hook-less via `JavaParser::new`, so this grammar -//! cannot use them until the entry points accept hooks -//! (). -//! -//! ```no_run -//! use mehen_java_parser::hooks::JavaParserBase; -//! use mehen_java_parser::java_parser::{self, JavaParser}; -//! use mehen_java_parser::java_lexer::JavaLexer; -//! use antlr4_runtime::{CommonTokenStream, InputStream}; -//! // `number_of_syntax_errors` is a `Parser`-trait method, so the trait -//! // must be in scope to call it. -//! use antlr4_runtime::Parser; -//! -//! # fn main() -> Result<(), antlr4_runtime::AntlrError> { -//! let lexer = JavaLexer::new(InputStream::new("class C {}\n")); -//! let tokens = CommonTokenStream::new(lexer); -//! // `with_typed_hooks` installs the JavaParserBase predicate port. -//! let mut parser = JavaParser::with_typed_hooks(tokens, JavaParserBase); -//! let result = parser.compilation_unit()?; -//! let errors = parser.number_of_syntax_errors(); -//! let parsed = parser.into_parsed_file(result); -//! let _ = (errors, parsed.tree()); -//! # Ok(()) -//! # } -//! ``` - -#![forbid(unsafe_code)] - -/// Re-export of the ANTLR v4 Rust runtime the generated modules were built -/// against, so downstream crates can name the runtime types (`ParseTree`, -/// `Node`, `TokenView`, …) without pinning the runtime version themselves. -pub use antlr4_runtime; - -pub mod hooks; - -/// ANTLR-generated Java lexer. -/// -/// Regenerate with `cargo xtask antlr generate java` — never hand-edit. -#[path = "generated/java_lexer.rs"] -pub mod java_lexer; - -/// ANTLR-generated Java parser. -/// -/// Regenerate with `cargo xtask antlr generate java` — never hand-edit. -#[path = "generated/java_parser.rs"] -pub mod java_parser; diff --git a/crates/mehen-java-parser/tests/hooks.rs b/crates/mehen-java-parser/tests/hooks.rs deleted file mode 100644 index d91d81c7..00000000 --- a/crates/mehen-java-parser/tests/hooks.rs +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Behavioral tests for the `JavaParserBase` hook port (`src/hooks.rs`). -//! -//! Each test pins one observable consequence of a predicate so a regression -//! in the port (or a regenerate that stops routing the predicate to hooks) -//! fails here rather than silently skewing downstream metrics. - -use antlr4_runtime::{CommonTokenStream, InputStream, Parser}; -use mehen_java_parser::hooks::JavaParserBase; -use mehen_java_parser::java_lexer::JavaLexer; -use mehen_java_parser::java_parser::JavaParser; - -/// Parse a compilation unit with the hooks installed, returning the -/// recovered syntax-error count. -fn syntax_errors(source: &str) -> usize { - let lexer = JavaLexer::new(InputStream::new(source)); - let tokens = CommonTokenStream::new(lexer); - let mut parser = JavaParser::with_typed_hooks(tokens, JavaParserBase); - parser.remove_error_listeners(); - let _ = parser - .compilation_unit() - .expect("entry rule must not hard-fail"); - parser.number_of_syntax_errors() -} - -#[test] -fn named_annotation_arguments_parse_cleanly() { - // `IsNotIdentifierAssign` steers `key = value` pairs to the explicit - // `identifier '=' annotationValue` alternative. - let src = "@interface Foo { int bar() default 0; }\n@Foo(bar = 1)\nclass C {}\n"; - assert_eq!(syntax_errors(src), 0); -} - -#[test] -fn contextual_keyword_annotation_argument_parses_cleanly() { - // The identifier-like set includes contextual keywords (`module`, `yield`, - // `record`, …): `@Foo(record = 1)` must take the named-argument alternative - // exactly like a plain identifier. - let src = "@interface Foo { int record() default 0; }\n@Foo(record = 1)\nclass C {}\n"; - assert_eq!(syntax_errors(src), 0); -} - -#[test] -fn positional_annotation_argument_parses_cleanly() { - // Lookahead that is not ` =` keeps the predicate true, so - // a single positional value still parses via `annotationValue`. - let src = "@interface Foo { int value() default 0; }\n@Foo(41 + 1)\nclass C {}\n"; - assert_eq!(syntax_errors(src), 0); -} - -#[test] -fn trailing_varargs_record_component_parses_cleanly() { - // `DoLastRecordComponent` accepts `...` on the LAST component. - let src = "record R(int x, int... ys) {}\n"; - assert_eq!(syntax_errors(src), 0); -} - -#[test] -fn non_trailing_varargs_record_component_is_rejected() { - // …and rejects `...` on a non-last component, as `javac` does. Without - // the hook (old assume-true builds) this parsed cleanly. - let src = "record R(int... xs, int y) {}\n"; - assert!( - syntax_errors(src) > 0, - "varargs before the last record component must be a syntax error" - ); -} - -#[test] -fn hookless_parser_fails_loud_on_hooked_predicate() { - // The generated modules carry `--sem-unknown error`: a parser built - // without hooks must surface `AntlrError::Unsupported` when an input - // reaches a hooked predicate — never silently assume it true. - let lexer = JavaLexer::new(InputStream::new("@Foo(bar = 1) class C {}\n")); - let tokens = CommonTokenStream::new(lexer); - let mut parser = JavaParser::new(tokens); - parser.remove_error_listeners(); - assert!( - parser.compilation_unit().is_err(), - "hook-less parse must fail loud, not mis-parse" - ); -} diff --git a/crates/mehen-java/Cargo.toml b/crates/mehen-java/Cargo.toml deleted file mode 100644 index dc8ad3ba..00000000 --- a/crates/mehen-java/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "mehen-java" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — Java language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -# The generated Java lexer/parser now live in the standalone, publishable -# `mehen-java-parser` crate (produced by `cargo xtask antlr generate java`). -# This analyzer depends on it for the grammar and reaches the ANTLR runtime -# through its `antlr4_runtime` re-export. -mehen-java-parser = { workspace = true } -# `mehen-antlr` owns the runtime version pin and the shared span/comment/ -# diagnostic helpers; the walker reaches the runtime types (`Node`, -# `RuleNodeView`, `TokenView`, …) through its `runtime` re-export. -mehen-antlr = { workspace = true } -smol_str = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-java/src/lib.rs b/crates/mehen-java/src/lib.rs deleted file mode 100644 index 0768ae9f..00000000 --- a/crates/mehen-java/src/lib.rs +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-java` — Java language analyzer. -//! -//! Java is parsed by a parser generated from the community-maintained -//! **grammars-v4 Java grammar** (`antlr/grammars-v4`, vendored in `grammar/`) -//! running on the ANTLR Rust runtime via [`mehen_antlr`]. The grammar covers -//! modern Java (records, sealed types, switch expressions, text blocks, -//! pattern matching, modules), giving the metric walker a semantically-named -//! CST (`classDeclaration`, `methodDeclaration`, `recordDeclaration`, -//! `switchExpression`, `lambdaExpression`, …). -//! -//! The generated lexer/parser modules live in [`generated`]; they are -//! produced by `cargo run -p xtask -- antlr generate java` and checked in -//! verbatim (see `src/generated/README.md`). They are not hand-edited and are -//! self-contained generated modules with their own lint and formatting -//! attributes. -//! -//! Metric coverage follows SonarJava's definitions where they exist; see -//! [`walker`] for the per-metric table. - -#![forbid(unsafe_code)] - -mod walker; - -use mehen_antlr::DiagnosticCollector; -use mehen_antlr::runtime::{CommonTokenStream, InputStream, ParsedFile}; -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, LineIndex, - ParseDiagnostic, Result, SourceFile, SourceSpan, byte_offset_clamped, -}; - -use mehen_java_parser::hooks::JavaParserBase; -use mehen_java_parser::java_lexer::JavaLexer; -use mehen_java_parser::java_parser::JavaParser; -use mehen_metrics::MetricEvidence; - -pub struct JavaAnalyzer; - -/// A recovered parse: the flat-arena [`ParsedFile`] owns the token store and -/// CST storage, and the walker borrows [`Node`](mehen_antlr::runtime::Node) -/// views from it. `loc_tokens` is precomputed from the (eagerly buffered, -/// hidden-channel-inclusive) token store. -struct ParsedJava { - parsed: ParsedFile, - lexer_diagnostics: Vec, - loc_tokens: Vec, -} - -impl JavaAnalyzer { - pub fn new() -> Self { - Self - } - - /// Parse `source` via the single `compilationUnit` entry rule and return - /// the recovered [`ParsedFile`] plus the source-ordered LOC token list. - /// Returns `None` only if the rule call hard-fails (returns `Err` rather - /// than a recovered tree). - /// - /// The parser is constructed with the [`JavaParserBase`] typed hooks — the - /// exact port of the grammar's `superClass` predicates. The generated - /// modules use `--sem-unknown error`, so a hook-less parser would hard-fail - /// (not mis-parse) on inputs reaching those predicates. - /// - /// Replaces the runtime's default lexer console listener with a structured - /// diagnostic collector and removes the parser console listener. - /// - /// Unlike the Kotlin and C# analyzers, this driver is hand-rolled instead - /// of going through the generated `parse_with_parser` (runtime 0.33): the - /// generated entry points always construct the parser hook-less via - /// `JavaParser::new`, so a `superClass` grammar cannot install its typed - /// hooks through them. Tracked upstream as - /// ; fold this - /// onto the generated driver once the entry points accept hooks. - fn parse(&self, source: &str, line_index: &LineIndex) -> Option { - let mut lexer = JavaLexer::new(InputStream::new(source)); - lexer.remove_error_listeners(); - let lexer_diagnostics = DiagnosticCollector::default(); - lexer.add_error_listener(lexer_diagnostics.clone()); - let tokens = CommonTokenStream::new(lexer); - let mut parser = JavaParser::with_typed_hooks(tokens, JavaParserBase); - parser.remove_error_listeners(); - let result = parser.compilation_unit().ok()?; - let lexer_diagnostics = lexer_diagnostics.diagnostics("java.syntax_error", 16, line_index); - - // `into_parsed_file` consumes the parser and moves the eagerly-buffered - // token store into the `ParsedFile`; the LOC token list is then read - // straight from that store (all channels, so hidden-channel comments - // are present — no `fill()` step needed). - let parsed = parser.into_parsed_file(result); - let loc_tokens = collect_loc_tokens(&parsed, line_index); - Some(ParsedJava { - parsed, - lexer_diagnostics, - loc_tokens, - }) - } -} - -impl Default for JavaAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for JavaAnalyzer { - fn language(&self) -> Language { - Language::Java - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::Antlr - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - let line_index = LineIndex::new(&source.text); - - let parsed = match self.parse(&source.text, &line_index) { - Some(parsed) => parsed, - None => { - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: line_index.line_count(), - }; - return Ok(LanguageAnalysis { - language: Language::Java, - backend: AnalysisBackend::Antlr, - diagnostics: vec![ParseDiagnostic::fatal( - "java.parse_error", - "java ANTLR parse failed".to_string(), - )], - root: mehen_antlr::empty_space(span), - contributions: Vec::new(), - }); - } - }; - - // The `ParsedFile` owns the token store and CST; `tree()` is the root - // `Node` borrowing view the walker traverses. Contribution evidence is - // recorded into the walker-threaded sink (plan §5.4); a benchmark - // profile disables it without changing any metric. - let tree = parsed.parsed.tree(); - let mut evidence = MetricEvidence::new("java", config.emit_contributions); - let root = walker::walk( - tree, - &line_index, - source.text.len(), - &parsed.loc_tokens, - &mut evidence, - ); - - // Recovered ANTLR error nodes are surfaced as `error` so the - // diagnostic contract treats the analysis as incomplete. - let mut diagnostics = parsed.lexer_diagnostics; - let remaining = 16usize.saturating_sub(diagnostics.len()); - diagnostics.extend(mehen_antlr::collect_errors( - tree, - "java.syntax_error", - remaining, - &line_index, - )); - - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::Java, - backend: AnalysisBackend::Antlr, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} - -/// Classify the parsed file's token store into the source-ordered LOC token -/// list that drives the LOC family. Java comments are `COMMENT` (block, may -/// span lines) and `LINE_COMMENT`; whitespace is `WS`. Unlike Kotlin, Java -/// has no string-mode comment tokens and no trivia-folding operator tokens -/// (annotations are a plain `AT` token followed by a name), so no -/// trivia-bearing token scan is needed. The token store is eagerly buffered -/// through EOF, so every token (all channels) is present. -fn collect_loc_tokens(parsed: &ParsedFile, line_index: &LineIndex) -> Vec { - use mehen_java_parser::java_lexer::{COMMENT, LINE_COMMENT, WS}; - - mehen_antlr::loc_tokens( - // Since the 0.15 runtime `&TokenStore` is `IntoIterator` (issue #123), - // so the eagerly-buffered store feeds the LOC sweep directly — no - // hand-rolled index loop. - parsed.tokens(), - &[COMMENT, LINE_COMMENT], - &[WS], - &[], - line_index, - ) -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, Language, SourceFile, SpaceKind}; - - fn analyze(source: &str, path: &str) -> LanguageAnalysis { - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new(path.into(), Language::Java, source.to_string()); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() - } - - #[test] - fn empty_file_yields_root_unit() { - let a = analyze("", "Empty.java"); - assert_eq!(a.root.kind, SpaceKind::Unit); - assert!(a.root.spaces.is_empty()); - } - - #[test] - fn class_with_method_parses_cleanly() { - let src = "package demo;\n\nclass C {\n int m() { return 1; }\n}\n"; - let a = analyze(src, "C.java"); - assert!( - a.diagnostics.is_empty(), - "compilation unit should parse cleanly, got {}", - a.diagnostics.len() - ); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("C")); - } - - #[test] - fn recovered_error_nodes_carry_byte_spans() { - // Since the 0.19 runtime the offending token reaches the diagnostic - // path (upstream #196), so a recovered parse error must report a real - // byte range rather than only a line number in its message. - let src = "class C {\n void m() { int x = @@@; }\n}\n"; - let a = analyze(src, "C.java"); - let spanned: Vec<_> = a - .diagnostics - .iter() - .filter_map(|d| d.span.as_ref()) - .collect(); - assert!( - !spanned.is_empty(), - "recovered error nodes should carry spans, got {:?}", - a.diagnostics - ); - for span in spanned { - assert!( - span.end_byte > span.start_byte, - "span must be non-empty: {span:?}" - ); - assert!( - (span.end_byte as usize) <= src.len(), - "span must stay inside the source: {span:?}" - ); - assert_eq!(span.start_line, 2, "the bad token is on line 2"); - } - } -} diff --git a/crates/mehen-java/src/walker.rs b/crates/mehen-java/src/walker.rs deleted file mode 100644 index ceea8450..00000000 --- a/crates/mehen-java/src/walker.rs +++ /dev/null @@ -1,2518 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ANTLR-based Java metric walker. -//! -//! Drives a recursive descent over the ANTLR `ParseTree` (entry rule -//! `compilationUnit`) and produces a populated [`MetricSpace`]. The structure -//! mirrors the `mehen-kotlin` walker — one [`State`] per space, -//! finalize-and-merge on close, with the parent-less ANTLR tree handled by -//! threading context **top-down**. -//! -//! ## Grammar shape (vs Kotlin) -//! -//! The grammars-v4 Java grammar differs from the Kotlin spec grammar in two -//! ways that shape every classification here: -//! -//! - **Control flow is not separate named rules.** `if`/`for`/`while`/`do`/ -//! `switch`/`try`/`return`/`throw`/`break`/`continue`/`yield` are all -//! *alternatives of the single `statement` rule*, discriminated by a leading -//! keyword token (`IF`, `FOR`, …) that is a direct child of the `statement` -//! context. So the walker inspects `statement` tokens rather than matching a -//! distinct `RULE_IF_EXPRESSION`-style index. -//! - **Operators are not separate named rules.** All binary/ternary operators -//! are alternatives of the single `expression` rule (labeled alternatives -//! that ANTLR's Rust target flattens into one `RULE_EXPRESSION` context), so -//! short-circuit `&&`/`||`, comparisons, and the ternary `?` are detected by -//! scanning the operator *tokens* that are direct children of an -//! `expression` context. -//! -//! ## Metric coverage (SonarJava-aligned) -//! -//! - **Cyclomatic**: `if`, every loop (`for`/`while`/`do`), each `case` -//! label, the ternary `?`, and each short-circuit `&&`/`||`. `catch`, -//! `switch` itself, and `default` are not decisions (matches SonarJava's -//! cyclomatic; `catch` counts only in cognitive). -//! - **Cognitive**: nesting on `if`, loops, `switch` (statement *and* -//! expression), `catch`, and the ternary; flat `+1` on `else`/`else if` and -//! on labeled `break`/`continue`; a *parent-relative* boolean-run collapse on -//! `&&`/`||` (a boolean node adds `+1` only when its operator differs from -//! its enclosing boolean operator, matching SonarSource's tree-based rule). -//! - **ABC**: assignments via `=`, compound-assign, and `++`/`--` operators and -//! via any initialized declarator (`variableDeclarator`/`fieldDeclaration`, -//! `var x = e`, try-with-resources `T r = e`); branches via every -//! `methodCall` and object creation (`new`); conditions via -//! `if`/`case`/`catch`/loops/comparison & equality/`&&`/`||`/ternary/ -//! `instanceof` (bit-shifts `<<`/`>>`/`>>>` are excluded — they are not -//! relational). -//! - **NExit**: `return` and `throw` statements. -//! - **NArgs**: `formalParameter` count for methods/constructors; -//! `lambdaParameters` count for lambdas. -//! - **NOM**: every `methodDeclaration`, `constructorDeclaration`, -//! `compactConstructorDeclaration`, `interfaceMethodDeclaration`, -//! `annotationMethodRest` is a function space; every `lambdaExpression` is a -//! closure-shaped function space. -//! - **LOC**: PLOC from per-space code-token rows during the walk, LLOC from -//! statement/declaration-shaped rules, CLOC from a source-ordered pass over -//! the hidden-channel comment tokens routed via `SpaceRangeTracker`. -//! - **Halstead**: per-token operator/operand classification — keywords and -//! punctuation are operators; identifiers, literals, `this`, `super` are -//! operands (deduped by text). -//! - **NPA / NPM / WMC**: class-vs-interface routing by the type-declaration -//! keyword. NPA counts `fieldDeclaration` variables (and `recordComponent`s) -//! directly under a class/interface body. NPM counts methods/constructors -//! (including generic ` …` members) directly under a class/interface body. -//! Java visibility: a class member with no access modifier is -//! package-private (NOT public), so only an explicit `public` counts toward -//! NPA/NPM; interface/annotation members are implicitly public. - -use mehen_antlr::runtime::token::Token; -use mehen_antlr::runtime::{FromRuleNode, Node, RuleNodeView, TerminalNodeView}; -use mehen_antlr::{LocToken, LocTokenKind, ctx_span, span_from_tokens}; -use mehen_core::{LineIndex, MetricSpace, SourceSpan, SpaceKind}; -use mehen_metrics::{ - ContainerKind, HalsteadOperand, HalsteadOperator, MetricEvidence, MetricTreeBuilder, - SpaceRangeTracker, State, apply_state_to, finalize_state, merge_child_into_parent, -}; -use smol_str::SmolStr; - -use mehen_java_parser::java_lexer as jl; -use mehen_java_parser::java_parser as jp; - -/// Drive the walk over the parsed `compilationUnit` tree and return the unit -/// `MetricSpace`. LOC is computed from `loc_tokens` in a single ordered pass -/// *after* the tree walk has opened and closed every space. Contribution -/// evidence is recorded into the caller-owned `evidence` sink (plan §5.4); -/// every record is a no-op when the sink is disabled. -pub(crate) fn walk( - tree: Node<'_>, - line_index: &LineIndex, - source_len: usize, - loc_tokens: &[LocToken], - evidence: &mut MetricEvidence, -) -> MetricSpace { - let unit_span = match tree.as_rule() { - Some(rule) => ctx_span(rule, line_index, source_len), - None => mehen_core::SourceSpan::empty(), - }; - - let mut unit_state = State::new(); - unit_state - .loc - .set_span(0, line_index.line_count().saturating_sub(1), true); - - let mut walker = Walker { - line_index, - source_len, - tree: MetricTreeBuilder::new(unit_span), - stack: vec![unit_state], - kinds: vec![SpaceKind::Unit], - suppress_parent_wmc: vec![false], - cognitive: CognitiveContext::default(), - loc_routing: SpaceRangeTracker::new(), - evidence, - }; - - if let Some(rule) = tree.as_rule() { - for child in rule.children() { - walker.visit(child, ChildHint::default()); - } - } - - let mut unit_state = walker.stack.pop().expect("walker stack underflow"); - - // CLOC pass: route each comment to the deepest enclosing space (or the - // unit) in source order (mirrors `mehen-kotlin`/`mehen-python`). - for t in loc_tokens { - if t.kind == LocTokenKind::Comment { - walker.loc_routing.observe_comment( - t.start_byte, - t.end_byte, - &mut unit_state.loc, - t.start_row, - t.end_row, - ); - } - } - - finalize_state(&mut unit_state); - - let mut root = walker.tree.finish(); - let mut unit_halstead = std::mem::take(&mut unit_state.halstead); - let mut unit_loc = std::mem::take(&mut unit_state.loc); - walker - .loc_routing - .finalize_into_tree(&mut root, &mut unit_halstead, &mut unit_loc); - unit_state.halstead = unit_halstead; - unit_state.loc = unit_loc; - apply_state_to(unit_state, &mut root.metrics); - root -} - -/// Per-frame cognitive context — the `(nesting, depth, lambda)` triple used -/// exactly as the Kotlin walker uses it. -#[derive(Clone, Copy, Debug, Default)] -struct CognitiveContext { - nesting: u32, - depth: u32, - lambda: u32, -} - -/// Context threaded *down* into a child during the walk (ANTLR contexts have -/// no parent pointer). -#[derive(Clone, Copy, Debug, Default)] -struct ChildHint { - /// This `statement` is the `else`-branch body of an enclosing `if` - /// statement. An `if` reached through this hint is an `else if` and must - /// not add cognitive nesting (only the flat `else` +1 applies). - is_else_branch: bool, - /// This node is a direct member position of the enclosing class/interface - /// body, so NPA/NPM should consider it. - in_class_member: bool, - /// The container kind of the enclosing class-like body, so a member's - /// counters route to class-vs-interface buckets and inherit the - /// interface-default-public rule. - member_container: Option, - /// The member's resolved visibility, captured at the body-declaration - /// wrapper (`classBodyDeclaration: modifier* memberDeclaration`) where the - /// `modifier`s are siblings of the declaration — the declaration itself - /// has no parent pointer and does not carry them. `None` outside a member - /// position. - member_is_public: Option, - /// The immediately-enclosing short-circuit boolean operator (`&&` / `||`), - /// threaded down through `expression` descendants (transparent parens - /// included) so the cognitive boolean-run counter fires only at the ROOT of - /// a logical-operator tree. A `&&`/`||` node whose `parent_bool_op` is - /// `None` is a run root: it flattens its whole subtree in source order and - /// counts +1 per operator-kind change (SonarSource's rule). A nested - /// `&&`/`||` reached as a logical operand has `parent_bool_op == Some(_)` - /// and is consumed by the root's flatten, so it does not count again. - /// Threading resets to `None` at any non-`expression`/`primary` boundary — - /// statement, `arguments`, `methodCall`, a comparison/ternary expression — - /// which isolates independent boolean expressions. `None` outside one. - parent_bool_op: Option, - /// This node is (within) a `for` statement's `forControl` header, so a - /// `localVariableDeclaration` reached through it is the loop initializer, - /// not a standalone statement — it must not add its own LLOC (the `for` - /// statement already contributes the single header logical line). - in_for_init: bool, - /// This terminal is the token of an `identifier`/`typeIdentifier` rule. - /// Java's contextual keywords (`record`, `var`, `yield`, `sealed`, - /// `permits`, `module`, …) lex as dedicated token types but are - /// identifiers in name position, so a terminal reached through this hint is - /// a Halstead *operand* regardless of its token type (mirrors the Kotlin - /// walker's `simpleIdentifier` handling). - in_identifier: bool, - /// We are inside a constant-specific enum-constant body - /// (`enum E { A { … } }`), which opens no metric space of its own. Its - /// members belong to `A`'s anonymous subclass, not the lexically-enclosing - /// enum, so their `classBodyDeclaration`s must NOT seed `in_class_member` - /// (NPA/NPM) and their methods must NOT roll into the enum's WMC. Cleared - /// once a *real* nested class-like declaration opens its own space (its - /// members belong to that class). Mirrors the Kotlin walker's - /// `in_anon_body`. - in_anon_body: bool, - /// The enclosing record's component count, threaded down from - /// `recordDeclaration`. A *compact* constructor (`record R(int x) { R {} }`) - /// has no `formalParameters` node — its parameter list *is* the record's - /// components — so its NArgs must come from this count. `None` outside a - /// record. - record_component_count: Option, - /// The enclosing record's own visibility, threaded down from - /// `recordDeclaration`. Java gives a modifier-less *compact* canonical - /// constructor (`public record R(int x) { R {} }`) the record's access - /// level, but the compact ctor is reached directly under the modifier-less - /// `recordBody`, so the ambient `member_is_public` there is always `false`. - /// A compact ctor with no explicit modifier falls back to this instead. - /// `None` outside a record. - enclosing_record_public: Option, - /// The 0-based start line of the enclosing member's body-declaration - /// wrapper (`classBodyDeclaration: modifier* memberDeclaration`), threaded - /// down so a method/constructor space can widen its span upward to cover - /// its own-line modifiers/annotations. In the grammars-v4 Java grammar the - /// `modifier`s (including annotations) are SIBLINGS of the declaration on - /// the wrapper, so the declaration's own `ctx_span` starts *after* them — - /// leaving `@Deprecated\npublic void m() {}`'s annotation row attributed to - /// the enclosing class. The wrapper's start line is where the declaration - /// truly begins. Carries the wrapper's `(start_byte, start_line)` so the - /// method space widens both its LOC span (row attribution) and its - /// comment-routing byte range. `None` outside a member position. - member_decl_start: Option<(u32, u32)>, - /// This method/constructor declaration's function space was already opened - /// by its enclosing body-declaration wrapper (so the wrapper's own-line - /// modifiers/annotations are visited *inside* the method space, giving the - /// method correct Halstead/PLOC/span). The declaration node must therefore - /// NOT open a second space of its own. - space_opened_by_wrapper: bool, - /// We are inside an `annotation` (`@Ann(value = 1)`). Annotation values are - /// compile-time metadata, not executable code, so ABC assignment - /// accounting must be suppressed here: the grammar's `IsNotIdentifierAssign` - /// predicate (which would parse `value = 1` as `identifier '=' …` rather - /// than an assignment expression) is dropped by the Rust generator, so a - /// named element value otherwise reaches the `RULE_EXPRESSION` assignment - /// arm with an `=` token and inflates ABC. - in_annotation: bool, -} - -/// A short-circuit boolean operator, for parent-relative cognitive -/// boolean-run collapse. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum BoolOp { - And, - Or, -} - -struct Walker<'a> { - line_index: &'a LineIndex, - source_len: usize, - tree: MetricTreeBuilder, - stack: Vec, - kinds: Vec, - /// Parallel to `stack`/`kinds`: whether the closing function space must - /// NOT contribute its cyclomatic to the parent's WMC. Set for functions - /// opened inside a constant-specific enum-constant body — that body opens - /// no space of its own, so the function closes with the *enum* as parent, - /// but it belongs to the constant's anonymous subclass, not the enum. - suppress_parent_wmc: Vec, - cognitive: CognitiveContext, - loc_routing: SpaceRangeTracker, - /// Contribution-evidence sink (plan §5.4). Owned by the analyzer; - /// disabled sinks make every record call a no-op, and span conversion - /// is skipped entirely on the disabled path. - evidence: &'a mut MetricEvidence, -} - -impl Walker<'_> { - fn current(&mut self) -> &mut State { - self.stack.last_mut().expect("walker stack empty") - } - - /// Record contribution evidence for `ctx`'s covered span. The span is - /// converted only when the sink is enabled so the disabled (benchmark) - /// path pays nothing beyond the flag check. - fn record_evidence( - &mut self, - ctx: RuleNodeView<'_>, - f: impl FnOnce(&mut MetricEvidence, SourceSpan), - ) { - if self.evidence.is_enabled() { - let span = ctx_span(ctx, self.line_index, self.source_len); - f(&mut *self.evidence, span); - } - } - - /// Span of the first direct terminal child of `ctx` with `token_type` - /// (e.g. the `ELSE` keyword of an `if` statement), if present. Gives - /// keyword-level evidence a tighter span than the whole statement. - fn first_token_span(&self, ctx: RuleNodeView<'_>, token_type: i32) -> Option { - ctx.children().find_map(|child| { - child - .as_terminal() - .filter(|t| t.symbol().token_type() == token_type) - .map(|t| { - span_from_tokens(&t.symbol(), &t.symbol(), self.line_index, self.source_len) - }) - }) - } - - fn visit(&mut self, node: Node<'_>, hint: ChildHint) { - if let Some(rule) = node.as_rule() { - self.visit_rule(rule, hint); - } else if let Some(term) = node.as_terminal() { - self.visit_terminal(term, hint); - } - // Error leaves carry no metric contribution; they are surfaced as - // diagnostics by `mehen_antlr::collect_errors` in the analyzer. - } - - fn visit_terminal(&mut self, term: TerminalNodeView<'_>, hint: ChildHint) { - let tt = term.symbol().token_type(); - - // Halstead operator/operand token classification. A terminal reached - // through an `identifier`/`typeIdentifier` rule is always an operand — - // this covers Java's contextual keywords (`record`, `var`, `yield`, …) - // used as names, which carry dedicated token types but are identifiers - // here. - let class = if hint.in_identifier { - HalsteadClass::Operand - } else { - halstead_class(tt) - }; - match class { - HalsteadClass::Operator => { - self.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(kp_token_name(tt)), - text: None, - }); - } - HalsteadClass::Operand => { - let text = term.symbol().text_or_empty(); - self.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(SmolStr::new(text)), - }); - } - HalsteadClass::Skip => {} - } - - // PLOC: a visible code token's start row is a code line, recorded into - // the current space during the AST walk. Comments are hidden-channel - // (routed after the walk), and EOF (`tt < 0`) is not code. - // - // A single visible token can span multiple physical lines — a Java - // text block (`"""…"""`, `TEXT_BLOCK`) is one token covering several - // rows. Record *every* row it covers as code, or the interior rows sit - // inside the enclosing span with no PLOC observation and are reported - // as phantom blank lines (`blank = sloc - ploc - only_comment`). - if tt >= 0 { - let start_row = (term.symbol().line() as u32).saturating_sub(1); - let extra_rows = term - .symbol() - .text_or_empty() - .bytes() - .filter(|&b| b == b'\n') - .count() as u32; - for row in start_row..=start_row.saturating_add(extra_rows) { - self.current().loc.observe_code_line(row); - } - } - } - - fn visit_rule(&mut self, ctx: RuleNodeView<'_>, hint: ChildHint) { - let ri = ctx.rule_index(); - let saved_cognitive = self.cognitive; - - // NPA / NPM: classify a direct member of the enclosing class/interface - // body before opening any space for this node (so the kinds stack - // still has the class on top). - // A method/constructor whose space was already opened by its wrapper - // had its NPM recorded there (into the class, before the space opened); - // skip re-classifying here (this node now sits inside the method space, - // so it would misroute NPM into the method). - if hint.in_class_member - && !hint.space_opened_by_wrapper - && let Some(container) = hint.member_container - { - let public = hint.member_is_public.unwrap_or(true); - self.classify_class_member(ctx, ri, container, public, hint); - } - - // Capture the enclosing class-like container BEFORE opening any space - // for this node. `member_propagation` (run inside `visit_children`, - // after the open) resolves a member's container/visibility from the - // stack — but a body-declaration wrapper may now open a nested type - // space here (round 29), so `self.enclosing_container()` would then see - // that just-opened type instead of the real enclosing scope. Passing - // the pre-open container keeps interface/annotation member visibility - // correct (e.g. an interface-nested record's compact ctor stays public). - let container_before_open = self.enclosing_container(); - - let opened = self.maybe_open_space(ctx, ri, hint); - self.classify_rule(ctx, ri, hint); - - self.visit_children(ctx, ri, hint, container_before_open); - - if opened { - self.close_space(); - } - self.cognitive = saved_cognitive; - } - - fn visit_children( - &mut self, - ctx: RuleNodeView<'_>, - ri: usize, - hint: ChildHint, - container_before_open: Option, - ) { - // `NodeChildren` is a cheap `Clone` slice-iterator, so it is re-walked - // (below, and for the `else`/anon-body scans here) without allocating — - // the hot path avoids collecting children into a `Vec` for every node. - - // For an `if` statement, the `else`-branch body is the `statement` - // that appears after the `ELSE` token. Tag it so an `if` reached - // through it (without an intervening `block`) is recognized as - // `else if` and does not add nesting. - let else_body_idx = if is_if_statement(ctx, ri) { - else_branch_index(ctx.children()) - } else { - None - }; - // `is_else_branch` also flows through a *transparent* `statement` - // wrapper so an `else if` chain is recognized even when the grammar - // nests the inner `if` under the outer statement's `else` position - // (e.g. a label wrapper `else lbl: if …`). It must NOT flow through: - // - a `block` (`else { if … }` is genuinely nested); - // - an actual `if` statement (`if` targets its else child precisely - // via `else_body_idx`; blanket propagation would wrongly stamp the - // flag onto the *then*-branch too — `else if (b) if (d) {}`); - // - any statement that introduces its OWN control-flow construct - // (`while`/`for`/`do`/`switch`/`try`/`synchronized`/…). Such a - // statement's body is a genuinely nested scope, not an else-if — so - // an `if` in an `else while (c) if (b) {}` loop body must keep its - // nesting increment. - let propagate_else = hint.is_else_branch && statement_is_else_transparent(ctx, ri); - - // Class/interface body member positions originate at - // `classBodyDeclaration` / `interfaceBodyDeclaration`, then flow - // through the transparent `memberDeclaration` / - // `interfaceMemberDeclaration` wrappers to the real member rule. The - // visibility is resolved here (the body-declaration level) because the - // `modifier`s are siblings of the member declaration, not its - // children. - let (propagate_member, member_container, member_is_public) = - self.member_propagation(ctx, ri, hint, container_before_open); - - // Capture the member's body-declaration wrapper start line so a - // method/constructor space can widen its span upward to cover its - // own-line modifiers/annotations (siblings of the declaration on the - // wrapper). Set at the wrapper that opens the member position; a - // transparent wrapper inherits it; a nested class/function resets it - // (its members' spans are computed from their own wrappers). Cleared - // once a space actually opens so an inner declaration doesn't reuse an - // outer member's start. - let member_decl_start = if is_member_body_wrapper(ri) { - let span = ctx_span(ctx, self.line_index, self.source_len); - Some((span.start_byte, span.start_line)) - } else if opens_class_like(ri) || opens_function_space(ri) { - None - } else { - hint.member_decl_start - }; - - // Thread the enclosing boolean operator down through `expression` - // descendants for the parent-relative cognitive boolean-run collapse. - // - // - A boolean `expression` (`&&`/`||`) sets the operator for its - // operands. - // - A *transparent* `expression` — one that carries NO operator token - // of its own (a bare operand: `a`, or a single sub-expression) — and - // a `primary` (`'(' expression ')'`) forward the enclosing operator, - // so `a && (b && c)` and `(a && b) && c` collapse into one run. - // - Any expression that introduces its OWN operator other than - // `&&`/`||` — equality (`==`), comparison, ternary (`? :`), index - // (`[]`), unary, `instanceof`, a method call, etc. — is a distinct - // boolean context and RESETS the run (`None`), so a `&&` nested - // inside `(b && c) == d` is not wrongly collapsed with an outer `&&`. - // - Every other node kind also resets, isolating method-call arguments - // and nested statements from the enclosing run. - // The operator THIS node itself introduces (only a `&&`/`||` expression - // does), used both to set the operands' run operator and to place a - // predecessor for the run (its right operand follows its left). - let this_bool_op = expression_bool_op(ctx); - let child_bool_op = if ri == jp::RULE_EXPRESSION { - if this_bool_op.is_some() { - this_bool_op - } else if expression_has_operator_token(ctx) { - None - } else { - hint.parent_bool_op - } - } else if ri == jp::RULE_PRIMARY { - hint.parent_bool_op - } else { - None - }; - // A classic `for` header (`forControl → forInit → localVariableDeclaration`) - // must not let its initializer declaration add a second LLOC. Tag ONLY - // the direct children of `forInit` (the header declaration) — NOT the - // whole subtree. A sticky, subtree-wide flag would also suppress a real - // local declaration nested inside a lambda or anonymous-class body that - // lives in the initializer, e.g. - // `for (Supplier s = () -> { int x = 0; return x; }; ; ) {}` — - // the lambda body's `int x = 0;` is genuine code and must count. - // `localVariableDeclaration` is a direct child of `forInit`, so a - // non-sticky flag reaches exactly the header declaration and stops one - // level down (mirrors the per-child `anon_body_child` tagging below). - let in_for_init = ri == jp::RULE_FOR_INIT; - - // A terminal directly under `identifier`/`typeIdentifier` is a name → - // Halstead operand (covers contextual keywords used as identifiers). - let in_identifier = matches!(ri, jp::RULE_IDENTIFIER | jp::RULE_TYPE_IDENTIFIER); - - // Track whether we're inside an anonymous class body that opens no - // metric space of its own — a constant-specific enum-constant body - // (`enum E { A { … } }`) or an anonymous class expression - // (`new Runnable() { … }`, via `classCreatorRest → classBody`). Their - // members belong to the anonymous subclass, not the lexically-enclosing - // class/enum, so they must not seed NPA/NPM or roll into its WMC. - // - // The anon body is ONLY the `classBody` child of `classCreatorRest` / - // `enumConstant` — NOT their sibling `arguments`/`identifier`. Tagging - // the whole node would wrongly suppress a lambda passed as a plain - // constructor argument (`new Foo(() -> …)`), resetting its cognitive - // depth. So the trigger is applied per-child below (only the - // `classBody`); here we just propagate the inbound flag, CLEARING it - // once a real nested class-like or a function space opens (the latter - // so a lambda inside the anon body's direct method still inherits the - // method's depth). The method's own NPA/NPM/WMC suppression is captured - // from its inbound hint before its children are visited. - let anon_body_child = if matches!(ri, jp::RULE_ENUM_CONSTANT | jp::RULE_CLASS_CREATOR_REST) - { - child_index_of_rule(ctx.children(), jp::RULE_CLASS_BODY) - } else { - None - }; - let in_anon_body = if opens_class_like(ri) || opens_function_space(ri) { - false - } else { - hint.in_anon_body - }; - - // Once inside an `annotation` OR an annotation element's `defaultValue`, - // stay inside for the whole subtree so annotation metadata does not - // record executable complexity (ABC assignments/conditions, cyclomatic - // decisions, cognitive nesting). Two entry points: a use-site annotation - // (`@Ann(value = 1)`, `RULE_ANNOTATION`) and an element default - // (`@interface A { boolean v() default true && false; }`, parsed under - // `annotationMethodRest → defaultValue → elementValue → expression`, NOT - // under `RULE_ANNOTATION`). - let in_annotation = - hint.in_annotation || ri == jp::RULE_ANNOTATION || ri == jp::RULE_DEFAULT_VALUE; - - // Thread the record's component count down so a compact constructor - // (which has no `formalParameters`) can report the components as its - // NArgs. Set on entering `recordDeclaration`; a nested type resets it - // (a nested class/record's members are not this record's components). - let record_component_count = if ri == jp::RULE_RECORD_DECLARATION { - Some(count_record_components(ctx)) - } else if opens_class_like(ri) { - None - } else { - hint.record_component_count - }; - - // Thread the enclosing record's visibility down so a modifier-less - // compact canonical constructor can inherit the record's access level - // (Java rule). The record's visibility is what was resolved for the - // record declaration itself as a member (`member_is_public`, set by its - // enclosing class/type wrapper); a top-level record has no such wrapper, - // so fall back to modifiers on the record declaration. A nested type - // resets it (its own members are not this record's). - let enclosing_record_public = if ri == jp::RULE_RECORD_DECLARATION { - Some( - hint.member_is_public.unwrap_or(false) - || visibility_from_modifiers(ctx) == Some(true), - ) - } else if opens_class_like(ri) { - None - } else { - hint.enclosing_record_public - }; - - // When this wrapper opened the method OR type space itself (to capture - // own-line modifiers), tell the inner declaration to skip its own open. - // The flag flows through the transparent `memberDeclaration` / - // generic-method / `annotationTypeElementRest` wrappers to the - // declaration node, which consumes it; a real space open clears it so a - // nested declaration inside the body still opens normally. - let opened_at_wrapper = (matches!( - ri, - jp::RULE_CLASS_BODY_DECLARATION - | jp::RULE_INTERFACE_BODY_DECLARATION - | jp::RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION - ) && wrapper_inner_method(ctx).is_some()) - || (is_type_wrapper(ri) && wrapper_inner_type(ctx).is_some()); - let space_opened_by_wrapper = if opens_function_space(ri) || opens_class_like(ri) { - false - } else { - opened_at_wrapper || hint.space_opened_by_wrapper - }; - - for (idx, child) in ctx.children().enumerate() { - let mut child_hint = ChildHint::default(); - if Some(idx) == else_body_idx || propagate_else { - child_hint.is_else_branch = true; - } - child_hint.space_opened_by_wrapper = space_opened_by_wrapper; - child_hint.in_class_member = propagate_member; - child_hint.member_container = member_container; - child_hint.member_is_public = member_is_public; - child_hint.parent_bool_op = child_bool_op; - child_hint.in_for_init = in_for_init; - child_hint.in_identifier = in_identifier; - // The anon-body `classBody` child gets the suppression; its sibling - // `arguments`/`identifier` (a plain constructor call, an enum - // constant's args) do not. - let is_anon_body_child = Some(idx) == anon_body_child; - child_hint.in_anon_body = in_anon_body || is_anon_body_child; - child_hint.record_component_count = record_component_count; - child_hint.enclosing_record_public = enclosing_record_public; - child_hint.member_decl_start = member_decl_start; - child_hint.in_annotation = in_annotation; - // An anonymous class body (`new X() { … }`) is a fresh class scope - // but opens no metric space, so — unlike a named class, which - // resets via `enter_class_cognitive` in `maybe_open_space` — its - // class-body-level code (initializer blocks, field initializers) - // would otherwise inherit the enclosing statement's cognitive - // nesting. Reset the cognitive context for that subtree and restore - // it afterward (the sibling `arguments` were already visited, and - // this scopes the reset to just the anon body). - if is_anon_body_child { - let saved = self.cognitive; - self.cognitive = CognitiveContext::default(); - self.visit(child, child_hint); - self.cognitive = saved; - } else { - self.visit(child, child_hint); - } - } - } - - /// Compute the `(in_class_member, container, is_public)` hint for this - /// rule's children. Members reach their declaration through transparent - /// wrapper layers; the container comes from the enclosing space kind and - /// the visibility is resolved from the body-declaration's `modifier`s - /// (siblings of the member declaration). - fn member_propagation( - &self, - ctx: RuleNodeView<'_>, - ri: usize, - hint: ChildHint, - container_before_open: Option, - ) -> (bool, Option, Option) { - // A body-declaration reached *inside* an anonymous class / enum-constant - // body belongs to that anonymous subclass, which opens no space here — - // so it must NOT seed a member position on the lexically-enclosing space - // (NPA/NPM), mirroring the WMC suppression at close time. But the - // wrapper's resolved *visibility* must still be threaded (as - // `member_is_public`) so a NESTED type inside the anon body can inherit - // it — e.g. `new Object(){ public record R(int x) { R {} } }` needs the - // record's `public` for its modifier-less compact ctor. So keep - // `propagate_member = false` and `container = None` (no attribution to - // the anon owner) but resolve visibility from the wrapper's modifiers. - if hint.in_anon_body { - // Resolve the wrapper's own visibility from its modifiers; a - // transparent inner wrapper (`memberDeclaration`, generic wrappers) - // has no modifiers of its own, so it must INHERIT the visibility - // already threaded down rather than reset it to `None` — otherwise - // it clobbers the value before it reaches a nested type declaration. - let public = if is_member_body_wrapper(ri) { - visibility_from_modifiers(ctx) - } else { - hint.member_is_public - }; - return (false, None, public); - } - match ri { - // The body-declaration wrappers open a member position; the - // container is the class-like currently on the kinds stack, and - // the visibility is resolved from this wrapper's own `modifier`s. - // - // `recordBody` is included because a *compact* constructor is a - // direct `compactConstructorDeclaration` child of `recordBody` - // (not wrapped in `classBodyDeclaration`), so without seeding the - // member position here it would be visited with - // `in_class_member == false` and dropped from NPM. Its own - // `modifier`s live on the declaration, so visibility is resolved - // in `classify_class_member` rather than from this wrapper. - jp::RULE_CLASS_BODY_DECLARATION - | jp::RULE_INTERFACE_BODY_DECLARATION - | jp::RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION - | jp::RULE_ENUM_BODY_DECLARATIONS - | jp::RULE_RECORD_BODY => { - // Use the container captured BEFORE this node's `maybe_open_space` - // — a body-declaration wrapper may have just opened a nested type - // space (round 29), so `self.enclosing_container()` here would - // wrongly report that type. The real enclosing scope determines - // the member's default visibility (interface members are public). - let container = container_before_open; - // Java visibility semantics (not Kotlin's): a class member with - // no access modifier is *package-private*, which is NOT public, - // so a class member's default is `false` — only an explicit - // `public` modifier makes it count toward NPA/NPM. Interface - // and annotation members are implicitly public, so their - // default is `true`. - let default_public = matches!(container, Some(ContainerKind::Interface)); - let public = visibility_from_modifiers(ctx).unwrap_or(default_public); - (true, container, Some(public)) - } - // A top-level / local type's access modifiers live on the - // `typeDeclaration` / `localTypeDeclaration` wrapper (a sibling of - // the declaration, which has no parent pointer). Thread that - // visibility down as `member_is_public` so a record declaration can - // inherit it for its modifier-less compact canonical constructor — - // WITHOUT marking the type itself as a class member (a top-level - // type is not counted in NPA/NPM), so `propagate_member` stays - // false. A top-level type with no modifier is package-private. - jp::RULE_TYPE_DECLARATION | jp::RULE_LOCAL_TYPE_DECLARATION => { - let public = visibility_from_modifiers(ctx).unwrap_or(false); - (false, None, Some(public)) - } - // Transparent member wrappers keep the inbound member position. - // The generic wrappers (` …`) and the interface-method wrapper - // must be transparent too: they nest the real declaration - // (`methodDeclaration` / `constructorDeclaration` / - // `interfaceCommonBodyDeclaration`) one level deeper, and without - // forwarding the hint their inner declaration is visited with - // `in_class_member = false`, so NPM/NPA silently drop generic and - // interface members. - jp::RULE_MEMBER_DECLARATION - | jp::RULE_INTERFACE_MEMBER_DECLARATION - | jp::RULE_GENERIC_METHOD_DECLARATION - | jp::RULE_GENERIC_CONSTRUCTOR_DECLARATION - | jp::RULE_GENERIC_INTERFACE_METHOD_DECLARATION - | jp::RULE_INTERFACE_METHOD_DECLARATION - | jp::RULE_ANNOTATION_TYPE_ELEMENT_REST - | jp::RULE_ANNOTATION_METHOD_OR_CONSTANT_REST => ( - hint.in_class_member, - hint.member_container, - hint.member_is_public, - ), - _ => (false, None, None), - } - } - - /// The `ContainerKind` of the class-like space currently on top of the - /// kinds stack (for member NPA/NPM routing), or `None` if the top is not - /// a class-like scope. - fn enclosing_container(&self) -> Option { - match self.kinds.last() { - Some(SpaceKind::Class | SpaceKind::Impl | SpaceKind::Enum) => { - Some(ContainerKind::Class) - } - Some(SpaceKind::Interface | SpaceKind::Trait) => Some(ContainerKind::Interface), - _ => None, - } - } - - /// Open a `Function` space for a method/constructor. `span_ctx` supplies - /// the span (the `classBodyDeclaration` wrapper when opening at the wrapper, - /// so the span covers own-line modifiers/annotations; otherwise the - /// declaration itself); `method_ctx` supplies the name and NArgs. When - /// opening at the declaration node (`span_ctx == method_ctx`) the own-line - /// modifiers of a *different* wrapper (interface/annotation) are pulled in - /// via PLOC-range adoption from the parent; when opening at the wrapper the - /// modifiers are walked inside this space directly, so no adoption is - /// needed. - fn open_method_space( - &mut self, - span_ctx: RuleNodeView<'_>, - method_ctx: RuleNodeView<'_>, - hint: ChildHint, - ) { - let name = method_name(method_ctx); - // Node identity: the arena addresses every node by a `NodeId`, so - // "different node" is an id comparison, not pointer equality. - let opened_at_wrapper = span_ctx.node().id() != method_ctx.node().id(); - // When opening at the wrapper, NPM must be recorded into the enclosing - // class BEFORE the method space is pushed (member classification - // normally runs at the inner declaration, but that node now sits inside - // this method space and would misroute NPM into the method). The inner - // declaration skips its own classification via `space_opened_by_wrapper`. - // A method in an anonymous-class body belongs to the anon subclass (no - // space of its own) and must NOT count toward the enclosing container's - // NPM — mirrors the `in_anon_body` suppression in `member_propagation`. - if opened_at_wrapper - && !hint.in_anon_body - && let Some(container) = self.enclosing_container() - { - let default_public = matches!(container, ContainerKind::Interface); - let public = visibility_from_modifiers(span_ctx).unwrap_or(default_public); - self.current().npm.record_method(container, public); - // NPM evidence only for public members — the headline metric - // counts public methods only. - if public { - let detail = method_space_detail(method_ctx.rule_index()); - self.record_evidence(span_ctx, |e, s| e.public_method(s, detail)); - } - } - // Widen the declaration-node span up to its body-declaration wrapper so - // own-line modifiers belong to the method. Unused when opening at the - // wrapper (the span already starts at the wrapper). - let widened = if opened_at_wrapper { - None - } else { - hint.member_decl_start - }; - let mut state = self.new_space_state_widened(span_ctx, widened); - // When opening at the declaration node, the modifier/annotation rows - // were already visited (PLOC-counted) on the enclosing class before - // this space is pushed, so adopt those rows into the method. When - // opening at the wrapper, the modifiers are walked *inside* this space, - // so they are counted directly (no adoption). - if let Some((_, wrapper_start_line)) = widened { - let method_start_line = ctx_span(span_ctx, self.line_index, self.source_len).start_line; - if wrapper_start_line < method_start_line { - let parent_loc = self.current().loc.clone(); - state.loc.adopt_code_lines_in_range( - &parent_loc, - wrapper_start_line.saturating_sub(1), - method_start_line.saturating_sub(1), - ); - } - } - state.nom.record_function(); - // A compact record constructor has no `formalParameters` — its - // parameter list *is* the record's components, so its NArgs is the - // enclosing record's component count (threaded down via `ChildHint`). - // Every other method shape counts its own `formalParameters`. - let nargs = if method_ctx.rule_index() == jp::RULE_COMPACT_CONSTRUCTOR_DECLARATION { - hint.record_component_count.unwrap_or(0) - } else { - count_formal_params(method_ctx) - }; - state.nargs.record_function_args(nargs); - // NOM/NArgs evidence at the space-open site, spanning the same - // (possibly modifier-widened) range the metric space records. - if self.evidence.is_enabled() { - let span = self.space_span(span_ctx, widened); - let detail = method_space_detail(method_ctx.rule_index()); - self.evidence.function(span, detail); - self.evidence.function_args(span, nargs, detail); - } - self.push_space_widened( - SpaceKind::Function, - name, - span_ctx, - state, - hint.in_anon_body, - widened, - ); - self.enter_function_cognitive(hint.in_anon_body); - } - - /// Open a class-like (`Class`/`Enum`/`Interface`) space for `type_ctx`. - /// `span_ctx` supplies the span — the wrapper (`typeDeclaration` / member - /// body-declaration) when opening at the wrapper, so own-line - /// modifiers/annotations are covered; otherwise the declaration itself - /// (with PLOC-range adoption for own-line modifiers on a different wrapper). - /// Mirrors `open_method_space` but for class-like scopes: nested types are - /// not member-classified into NPA/NPM, so there is no member-routing to - /// relocate. - fn open_type_space(&mut self, span_ctx: RuleNodeView<'_>, type_ctx: RuleNodeView<'_>) { - let name = type_name(type_ctx); - let ri = type_ctx.rule_index(); - // Node identity is a `NodeId` comparison in the arena model. - let opened_at_wrapper = span_ctx.node().id() != type_ctx.node().id(); - let widened = if opened_at_wrapper { - None - } else { - // (Only used by the self-open path; kept for symmetry — a class's - // own-line modifiers are already handled by opening at the wrapper.) - None - }; - let mut state = self.new_space_state_widened(span_ctx, widened); - state.npa.record_class_like(); - state.npm.record_class_like(); - let kind = if matches!(ri, jp::RULE_ENUM_DECLARATION) { - state.wmc.record_class_like(); - SpaceKind::Enum - } else if matches!( - ri, - jp::RULE_INTERFACE_DECLARATION | jp::RULE_ANNOTATION_TYPE_DECLARATION - ) { - // Interfaces/annotations do not carry WMC (their methods are not - // weighted); match the original arm which omits `record_class_like` - // on WMC. - SpaceKind::Interface - } else { - state.wmc.record_class_like(); - // `record R(...)` component parameters are class attributes. - record_record_components(type_ctx, &mut state); - self.record_component_evidence(type_ctx); - SpaceKind::Class - }; - self.push_space_widened(kind, name, span_ctx, state, false, None); - self.enter_class_cognitive(); - } - - /// NPA evidence for a record's component parameters — one public - /// attribute per declared component, at the component's own span. - /// Walks the same typed-context path as [`count_record_components`] - /// (which drives [`record_record_components`]), so the evidence count - /// always equals the recorded stat count. - fn record_component_evidence(&mut self, type_ctx: RuleNodeView<'_>) { - if !self.evidence.is_enabled() { - return; - } - let Some(list) = jp::RecordDeclarationContext::from_rule_node(type_ctx) - .and_then(|record| record.record_header().ok()) - .and_then(|header| header.record_component_list()) - else { - return; - }; - for component in list.record_component_children() { - let span = ctx_span(component.rule_node(), self.line_index, self.source_len); - self.evidence.public_attribute(span, "record_component"); - } - } - - /// Open a metric space for space-introducing rules. Returns whether a - /// space was pushed. - fn maybe_open_space(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) -> bool { - match ri { - // One function space per method shape. Interface methods reach - // their name/params/body via `interfaceCommonBodyDeclaration` - // (wrapped by `interfaceMethodDeclaration` / - // `genericInterfaceMethodDeclaration`), so the space is opened - // there — opening at the wrapper too would double-count. A function - // opened inside an enum-constant body must not roll into the enum's - // WMC (it belongs to the constant's anonymous subclass). - // A `classBodyDeclaration` wrapping a plain method/constructor opens - // the function space HERE (not at the inner declaration) so the - // wrapper's own-line modifiers/annotations — siblings of the - // declaration, visited before it — are walked *inside* the method - // space and count toward its LOC/Halstead/span. The inner - // declaration then skips its own open (`space_opened_by_wrapper`). - // Only plain method/constructor members route this way; fields, - // nested types, and compact/interface/annotation members keep their - // existing open sites. - jp::RULE_CLASS_BODY_DECLARATION - | jp::RULE_INTERFACE_BODY_DECLARATION - | jp::RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION - if wrapper_inner_method(ctx).is_some() => - { - let method = wrapper_inner_method(ctx).expect("guarded by match arm"); - self.open_method_space(ctx, method, hint); - true - } - jp::RULE_METHOD_DECLARATION - | jp::RULE_CONSTRUCTOR_DECLARATION - | jp::RULE_INTERFACE_COMMON_BODY_DECLARATION - | jp::RULE_ANNOTATION_METHOD_REST - if hint.space_opened_by_wrapper => - { - // The wrapper already opened this method's space; do not open a - // second one. (Its children are still visited into that space.) - false - } - jp::RULE_METHOD_DECLARATION - | jp::RULE_CONSTRUCTOR_DECLARATION - | jp::RULE_COMPACT_CONSTRUCTOR_DECLARATION - | jp::RULE_INTERFACE_COMMON_BODY_DECLARATION - | jp::RULE_ANNOTATION_METHOD_REST => { - // Opened at the declaration node itself (compact ctor, interface - // method, annotation element, or a method not reached through a - // `classBodyDeclaration` wrapper — e.g. inside an anon body). - // Its own-line modifiers, if any, are covered by the PLOC-range - // adoption inside `open_method_space`. - self.open_method_space(ctx, ctx, hint); - true - } - jp::RULE_LAMBDA_EXPRESSION => { - let mut state = self.new_space_state(ctx); - state.nom.record_closure(); - let argc = count_lambda_args(ctx); - state.nargs.record_closure_args(argc); - if self.evidence.is_enabled() { - let span = ctx_span(ctx, self.line_index, self.source_len); - self.evidence.closure(span, "lambda_expression"); - self.evidence.closure_args(span, argc, "lambda_expression"); - } - // A lambda is a `Closure`, not a `Function`: NOM/NArgs already - // record it as a closure, and its cyclomatic must NOT roll into - // the enclosing class's WMC (WMC weights *methods*). A lambda in - // a field initializer would otherwise inflate the class's WMC. - self.push_space(SpaceKind::Closure, None, ctx, state, hint.in_anon_body); - self.enter_function_cognitive(hint.in_anon_body); - true - } - // A type wrapper (`typeDeclaration`/`localTypeDeclaration` or a - // member body-declaration) opens the class-like space HERE so its - // own-line modifiers/annotations (`@Deprecated\npublic class C {}`, - // `public static class Inner {}`) — siblings of the declaration, - // visited before it — are walked *inside* the type space and count - // toward its LOC/Halstead/span. The inner declaration then skips its - // own open via `space_opened_by_wrapper`. - _ if is_type_wrapper(ri) && wrapper_inner_type(ctx).is_some() => { - let type_ctx = wrapper_inner_type(ctx).expect("guarded by match arm"); - self.open_type_space(ctx, type_ctx); - true - } - jp::RULE_CLASS_DECLARATION - | jp::RULE_RECORD_DECLARATION - | jp::RULE_ENUM_DECLARATION - | jp::RULE_INTERFACE_DECLARATION - | jp::RULE_ANNOTATION_TYPE_DECLARATION - if hint.space_opened_by_wrapper => - { - // The wrapper already opened this type's space; do not open a - // second one. (Its children are still visited into that space.) - false - } - jp::RULE_CLASS_DECLARATION - | jp::RULE_RECORD_DECLARATION - | jp::RULE_ENUM_DECLARATION - | jp::RULE_INTERFACE_DECLARATION - | jp::RULE_ANNOTATION_TYPE_DECLARATION => { - // Opened at the declaration node itself (a type not reached - // through a wrapper — e.g. inside an anonymous-class body, which - // opens no space and whose members are visited directly). - self.open_type_space(ctx, ctx); - true - } - _ => false, - } - } - - fn new_space_state(&self, ctx: RuleNodeView<'_>) -> State { - self.new_space_state_widened(ctx, None) - } - - /// The metric-space span for `ctx`: its covered token range with the - /// start widened (byte + line) to `widened_start` when that precedes the - /// context's own start. Single source of the span recorded by - /// [`push_space_widened`](Self::push_space_widened) and attached to - /// NOM/NArgs evidence at space-open sites. - fn space_span(&self, ctx: RuleNodeView<'_>, widened_start: Option<(u32, u32)>) -> SourceSpan { - let mut span = ctx_span(ctx, self.line_index, self.source_len); - if let Some((start_byte, start_line)) = widened_start - && start_byte < span.start_byte - { - span.start_byte = start_byte; - span.start_line = start_line; - } - span - } - - /// Build a space's initial `State`, optionally widening the span's start - /// (byte + line) upward to `widened_start`. A method/constructor uses this - /// to cover own-line modifiers/annotations that live on its - /// `classBodyDeclaration` wrapper (siblings of the declaration, so *before* - /// the declaration's own `ctx_span` start). - fn new_space_state_widened( - &self, - ctx: RuleNodeView<'_>, - widened_start: Option<(u32, u32)>, - ) -> State { - let mut state = State::new(); - let span = ctx_span(ctx, self.line_index, self.source_len); - let start_line = match widened_start { - Some((_, line)) if line < span.start_line => line, - _ => span.start_line, - }; - state.loc.set_span( - start_line.saturating_sub(1), - span.end_line.saturating_sub(1), - false, - ); - state - } - - fn push_space( - &mut self, - kind: SpaceKind, - name: Option, - ctx: RuleNodeView<'_>, - state: State, - suppress_parent_wmc: bool, - ) { - self.push_space_widened(kind, name, ctx, state, suppress_parent_wmc, None); - } - - /// Like [`push_space`], but widens the recorded span's start (byte + line) - /// upward to `widened_start` when it precedes the context's own start — so - /// comment routing and the tree span cover the member's own-line - /// modifiers/annotations. - fn push_space_widened( - &mut self, - kind: SpaceKind, - name: Option, - ctx: RuleNodeView<'_>, - state: State, - suppress_parent_wmc: bool, - widened_start: Option<(u32, u32)>, - ) { - let span = self.space_span(ctx, widened_start); - let space_id = self.tree.open(kind.clone(), span, name); - self.loc_routing - .record_open(space_id, span.start_byte, span.end_byte); - self.stack.push(state); - self.kinds.push(kind); - self.suppress_parent_wmc.push(suppress_parent_wmc); - } - - /// Reset the cognitive context when opening a class-like space. A class - /// body is a fresh scope: code that runs *directly* in it (instance/static - /// initializer blocks, field initializers) must not inherit the enclosing - /// method's or statement's nesting. Methods do this via - /// `enter_function_cognitive`, but class-body-level code opens no function - /// space, so the class-open must reset it. `visit_rule`'s `saved_cognitive` - /// restore unwinds it when the class-like node's subtree is done. - fn enter_class_cognitive(&mut self) { - self.cognitive = CognitiveContext::default(); - } - - fn enter_function_cognitive(&mut self, in_anon_body: bool) { - // Depth is inherited only from an *enclosing function/closure within - // the same class scope* — a lambda or nested function nested directly - // in another function's body. A class scope resets the baseline: a - // method in a nested class is fresh, so its cognitive nesting starts at - // 0, not inheriting the enclosing method's depth. Two kinds of class - // scope must be honored: - // - a *named* local/anonymous class pushes a `Class` SpaceKind - // (`void outer(){ class L { void inner(){…} } }`), caught by the - // `take_while` boundary below; - // - an *anonymous* class expression (`new Runnable(){ void run(){…} }`) - // opens NO space — it's tracked only by `in_anon_body` — so the - // ancestor scan would otherwise walk past it to `outer`. When we're - // directly in such a body, do not inherit depth at all. - let nested_inside_function = !in_anon_body - && self - .kinds - .iter() - .rev() - .skip(1) - .take_while(|k| { - !matches!( - k, - SpaceKind::Class - | SpaceKind::Interface - | SpaceKind::Trait - | SpaceKind::Impl - | SpaceKind::Enum - ) - }) - .any(|k| matches!(k, SpaceKind::Function | SpaceKind::Closure)); - self.cognitive.nesting = 0; - self.cognitive.lambda = 0; - if nested_inside_function { - self.cognitive.depth = self.cognitive.depth.saturating_add(1); - } - } - - fn close_space(&mut self) { - let closed_kind = self.kinds.pop().expect("kinds underflow"); - let suppress_wmc = self.suppress_parent_wmc.pop().unwrap_or(false); - let mut state = self.stack.pop().expect("stack underflow"); - // A function OR closure space carries its own McCabe value (base + 1), - // used for its per-space cyclomatic and (for methods) the WMC rollup. - if matches!(closed_kind, SpaceKind::Function | SpaceKind::Closure) { - state.wmc.set_cyclomatic(state.cyclomatic.cyclomatic + 1); - } - finalize_state(&mut state); - if let Some(space_id) = self.tree.current_id() { - self.loc_routing - .record_close(space_id, &state.loc, &state.cyclomatic); - } - apply_state_to(state.clone(), self.tree.metrics_mut()); - if let Some(parent) = self.stack.last_mut() { - let parent_kind = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - merge_child_into_parent(parent, &state); - // Roll a closing function's cyclomatic into the parent's WMC — - // unless it's a function from an enum-constant body, which belongs - // to that constant's anonymous subclass (no space of its own) and - // must not inflate the enclosing enum's WMC. Java WMC is *per - // class* — an interface's methods (`default`/`static`/abstract) are - // NOT weighted, so only roll into a class/enum parent. A method - // whose parent is an interface contributes nothing to WMC. - if matches!(closed_kind, SpaceKind::Function) - && !suppress_wmc - && matches!( - parent_kind, - SpaceKind::Class | SpaceKind::Impl | SpaceKind::Enum - ) - { - let container = container_kind(parent_kind); - state.wmc.finalize_method_into(container, &mut parent.wmc); - } - } - self.tree.close(); - } - - /// Per-rule cyclomatic / cognitive / ABC / exit / LOC classification. - fn classify_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) { - if ri == jp::RULE_STATEMENT { - self.classify_statement(ctx, hint); - } - if ri == jp::RULE_SWITCH_LABEL || ri == jp::RULE_SWITCH_LABELED_RULE { - // Each `case` label is a decision (cyclomatic) and a condition - // (ABC). `default` (no CASE token) is neither. The `switch` - // statement/expression already opened the cognitive nesting level, - // so a `case` adds only the flat structural cost, not another - // nesting. - if ctx.has_token(jl::CASE) { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, "switch_case"); - e.abc_condition(s, "switch_case"); - }); - } - } - // A pattern-switch guard (`case String s when expr -> …`, grammar - // `guard: 'when' expression`) is a distinct boolean test — like an extra - // `if` on the case — so it records one ABC condition of its own (any - // operators *inside* the guard expression still count on top, via - // `classify_expression`). It is its own rule, so `default` and unguarded - // cases are unaffected. Cyclomatic/cognitive are unchanged: the `case` - // already carries the decision and the `switch` the nesting. - if ri == jp::RULE_GUARD { - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| e.abc_condition(s, "guard")); - } - // A `switch` *expression* (Java 14+) owns its `SWITCH` token in the - // separate `switchExpression` rule — the statement-form handler in - // `classify_statement` (keyed on `statement`'s direct `SWITCH` token) - // can never see it. Give it the same cognitive nesting increment so a - // switch expression and the equivalent switch statement score - // identically, and so structures nested in its arms see the raised - // nesting level (the `saved_cognitive` restore in `visit_rule` unwinds - // it afterward). - if ri == jp::RULE_SWITCH_EXPRESSION { - let eff = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, "switch_expression")); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - } - // An enum constant (`enum E { A, B }`) is a public static final field - // of the enum → a public class attribute (NPA). Constants live under - // `enumConstants` (before the `;`), not `enumBodyDeclarations`, so they - // never reach the `classify_class_member` member-position path; count - // them directly here. The enclosing space must be the enum itself (not - // a nested anonymous body, which owns no space). - if ri == jp::RULE_ENUM_CONSTANT - && !hint.in_anon_body - && matches!(self.kinds.last(), Some(SpaceKind::Enum)) - { - self.current() - .npa - .record_attribute(ContainerKind::Class, true); - self.record_evidence(ctx, |e, s| e.public_attribute(s, "enum_constant")); - } - // Annotation values (`@Ann(value = true && false)`, `@Ann(x = c ? 1 : 2)`) - // are compile-time metadata, not executable code, so a composed constant - // in them must NOT record cyclomatic decisions, cognitive nesting, or - // ABC conditions/branches/assignments. `in_annotation` covers the whole - // annotation subtree; guarding here generalizes the round-16 fix (which - // only suppressed ABC *assignments*) to all executable-complexity - // accounting. LOC/Halstead still count — the tokens physically exist. - if !hint.in_annotation { - self.classify_expression(ctx, ri, hint); - self.classify_abc_rule(ctx, ri, hint); - } - self.classify_loc_rule(ctx, ri, hint); - } - - /// Classify a `statement` context by its leading keyword token. - fn classify_statement(&mut self, ctx: RuleNodeView<'_>, hint: ChildHint) { - let eff = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - - if ctx.has_token(jl::IF) { - // Cyclomatic + ABC always; cognitive nesting unless this is an - // `else if` (flat +1 emitted when the ELSE token is visited). - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, "if_statement"); - e.abc_condition(s, "if_statement"); - }); - if !hint.is_else_branch { - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, "if_statement")); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - } - // `else` adds a flat +1 (covers `else if`). Evidence points at - // the ELSE keyword itself, not the whole if statement. - if ctx.has_token(jl::ELSE) { - let before = self.current().cognitive.structural; - self.current().cognitive.increment_by_one(); - let delta = self.current().cognitive.structural.saturating_sub(before); - if self.evidence.is_enabled() { - let span = self - .first_token_span(ctx, jl::ELSE) - .unwrap_or_else(|| ctx_span(ctx, self.line_index, self.source_len)); - self.evidence.cognitive(span, delta, "else"); - } - } - } else if ctx.has_token(jl::FOR) || ctx.has_token(jl::WHILE) || ctx.has_token(jl::DO) { - // A `do … while` statement carries both DO and WHILE as direct - // tokens, so the DO probe must come first when naming the - // construct for the evidence reason. - let detail = if ctx.has_token(jl::DO) { - "do_statement" - } else if ctx.has_token(jl::FOR) { - "for_statement" - } else { - "while_statement" - }; - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| { - e.decision(s, detail); - e.abc_condition(s, detail); - e.cognitive(s, delta, detail); - }); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - } else if ctx.has_token(jl::SWITCH) { - // `switch` itself adds cognitive nesting but not cyclomatic — the - // individual `case` labels carry the cyclomatic/ABC decisions. - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, "switch_statement")); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - } else if ctx.has_token(jl::RETURN) || ctx.has_token(jl::THROW) { - self.current().nexit.record_exit(); - let detail = if ctx.has_token(jl::RETURN) { - "return_statement" - } else { - "throw_statement" - }; - self.record_evidence(ctx, |e, s| e.exit(s, detail)); - } else if (ctx.has_token(jl::BREAK) || ctx.has_token(jl::CONTINUE)) - && ctx.child_rule(jp::RULE_IDENTIFIER).is_some() - { - // A labeled break/continue is goto-like: flat +1 (cognitive). - let detail = if ctx.has_token(jl::BREAK) { - "labeled_break" - } else { - "labeled_continue" - }; - let before = self.current().cognitive.structural; - self.current().cognitive.increment_by_one(); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, detail)); - } - } - - /// Classify operator tokens carried directly by an `expression` context: - /// short-circuit `&&`/`||` (cyclomatic + cognitive + ABC), the ternary `?` - /// (cyclomatic + cognitive + ABC), comparison/equality (ABC condition), - /// and `instanceof` (ABC condition). - fn classify_expression(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) { - if ri == jp::RULE_CATCH_CLAUSE { - // `catch` is cognitive-only (matches SonarJava): nesting increment - // + an ABC condition, but no cyclomatic decision. - let eff = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.cognitive(s, delta, "catch_clause"); - e.abc_condition(s, "catch_clause"); - }); - return; - } - if ri != jp::RULE_EXPRESSION { - return; - } - // Read this `expression` node's operator tokens through the generated - // typed context (0.15.2 runtime, issue #178): `and_token()` is `&&` - // (distinct from `bitand_tokens()` `&`), `or_token()` is `||`, etc. — - // named `Option` accessors that replace `has_token(jl::…)` - // integer probing. - let Some(expr) = jp::ExpressionContext::from_rule_node(ctx) else { - return; - }; - // Short-circuit `&&`/`||`: a cyclomatic decision and an ABC condition - // per operator (both independent of the cognitive run-collapse), plus - // the cognitive boolean-sequence cost. Uses the same `expression_bool_op` - // helper as `visit_children`'s run-threading so both agree on the - // operator. - let this_op = expression_bool_op(ctx); - if let Some(op) = this_op { - let detail = bool_op_detail(op); - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - // Per-operator evidence points at the `&&`/`||` token itself — - // tighter than the whole boolean expression, whose operands can - // span lines. - if self.evidence.is_enabled() { - let token = match op { - BoolOp::And => expr.and_token(), - BoolOp::Or => expr.or_token(), - }; - let span = token - .map(|t| { - span_from_tokens(&t.symbol(), &t.symbol(), self.line_index, self.source_len) - }) - .unwrap_or_else(|| ctx_span(ctx, self.line_index, self.source_len)); - self.evidence.decision(span, detail); - self.evidence.abc_condition(span, detail); - } - // Cognitive: SonarSource counts +1 per *sequence of like logical - // operators*, computed by flattening the boolean expression in - // SOURCE ORDER and adding +1 whenever the operator kind changes - // (SonarJava `CognitiveComplexityVisitor.flattenLogicalExpression`; - // SonarKotlin `CognitiveComplexity.flattenOperators`). Parentheses - // are transparent to the flattening, and — critically — a `!` - // negation is NOT special: it is just an operand where flattening - // stops, so it never breaks a run (`a && !b && c` is one `&&` run). - // - // Only the ROOT of a logical-operator tree does the counting: a - // `&&`/`||` node whose enclosing boolean operator is `None` - // (`hint.parent_bool_op` — threaded through transparent parens). - // A nested `&&`/`||` reached as a logical operand is consumed by its - // root's flatten and must not double-count. So `a && b || c && d` - // (root `||`, flattened `&& || &&`) scores 3, and `a && (b || c) && - // d` (flattened `&& || &&` after skipping parens) also scores 3 — - // the parenthesized `||` interrupts the `&&` sequence. - if hint.parent_bool_op.is_none() { - let mut ops = Vec::new(); - flatten_logical_operators(ctx, &mut ops); - let mut prev: Option = None; - let mut increments = 0u32; - for op in ops { - if prev != Some(op) { - increments += 1; - } - prev = Some(op); - } - if increments > 0 { - let before = self.current().cognitive.structural; - self.current().cognitive.record_increment(increments); - let delta = self.current().cognitive.structural.saturating_sub(before); - // One evidence row for the whole run, at the run root's - // span, named after the root operator. - self.record_evidence(ctx, |e, s| e.cognitive(s, delta, detail)); - } - } - } - // Ternary `? :` — a decision, an ABC condition, and a cognitive nesting - // structure (SonarJava scores it like an `if`). Bump the walker nesting - // so a structure nested in an operand (notably a nested ternary) is - // scored one level deeper; `visit_rule`'s `saved_cognitive` restore - // unwinds it after the operands are walked. - if expr.question_token().is_some() && expr.colon_token().is_some() { - let eff = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cyclomatic.record_decision(); - let before = self.current().cognitive.structural; - self.current().cognitive.increase_nesting(eff); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - self.current().abc.record_condition(); - self.record_evidence(ctx, |e, s| { - e.decision(s, "ternary_expression"); - e.cognitive(s, delta, "ternary_expression"); - e.abc_condition(s, "ternary_expression"); - }); - } - // Comparison / equality / instanceof → ABC conditions only. A bit-shift - // (`<<`, `>>`, `>>>`) is NOT a condition — but the grammar spells it - // with multiple bare `LT`/`GT` terminals (there is no `<<` token), so a - // bare presence check can't tell a shift from a relational `<`/`>`. - // Distinguish by count: a *relational* operator contributes exactly one - // `LT` (or one `GT`); a shift contributes two-or-three. `lt_tokens()`/ - // `gt_tokens()` are the grouped-token iterators for those bare literals. - let lt = expr.lt_tokens().count(); - let gt = expr.gt_tokens().count(); - if lt == 1 - || gt == 1 - || expr.equal_token().is_some() - || expr.notequal_token().is_some() - || expr.le_token().is_some() - || expr.ge_token().is_some() - || expr.instanceof_token().is_some() - { - self.current().abc.record_condition(); - let detail = if expr.instanceof_token().is_some() { - "instanceof" - } else { - "comparison" - }; - self.record_evidence(ctx, |e, s| e.abc_condition(s, detail)); - } - } - - fn classify_abc_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) { - match ri { - // A method/constructor call, or object creation, is a branch. - jp::RULE_METHOD_CALL => { - self.current().abc.record_branch(); - self.record_evidence(ctx, |e, s| e.abc_branch(s, "method_call")); - } - jp::RULE_CREATOR | jp::RULE_INNER_CREATOR => { - self.current().abc.record_branch(); - let detail = if ri == jp::RULE_CREATOR { - "creator" - } else { - "inner_creator" - }; - self.record_evidence(ctx, |e, s| e.abc_branch(s, detail)); - } - // Calls that don't route through `methodCall`. The Java grammar - // reaches several call forms via suffix rules; count each call - // exactly once at the innermost call-bearing node to avoid the - // double-counting that would arise from also counting the - // enclosing `explicitGenericInvocation` wrapper: - // - `superSuffix` — a qualified super call (`I.super.m()`) and - // the `SUPER superSuffix` form of an explicit generic - // invocation (`super.m()`). - // - `explicitGenericInvocationSuffix` in its `identifier - // arguments` form (a direct `arguments` child) — a qualified - // (`C.this.m()`) or unqualified (`m()`) - // explicit-type-argument call. Its `SUPER superSuffix` form is - // counted via the nested `superSuffix` above, so it's excluded - // here by the direct-`arguments` guard. - // `superSuffix` is also qualified super *field* access - // (`Outer.super.field`) — its grammar alternative - // `'.' typeArguments? identifier arguments?` makes `arguments` - // optional. Only count it as a branch when it actually carries an - // `arguments` child (a call), not a bare field read. - jp::RULE_SUPER_SUFFIX if ctx.child_rule(jp::RULE_ARGUMENTS).is_some() => { - self.current().abc.record_branch(); - self.record_evidence(ctx, |e, s| e.abc_branch(s, "super_suffix")); - } - jp::RULE_EXPLICIT_GENERIC_INVOCATION_SUFFIX - if ctx.child_rule(jp::RULE_ARGUMENTS).is_some() => - { - self.current().abc.record_branch(); - self.record_evidence(ctx, |e, s| { - e.abc_branch(s, "explicit_generic_invocation_suffix"); - }); - } - // A generic explicit constructor invocation (`this(arg)`) - // routes through `primary: nonWildcardTypeArguments THIS arguments` - // — not `methodCall` (which handles the plain `this(…)`/`super(…)` - // forms). Count it when the `primary` carries a `THIS` token AND a - // direct `arguments` child; a bare `this` / `this.field` (no - // `arguments`) is not a call. - jp::RULE_PRIMARY - if ctx.has_token(jl::THIS) && ctx.child_rule(jp::RULE_ARGUMENTS).is_some() => - { - self.current().abc.record_branch(); - self.record_evidence(ctx, |e, s| e.abc_branch(s, "this_call")); - } - // An `expression` carrying an assignment operator is an assignment. - // Compound assigns (`+=`, `-=`, …) and the increment/decrement - // operators (`++`, `--`) count too (Fitzpatrick's ABC lists both - // under A). `has_assignment_op` covers all of them. Suppressed - // inside an annotation: a named element value (`@Ann(value = 1)`) - // is compile-time metadata, not an executable assignment — and the - // grammar's `IsNotIdentifierAssign` predicate that would keep it out - // of the assignment-expression path is dropped by the Rust - // generator. - jp::RULE_EXPRESSION if has_assignment_op(ctx) && !hint.in_annotation => { - self.current().abc.record_assignment(); - // `++`/`--` are named apart from `=`/compound assigns in the - // evidence reason (both count under ABC's A component). - let detail = if has_update_op(ctx) { - "update_expression" - } else { - "assignment_expression" - }; - self.record_evidence(ctx, |e, s| e.abc_assignment(s, detail)); - } - // A local variable / field / record-component declarator with an - // initializer (`= …`) is an assignment. - jp::RULE_VARIABLE_DECLARATOR | jp::RULE_CONSTANT_DECLARATOR - if ctx.has_token(jl::ASSIGN) => - { - self.current().abc.record_assignment(); - let detail = if ri == jp::RULE_VARIABLE_DECLARATOR { - "variable_declarator" - } else { - "constant_declarator" - }; - self.record_evidence(ctx, |e, s| e.abc_assignment(s, detail)); - } - // A `var x = expr` local-variable declaration places its `=` as a - // direct child of `localVariableDeclaration` (no `variableDeclarator` - // node), and a try-with-resources `T r = expr` places its `=` - // directly on `resource`. Both are initialized declarations → one - // assignment. The explicit-type local (`int x = e`) routes its `=` - // through `variableDeclarator` (handled above), so this arm's - // `has_token(ASSIGN)` guard fires only for the `var` form and never - // double-counts. A bare `qualifiedName` resource has no `=`. - jp::RULE_LOCAL_VARIABLE_DECLARATION | jp::RULE_RESOURCE - if ctx.has_token(jl::ASSIGN) => - { - self.current().abc.record_assignment(); - let detail = if ri == jp::RULE_LOCAL_VARIABLE_DECLARATION { - "local_variable_declaration" - } else { - "resource" - }; - self.record_evidence(ctx, |e, s| e.abc_assignment(s, detail)); - } - _ => {} - } - } - - fn classify_loc_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) { - // A `for` header's initializer declaration is part of the `for` - // statement's single logical line — not its own LLOC. - if ri == jp::RULE_LOCAL_VARIABLE_DECLARATION && hint.in_for_init { - return; - } - // An *expression-bodied* lambda (`x -> x + 1`) opens a closure space but - // its body (`lambdaBody: expression`) contains no statement/declaration, - // so the closure would report `lloc = 0`. Count the lambda itself as one - // logical line to match a block-bodied lambda (whose inner statements - // already count) and method declarations. A block body is skipped here - // — its statements are counted individually. - if ri == jp::RULE_LAMBDA_EXPRESSION && lambda_body_is_expression(ctx) { - self.current().loc.observe_lloc(); - return; - } - // LLOC: statement- and declaration-shaped rules. Interface methods - // (`interfaceCommonBodyDeclaration`) and annotation elements/constants - // (`annotationMethodRest`/`annotationConstantRest`) are the - // declaration nodes for their member kinds — a class abstract method - // counts via `methodDeclaration`, so their interface/annotation - // equivalents must count too, or interface/annotation APIs - // under-report LLOC. - if matches!( - ri, - jp::RULE_STATEMENT - | jp::RULE_LOCAL_VARIABLE_DECLARATION - | jp::RULE_FIELD_DECLARATION - | jp::RULE_METHOD_DECLARATION - | jp::RULE_CONSTRUCTOR_DECLARATION - | jp::RULE_COMPACT_CONSTRUCTOR_DECLARATION - | jp::RULE_INTERFACE_COMMON_BODY_DECLARATION - | jp::RULE_ANNOTATION_METHOD_REST - | jp::RULE_ANNOTATION_CONSTANT_REST - | jp::RULE_CONST_DECLARATION - // An enum constant (`A`, `B` in `enum E { A, B }`) is a - // declaration — a logical line, like a field. - | jp::RULE_ENUM_CONSTANT - | jp::RULE_CLASS_DECLARATION - | jp::RULE_INTERFACE_DECLARATION - | jp::RULE_ENUM_DECLARATION - | jp::RULE_RECORD_DECLARATION - | jp::RULE_ANNOTATION_TYPE_DECLARATION - | jp::RULE_IMPORT_DECLARATION - | jp::RULE_PACKAGE_DECLARATION - // Java 9+ module descriptors (`module-info.java`): the module - // declaration and each directive (`requires`/`exports`/…) are - // logical lines, or a module file reports lloc == 0. - | jp::RULE_MODULE_DECLARATION - | jp::RULE_MODULE_DIRECTIVE - ) { - // Some `statement` shapes are pure wrappers that are not their own - // logical line — the statement(s) they contain each count: - // - a bare block `{ … }` (the inner statements count), - // - an empty statement `;` (no work at all), - // - a labeled statement `label: stmt` (the label is an attribute - // of the inner statement, which is counted when visited). - if ri == jp::RULE_STATEMENT - && (ctx_is_block(ctx) || ctx_is_empty_statement(ctx) || ctx_is_label_wrapper(ctx)) - { - return; - } - self.current().loc.observe_lloc(); - } - } - - /// NPA / NPM classification for a direct member of an enclosing class or - /// interface body. `ctx` is the member declaration rule itself; `public` - /// is the visibility resolved from the body-declaration wrapper's - /// `modifier`s (threaded down via [`ChildHint`]). `hint` carries the - /// enclosing record's visibility for the compact-constructor fallback. - fn classify_class_member( - &mut self, - ctx: RuleNodeView<'_>, - ri: usize, - container: ContainerKind, - public: bool, - hint: ChildHint, - ) { - match ri { - jp::RULE_FIELD_DECLARATION => { - // A field declaration can declare several variables. - let count = field_variable_count(ctx).max(1); - for _ in 0..count { - self.current().npa.record_attribute(container, public); - } - // NPA evidence only for public members — one row per declared - // variable, all at the declaration's span. - if public && self.evidence.is_enabled() { - let span = ctx_span(ctx, self.line_index, self.source_len); - for _ in 0..count { - self.evidence.public_attribute(span, "field_declaration"); - } - } - } - jp::RULE_CONST_DECLARATION => { - let count = ctx.child_rules(jp::RULE_CONSTANT_DECLARATOR).count().max(1); - for _ in 0..count { - self.current().npa.record_attribute(container, true); - } - if self.evidence.is_enabled() { - let span = ctx_span(ctx, self.line_index, self.source_len); - for _ in 0..count { - self.evidence.public_attribute(span, "const_declaration"); - } - } - } - // Interface methods are counted at `interfaceCommonBodyDeclaration` - // only (the single site where the space is also opened), NOT at - // the `interfaceMethodDeclaration` wrapper — the wrapper is now a - // transparent hint-forwarder, so counting at both would - // double-count the non-generic interface method. - jp::RULE_METHOD_DECLARATION - | jp::RULE_CONSTRUCTOR_DECLARATION - | jp::RULE_INTERFACE_COMMON_BODY_DECLARATION => { - self.current().npm.record_method(container, public); - if public { - let detail = method_space_detail(ri); - self.record_evidence(ctx, |e, s| e.public_method(s, detail)); - } - } - // A compact record constructor (`record R(int x) { public R {} }`) - // is reached directly under `recordBody`, so the threaded `public` - // comes from the (modifier-less) record body and is always `false`. - // Its own `modifier`s are its children, so an *explicit* modifier is - // resolved from `ctx`; a modifier-less compact canonical constructor - // inherits the RECORD's access level (Java rule), threaded via - // `enclosing_record_public` — not the record-body default. - jp::RULE_COMPACT_CONSTRUCTOR_DECLARATION => { - let is_public = visibility_from_modifiers(ctx) - .or(hint.enclosing_record_public) - .unwrap_or(public); - self.current().npm.record_method(container, is_public); - if is_public { - self.record_evidence(ctx, |e, s| { - e.public_method(s, "compact_constructor_declaration"); - }); - } - } - // An annotation element (`@interface A { String value(); }`) is an - // implicitly-public interface-like method — `annotationMethodRest` - // is the declaration reached through the annotation wrappers - // (`annotationTypeElementRest → annotationMethodOrConstantRest`). - jp::RULE_ANNOTATION_METHOD_REST => { - self.current().npm.record_method(container, true); - self.record_evidence(ctx, |e, s| e.public_method(s, "annotation_method_rest")); - } - // An annotation constant (`int X = 1;` in an `@interface`) is an - // implicitly-public attribute; `annotationConstantRest` wraps a - // `variableDeclarators`, so several constants can be declared at - // once (`int X = 1, Y = 2;`). - jp::RULE_ANNOTATION_CONSTANT_REST => { - let count = ctx - .child_rule(jp::RULE_VARIABLE_DECLARATORS) - .map(|vds| vds.child_rules(jp::RULE_VARIABLE_DECLARATOR).count()) - .unwrap_or(0) - .max(1); - for _ in 0..count { - self.current().npa.record_attribute(container, true); - } - if self.evidence.is_enabled() { - let span = ctx_span(ctx, self.line_index, self.source_len); - for _ in 0..count { - self.evidence - .public_attribute(span, "annotation_constant_rest"); - } - } - } - _ => {} - } - } -} - -// -------------------------------------------------------------------- -// Free helpers (top-down tree inspection — no parent pointers). -// -------------------------------------------------------------------- - -/// Index of the first direct child that is a rule with `rule_index`, if any. -/// Used to tag only the `classBody` child of `classCreatorRest`/`enumConstant` -/// as the anonymous body (its sibling `arguments` is a plain call). Takes the -/// child iterator directly so no `Vec` is allocated. -fn child_index_of_rule<'a>( - children: impl Iterator>, - rule_index: usize, -) -> Option { - children.enumerate().find_map(|(idx, c)| { - c.as_rule() - .filter(|rule| rule.rule_index() == rule_index) - .map(|_| idx) - }) -} - -/// Rules that open a class-like metric space (see `maybe_open_space`). Used to -/// clear the `in_anon_body` suppression once a real nested class/interface/enum -/// owns the following body — its members belong to that class, not the enum -/// constant whose body lexically encloses it. -fn opens_class_like(ri: usize) -> bool { - matches!( - ri, - jp::RULE_CLASS_DECLARATION - | jp::RULE_RECORD_DECLARATION - | jp::RULE_ENUM_DECLARATION - | jp::RULE_INTERFACE_DECLARATION - | jp::RULE_ANNOTATION_TYPE_DECLARATION - ) -} - -/// Rules that open a function/closure metric space (mirrors the function arms -/// of `maybe_open_space`). Used to clear the `in_anon_body` flag: the anon -/// body's direct method is the boundary, and a lambda nested *inside* that -/// method is enclosed by the method (a function), not the anon body. -fn opens_function_space(ri: usize) -> bool { - matches!( - ri, - jp::RULE_METHOD_DECLARATION - | jp::RULE_CONSTRUCTOR_DECLARATION - | jp::RULE_COMPACT_CONSTRUCTOR_DECLARATION - | jp::RULE_INTERFACE_COMMON_BODY_DECLARATION - | jp::RULE_ANNOTATION_METHOD_REST - | jp::RULE_LAMBDA_EXPRESSION - ) -} - -/// The body-declaration wrappers whose leading `modifier`s (including -/// annotations) are siblings of the member declaration. Their start line is -/// where the member truly begins, so a method/constructor space widens its -/// span up to it to cover own-line modifiers/annotations. -fn is_member_body_wrapper(ri: usize) -> bool { - matches!( - ri, - jp::RULE_CLASS_BODY_DECLARATION - | jp::RULE_INTERFACE_BODY_DECLARATION - | jp::RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION - ) -} - -/// Flatten a logical-operator (`&&`/`||`) expression tree into its operator -/// sequence in SOURCE ORDER, mirroring SonarJava's -/// `CognitiveComplexityVisitor.flattenLogicalExpression` and SonarKotlin's -/// `CognitiveComplexity.flattenOperators`: recurse into the left operand, -/// emit this node's operator, recurse into the right operand — descending only -/// into logical-binary children and skipping transparent parentheses / -/// pass-through wrappers. A `!` negation, a comparison (`==`, `<`, …), a -/// method call, etc. are NOT logical-binary, so flattening stops there (they -/// are plain operands) — matching SonarSource, where negation never breaks a -/// boolean run. The caller counts +1 whenever the operator kind changes across -/// the resulting sequence. A depth bound guards against pathological nesting. -fn flatten_logical_operators(ctx: RuleNodeView<'_>, out: &mut Vec) { - flatten_logical_operators_inner(ctx, out, 0); -} - -fn flatten_logical_operators_inner(ctx: RuleNodeView<'_>, out: &mut Vec, depth: usize) { - if depth > 64 { - return; - } - // Unwrap a transparent operand — a parenthesized `primary` (`'(' expression - // ')'`) or a pass-through `expression` with no operator token of its own — - // to the logical-binary expression it may contain. - let Some(logical) = unwrap_to_logical(ctx, depth) else { - return; - }; - let op = if logical.has_token(jl::AND) { - BoolOp::And - } else if logical.has_token(jl::OR) { - BoolOp::Or - } else { - return; - }; - // `expression op expression` — left operand, this operator, right operand. - let operands: Vec> = logical.children().filter_map(|c| c.as_rule()).collect(); - if let Some(&left) = operands.first() { - flatten_logical_operators_inner(left, out, depth + 1); - } - out.push(op); - if let Some(&right) = operands.get(1) { - flatten_logical_operators_inner(right, out, depth + 1); - } -} - -/// Resolve `ctx` to a logical-binary (`&&`/`||`) `expression`, unwrapping -/// transparent parenthesis (`primary`) and single-child pass-through -/// `expression` wrappers. Returns `None` when `ctx` is not (and does not -/// transparently wrap) a logical-binary expression — i.e. it is a plain -/// operand (identifier, comparison, negation, call, …) where flattening stops. -fn unwrap_to_logical(ctx: RuleNodeView<'_>, depth: usize) -> Option> { - if depth > 64 { - return None; - } - match ctx.rule_index() { - jp::RULE_EXPRESSION => { - if ctx.has_token(jl::AND) || ctx.has_token(jl::OR) { - return Some(ctx); - } - // A transparent expression (a bare operand or single wrapped - // sub-expression, no operator token of its own) — unwrap and retry. - if !expression_has_operator_token(ctx) { - return ctx - .children() - .filter_map(|c| c.as_rule()) - .find_map(|rule| unwrap_to_logical(rule, depth + 1)); - } - None - } - // `primary: '(' expression ')'` — unwrap the parenthesized expression. - jp::RULE_PRIMARY => ctx - .children() - .filter_map(|c| c.as_rule()) - .find_map(|rule| unwrap_to_logical(rule, depth + 1)), - _ => None, - } -} - -/// Whether an `expression` context carries its own operator — i.e. has any -/// direct terminal (token) child. A transparent operand expression (`a`, or a -/// single wrapped sub-expression) has only rule children and no tokens; an -/// operator form (`==`, `<`, ternary `? :`, index `[]`, unary, `instanceof`, a -/// method/creator call, `.` access, …) always has at least one token child. -/// Used by the cognitive boolean-run collapse: only a token-less (transparent) -/// expression forwards the enclosing `&&`/`||`; anything with its own operator -/// starts a fresh boolean context. -fn expression_has_operator_token(ctx: RuleNodeView<'_>) -> bool { - ctx.children().any(|c| c.as_terminal().is_some()) -} - -/// The short-circuit boolean operator at the root of an `expression` node, if -/// any: `&&` → [`BoolOp::And`], `||` → [`BoolOp::Or`], else `None` (including -/// for non-`expression` nodes). Reads the typed `ExpressionContext` accessors -/// (`and_token()` is `&&`, distinct from `bitand_tokens()` `&`). Shared by the -/// cognitive boolean-run threading in `visit_children` and the per-operator -/// scoring in `classify_expression` so both derive the operator identically. -fn expression_bool_op(ctx: RuleNodeView<'_>) -> Option { - let expr = jp::ExpressionContext::from_rule_node(ctx)?; - if expr.and_token().is_some() { - Some(BoolOp::And) - } else if expr.or_token().is_some() { - Some(BoolOp::Or) - } else { - None - } -} - -/// Stable snake_case evidence detail for a short-circuit boolean operator. -fn bool_op_detail(op: BoolOp) -> &'static str { - match op { - BoolOp::And => "logical_and", - BoolOp::Or => "logical_or", - } -} - -/// Stable snake_case evidence detail for a method-shaped declaration rule — -/// the grammar rule that opens the function space / records the NPM member. -fn method_space_detail(ri: usize) -> &'static str { - match ri { - jp::RULE_METHOD_DECLARATION => "method_declaration", - jp::RULE_CONSTRUCTOR_DECLARATION => "constructor_declaration", - jp::RULE_COMPACT_CONSTRUCTOR_DECLARATION => "compact_constructor_declaration", - jp::RULE_INTERFACE_COMMON_BODY_DECLARATION => "interface_common_body_declaration", - jp::RULE_ANNOTATION_METHOD_REST => "annotation_method_rest", - _ => "method_declaration", - } -} - -/// Whether a `lambdaExpression`'s body is an expression (`lambdaBody: -/// expression`) rather than a block. An expression body is a single logical -/// line for LLOC; a block body's statements are counted individually. -fn lambda_body_is_expression(ctx: RuleNodeView<'_>) -> bool { - ctx.child_rule(jp::RULE_LAMBDA_BODY) - .map(|body| { - body.child_rule(jp::RULE_EXPRESSION).is_some() - && body.child_rule(jp::RULE_BLOCK).is_none() - }) - .unwrap_or(false) -} - -/// Whether this `statement` context is an `if` statement (has an `IF` token as -/// a direct child). -fn is_if_statement(ctx: RuleNodeView<'_>, ri: usize) -> bool { - ri == jp::RULE_STATEMENT && ctx.has_token(jl::IF) -} - -/// Whether the `is_else_branch` flag may propagate through this `statement` -/// toward a nested `if` (marking it an `else if`). -/// -/// True only for a *transparent wrapper* statement — one that introduces no -/// control-flow construct of its own and isn't a block. That covers a label -/// wrapper (`lbl: stmt`) or a bare-expression statement whose subtree leads to -/// the `if`. It is FALSE for: -/// - a `block` (`else { if … }` is genuinely nested); -/// - an `if` statement itself (its else child is targeted precisely via -/// `else_branch_index`, so the flag must not blanket-tag the then-branch); -/// - any statement carrying its own control-flow keyword -/// (`for`/`while`/`do`/`switch`/`try`/`synchronized`/`return`/`throw`/ -/// `break`/`continue`/`yield`/`assert`) — its body is a real nested scope, -/// not an else-if, so e.g. an `if` in `else while (c) if (b) {}` keeps its -/// nesting increment. -fn statement_is_else_transparent(ctx: RuleNodeView<'_>, ri: usize) -> bool { - ri == jp::RULE_STATEMENT - && !ctx_is_block(ctx) - && !ctx.has_token(jl::IF) - && !ctx.has_token(jl::FOR) - && !ctx.has_token(jl::WHILE) - && !ctx.has_token(jl::DO) - && !ctx.has_token(jl::SWITCH) - && !ctx.has_token(jl::TRY) - && !ctx.has_token(jl::SYNCHRONIZED) - && !ctx.has_token(jl::RETURN) - && !ctx.has_token(jl::THROW) - && !ctx.has_token(jl::BREAK) - && !ctx.has_token(jl::CONTINUE) - && !ctx.has_token(jl::YIELD) - && !ctx.has_token(jl::ASSERT) -} - -/// Whether this context is a bare block statement (`{ … }`) — a `statement` -/// whose only rule child is a `block`. -fn ctx_is_block(ctx: RuleNodeView<'_>) -> bool { - let mut rules = ctx.children().filter_map(|c| c.as_rule()); - matches!((rules.next(), rules.next()), (Some(only), None) - if only.rule_index() == jp::RULE_BLOCK) -} - -/// Whether this `statement` is an empty statement (a bare `;`) — its only -/// child is the `SEMI` terminal. Distinguished from `return;`/`break;` (which -/// carry a keyword terminal too) by requiring exactly one child. -fn ctx_is_empty_statement(ctx: RuleNodeView<'_>) -> bool { - let mut children = ctx.children(); - matches!( - (children.next(), children.next()), - (Some(only), None) - if only.as_terminal().is_some_and(|t| t.symbol().token_type() == jl::SEMI) - ) -} - -/// Whether this `statement` is a labeled-statement wrapper -/// (`identifierLabel = identifier ':' statement`) — its rule children are -/// exactly one `identifier` followed by one nested `statement`. The label is -/// an attribute of the inner statement (counted when visited), not its own -/// logical line. -fn ctx_is_label_wrapper(ctx: RuleNodeView<'_>) -> bool { - let mut rules = ctx - .children() - .filter_map(|c| c.as_rule().map(|r| r.rule_index())); - matches!( - (rules.next(), rules.next(), rules.next()), - (Some(jp::RULE_IDENTIFIER), Some(jp::RULE_STATEMENT), None) - ) -} - -/// Index of the `else`-branch `statement` child of an `if` statement, if -/// present. The else body is the `statement` that appears *after* the `ELSE` -/// terminal among the children. -fn else_branch_index<'a>(children: impl Iterator>) -> Option { - let mut seen_else = false; - for (idx, child) in children.enumerate() { - if let Some(t) = child.as_terminal() { - if t.symbol().token_type() == jl::ELSE { - seen_else = true; - } - } else if let Some(rule) = child.as_rule() - && seen_else - && rule.rule_index() == jp::RULE_STATEMENT - { - return Some(idx); - } - } - None -} - -/// The declared name of a type: its first `identifier`/`typeIdentifier` -/// child's covered text. -fn type_name(ctx: RuleNodeView<'_>) -> Option { - name_from_identifier(ctx) -} - -/// The declared name of a method/constructor: its first `identifier` child's -/// covered text. -fn method_name(ctx: RuleNodeView<'_>) -> Option { - name_from_identifier(ctx) -} - -/// Given a member body-declaration wrapper, find the inner method/constructor -/// declaration whose function space should be opened at the wrapper level — so -/// the wrapper's own-line modifiers/annotations (siblings of the declaration, -/// visited before the declaration node) belong to the method's -/// LOC/Halstead/span rather than the enclosing class/interface. -/// -/// Handles: -/// - `classBodyDeclaration` → (generic) method/constructor declaration; -/// - `interfaceBodyDeclaration` → `interfaceMethodDeclaration` / -/// `genericInterfaceMethodDeclaration` → `interfaceCommonBodyDeclaration`; -/// - `annotationTypeElementDeclaration` → `annotationTypeElementRest` → -/// `annotationMethodOrConstantRest` → `annotationMethodRest`. -/// -/// Returns the node that would otherwise open the space (the same node the -/// declaration-arm opens), or `None` when the member is not a method-shaped -/// declaration (a field, nested type, const, compact ctor — those keep their -/// existing open sites). -fn wrapper_inner_method(ctx: RuleNodeView<'_>) -> Option> { - // Navigate via the generated typed contexts (named `Option`/`Result` - // accessors reach only the declared direct child of each rule), then hand - // back the underlying `RuleNodeView` the caller opens a space for. The - // typed accessors enforce the "direct child only" property that the anti- - // descend comments below spell out by hand. - match ctx.rule_index() { - jp::RULE_CLASS_BODY_DECLARATION => { - let member = - jp::ClassBodyDeclarationContext::from_rule_node(ctx)?.member_declaration()?; - // `method`/`constructor` are direct; the generic forms wrap the - // real declaration one level down. - if let Some(m) = member.method_declaration() { - return Some(m.rule_node()); - } - if let Some(c) = member.constructor_declaration() { - return Some(c.rule_node()); - } - if let Some(g) = member.generic_method_declaration() { - return g.method_declaration().ok().map(|m| m.rule_node()); - } - if let Some(g) = member.generic_constructor_declaration() { - return g.constructor_declaration().ok().map(|c| c.rule_node()); - } - None - } - // Interface method: walk the DIRECT path interfaceBodyDeclaration → - // interfaceMemberDeclaration → (generic)interfaceMethodDeclaration → - // interfaceCommonBodyDeclaration. `interfaceCommonBodyDeclaration` is a - // direct child of both method-declaration forms, so the typed accessors - // (never an unbounded search) can't reach a nested type's method. - jp::RULE_INTERFACE_BODY_DECLARATION => { - let member = jp::InterfaceBodyDeclarationContext::from_rule_node(ctx)? - .interface_member_declaration()?; - let common = match ( - member.interface_method_declaration(), - member.generic_interface_method_declaration(), - ) { - (Some(d), _) => d.interface_common_body_declaration().ok()?, - (None, Some(g)) => g.interface_common_body_declaration().ok()?, - (None, None) => return None, - }; - Some(common.rule_node()) - } - // Annotation element: walk the DIRECT path - // annotationTypeElementDeclaration → annotationTypeElementRest → - // annotationMethodOrConstantRest → annotationMethodRest. The typed - // accessors reach only named direct children, so — unlike an unbounded - // `find_descendant` — they never dip into `annotationTypeElementRest`'s - // nested-type alternatives (`annotationTypeDeclaration`, - // `classDeclaration`, …). That is what keeps a nested annotation's - // element from opening a phantom method on the outer type - // (`@interface A { @interface B { String v(); } }` → no method on `A`). - // `None` when the element is a nested type or a constant, not a method. - jp::RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION => Some( - jp::AnnotationTypeElementDeclarationContext::from_rule_node(ctx)? - .annotation_type_element_rest()? - .annotation_method_or_constant_rest()? - .annotation_method_rest()? - .rule_node(), - ), - _ => None, - } -} - -/// The wrapper rules whose own-line modifiers/annotations should be folded into -/// the type-declaration space opened beneath them (mirrors `wrapper_inner_type` -/// / the method wrappers). A top-level type wraps in `typeDeclaration`; a -/// method-local type in `localTypeDeclaration`; a member type in one of the -/// body-declaration wrappers. -fn is_type_wrapper(ri: usize) -> bool { - matches!( - ri, - jp::RULE_TYPE_DECLARATION - | jp::RULE_LOCAL_TYPE_DECLARATION - | jp::RULE_CLASS_BODY_DECLARATION - | jp::RULE_INTERFACE_BODY_DECLARATION - | jp::RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION - ) -} - -/// Given a type wrapper (`typeDeclaration`/`localTypeDeclaration` or a member -/// body-declaration), find the inner class-like declaration whose space should -/// be opened at the wrapper — so the wrapper's own-line modifiers/annotations -/// (`@Deprecated\npublic class C {}`, `public static class Inner {}`) belong to -/// the type's LOC/Halstead/span rather than the enclosing space. Descends the -/// direct `child_rule` path (never an unbounded search — a body wrapper's -/// member alternatives include *other* declarations whose own nested types must -/// not be captured here). Returns `None` when the member is not a class-like -/// type (a field, method, const, etc. keep their existing sites). -fn wrapper_inner_type(ctx: RuleNodeView<'_>) -> Option> { - let holder = match ctx.rule_index() { - // typeDeclaration / localTypeDeclaration hold the type declaration as a - // direct child (after `classOrInterfaceModifier*`). - jp::RULE_TYPE_DECLARATION | jp::RULE_LOCAL_TYPE_DECLARATION => ctx, - // A member type is `classBodyDeclaration → memberDeclaration → ` - // (or the interface/annotation equivalents). - jp::RULE_CLASS_BODY_DECLARATION => ctx.child_rule(jp::RULE_MEMBER_DECLARATION)?, - jp::RULE_INTERFACE_BODY_DECLARATION => { - ctx.child_rule(jp::RULE_INTERFACE_MEMBER_DECLARATION)? - } - jp::RULE_ANNOTATION_TYPE_ELEMENT_DECLARATION => { - ctx.child_rule(jp::RULE_ANNOTATION_TYPE_ELEMENT_REST)? - } - _ => return None, - }; - for child in holder.children() { - if let Some(c) = child.as_rule() - && opens_class_like(c.rule_index()) - { - return Some(c); - } - } - None -} - -fn name_from_identifier(ctx: RuleNodeView<'_>) -> Option { - for child in ctx.children() { - if let Some(c) = child.as_rule() - && matches!( - c.rule_index(), - jp::RULE_IDENTIFIER | jp::RULE_TYPE_IDENTIFIER - ) - { - let t = c.text(); - if !t.is_empty() { - return Some(t); - } - } - } - None -} - -/// Count the declared formal parameters of a method/constructor. -/// -/// The grammar's `formalParameters` rule is asymmetric: -/// `'(' ((receiverParameter | formalParameter) (',' formalParameterList)*)? ')'` -/// — the *first* parameter is a direct `formalParameter` child of -/// `formalParameters`, and the *remaining* parameters live in a nested -/// `formalParameterList`. So the count is the direct `formalParameter` -/// children plus the `formalParameterList`'s `formalParameter`s. A leading -/// `receiverParameter` (`Foo this`) is not a value parameter and is excluded. -/// A trailing varargs (`int... rest`) is a plain `formalParameter` here. -fn count_formal_params(ctx: RuleNodeView<'_>) -> u32 { - // `find_descendant` has no typed equivalent (the typed contexts expose - // named direct children, not arbitrary-depth search), so it stays; the - // `formalParameters` subtree is then read through its typed context. - let Some(params) = find_descendant(ctx, jp::RULE_FORMAL_PARAMETERS) - .and_then(jp::FormalParametersContext::from_rule_node) - else { - return 0; - }; - // Grammar: `'(' ((receiverParameter | formalParameter) (',' formalParameterList)*)? ')'` - // — the first value parameter is a direct `formalParameter`, the rest live - // in a nested `formalParameterList`. A leading `receiverParameter` - // (`Foo this`) is excluded (it is a separate optional child). - let direct = u32::from(params.formal_parameter().is_some()); - let in_list: u32 = params - .formal_parameter_list_children() - .map(|list| list.formal_parameter_children().count() as u32) - .sum(); - direct + in_list -} - -/// Count lambda parameters. A lambda's parameters are either a single bare -/// `identifier`, a parenthesized `formalParameterList`, or a -/// `lambdaLVTIList`/identifier list. -fn count_lambda_args(ctx: RuleNodeView<'_>) -> u32 { - let Some(params) = jp::LambdaExpressionContext::from_rule_node(ctx) - .and_then(|lambda| lambda.lambda_parameters().ok()) - else { - return 0; - }; - // `(a, b) -> …` → formalParameterList; `(var a, var b) -> …` → - // lambdaLVTIList; `x -> …` → a single bare identifier; `(x, y) -> …` → - // a comma-separated identifier list. - if let Some(list) = params.formal_parameter_list() { - return list.formal_parameter_children().count() as u32; - } - if let Some(list) = params.lambda_lvti_list() { - return list.lambda_lvti_parameter_children().count() as u32; - } - - params.identifier_children().count() as u32 -} - -/// Count the variables declared by a `fieldDeclaration` -/// (`int a, b, c;` → 3), via `variableDeclarators → variableDeclarator`. -fn field_variable_count(ctx: RuleNodeView<'_>) -> u32 { - let Some(field) = jp::FieldDeclarationContext::from_rule_node(ctx) else { - return 0; - }; - field - .variable_declarators() - .ok() - .map(|vds| vds.variable_declarator_children().count() as u32) - .unwrap_or(0) -} - -/// Record a record's component parameters as class attributes (NPA). Walks -/// `recordDeclaration → recordHeader → recordComponentList → recordComponent`. -fn record_record_components(ctx: RuleNodeView<'_>, state: &mut State) { - let count = count_record_components(ctx); - for _ in 0..count { - state.npa.record_attribute(ContainerKind::Class, true); - } -} - -/// Count a record's declared components via -/// `recordDeclaration → recordHeader → recordComponentList → recordComponent`. -/// These are both the record's public attributes (NPA) and the parameter list -/// of its (canonical/compact) constructor (NArgs). -/// -/// Uses the generated typed context (0.15 runtime) so the navigation is by -/// named, grammar-checked accessors rather than raw `RULE_*` indices: -/// `record_header()` is a required child (`Result`), the component list is -/// optional (`Option`), and the components are a repeated child (iterator). -fn count_record_components(ctx: RuleNodeView<'_>) -> u32 { - let Some(record) = jp::RecordDeclarationContext::from_rule_node(ctx) else { - return 0; - }; - record - .record_header() - .ok() - .and_then(|header| header.record_component_list()) - .map(|list| list.record_component_children().count() as u32) - .unwrap_or(0) -} - -/// Resolve an explicit visibility from a body-declaration wrapper's -/// `modifier`s: `Some(false)` if any `modifier` carries `private`/`protected`, -/// `Some(true)` if one carries `public`, `None` if no visibility modifier is -/// present (caller applies the container default). -/// -/// `ctx` is the body-declaration wrapper (`classBodyDeclaration`, -/// `interfaceBodyDeclaration`, …); its `modifier` children are siblings of the -/// member declaration, which is where Java places visibility keywords. The -/// `modifier` rule wraps a `classOrInterfaceModifier`, so we scan two levels -/// for the visibility token. -fn visibility_from_modifiers(ctx: RuleNodeView<'_>) -> Option { - for modifier in ctx.child_rules(jp::RULE_MODIFIER) { - if let Some(vis) = visibility_token(modifier) { - return Some(vis); - } - } - // Interface body declarations wrap modifiers in `modifier` too, but a - // record/enum body may present a bare `classOrInterfaceModifier`; scan - // those directly as well. - for m in ctx.child_rules(jp::RULE_CLASS_OR_INTERFACE_MODIFIER) { - if let Some(vis) = visibility_from_token_holder(m) { - return Some(vis); - } - } - None -} - -/// Read a visibility token from a `modifier` context, descending into its -/// `classOrInterfaceModifier` child if present. -fn visibility_token(modifier: RuleNodeView<'_>) -> Option { - if let Some(v) = visibility_from_token_holder(modifier) { - return Some(v); - } - for coi in modifier.child_rules(jp::RULE_CLASS_OR_INTERFACE_MODIFIER) { - if let Some(v) = visibility_from_token_holder(coi) { - return Some(v); - } - } - None -} - -/// Read `public`/`private`/`protected` directly from a context's token -/// children. -fn visibility_from_token_holder(ctx: RuleNodeView<'_>) -> Option { - if ctx.has_token(jl::PUBLIC) { - return Some(true); - } - if ctx.has_token(jl::PRIVATE) || ctx.has_token(jl::PROTECTED) { - return Some(false); - } - None -} - -/// Whether an `expression` context carries a top-level assignment operator as -/// a direct child token: `=`, a compound assign (`+=`, `-=`, …), or an -/// increment/decrement (`++`, `--`). Fitzpatrick's ABC lists `++`/`--` under -/// the assignment (A) component alongside `=`. -/// -/// Reads the operators through the generated typed `ExpressionContext` -/// accessors (0.15.2 runtime, issue #178) — `assign_token()`, the eleven -/// compound-assign accessors, `inc_token()`/`dec_token()` — instead of -/// `has_token(jl::…)` integer probing. All are `Option`. -fn has_assignment_op(ctx: RuleNodeView<'_>) -> bool { - let Some(expr) = jp::ExpressionContext::from_rule_node(ctx) else { - return false; - }; - expr.assign_token().is_some() - || expr.add_assign_token().is_some() - || expr.sub_assign_token().is_some() - || expr.mul_assign_token().is_some() - || expr.div_assign_token().is_some() - || expr.and_assign_token().is_some() - || expr.or_assign_token().is_some() - || expr.xor_assign_token().is_some() - || expr.mod_assign_token().is_some() - || expr.lshift_assign_token().is_some() - || expr.rshift_assign_token().is_some() - || expr.urshift_assign_token().is_some() - || expr.inc_token().is_some() - || expr.dec_token().is_some() -} - -/// Whether an `expression` carries a top-level `++`/`--` operator — the -/// "update" subset of [`has_assignment_op`], named separately in the ABC -/// assignment evidence reason (`java.abc.assignment.update_expression`). -fn has_update_op(ctx: RuleNodeView<'_>) -> bool { - jp::ExpressionContext::from_rule_node(ctx) - .is_some_and(|expr| expr.inc_token().is_some() || expr.dec_token().is_some()) -} - -/// Find the first descendant rule with `rule_index`, searching direct children -/// then recursing. Used for parameter lists that may sit under an intermediate -/// wrapper (e.g. `genericMethodDeclaration → methodDeclaration`). -/// -/// Searches *descendants* (children-first), never `ctx` itself. The runtime's -/// [`Node::first_rule`](mehen_antlr::runtime::Node::first_rule) includes the -/// receiver in its pre-order search, so it is applied per child here to keep -/// the original "descendants only" semantics. -fn find_descendant(ctx: RuleNodeView<'_>, rule_index: usize) -> Option> { - ctx.children() - .find_map(|child| child.first_rule(rule_index)) - .and_then(|node| node.as_rule()) -} - -fn container_kind(parent_kind: SpaceKind) -> ContainerKind { - match parent_kind { - SpaceKind::Class | SpaceKind::Impl | SpaceKind::Enum => ContainerKind::Class, - SpaceKind::Interface | SpaceKind::Trait => ContainerKind::Interface, - _ => ContainerKind::Other, - } -} - -// -------------------------------------------------------------------- -// Halstead token classification. -// -------------------------------------------------------------------- - -enum HalsteadClass { - Operator, - Operand, - Skip, -} - -/// Classify a token type as a Halstead operator, operand, or skipped. -/// -/// Operands: identifiers, literals, `this`, `super`. Skipped: whitespace, -/// comments, EOF. Everything else (keywords, punctuation, operators) is an -/// operator. -fn halstead_class(tt: i32) -> HalsteadClass { - if matches!( - tt, - jl::IDENTIFIER - | jl::DECIMAL_LITERAL - | jl::HEX_LITERAL - | jl::OCT_LITERAL - | jl::BINARY_LITERAL - | jl::FLOAT_LITERAL - | jl::HEX_FLOAT_LITERAL - | jl::BOOL_LITERAL - | jl::CHAR_LITERAL - | jl::STRING_LITERAL - | jl::TEXT_BLOCK - | jl::NULL_LITERAL - | jl::THIS - | jl::SUPER - ) { - return HalsteadClass::Operand; - } - - if matches!(tt, jl::WS | jl::COMMENT | jl::LINE_COMMENT) || tt < 0 { - return HalsteadClass::Skip; - } - - HalsteadClass::Operator -} - -/// A stable string label for an operator token, used as its Halstead operator -/// key. The numeric token type is stable for a given generated grammar. -fn kp_token_name(tt: i32) -> String { - format!("t{tt}") -} diff --git a/crates/mehen-java/tests/abc.rs b/crates/mehen-java/tests/abc.rs deleted file mode 100644 index e93fe9a3..00000000 --- a/crates/mehen-java/tests/abc.rs +++ /dev/null @@ -1,377 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC (Assignments / Branches / Conditions) tests for the ANTLR Java walker. -//! -//! A = assignments (`=`, compound assigns, declarators with an initializer); -//! B = branches (method/constructor calls, `new`); C = conditions (comparison -//! & equality operators, `&&`/`||`, ternary, `instanceof`, and each -//! `if`/`case`/`catch`/loop test). `magnitude = sqrt(A² + B² + C²)`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn assignments_branches_conditions() { - // A: `int r = a + b;` initializer (1) + `r += bump();` compound (1) = 2 - // B: `bump()` call (1) - // C: `if (a > b)` test (1) + `>` operator (1) = 2 - let a = analyze( - "class C { - int f(int a, int b) { - int r = a + b; - if (a > b) { r += bump(); } - return r; - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!(abc, @r#" - { - "assignments": 2.0, - "branches": 1.0, - "conditions": 2.0, - "magnitude": 3.0, - "assignments_average": 0.6666666666666666, - "branches_average": 0.3333333333333333, - "conditions_average": 0.6666666666666666, - "assignments_min": 0.0, - "assignments_max": 2.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 2.0 - } - "#); -} - -#[test] -fn increment_decrement_count_as_assignments() { - // Regression (audit): `++`/`--` are assignments (A) per Fitzpatrick's ABC. - // `i++;` and `--j;` → A=2. No conditions/branches. - let a = analyze( - "class C { - void f() { - int i = 0, j = 0; - i++; - --j; - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - // A: two declarators with initializers (2) + i++ (1) + --j (1) = 4. - insta::assert_json_snapshot!(abc, @r#" - { - "assignments": 4.0, - "branches": 0.0, - "conditions": 0.0, - "magnitude": 4.0, - "assignments_average": 1.3333333333333333, - "branches_average": 0.0, - "conditions_average": 0.0, - "assignments_min": 0.0, - "assignments_max": 4.0, - "branches_min": 0.0, - "branches_max": 0.0, - "conditions_min": 0.0, - "conditions_max": 0.0 - } - "#); -} - -#[test] -fn bit_shifts_are_not_conditions() { - // Regression (audit): `<<`/`>>`/`>>>` must NOT count as ABC conditions - // (they decompose into bare LT/GT tokens). A relational `<` still does. - let shift = analyze( - "class C { - int f(int a, int b) { return (a << b) + (a >> b) + (a >>> b); } - }", - ); - let abc_shift = mehen_report::metrics_json::abc(&shift.root.metrics); - insta::assert_json_snapshot!(abc_shift, @r#" - { - "assignments": 0.0, - "branches": 0.0, - "conditions": 0.0, - "magnitude": 0.0, - "assignments_average": 0.0, - "branches_average": 0.0, - "conditions_average": 0.0, - "assignments_min": 0.0, - "assignments_max": 0.0, - "branches_min": 0.0, - "branches_max": 0.0, - "conditions_min": 0.0, - "conditions_max": 0.0 - } - "#); -} - -#[test] -fn var_and_resource_initializers_count_as_assignments() { - // Regression (audit): `var x = e` and try-with-resources `T r = e` are - // initialized declarations → assignments, like `int x = e`. - let a = analyze( - "class C { - void f() { - var x = compute(); - try (AutoCloseable r = open()) { use(r); } catch (Exception e) {} - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!(abc, @r#" - { - "assignments": 2.0, - "branches": 3.0, - "conditions": 1.0, - "magnitude": 3.7416573867739413, - "assignments_average": 0.6666666666666666, - "branches_average": 1.0, - "conditions_average": 0.3333333333333333, - "assignments_min": 0.0, - "assignments_max": 2.0, - "branches_min": 0.0, - "branches_max": 3.0, - "conditions_min": 0.0, - "conditions_max": 1.0 - } - "#); -} - -#[test] -fn explicit_generic_invocation_is_a_branch() { - // Regression (PR #160 review): `this.m()` routes through - // `explicitGenericInvocation`, not `methodCall`, so it must be counted as - // an ABC branch too. Here: B=1 (the generic call). - let a = analyze( - "class C { - T m() { return null; } - void f() { this.m(); } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!(abc, @r#" - { - "assignments": 0.0, - "branches": 1.0, - "conditions": 0.0, - "magnitude": 1.0, - "assignments_average": 0.0, - "branches_average": 0.25, - "conditions_average": 0.0, - "assignments_min": 0.0, - "assignments_max": 0.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 0.0 - } - "#); -} - -#[test] -fn suffix_routed_calls_are_branches() { - // Regression (PR #160 review): calls that don't route through `methodCall` - // must still count as ABC branches, exactly once each: - // - `I.super.d()` → superSuffix - // - `m()` → explicitGenericInvocationSuffix (unqualified) - // - `this.m()` → explicitGenericInvocation(Suffix) (qualified) - for (src, label) in [ - ( - "interface I { default void d() {} } class C implements I { void f() { I.super.d(); } }", - "I.super.d()", - ), - ( - "class C { T m() { return null; } void f() { m(); } }", - "m()", - ), - ( - "class C { T m() { return null; } void f() { this.m(); } }", - "this.m()", - ), - ] { - let a = analyze(src); - let abc = serde_json::to_value(mehen_report::metrics_json::abc(&a.root.metrics)).unwrap(); - assert_eq!( - abc["branches"], - serde_json::json!(1.0), - "exactly one branch for: {label}" - ); - } -} - -#[test] -fn generic_explicit_this_constructor_call_is_a_branch() { - // Regression (PR #160 review): a generic explicit constructor invocation - // (`this(arg)`) routes through `primary: nonWildcardTypeArguments - // THIS arguments`, not `methodCall`, so it must be counted as an ABC - // branch too. The plain `this(…)`/`super(…)` forms go through `methodCall`. - let a = analyze("class C { C(T t) {} C() { this(null); } }"); - let abc = serde_json::to_value(mehen_report::metrics_json::abc(&a.root.metrics)).unwrap(); - assert_eq!( - abc["branches"], - serde_json::json!(1.0), - "a generic explicit this-constructor call is a branch" - ); - // Guard: a bare `this` / `this.field` access (no `arguments`) is not a call. - let field = analyze("class C { int x; int m() { return this.x; } }"); - let fabc = serde_json::to_value(mehen_report::metrics_json::abc(&field.root.metrics)).unwrap(); - assert_eq!( - fabc["branches"], - serde_json::json!(0.0), - "a bare `this` field access is not a branch" - ); -} - -#[test] -fn qualified_super_field_access_is_not_a_branch() { - // Regression (PR #160 review): `superSuffix` also represents qualified - // super *field* access (`Outer.super.field`), where the grammar's - // `arguments` child is optional. A bare field read is NOT a call, so it - // must not count as an ABC branch — only a `superSuffix` with an - // `arguments` child (a real call) does. - let a = analyze( - "class Outer { - int field; - class Inner extends Outer { - int f() { return Outer.super.field; } - } - }", - ); - let abc = serde_json::to_value(mehen_report::metrics_json::abc(&a.root.metrics)).unwrap(); - assert_eq!( - abc["branches"], - serde_json::json!(0.0), - "a super field read is not a branch" - ); -} - -#[test] -fn annotation_named_element_is_not_an_assignment() { - // Regression (PR #160 review): the vendored grammar's `IsNotIdentifierAssign` - // predicate is dropped by the Rust generator, so `@Ann(value = 1)`'s named - // element value parses through the assignment-expression path with an `=`. - // Annotation metadata is not executable code, so it must NOT count as an - // ABC assignment. - let a = analyze("class C { @Ann(value = 1) void m() {} }"); - let abc = serde_json::to_value(mehen_report::metrics_json::abc(&a.root.metrics)).unwrap(); - assert_eq!( - abc["assignments"], - serde_json::json!(0.0), - "an annotation named-element value is not an assignment" - ); - // Guard: a real assignment in the body of an annotated method still counts - // (the `in_annotation` flag must not leak past the annotation subtree). - let with_body = analyze("class C { @Ann(value = 1) void m() { int x = 5; } }"); - let wb = - serde_json::to_value(mehen_report::metrics_json::abc(&with_body.root.metrics)).unwrap(); - assert_eq!( - wb["assignments"], - serde_json::json!(1.0), - "a real assignment in an annotated method's body still counts" - ); -} - -#[test] -fn switch_guard_is_a_condition() { - // Regression (PR #160 review): a Java pattern-switch guard - // (`case String s when ready -> …`, grammar `guard: 'when' expression`) is - // a distinct boolean test — like an extra `if` on the case — so it must - // record an ABC condition. Using a bare boolean operand (`ready`) isolates - // the guard: without the fix no expression operator fires, so the guard's - // test would be uncounted. Here: C = the `case` (1) + the guard (1) = 2. - let a = analyze( - "class C { - boolean ready; - int f(Object o) { - return switch (o) { - case String s when ready -> 1; - default -> 0; - }; - } - }", - ); - let abc = serde_json::to_value(mehen_report::metrics_json::abc(&a.root.metrics)).unwrap(); - assert_eq!( - abc["conditions"], - serde_json::json!(2.0), - "a guarded pattern case counts the case AND the guard as conditions" - ); - // Guard: operators inside the guard still count on top of the guard test. - // `case String s when a > b` → case (1) + guard (1) + `>` (1) = 3. - let with_op = analyze( - "class C { - int f(Object o, int a, int b) { - return switch (o) { - case String s when a > b -> 1; - default -> 0; - }; - } - }", - ); - let wabc = - serde_json::to_value(mehen_report::metrics_json::abc(&with_op.root.metrics)).unwrap(); - assert_eq!( - wabc["conditions"], - serde_json::json!(3.0), - "an operator inside the guard adds a condition on top of the guard test" - ); - // Guard: an unguarded pattern case (no `when`) counts only the case. - let unguarded = analyze( - "class C { - int f(Object o) { - return switch (o) { - case String s -> 1; - default -> 0; - }; - } - }", - ); - let uabc = - serde_json::to_value(mehen_report::metrics_json::abc(&unguarded.root.metrics)).unwrap(); - assert_eq!( - uabc["conditions"], - serde_json::json!(1.0), - "an unguarded pattern case counts only the case, not a phantom guard" - ); -} - -#[test] -fn object_creation_is_a_branch() { - // B: `new Object()` (1) + no other calls. A: `Object o = …` initializer (1). - let a = analyze( - "class C { - void f() { - Object o = new Object(); - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!(abc, @r#" - { - "assignments": 1.0, - "branches": 1.0, - "conditions": 0.0, - "magnitude": 1.4142135623730951, - "assignments_average": 0.3333333333333333, - "branches_average": 0.3333333333333333, - "conditions_average": 0.0, - "assignments_min": 0.0, - "assignments_max": 1.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 0.0 - } - "#); -} diff --git a/crates/mehen-java/tests/cognitive.rs b/crates/mehen-java/tests/cognitive.rs deleted file mode 100644 index 345d4975..00000000 --- a/crates/mehen-java/tests/cognitive.rs +++ /dev/null @@ -1,624 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity tests for the ANTLR Java walker (SonarSource rules). -//! -//! Nesting increments (`+1` plus the current nesting level): `if`, loops, -//! `switch`, `catch`, and the ternary. Flat `+1`: `else`/`else if`, labeled -//! `break`/`continue`. Sequences of like boolean operators collapse. `else if` -//! does not add a nesting level. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn nested_structures_accumulate_nesting() { - // for(+1) → if(+2) → while(+3) = 6. - let a = analyze( - "class C { - void f(int[] xs) { - for (int x : xs) { - if (x > 0) { - while (x > 0) { x--; } - } - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 6.0, - "average": 6.0, - "min": 0.0, - "max": 6.0 - } - "###); -} - -#[test] -fn boolean_sequence_collapses_like_operators() { - // `if`(+1) then `a && b || c`: one `&&` run (+1) and one `||` run (+1) = 3. - let a = analyze( - "class C { - boolean check(boolean a, boolean b, boolean c) { - if (a && b || c) { return true; } - return false; - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "###); -} - -#[test] -fn mixed_boolean_operators_count_each_run() { - // `if`(+1) then `a && b || c && d`: three like-operator runs — the first - // `&&` (+1), the `||` (+1), and the second `&&` (+1) — because switching - // operator ends a run and switching back starts a new one. Total = 4. - let a = analyze( - "class C { - boolean check(boolean a, boolean b, boolean c, boolean d) { - if (a && b || c && d) { return true; } - return false; - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - } - "###); -} - -#[test] -fn else_if_does_not_add_nesting() { - // if(+1), else if → flat else(+1) + the if is an else-branch so no - // nesting, else(+1) = 3 total. - let a = analyze( - "class C { - int f(int x) { - if (x > 2) { return 2; } - else if (x > 1) { return 1; } - else { return 0; } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "###); -} - -#[test] -fn parentheses_do_not_break_boolean_run_collapse() { - // Regression (PR #160 review): a parenthesized boolean sub-expression - // (`primary: '(' expression ')'`) must stay in the same boolean run. All - // three forms below are a single `&&` run → cognitive 2 (if=1, one run=1). - for src in [ - "class C { boolean f(boolean a, boolean b, boolean c) { if ((a && b) && c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && (b && c)) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && b && c) return true; return false; } }", - ] { - let a = analyze(src); - let cog = - serde_json::to_value(mehen_report::metrics_json::cognitive(&a.root.metrics)).unwrap(); - assert_eq!( - cog["sum"], - serde_json::json!(2.0), - "boolean run should collapse for: {src}" - ); - } -} - -#[test] -fn negation_does_not_break_boolean_run() { - // A prefix `!` negation does NOT break a same-operator boolean run. Both - // SonarJava (`CognitiveComplexityVisitor.flattenLogicalExpression`) and - // SonarKotlin (`CognitiveComplexity.flattenOperators`) flatten only the - // `&&`/`||` operators and treat a negated operand as a plain operand where - // flattening stops — the `!` is invisible to the run. So `a && !b && c` is - // a single `&&` run: if(+1) + one run(+1) = 2, exactly like `a && b && c`. - let neg = analyze( - "class C { - boolean f(boolean a, boolean b, boolean c) { - if (a && !b && c) return true; - return false; - } - }", - ); - let nj = - serde_json::to_value(mehen_report::metrics_json::cognitive(&neg.root.metrics)).unwrap(); - assert_eq!( - nj["sum"], - serde_json::json!(2.0), - "negation must not break the run" - ); - // Same score without the negation. - let plain = analyze( - "class C { - boolean f(boolean a, boolean b, boolean c) { - if (a && b && c) return true; - return false; - } - }", - ); - let pj = - serde_json::to_value(mehen_report::metrics_json::cognitive(&plain.root.metrics)).unwrap(); - assert_eq!(pj["sum"], serde_json::json!(2.0)); - // Multiple negations, leading/trailing/middle — still one run. - for src in [ - "class C { boolean f(boolean a, boolean b, boolean c) { if (!a && b && c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && b && !c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (!a && !b && !c) return true; return false; } }", - ] { - let a = analyze(src); - let cog = - serde_json::to_value(mehen_report::metrics_json::cognitive(&a.root.metrics)).unwrap(); - assert_eq!( - cog["sum"], - serde_json::json!(2.0), - "negations are ignored: {src}" - ); - } -} - -#[test] -fn parenthesized_negation_does_not_break_boolean_run() { - // A `!` negation is ignored by the boolean-run flatten regardless of - // parenthesization, so `a && (!b) && c` / `a && ((!b)) && c` are a single - // `&&` run → cognitive 2, exactly like `a && (b) && c`. - for src in [ - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && (!b) && c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && ((!b)) && c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && (b) && c) return true; return false; } }", - "class C { boolean f(boolean a, int b, boolean c) { if (a && (b != 0) && c) return true; return false; } }", - ] { - let a = analyze(src); - let cog = - serde_json::to_value(mehen_report::metrics_json::cognitive(&a.root.metrics)).unwrap(); - assert_eq!( - cog["sum"], - serde_json::json!(2.0), - "paren negation is ignored, single run: {src}" - ); - } -} - -#[test] -fn mixed_operator_through_parentheses_splits_the_run() { - // Regression (PR #160 review): SonarSource flattens the boolean tree in - // source order, SKIPPING parentheses, then +1 per operator-kind change. So - // a parenthesized *opposite* operator interrupts the outer run: - // `a && (b || c) && d` flattens to `&& || &&` → 3 boolean increments, + - // if(1) = 4 — the same as the unparenthesized `a && b || c && d`. A - // parenthesized *same* operator stays one run: `a && (b && c) && d` = 2. - let cases = [ - ("if (a && (b || c) && d)", 4.0), - ("if (a || (b && c) || d)", 4.0), - ("if (a && (b && c) && d)", 2.0), - ("if (a && (b || c))", 3.0), - ]; - for (cond, want) in cases { - let src = format!( - "class C {{ boolean f(boolean a, boolean b, boolean c, boolean d) {{ {cond} return true; return false; }} }}" - ); - let a = analyze(&src); - let cog = - serde_json::to_value(mehen_report::metrics_json::cognitive(&a.root.metrics)).unwrap(); - assert_eq!( - cog["sum"], - serde_json::json!(want), - "mixed-operator flatten (skip parens): {cond}" - ); - } -} - -#[test] -fn leading_negation_does_not_break_boolean_run() { - // A leading `!` is ignored like any negation: `!a && b && c` is a single - // `&&` run → cognitive 2. - for src in [ - "class C { boolean f(boolean a, boolean b, boolean c) { if (!a && b && c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if ((!a) && b && c) return true; return false; } }", - ] { - let a = analyze(src); - let cog = - serde_json::to_value(mehen_report::metrics_json::cognitive(&a.root.metrics)).unwrap(); - assert_eq!( - cog["sum"], - serde_json::json!(2.0), - "a leading negation must not break the run: {src}" - ); - } - // Multiple negations in one run are all ignored — `!a && !b && c` is still a - // single `&&` run → cognitive 2. - let mid = analyze( - "class C { boolean f(boolean a, boolean b, boolean c) { if (!a && !b && c) return true; return false; } }", - ); - let mj = - serde_json::to_value(mehen_report::metrics_json::cognitive(&mid.root.metrics)).unwrap(); - assert_eq!( - mj["sum"], - serde_json::json!(2.0), - "multiple negations do not break the run" - ); -} - -#[test] -fn negation_adjacent_to_operator_switch_counts_only_the_switch() { - // A `!` never adds a boolean increment; only operator-kind changes do. So - // `(a && !b) || c` flattens (negation ignored) to `&& ||` → 2 increments + - // if(1) = 3, and the parenthesized-`&&`-run forms score the same as their - // flat equivalents. - for src in [ - "class C { boolean f(boolean a, boolean b, boolean c) { if ((a && !b) || c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (a || (!b && c)) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if ((a || !b) && c) return true; return false; } }", - ] { - let a = analyze(src); - let cog = - serde_json::to_value(mehen_report::metrics_json::cognitive(&a.root.metrics)).unwrap(); - assert_eq!( - cog["sum"], - serde_json::json!(3.0), - "negation ignored; only the operator switch counts: {src}" - ); - } - // A trailing negation and multiple negations in a single-operator run add - // nothing: these are all one run → 2. - for src in [ - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && b && !c) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c) { if (a && (b && !c)) return true; return false; } }", - "class C { boolean f(boolean a, boolean b, boolean c, boolean d) { if (a && (!b && !c) && d) return true; return false; } }", - ] { - let a = analyze(src); - let cog = - serde_json::to_value(mehen_report::metrics_json::cognitive(&a.root.metrics)).unwrap(); - assert_eq!( - cog["sum"], - serde_json::json!(2.0), - "negations in a single-operator run are ignored: {src}" - ); - } -} - -#[test] -fn operator_expression_resets_boolean_run() { - // Regression (PR #160 review): only *transparent* wrappers (parens/bare - // operands) preserve a boolean run; an expression with its own operator - // (here `==`) is a distinct boolean context. For `a && ((b && c) == d)` - // the inner `b && c` must NOT collapse with the outer `&&`: - // if(+1), outer `&&`(+1), inner `&&` (fresh run after `==`)(+1) = 3. - let a = analyze( - "class C { - boolean f(int a, int b, int c, int d) { - if (a > 0 && ((b > 0 && c > 0) == (d > 0))) return true; - return false; - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "###); -} - -#[test] -fn lambda_in_plain_constructor_argument_inherits_method_depth() { - // Regression (PR #160 review): `new Foo(() -> …)` routes through - // `classCreatorRest: arguments classBody?`, but only the optional - // `classBody` is an anonymous body — the `arguments` (a plain constructor - // call) is not. A lambda passed as a constructor argument must inherit the - // enclosing method's depth, exactly like a lambda passed to a method call. - let ctor = analyze("class C { void m() { new Foo(() -> { if (x) {} }); } }"); - let call = analyze("class C { void m() { bar(() -> { if (x) {} }); } }"); - let cc = - serde_json::to_value(mehen_report::metrics_json::cognitive(&ctor.root.metrics)).unwrap(); - let ca = - serde_json::to_value(mehen_report::metrics_json::cognitive(&call.root.metrics)).unwrap(); - assert_eq!( - cc["sum"], ca["sum"], - "a lambda in a constructor argument must score like one in a method-call argument" - ); - assert_eq!(cc["sum"], serde_json::json!(2.0)); -} - -#[test] -fn lambda_inside_anonymous_class_method_inherits_method_depth() { - // Regression (PR #160 review): `in_anon_body` is a subtree-wide flag, but a - // lambda nested *inside* an anonymous class's method is enclosed by the - // method (a function), not the anon body — so it must inherit the method's - // cognitive depth. The lambda's `if` scores the same whether the method is - // in an anonymous class or a plain class. - let anon = analyze( - "class C { void outer() { new Runnable() { public void run() { Runnable r = () -> { if (x) {} }; } }; } }", - ); - let plain = analyze("class C { void run() { Runnable r = () -> { if (x) {} }; } }"); - let a = - serde_json::to_value(mehen_report::metrics_json::cognitive(&anon.root.metrics)).unwrap(); - let p = - serde_json::to_value(mehen_report::metrics_json::cognitive(&plain.root.metrics)).unwrap(); - assert_eq!( - a["sum"], p["sum"], - "a lambda inside an anon-class method must inherit the method's depth" - ); - assert_eq!(a["sum"], serde_json::json!(2.0)); -} - -#[test] -fn method_in_anonymous_class_does_not_inherit_outer_depth() { - // Regression (PR #160 review): an anonymous class opens no metric space - // (tracked only via `in_anon_body`), so the ancestor scan can't see a - // class boundary. A method in `new Runnable(){ void run(){…} }` inside - // `outer()` must still start at the baseline depth, not inherit `outer`'s. - let nested = - analyze("class C { void outer() { new Runnable() { public void run() { if (x) {} } }; } }"); - let flat = - analyze("class C { Runnable r = new Runnable() { public void run() { if (x) {} } }; }"); - let n = - serde_json::to_value(mehen_report::metrics_json::cognitive(&nested.root.metrics)).unwrap(); - let f = - serde_json::to_value(mehen_report::metrics_json::cognitive(&flat.root.metrics)).unwrap(); - assert_eq!( - n["sum"], f["sum"], - "an anonymous-class method must not inherit the enclosing method's depth" - ); - assert_eq!(n["sum"], serde_json::json!(1.0)); -} - -#[test] -fn anonymous_class_body_initializer_does_not_inherit_enclosing_nesting() { - // Regression (PR #160 review): an anonymous class body (`new X() { … }`) is - // a fresh class scope but opens no metric space, so — like a named class - // (which resets via `enter_class_cognitive`) — its class-body-level code - // (an instance initializer block) must not inherit the enclosing `if`'s - // nesting. `if (a) { new Object() { { if (b) {} } }; }`: - // if (a) → +1; the anon body's initializer `if (b)` is a fresh scope → +1 - // = 2, not 3. - let nested = analyze("class C { void m() { if (a) { new Object() { { if (b) {} } }; } } }"); - let flat = analyze("class C { void m() { new Object() { { if (b) {} } }; } }"); - let n = - serde_json::to_value(mehen_report::metrics_json::cognitive(&nested.root.metrics)).unwrap(); - let f = - serde_json::to_value(mehen_report::metrics_json::cognitive(&flat.root.metrics)).unwrap(); - assert_eq!( - f["sum"], - serde_json::json!(1.0), - "anon initializer `if` is a fresh scope" - ); - assert_eq!( - n["sum"], - serde_json::json!(2.0), - "outer if (1) + anon initializer if at baseline (1), not nested (2)" - ); -} - -#[test] -fn class_body_initializer_does_not_inherit_enclosing_nesting() { - // Regression (PR #160 review): a class-like scope resets the cognitive - // context, so code that runs *directly* in a class body (an instance - // initializer block) does not inherit the enclosing statement's nesting. - // Methods reset via `enter_function_cognitive`; class-body code opens no - // function space, so the class-open must reset it. Here a local class with - // an initializer block is declared inside `if (a)`: - // if (a) → +1; the initializer's `if (b)` is a fresh scope → +1 = 2. - // Without the reset the inner `if` would be scored nested (+2), giving 3. - let nested = analyze("class C { void m() { if (a) { class L { { if (b) {} } } } } }"); - let flat = analyze("class C { void m() { class L { { if (b) {} } } } }"); - let n = - serde_json::to_value(mehen_report::metrics_json::cognitive(&nested.root.metrics)).unwrap(); - let f = - serde_json::to_value(mehen_report::metrics_json::cognitive(&flat.root.metrics)).unwrap(); - // The local class's initializer `if` scores the same (baseline 1) whether - // or not the class is declared inside the outer `if`. - assert_eq!( - f["sum"], - serde_json::json!(1.0), - "initializer `if` is a fresh scope" - ); - assert_eq!( - n["sum"], - serde_json::json!(2.0), - "outer if (1) + initializer if at baseline (1), not nested (2)" - ); -} - -#[test] -fn method_in_local_class_does_not_inherit_outer_depth() { - // Regression (PR #160 review): a method in a local/anonymous class nested - // in another method must NOT inherit the outer method's cognitive depth — - // a class scope resets the baseline. `inner`'s `if` scores 1, matching the - // same method declared without the enclosing method. - let local = analyze("class C { void outer() { class L { void inner() { if (x) {} } } } }"); - let flat = analyze("class C { class L { void inner() { if (x) {} } } }"); - let l = - serde_json::to_value(mehen_report::metrics_json::cognitive(&local.root.metrics)).unwrap(); - let f = - serde_json::to_value(mehen_report::metrics_json::cognitive(&flat.root.metrics)).unwrap(); - assert_eq!( - l["sum"], f["sum"], - "a method in a local class must not inherit the enclosing method's depth" - ); - assert_eq!(l["sum"], serde_json::json!(1.0)); -} - -#[test] -fn else_if_flag_does_not_leak_through_a_loop_body() { - // Regression (PR #160 review): the `is_else_branch` flag must only flow - // through a *transparent* wrapper statement toward an else-if, NOT through - // a loop/switch/try in the else position. For `if (a) {} else while (c) if - // (b) {}` the `while` body's `if (b)` is a genuinely nested `if`, not an - // `else if`, so it must keep its cognitive nesting increment. If the flag - // leaked, `if (b)` would be scored as an else-if (no nesting) and the score - // would drop by its nesting contribution. - let leaked = analyze( - "class C { void m(int a, int c, int b) { if (a > 0) {} else while (c > 0) if (b > 0) {} } }", - ); - let no_body_if = - analyze("class C { void m(int a, int c) { if (a > 0) {} else while (c > 0) {} } }"); - let l = - serde_json::to_value(mehen_report::metrics_json::cognitive(&leaked.root.metrics)).unwrap(); - let n = serde_json::to_value(mehen_report::metrics_json::cognitive( - &no_body_if.root.metrics, - )) - .unwrap(); - // Adding the nested `if (b)` inside the else-branch loop must increase the - // cognitive score — it is NOT an else-if and must not be suppressed. - assert!( - l["sum"].as_f64().unwrap() > n["sum"].as_f64().unwrap(), - "the loop-body `if` must add cognitive nesting (not be treated as else-if): \ - with-if={} without-if={}", - l["sum"], - n["sum"] - ); -} - -#[test] -fn braceless_if_in_else_if_then_branch_still_nests() { - // Regression (PR #160 review): the `is_else_branch` flag must NOT leak from - // an else-if node onto its *then*-branch. Here `else if (b > 0)` has a - // braceless then-branch containing `if (d > 0)`, which is a genuine nested - // `if` and must add nesting. - // if (a > 0) -> +1 - // else if (b > 0) -> flat else +1 (the `if` is an else-branch: no nest) - // if (d > 0) ... -> +2 (nested at level 1 inside the else-if body) - // = 4. If the flag leaked, the inner `if` would be mis-tagged as an - // else-branch and skip its nesting, giving 2. - let a = analyze( - "class C { - int f(int a, int b, int d) { - if (a > 0) { return 1; } - else if (b > 0) - if (d > 0) return 2; - return 0; - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - } - "###); -} - -#[test] -fn switch_expression_scores_like_switch_statement() { - // Regression (audit): a switch *expression* (Java 14+) must get the same - // cognitive nesting as the statement form. Here: switch expr(+1) then a - // nested `if` in an arm at nesting 1 (+2) = 3. - let expr = analyze( - "class C { - int f(int x) { - int y = switch (x) { - case 1 -> { if (x > 0) { yield 1; } yield 2; } - default -> 0; - }; - return y; - } - }", - ); - let stmt = analyze( - "class C { - int f(int x) { - switch (x) { - case 1: if (x > 0) { return 1; } return 2; - default: return 0; - } - } - }", - ); - let e = mehen_report::metrics_json::cognitive(&expr.root.metrics); - let s = mehen_report::metrics_json::cognitive(&stmt.root.metrics); - let ej = serde_json::to_value(&e).unwrap(); - let sj = serde_json::to_value(&s).unwrap(); - assert_eq!( - ej, sj, - "switch expression and switch statement must score identically" - ); - insta::assert_json_snapshot!(e, @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "###); -} - -#[test] -fn nested_ternary_deepens_nesting() { - // Regression (audit): a ternary nested in another ternary's operand is one - // level deeper. `a>0 ? (b>0 ? 1 : 2) : 3`: outer ternary(+1 at level 0), - // inner ternary(+2 at level 1) = 3. - let a = analyze( - "class C { - int f(int a, int b) { - return a > 0 ? (b > 0 ? 1 : 2) : 3; - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "###); -} - -#[test] -fn catch_adds_nesting_increment() { - // `catch`(+1). `try` itself adds nothing. - let a = analyze( - "class C { - void f() { - try { risky(); } catch (Exception e) { } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!(cog, @r###" - { - "sum": 1.0, - "average": 1.0, - "min": 0.0, - "max": 1.0 - } - "###); -} diff --git a/crates/mehen-java/tests/contributions.rs b/crates/mehen-java/tests/contributions.rs deleted file mode 100644 index 14b94ca8..00000000 --- a/crates/mehen-java/tests/contributions.rs +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the Java analyzer (plan §5.4). - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - JavaAnalyzer::new() - .analyze( - &SourceFile::new("Demo.java".into(), Language::Java, source.to_string()), - config, - ) - .expect("Java analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -class Demo { - public int total; - - public int classify(int a, int b) { - int sign = 0; - if (a > 0 && b > 0) { - sign = 1; - } else { - sign = -1; - } - int scaled = sign > 0 ? a : b; - java.util.function.IntUnaryOperator twice = x -> x * 2; - total += twice.applyAsInt(scaled); - if (total < 0) { - throw new IllegalStateException(\"negative\"); - } - return total; - } -} -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - // Families whose rolled-up value is exactly the sum of their per-event - // evidence. Cyclomatic includes the per-space McCabe base rows - // (`java.cyclomatic.base.`), so it sums exactly too. - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ("npa", "npa"), - ("npm", "npm"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn reasons_are_java_namespaced_with_construct_names() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "java.cyclomatic.if_statement", - "java.cyclomatic.logical_and", - "java.cyclomatic.ternary_expression", - "java.cognitive.if_statement", - "java.cognitive.else", - "java.cognitive.logical_and", - "java.cognitive.ternary_expression", - "java.nexit.return_statement", - "java.nexit.throw_statement", - "java.abc.assignment.variable_declarator", - "java.abc.assignment.assignment_expression", - "java.abc.branch.method_call", - "java.abc.branch.creator", - "java.abc.condition.if_statement", - "java.abc.condition.logical_and", - "java.abc.condition.comparison", - "java.nom.function.method_declaration", - "java.nom.closure.lambda_expression", - "java.nargs.function.method_declaration", - "java.nargs.closure.lambda_expression", - "java.npa.field_declaration", - "java.npm.method_declaration", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("java."))); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn cognitive_amounts_carry_nesting_depth() { - // A doubly-nested `if` pays nesting+1 = 2 on the inner statement — the - // §5.4 "why did cognitive move +2 here" answer. - let source = "\ -class Nest { - int probe(int a, int b) { - if (a > 0) { - if (b > 0) { - return 1; - } - } - return 0; - } -} -"; - let analysis = analyze(source, &AnalysisConfig::production()); - let cognitive: Vec = analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == "cognitive.sum") - .map(|item| item.amount) - .collect(); - assert_eq!(cognitive, vec![1.0, 2.0]); - assert_eq!(metric(&analysis, "cognitive.sum"), 3.0); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc", - "nom", - "nargs", - "npa", - "npm", - ] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-java/tests/cyclomatic.rs b/crates/mehen-java/tests/cyclomatic.rs deleted file mode 100644 index 4636185c..00000000 --- a/crates/mehen-java/tests/cyclomatic.rs +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity tests for the ANTLR Java walker. -//! -//! Decisions (SonarJava-aligned): `if`, every loop (`for`/`while`/`do`), each -//! `case` label, the ternary `?`, and each short-circuit `&&`/`||`. `switch` -//! itself, `catch`, `else`, and `try` are not decisions. Every method space -//! contributes a base McCabe `+1`, as does the enclosing class space — so the -//! unit `sum` folds in the class(1) and each method's McCabe value. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn simple_if() { - // unit(1) + class(1) + method(1 + 1 if) = 4 - let a = analyze( - "class C { - int f(int a, int b) { - if (a > b) { return a; } - return b; - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!(cy, @r###" - { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0 - } - "###); -} - -#[test] -fn logical_operators() { - // method McCabe = 1 + if(1) + &&(1) + ||(1) = 4; unit sum = 1 + class(1) + 4 - let a = analyze( - "class C { - boolean check(boolean a, boolean b, boolean c) { - if (a && b || c) { return true; } - return false; - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!(cy, @r###" - { - "sum": 6.0, - "average": 2.0, - "min": 1.0, - "max": 4.0 - } - "###); -} - -#[test] -fn switch_cases_count_not_switch_or_default() { - // method McCabe = 1 + case(1) + case(1) = 3 (`default` does not count). - let a = analyze( - "class C { - int g(int x) { - switch (x) { - case 1: return 1; - case 2: return 2; - default: return 0; - } - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!(cy, @r###" - { - "sum": 5.0, - "average": 1.6666666666666667, - "min": 1.0, - "max": 3.0 - } - "###); -} - -#[test] -fn try_catch_is_not_a_decision() { - // `try`/`catch` add no cyclomatic decision (matches SonarJava): method - // McCabe stays 1. unit sum = 1 + class(1) + 1. - let a = analyze( - "class C { - void f() { - try { risky(); } catch (Exception e) { } - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!(cy, @r###" - { - "sum": 3.0, - "average": 1.0, - "min": 1.0, - "max": 1.0 - } - "###); -} - -#[test] -fn ternary_counts_as_decision() { - // method McCabe = 1 + ternary(1) = 2. - let a = analyze( - "class C { - int f(int a) { - return a > 0 ? a : -a; - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!(cy, @r###" - { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0 - } - "###); -} - -#[test] -fn annotation_value_expressions_do_not_add_complexity() { - // Regression (PR #160 review): annotation values are compile-time metadata, - // not executable code. A composed constant in an annotation value - // (`@Ann(value = true && false)`, `@Ann(x = c ? 1 : 2)`) must NOT record - // cyclomatic decisions (nor cognitive/ABC) — it would otherwise inflate the - // annotated method/class complexity. The annotated method scores the same - // as the un-annotated one. - let plain = analyze("class C { void m() {} }"); - let p = - serde_json::to_value(mehen_report::metrics_json::cyclomatic(&plain.root.metrics)).unwrap(); - for src in [ - "class C { @Ann(value = true && false) void m() {} }", - "class C { @Ann(x = cond ? 1 : 2) void m() {} }", - "class C { @Ann(flags = A || B || C) void m() {} }", - ] { - let a = analyze(src); - let av = - serde_json::to_value(mehen_report::metrics_json::cyclomatic(&a.root.metrics)).unwrap(); - assert_eq!( - av["sum"], p["sum"], - "annotation-value expressions must not add cyclomatic complexity: {src}" - ); - } - // Guard: a real `&&` in the method *body* still counts. - let with_body = analyze( - "class C { @Ann(value = true) boolean m(boolean a, boolean b) { return a && b; } }", - ); - let wb = serde_json::to_value(mehen_report::metrics_json::cyclomatic( - &with_body.root.metrics, - )) - .unwrap(); - assert!( - wb["sum"].as_f64().unwrap() > p["sum"].as_f64().unwrap(), - "a real decision in an annotated method's body still counts" - ); -} - -#[test] -fn annotation_element_default_expressions_do_not_add_complexity() { - // Regression (PR #160 review): an annotation element's DEFAULT value - // (`@interface A { boolean v() default true && false; }`) is metadata too, - // parsed under `annotationMethodRest → defaultValue → elementValue → - // expression` — NOT under `RULE_ANNOTATION`. The `in_annotation` guard must - // also trigger on `defaultValue`, or a composed constant in a default - // inflates the annotation method's cyclomatic/cognitive/ABC. - let plain = analyze("@interface A { boolean v(); }"); - let p = - serde_json::to_value(mehen_report::metrics_json::cyclomatic(&plain.root.metrics)).unwrap(); - for src in [ - "@interface A { boolean v() default true && false; }", - "@interface A { int v() default cond ? 1 : 2; }", - ] { - let a = analyze(src); - let av = - serde_json::to_value(mehen_report::metrics_json::cyclomatic(&a.root.metrics)).unwrap(); - assert_eq!( - av["sum"], p["sum"], - "an annotation element default expression must not add complexity: {src}" - ); - } -} diff --git a/crates/mehen-java/tests/exit.rs b/crates/mehen-java/tests/exit.rs deleted file mode 100644 index e18adc87..00000000 --- a/crates/mehen-java/tests/exit.rs +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NExit (exit-point) tests for the ANTLR Java walker. -//! -//! `return` and `throw` statements count as exits; `break`/`continue` do not. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn return_and_throw_count_as_exits() { - let a = analyze( - "class C { - int f(int a) { - if (a < 0) { throw new IllegalArgumentException(); } - return a; - } - }", - ); - let nexit = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!(nexit, @r#" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - } - "#); -} - -#[test] -fn break_and_continue_are_not_exits() { - let a = analyze( - "class C { - void f(int[] xs) { - for (int x : xs) { - if (x == 0) { continue; } - if (x < 0) { break; } - } - } - }", - ); - let nexit = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!(nexit, @r#" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - } - "#); -} diff --git a/crates/mehen-java/tests/halstead.rs b/crates/mehen-java/tests/halstead.rs deleted file mode 100644 index 810e2809..00000000 --- a/crates/mehen-java/tests/halstead.rs +++ /dev/null @@ -1,188 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Halstead tests for the ANTLR Java walker. -//! -//! Operators = keyword and punctuation/operator tokens; operands = -//! identifiers, literals, `this`, `super` (deduped by text). Whitespace, -//! comments, and EOF are skipped. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn operators_and_operands_are_counted() { - let a = analyze( - "class C { - int add(int a, int b) { return a + b; } - }", - ); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - // Non-zero vocabulary/volume proves operator+operand classification runs. - assert!(h.n1 > 0.0, "distinct operators must be counted"); - assert!(h.n2 > 0.0, "distinct operands must be counted"); - assert!(h.volume > 0.0, "volume must be positive"); -} - -#[test] -fn contextual_keyword_used_as_identifier_is_an_operand() { - // Regression (audit): `record`/`var`/`yield`/… used as a *name* lex as - // dedicated tokens but are identifiers → Halstead operands, not operators. - // A field named `record` should classify like a field named `plain`: same - // operand count, same operator count. - let named_kw = analyze("class C { int record = 5; }"); - let named_plain = analyze("class C { int plain = 5; }"); - let hk = mehen_report::metrics_json::halstead(&named_kw.root.metrics); - let hp = mehen_report::metrics_json::halstead(&named_plain.root.metrics); - assert_eq!( - hk.n1, hp.n1, - "a contextual keyword used as a name must not add a distinct operator" - ); - assert_eq!( - hk.n2, hp.n2, - "a contextual keyword used as a name must be an operand like any identifier" - ); -} - -#[test] -fn method_own_line_modifiers_belong_to_the_method() { - // Regression (PR #160 review): a method's own-line modifiers/annotations - // (`@Deprecated\npublic void m() {}`) are siblings of the declaration on - // the `classBodyDeclaration` wrapper. The method space is opened at the - // wrapper so those tokens are walked *inside* the method — counting toward - // its Halstead (and PLOC), not only the enclosing class. An annotated - // method must have strictly more Halstead length than the same method with - // the annotation removed. - fn method_len(sp: &mehen_core::MetricSpace) -> Option { - if sp.kind == mehen_core::SpaceKind::Function { - return Some( - sp.metrics - .get(&mehen_core::MetricKey::new("halstead.N1")) - .map(|m| m.as_f64()) - .unwrap_or(0.0), - ); - } - sp.spaces.iter().find_map(method_len) - } - let plain = analyze("class C {\n public void m() {\n x();\n }\n}"); - let annotated = analyze("class C {\n @Deprecated\n public void m() {\n x();\n }\n}"); - let p = method_len(&plain.root).expect("method space"); - let a = method_len(&annotated.root).expect("method space"); - assert!( - a > p, - "an annotated method must count the annotation tokens in its Halstead: \ - annotated N1={a} vs plain N1={p}" - ); - - // The method's PLOC must include the annotation line too (consistent with - // Halstead — both derive from the same tokens now visited inside the space). - fn method_ploc(sp: &mehen_core::MetricSpace) -> Option { - if sp.kind == mehen_core::SpaceKind::Function { - return Some( - sp.metrics - .get(&mehen_core::MetricKey::new("loc.ploc")) - .map(|m| m.as_f64()) - .unwrap_or(0.0), - ); - } - sp.spaces.iter().find_map(method_ploc) - } - assert_eq!( - method_ploc(&annotated.root), - Some(4.0), - "the annotation row is part of the method's PLOC" - ); - assert_eq!(method_ploc(&plain.root), Some(3.0)); -} - -#[test] -fn anon_and_interface_method_modifiers_belong_to_the_method() { - // Regression (PR #160 review): the wrapper-open fix must also cover methods - // whose space is opened at a NON-class wrapper — anonymous-class methods - // (opened at the anon body's `classBodyDeclaration`), interface methods - // (opened at `interfaceBodyDeclaration → … → interfaceCommonBodyDeclaration`), - // and annotation elements. Their own-line modifiers/annotations must count - // toward the method's Halstead, consistent with its (already-widened) PLOC — - // otherwise PLOC and Halstead disagree about the annotation row. - fn method_len(sp: &mehen_core::MetricSpace) -> Option { - if sp.kind == mehen_core::SpaceKind::Function { - return Some( - sp.metrics - .get(&mehen_core::MetricKey::new("halstead.N1")) - .map(|m| m.as_f64()) - .unwrap_or(0.0), - ); - } - sp.spaces.iter().find_map(method_len) - } - // Anonymous-class method. - let anon_plain = analyze( - "class C {\n Runnable r = new Runnable() {\n public void run() {\n x();\n }\n };\n}", - ); - let anon_annot = analyze( - "class C {\n Runnable r = new Runnable() {\n @Deprecated\n public void run() {\n x();\n }\n };\n}", - ); - assert!( - method_len(&anon_annot.root).unwrap() > method_len(&anon_plain.root).unwrap(), - "an anon-class method's annotation must count toward its Halstead" - ); - // Interface (default) method. - let iface_plain = analyze("interface I {\n default void m() {\n x();\n }\n}"); - let iface_annot = - analyze("interface I {\n @Deprecated\n default void m() {\n x();\n }\n}"); - assert!( - method_len(&iface_annot.root).unwrap() > method_len(&iface_plain.root).unwrap(), - "an interface method's annotation must count toward its Halstead" - ); -} - -#[test] -fn type_own_line_modifiers_belong_to_the_type() { - // Regression (PR #160 review): a class-like type's own-line - // modifiers/annotations (`@Deprecated\npublic class C {}`, a nested - // `public static class Inner {}`) live on the `typeDeclaration` / - // `classBodyDeclaration` wrapper, visited before the type space opens. The - // type space is opened at the wrapper so those tokens count toward the - // type's Halstead/PLOC, not the enclosing unit/class. - fn type_len(sp: &mehen_core::MetricSpace, name: &str) -> Option { - if matches!( - sp.kind, - mehen_core::SpaceKind::Class - | mehen_core::SpaceKind::Interface - | mehen_core::SpaceKind::Enum - ) && sp.name.as_deref() == Some(name) - { - return Some( - sp.metrics - .get(&mehen_core::MetricKey::new("halstead.N1")) - .map(|m| m.as_f64()) - .unwrap_or(0.0), - ); - } - sp.spaces.iter().find_map(|c| type_len(c, name)) - } - // Top-level annotated class. - let top_plain = analyze("class C {\n int x;\n}"); - let top_annot = analyze("@Deprecated\npublic class C {\n int x;\n}"); - assert!( - type_len(&top_annot.root, "C").unwrap() > type_len(&top_plain.root, "C").unwrap(), - "a top-level type's own-line annotation/modifier must count in its Halstead" - ); - // Nested class with own-line modifiers. - let nested_plain = analyze("class O {\n class Inner {\n int x;\n }\n}"); - let nested_mods = - analyze("class O {\n @Deprecated\n public static class Inner {\n int x;\n }\n}"); - assert!( - type_len(&nested_mods.root, "Inner").unwrap() - > type_len(&nested_plain.root, "Inner").unwrap(), - "a nested type's own-line modifiers must count in its Halstead" - ); -} diff --git a/crates/mehen-java/tests/loc.rs b/crates/mehen-java/tests/loc.rs deleted file mode 100644 index 931a3e49..00000000 --- a/crates/mehen-java/tests/loc.rs +++ /dev/null @@ -1,345 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC tests for the ANTLR Java walker. -//! -//! PLOC = physical code lines; LLOC = logical (statement/declaration) lines; -//! CLOC = comment lines (block `COMMENT` + `LINE_COMMENT`, routed to the -//! deepest enclosing space); SLOC = source lines. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn simple_loc() { - let a = analyze( - "package demo;\n\ - // a line comment\n\ - class C {\n\ - \x20 /* a block comment */\n\ - \x20 int f() {\n\ - \x20 return 1;\n\ - \x20 }\n\ - }\n", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!(loc, @r#" - { - "sloc": 8.0, - "ploc": 6.0, - "lloc": 4.0, - "cloc": 2.0, - "blank": 0.0, - "sloc_average": 2.6666666666666665, - "ploc_average": 2.0, - "lloc_average": 1.3333333333333333, - "cloc_average": 0.6666666666666666, - "blank_average": 0.0, - "sloc_min": 3.0, - "sloc_max": 3.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 3.0, - "ploc_max": 3.0, - "lloc_min": 2.0, - "lloc_max": 2.0, - "blank_min": 0.0, - "blank_max": 0.0 - } - "#); -} - -#[test] -fn classic_for_header_is_one_lloc_like_enhanced_for() { - // Regression (audit): a classic `for (int i=…; …)` must not double-count - // its initializer declaration as a second LLOC — it should match the - // equivalent enhanced-for's LLOC. - let classic = analyze( - "class C { - void f() { - for (int i = 0; i < 10; i++) { g(i); } - } - }", - ); - let enhanced = analyze( - "class C { - void f(int[] xs) { - for (int x : xs) { g(x); } - } - }", - ); - let c = serde_json::to_value(mehen_report::metrics_json::loc(&classic.root.metrics)).unwrap(); - let e = serde_json::to_value(mehen_report::metrics_json::loc(&enhanced.root.metrics)).unwrap(); - assert_eq!( - c["lloc"], e["lloc"], - "classic-for and enhanced-for should report the same LLOC" - ); -} - -#[test] -fn empty_and_labeled_statements_are_not_their_own_lloc() { - // Regression (audit): a bare `;` (empty statement) and a label wrapper - // (`lbl: stmt`) are not their own logical lines. Here the only LLOC-bearing - // statements are the two `g(...)` calls inside the labeled loop and the - // plain call, matching an equivalent body without `;`/labels. - let with_noise = analyze( - "class C { - void f() { - ; - lbl: for (int i = 0; i < 2; i++) { g(i); } - ; - } - }", - ); - let without = analyze( - "class C { - void f() { - for (int i = 0; i < 2; i++) { g(i); } - } - }", - ); - let a = - serde_json::to_value(mehen_report::metrics_json::loc(&with_noise.root.metrics)).unwrap(); - let b = serde_json::to_value(mehen_report::metrics_json::loc(&without.root.metrics)).unwrap(); - assert_eq!( - a["lloc"], b["lloc"], - "empty statements and labels must not inflate LLOC" - ); -} - -#[test] -fn text_block_interior_rows_count_as_ploc() { - // Regression (PR #160 review): a Java text block (`"""…"""`) is a single - // `TEXT_BLOCK` token spanning multiple physical lines. Every row it covers - // is code (PLOC), not blank — otherwise the interior rows are reported as - // phantom blank lines. - let a = analyze( - "class C {\n\ - \x20 String s = \"\"\"\n\ - \x20 line one\n\ - \x20 line two\n\ - \x20 \"\"\";\n\ - }\n", - ); - let loc = serde_json::to_value(mehen_report::metrics_json::loc(&a.root.metrics)).unwrap(); - // 6 physical lines, all code, none blank. - assert_eq!( - loc["ploc"], - serde_json::json!(6.0), - "all text-block rows are code" - ); - assert_eq!( - loc["blank"], - serde_json::json!(0.0), - "no phantom blank lines" - ); -} - -#[test] -fn enum_constants_count_as_lloc() { - // Regression (PR #160 review): each enum constant is a declaration → a - // logical line. `enum E { A, B, C }` = enum decl (1) + 3 constants = 4. - let a = analyze("enum E { A, B, C }"); - let loc = serde_json::to_value(mehen_report::metrics_json::loc(&a.root.metrics)).unwrap(); - assert_eq!(loc["lloc"], serde_json::json!(4.0)); -} - -#[test] -fn expression_bodied_lambda_counts_one_lloc() { - // Regression (PR #160 review): an expression-bodied lambda (`x -> x + 1`) - // opens a closure space whose body is an `expression`, not a statement, so - // its own `loc.lloc` would be 0. It must count as one logical line, like a - // block-bodied lambda (whose inner statements count) and method decls. Find - // the closure space and assert its LLOC. - fn closure_lloc(sp: &mehen_core::MetricSpace) -> Option { - if sp.kind == mehen_core::SpaceKind::Closure { - return Some( - sp.metrics - .get(&mehen_core::MetricKey::new("loc.lloc")) - .map(|m| m.as_f64()) - .unwrap_or(0.0), - ); - } - sp.spaces.iter().find_map(closure_lloc) - } - let expr = analyze("class C { java.util.function.Function f = x -> x + 1; }"); - assert_eq!( - closure_lloc(&expr.root), - Some(1.0), - "an expression-bodied lambda is one logical line" - ); - let block = analyze("class C { Runnable r = () -> { g(); }; }"); - assert_eq!( - closure_lloc(&block.root), - Some(1.0), - "a block-bodied lambda counts its inner statement (no double-count)" - ); -} - -#[test] -fn module_descriptor_directives_count_as_lloc() { - // Regression (PR #160 review): a `module-info.java` descriptor parses via - // `modularCompilationUnit → moduleDeclaration` with `moduleDirective` - // children; these must count as LLOC or a module file reports lloc == 0. - // Here: module declaration (1) + requires (1) + exports (1) = 3. - let a = analyze("module com.example { requires java.base; exports com.example.api; }"); - let loc = serde_json::to_value(mehen_report::metrics_json::loc(&a.root.metrics)).unwrap(); - assert_eq!( - loc["lloc"], - serde_json::json!(3.0), - "module declaration + 2 directives should be 3 logical lines" - ); - assert!( - a.diagnostics.is_empty(), - "module descriptor should parse cleanly" - ); -} - -#[test] -fn interface_and_annotation_members_count_as_lloc() { - // Regression (PR #160 review): an interface method - // (`interfaceCommonBodyDeclaration`) and an annotation element - // (`annotationMethodRest`) are declaration nodes and must count as LLOC, - // just like a class abstract method — an interface API should not - // under-report logical LOC vs the equivalent abstract class. - let iface = analyze("interface I { void m(); }"); - let cls = analyze("abstract class C { abstract void m(); }"); - let i = serde_json::to_value(mehen_report::metrics_json::loc(&iface.root.metrics)).unwrap(); - let c = serde_json::to_value(mehen_report::metrics_json::loc(&cls.root.metrics)).unwrap(); - assert_eq!( - i["lloc"], c["lloc"], - "interface method LLOC should match the equivalent abstract class method" - ); - // Annotation element + constant each count: type decl + method + constant. - let anno = analyze("@interface An { String v(); int X = 1; }"); - let av = serde_json::to_value(mehen_report::metrics_json::loc(&anno.root.metrics)).unwrap(); - assert_eq!(av["lloc"], serde_json::json!(3.0)); -} - -#[test] -fn for_init_suppression_does_not_leak_into_nested_lambda_body() { - // Regression (PR #160 review): the classic-`for` header suppresses its - // initializer declaration's own LLOC (it is part of the `for` statement's - // single logical line). That suppression must apply ONLY to the direct - // `forInit` declaration — not to real local declarations nested inside a - // lambda/anonymous-class body that happens to live in the header - // initializer. Here the lambda body's `int x = 0;` is genuine code and must - // count. The same lambda scores identically whether it initializes a `for` - // header variable or a plain field. - fn closure_lloc(sp: &mehen_core::MetricSpace) -> Option { - if sp.kind == mehen_core::SpaceKind::Closure { - return Some( - sp.metrics - .get(&mehen_core::MetricKey::new("loc.lloc")) - .map(|m| m.as_f64()) - .unwrap_or(0.0), - ); - } - sp.spaces.iter().find_map(closure_lloc) - } - let in_for = analyze( - "class C { - void f() { - for (java.util.function.Supplier s = () -> { int x = 0; return x; }; ; ) { break; } - } - }", - ); - let plain = analyze( - "class C { - java.util.function.Supplier s = () -> { int x = 0; return x; }; - }", - ); - // The lambda body has two logical lines (`int x = 0;` + `return x;`); the - // for-init suppression must not drop the declaration. - assert_eq!( - closure_lloc(&in_for.root), - Some(2.0), - "the lambda body's declaration must count even inside a for-init" - ); - assert_eq!( - closure_lloc(&in_for.root), - closure_lloc(&plain.root), - "a lambda body scores the same in a for-init as in a field initializer" - ); -} - -#[test] -fn block_only_statement_is_not_its_own_lloc() { - // A bare `{ … }` block statement is not a logical line; the inner - // statements each count. - let a = analyze( - "class C { - void f() { - { - int x = 1; - } - } - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!(loc, @r#" - { - "sloc": 7.0, - "ploc": 7.0, - "lloc": 3.0, - "cloc": 0.0, - "blank": 0.0, - "sloc_average": 2.3333333333333335, - "ploc_average": 2.3333333333333335, - "lloc_average": 1.0, - "cloc_average": 0.0, - "blank_average": 0.0, - "sloc_min": 5.0, - "sloc_max": 5.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 5.0, - "ploc_max": 5.0, - "lloc_min": 2.0, - "lloc_max": 2.0, - "blank_min": 0.0, - "blank_max": 0.0 - } - "#); -} - -#[test] -fn a_unicode_separator_in_a_block_comment_is_not_a_row_break() { - // REGRESSION from the C# work in this PR. `loc_tokens` in the shared `mehen-antlr` - // crate counted five line terminators inline when finding a block comment's end row - // — but which characters break a row is per-language policy, and Java passes - // `LineIndex::new` (LF/CRLF only, matching the JLS \u000A/\u000D/\u2028?/no). - // - // So `/*ab*/` was reported as covering two comment rows in a ONE-row file: - // CLOC 2 against SLOC 1, which is impossible, and which also skews - // `blank = sloc - ploc - only_comment` and every MI variant downstream. The end row - // now comes from the same `LineIndex` the start row does. - for separator in ['\u{85}', '\u{2028}', '\u{2029}'] { - let a = analyze(&format!("class C {{ /*a{separator}b*/ }}")); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.cloc, 1.0, - "U+{:04X} is not a row break for Java", - separator as u32 - ); - assert!( - loc.cloc <= loc.sloc, - "U+{:04X}: CLOC {} must not exceed SLOC {}", - separator as u32, - loc.cloc, - loc.sloc - ); - } - - // The control: LF *is* a row break, so the same comment covers two rows. - let lf = mehen_report::metrics_json::loc(&analyze("class C { /*a\nb*/ }").root.metrics); - assert_eq!(lf.cloc, 2.0); -} diff --git a/crates/mehen-java/tests/nargs.rs b/crates/mehen-java/tests/nargs.rs deleted file mode 100644 index d2058477..00000000 --- a/crates/mehen-java/tests/nargs.rs +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NArgs (declared parameter count) tests for the ANTLR Java walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn counts_method_parameters() { - let a = analyze( - "class C { - int add(int a, int b, int c) { return a + b + c; } - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!(nargs, @r#" - { - "total_functions": 3.0, - "total_closures": 0.0, - "average_functions": 3.0, - "average_closures": 0.0, - "total": 3.0, - "average": 3.0, - "functions_min": 3.0, - "functions_max": 3.0, - "closures_min": 0.0, - "closures_max": 0.0 - } - "#); -} - -#[test] -fn counts_lambda_parameters() { - let a = analyze( - "class C { - java.util.function.BiFunction add = (a, b) -> a + b; - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!(nargs, @r#" - { - "total_functions": 0.0, - "total_closures": 2.0, - "average_functions": 0.0, - "average_closures": 2.0, - "total": 2.0, - "average": 2.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 2.0, - "closures_max": 2.0 - } - "#); -} - -#[test] -fn varargs_parameter_counts() { - let a = analyze( - "class C { - int sum(int first, int... rest) { return first; } - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!(nargs, @r#" - { - "total_functions": 2.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 2.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - } - "#); -} - -#[test] -fn compact_record_constructor_reports_component_count() { - // Regression (PR #160 review): a compact record constructor has no - // `formalParameters` node — its parameter list is the record's components, - // so its NArgs is the record's component count (2 here), not 0. - let a = analyze("record R(int x, int y) { public R { } }"); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!(nargs, @r#" - { - "total_functions": 2.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 2.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - } - "#); -} diff --git a/crates/mehen-java/tests/nom.rs b/crates/mehen-java/tests/nom.rs deleted file mode 100644 index 90c25c1c..00000000 --- a/crates/mehen-java/tests/nom.rs +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NOM (number of methods) tests for the ANTLR Java walker. -//! -//! Every method/constructor is a function space; every lambda is a closure. -//! Interface methods (abstract and `default`) count exactly once (reached via -//! `interfaceCommonBodyDeclaration`). - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile, SpaceKind}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn counts_methods_and_constructor() { - let a = analyze( - "class C { - C() {} - int a() { return 1; } - void b() {} - }", - ); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - insta::assert_json_snapshot!(nom, @r#" - { - "functions": 3.0, - "closures": 0.0, - "functions_average": 0.6, - "closures_average": 0.0, - "total": 3.0, - "average": 0.6, - "functions_min": 0.0, - "functions_max": 1.0, - "closures_min": 0.0, - "closures_max": 0.0 - } - "#); -} - -#[test] -fn interface_methods_count_once() { - // Regression: interface methods reach the walker through - // `interfaceMethodDeclaration → interfaceCommonBodyDeclaration`; the space - // is opened only at the common-body rule so each method counts once. - let a = analyze( - "interface I { - void m(); - default int d() { return 2; } - }", - ); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - insta::assert_json_snapshot!(nom, @r#" - { - "functions": 2.0, - "closures": 0.0, - "functions_average": 0.5, - "closures_average": 0.0, - "total": 2.0, - "average": 0.5, - "functions_min": 0.0, - "functions_max": 1.0, - "closures_min": 0.0, - "closures_max": 0.0 - } - "#); -} - -#[test] -fn lambda_is_a_closure() { - let a = analyze( - "class C { - Runnable r = () -> System.out.println(\"hi\"); - }", - ); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - insta::assert_json_snapshot!(nom, @r#" - { - "functions": 0.0, - "closures": 1.0, - "functions_average": 0.0, - "closures_average": 0.3333333333333333, - "total": 1.0, - "average": 0.3333333333333333, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 0.0, - "closures_max": 1.0 - } - "#); - // The lambda opens a closure-shaped function space under the class. - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); -} - -#[test] -fn nested_annotation_element_is_not_counted_on_the_outer_type() { - // Regression (PR #160 review): the wrapper-open logic resolves an - // annotation element via the DIRECT `annotationTypeElementDeclaration → - // annotationTypeElementRest → annotationMethodOrConstantRest → - // annotationMethodRest` path — NOT an unbounded descendant search, which - // would reach a *nested* annotation's element and open a phantom method on - // the outer type. `@interface A { @interface B { String v(); } }` has ONE - // method total (`B.v()`), not two. - let nested = analyze("@interface A { @interface B { String v(); } }"); - let nom = serde_json::to_value(mehen_report::metrics_json::nom(&nested.root.metrics)).unwrap(); - assert_eq!( - nom["total"], - serde_json::json!(1.0), - "a nested annotation's element must not also count on the outer annotation" - ); - let npm = serde_json::to_value(mehen_report::metrics_json::npm(&nested.root.metrics)).unwrap(); - assert_eq!( - npm["total"], - serde_json::json!(1.0), - "the nested element must not inflate the outer annotation's NPM" - ); - // Control: a flat annotation with two elements has exactly two methods. - let flat = analyze("@interface A { String v(); int c(); }"); - let fnom = serde_json::to_value(mehen_report::metrics_json::nom(&flat.root.metrics)).unwrap(); - assert_eq!(fnom["total"], serde_json::json!(2.0)); -} diff --git a/crates/mehen-java/tests/npa.rs b/crates/mehen-java/tests/npa.rs deleted file mode 100644 index 24b1dfcf..00000000 --- a/crates/mehen-java/tests/npa.rs +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPA (number of public attributes) tests for the ANTLR Java walker. -//! -//! Java visibility: a class field with no access modifier is package-private -//! (NOT public); only an explicit `public` field counts toward NPA. Interface -//! fields are implicitly public. Record components count as public attributes. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn only_public_class_fields_count() { - // `x` private, `y` public, `z` package-private → public NPA = 1, total = 3. - let a = analyze( - "class C { - private int x; - public int y; - int z; - }", - ); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!(npa, @r#" - { - "classes": 1.0, - "interfaces": 0.0, - "class_attributes": 3.0, - "interface_attributes": 0.0, - "classes_average": 0.3333333333333333, - "interfaces_average": null, - "total": 1.0, - "total_attributes": 3.0, - "average": 0.3333333333333333 - } - "#); -} - -#[test] -fn multiple_declarators_each_count() { - // `public int a, b, c;` declares three public attributes. - let a = analyze( - "class C { - public int a, b, c; - }", - ); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!(npa, @r#" - { - "classes": 3.0, - "interfaces": 0.0, - "class_attributes": 3.0, - "interface_attributes": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 3.0, - "total_attributes": 3.0, - "average": 1.0 - } - "#); -} - -#[test] -fn interface_fields_are_public() { - let a = analyze( - "interface I { - int A = 1; - int B = 2; - }", - ); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!(npa, @r#" - { - "classes": 0.0, - "interfaces": 2.0, - "class_attributes": 0.0, - "interface_attributes": 2.0, - "classes_average": null, - "interfaces_average": 1.0, - "total": 2.0, - "total_attributes": 2.0, - "average": 1.0 - } - "#); -} - -#[test] -fn record_components_are_public_attributes() { - let a = analyze("record Point(int x, int y) {}"); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!(npa, @r#" - { - "classes": 2.0, - "interfaces": 0.0, - "class_attributes": 2.0, - "interface_attributes": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 2.0, - "total_attributes": 2.0, - "average": 1.0 - } - "#); -} - -#[test] -fn enum_constants_are_public_attributes() { - // Regression (PR #160 review): enum constants (`enum E { A, B, C }`) are - // public static final fields → public class attributes. They live under - // `enumConstants` (before the `;`), so they don't reach the member-position - // path and must be counted directly. - let a = analyze("enum E { A, B, C }"); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!(npa, @r#" - { - "classes": 3.0, - "interfaces": 0.0, - "class_attributes": 3.0, - "interface_attributes": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 3.0, - "total_attributes": 3.0, - "average": 1.0 - } - "#); -} - -#[test] -fn annotation_constants_are_public_attributes() { - // Regression (PR #160 review): annotation constants (`int X = 1;` in an - // `@interface`) reach the walker via annotationConstantRest and are - // implicitly-public interface attributes. `int Y = 2, Z = 3;` declares two. - let a = analyze("@interface Ann { int X = 1; int Y = 2, Z = 3; }"); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!(npa, @r#" - { - "classes": 0.0, - "interfaces": 3.0, - "class_attributes": 0.0, - "interface_attributes": 3.0, - "classes_average": null, - "interfaces_average": 1.0, - "total": 3.0, - "total_attributes": 3.0, - "average": 1.0 - } - "#); -} diff --git a/crates/mehen-java/tests/npm.rs b/crates/mehen-java/tests/npm.rs deleted file mode 100644 index 1c1d095a..00000000 --- a/crates/mehen-java/tests/npm.rs +++ /dev/null @@ -1,325 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPM (number of public methods) tests for the ANTLR Java walker. -//! -//! Java visibility: a class method with no access modifier is package-private -//! (NOT public); only an explicit `public` method counts toward NPM. -//! `protected`/`private` are non-public. Interface methods are implicitly -//! public. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn only_explicitly_public_class_methods_count() { - // `pub` public (1), `prot` protected, `priv` private, `pkg` package-private - // → public NPM = 1, total methods = 4. - let a = analyze( - "class C { - public void pub() {} - protected void prot() {} - private void priv() {} - void pkg() {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 1.0, - "interfaces": 0.0, - "class_methods": 4.0, - "interface_methods": 0.0, - "classes_average": 0.25, - "interfaces_average": null, - "total": 1.0, - "total_methods": 4.0, - "average": 0.25 - } - "#); -} - -#[test] -fn generic_methods_and_constructors_count() { - // Regression (audit): generic methods/constructors reach the walker - // through genericMethodDeclaration/genericConstructorDeclaration wrappers. - // Both public members must count toward NPM. - let a = analyze( - "class C { - public T identity(T x) { return x; } - public C(T seed) {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 2.0, - "interfaces": 0.0, - "class_methods": 2.0, - "interface_methods": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 2.0, - "total_methods": 2.0, - "average": 1.0 - } - "#); -} - -#[test] -fn generic_interface_methods_count() { - // Regression (audit): a generic interface method reaches the walker via - // genericInterfaceMethodDeclaration → interfaceCommonBodyDeclaration and - // must count exactly once toward interface NPM. - let a = analyze( - "interface I { - int plain(); - T generic(T x); - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 0.0, - "interfaces": 2.0, - "class_methods": 0.0, - "interface_methods": 2.0, - "classes_average": null, - "interfaces_average": 1.0, - "total": 2.0, - "total_methods": 2.0, - "average": 1.0 - } - "#); -} - -#[test] -fn interface_methods_are_public() { - let a = analyze( - "interface I { - void m(); - default int d() { return 2; } - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 0.0, - "interfaces": 2.0, - "class_methods": 0.0, - "interface_methods": 2.0, - "classes_average": null, - "interfaces_average": 1.0, - "total": 2.0, - "total_methods": 2.0, - "average": 1.0 - } - "#); -} - -#[test] -fn annotation_elements_are_public_interface_methods() { - // Regression (PR #160 review): annotation elements (`String value();`) - // reach the walker via annotationMethodRest and are implicitly-public - // interface-like methods — they must count toward interface NPM. - let a = analyze("@interface Ann { String value(); int count(); }"); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 0.0, - "interfaces": 2.0, - "class_methods": 0.0, - "interface_methods": 2.0, - "classes_average": null, - "interfaces_average": 1.0, - "total": 2.0, - "total_methods": 2.0, - "average": 1.0 - } - "#); -} - -#[test] -fn compact_record_constructor_counts_as_public_method() { - // Regression (PR #160 review): a compact record constructor is a direct - // `compactConstructorDeclaration` child of `recordBody` (not wrapped in - // `classBodyDeclaration`), so the member position must be seeded from - // `recordBody`. Its visibility comes from its own modifiers. - let a = analyze("record R(int x) { public R { } }"); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 1.0, - "interfaces": 0.0, - "class_methods": 1.0, - "interface_methods": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 1.0, - "total_methods": 1.0, - "average": 1.0 - } - "#); -} - -#[test] -fn modifierless_compact_constructor_inherits_record_visibility() { - // Regression (PR #160 review): Java gives a modifier-less compact canonical - // constructor the RECORD's access level. The compact ctor is reached under - // the (modifier-less) `recordBody`, so it must inherit the record's - // visibility — threaded via `enclosing_record_public` — not the record-body - // default (always package-private). A `public record` with the common - // modifier-less compact ctor therefore has NPM = 1. - let public_top = analyze("public record R(int x) { R { } }"); - let pt = - serde_json::to_value(mehen_report::metrics_json::npm(&public_top.root.metrics)).unwrap(); - assert_eq!( - pt["total"], - serde_json::json!(1.0), - "a modifier-less compact ctor in a public (top-level) record is public" - ); - // Nested public record: visibility comes through the classBodyDeclaration - // wrapper. The outer class contributes no methods; only the record's ctor. - let public_nested = analyze("class C { public record R(int x) { R { } } }"); - let nested = - serde_json::to_value(mehen_report::metrics_json::npm(&public_nested.root.metrics)).unwrap(); - assert_eq!( - nested["total"], - serde_json::json!(1.0), - "a modifier-less compact ctor in a nested public record is public" - ); - // Package-private record → its modifier-less compact ctor is NOT public. - let pkg = analyze("record R(int x) { R { } }"); - let pk = serde_json::to_value(mehen_report::metrics_json::npm(&pkg.root.metrics)).unwrap(); - assert_eq!( - pk["total"], - serde_json::json!(0.0), - "a modifier-less compact ctor in a package-private record is not public" - ); - // An explicit modifier on the compact ctor still wins over the record's. - let explicit_priv = analyze("public record R(int x) { private R { } }"); - let ep = - serde_json::to_value(mehen_report::metrics_json::npm(&explicit_priv.root.metrics)).unwrap(); - assert_eq!( - ep["total"], - serde_json::json!(0.0), - "an explicit private compact ctor overrides the record's public access" - ); -} - -#[test] -fn anonymous_class_body_methods_are_not_enclosing_members() { - // Regression (PR #160 review): a method in an anonymous class expression - // (`new Runnable() { void run() {} }`) belongs to the anonymous subclass, - // not the enclosing class, so it must NOT count toward the enclosing - // class's NPM. - let a = analyze("class C { Runnable r = new Runnable() { public void run() {} }; }"); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 0.0, - "interfaces": 0.0, - "class_methods": 0.0, - "interface_methods": 0.0, - "classes_average": null, - "interfaces_average": null, - "total": 0.0, - "total_methods": 0.0, - "average": null - } - "#); -} - -#[test] -fn enum_constant_body_methods_are_not_enum_members() { - // Regression (PR #160 review): a method inside a constant-specific enum - // body belongs to that constant's anonymous subclass, not the enum, so it - // must NOT count toward the enum's NPM. The enum declares no methods of its - // own here. - let a = analyze( - "enum E { - A { - public void m() {} - }; - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!(npm, @r#" - { - "classes": 0.0, - "interfaces": 0.0, - "class_methods": 0.0, - "interface_methods": 0.0, - "classes_average": null, - "interfaces_average": null, - "total": 0.0, - "total_methods": 0.0, - "average": null - } - "#); -} - -#[test] -fn interface_nested_record_compact_ctor_is_public() { - // Regression (PR #160 review): after class-like spaces open at their - // wrapper (round 29), member visibility must be resolved from the container - // enclosing the wrapper, NOT the just-opened type space. An interface's - // members are implicitly public, so a modifier-less compact canonical - // constructor of an interface-nested record inherits public access → NPM 1. - let iface = analyze("interface I { record R(int x) { R {} } }"); - let i = serde_json::to_value(mehen_report::metrics_json::npm(&iface.root.metrics)).unwrap(); - assert_eq!( - i["total"], - serde_json::json!(1.0), - "an interface-nested record's modifier-less compact ctor is public" - ); - // Control: the same nested in a class is package-private (not public). - let cls = analyze("class C { record R(int x) { R {} } }"); - let c = serde_json::to_value(mehen_report::metrics_json::npm(&cls.root.metrics)).unwrap(); - assert_eq!( - c["total"], - serde_json::json!(0.0), - "a class-nested record's modifier-less compact ctor is package-private" - ); -} - -#[test] -fn anon_body_nested_record_preserves_record_visibility() { - // Regression (PR #160 review): the `in_anon_body` early return in - // member_propagation must not discard visibility a nested type needs. A - // `public record` inside an anonymous class body must keep its `public` so - // its modifier-less compact canonical constructor is counted public — even - // though the anon body's OWN members are not attributed to any enclosing - // space. `new Object(){ public record R(int x) { R {} } }` → NPM 1. - let public_rec = - analyze("class C { Object o = new Object(){ public record R(int x) { R {} } }; }"); - let pr = - serde_json::to_value(mehen_report::metrics_json::npm(&public_rec.root.metrics)).unwrap(); - assert_eq!( - pr["total"], - serde_json::json!(1.0), - "a public record's compact ctor stays public inside an anon body" - ); - // A package-private record in an anon body → its compact ctor is not public. - let pkg_rec = analyze("class C { Object o = new Object(){ record R(int x) { R {} } }; }"); - let kr = serde_json::to_value(mehen_report::metrics_json::npm(&pkg_rec.root.metrics)).unwrap(); - assert_eq!(kr["total"], serde_json::json!(0.0)); - // Guard: the anon body's OWN public method must still NOT count toward the - // enclosing class's NPM (it belongs to the anonymous subclass). - let own_method = analyze("class C { Object o = new Object(){ public void m() {} }; }"); - let om = - serde_json::to_value(mehen_report::metrics_json::npm(&own_method.root.metrics)).unwrap(); - assert_eq!( - om["total"], - serde_json::json!(0.0), - "an anonymous class's own method must not count toward the enclosing NPM" - ); -} diff --git a/crates/mehen-java/tests/wmc.rs b/crates/mehen-java/tests/wmc.rs deleted file mode 100644 index 11c8246c..00000000 --- a/crates/mehen-java/tests/wmc.rs +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! WMC (weighted methods per class) tests for the ANTLR Java walker. -//! -//! WMC sums the cyclomatic complexity of a class's methods. Interfaces are -//! excluded from WMC. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_java::JavaAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = JavaAnalyzer::new(); - let file = SourceFile::new("Foo.java".into(), Language::Java, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn class_sums_method_cyclomatics() { - // `simple` McCabe 1; `branchy` McCabe 1 + if(1) + &&(1) = 3. WMC = 4. - let a = analyze( - "class C { - int simple() { return 1; } - int branchy(int a, int b) { - if (a > 0 && b > 0) { return a; } - return b; - } - }", - ); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - insta::assert_json_snapshot!(wmc, @r#" - { - "classes": 4.0, - "interfaces": 0.0, - "total": 4.0 - } - "#); -} - -#[test] -fn enum_constant_body_method_does_not_inflate_enum_wmc() { - // Regression (PR #160 review): a method inside a constant-specific enum - // body (`A { void m() {…} }`) belongs to `A`'s anonymous subclass, not the - // enum, so it must NOT roll into the enum's WMC. The enum here declares no - // methods of its own, so WMC stays 0. - let a = analyze( - "enum E { - A { - public void m() { if (true) {} } - }; - }", - ); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - insta::assert_json_snapshot!(wmc, @r#" - { - "classes": 0.0, - "interfaces": 0.0, - "total": 0.0 - } - "#); -} - -#[test] -fn interface_methods_are_excluded_from_wmc() { - // Regression (PR #160 review): Java WMC is per class — an interface's - // methods (including `default`) must not accumulate WMC, even in a file - // that also contains a class. Here the class has no methods, so total WMC - // is 0 despite the interface's `default` method containing an `if`. - let a = analyze( - "class C {} - interface I { - default int m() { if (flag) {} return 1; } - }", - ); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - insta::assert_json_snapshot!(wmc, @r#" - { - "classes": 0.0, - "interfaces": 0.0, - "total": 0.0 - } - "#); -} - -#[test] -fn anonymous_class_body_method_does_not_inflate_enclosing_wmc() { - // Regression (PR #160 review): a method in an anonymous class body - // (`new Runnable() { void run() {…} }`, reached via - // `classCreatorRest → classBody`) belongs to the anonymous subclass, not - // the enclosing class C, so it must NOT roll into C's WMC. C declares no - // methods of its own. - let a = analyze("class C { Runnable r = new Runnable() { public void run() { if (x) {} } }; }"); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - insta::assert_json_snapshot!(wmc, @r#" - { - "classes": 0.0, - "interfaces": 0.0, - "total": 0.0 - } - "#); -} - -#[test] -fn lambda_in_field_initializer_does_not_inflate_class_wmc() { - // Regression (PR #160 review): a lambda is a Closure, not a method — its - // cyclomatic must NOT roll into the class's WMC (WMC weights methods). The - // class declares no methods, so WMC stays 0 even though the lambda body - // contains an `if`. - let a = analyze("class C { Runnable r = () -> { if (flag) {} }; }"); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - insta::assert_json_snapshot!(wmc, @r#" - { - "classes": 0.0, - "interfaces": 0.0, - "total": 0.0 - } - "#); -} diff --git a/crates/mehen-kotlin-parser/Cargo.toml b/crates/mehen-kotlin-parser/Cargo.toml deleted file mode 100644 index 5a031be7..00000000 --- a/crates/mehen-kotlin-parser/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "mehen-kotlin-parser" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -# Generated from `xtask/templates/parser-readme.md` by `cargo xtask antlr -# generate kotlin` — never hand-edit. Named explicitly so it ships on the -# crate's registry page when published. -readme = "README.md" -description = "ANTLR-generated Kotlin lexer and parser (Kotlin spec grammar) on the antlr-rust-runtime." -# Unlike the internal `mehen-*` analyzer crates (`publish = false`), this -# crate ships ONLY the generated lexer/parser so external tools can depend -# on the Kotlin parser alone via a git tag on this repo — the same way -# `mehen` itself consumes ruff/oxc/sqruff parser crates. It carries no -# mehen-specific logic and no dependency on `mehen-core`. -publish = true - -[dependencies] -# The generated modules reference the runtime by its real crate name -# (`use antlr4_runtime::…`). Pinned in exactly one place — the workspace -# `[workspace.dependencies]` `antlr4_runtime` entry — so every consumer -# links the same revision the modules were generated against. Regenerate -# with `cargo xtask antlr generate kotlin` after any bump. -antlr4_runtime = { workspace = true } - -# The generated modules are checked in verbatim and intentionally expose -# their whole surface, so this crate deliberately does NOT opt into the -# workspace `unreachable_pub` lint (`[lints] workspace = true`) that the -# hand-written crates use. diff --git a/crates/mehen-kotlin-parser/README.md b/crates/mehen-kotlin-parser/README.md deleted file mode 100644 index f2829051..00000000 --- a/crates/mehen-kotlin-parser/README.md +++ /dev/null @@ -1,95 +0,0 @@ - -# mehen-kotlin-parser - -ANTLR-generated **Kotlin** lexer and parser, running on the -[`antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime) Rust -runtime. - -This crate is produced by the [`mehen`](https://github.com/ophi-dev/mehen) code-metrics tool but -carries **no mehen-specific logic** and **no dependency on `mehen-core`**: it -ships only the machine-generated lexer/parser plus the vendored `.g4` grammar. -That makes it usable on its own — the same way `mehen` itself consumes the -ruff / oxc / sqruff parser crates — so you can parse Kotlin in your -own tool without pulling in an analyzer. - - - -## Add the dependency - -The crate is published from a git tag on the [`mehen` repository](https://github.com/ophi-dev/mehen), -not to crates.io. Depend on it by tag or branch: - -```toml -[dependencies] -# Pin a release tag (recommended) — see the repository's Releases page: -mehen-kotlin-parser = { git = "https://github.com/ophi-dev/mehen", tag = "vX.Y.Z" } -# …or track the default branch: -# mehen-kotlin-parser = { git = "https://github.com/ophi-dev/mehen", branch = "main" } -``` - -You do **not** need to depend on `antlr-rust-runtime` yourself: this crate -re-exports the exact runtime revision the modules were generated against as -`mehen_kotlin_parser::antlr4_runtime`. Reach the runtime types (`ParsedFile`, -`Node`, `TokenView`, …) through that path so your version can never drift from -the generated code. - -## Parse some Kotlin - -`kotlin_parser::parse` wires up the lexer, token stream, parser, and a -chosen entry rule in one call, returning an owned `ParsedFile` that holds the -token store and the flat CST: - -```rust -use mehen_kotlin_parser::kotlin_parser::{self, KotlinParser}; -use mehen_kotlin_parser::kotlin_lexer::KotlinLexer; - -fn main() -> Result<(), mehen_kotlin_parser::antlr4_runtime::AntlrError> { - let parsed = kotlin_parser::parse( - "fun main() {}\n", - KotlinLexer::new, - KotlinParser::kotlin_file, - )?; - - // Walk the CST from the entry-rule root, or read the buffered tokens. - let root = parsed.tree(); - let _ = root; - Ok(()) -} -``` - -Need parser diagnostics (e.g. the syntax-error count) after the entry rule -runs? Use `parse_with_parser`, which hands the parser back: - -```rust -use mehen_kotlin_parser::kotlin_parser::{self, KotlinParser}; -use mehen_kotlin_parser::kotlin_lexer::KotlinLexer; -// `number_of_syntax_errors` is a `Parser`-trait method, so the trait must be -// in scope to call it. -use mehen_kotlin_parser::antlr4_runtime::Parser; - -fn main() -> Result<(), mehen_kotlin_parser::antlr4_runtime::AntlrError> { - let out = kotlin_parser::parse_with_parser( - "fun main() {}\n", - KotlinLexer::new, - KotlinParser::kotlin_file, - )?; - let errors = out.parser.number_of_syntax_errors(); - let parsed = out.parser.into_parsed_file(out.result); - let _ = (errors, parsed.tree()); - Ok(()) -} -``` - -The parse tree has **no parent pointers** (the runtime stores `Node` views in a -flat arena), so thread any parent-dependent context top-down as you walk. - -## Grammar & provenance - -- **Upstream grammar:** [`Kotlin/kotlin-spec`](https://github.com/Kotlin/kotlin-spec) -- **Vendored `.g4` files + any local patches:** [`grammar/`](grammar/) — see [`grammar/PROVENANCE.md`](grammar/PROVENANCE.md) for the exact commit -- **ANTLR Rust runtime + codegen:** [`antlr-rust-runtime`](https://crates.io/crates/antlr-rust-runtime) / [`antlr-rust-codegen`](https://crates.io/crates/antlr-rust-codegen) `v0.33.1` - -## License - -`AGPL-3.0-only`, same as the `mehen` workspace. diff --git a/crates/mehen-kotlin-parser/grammar/KotlinLexer.g4 b/crates/mehen-kotlin-parser/grammar/KotlinLexer.g4 deleted file mode 100644 index 25943a3a..00000000 --- a/crates/mehen-kotlin-parser/grammar/KotlinLexer.g4 +++ /dev/null @@ -1,538 +0,0 @@ -/** - * Kotlin lexical grammar in ANTLR4 notation - */ - -lexer grammar KotlinLexer; - -import UnicodeClasses; - -// SECTION: lexicalGeneral - -ShebangLine - : '#!' ~[\r\n]* - ; - -DelimitedComment - : '/*' ( DelimitedComment | . )*? '*/' - -> channel(HIDDEN) - ; - -LineComment - : '//' ~[\r\n]* - -> channel(HIDDEN) - ; - -WS - : [\u0020\u0009\u000C] - -> channel(HIDDEN) - ; - -NL: '\n' | '\r' '\n'?; - -fragment Hidden: DelimitedComment | LineComment | WS; - -// SECTION: separatorsAndOperations - -RESERVED: '...'; -DOT: '.'; -COMMA: ','; -LPAREN: '(' -> pushMode(Inside); -RPAREN: ')'; -LSQUARE: '[' -> pushMode(Inside); -RSQUARE: ']'; -LCURL: '{' -> pushMode(DEFAULT_MODE); -/* - * MEHEN LOCAL PATCH (do not drop on re-vendor): - * Upstream uses a Java embedded action here — - * RCURL: '}' { if (!_modeStack.isEmpty()) { popMode(); } }; - * — which the ANTLR Rust target cannot translate, so the generated Rust - * lexer never popped the mode on `}`. That broke string-template - * interpolation (`"x ${foo()} y"`): everything after `}` was tokenized in - * DEFAULT_MODE instead of returning to string mode, producing recovered - * syntax errors. The grammar's own comment invites replacing this action - * with the target language's equivalent; the standard `-> popMode` lexer - * command is target-portable and the runtime's `pop_mode()` is a safe no-op - * on an empty mode stack, so it matches the guarded Java behavior. - */ -RCURL: '}' -> popMode; -MULT: '*'; -MOD: '%'; -DIV: '/'; -ADD: '+'; -SUB: '-'; -INCR: '++'; -DECR: '--'; -CONJ: '&&'; -DISJ: '||'; -EXCL_WS: '!' Hidden; -EXCL_NO_WS: '!'; -COLON: ':'; -SEMICOLON: ';'; -ASSIGNMENT: '='; -ADD_ASSIGNMENT: '+='; -SUB_ASSIGNMENT: '-='; -MULT_ASSIGNMENT: '*='; -DIV_ASSIGNMENT: '/='; -MOD_ASSIGNMENT: '%='; -ARROW: '->'; -DOUBLE_ARROW: '=>'; -RANGE: '..'; -RANGE_UNTIL: '..<'; -COLONCOLON: '::'; -DOUBLE_SEMICOLON: ';;'; -HASH: '#'; -AT_NO_WS: '@'; -AT_POST_WS: '@' (Hidden | NL); -AT_PRE_WS: (Hidden | NL) '@' ; -AT_BOTH_WS: (Hidden | NL) '@' (Hidden | NL); -QUEST_WS: '?' Hidden; -QUEST_NO_WS: '?'; -LANGLE: '<'; -RANGLE: '>'; -LE: '<='; -GE: '>='; -EXCL_EQ: '!='; -EXCL_EQEQ: '!=='; -AS_SAFE: 'as?'; -EQEQ: '=='; -EQEQEQ: '==='; -SINGLE_QUOTE: '\''; -AMP: '&'; - -// SECTION: keywords - -RETURN_AT: 'return@' Identifier; -CONTINUE_AT: 'continue@' Identifier; -BREAK_AT: 'break@' Identifier; - -THIS_AT: 'this@' Identifier; -SUPER_AT: 'super@' Identifier; - -FILE: 'file'; -FIELD: 'field'; -PROPERTY: 'property'; -GET: 'get'; -SET: 'set'; -RECEIVER: 'receiver'; -PARAM: 'param'; -SETPARAM: 'setparam'; -DELEGATE: 'delegate'; - -PACKAGE: 'package'; -IMPORT: 'import'; -CLASS: 'class'; -INTERFACE: 'interface'; -FUN: 'fun'; -OBJECT: 'object'; -VAL: 'val'; -VAR: 'var'; -TYPE_ALIAS: 'typealias'; -CONSTRUCTOR: 'constructor'; -BY: 'by'; -COMPANION: 'companion'; -INIT: 'init'; -THIS: 'this'; -SUPER: 'super'; -TYPEOF: 'typeof'; -WHERE: 'where'; -IF: 'if'; -ELSE: 'else'; -WHEN: 'when'; -TRY: 'try'; -CATCH: 'catch'; -FINALLY: 'finally'; -FOR: 'for'; -DO: 'do'; -WHILE: 'while'; -THROW: 'throw'; -RETURN: 'return'; -CONTINUE: 'continue'; -BREAK: 'break'; -AS: 'as'; -IS: 'is'; -IN: 'in'; -NOT_IS: '!is' (Hidden | NL); -NOT_IN: '!in' (Hidden | NL); -OUT: 'out'; -DYNAMIC: 'dynamic'; - -// SECTION: lexicalModifiers - -PUBLIC: 'public'; -PRIVATE: 'private'; -PROTECTED: 'protected'; -INTERNAL: 'internal'; -ENUM: 'enum'; -SEALED: 'sealed'; -ANNOTATION: 'annotation'; -DATA: 'data'; -INNER: 'inner'; -VALUE: 'value'; -TAILREC: 'tailrec'; -OPERATOR: 'operator'; -INLINE: 'inline'; -INFIX: 'infix'; -EXTERNAL: 'external'; -SUSPEND: 'suspend'; -OVERRIDE: 'override'; -ABSTRACT: 'abstract'; -FINAL: 'final'; -OPEN: 'open'; -CONST: 'const'; -LATEINIT: 'lateinit'; -VARARG: 'vararg'; -NOINLINE: 'noinline'; -CROSSINLINE: 'crossinline'; -REIFIED: 'reified'; -EXPECT: 'expect'; -ACTUAL: 'actual'; - -// SECTION: literals - -fragment DecDigit: '0'..'9'; -fragment DecDigitNoZero: '1'..'9'; -fragment DecDigitOrSeparator: DecDigit | '_'; - -fragment DecDigits - : DecDigit DecDigitOrSeparator* DecDigit - | DecDigit - ; - -fragment DoubleExponent: [eE] [+-]? DecDigits; - -RealLiteral - : FloatLiteral - | DoubleLiteral - ; - -FloatLiteral - : DoubleLiteral [fF] - | DecDigits [fF] - ; - -DoubleLiteral - : DecDigits? '.' DecDigits DoubleExponent? - | DecDigits DoubleExponent - ; - -IntegerLiteral - : DecDigitNoZero DecDigitOrSeparator* DecDigit - | DecDigit - ; - -fragment HexDigit: [0-9a-fA-F]; -fragment HexDigitOrSeparator: HexDigit | '_'; - -HexLiteral - : '0' [xX] HexDigit HexDigitOrSeparator* HexDigit - | '0' [xX] HexDigit - ; - -fragment BinDigit: [01]; -fragment BinDigitOrSeparator: BinDigit | '_'; - -BinLiteral - : '0' [bB] BinDigit BinDigitOrSeparator* BinDigit - | '0' [bB] BinDigit - ; - -UnsignedLiteral - : (IntegerLiteral | HexLiteral | BinLiteral) [uU] [lL]? - ; - -LongLiteral - : (IntegerLiteral | HexLiteral | BinLiteral) [lL] - ; - -BooleanLiteral: 'true'| 'false'; - -NullLiteral: 'null'; - -CharacterLiteral - : '\'' (EscapeSeq | ~[\n\r'\\]) '\'' - ; - -// SECTION: lexicalIdentifiers - -fragment UnicodeDigit: UNICODE_CLASS_ND; - -Identifier - : (Letter | '_') (Letter | '_' | UnicodeDigit)* - | '`' ~([\r\n] | '`')+ '`' - ; - -IdentifierOrSoftKey - : Identifier - /* Soft keywords */ - | ABSTRACT - | ANNOTATION - | BY - | CATCH - | COMPANION - | CONSTRUCTOR - | CROSSINLINE - | DATA - | DYNAMIC - | ENUM - | EXTERNAL - | FINAL - | FINALLY - | IMPORT - | INFIX - | INIT - | INLINE - | INNER - | INTERNAL - | LATEINIT - | NOINLINE - | OPEN - | OPERATOR - | OUT - | OVERRIDE - | PRIVATE - | PROTECTED - | PUBLIC - | REIFIED - | SEALED - | TAILREC - | VARARG - | WHERE - | GET - | SET - | FIELD - | PROPERTY - | RECEIVER - | PARAM - | SETPARAM - | DELEGATE - | FILE - | EXPECT - | ACTUAL - | VALUE - /* Strong keywords */ - | CONST - | SUSPEND - ; - -FieldIdentifier - : '$' IdentifierOrSoftKey - ; - -fragment UniCharacterLiteral - : '\\' 'u' HexDigit HexDigit HexDigit HexDigit - ; - -fragment EscapedIdentifier - : '\\' ('t' | 'b' | 'r' | 'n' | '\'' | '"' | '\\' | '$') - ; - -fragment EscapeSeq - : UniCharacterLiteral - | EscapedIdentifier - ; - -// SECTION: characters - -fragment Letter - : UNICODE_CLASS_LU - | UNICODE_CLASS_LL - | UNICODE_CLASS_LT - | UNICODE_CLASS_LM - | UNICODE_CLASS_LO - ; - -// SECTION: strings - -QUOTE_OPEN: '"' -> pushMode(LineString); - -TRIPLE_QUOTE_OPEN: '"""' -> pushMode(MultiLineString); - -mode LineString; - -QUOTE_CLOSE - : '"' -> popMode - ; - -LineStrRef - : FieldIdentifier - ; - -LineStrText - : ~('\\' | '"' | '$')+ | '$' - ; - -LineStrEscapedChar - : EscapedIdentifier - | UniCharacterLiteral - ; - -LineStrExprStart - : '${' -> pushMode(DEFAULT_MODE) - ; - -mode MultiLineString; - -TRIPLE_QUOTE_CLOSE - : MultiLineStringQuote? '"""' -> popMode - ; - -MultiLineStringQuote - : '"'+ - ; - -MultiLineStrRef - : FieldIdentifier - ; - -MultiLineStrText - : ~('"' | '$')+ | '$' - ; - -MultiLineStrExprStart - : '${' -> pushMode(DEFAULT_MODE) - ; - -// SECTION: inside - -mode Inside; - -Inside_RPAREN: RPAREN -> popMode, type(RPAREN); -Inside_RSQUARE: RSQUARE -> popMode, type(RSQUARE); -Inside_LPAREN: LPAREN -> pushMode(Inside), type(LPAREN); -Inside_LSQUARE: LSQUARE -> pushMode(Inside), type(LSQUARE); -Inside_LCURL: LCURL -> pushMode(DEFAULT_MODE), type(LCURL); -Inside_RCURL: RCURL -> popMode, type(RCURL); - -Inside_DOT: DOT -> type(DOT); -Inside_COMMA: COMMA -> type(COMMA); -Inside_MULT: MULT -> type(MULT); -Inside_MOD: MOD -> type(MOD); -Inside_DIV: DIV -> type(DIV); -Inside_ADD: ADD -> type(ADD); -Inside_SUB: SUB -> type(SUB); -Inside_INCR: INCR -> type(INCR); -Inside_DECR: DECR -> type(DECR); -Inside_CONJ: CONJ -> type(CONJ); -Inside_DISJ: DISJ -> type(DISJ); -Inside_EXCL_WS: '!' (Hidden|NL) -> type(EXCL_WS); -Inside_EXCL_NO_WS: EXCL_NO_WS -> type(EXCL_NO_WS); -Inside_COLON: COLON -> type(COLON); -Inside_SEMICOLON: SEMICOLON -> type(SEMICOLON); -Inside_ASSIGNMENT: ASSIGNMENT -> type(ASSIGNMENT); -Inside_ADD_ASSIGNMENT: ADD_ASSIGNMENT -> type(ADD_ASSIGNMENT); -Inside_SUB_ASSIGNMENT: SUB_ASSIGNMENT -> type(SUB_ASSIGNMENT); -Inside_MULT_ASSIGNMENT: MULT_ASSIGNMENT -> type(MULT_ASSIGNMENT); -Inside_DIV_ASSIGNMENT: DIV_ASSIGNMENT -> type(DIV_ASSIGNMENT); -Inside_MOD_ASSIGNMENT: MOD_ASSIGNMENT -> type(MOD_ASSIGNMENT); -Inside_ARROW: ARROW -> type(ARROW); -Inside_DOUBLE_ARROW: DOUBLE_ARROW -> type(DOUBLE_ARROW); -Inside_RANGE: RANGE -> type(RANGE); -Inside_RANGE_UNTIL: RANGE_UNTIL -> type(RANGE_UNTIL); -Inside_RESERVED: RESERVED -> type(RESERVED); -Inside_COLONCOLON: COLONCOLON -> type(COLONCOLON); -Inside_DOUBLE_SEMICOLON: DOUBLE_SEMICOLON -> type(DOUBLE_SEMICOLON); -Inside_HASH: HASH -> type(HASH); -Inside_AT_NO_WS: AT_NO_WS -> type(AT_NO_WS); -Inside_AT_POST_WS: AT_POST_WS -> type(AT_POST_WS); -Inside_AT_PRE_WS: AT_PRE_WS -> type(AT_PRE_WS); -Inside_AT_BOTH_WS: AT_BOTH_WS -> type(AT_BOTH_WS); -Inside_QUEST_WS: '?' (Hidden | NL) -> type(QUEST_WS); -Inside_QUEST_NO_WS: QUEST_NO_WS -> type(QUEST_NO_WS); -Inside_LANGLE: LANGLE -> type(LANGLE); -Inside_RANGLE: RANGLE -> type(RANGLE); -Inside_LE: LE -> type(LE); -Inside_GE: GE -> type(GE); -Inside_EXCL_EQ: EXCL_EQ -> type(EXCL_EQ); -Inside_EXCL_EQEQ: EXCL_EQEQ -> type(EXCL_EQEQ); -Inside_IS: IS -> type(IS); -Inside_NOT_IS: NOT_IS -> type(NOT_IS); -Inside_NOT_IN: NOT_IN -> type(NOT_IN); -Inside_AS: AS -> type(AS); -Inside_AS_SAFE: AS_SAFE -> type(AS_SAFE); -Inside_EQEQ: EQEQ -> type(EQEQ); -Inside_EQEQEQ: EQEQEQ -> type(EQEQEQ); -Inside_SINGLE_QUOTE: SINGLE_QUOTE -> type(SINGLE_QUOTE); -Inside_AMP: AMP -> type(AMP); -Inside_QUOTE_OPEN: QUOTE_OPEN -> pushMode(LineString), type(QUOTE_OPEN); -Inside_TRIPLE_QUOTE_OPEN: TRIPLE_QUOTE_OPEN -> pushMode(MultiLineString), type(TRIPLE_QUOTE_OPEN); - -Inside_VAL: VAL -> type(VAL); -Inside_VAR: VAR -> type(VAR); -Inside_FUN: FUN -> type(FUN); -Inside_OBJECT: OBJECT -> type(OBJECT); -Inside_SUPER: SUPER -> type(SUPER); -Inside_IN: IN -> type(IN); -Inside_OUT: OUT -> type(OUT); -Inside_FIELD: FIELD -> type(FIELD); -Inside_FILE: FILE -> type(FILE); -Inside_PROPERTY: PROPERTY -> type(PROPERTY); -Inside_GET: GET -> type(GET); -Inside_SET: SET -> type(SET); -Inside_RECEIVER: RECEIVER -> type(RECEIVER); -Inside_PARAM: PARAM -> type(PARAM); -Inside_SETPARAM: SETPARAM -> type(SETPARAM); -Inside_DELEGATE: DELEGATE -> type(DELEGATE); -Inside_THROW: THROW -> type(THROW); -Inside_RETURN: RETURN -> type(RETURN); -Inside_CONTINUE: CONTINUE -> type(CONTINUE); -Inside_BREAK: BREAK -> type(BREAK); -Inside_RETURN_AT: RETURN_AT -> type(RETURN_AT); -Inside_CONTINUE_AT: CONTINUE_AT -> type(CONTINUE_AT); -Inside_BREAK_AT: BREAK_AT -> type(BREAK_AT); -Inside_IF: IF -> type(IF); -Inside_ELSE: ELSE -> type(ELSE); -Inside_WHEN: WHEN -> type(WHEN); -Inside_TRY: TRY -> type(TRY); -Inside_CATCH: CATCH -> type(CATCH); -Inside_FINALLY: FINALLY -> type(FINALLY); -Inside_FOR: FOR -> type(FOR); -Inside_DO: DO -> type(DO); -Inside_WHILE: WHILE -> type(WHILE); - -Inside_PUBLIC: PUBLIC -> type(PUBLIC); -Inside_PRIVATE: PRIVATE -> type(PRIVATE); -Inside_PROTECTED: PROTECTED -> type(PROTECTED); -Inside_INTERNAL: INTERNAL -> type(INTERNAL); -Inside_ENUM: ENUM -> type(ENUM); -Inside_SEALED: SEALED -> type(SEALED); -Inside_ANNOTATION: ANNOTATION -> type(ANNOTATION); -Inside_DATA: DATA -> type(DATA); -Inside_INNER: INNER -> type(INNER); -Inside_VALUE: VALUE -> type(VALUE); -Inside_TAILREC: TAILREC -> type(TAILREC); -Inside_OPERATOR: OPERATOR -> type(OPERATOR); -Inside_INLINE: INLINE -> type(INLINE); -Inside_INFIX: INFIX -> type(INFIX); -Inside_EXTERNAL: EXTERNAL -> type(EXTERNAL); -Inside_SUSPEND: SUSPEND -> type(SUSPEND); -Inside_OVERRIDE: OVERRIDE -> type(OVERRIDE); -Inside_ABSTRACT: ABSTRACT -> type(ABSTRACT); -Inside_FINAL: FINAL -> type(FINAL); -Inside_OPEN: OPEN -> type(OPEN); -Inside_CONST: CONST -> type(CONST); -Inside_LATEINIT: LATEINIT -> type(LATEINIT); -Inside_VARARG: VARARG -> type(VARARG); -Inside_NOINLINE: NOINLINE -> type(NOINLINE); -Inside_CROSSINLINE: CROSSINLINE -> type(CROSSINLINE); -Inside_REIFIED: REIFIED -> type(REIFIED); -Inside_EXPECT: EXPECT -> type(EXPECT); -Inside_ACTUAL: ACTUAL -> type(ACTUAL); - -Inside_BooleanLiteral: BooleanLiteral -> type(BooleanLiteral); -Inside_IntegerLiteral: IntegerLiteral -> type(IntegerLiteral); -Inside_HexLiteral: HexLiteral -> type(HexLiteral); -Inside_BinLiteral: BinLiteral -> type(BinLiteral); -Inside_CharacterLiteral: CharacterLiteral -> type(CharacterLiteral); -Inside_RealLiteral: RealLiteral -> type(RealLiteral); -Inside_NullLiteral: NullLiteral -> type(NullLiteral); -Inside_LongLiteral: LongLiteral -> type(LongLiteral); -Inside_UnsignedLiteral: UnsignedLiteral -> type(UnsignedLiteral); - -Inside_Identifier: Identifier -> type(Identifier); -Inside_Comment: (LineComment | DelimitedComment) -> channel(HIDDEN); -Inside_WS: WS -> channel(HIDDEN); -Inside_NL: NL -> channel(HIDDEN); - -mode DEFAULT_MODE; - -ErrorCharacter: .; diff --git a/crates/mehen-kotlin-parser/grammar/KotlinParser.g4 b/crates/mehen-kotlin-parser/grammar/KotlinParser.g4 deleted file mode 100644 index a0335df4..00000000 --- a/crates/mehen-kotlin-parser/grammar/KotlinParser.g4 +++ /dev/null @@ -1,928 +0,0 @@ -/** - * Kotlin syntax grammar in ANTLR4 notation - */ - -parser grammar KotlinParser; - -options { tokenVocab = KotlinLexer; } - -// SECTION: general - -kotlinFile - : shebangLine? NL* fileAnnotation* packageHeader importList topLevelObject* EOF - ; - -script - : shebangLine? NL* fileAnnotation* packageHeader importList (statement semi)* EOF - ; - -shebangLine - : ShebangLine NL+ - ; - -fileAnnotation - : (AT_NO_WS | AT_PRE_WS) FILE NL* COLON NL* (LSQUARE unescapedAnnotation+ RSQUARE | unescapedAnnotation) NL* - ; - -packageHeader - : (PACKAGE identifier semi?)? - ; - -importList - : importHeader* - ; - -importHeader - : IMPORT identifier (DOT MULT | importAlias)? semi? - ; - -importAlias - : AS simpleIdentifier - ; - -topLevelObject - : declaration semis? - ; - -typeAlias - : modifiers? TYPE_ALIAS NL* simpleIdentifier (NL* typeParameters)? NL* ASSIGNMENT NL* type - ; - -declaration - : classDeclaration - | objectDeclaration - | functionDeclaration - | propertyDeclaration - | typeAlias - ; - -// SECTION: classes - -classDeclaration - : modifiers? (CLASS | (FUN NL*)? INTERFACE) NL* simpleIdentifier - (NL* typeParameters)? (NL* primaryConstructor)? - (NL* COLON NL* delegationSpecifiers)? - (NL* typeConstraints)? - (NL* classBody | NL* enumClassBody)? - ; - -primaryConstructor - : (modifiers? CONSTRUCTOR NL*)? classParameters - ; - -classBody - : LCURL NL* classMemberDeclarations NL* RCURL - ; - -classParameters - : LPAREN NL* (classParameter (NL* COMMA NL* classParameter)* (NL* COMMA)?)? NL* RPAREN - ; - -classParameter - : modifiers? (VAL | VAR)? NL* simpleIdentifier COLON NL* type (NL* ASSIGNMENT NL* expression)? - ; - -delegationSpecifiers - : annotatedDelegationSpecifier (NL* COMMA NL* annotatedDelegationSpecifier)* - ; - -delegationSpecifier - : constructorInvocation - | explicitDelegation - | userType - | functionType - | SUSPEND NL* functionType - ; - -constructorInvocation - : userType NL* valueArguments - ; - -annotatedDelegationSpecifier - : annotation* NL* delegationSpecifier - ; - -explicitDelegation - : (userType | functionType) NL* BY NL* expression - ; - -typeParameters - : LANGLE NL* typeParameter (NL* COMMA NL* typeParameter)* (NL* COMMA)? NL* RANGLE - ; - -typeParameter - : typeParameterModifiers? NL* simpleIdentifier (NL* COLON NL* type)? - ; - -typeConstraints - : WHERE NL* typeConstraint (NL* COMMA NL* typeConstraint)* - ; - -typeConstraint - : annotation* simpleIdentifier NL* COLON NL* type - ; - -// SECTION: classMembers - -classMemberDeclarations - : (classMemberDeclaration semis?)* - ; - -classMemberDeclaration - : declaration - | companionObject - | anonymousInitializer - | secondaryConstructor - ; - -anonymousInitializer - : INIT NL* block - ; - -companionObject - : modifiers? COMPANION NL* DATA? NL* OBJECT - (NL* simpleIdentifier)? - (NL* COLON NL* delegationSpecifiers)? - (NL* classBody)? - ; - -functionValueParameters - : LPAREN NL* (functionValueParameter (NL* COMMA NL* functionValueParameter)* (NL* COMMA)?)? NL* RPAREN - ; - -functionValueParameter - : parameterModifiers? parameter (NL* ASSIGNMENT NL* expression)? - ; - -functionDeclaration - : modifiers? - FUN (NL* typeParameters)? (NL* receiverType NL* DOT)? NL* simpleIdentifier - NL* functionValueParameters - (NL* COLON NL* type)? - (NL* typeConstraints)? - (NL* functionBody)? - ; - -functionBody - : block - | ASSIGNMENT NL* expression - ; - -variableDeclaration - : annotation* NL* simpleIdentifier (NL* COLON NL* type)? - ; - -multiVariableDeclaration - : LPAREN NL* variableDeclaration (NL* COMMA NL* variableDeclaration)* (NL* COMMA)? NL* RPAREN - ; - -propertyDeclaration - : modifiers? (VAL | VAR) - (NL* typeParameters)? - (NL* receiverType NL* DOT)? - (NL* (multiVariableDeclaration | variableDeclaration)) - (NL* typeConstraints)? - (NL* (ASSIGNMENT NL* expression | propertyDelegate))? - (NL* SEMICOLON)? NL* (getter? (NL* semi? setter)? | setter? (NL* semi? getter)?) - ; - -propertyDelegate - : BY NL* expression - ; - -getter - : modifiers? GET - (NL* LPAREN NL* RPAREN (NL* COLON NL* type)? NL* functionBody)? - ; - -setter - : modifiers? SET - (NL* LPAREN NL* functionValueParameterWithOptionalType (NL* COMMA)? NL* RPAREN (NL* COLON NL* type)? NL* functionBody)? - ; - -parametersWithOptionalType - : LPAREN NL* (functionValueParameterWithOptionalType (NL* COMMA NL* functionValueParameterWithOptionalType)* (NL* COMMA)?)? NL* RPAREN - ; - -functionValueParameterWithOptionalType - : parameterModifiers? parameterWithOptionalType (NL* ASSIGNMENT NL* expression)? - ; - -parameterWithOptionalType - : simpleIdentifier NL* (COLON NL* type)? - ; - -parameter - : simpleIdentifier NL* COLON NL* type - ; - -objectDeclaration - : modifiers? OBJECT - NL* simpleIdentifier - (NL* COLON NL* delegationSpecifiers)? - (NL* classBody)? - ; - -secondaryConstructor - : modifiers? CONSTRUCTOR NL* functionValueParameters (NL* COLON NL* constructorDelegationCall)? NL* block? - ; - -constructorDelegationCall - : (THIS | SUPER) NL* valueArguments - ; - -// SECTION: enumClasses - -enumClassBody - : LCURL NL* enumEntries? (NL* SEMICOLON NL* classMemberDeclarations)? NL* RCURL - ; - -enumEntries - : enumEntry (NL* COMMA NL* enumEntry)* NL* COMMA? - ; - -enumEntry - : (modifiers NL*)? simpleIdentifier (NL* valueArguments)? (NL* classBody)? - ; - -// SECTION: types - -type - : typeModifiers? (functionType | parenthesizedType | nullableType | typeReference | definitelyNonNullableType) - ; - -typeReference - : userType - | DYNAMIC - ; - -nullableType - : (typeReference | parenthesizedType) NL* quest+ - ; - -quest - : QUEST_NO_WS - | QUEST_WS - ; - -userType - : simpleUserType (NL* DOT NL* simpleUserType)* - ; - -simpleUserType - : simpleIdentifier (NL* typeArguments)? - ; - -typeProjection - : typeProjectionModifiers? type - | MULT - ; - -typeProjectionModifiers - : typeProjectionModifier+ - ; - -typeProjectionModifier - : varianceModifier NL* - | annotation - ; - -functionType - : (receiverType NL* DOT NL*)? functionTypeParameters NL* ARROW NL* type - ; - -functionTypeParameters - : LPAREN NL* (parameter | type)? (NL* COMMA NL* (parameter | type))* (NL* COMMA)? NL* RPAREN - ; - -parenthesizedType - : LPAREN NL* type NL* RPAREN - ; - -receiverType - : typeModifiers? (parenthesizedType | nullableType | typeReference) - ; - -parenthesizedUserType - : LPAREN NL* (userType | parenthesizedUserType) NL* RPAREN - ; - -definitelyNonNullableType - : typeModifiers? (userType | parenthesizedUserType) NL* AMP NL* typeModifiers? (userType | parenthesizedUserType) - ; - -// SECTION: statements - -statements - : (statement (semis statement)*)? semis? - ; - -statement - : (label | annotation)* ( declaration | assignment | loopStatement | expression) - ; - -label - : simpleIdentifier (AT_NO_WS | AT_POST_WS) NL* - ; - -controlStructureBody - : block - | statement - ; - -block - : LCURL NL* statements NL* RCURL - ; - -loopStatement - : forStatement - | whileStatement - | doWhileStatement - ; - -forStatement - : FOR NL* LPAREN annotation* (variableDeclaration | multiVariableDeclaration) - IN expression RPAREN NL* controlStructureBody? - ; - -whileStatement - : WHILE NL* LPAREN expression RPAREN NL* (controlStructureBody | SEMICOLON) - ; - -doWhileStatement - : DO NL* controlStructureBody? NL* WHILE NL* LPAREN expression RPAREN - ; - -assignment - : (directlyAssignableExpression ASSIGNMENT | assignableExpression assignmentAndOperator) NL* expression - ; - -semi - : (SEMICOLON | NL) NL* - ; - -semis - : (SEMICOLON | NL)+ - ; - -// SECTION: expressions - -expression - : disjunction - ; - -disjunction - : conjunction (NL* DISJ NL* conjunction)* - ; - -conjunction - : equality (NL* CONJ NL* equality)* - ; - -equality - : comparison (equalityOperator NL* comparison)* - ; - -comparison - : genericCallLikeComparison (comparisonOperator NL* genericCallLikeComparison)* - ; - -genericCallLikeComparison - : infixOperation callSuffix* - ; - -infixOperation - : elvisExpression (inOperator NL* elvisExpression | isOperator NL* type)* - ; - -elvisExpression - : infixFunctionCall (NL* elvis NL* infixFunctionCall)* - ; - -elvis - : QUEST_NO_WS COLON - ; - -infixFunctionCall - : rangeExpression (simpleIdentifier NL* rangeExpression)* - ; - -rangeExpression - : additiveExpression ((RANGE | RANGE_UNTIL) NL* additiveExpression)* - ; - -additiveExpression - : multiplicativeExpression (additiveOperator NL* multiplicativeExpression)* - ; - -multiplicativeExpression - : asExpression (multiplicativeOperator NL* asExpression)* - ; - -asExpression - : prefixUnaryExpression (NL* asOperator NL* type)* - ; - -prefixUnaryExpression - : unaryPrefix* postfixUnaryExpression - ; - -unaryPrefix - : annotation - | label - | prefixUnaryOperator NL* - ; - -postfixUnaryExpression - : primaryExpression postfixUnarySuffix* - ; - -postfixUnarySuffix - : postfixUnaryOperator - | typeArguments - | callSuffix - | indexingSuffix - | navigationSuffix - ; - -directlyAssignableExpression - : postfixUnaryExpression assignableSuffix - | simpleIdentifier - | parenthesizedDirectlyAssignableExpression - ; - -parenthesizedDirectlyAssignableExpression - : LPAREN NL* directlyAssignableExpression NL* RPAREN - ; - -assignableExpression - : prefixUnaryExpression - | parenthesizedAssignableExpression - ; - -parenthesizedAssignableExpression - : LPAREN NL* assignableExpression NL* RPAREN - ; - -assignableSuffix - : typeArguments - | indexingSuffix - | navigationSuffix - ; - -indexingSuffix - : LSQUARE NL* expression (NL* COMMA NL* expression)* (NL* COMMA)? NL* RSQUARE - ; - -navigationSuffix - : memberAccessOperator NL* (simpleIdentifier | parenthesizedExpression | CLASS) - ; - -callSuffix - : typeArguments? (valueArguments? annotatedLambda | valueArguments) - ; - -annotatedLambda - : annotation* label? NL* lambdaLiteral - ; - -typeArguments - : LANGLE NL* typeProjection (NL* COMMA NL* typeProjection)* (NL* COMMA)? NL* RANGLE - ; - -valueArguments - : LPAREN NL* (valueArgument (NL* COMMA NL* valueArgument)* (NL* COMMA)? NL*)? RPAREN - ; - -valueArgument - : annotation? NL* (simpleIdentifier NL* ASSIGNMENT NL*)? MULT? NL* expression - ; - -primaryExpression - : parenthesizedExpression - | simpleIdentifier - | literalConstant - | stringLiteral - | callableReference - | functionLiteral - | objectLiteral - | collectionLiteral - | thisExpression - | superExpression - | ifExpression - | whenExpression - | tryExpression - | jumpExpression - ; - -parenthesizedExpression - : LPAREN NL* expression NL* RPAREN - ; - -collectionLiteral - : LSQUARE NL* (expression (NL* COMMA NL* expression)* (NL* COMMA)? NL*)? RSQUARE - ; - -literalConstant - : BooleanLiteral - | IntegerLiteral - | HexLiteral - | BinLiteral - | CharacterLiteral - | RealLiteral - | NullLiteral - | LongLiteral - | UnsignedLiteral - ; - -stringLiteral - : lineStringLiteral - | multiLineStringLiteral - ; - -lineStringLiteral - : QUOTE_OPEN (lineStringContent | lineStringExpression)* QUOTE_CLOSE - ; - -multiLineStringLiteral - : TRIPLE_QUOTE_OPEN (multiLineStringContent | multiLineStringExpression | MultiLineStringQuote)* TRIPLE_QUOTE_CLOSE - ; - -lineStringContent - : LineStrText - | LineStrEscapedChar - | LineStrRef - ; - -lineStringExpression - : LineStrExprStart NL* expression NL* RCURL - ; - -multiLineStringContent - : MultiLineStrText - | MultiLineStringQuote - | MultiLineStrRef - ; - -multiLineStringExpression - : MultiLineStrExprStart NL* expression NL* RCURL - ; - -lambdaLiteral - : LCURL NL* (lambdaParameters? NL* ARROW NL*)? statements NL* RCURL - ; - -lambdaParameters - : lambdaParameter (NL* COMMA NL* lambdaParameter)* (NL* COMMA)? - ; - -lambdaParameter - : variableDeclaration - | multiVariableDeclaration (NL* COLON NL* type)? - ; - -anonymousFunction - : SUSPEND? - NL* - FUN - (NL* type NL* DOT)? - NL* parametersWithOptionalType - (NL* COLON NL* type)? - (NL* typeConstraints)? - (NL* functionBody)? - ; - -functionLiteral - : lambdaLiteral - | anonymousFunction - ; - -objectLiteral - : DATA? NL* OBJECT (NL* COLON NL* delegationSpecifiers NL*)? (NL* classBody)? - ; - -thisExpression - : THIS - | THIS_AT - ; - -superExpression - : SUPER (LANGLE NL* type NL* RANGLE)? (AT_NO_WS simpleIdentifier)? - | SUPER_AT - ; - -ifExpression - : IF NL* LPAREN NL* expression NL* RPAREN NL* - ( controlStructureBody - | controlStructureBody? NL* SEMICOLON? NL* ELSE NL* (controlStructureBody | SEMICOLON) - | SEMICOLON) - ; - -whenSubject - : LPAREN (annotation* NL* VAL NL* variableDeclaration NL* ASSIGNMENT NL*)? expression RPAREN - ; - -whenExpression - : WHEN NL* whenSubject? NL* LCURL NL* (whenEntry NL*)* NL* RCURL - ; - -whenEntry - : whenCondition (NL* COMMA NL* whenCondition)* (NL* COMMA)? NL* ARROW NL* controlStructureBody semi? - | ELSE NL* ARROW NL* controlStructureBody semi? - ; - -whenCondition - : expression - | rangeTest - | typeTest - ; - -rangeTest - : inOperator NL* expression - ; - -typeTest - : isOperator NL* type - ; - -tryExpression - : TRY NL* block ((NL* catchBlock)+ (NL* finallyBlock)? | NL* finallyBlock) - ; - -catchBlock - : CATCH NL* LPAREN annotation* simpleIdentifier COLON type (NL* COMMA)? RPAREN NL* block - ; - -finallyBlock - : FINALLY NL* block - ; - -jumpExpression - : THROW NL* expression - | (RETURN | RETURN_AT) expression? - | CONTINUE - | CONTINUE_AT - | BREAK - | BREAK_AT - ; - -callableReference - : receiverType? COLONCOLON NL* (simpleIdentifier | CLASS) - ; - -assignmentAndOperator - : ADD_ASSIGNMENT - | SUB_ASSIGNMENT - | MULT_ASSIGNMENT - | DIV_ASSIGNMENT - | MOD_ASSIGNMENT - ; - -equalityOperator - : EXCL_EQ - | EXCL_EQEQ - | EQEQ - | EQEQEQ - ; - -comparisonOperator - : LANGLE - | RANGLE - | LE - | GE - ; - -inOperator - : IN - | NOT_IN - ; - -isOperator - : IS - | NOT_IS - ; - -additiveOperator - : ADD - | SUB - ; - -multiplicativeOperator - : MULT - | DIV - | MOD - ; - -asOperator - : AS - | AS_SAFE - ; - -prefixUnaryOperator - : INCR - | DECR - | SUB - | ADD - | excl - ; - -postfixUnaryOperator - : INCR - | DECR - | EXCL_NO_WS excl - ; - -excl - : EXCL_NO_WS - | EXCL_WS - ; - -memberAccessOperator - : NL* DOT - | NL* safeNav - | COLONCOLON - ; - -safeNav - : QUEST_NO_WS DOT - ; - -// SECTION: modifiers - -modifiers - : (annotation | modifier)+ - ; - -parameterModifiers - : (annotation | parameterModifier)+ - ; - -modifier - : (classModifier - | memberModifier - | visibilityModifier - | functionModifier - | propertyModifier - | inheritanceModifier - | parameterModifier - | platformModifier) NL* - ; - -typeModifiers - : typeModifier+ - ; - -typeModifier - : annotation - | SUSPEND NL* - ; - -classModifier - : ENUM - | SEALED - | ANNOTATION - | DATA - | INNER - | VALUE - ; - -memberModifier - : OVERRIDE - | LATEINIT - ; - -visibilityModifier - : PUBLIC - | PRIVATE - | INTERNAL - | PROTECTED - ; - -varianceModifier - : IN - | OUT - ; - -typeParameterModifiers - : typeParameterModifier+ - ; - -typeParameterModifier - : reificationModifier NL* - | varianceModifier NL* - | annotation - ; - -functionModifier - : TAILREC - | OPERATOR - | INFIX - | INLINE - | EXTERNAL - | SUSPEND - ; - -propertyModifier - : CONST - ; - -inheritanceModifier - : ABSTRACT - | FINAL - | OPEN - ; - -parameterModifier - : VARARG - | NOINLINE - | CROSSINLINE - ; - -reificationModifier - : REIFIED - ; - -platformModifier - : EXPECT - | ACTUAL - ; - -// SECTION: annotations - -annotation - : (singleAnnotation | multiAnnotation) NL* - ; - -singleAnnotation - : (annotationUseSiteTarget NL* | AT_NO_WS | AT_PRE_WS) unescapedAnnotation - ; - -multiAnnotation - : (annotationUseSiteTarget NL* | AT_NO_WS | AT_PRE_WS) LSQUARE unescapedAnnotation+ RSQUARE - ; - -annotationUseSiteTarget - : (AT_NO_WS | AT_PRE_WS) (FIELD | PROPERTY | GET | SET | RECEIVER | PARAM | SETPARAM | DELEGATE) NL* COLON - ; - -unescapedAnnotation - : constructorInvocation - | userType - ; - -// SECTION: identifiers - -simpleIdentifier - : Identifier - | ABSTRACT - | ANNOTATION - | BY - | CATCH - | COMPANION - | CONSTRUCTOR - | CROSSINLINE - | DATA - | DYNAMIC - | ENUM - | EXTERNAL - | FINAL - | FINALLY - | GET - | IMPORT - | INFIX - | INIT - | INLINE - | INNER - | INTERNAL - | LATEINIT - | NOINLINE - | OPEN - | OPERATOR - | OUT - | OVERRIDE - | PRIVATE - | PROTECTED - | PUBLIC - | REIFIED - | SEALED - | TAILREC - | SET - | VARARG - | WHERE - | FIELD - | PROPERTY - | RECEIVER - | PARAM - | SETPARAM - | DELEGATE - | FILE - | EXPECT - | ACTUAL - | CONST - | SUSPEND - | VALUE - ; - -identifier - : simpleIdentifier (NL* DOT simpleIdentifier)* - ; diff --git a/crates/mehen-kotlin-parser/grammar/PROVENANCE.md b/crates/mehen-kotlin-parser/grammar/PROVENANCE.md deleted file mode 100644 index 427318b7..00000000 --- a/crates/mehen-kotlin-parser/grammar/PROVENANCE.md +++ /dev/null @@ -1,60 +0,0 @@ -# Kotlin ANTLR grammar — provenance - -These `.g4` files are the **source of truth** for the Kotlin analyzer's parser. -They are vendored from upstream with one small local patch (see "Local -patches" below); the generated Rust modules in `../src/generated/` are -produced from them by `cargo xtask antlr generate kotlin`. - -## Source - -| Field | Value | -|---|---| -| Upstream | [`Kotlin/kotlin-spec`](https://github.com/Kotlin/kotlin-spec) — the official Kotlin language specification grammar | -| Path | `grammar/src/main/antlr/{KotlinLexer,KotlinParser,UnicodeClasses}.g4` | -| Branch | `release` | -| Commit | `2f7aa0524ec27e788dfacd550f144809f2e0254c` | - -`KotlinLexer.g4` `import`s `UnicodeClasses`, so all three files must stay together. - -## Local patches - -These divergences from upstream are intentional and **must be re-applied if -the grammar is re-vendored**. Each is marked with a `MEHEN LOCAL PATCH` -comment in the `.g4` file. - -- **`KotlinLexer.g4` — `RCURL` mode pop.** Upstream guards the `}` mode pop - with a Java embedded action (`{ if (!_modeStack.isEmpty()) { popMode(); } }`), - which the ANTLR Rust target cannot translate — the generated Rust lexer - never popped the mode, breaking string-template interpolation - (`"x ${foo()} y"`). Replaced with the target-portable `-> popMode` lexer - command (the runtime's `pop_mode()` is a safe no-op on an empty mode stack, - matching the guarded behavior). The grammar's own comment invites this - replacement. - -## Toolchain - -| Tool | Version | -|---|---| -| Rust runtime + codegen | [`ophi-dev/antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime) `v0.29.0` | - -## Regenerating - -Never hand-edit the files in `../src/generated/`. To regenerate after bumping the -grammar or the runtime: - -```bash -cargo xtask antlr generate kotlin -``` - -That command configures `antlr_rust_codegen::Builder` with the equivalent of: - -```rust -Builder::new() - .grammar("KotlinLexer.g4") - .grammar("KotlinParser.g4") - .out_dir("../src/generated") -``` - -The analyzer selects between the generated `kotlinFile` -(`KotlinParser::kotlin_file()`) and `script` (`KotlinParser::script()`) entry -rules, matching the generated parser's entry-rule documentation. diff --git a/crates/mehen-kotlin-parser/grammar/UnicodeClasses.g4 b/crates/mehen-kotlin-parser/grammar/UnicodeClasses.g4 deleted file mode 100644 index 53728480..00000000 --- a/crates/mehen-kotlin-parser/grammar/UnicodeClasses.g4 +++ /dev/null @@ -1,1649 +0,0 @@ -/** - * Kotlin lexical grammar in ANTLR4 notation (Unicode classes) - * - * Taken from http://www.antlr3.org/grammar/1345144569663/AntlrUnicode.txt - */ - -lexer grammar UnicodeClasses; - -UNICODE_CLASS_LL: - '\u0061'..'\u007A' | - '\u00B5' | - '\u00DF'..'\u00F6' | - '\u00F8'..'\u00FF' | - '\u0101' | - '\u0103' | - '\u0105' | - '\u0107' | - '\u0109' | - '\u010B' | - '\u010D' | - '\u010F' | - '\u0111' | - '\u0113' | - '\u0115' | - '\u0117' | - '\u0119' | - '\u011B' | - '\u011D' | - '\u011F' | - '\u0121' | - '\u0123' | - '\u0125' | - '\u0127' | - '\u0129' | - '\u012B' | - '\u012D' | - '\u012F' | - '\u0131' | - '\u0133' | - '\u0135' | - '\u0137' | - '\u0138' | - '\u013A' | - '\u013C' | - '\u013E' | - '\u0140' | - '\u0142' | - '\u0144' | - '\u0146' | - '\u0148' | - '\u0149' | - '\u014B' | - '\u014D' | - '\u014F' | - '\u0151' | - '\u0153' | - '\u0155' | - '\u0157' | - '\u0159' | - '\u015B' | - '\u015D' | - '\u015F' | - '\u0161' | - '\u0163' | - '\u0165' | - '\u0167' | - '\u0169' | - '\u016B' | - '\u016D' | - '\u016F' | - '\u0171' | - '\u0173' | - '\u0175' | - '\u0177' | - '\u017A' | - '\u017C' | - '\u017E'..'\u0180' | - '\u0183' | - '\u0185' | - '\u0188' | - '\u018C' | - '\u018D' | - '\u0192' | - '\u0195' | - '\u0199'..'\u019B' | - '\u019E' | - '\u01A1' | - '\u01A3' | - '\u01A5' | - '\u01A8' | - '\u01AA' | - '\u01AB' | - '\u01AD' | - '\u01B0' | - '\u01B4' | - '\u01B6' | - '\u01B9' | - '\u01BA' | - '\u01BD'..'\u01BF' | - '\u01C6' | - '\u01C9' | - '\u01CC' | - '\u01CE' | - '\u01D0' | - '\u01D2' | - '\u01D4' | - '\u01D6' | - '\u01D8' | - '\u01DA' | - '\u01DC' | - '\u01DD' | - '\u01DF' | - '\u01E1' | - '\u01E3' | - '\u01E5' | - '\u01E7' | - '\u01E9' | - '\u01EB' | - '\u01ED' | - '\u01EF' | - '\u01F0' | - '\u01F3' | - '\u01F5' | - '\u01F9' | - '\u01FB' | - '\u01FD' | - '\u01FF' | - '\u0201' | - '\u0203' | - '\u0205' | - '\u0207' | - '\u0209' | - '\u020B' | - '\u020D' | - '\u020F' | - '\u0211' | - '\u0213' | - '\u0215' | - '\u0217' | - '\u0219' | - '\u021B' | - '\u021D' | - '\u021F' | - '\u0221' | - '\u0223' | - '\u0225' | - '\u0227' | - '\u0229' | - '\u022B' | - '\u022D' | - '\u022F' | - '\u0231' | - '\u0233'..'\u0239' | - '\u023C' | - '\u023F' | - '\u0240' | - '\u0242' | - '\u0247' | - '\u0249' | - '\u024B' | - '\u024D' | - '\u024F'..'\u0293' | - '\u0295'..'\u02AF' | - '\u0371' | - '\u0373' | - '\u0377' | - '\u037B'..'\u037D' | - '\u0390' | - '\u03AC'..'\u03CE' | - '\u03D0' | - '\u03D1' | - '\u03D5'..'\u03D7' | - '\u03D9' | - '\u03DB' | - '\u03DD' | - '\u03DF' | - '\u03E1' | - '\u03E3' | - '\u03E5' | - '\u03E7' | - '\u03E9' | - '\u03EB' | - '\u03ED' | - '\u03EF'..'\u03F3' | - '\u03F5' | - '\u03F8' | - '\u03FB' | - '\u03FC' | - '\u0430'..'\u045F' | - '\u0461' | - '\u0463' | - '\u0465' | - '\u0467' | - '\u0469' | - '\u046B' | - '\u046D' | - '\u046F' | - '\u0471' | - '\u0473' | - '\u0475' | - '\u0477' | - '\u0479' | - '\u047B' | - '\u047D' | - '\u047F' | - '\u0481' | - '\u048B' | - '\u048D' | - '\u048F' | - '\u0491' | - '\u0493' | - '\u0495' | - '\u0497' | - '\u0499' | - '\u049B' | - '\u049D' | - '\u049F' | - '\u04A1' | - '\u04A3' | - '\u04A5' | - '\u04A7' | - '\u04A9' | - '\u04AB' | - '\u04AD' | - '\u04AF' | - '\u04B1' | - '\u04B3' | - '\u04B5' | - '\u04B7' | - '\u04B9' | - '\u04BB' | - '\u04BD' | - '\u04BF' | - '\u04C2' | - '\u04C4' | - '\u04C6' | - '\u04C8' | - '\u04CA' | - '\u04CC' | - '\u04CE' | - '\u04CF' | - '\u04D1' | - '\u04D3' | - '\u04D5' | - '\u04D7' | - '\u04D9' | - '\u04DB' | - '\u04DD' | - '\u04DF' | - '\u04E1' | - '\u04E3' | - '\u04E5' | - '\u04E7' | - '\u04E9' | - '\u04EB' | - '\u04ED' | - '\u04EF' | - '\u04F1' | - '\u04F3' | - '\u04F5' | - '\u04F7' | - '\u04F9' | - '\u04FB' | - '\u04FD' | - '\u04FF' | - '\u0501' | - '\u0503' | - '\u0505' | - '\u0507' | - '\u0509' | - '\u050B' | - '\u050D' | - '\u050F' | - '\u0511' | - '\u0513' | - '\u0515' | - '\u0517' | - '\u0519' | - '\u051B' | - '\u051D' | - '\u051F' | - '\u0521' | - '\u0523' | - '\u0525' | - '\u0527' | - '\u0561'..'\u0587' | - '\u1D00'..'\u1D2B' | - '\u1D6B'..'\u1D77' | - '\u1D79'..'\u1D9A' | - '\u1E01' | - '\u1E03' | - '\u1E05' | - '\u1E07' | - '\u1E09' | - '\u1E0B' | - '\u1E0D' | - '\u1E0F' | - '\u1E11' | - '\u1E13' | - '\u1E15' | - '\u1E17' | - '\u1E19' | - '\u1E1B' | - '\u1E1D' | - '\u1E1F' | - '\u1E21' | - '\u1E23' | - '\u1E25' | - '\u1E27' | - '\u1E29' | - '\u1E2B' | - '\u1E2D' | - '\u1E2F' | - '\u1E31' | - '\u1E33' | - '\u1E35' | - '\u1E37' | - '\u1E39' | - '\u1E3B' | - '\u1E3D' | - '\u1E3F' | - '\u1E41' | - '\u1E43' | - '\u1E45' | - '\u1E47' | - '\u1E49' | - '\u1E4B' | - '\u1E4D' | - '\u1E4F' | - '\u1E51' | - '\u1E53' | - '\u1E55' | - '\u1E57' | - '\u1E59' | - '\u1E5B' | - '\u1E5D' | - '\u1E5F' | - '\u1E61' | - '\u1E63' | - '\u1E65' | - '\u1E67' | - '\u1E69' | - '\u1E6B' | - '\u1E6D' | - '\u1E6F' | - '\u1E71' | - '\u1E73' | - '\u1E75' | - '\u1E77' | - '\u1E79' | - '\u1E7B' | - '\u1E7D' | - '\u1E7F' | - '\u1E81' | - '\u1E83' | - '\u1E85' | - '\u1E87' | - '\u1E89' | - '\u1E8B' | - '\u1E8D' | - '\u1E8F' | - '\u1E91' | - '\u1E93' | - '\u1E95'..'\u1E9D' | - '\u1E9F' | - '\u1EA1' | - '\u1EA3' | - '\u1EA5' | - '\u1EA7' | - '\u1EA9' | - '\u1EAB' | - '\u1EAD' | - '\u1EAF' | - '\u1EB1' | - '\u1EB3' | - '\u1EB5' | - '\u1EB7' | - '\u1EB9' | - '\u1EBB' | - '\u1EBD' | - '\u1EBF' | - '\u1EC1' | - '\u1EC3' | - '\u1EC5' | - '\u1EC7' | - '\u1EC9' | - '\u1ECB' | - '\u1ECD' | - '\u1ECF' | - '\u1ED1' | - '\u1ED3' | - '\u1ED5' | - '\u1ED7' | - '\u1ED9' | - '\u1EDB' | - '\u1EDD' | - '\u1EDF' | - '\u1EE1' | - '\u1EE3' | - '\u1EE5' | - '\u1EE7' | - '\u1EE9' | - '\u1EEB' | - '\u1EED' | - '\u1EEF' | - '\u1EF1' | - '\u1EF3' | - '\u1EF5' | - '\u1EF7' | - '\u1EF9' | - '\u1EFB' | - '\u1EFD' | - '\u1EFF'..'\u1F07' | - '\u1F10'..'\u1F15' | - '\u1F20'..'\u1F27' | - '\u1F30'..'\u1F37' | - '\u1F40'..'\u1F45' | - '\u1F50'..'\u1F57' | - '\u1F60'..'\u1F67' | - '\u1F70'..'\u1F7D' | - '\u1F80'..'\u1F87' | - '\u1F90'..'\u1F97' | - '\u1FA0'..'\u1FA7' | - '\u1FB0'..'\u1FB4' | - '\u1FB6' | - '\u1FB7' | - '\u1FBE' | - '\u1FC2'..'\u1FC4' | - '\u1FC6' | - '\u1FC7' | - '\u1FD0'..'\u1FD3' | - '\u1FD6' | - '\u1FD7' | - '\u1FE0'..'\u1FE7' | - '\u1FF2'..'\u1FF4' | - '\u1FF6' | - '\u1FF7' | - '\u210A' | - '\u210E' | - '\u210F' | - '\u2113' | - '\u212F' | - '\u2134' | - '\u2139' | - '\u213C' | - '\u213D' | - '\u2146'..'\u2149' | - '\u214E' | - '\u2184' | - '\u2C30'..'\u2C5E' | - '\u2C61' | - '\u2C65' | - '\u2C66' | - '\u2C68' | - '\u2C6A' | - '\u2C6C' | - '\u2C71' | - '\u2C73' | - '\u2C74' | - '\u2C76'..'\u2C7B' | - '\u2C81' | - '\u2C83' | - '\u2C85' | - '\u2C87' | - '\u2C89' | - '\u2C8B' | - '\u2C8D' | - '\u2C8F' | - '\u2C91' | - '\u2C93' | - '\u2C95' | - '\u2C97' | - '\u2C99' | - '\u2C9B' | - '\u2C9D' | - '\u2C9F' | - '\u2CA1' | - '\u2CA3' | - '\u2CA5' | - '\u2CA7' | - '\u2CA9' | - '\u2CAB' | - '\u2CAD' | - '\u2CAF' | - '\u2CB1' | - '\u2CB3' | - '\u2CB5' | - '\u2CB7' | - '\u2CB9' | - '\u2CBB' | - '\u2CBD' | - '\u2CBF' | - '\u2CC1' | - '\u2CC3' | - '\u2CC5' | - '\u2CC7' | - '\u2CC9' | - '\u2CCB' | - '\u2CCD' | - '\u2CCF' | - '\u2CD1' | - '\u2CD3' | - '\u2CD5' | - '\u2CD7' | - '\u2CD9' | - '\u2CDB' | - '\u2CDD' | - '\u2CDF' | - '\u2CE1' | - '\u2CE3' | - '\u2CE4' | - '\u2CEC' | - '\u2CEE' | - '\u2CF3' | - '\u2D00'..'\u2D25' | - '\u2D27' | - '\u2D2D' | - '\uA641' | - '\uA643' | - '\uA645' | - '\uA647' | - '\uA649' | - '\uA64B' | - '\uA64D' | - '\uA64F' | - '\uA651' | - '\uA653' | - '\uA655' | - '\uA657' | - '\uA659' | - '\uA65B' | - '\uA65D' | - '\uA65F' | - '\uA661' | - '\uA663' | - '\uA665' | - '\uA667' | - '\uA669' | - '\uA66B' | - '\uA66D' | - '\uA681' | - '\uA683' | - '\uA685' | - '\uA687' | - '\uA689' | - '\uA68B' | - '\uA68D' | - '\uA68F' | - '\uA691' | - '\uA693' | - '\uA695' | - '\uA697' | - '\uA723' | - '\uA725' | - '\uA727' | - '\uA729' | - '\uA72B' | - '\uA72D' | - '\uA72F'..'\uA731' | - '\uA733' | - '\uA735' | - '\uA737' | - '\uA739' | - '\uA73B' | - '\uA73D' | - '\uA73F' | - '\uA741' | - '\uA743' | - '\uA745' | - '\uA747' | - '\uA749' | - '\uA74B' | - '\uA74D' | - '\uA74F' | - '\uA751' | - '\uA753' | - '\uA755' | - '\uA757' | - '\uA759' | - '\uA75B' | - '\uA75D' | - '\uA75F' | - '\uA761' | - '\uA763' | - '\uA765' | - '\uA767' | - '\uA769' | - '\uA76B' | - '\uA76D' | - '\uA76F' | - '\uA771'..'\uA778' | - '\uA77A' | - '\uA77C' | - '\uA77F' | - '\uA781' | - '\uA783' | - '\uA785' | - '\uA787' | - '\uA78C' | - '\uA78E' | - '\uA791' | - '\uA793' | - '\uA7A1' | - '\uA7A3' | - '\uA7A5' | - '\uA7A7' | - '\uA7A9' | - '\uA7FA' | - '\uFB00'..'\uFB06' | - '\uFB13'..'\uFB17' | - '\uFF41'..'\uFF5A'; - -UNICODE_CLASS_LM: - '\u02B0'..'\u02C1' | - '\u02C6'..'\u02D1' | - '\u02E0'..'\u02E4' | - '\u02EC' | - '\u02EE' | - '\u0374' | - '\u037A' | - '\u0559' | - '\u0640' | - '\u06E5' | - '\u06E6' | - '\u07F4' | - '\u07F5' | - '\u07FA' | - '\u081A' | - '\u0824' | - '\u0828' | - '\u0971' | - '\u0E46' | - '\u0EC6' | - '\u10FC' | - '\u17D7' | - '\u1843' | - '\u1AA7' | - '\u1C78'..'\u1C7D' | - '\u1D2C'..'\u1D6A' | - '\u1D78' | - '\u1D9B'..'\u1DBF' | - '\u2071' | - '\u207F' | - '\u2090'..'\u209C' | - '\u2C7C' | - '\u2C7D' | - '\u2D6F' | - '\u2E2F' | - '\u3005' | - '\u3031'..'\u3035' | - '\u303B' | - '\u309D' | - '\u309E' | - '\u30FC'..'\u30FE' | - '\uA015' | - '\uA4F8'..'\uA4FD' | - '\uA60C' | - '\uA67F' | - '\uA717'..'\uA71F' | - '\uA770' | - '\uA788' | - '\uA7F8' | - '\uA7F9' | - '\uA9CF' | - '\uAA70' | - '\uAADD' | - '\uAAF3' | - '\uAAF4' | - '\uFF70' | - '\uFF9E' | - '\uFF9F'; - -UNICODE_CLASS_LO: - '\u00AA' | - '\u00BA' | - '\u01BB' | - '\u01C0'..'\u01C3' | - '\u0294' | - '\u05D0'..'\u05EA' | - '\u05F0'..'\u05F2' | - '\u0620'..'\u063F' | - '\u0641'..'\u064A' | - '\u066E' | - '\u066F' | - '\u0671'..'\u06D3' | - '\u06D5' | - '\u06EE' | - '\u06EF' | - '\u06FA'..'\u06FC' | - '\u06FF' | - '\u0710' | - '\u0712'..'\u072F' | - '\u074D'..'\u07A5' | - '\u07B1' | - '\u07CA'..'\u07EA' | - '\u0800'..'\u0815' | - '\u0840'..'\u0858' | - '\u08A0' | - '\u08A2'..'\u08AC' | - '\u0904'..'\u0939' | - '\u093D' | - '\u0950' | - '\u0958'..'\u0961' | - '\u0972'..'\u0977' | - '\u0979'..'\u097F' | - '\u0985'..'\u098C' | - '\u098F' | - '\u0990' | - '\u0993'..'\u09A8' | - '\u09AA'..'\u09B0' | - '\u09B2' | - '\u09B6'..'\u09B9' | - '\u09BD' | - '\u09CE' | - '\u09DC' | - '\u09DD' | - '\u09DF'..'\u09E1' | - '\u09F0' | - '\u09F1' | - '\u0A05'..'\u0A0A' | - '\u0A0F' | - '\u0A10' | - '\u0A13'..'\u0A28' | - '\u0A2A'..'\u0A30' | - '\u0A32' | - '\u0A33' | - '\u0A35' | - '\u0A36' | - '\u0A38' | - '\u0A39' | - '\u0A59'..'\u0A5C' | - '\u0A5E' | - '\u0A72'..'\u0A74' | - '\u0A85'..'\u0A8D' | - '\u0A8F'..'\u0A91' | - '\u0A93'..'\u0AA8' | - '\u0AAA'..'\u0AB0' | - '\u0AB2' | - '\u0AB3' | - '\u0AB5'..'\u0AB9' | - '\u0ABD' | - '\u0AD0' | - '\u0AE0' | - '\u0AE1' | - '\u0B05'..'\u0B0C' | - '\u0B0F' | - '\u0B10' | - '\u0B13'..'\u0B28' | - '\u0B2A'..'\u0B30' | - '\u0B32' | - '\u0B33' | - '\u0B35'..'\u0B39' | - '\u0B3D' | - '\u0B5C' | - '\u0B5D' | - '\u0B5F'..'\u0B61' | - '\u0B71' | - '\u0B83' | - '\u0B85'..'\u0B8A' | - '\u0B8E'..'\u0B90' | - '\u0B92'..'\u0B95' | - '\u0B99' | - '\u0B9A' | - '\u0B9C' | - '\u0B9E' | - '\u0B9F' | - '\u0BA3' | - '\u0BA4' | - '\u0BA8'..'\u0BAA' | - '\u0BAE'..'\u0BB9' | - '\u0BD0' | - '\u0C05'..'\u0C0C' | - '\u0C0E'..'\u0C10' | - '\u0C12'..'\u0C28' | - '\u0C2A'..'\u0C33' | - '\u0C35'..'\u0C39' | - '\u0C3D' | - '\u0C58' | - '\u0C59' | - '\u0C60' | - '\u0C61' | - '\u0C85'..'\u0C8C' | - '\u0C8E'..'\u0C90' | - '\u0C92'..'\u0CA8' | - '\u0CAA'..'\u0CB3' | - '\u0CB5'..'\u0CB9' | - '\u0CBD' | - '\u0CDE' | - '\u0CE0' | - '\u0CE1' | - '\u0CF1' | - '\u0CF2' | - '\u0D05'..'\u0D0C' | - '\u0D0E'..'\u0D10' | - '\u0D12'..'\u0D3A' | - '\u0D3D' | - '\u0D4E' | - '\u0D60' | - '\u0D61' | - '\u0D7A'..'\u0D7F' | - '\u0D85'..'\u0D96' | - '\u0D9A'..'\u0DB1' | - '\u0DB3'..'\u0DBB' | - '\u0DBD' | - '\u0DC0'..'\u0DC6' | - '\u0E01'..'\u0E30' | - '\u0E32' | - '\u0E33' | - '\u0E40'..'\u0E45' | - '\u0E81' | - '\u0E82' | - '\u0E84' | - '\u0E87' | - '\u0E88' | - '\u0E8A' | - '\u0E8D' | - '\u0E94'..'\u0E97' | - '\u0E99'..'\u0E9F' | - '\u0EA1'..'\u0EA3' | - '\u0EA5' | - '\u0EA7' | - '\u0EAA' | - '\u0EAB' | - '\u0EAD'..'\u0EB0' | - '\u0EB2' | - '\u0EB3' | - '\u0EBD' | - '\u0EC0'..'\u0EC4' | - '\u0EDC'..'\u0EDF' | - '\u0F00' | - '\u0F40'..'\u0F47' | - '\u0F49'..'\u0F6C' | - '\u0F88'..'\u0F8C' | - '\u1000'..'\u102A' | - '\u103F' | - '\u1050'..'\u1055' | - '\u105A'..'\u105D' | - '\u1061' | - '\u1065' | - '\u1066' | - '\u106E'..'\u1070' | - '\u1075'..'\u1081' | - '\u108E' | - '\u10D0'..'\u10FA' | - '\u10FD'..'\u1248' | - '\u124A'..'\u124D' | - '\u1250'..'\u1256' | - '\u1258' | - '\u125A'..'\u125D' | - '\u1260'..'\u1288' | - '\u128A'..'\u128D' | - '\u1290'..'\u12B0' | - '\u12B2'..'\u12B5' | - '\u12B8'..'\u12BE' | - '\u12C0' | - '\u12C2'..'\u12C5' | - '\u12C8'..'\u12D6' | - '\u12D8'..'\u1310' | - '\u1312'..'\u1315' | - '\u1318'..'\u135A' | - '\u1380'..'\u138F' | - '\u13A0'..'\u13F4' | - '\u1401'..'\u166C' | - '\u166F'..'\u167F' | - '\u1681'..'\u169A' | - '\u16A0'..'\u16EA' | - '\u1700'..'\u170C' | - '\u170E'..'\u1711' | - '\u1720'..'\u1731' | - '\u1740'..'\u1751' | - '\u1760'..'\u176C' | - '\u176E'..'\u1770' | - '\u1780'..'\u17B3' | - '\u17DC' | - '\u1820'..'\u1842' | - '\u1844'..'\u1877' | - '\u1880'..'\u18A8' | - '\u18AA' | - '\u18B0'..'\u18F5' | - '\u1900'..'\u191C' | - '\u1950'..'\u196D' | - '\u1970'..'\u1974' | - '\u1980'..'\u19AB' | - '\u19C1'..'\u19C7' | - '\u1A00'..'\u1A16' | - '\u1A20'..'\u1A54' | - '\u1B05'..'\u1B33' | - '\u1B45'..'\u1B4B' | - '\u1B83'..'\u1BA0' | - '\u1BAE' | - '\u1BAF' | - '\u1BBA'..'\u1BE5' | - '\u1C00'..'\u1C23' | - '\u1C4D'..'\u1C4F' | - '\u1C5A'..'\u1C77' | - '\u1CE9'..'\u1CEC' | - '\u1CEE'..'\u1CF1' | - '\u1CF5' | - '\u1CF6' | - '\u2135'..'\u2138' | - '\u2D30'..'\u2D67' | - '\u2D80'..'\u2D96' | - '\u2DA0'..'\u2DA6' | - '\u2DA8'..'\u2DAE' | - '\u2DB0'..'\u2DB6' | - '\u2DB8'..'\u2DBE' | - '\u2DC0'..'\u2DC6' | - '\u2DC8'..'\u2DCE' | - '\u2DD0'..'\u2DD6' | - '\u2DD8'..'\u2DDE' | - '\u3006' | - '\u303C' | - '\u3041'..'\u3096' | - '\u309F' | - '\u30A1'..'\u30FA' | - '\u30FF' | - '\u3105'..'\u312D' | - '\u3131'..'\u318E' | - '\u31A0'..'\u31BA' | - '\u31F0'..'\u31FF' | - '\u3400' | - '\u4DB5' | - '\u4E00' | - '\u9FCC' | - '\uA000'..'\uA014' | - '\uA016'..'\uA48C' | - '\uA4D0'..'\uA4F7' | - '\uA500'..'\uA60B' | - '\uA610'..'\uA61F' | - '\uA62A' | - '\uA62B' | - '\uA66E' | - '\uA6A0'..'\uA6E5' | - '\uA7FB'..'\uA801' | - '\uA803'..'\uA805' | - '\uA807'..'\uA80A' | - '\uA80C'..'\uA822' | - '\uA840'..'\uA873' | - '\uA882'..'\uA8B3' | - '\uA8F2'..'\uA8F7' | - '\uA8FB' | - '\uA90A'..'\uA925' | - '\uA930'..'\uA946' | - '\uA960'..'\uA97C' | - '\uA984'..'\uA9B2' | - '\uAA00'..'\uAA28' | - '\uAA40'..'\uAA42' | - '\uAA44'..'\uAA4B' | - '\uAA60'..'\uAA6F' | - '\uAA71'..'\uAA76' | - '\uAA7A' | - '\uAA80'..'\uAAAF' | - '\uAAB1' | - '\uAAB5' | - '\uAAB6' | - '\uAAB9'..'\uAABD' | - '\uAAC0' | - '\uAAC2' | - '\uAADB' | - '\uAADC' | - '\uAAE0'..'\uAAEA' | - '\uAAF2' | - '\uAB01'..'\uAB06' | - '\uAB09'..'\uAB0E' | - '\uAB11'..'\uAB16' | - '\uAB20'..'\uAB26' | - '\uAB28'..'\uAB2E' | - '\uABC0'..'\uABE2' | - '\uAC00' | - '\uD7A3' | - '\uD7B0'..'\uD7C6' | - '\uD7CB'..'\uD7FB' | - '\uF900'..'\uFA6D' | - '\uFA70'..'\uFAD9' | - '\uFB1D' | - '\uFB1F'..'\uFB28' | - '\uFB2A'..'\uFB36' | - '\uFB38'..'\uFB3C' | - '\uFB3E' | - '\uFB40' | - '\uFB41' | - '\uFB43' | - '\uFB44' | - '\uFB46'..'\uFBB1' | - '\uFBD3'..'\uFD3D' | - '\uFD50'..'\uFD8F' | - '\uFD92'..'\uFDC7' | - '\uFDF0'..'\uFDFB' | - '\uFE70'..'\uFE74' | - '\uFE76'..'\uFEFC' | - '\uFF66'..'\uFF6F' | - '\uFF71'..'\uFF9D' | - '\uFFA0'..'\uFFBE' | - '\uFFC2'..'\uFFC7' | - '\uFFCA'..'\uFFCF' | - '\uFFD2'..'\uFFD7' | - '\uFFDA'..'\uFFDC'; - -UNICODE_CLASS_LT: - '\u01C5' | - '\u01C8' | - '\u01CB' | - '\u01F2' | - '\u1F88'..'\u1F8F' | - '\u1F98'..'\u1F9F' | - '\u1FA8'..'\u1FAF' | - '\u1FBC' | - '\u1FCC' | - '\u1FFC'; - -UNICODE_CLASS_LU: - '\u0041'..'\u005A' | - '\u00C0'..'\u00D6' | - '\u00D8'..'\u00DE' | - '\u0100' | - '\u0102' | - '\u0104' | - '\u0106' | - '\u0108' | - '\u010A' | - '\u010C' | - '\u010E' | - '\u0110' | - '\u0112' | - '\u0114' | - '\u0116' | - '\u0118' | - '\u011A' | - '\u011C' | - '\u011E' | - '\u0120' | - '\u0122' | - '\u0124' | - '\u0126' | - '\u0128' | - '\u012A' | - '\u012C' | - '\u012E' | - '\u0130' | - '\u0132' | - '\u0134' | - '\u0136' | - '\u0139' | - '\u013B' | - '\u013D' | - '\u013F' | - '\u0141' | - '\u0143' | - '\u0145' | - '\u0147' | - '\u014A' | - '\u014C' | - '\u014E' | - '\u0150' | - '\u0152' | - '\u0154' | - '\u0156' | - '\u0158' | - '\u015A' | - '\u015C' | - '\u015E' | - '\u0160' | - '\u0162' | - '\u0164' | - '\u0166' | - '\u0168' | - '\u016A' | - '\u016C' | - '\u016E' | - '\u0170' | - '\u0172' | - '\u0174' | - '\u0176' | - '\u0178' | - '\u0179' | - '\u017B' | - '\u017D' | - '\u0181' | - '\u0182' | - '\u0184' | - '\u0186' | - '\u0187' | - '\u0189'..'\u018B' | - '\u018E'..'\u0191' | - '\u0193' | - '\u0194' | - '\u0196'..'\u0198' | - '\u019C' | - '\u019D' | - '\u019F' | - '\u01A0' | - '\u01A2' | - '\u01A4' | - '\u01A6' | - '\u01A7' | - '\u01A9' | - '\u01AC' | - '\u01AE' | - '\u01AF' | - '\u01B1'..'\u01B3' | - '\u01B5' | - '\u01B7' | - '\u01B8' | - '\u01BC' | - '\u01C4' | - '\u01C7' | - '\u01CA' | - '\u01CD' | - '\u01CF' | - '\u01D1' | - '\u01D3' | - '\u01D5' | - '\u01D7' | - '\u01D9' | - '\u01DB' | - '\u01DE' | - '\u01E0' | - '\u01E2' | - '\u01E4' | - '\u01E6' | - '\u01E8' | - '\u01EA' | - '\u01EC' | - '\u01EE' | - '\u01F1' | - '\u01F4' | - '\u01F6'..'\u01F8' | - '\u01FA' | - '\u01FC' | - '\u01FE' | - '\u0200' | - '\u0202' | - '\u0204' | - '\u0206' | - '\u0208' | - '\u020A' | - '\u020C' | - '\u020E' | - '\u0210' | - '\u0212' | - '\u0214' | - '\u0216' | - '\u0218' | - '\u021A' | - '\u021C' | - '\u021E' | - '\u0220' | - '\u0222' | - '\u0224' | - '\u0226' | - '\u0228' | - '\u022A' | - '\u022C' | - '\u022E' | - '\u0230' | - '\u0232' | - '\u023A' | - '\u023B' | - '\u023D' | - '\u023E' | - '\u0241' | - '\u0243'..'\u0246' | - '\u0248' | - '\u024A' | - '\u024C' | - '\u024E' | - '\u0370' | - '\u0372' | - '\u0376' | - '\u0386' | - '\u0388'..'\u038A' | - '\u038C' | - '\u038E' | - '\u038F' | - '\u0391'..'\u03A1' | - '\u03A3'..'\u03AB' | - '\u03CF' | - '\u03D2'..'\u03D4' | - '\u03D8' | - '\u03DA' | - '\u03DC' | - '\u03DE' | - '\u03E0' | - '\u03E2' | - '\u03E4' | - '\u03E6' | - '\u03E8' | - '\u03EA' | - '\u03EC' | - '\u03EE' | - '\u03F4' | - '\u03F7' | - '\u03F9' | - '\u03FA' | - '\u03FD'..'\u042F' | - '\u0460' | - '\u0462' | - '\u0464' | - '\u0466' | - '\u0468' | - '\u046A' | - '\u046C' | - '\u046E' | - '\u0470' | - '\u0472' | - '\u0474' | - '\u0476' | - '\u0478' | - '\u047A' | - '\u047C' | - '\u047E' | - '\u0480' | - '\u048A' | - '\u048C' | - '\u048E' | - '\u0490' | - '\u0492' | - '\u0494' | - '\u0496' | - '\u0498' | - '\u049A' | - '\u049C' | - '\u049E' | - '\u04A0' | - '\u04A2' | - '\u04A4' | - '\u04A6' | - '\u04A8' | - '\u04AA' | - '\u04AC' | - '\u04AE' | - '\u04B0' | - '\u04B2' | - '\u04B4' | - '\u04B6' | - '\u04B8' | - '\u04BA' | - '\u04BC' | - '\u04BE' | - '\u04C0' | - '\u04C1' | - '\u04C3' | - '\u04C5' | - '\u04C7' | - '\u04C9' | - '\u04CB' | - '\u04CD' | - '\u04D0' | - '\u04D2' | - '\u04D4' | - '\u04D6' | - '\u04D8' | - '\u04DA' | - '\u04DC' | - '\u04DE' | - '\u04E0' | - '\u04E2' | - '\u04E4' | - '\u04E6' | - '\u04E8' | - '\u04EA' | - '\u04EC' | - '\u04EE' | - '\u04F0' | - '\u04F2' | - '\u04F4' | - '\u04F6' | - '\u04F8' | - '\u04FA' | - '\u04FC' | - '\u04FE' | - '\u0500' | - '\u0502' | - '\u0504' | - '\u0506' | - '\u0508' | - '\u050A' | - '\u050C' | - '\u050E' | - '\u0510' | - '\u0512' | - '\u0514' | - '\u0516' | - '\u0518' | - '\u051A' | - '\u051C' | - '\u051E' | - '\u0520' | - '\u0522' | - '\u0524' | - '\u0526' | - '\u0531'..'\u0556' | - '\u10A0'..'\u10C5' | - '\u10C7' | - '\u10CD' | - '\u1E00' | - '\u1E02' | - '\u1E04' | - '\u1E06' | - '\u1E08' | - '\u1E0A' | - '\u1E0C' | - '\u1E0E' | - '\u1E10' | - '\u1E12' | - '\u1E14' | - '\u1E16' | - '\u1E18' | - '\u1E1A' | - '\u1E1C' | - '\u1E1E' | - '\u1E20' | - '\u1E22' | - '\u1E24' | - '\u1E26' | - '\u1E28' | - '\u1E2A' | - '\u1E2C' | - '\u1E2E' | - '\u1E30' | - '\u1E32' | - '\u1E34' | - '\u1E36' | - '\u1E38' | - '\u1E3A' | - '\u1E3C' | - '\u1E3E' | - '\u1E40' | - '\u1E42' | - '\u1E44' | - '\u1E46' | - '\u1E48' | - '\u1E4A' | - '\u1E4C' | - '\u1E4E' | - '\u1E50' | - '\u1E52' | - '\u1E54' | - '\u1E56' | - '\u1E58' | - '\u1E5A' | - '\u1E5C' | - '\u1E5E' | - '\u1E60' | - '\u1E62' | - '\u1E64' | - '\u1E66' | - '\u1E68' | - '\u1E6A' | - '\u1E6C' | - '\u1E6E' | - '\u1E70' | - '\u1E72' | - '\u1E74' | - '\u1E76' | - '\u1E78' | - '\u1E7A' | - '\u1E7C' | - '\u1E7E' | - '\u1E80' | - '\u1E82' | - '\u1E84' | - '\u1E86' | - '\u1E88' | - '\u1E8A' | - '\u1E8C' | - '\u1E8E' | - '\u1E90' | - '\u1E92' | - '\u1E94' | - '\u1E9E' | - '\u1EA0' | - '\u1EA2' | - '\u1EA4' | - '\u1EA6' | - '\u1EA8' | - '\u1EAA' | - '\u1EAC' | - '\u1EAE' | - '\u1EB0' | - '\u1EB2' | - '\u1EB4' | - '\u1EB6' | - '\u1EB8' | - '\u1EBA' | - '\u1EBC' | - '\u1EBE' | - '\u1EC0' | - '\u1EC2' | - '\u1EC4' | - '\u1EC6' | - '\u1EC8' | - '\u1ECA' | - '\u1ECC' | - '\u1ECE' | - '\u1ED0' | - '\u1ED2' | - '\u1ED4' | - '\u1ED6' | - '\u1ED8' | - '\u1EDA' | - '\u1EDC' | - '\u1EDE' | - '\u1EE0' | - '\u1EE2' | - '\u1EE4' | - '\u1EE6' | - '\u1EE8' | - '\u1EEA' | - '\u1EEC' | - '\u1EEE' | - '\u1EF0' | - '\u1EF2' | - '\u1EF4' | - '\u1EF6' | - '\u1EF8' | - '\u1EFA' | - '\u1EFC' | - '\u1EFE' | - '\u1F08'..'\u1F0F' | - '\u1F18'..'\u1F1D' | - '\u1F28'..'\u1F2F' | - '\u1F38'..'\u1F3F' | - '\u1F48'..'\u1F4D' | - '\u1F59' | - '\u1F5B' | - '\u1F5D' | - '\u1F5F' | - '\u1F68'..'\u1F6F' | - '\u1FB8'..'\u1FBB' | - '\u1FC8'..'\u1FCB' | - '\u1FD8'..'\u1FDB' | - '\u1FE8'..'\u1FEC' | - '\u1FF8'..'\u1FFB' | - '\u2102' | - '\u2107' | - '\u210B'..'\u210D' | - '\u2110'..'\u2112' | - '\u2115' | - '\u2119'..'\u211D' | - '\u2124' | - '\u2126' | - '\u2128' | - '\u212A'..'\u212D' | - '\u2130'..'\u2133' | - '\u213E' | - '\u213F' | - '\u2145' | - '\u2183' | - '\u2C00'..'\u2C2E' | - '\u2C60' | - '\u2C62'..'\u2C64' | - '\u2C67' | - '\u2C69' | - '\u2C6B' | - '\u2C6D'..'\u2C70' | - '\u2C72' | - '\u2C75' | - '\u2C7E'..'\u2C80' | - '\u2C82' | - '\u2C84' | - '\u2C86' | - '\u2C88' | - '\u2C8A' | - '\u2C8C' | - '\u2C8E' | - '\u2C90' | - '\u2C92' | - '\u2C94' | - '\u2C96' | - '\u2C98' | - '\u2C9A' | - '\u2C9C' | - '\u2C9E' | - '\u2CA0' | - '\u2CA2' | - '\u2CA4' | - '\u2CA6' | - '\u2CA8' | - '\u2CAA' | - '\u2CAC' | - '\u2CAE' | - '\u2CB0' | - '\u2CB2' | - '\u2CB4' | - '\u2CB6' | - '\u2CB8' | - '\u2CBA' | - '\u2CBC' | - '\u2CBE' | - '\u2CC0' | - '\u2CC2' | - '\u2CC4' | - '\u2CC6' | - '\u2CC8' | - '\u2CCA' | - '\u2CCC' | - '\u2CCE' | - '\u2CD0' | - '\u2CD2' | - '\u2CD4' | - '\u2CD6' | - '\u2CD8' | - '\u2CDA' | - '\u2CDC' | - '\u2CDE' | - '\u2CE0' | - '\u2CE2' | - '\u2CEB' | - '\u2CED' | - '\u2CF2' | - '\uA640' | - '\uA642' | - '\uA644' | - '\uA646' | - '\uA648' | - '\uA64A' | - '\uA64C' | - '\uA64E' | - '\uA650' | - '\uA652' | - '\uA654' | - '\uA656' | - '\uA658' | - '\uA65A' | - '\uA65C' | - '\uA65E' | - '\uA660' | - '\uA662' | - '\uA664' | - '\uA666' | - '\uA668' | - '\uA66A' | - '\uA66C' | - '\uA680' | - '\uA682' | - '\uA684' | - '\uA686' | - '\uA688' | - '\uA68A' | - '\uA68C' | - '\uA68E' | - '\uA690' | - '\uA692' | - '\uA694' | - '\uA696' | - '\uA722' | - '\uA724' | - '\uA726' | - '\uA728' | - '\uA72A' | - '\uA72C' | - '\uA72E' | - '\uA732' | - '\uA734' | - '\uA736' | - '\uA738' | - '\uA73A' | - '\uA73C' | - '\uA73E' | - '\uA740' | - '\uA742' | - '\uA744' | - '\uA746' | - '\uA748' | - '\uA74A' | - '\uA74C' | - '\uA74E' | - '\uA750' | - '\uA752' | - '\uA754' | - '\uA756' | - '\uA758' | - '\uA75A' | - '\uA75C' | - '\uA75E' | - '\uA760' | - '\uA762' | - '\uA764' | - '\uA766' | - '\uA768' | - '\uA76A' | - '\uA76C' | - '\uA76E' | - '\uA779' | - '\uA77B' | - '\uA77D' | - '\uA77E' | - '\uA780' | - '\uA782' | - '\uA784' | - '\uA786' | - '\uA78B' | - '\uA78D' | - '\uA790' | - '\uA792' | - '\uA7A0' | - '\uA7A2' | - '\uA7A4' | - '\uA7A6' | - '\uA7A8' | - '\uA7AA' | - '\uFF21'..'\uFF3A'; - -UNICODE_CLASS_ND: - '\u0030'..'\u0039' | - '\u0660'..'\u0669' | - '\u06F0'..'\u06F9' | - '\u07C0'..'\u07C9' | - '\u0966'..'\u096F' | - '\u09E6'..'\u09EF' | - '\u0A66'..'\u0A6F' | - '\u0AE6'..'\u0AEF' | - '\u0B66'..'\u0B6F' | - '\u0BE6'..'\u0BEF' | - '\u0C66'..'\u0C6F' | - '\u0CE6'..'\u0CEF' | - '\u0D66'..'\u0D6F' | - '\u0E50'..'\u0E59' | - '\u0ED0'..'\u0ED9' | - '\u0F20'..'\u0F29' | - '\u1040'..'\u1049' | - '\u1090'..'\u1099' | - '\u17E0'..'\u17E9' | - '\u1810'..'\u1819' | - '\u1946'..'\u194F' | - '\u19D0'..'\u19D9' | - '\u1A80'..'\u1A89' | - '\u1A90'..'\u1A99' | - '\u1B50'..'\u1B59' | - '\u1BB0'..'\u1BB9' | - '\u1C40'..'\u1C49' | - '\u1C50'..'\u1C59' | - '\uA620'..'\uA629' | - '\uA8D0'..'\uA8D9' | - '\uA900'..'\uA909' | - '\uA9D0'..'\uA9D9' | - '\uAA50'..'\uAA59' | - '\uABF0'..'\uABF9' | - '\uFF10'..'\uFF19'; - -UNICODE_CLASS_NL: - '\u16EE'..'\u16F0' | - '\u2160'..'\u2182' | - '\u2185'..'\u2188' | - '\u3007' | - '\u3021'..'\u3029' | - '\u3038'..'\u303A' | - '\uA6E6'..'\uA6EF'; \ No newline at end of file diff --git a/crates/mehen-kotlin-parser/src/generated/README.md b/crates/mehen-kotlin-parser/src/generated/README.md deleted file mode 100644 index e90b9cdd..00000000 --- a/crates/mehen-kotlin-parser/src/generated/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Generated ANTLR modules — DO NOT EDIT - -`kotlin_lexer.rs`, `kotlin_parser.rs`, `decisions.json`, and `semantics.json` -are generated from the vendored grammar in `../../grammar/` by -`cargo xtask antlr generate kotlin`. They are checked in (like the tree-sitter -`grammar.rs` kind enums), so a normal `cargo build` uses them without compiling -xtask's `antlr-rust-codegen` dependency. All four artifacts are drift-checked by -`cargo xtask antlr check-generated`. - -Regenerate — never hand-edit — via `cargo xtask antlr generate kotlin`. See -`../../grammar/PROVENANCE.md` for the exact grammar commit and runtime/codegen -versions. `cargo xtask antlr check-generated` guards against drift in CI. diff --git a/crates/mehen-kotlin-parser/src/generated/decisions.json b/crates/mehen-kotlin-parser/src/generated/decisions.json deleted file mode 100644 index f9d054cc..00000000 --- a/crates/mehen-kotlin-parser/src/generated/decisions.json +++ /dev/null @@ -1,4315 +0,0 @@ -{ - "version": 2, - "fixedLookahead": null, - "grammars": [ - { - "name": "KotlinParser", - "summary": { - "total": 542, - "ll1": 290, - "fixed": 0, - "adaptive": 252 - }, - "decisions": [ - { - "decision": 0, - "rule": "kotlinFile", - "state": 349, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 1, - "rule": "kotlinFile", - "state": 354, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 2, - "rule": "kotlinFile", - "state": 360, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 3, - "rule": "kotlinFile", - "state": 368, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 4, - "rule": "script", - "state": 374, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 5, - "rule": "script", - "state": 379, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 6, - "rule": "script", - "state": 385, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 7, - "rule": "script", - "state": 395, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 8, - "rule": "shebangLine", - "state": 404, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 9, - "rule": "fileAnnotation", - "state": 411, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 10, - "rule": "fileAnnotation", - "state": 418, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 11, - "rule": "fileAnnotation", - "state": 425, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 12, - "rule": "fileAnnotation", - "state": 430, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 13, - "rule": "fileAnnotation", - "state": 435, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 14, - "rule": "packageHeader", - "state": 441, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 15, - "rule": "packageHeader", - "state": 443, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 16, - "rule": "importList", - "state": 448, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 17, - "rule": "importHeader", - "state": 456, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 18, - "rule": "importHeader", - "state": 459, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 19, - "rule": "topLevelObject", - "state": 466, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 20, - "rule": "typeAlias", - "state": 469, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 21, - "rule": "typeAlias", - "state": 475, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 22, - "rule": "typeAlias", - "state": 482, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 23, - "rule": "typeAlias", - "state": 486, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 24, - "rule": "typeAlias", - "state": 491, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 25, - "rule": "typeAlias", - "state": 498, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 26, - "rule": "declaration", - "state": 508, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 27, - "rule": "classDeclaration", - "state": 511, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 28, - "rule": "classDeclaration", - "state": 518, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 29, - "rule": "classDeclaration", - "state": 521, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 30, - "rule": "classDeclaration", - "state": 524, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 31, - "rule": "classDeclaration", - "state": 529, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 32, - "rule": "classDeclaration", - "state": 536, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 33, - "rule": "classDeclaration", - "state": 540, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 34, - "rule": "classDeclaration", - "state": 545, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 35, - "rule": "classDeclaration", - "state": 549, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 36, - "rule": "classDeclaration", - "state": 554, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 37, - "rule": "classDeclaration", - "state": 561, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 38, - "rule": "classDeclaration", - "state": 565, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 39, - "rule": "classDeclaration", - "state": 570, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 40, - "rule": "classDeclaration", - "state": 574, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 41, - "rule": "classDeclaration", - "state": 579, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 42, - "rule": "classDeclaration", - "state": 586, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 43, - "rule": "classDeclaration", - "state": 590, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 44, - "rule": "primaryConstructor", - "state": 593, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 45, - "rule": "primaryConstructor", - "state": 599, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 46, - "rule": "primaryConstructor", - "state": 602, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 47, - "rule": "classBody", - "state": 610, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 48, - "rule": "classBody", - "state": 617, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 49, - "rule": "classParameters", - "state": 626, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 50, - "rule": "classParameters", - "state": 633, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 51, - "rule": "classParameters", - "state": 640, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 52, - "rule": "classParameters", - "state": 646, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 53, - "rule": "classParameters", - "state": 652, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 54, - "rule": "classParameters", - "state": 656, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 55, - "rule": "classParameters", - "state": 658, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 56, - "rule": "classParameters", - "state": 663, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 57, - "rule": "classParameter", - "state": 669, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 58, - "rule": "classParameter", - "state": 672, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 59, - "rule": "classParameter", - "state": 677, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 60, - "rule": "classParameter", - "state": 685, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 61, - "rule": "classParameter", - "state": 692, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 62, - "rule": "classParameter", - "state": 699, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 63, - "rule": "classParameter", - "state": 703, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 64, - "rule": "delegationSpecifiers", - "state": 709, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 65, - "rule": "delegationSpecifiers", - "state": 716, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 66, - "rule": "delegationSpecifiers", - "state": 722, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 67, - "rule": "delegationSpecifier", - "state": 733, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 68, - "rule": "delegationSpecifier", - "state": 737, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 69, - "rule": "constructorInvocation", - "state": 743, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 70, - "rule": "annotatedDelegationSpecifier", - "state": 751, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 71, - "rule": "annotatedDelegationSpecifier", - "state": 757, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 72, - "rule": "explicitDelegation", - "state": 764, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 73, - "rule": "explicitDelegation", - "state": 769, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 74, - "rule": "explicitDelegation", - "state": 776, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 75, - "rule": "typeParameters", - "state": 785, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 76, - "rule": "typeParameters", - "state": 792, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 77, - "rule": "typeParameters", - "state": 799, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 78, - "rule": "typeParameters", - "state": 805, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 79, - "rule": "typeParameters", - "state": 811, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 80, - "rule": "typeParameters", - "state": 815, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 81, - "rule": "typeParameters", - "state": 820, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 82, - "rule": "typeParameter", - "state": 826, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 83, - "rule": "typeParameter", - "state": 831, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 84, - "rule": "typeParameter", - "state": 838, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 85, - "rule": "typeParameter", - "state": 845, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 86, - "rule": "typeParameter", - "state": 849, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 87, - "rule": "typeConstraints", - "state": 855, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 88, - "rule": "typeConstraints", - "state": 862, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 89, - "rule": "typeConstraints", - "state": 869, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 90, - "rule": "typeConstraints", - "state": 875, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 91, - "rule": "typeConstraint", - "state": 881, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 92, - "rule": "typeConstraint", - "state": 888, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 93, - "rule": "typeConstraint", - "state": 895, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 94, - "rule": "classMemberDeclarations", - "state": 902, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 95, - "rule": "classMemberDeclarations", - "state": 906, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 96, - "rule": "classMemberDeclaration", - "state": 913, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 97, - "rule": "anonymousInitializer", - "state": 919, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 98, - "rule": "companionObject", - "state": 925, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 99, - "rule": "companionObject", - "state": 931, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 100, - "rule": "companionObject", - "state": 935, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 101, - "rule": "companionObject", - "state": 940, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 102, - "rule": "companionObject", - "state": 947, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 103, - "rule": "companionObject", - "state": 951, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 104, - "rule": "companionObject", - "state": 956, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 105, - "rule": "companionObject", - "state": 963, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 106, - "rule": "companionObject", - "state": 967, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 107, - "rule": "companionObject", - "state": 972, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 108, - "rule": "companionObject", - "state": 976, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 109, - "rule": "functionValueParameters", - "state": 982, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 110, - "rule": "functionValueParameters", - "state": 989, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 111, - "rule": "functionValueParameters", - "state": 996, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 112, - "rule": "functionValueParameters", - "state": 1002, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 113, - "rule": "functionValueParameters", - "state": 1008, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 114, - "rule": "functionValueParameters", - "state": 1012, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 115, - "rule": "functionValueParameters", - "state": 1014, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 116, - "rule": "functionValueParameters", - "state": 1019, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 117, - "rule": "functionValueParameter", - "state": 1025, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 118, - "rule": "functionValueParameter", - "state": 1031, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 119, - "rule": "functionValueParameter", - "state": 1038, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 120, - "rule": "functionValueParameter", - "state": 1042, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 121, - "rule": "functionDeclaration", - "state": 1045, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 122, - "rule": "functionDeclaration", - "state": 1051, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 123, - "rule": "functionDeclaration", - "state": 1055, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 124, - "rule": "functionDeclaration", - "state": 1060, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 125, - "rule": "functionDeclaration", - "state": 1067, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 126, - "rule": "functionDeclaration", - "state": 1072, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 127, - "rule": "functionDeclaration", - "state": 1077, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 128, - "rule": "functionDeclaration", - "state": 1084, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 129, - "rule": "functionDeclaration", - "state": 1091, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 130, - "rule": "functionDeclaration", - "state": 1098, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 131, - "rule": "functionDeclaration", - "state": 1102, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 132, - "rule": "functionDeclaration", - "state": 1107, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 133, - "rule": "functionDeclaration", - "state": 1111, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 134, - "rule": "functionDeclaration", - "state": 1116, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 135, - "rule": "functionDeclaration", - "state": 1120, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 136, - "rule": "functionBody", - "state": 1127, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 137, - "rule": "functionBody", - "state": 1131, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 138, - "rule": "variableDeclaration", - "state": 1136, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 139, - "rule": "variableDeclaration", - "state": 1142, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 140, - "rule": "variableDeclaration", - "state": 1149, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 141, - "rule": "variableDeclaration", - "state": 1156, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 142, - "rule": "variableDeclaration", - "state": 1160, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 143, - "rule": "multiVariableDeclaration", - "state": 1166, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 144, - "rule": "multiVariableDeclaration", - "state": 1173, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 145, - "rule": "multiVariableDeclaration", - "state": 1180, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 146, - "rule": "multiVariableDeclaration", - "state": 1186, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 147, - "rule": "multiVariableDeclaration", - "state": 1192, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 148, - "rule": "multiVariableDeclaration", - "state": 1196, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 149, - "rule": "multiVariableDeclaration", - "state": 1201, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 150, - "rule": "propertyDeclaration", - "state": 1207, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 151, - "rule": "propertyDeclaration", - "state": 1213, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 152, - "rule": "propertyDeclaration", - "state": 1217, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 153, - "rule": "propertyDeclaration", - "state": 1222, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 154, - "rule": "propertyDeclaration", - "state": 1229, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 155, - "rule": "propertyDeclaration", - "state": 1234, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 156, - "rule": "propertyDeclaration", - "state": 1239, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 157, - "rule": "propertyDeclaration", - "state": 1244, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 158, - "rule": "propertyDeclaration", - "state": 1249, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 159, - "rule": "propertyDeclaration", - "state": 1253, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 160, - "rule": "propertyDeclaration", - "state": 1258, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 161, - "rule": "propertyDeclaration", - "state": 1265, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 162, - "rule": "propertyDeclaration", - "state": 1270, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 163, - "rule": "propertyDeclaration", - "state": 1272, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 164, - "rule": "propertyDeclaration", - "state": 1277, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 165, - "rule": "propertyDeclaration", - "state": 1281, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 166, - "rule": "propertyDeclaration", - "state": 1286, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 167, - "rule": "propertyDeclaration", - "state": 1290, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 168, - "rule": "propertyDeclaration", - "state": 1295, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 169, - "rule": "propertyDeclaration", - "state": 1299, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 170, - "rule": "propertyDeclaration", - "state": 1302, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 171, - "rule": "propertyDeclaration", - "state": 1305, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 172, - "rule": "propertyDeclaration", - "state": 1310, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 173, - "rule": "propertyDeclaration", - "state": 1314, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 174, - "rule": "propertyDeclaration", - "state": 1317, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 175, - "rule": "propertyDeclaration", - "state": 1319, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 176, - "rule": "propertyDelegate", - "state": 1325, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 177, - "rule": "getter", - "state": 1331, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 178, - "rule": "getter", - "state": 1337, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 179, - "rule": "getter", - "state": 1344, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 180, - "rule": "getter", - "state": 1351, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 181, - "rule": "getter", - "state": 1358, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 182, - "rule": "getter", - "state": 1362, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 183, - "rule": "getter", - "state": 1367, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 184, - "rule": "getter", - "state": 1371, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 185, - "rule": "setter", - "state": 1374, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 186, - "rule": "setter", - "state": 1380, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 187, - "rule": "setter", - "state": 1387, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 188, - "rule": "setter", - "state": 1394, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 189, - "rule": "setter", - "state": 1398, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 190, - "rule": "setter", - "state": 1403, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 191, - "rule": "setter", - "state": 1410, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 192, - "rule": "setter", - "state": 1417, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 193, - "rule": "setter", - "state": 1421, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 194, - "rule": "setter", - "state": 1426, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 195, - "rule": "setter", - "state": 1431, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 196, - "rule": "parametersWithOptionalType", - "state": 1437, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 197, - "rule": "parametersWithOptionalType", - "state": 1444, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 198, - "rule": "parametersWithOptionalType", - "state": 1451, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 199, - "rule": "parametersWithOptionalType", - "state": 1457, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 200, - "rule": "parametersWithOptionalType", - "state": 1463, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 201, - "rule": "parametersWithOptionalType", - "state": 1467, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 202, - "rule": "parametersWithOptionalType", - "state": 1469, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 203, - "rule": "parametersWithOptionalType", - "state": 1474, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 204, - "rule": "functionValueParameterWithOptionalType", - "state": 1480, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 205, - "rule": "functionValueParameterWithOptionalType", - "state": 1486, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 206, - "rule": "functionValueParameterWithOptionalType", - "state": 1493, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 207, - "rule": "functionValueParameterWithOptionalType", - "state": 1497, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 208, - "rule": "parameterWithOptionalType", - "state": 1503, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 209, - "rule": "parameterWithOptionalType", - "state": 1510, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 210, - "rule": "parameterWithOptionalType", - "state": 1514, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 211, - "rule": "parameter", - "state": 1520, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 212, - "rule": "parameter", - "state": 1527, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 213, - "rule": "objectDeclaration", - "state": 1533, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 214, - "rule": "objectDeclaration", - "state": 1539, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 215, - "rule": "objectDeclaration", - "state": 1546, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 216, - "rule": "objectDeclaration", - "state": 1553, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 217, - "rule": "objectDeclaration", - "state": 1557, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 218, - "rule": "objectDeclaration", - "state": 1562, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 219, - "rule": "objectDeclaration", - "state": 1566, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 220, - "rule": "secondaryConstructor", - "state": 1569, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 221, - "rule": "secondaryConstructor", - "state": 1575, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 222, - "rule": "secondaryConstructor", - "state": 1582, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 223, - "rule": "secondaryConstructor", - "state": 1589, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 224, - "rule": "secondaryConstructor", - "state": 1593, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 225, - "rule": "secondaryConstructor", - "state": 1598, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 226, - "rule": "secondaryConstructor", - "state": 1602, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 227, - "rule": "constructorDelegationCall", - "state": 1608, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 228, - "rule": "enumClassBody", - "state": 1617, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 229, - "rule": "enumClassBody", - "state": 1621, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 230, - "rule": "enumClassBody", - "state": 1626, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 231, - "rule": "enumClassBody", - "state": 1633, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 232, - "rule": "enumClassBody", - "state": 1637, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 233, - "rule": "enumClassBody", - "state": 1642, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 234, - "rule": "enumEntries", - "state": 1651, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 235, - "rule": "enumEntries", - "state": 1658, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 236, - "rule": "enumEntries", - "state": 1664, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 237, - "rule": "enumEntries", - "state": 1670, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 238, - "rule": "enumEntries", - "state": 1674, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 239, - "rule": "enumEntry", - "state": 1680, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 240, - "rule": "enumEntry", - "state": 1683, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 241, - "rule": "enumEntry", - "state": 1689, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 242, - "rule": "enumEntry", - "state": 1693, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 243, - "rule": "enumEntry", - "state": 1698, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 244, - "rule": "enumEntry", - "state": 1702, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 245, - "rule": "type", - "state": 1705, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 246, - "rule": "type", - "state": 1712, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 247, - "rule": "typeReference", - "state": 1716, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 248, - "rule": "nullableType", - "state": 1720, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 249, - "rule": "nullableType", - "state": 1725, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 250, - "rule": "nullableType", - "state": 1731, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 251, - "rule": "userType", - "state": 1739, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 252, - "rule": "userType", - "state": 1746, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 253, - "rule": "userType", - "state": 1752, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 254, - "rule": "simpleUserType", - "state": 1759, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 255, - "rule": "simpleUserType", - "state": 1763, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 256, - "rule": "typeProjection", - "state": 1766, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 257, - "rule": "typeProjection", - "state": 1770, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 258, - "rule": "typeProjectionModifiers", - "state": 1775, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 259, - "rule": "typeProjectionModifier", - "state": 1781, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 260, - "rule": "typeProjectionModifier", - "state": 1785, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 261, - "rule": "functionType", - "state": 1791, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 262, - "rule": "functionType", - "state": 1798, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 263, - "rule": "functionType", - "state": 1801, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 264, - "rule": "functionType", - "state": 1807, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 265, - "rule": "functionType", - "state": 1814, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 266, - "rule": "functionTypeParameters", - "state": 1823, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 267, - "rule": "functionTypeParameters", - "state": 1828, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 268, - "rule": "functionTypeParameters", - "state": 1833, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 269, - "rule": "functionTypeParameters", - "state": 1840, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 270, - "rule": "functionTypeParameters", - "state": 1845, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 271, - "rule": "functionTypeParameters", - "state": 1849, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 272, - "rule": "functionTypeParameters", - "state": 1855, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 273, - "rule": "functionTypeParameters", - "state": 1859, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 274, - "rule": "functionTypeParameters", - "state": 1864, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 275, - "rule": "parenthesizedType", - "state": 1873, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 276, - "rule": "parenthesizedType", - "state": 1880, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 277, - "rule": "receiverType", - "state": 1886, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 278, - "rule": "receiverType", - "state": 1891, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 279, - "rule": "parenthesizedUserType", - "state": 1897, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 280, - "rule": "parenthesizedUserType", - "state": 1902, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 281, - "rule": "parenthesizedUserType", - "state": 1907, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 282, - "rule": "definitelyNonNullableType", - "state": 1913, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 283, - "rule": "definitelyNonNullableType", - "state": 1917, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 284, - "rule": "definitelyNonNullableType", - "state": 1922, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 285, - "rule": "definitelyNonNullableType", - "state": 1929, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 286, - "rule": "definitelyNonNullableType", - "state": 1933, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 287, - "rule": "definitelyNonNullableType", - "state": 1937, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 288, - "rule": "statements", - "state": 1945, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 289, - "rule": "statements", - "state": 1948, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 290, - "rule": "statements", - "state": 1951, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 291, - "rule": "statement", - "state": 1955, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 292, - "rule": "statement", - "state": 1957, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 293, - "rule": "statement", - "state": 1964, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 294, - "rule": "label", - "state": 1971, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 295, - "rule": "controlStructureBody", - "state": 1976, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 296, - "rule": "block", - "state": 1982, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 297, - "rule": "block", - "state": 1989, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 298, - "rule": "loopStatement", - "state": 1997, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 299, - "rule": "forStatement", - "state": 2003, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 300, - "rule": "forStatement", - "state": 2010, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 301, - "rule": "forStatement", - "state": 2015, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 302, - "rule": "forStatement", - "state": 2023, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 303, - "rule": "forStatement", - "state": 2027, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 304, - "rule": "whileStatement", - "state": 2033, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 305, - "rule": "whileStatement", - "state": 2042, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 306, - "rule": "whileStatement", - "state": 2047, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 307, - "rule": "doWhileStatement", - "state": 2053, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 308, - "rule": "doWhileStatement", - "state": 2057, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 309, - "rule": "doWhileStatement", - "state": 2062, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 310, - "rule": "doWhileStatement", - "state": 2069, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 311, - "rule": "assignment", - "state": 2082, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 312, - "rule": "assignment", - "state": 2087, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 313, - "rule": "semi", - "state": 2096, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 314, - "rule": "semis", - "state": 2102, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 315, - "rule": "disjunction", - "state": 2110, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 316, - "rule": "disjunction", - "state": 2117, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 317, - "rule": "disjunction", - "state": 2123, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 318, - "rule": "conjunction", - "state": 2130, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 319, - "rule": "conjunction", - "state": 2137, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 320, - "rule": "conjunction", - "state": 2143, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 321, - "rule": "equality", - "state": 2151, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 322, - "rule": "equality", - "state": 2158, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 323, - "rule": "comparison", - "state": 2166, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 324, - "rule": "comparison", - "state": 2173, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 325, - "rule": "genericCallLikeComparison", - "state": 2180, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 326, - "rule": "infixOperation", - "state": 2188, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 327, - "rule": "infixOperation", - "state": 2197, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 328, - "rule": "infixOperation", - "state": 2202, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 329, - "rule": "infixOperation", - "state": 2204, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 330, - "rule": "elvisExpression", - "state": 2211, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 331, - "rule": "elvisExpression", - "state": 2218, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 332, - "rule": "elvisExpression", - "state": 2225, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 333, - "rule": "infixFunctionCall", - "state": 2236, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 334, - "rule": "infixFunctionCall", - "state": 2243, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 335, - "rule": "rangeExpression", - "state": 2251, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 336, - "rule": "rangeExpression", - "state": 2257, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 337, - "rule": "additiveExpression", - "state": 2265, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 338, - "rule": "additiveExpression", - "state": 2272, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 339, - "rule": "multiplicativeExpression", - "state": 2280, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 340, - "rule": "multiplicativeExpression", - "state": 2287, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 341, - "rule": "asExpression", - "state": 2294, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 342, - "rule": "asExpression", - "state": 2301, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 343, - "rule": "asExpression", - "state": 2308, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 344, - "rule": "prefixUnaryExpression", - "state": 2314, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 345, - "rule": "unaryPrefix", - "state": 2325, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 346, - "rule": "unaryPrefix", - "state": 2328, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 347, - "rule": "postfixUnaryExpression", - "state": 2334, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 348, - "rule": "postfixUnarySuffix", - "state": 2342, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 349, - "rule": "directlyAssignableExpression", - "state": 2349, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 350, - "rule": "parenthesizedDirectlyAssignableExpression", - "state": 2355, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 351, - "rule": "parenthesizedDirectlyAssignableExpression", - "state": 2362, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 352, - "rule": "assignableExpression", - "state": 2369, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 353, - "rule": "parenthesizedAssignableExpression", - "state": 2375, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 354, - "rule": "parenthesizedAssignableExpression", - "state": 2382, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 355, - "rule": "assignableSuffix", - "state": 2390, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 356, - "rule": "indexingSuffix", - "state": 2396, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 357, - "rule": "indexingSuffix", - "state": 2403, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 358, - "rule": "indexingSuffix", - "state": 2410, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 359, - "rule": "indexingSuffix", - "state": 2416, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 360, - "rule": "indexingSuffix", - "state": 2422, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 361, - "rule": "indexingSuffix", - "state": 2426, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 362, - "rule": "indexingSuffix", - "state": 2431, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 363, - "rule": "navigationSuffix", - "state": 2440, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 364, - "rule": "navigationSuffix", - "state": 2446, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 365, - "rule": "callSuffix", - "state": 2449, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 366, - "rule": "callSuffix", - "state": 2452, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 367, - "rule": "callSuffix", - "state": 2456, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 368, - "rule": "annotatedLambda", - "state": 2461, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 369, - "rule": "annotatedLambda", - "state": 2465, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 370, - "rule": "annotatedLambda", - "state": 2470, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 371, - "rule": "typeArguments", - "state": 2479, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 372, - "rule": "typeArguments", - "state": 2486, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 373, - "rule": "typeArguments", - "state": 2493, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 374, - "rule": "typeArguments", - "state": 2499, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 375, - "rule": "typeArguments", - "state": 2505, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 376, - "rule": "typeArguments", - "state": 2509, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 377, - "rule": "typeArguments", - "state": 2514, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 378, - "rule": "valueArguments", - "state": 2523, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 379, - "rule": "valueArguments", - "state": 2530, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 380, - "rule": "valueArguments", - "state": 2537, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 381, - "rule": "valueArguments", - "state": 2543, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 382, - "rule": "valueArguments", - "state": 2549, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 383, - "rule": "valueArguments", - "state": 2553, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 384, - "rule": "valueArguments", - "state": 2558, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 385, - "rule": "valueArguments", - "state": 2561, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 386, - "rule": "valueArgument", - "state": 2566, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 387, - "rule": "valueArgument", - "state": 2571, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 388, - "rule": "valueArgument", - "state": 2578, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 389, - "rule": "valueArgument", - "state": 2585, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 390, - "rule": "valueArgument", - "state": 2588, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 391, - "rule": "valueArgument", - "state": 2591, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 392, - "rule": "valueArgument", - "state": 2596, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 393, - "rule": "primaryExpression", - "state": 2615, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 394, - "rule": "parenthesizedExpression", - "state": 2621, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 395, - "rule": "parenthesizedExpression", - "state": 2628, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 396, - "rule": "collectionLiteral", - "state": 2637, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 397, - "rule": "collectionLiteral", - "state": 2644, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 398, - "rule": "collectionLiteral", - "state": 2651, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 399, - "rule": "collectionLiteral", - "state": 2657, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 400, - "rule": "collectionLiteral", - "state": 2663, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 401, - "rule": "collectionLiteral", - "state": 2667, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 402, - "rule": "collectionLiteral", - "state": 2672, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 403, - "rule": "collectionLiteral", - "state": 2675, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 404, - "rule": "stringLiteral", - "state": 2683, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 405, - "rule": "lineStringLiteral", - "state": 2688, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 406, - "rule": "lineStringLiteral", - "state": 2690, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 407, - "rule": "multiLineStringLiteral", - "state": 2699, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 408, - "rule": "multiLineStringLiteral", - "state": 2701, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 409, - "rule": "lineStringExpression", - "state": 2712, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 410, - "rule": "lineStringExpression", - "state": 2719, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 411, - "rule": "multiLineStringExpression", - "state": 2730, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 412, - "rule": "multiLineStringExpression", - "state": 2737, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 413, - "rule": "lambdaLiteral", - "state": 2746, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 414, - "rule": "lambdaLiteral", - "state": 2750, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 415, - "rule": "lambdaLiteral", - "state": 2755, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 416, - "rule": "lambdaLiteral", - "state": 2762, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 417, - "rule": "lambdaLiteral", - "state": 2765, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 418, - "rule": "lambdaLiteral", - "state": 2771, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 419, - "rule": "lambdaParameters", - "state": 2780, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 420, - "rule": "lambdaParameters", - "state": 2787, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 421, - "rule": "lambdaParameters", - "state": 2793, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 422, - "rule": "lambdaParameters", - "state": 2799, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 423, - "rule": "lambdaParameters", - "state": 2803, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 424, - "rule": "lambdaParameter", - "state": 2810, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 425, - "rule": "lambdaParameter", - "state": 2817, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 426, - "rule": "lambdaParameter", - "state": 2821, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 427, - "rule": "lambdaParameter", - "state": 2823, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 428, - "rule": "anonymousFunction", - "state": 2826, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 429, - "rule": "anonymousFunction", - "state": 2831, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 430, - "rule": "anonymousFunction", - "state": 2838, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 431, - "rule": "anonymousFunction", - "state": 2845, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 432, - "rule": "anonymousFunction", - "state": 2850, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 433, - "rule": "anonymousFunction", - "state": 2855, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 434, - "rule": "anonymousFunction", - "state": 2862, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 435, - "rule": "anonymousFunction", - "state": 2869, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 436, - "rule": "anonymousFunction", - "state": 2873, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 437, - "rule": "anonymousFunction", - "state": 2878, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 438, - "rule": "anonymousFunction", - "state": 2882, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 439, - "rule": "anonymousFunction", - "state": 2887, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 440, - "rule": "anonymousFunction", - "state": 2891, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 441, - "rule": "functionLiteral", - "state": 2895, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 442, - "rule": "objectLiteral", - "state": 2898, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 443, - "rule": "objectLiteral", - "state": 2903, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 444, - "rule": "objectLiteral", - "state": 2910, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 445, - "rule": "objectLiteral", - "state": 2917, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 446, - "rule": "objectLiteral", - "state": 2924, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 447, - "rule": "objectLiteral", - "state": 2927, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 448, - "rule": "objectLiteral", - "state": 2932, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 449, - "rule": "objectLiteral", - "state": 2936, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 450, - "rule": "superExpression", - "state": 2945, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 451, - "rule": "superExpression", - "state": 2952, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 452, - "rule": "superExpression", - "state": 2957, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 453, - "rule": "superExpression", - "state": 2961, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 454, - "rule": "superExpression", - "state": 2964, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 455, - "rule": "ifExpression", - "state": 2970, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 456, - "rule": "ifExpression", - "state": 2977, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 457, - "rule": "ifExpression", - "state": 2984, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 458, - "rule": "ifExpression", - "state": 2991, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 459, - "rule": "ifExpression", - "state": 2996, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 460, - "rule": "ifExpression", - "state": 3001, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 461, - "rule": "ifExpression", - "state": 3005, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 462, - "rule": "ifExpression", - "state": 3010, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 463, - "rule": "ifExpression", - "state": 3017, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 464, - "rule": "ifExpression", - "state": 3022, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 465, - "rule": "ifExpression", - "state": 3025, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 466, - "rule": "whenSubject", - "state": 3031, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 467, - "rule": "whenSubject", - "state": 3037, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 468, - "rule": "whenSubject", - "state": 3044, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 469, - "rule": "whenSubject", - "state": 3051, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 470, - "rule": "whenSubject", - "state": 3058, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 471, - "rule": "whenSubject", - "state": 3061, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 472, - "rule": "whenExpression", - "state": 3070, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 473, - "rule": "whenExpression", - "state": 3074, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 474, - "rule": "whenExpression", - "state": 3079, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 475, - "rule": "whenExpression", - "state": 3086, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 476, - "rule": "whenExpression", - "state": 3093, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 477, - "rule": "whenExpression", - "state": 3098, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 478, - "rule": "whenExpression", - "state": 3104, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 479, - "rule": "whenEntry", - "state": 3113, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 480, - "rule": "whenEntry", - "state": 3120, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 481, - "rule": "whenEntry", - "state": 3126, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 482, - "rule": "whenEntry", - "state": 3132, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 483, - "rule": "whenEntry", - "state": 3136, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 484, - "rule": "whenEntry", - "state": 3141, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 485, - "rule": "whenEntry", - "state": 3148, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 486, - "rule": "whenEntry", - "state": 3153, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 487, - "rule": "whenEntry", - "state": 3159, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 488, - "rule": "whenEntry", - "state": 3166, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 489, - "rule": "whenEntry", - "state": 3171, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 490, - "rule": "whenEntry", - "state": 3173, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 491, - "rule": "whenCondition", - "state": 3178, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 492, - "rule": "rangeTest", - "state": 3184, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 493, - "rule": "typeTest", - "state": 3193, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 494, - "rule": "tryExpression", - "state": 3202, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 495, - "rule": "tryExpression", - "state": 3209, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 496, - "rule": "tryExpression", - "state": 3215, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 497, - "rule": "tryExpression", - "state": 3220, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 498, - "rule": "tryExpression", - "state": 3224, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 499, - "rule": "tryExpression", - "state": 3229, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 500, - "rule": "tryExpression", - "state": 3233, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 501, - "rule": "catchBlock", - "state": 3239, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 502, - "rule": "catchBlock", - "state": 3246, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 503, - "rule": "catchBlock", - "state": 3255, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 504, - "rule": "catchBlock", - "state": 3259, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 505, - "rule": "catchBlock", - "state": 3265, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 506, - "rule": "finallyBlock", - "state": 3274, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 507, - "rule": "jumpExpression", - "state": 3283, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 508, - "rule": "jumpExpression", - "state": 3289, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 509, - "rule": "jumpExpression", - "state": 3295, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 510, - "rule": "callableReference", - "state": 3298, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 511, - "rule": "callableReference", - "state": 3304, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 512, - "rule": "callableReference", - "state": 3309, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 513, - "rule": "prefixUnaryOperator", - "state": 3332, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 514, - "rule": "postfixUnaryOperator", - "state": 3338, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 515, - "rule": "memberAccessOperator", - "state": 3345, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 516, - "rule": "memberAccessOperator", - "state": 3352, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 517, - "rule": "memberAccessOperator", - "state": 3357, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 518, - "rule": "modifiers", - "state": 3364, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 519, - "rule": "modifiers", - "state": 3366, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 520, - "rule": "parameterModifiers", - "state": 3370, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 521, - "rule": "parameterModifiers", - "state": 3372, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 522, - "rule": "modifier", - "state": 3382, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 523, - "rule": "modifier", - "state": 3387, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 524, - "rule": "typeModifiers", - "state": 3393, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 525, - "rule": "typeModifier", - "state": 3400, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 526, - "rule": "typeModifier", - "state": 3403, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 527, - "rule": "typeParameterModifiers", - "state": 3416, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 528, - "rule": "typeParameterModifier", - "state": 3422, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 529, - "rule": "typeParameterModifier", - "state": 3429, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 530, - "rule": "typeParameterModifier", - "state": 3433, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 531, - "rule": "annotation", - "state": 3449, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 532, - "rule": "annotation", - "state": 3454, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 533, - "rule": "singleAnnotation", - "state": 3461, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 534, - "rule": "singleAnnotation", - "state": 3466, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 535, - "rule": "multiAnnotation", - "state": 3474, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 536, - "rule": "multiAnnotation", - "state": 3479, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 537, - "rule": "multiAnnotation", - "state": 3485, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 538, - "rule": "annotationUseSiteTarget", - "state": 3494, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 539, - "rule": "unescapedAnnotation", - "state": 3501, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - }, - { - "decision": 540, - "rule": "identifier", - "state": 3509, - "canDefer": false, - "tier": "ll1" - }, - { - "decision": 541, - "rule": "identifier", - "state": 3516, - "canDefer": true, - "tier": "adaptive", - "reason": "not-disjoint", - "probedLookahead": 1 - } - ] - } - ] -} diff --git a/crates/mehen-kotlin-parser/src/generated/kotlin_lexer.rs b/crates/mehen-kotlin-parser/src/generated/kotlin_lexer.rs deleted file mode 100644 index 1d32c58d..00000000 --- a/crates/mehen-kotlin-parser/src/generated/kotlin_lexer.rs +++ /dev/null @@ -1,299 +0,0 @@ -// @generated by antlr-rust-codegen v0.33.1 - do not edit -// project: https://github.com/ophi-dev/antlr-rust-runtime -antlr4_runtime::__antlr4_rust_require_codegen_api!(14, "0.33.1"); -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -#[rustfmt::skip] -mod __antlr4_rust_generated { - -use antlr4_runtime::char_stream::CharStream; -use antlr4_runtime::atn::LexerAtn; -use antlr4_runtime::atn::lexer_dfa::CompiledLexerDfa; -use antlr4_runtime::atn::serialized::AtnDeserializer; -use antlr4_runtime::{BaseLexer, GrammarMetadata, Lexer}; -use std::sync::OnceLock; - -pub const EOF: i32 = antlr4_runtime::TOKEN_EOF; -pub const SHEBANG_LINE: i32 = 1; -pub const DELIMITED_COMMENT: i32 = 2; -pub const LINE_COMMENT: i32 = 3; -pub const WS: i32 = 4; -pub const NL: i32 = 5; -pub const RESERVED: i32 = 6; -pub const DOT: i32 = 7; -pub const COMMA: i32 = 8; -pub const LPAREN: i32 = 9; -pub const RPAREN: i32 = 10; -pub const LSQUARE: i32 = 11; -pub const RSQUARE: i32 = 12; -pub const LCURL: i32 = 13; -pub const RCURL: i32 = 14; -pub const MULT: i32 = 15; -pub const MOD: i32 = 16; -pub const DIV: i32 = 17; -pub const ADD: i32 = 18; -pub const SUB: i32 = 19; -pub const INCR: i32 = 20; -pub const DECR: i32 = 21; -pub const CONJ: i32 = 22; -pub const DISJ: i32 = 23; -pub const EXCL_WS: i32 = 24; -pub const EXCL_NO_WS: i32 = 25; -pub const COLON: i32 = 26; -pub const SEMICOLON: i32 = 27; -pub const ASSIGNMENT: i32 = 28; -pub const ADD_ASSIGNMENT: i32 = 29; -pub const SUB_ASSIGNMENT: i32 = 30; -pub const MULT_ASSIGNMENT: i32 = 31; -pub const DIV_ASSIGNMENT: i32 = 32; -pub const MOD_ASSIGNMENT: i32 = 33; -pub const ARROW: i32 = 34; -pub const DOUBLE_ARROW: i32 = 35; -pub const RANGE: i32 = 36; -pub const RANGE_UNTIL: i32 = 37; -pub const COLONCOLON: i32 = 38; -pub const DOUBLE_SEMICOLON: i32 = 39; -pub const HASH: i32 = 40; -pub const AT_NO_WS: i32 = 41; -pub const AT_POST_WS: i32 = 42; -pub const AT_PRE_WS: i32 = 43; -pub const AT_BOTH_WS: i32 = 44; -pub const QUEST_WS: i32 = 45; -pub const QUEST_NO_WS: i32 = 46; -pub const LANGLE: i32 = 47; -pub const RANGLE: i32 = 48; -pub const LE: i32 = 49; -pub const GE: i32 = 50; -pub const EXCL_EQ: i32 = 51; -pub const EXCL_EQEQ: i32 = 52; -pub const AS_SAFE: i32 = 53; -pub const EQEQ: i32 = 54; -pub const EQEQEQ: i32 = 55; -pub const SINGLE_QUOTE: i32 = 56; -pub const AMP: i32 = 57; -pub const RETURN_AT: i32 = 58; -pub const CONTINUE_AT: i32 = 59; -pub const BREAK_AT: i32 = 60; -pub const THIS_AT: i32 = 61; -pub const SUPER_AT: i32 = 62; -pub const FILE: i32 = 63; -pub const FIELD: i32 = 64; -pub const PROPERTY: i32 = 65; -pub const GET: i32 = 66; -pub const SET: i32 = 67; -pub const RECEIVER: i32 = 68; -pub const PARAM: i32 = 69; -pub const SETPARAM: i32 = 70; -pub const DELEGATE: i32 = 71; -pub const PACKAGE: i32 = 72; -pub const IMPORT: i32 = 73; -pub const CLASS: i32 = 74; -pub const INTERFACE: i32 = 75; -pub const FUN: i32 = 76; -pub const OBJECT: i32 = 77; -pub const VAL: i32 = 78; -pub const VAR: i32 = 79; -pub const TYPE_ALIAS: i32 = 80; -pub const CONSTRUCTOR: i32 = 81; -pub const BY: i32 = 82; -pub const COMPANION: i32 = 83; -pub const INIT: i32 = 84; -pub const THIS: i32 = 85; -pub const SUPER: i32 = 86; -pub const TYPEOF: i32 = 87; -pub const WHERE: i32 = 88; -pub const IF: i32 = 89; -pub const ELSE: i32 = 90; -pub const WHEN: i32 = 91; -pub const TRY: i32 = 92; -pub const CATCH: i32 = 93; -pub const FINALLY: i32 = 94; -pub const FOR: i32 = 95; -pub const DO: i32 = 96; -pub const WHILE: i32 = 97; -pub const THROW: i32 = 98; -pub const RETURN: i32 = 99; -pub const CONTINUE: i32 = 100; -pub const BREAK: i32 = 101; -pub const AS: i32 = 102; -pub const IS: i32 = 103; -pub const IN: i32 = 104; -pub const NOT_IS: i32 = 105; -pub const NOT_IN: i32 = 106; -pub const OUT: i32 = 107; -pub const DYNAMIC: i32 = 108; -pub const PUBLIC: i32 = 109; -pub const PRIVATE: i32 = 110; -pub const PROTECTED: i32 = 111; -pub const INTERNAL: i32 = 112; -pub const ENUM: i32 = 113; -pub const SEALED: i32 = 114; -pub const ANNOTATION: i32 = 115; -pub const DATA: i32 = 116; -pub const INNER: i32 = 117; -pub const VALUE: i32 = 118; -pub const TAILREC: i32 = 119; -pub const OPERATOR: i32 = 120; -pub const INLINE: i32 = 121; -pub const INFIX: i32 = 122; -pub const EXTERNAL: i32 = 123; -pub const SUSPEND: i32 = 124; -pub const OVERRIDE: i32 = 125; -pub const ABSTRACT: i32 = 126; -pub const FINAL: i32 = 127; -pub const OPEN: i32 = 128; -pub const CONST: i32 = 129; -pub const LATEINIT: i32 = 130; -pub const VARARG: i32 = 131; -pub const NOINLINE: i32 = 132; -pub const CROSSINLINE: i32 = 133; -pub const REIFIED: i32 = 134; -pub const EXPECT: i32 = 135; -pub const ACTUAL: i32 = 136; -pub const REAL_LITERAL: i32 = 137; -pub const FLOAT_LITERAL: i32 = 138; -pub const DOUBLE_LITERAL: i32 = 139; -pub const INTEGER_LITERAL: i32 = 140; -pub const HEX_LITERAL: i32 = 141; -pub const BIN_LITERAL: i32 = 142; -pub const UNSIGNED_LITERAL: i32 = 143; -pub const LONG_LITERAL: i32 = 144; -pub const BOOLEAN_LITERAL: i32 = 145; -pub const NULL_LITERAL: i32 = 146; -pub const CHARACTER_LITERAL: i32 = 147; -pub const IDENTIFIER: i32 = 148; -pub const IDENTIFIER_OR_SOFT_KEY: i32 = 149; -pub const FIELD_IDENTIFIER: i32 = 150; -pub const QUOTE_OPEN: i32 = 151; -pub const TRIPLE_QUOTE_OPEN: i32 = 152; -pub const UNICODE_CLASS_LL: i32 = 153; -pub const UNICODE_CLASS_LM: i32 = 154; -pub const UNICODE_CLASS_LO: i32 = 155; -pub const UNICODE_CLASS_LT: i32 = 156; -pub const UNICODE_CLASS_LU: i32 = 157; -pub const UNICODE_CLASS_ND: i32 = 158; -pub const UNICODE_CLASS_NL: i32 = 159; -pub const QUOTE_CLOSE: i32 = 160; -pub const LINE_STR_REF: i32 = 161; -pub const LINE_STR_TEXT: i32 = 162; -pub const LINE_STR_ESCAPED_CHAR: i32 = 163; -pub const LINE_STR_EXPR_START: i32 = 164; -pub const TRIPLE_QUOTE_CLOSE: i32 = 165; -pub const MULTI_LINE_STRING_QUOTE: i32 = 166; -pub const MULTI_LINE_STR_REF: i32 = 167; -pub const MULTI_LINE_STR_TEXT: i32 = 168; -pub const MULTI_LINE_STR_EXPR_START: i32 = 169; -pub const INSIDE_COMMENT: i32 = 170; -pub const INSIDE_WS: i32 = 171; -pub const INSIDE_NL: i32 = 172; -pub const ERROR_CHARACTER: i32 = 173; - -pub const CHANNEL_DEFAULT_TOKEN_CHANNEL: i32 = 0; -pub const CHANNEL_HIDDEN: i32 = 1; -pub const MODE_DEFAULT_MODE: i32 = 0; -pub const MODE_INSIDE: i32 = 3; -pub const MODE_LINE_STRING: i32 = 1; -pub const MODE_MULTI_LINE_STRING: i32 = 2; - -pub static METADATA: GrammarMetadata = GrammarMetadata::new( - "KotlinLexer", - &["ShebangLine", "DelimitedComment", "LineComment", "WS", "NL", "Hidden", "RESERVED", "DOT", "COMMA", "LPAREN", "RPAREN", "LSQUARE", "RSQUARE", "LCURL", "RCURL", "MULT", "MOD", "DIV", "ADD", "SUB", "INCR", "DECR", "CONJ", "DISJ", "EXCL_WS", "EXCL_NO_WS", "COLON", "SEMICOLON", "ASSIGNMENT", "ADD_ASSIGNMENT", "SUB_ASSIGNMENT", "MULT_ASSIGNMENT", "DIV_ASSIGNMENT", "MOD_ASSIGNMENT", "ARROW", "DOUBLE_ARROW", "RANGE", "RANGE_UNTIL", "COLONCOLON", "DOUBLE_SEMICOLON", "HASH", "AT_NO_WS", "AT_POST_WS", "AT_PRE_WS", "AT_BOTH_WS", "QUEST_WS", "QUEST_NO_WS", "LANGLE", "RANGLE", "LE", "GE", "EXCL_EQ", "EXCL_EQEQ", "AS_SAFE", "EQEQ", "EQEQEQ", "SINGLE_QUOTE", "AMP", "RETURN_AT", "CONTINUE_AT", "BREAK_AT", "THIS_AT", "SUPER_AT", "FILE", "FIELD", "PROPERTY", "GET", "SET", "RECEIVER", "PARAM", "SETPARAM", "DELEGATE", "PACKAGE", "IMPORT", "CLASS", "INTERFACE", "FUN", "OBJECT", "VAL", "VAR", "TYPE_ALIAS", "CONSTRUCTOR", "BY", "COMPANION", "INIT", "THIS", "SUPER", "TYPEOF", "WHERE", "IF", "ELSE", "WHEN", "TRY", "CATCH", "FINALLY", "FOR", "DO", "WHILE", "THROW", "RETURN", "CONTINUE", "BREAK", "AS", "IS", "IN", "NOT_IS", "NOT_IN", "OUT", "DYNAMIC", "PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "ENUM", "SEALED", "ANNOTATION", "DATA", "INNER", "VALUE", "TAILREC", "OPERATOR", "INLINE", "INFIX", "EXTERNAL", "SUSPEND", "OVERRIDE", "ABSTRACT", "FINAL", "OPEN", "CONST", "LATEINIT", "VARARG", "NOINLINE", "CROSSINLINE", "REIFIED", "EXPECT", "ACTUAL", "DecDigit", "DecDigitNoZero", "DecDigitOrSeparator", "DecDigits", "DoubleExponent", "RealLiteral", "FloatLiteral", "DoubleLiteral", "IntegerLiteral", "HexDigit", "HexDigitOrSeparator", "HexLiteral", "BinDigit", "BinDigitOrSeparator", "BinLiteral", "UnsignedLiteral", "LongLiteral", "BooleanLiteral", "NullLiteral", "CharacterLiteral", "UnicodeDigit", "Identifier", "IdentifierOrSoftKey", "FieldIdentifier", "UniCharacterLiteral", "EscapedIdentifier", "EscapeSeq", "Letter", "QUOTE_OPEN", "TRIPLE_QUOTE_OPEN", "UNICODE_CLASS_LL", "UNICODE_CLASS_LM", "UNICODE_CLASS_LO", "UNICODE_CLASS_LT", "UNICODE_CLASS_LU", "UNICODE_CLASS_ND", "UNICODE_CLASS_NL", "QUOTE_CLOSE", "LineStrRef", "LineStrText", "LineStrEscapedChar", "LineStrExprStart", "TRIPLE_QUOTE_CLOSE", "MultiLineStringQuote", "MultiLineStrRef", "MultiLineStrText", "MultiLineStrExprStart", "Inside_RPAREN", "Inside_RSQUARE", "Inside_LPAREN", "Inside_LSQUARE", "Inside_LCURL", "Inside_RCURL", "Inside_DOT", "Inside_COMMA", "Inside_MULT", "Inside_MOD", "Inside_DIV", "Inside_ADD", "Inside_SUB", "Inside_INCR", "Inside_DECR", "Inside_CONJ", "Inside_DISJ", "Inside_EXCL_WS", "Inside_EXCL_NO_WS", "Inside_COLON", "Inside_SEMICOLON", "Inside_ASSIGNMENT", "Inside_ADD_ASSIGNMENT", "Inside_SUB_ASSIGNMENT", "Inside_MULT_ASSIGNMENT", "Inside_DIV_ASSIGNMENT", "Inside_MOD_ASSIGNMENT", "Inside_ARROW", "Inside_DOUBLE_ARROW", "Inside_RANGE", "Inside_RANGE_UNTIL", "Inside_RESERVED", "Inside_COLONCOLON", "Inside_DOUBLE_SEMICOLON", "Inside_HASH", "Inside_AT_NO_WS", "Inside_AT_POST_WS", "Inside_AT_PRE_WS", "Inside_AT_BOTH_WS", "Inside_QUEST_WS", "Inside_QUEST_NO_WS", "Inside_LANGLE", "Inside_RANGLE", "Inside_LE", "Inside_GE", "Inside_EXCL_EQ", "Inside_EXCL_EQEQ", "Inside_IS", "Inside_NOT_IS", "Inside_NOT_IN", "Inside_AS", "Inside_AS_SAFE", "Inside_EQEQ", "Inside_EQEQEQ", "Inside_SINGLE_QUOTE", "Inside_AMP", "Inside_QUOTE_OPEN", "Inside_TRIPLE_QUOTE_OPEN", "Inside_VAL", "Inside_VAR", "Inside_FUN", "Inside_OBJECT", "Inside_SUPER", "Inside_IN", "Inside_OUT", "Inside_FIELD", "Inside_FILE", "Inside_PROPERTY", "Inside_GET", "Inside_SET", "Inside_RECEIVER", "Inside_PARAM", "Inside_SETPARAM", "Inside_DELEGATE", "Inside_THROW", "Inside_RETURN", "Inside_CONTINUE", "Inside_BREAK", "Inside_RETURN_AT", "Inside_CONTINUE_AT", "Inside_BREAK_AT", "Inside_IF", "Inside_ELSE", "Inside_WHEN", "Inside_TRY", "Inside_CATCH", "Inside_FINALLY", "Inside_FOR", "Inside_DO", "Inside_WHILE", "Inside_PUBLIC", "Inside_PRIVATE", "Inside_PROTECTED", "Inside_INTERNAL", "Inside_ENUM", "Inside_SEALED", "Inside_ANNOTATION", "Inside_DATA", "Inside_INNER", "Inside_VALUE", "Inside_TAILREC", "Inside_OPERATOR", "Inside_INLINE", "Inside_INFIX", "Inside_EXTERNAL", "Inside_SUSPEND", "Inside_OVERRIDE", "Inside_ABSTRACT", "Inside_FINAL", "Inside_OPEN", "Inside_CONST", "Inside_LATEINIT", "Inside_VARARG", "Inside_NOINLINE", "Inside_CROSSINLINE", "Inside_REIFIED", "Inside_EXPECT", "Inside_ACTUAL", "Inside_BooleanLiteral", "Inside_IntegerLiteral", "Inside_HexLiteral", "Inside_BinLiteral", "Inside_CharacterLiteral", "Inside_RealLiteral", "Inside_NullLiteral", "Inside_LongLiteral", "Inside_UnsignedLiteral", "Inside_Identifier", "Inside_Comment", "Inside_WS", "Inside_NL", "ErrorCharacter"], - &[None, None, None, None, None, None, Some("\'...\'"), Some("\'.\'"), Some("\',\'"), Some("\'(\'"), Some("\')\'"), Some("\'[\'"), Some("\']\'"), Some("\'{\'"), Some("\'}\'"), Some("\'*\'"), Some("\'%\'"), Some("\'/\'"), Some("\'+\'"), Some("\'-\'"), Some("\'++\'"), Some("\'--\'"), Some("\'&&\'"), Some("\'||\'"), None, Some("\'!\'"), Some("\':\'"), Some("\';\'"), Some("\'=\'"), Some("\'+=\'"), Some("\'-=\'"), Some("\'*=\'"), Some("\'/=\'"), Some("\'%=\'"), Some("\'->\'"), Some("\'=>\'"), Some("\'..\'"), Some("\'..<\'"), Some("\'::\'"), Some("\';;\'"), Some("\'#\'"), Some("\'@\'"), None, None, None, None, Some("\'?\'"), Some("\'<\'"), Some("\'>\'"), Some("\'<=\'"), Some("\'>=\'"), Some("\'!=\'"), Some("\'!==\'"), Some("\'as?\'"), Some("\'==\'"), Some("\'===\'"), Some("\'\\\'\'"), Some("\'&\'"), None, None, None, None, None, Some("\'file\'"), Some("\'field\'"), Some("\'property\'"), Some("\'get\'"), Some("\'set\'"), Some("\'receiver\'"), Some("\'param\'"), Some("\'setparam\'"), Some("\'delegate\'"), Some("\'package\'"), Some("\'import\'"), Some("\'class\'"), Some("\'interface\'"), Some("\'fun\'"), Some("\'object\'"), Some("\'val\'"), Some("\'var\'"), Some("\'typealias\'"), Some("\'constructor\'"), Some("\'by\'"), Some("\'companion\'"), Some("\'init\'"), Some("\'this\'"), Some("\'super\'"), Some("\'typeof\'"), Some("\'where\'"), Some("\'if\'"), Some("\'else\'"), Some("\'when\'"), Some("\'try\'"), Some("\'catch\'"), Some("\'finally\'"), Some("\'for\'"), Some("\'do\'"), Some("\'while\'"), Some("\'throw\'"), Some("\'return\'"), Some("\'continue\'"), Some("\'break\'"), Some("\'as\'"), Some("\'is\'"), Some("\'in\'"), None, None, Some("\'out\'"), Some("\'dynamic\'"), Some("\'public\'"), Some("\'private\'"), Some("\'protected\'"), Some("\'internal\'"), Some("\'enum\'"), Some("\'sealed\'"), Some("\'annotation\'"), Some("\'data\'"), Some("\'inner\'"), Some("\'value\'"), Some("\'tailrec\'"), Some("\'operator\'"), Some("\'inline\'"), Some("\'infix\'"), Some("\'external\'"), Some("\'suspend\'"), Some("\'override\'"), Some("\'abstract\'"), Some("\'final\'"), Some("\'open\'"), Some("\'const\'"), Some("\'lateinit\'"), Some("\'vararg\'"), Some("\'noinline\'"), Some("\'crossinline\'"), Some("\'reified\'"), Some("\'expect\'"), Some("\'actual\'"), None, None, None, None, None, None, None, None, None, Some("\'null\'"), None, None, None, None, None, Some("\'\"\"\"\'"), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &[None, Some("ShebangLine"), Some("DelimitedComment"), Some("LineComment"), Some("WS"), Some("NL"), Some("RESERVED"), Some("DOT"), Some("COMMA"), Some("LPAREN"), Some("RPAREN"), Some("LSQUARE"), Some("RSQUARE"), Some("LCURL"), Some("RCURL"), Some("MULT"), Some("MOD"), Some("DIV"), Some("ADD"), Some("SUB"), Some("INCR"), Some("DECR"), Some("CONJ"), Some("DISJ"), Some("EXCL_WS"), Some("EXCL_NO_WS"), Some("COLON"), Some("SEMICOLON"), Some("ASSIGNMENT"), Some("ADD_ASSIGNMENT"), Some("SUB_ASSIGNMENT"), Some("MULT_ASSIGNMENT"), Some("DIV_ASSIGNMENT"), Some("MOD_ASSIGNMENT"), Some("ARROW"), Some("DOUBLE_ARROW"), Some("RANGE"), Some("RANGE_UNTIL"), Some("COLONCOLON"), Some("DOUBLE_SEMICOLON"), Some("HASH"), Some("AT_NO_WS"), Some("AT_POST_WS"), Some("AT_PRE_WS"), Some("AT_BOTH_WS"), Some("QUEST_WS"), Some("QUEST_NO_WS"), Some("LANGLE"), Some("RANGLE"), Some("LE"), Some("GE"), Some("EXCL_EQ"), Some("EXCL_EQEQ"), Some("AS_SAFE"), Some("EQEQ"), Some("EQEQEQ"), Some("SINGLE_QUOTE"), Some("AMP"), Some("RETURN_AT"), Some("CONTINUE_AT"), Some("BREAK_AT"), Some("THIS_AT"), Some("SUPER_AT"), Some("FILE"), Some("FIELD"), Some("PROPERTY"), Some("GET"), Some("SET"), Some("RECEIVER"), Some("PARAM"), Some("SETPARAM"), Some("DELEGATE"), Some("PACKAGE"), Some("IMPORT"), Some("CLASS"), Some("INTERFACE"), Some("FUN"), Some("OBJECT"), Some("VAL"), Some("VAR"), Some("TYPE_ALIAS"), Some("CONSTRUCTOR"), Some("BY"), Some("COMPANION"), Some("INIT"), Some("THIS"), Some("SUPER"), Some("TYPEOF"), Some("WHERE"), Some("IF"), Some("ELSE"), Some("WHEN"), Some("TRY"), Some("CATCH"), Some("FINALLY"), Some("FOR"), Some("DO"), Some("WHILE"), Some("THROW"), Some("RETURN"), Some("CONTINUE"), Some("BREAK"), Some("AS"), Some("IS"), Some("IN"), Some("NOT_IS"), Some("NOT_IN"), Some("OUT"), Some("DYNAMIC"), Some("PUBLIC"), Some("PRIVATE"), Some("PROTECTED"), Some("INTERNAL"), Some("ENUM"), Some("SEALED"), Some("ANNOTATION"), Some("DATA"), Some("INNER"), Some("VALUE"), Some("TAILREC"), Some("OPERATOR"), Some("INLINE"), Some("INFIX"), Some("EXTERNAL"), Some("SUSPEND"), Some("OVERRIDE"), Some("ABSTRACT"), Some("FINAL"), Some("OPEN"), Some("CONST"), Some("LATEINIT"), Some("VARARG"), Some("NOINLINE"), Some("CROSSINLINE"), Some("REIFIED"), Some("EXPECT"), Some("ACTUAL"), Some("RealLiteral"), Some("FloatLiteral"), Some("DoubleLiteral"), Some("IntegerLiteral"), Some("HexLiteral"), Some("BinLiteral"), Some("UnsignedLiteral"), Some("LongLiteral"), Some("BooleanLiteral"), Some("NullLiteral"), Some("CharacterLiteral"), Some("Identifier"), Some("IdentifierOrSoftKey"), Some("FieldIdentifier"), Some("QUOTE_OPEN"), Some("TRIPLE_QUOTE_OPEN"), Some("UNICODE_CLASS_LL"), Some("UNICODE_CLASS_LM"), Some("UNICODE_CLASS_LO"), Some("UNICODE_CLASS_LT"), Some("UNICODE_CLASS_LU"), Some("UNICODE_CLASS_ND"), Some("UNICODE_CLASS_NL"), Some("QUOTE_CLOSE"), Some("LineStrRef"), Some("LineStrText"), Some("LineStrEscapedChar"), Some("LineStrExprStart"), Some("TRIPLE_QUOTE_CLOSE"), Some("MultiLineStringQuote"), Some("MultiLineStrRef"), Some("MultiLineStrText"), Some("MultiLineStrExprStart"), Some("Inside_Comment"), Some("Inside_WS"), Some("Inside_NL"), Some("ErrorCharacter")], - &[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &["DEFAULT_TOKEN_CHANNEL", "HIDDEN"], - &["DEFAULT_MODE", "LineString", "MultiLineString", "Inside", "DEFAULT_MODE"], - &[4, 0, 173, 2252, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 2, 202, 7, 202, 2, 203, 7, 203, 2, 204, 7, 204, 2, 205, 7, 205, 2, 206, 7, 206, 2, 207, 7, 207, 2, 208, 7, 208, 2, 209, 7, 209, 2, 210, 7, 210, 2, 211, 7, 211, 2, 212, 7, 212, 2, 213, 7, 213, 2, 214, 7, 214, 2, 215, 7, 215, 2, 216, 7, 216, 2, 217, 7, 217, 2, 218, 7, 218, 2, 219, 7, 219, 2, 220, 7, 220, 2, 221, 7, 221, 2, 222, 7, 222, 2, 223, 7, 223, 2, 224, 7, 224, 2, 225, 7, 225, 2, 226, 7, 226, 2, 227, 7, 227, 2, 228, 7, 228, 2, 229, 7, 229, 2, 230, 7, 230, 2, 231, 7, 231, 2, 232, 7, 232, 2, 233, 7, 233, 2, 234, 7, 234, 2, 235, 7, 235, 2, 236, 7, 236, 2, 237, 7, 237, 2, 238, 7, 238, 2, 239, 7, 239, 2, 240, 7, 240, 2, 241, 7, 241, 2, 242, 7, 242, 2, 243, 7, 243, 2, 244, 7, 244, 2, 245, 7, 245, 2, 246, 7, 246, 2, 247, 7, 247, 2, 248, 7, 248, 2, 249, 7, 249, 2, 250, 7, 250, 2, 251, 7, 251, 2, 252, 7, 252, 2, 253, 7, 253, 2, 254, 7, 254, 2, 255, 7, 255, 2, 256, 7, 256, 2, 257, 7, 257, 2, 258, 7, 258, 2, 259, 7, 259, 2, 260, 7, 260, 2, 261, 7, 261, 2, 262, 7, 262, 2, 263, 7, 263, 2, 264, 7, 264, 2, 265, 7, 265, 2, 266, 7, 266, 2, 267, 7, 267, 2, 268, 7, 268, 2, 269, 7, 269, 2, 270, 7, 270, 2, 271, 7, 271, 2, 272, 7, 272, 2, 273, 7, 273, 2, 274, 7, 274, 2, 275, 7, 275, 2, 276, 7, 276, 2, 277, 7, 277, 2, 278, 7, 278, 2, 279, 7, 279, 2, 280, 7, 280, 2, 281, 7, 281, 2, 282, 7, 282, 2, 283, 7, 283, 2, 284, 7, 284, 2, 285, 7, 285, 2, 286, 7, 286, 2, 287, 7, 287, 2, 288, 7, 288, 2, 289, 7, 289, 2, 290, 7, 290, 2, 291, 7, 291, 2, 292, 7, 292, 2, 293, 7, 293, 2, 294, 7, 294, 2, 295, 7, 295, 2, 296, 7, 296, 2, 297, 7, 297, 2, 298, 7, 298, 2, 299, 7, 299, 2, 300, 7, 300, 2, 301, 7, 301, 2, 302, 7, 302, 2, 303, 7, 303, 2, 304, 7, 304, 2, 305, 7, 305, 2, 306, 7, 306, 2, 307, 7, 307, 2, 308, 7, 308, 2, 309, 7, 309, 2, 310, 7, 310, 2, 311, 7, 311, 2, 312, 7, 312, 2, 313, 7, 313, 2, 314, 7, 314, 2, 315, 7, 315, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 642, 8, 0, 10, 0, 12, 0, 645, 9, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 652, 8, 1, 10, 1, 12, 1, 655, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 5, 2, 666, 8, 2, 10, 2, 12, 2, 669, 9, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 3, 4, 680, 8, 4, 3, 4, 682, 8, 4, 1, 5, 1, 5, 1, 5, 3, 5, 687, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 3, 42, 791, 8, 42, 1, 43, 1, 43, 3, 43, 795, 8, 43, 1, 43, 1, 43, 1, 44, 1, 44, 3, 44, 801, 8, 44, 1, 44, 1, 44, 1, 44, 3, 44, 806, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 3, 105, 1155, 8, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 3, 106, 1163, 8, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 138, 1, 138, 1, 139, 1, 139, 3, 139, 1398, 8, 139, 1, 140, 1, 140, 5, 140, 1402, 8, 140, 10, 140, 12, 140, 1405, 9, 140, 1, 140, 1, 140, 1, 140, 3, 140, 1410, 8, 140, 1, 141, 1, 141, 3, 141, 1414, 8, 141, 1, 141, 1, 141, 1, 142, 1, 142, 3, 142, 1420, 8, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 3, 143, 1428, 8, 143, 1, 144, 3, 144, 1431, 8, 144, 1, 144, 1, 144, 1, 144, 3, 144, 1436, 8, 144, 1, 144, 1, 144, 1, 144, 3, 144, 1441, 8, 144, 1, 145, 1, 145, 5, 145, 1445, 8, 145, 10, 145, 12, 145, 1448, 9, 145, 1, 145, 1, 145, 1, 145, 3, 145, 1453, 8, 145, 1, 146, 1, 146, 1, 147, 1, 147, 3, 147, 1459, 8, 147, 1, 148, 1, 148, 1, 148, 1, 148, 5, 148, 1465, 8, 148, 10, 148, 12, 148, 1468, 9, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 3, 148, 1475, 8, 148, 1, 149, 1, 149, 1, 150, 1, 150, 3, 150, 1481, 8, 150, 1, 151, 1, 151, 1, 151, 1, 151, 5, 151, 1487, 8, 151, 10, 151, 12, 151, 1490, 9, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 3, 151, 1497, 8, 151, 1, 152, 1, 152, 1, 152, 3, 152, 1502, 8, 152, 1, 152, 1, 152, 3, 152, 1506, 8, 152, 1, 153, 1, 153, 1, 153, 3, 153, 1511, 8, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 3, 154, 1524, 8, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 3, 156, 1534, 8, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 158, 1, 158, 3, 158, 1542, 8, 158, 1, 158, 1, 158, 1, 158, 5, 158, 1547, 8, 158, 10, 158, 12, 158, 1550, 9, 158, 1, 158, 1, 158, 4, 158, 1554, 8, 158, 11, 158, 12, 158, 1555, 1, 158, 3, 158, 1559, 8, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 3, 159, 1609, 8, 159, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 3, 163, 1626, 8, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 3, 164, 1633, 8, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 168, 1, 168, 1, 169, 1, 169, 1, 170, 1, 170, 1, 171, 1, 171, 1, 172, 1, 172, 1, 173, 1, 173, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 176, 4, 176, 1666, 8, 176, 11, 176, 12, 176, 1667, 1, 176, 3, 176, 1671, 8, 176, 1, 177, 1, 177, 3, 177, 1675, 8, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 3, 179, 1683, 8, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 4, 180, 1692, 8, 180, 11, 180, 12, 180, 1693, 1, 181, 1, 181, 1, 182, 4, 182, 1699, 8, 182, 11, 182, 12, 182, 1700, 1, 182, 3, 182, 1704, 8, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 190, 1, 190, 1, 190, 1, 190, 1, 191, 1, 191, 1, 191, 1, 191, 1, 192, 1, 192, 1, 192, 1, 192, 1, 193, 1, 193, 1, 193, 1, 193, 1, 194, 1, 194, 1, 194, 1, 194, 1, 195, 1, 195, 1, 195, 1, 195, 1, 196, 1, 196, 1, 196, 1, 196, 1, 197, 1, 197, 1, 197, 1, 197, 1, 198, 1, 198, 1, 198, 1, 198, 1, 199, 1, 199, 1, 199, 1, 199, 1, 200, 1, 200, 1, 200, 1, 200, 1, 201, 1, 201, 1, 201, 3, 201, 1788, 8, 201, 1, 201, 1, 201, 1, 202, 1, 202, 1, 202, 1, 202, 1, 203, 1, 203, 1, 203, 1, 203, 1, 204, 1, 204, 1, 204, 1, 204, 1, 205, 1, 205, 1, 205, 1, 205, 1, 206, 1, 206, 1, 206, 1, 206, 1, 207, 1, 207, 1, 207, 1, 207, 1, 208, 1, 208, 1, 208, 1, 208, 1, 209, 1, 209, 1, 209, 1, 209, 1, 210, 1, 210, 1, 210, 1, 210, 1, 211, 1, 211, 1, 211, 1, 211, 1, 212, 1, 212, 1, 212, 1, 212, 1, 213, 1, 213, 1, 213, 1, 213, 1, 214, 1, 214, 1, 214, 1, 214, 1, 215, 1, 215, 1, 215, 1, 215, 1, 216, 1, 216, 1, 216, 1, 216, 1, 217, 1, 217, 1, 217, 1, 217, 1, 218, 1, 218, 1, 218, 1, 218, 1, 219, 1, 219, 1, 219, 1, 219, 1, 220, 1, 220, 1, 220, 1, 220, 1, 221, 1, 221, 1, 221, 1, 221, 1, 222, 1, 222, 1, 222, 1, 222, 1, 223, 1, 223, 1, 223, 3, 223, 1879, 8, 223, 1, 223, 1, 223, 1, 224, 1, 224, 1, 224, 1, 224, 1, 225, 1, 225, 1, 225, 1, 225, 1, 226, 1, 226, 1, 226, 1, 226, 1, 227, 1, 227, 1, 227, 1, 227, 1, 228, 1, 228, 1, 228, 1, 228, 1, 229, 1, 229, 1, 229, 1, 229, 1, 230, 1, 230, 1, 230, 1, 230, 1, 231, 1, 231, 1, 231, 1, 231, 1, 232, 1, 232, 1, 232, 1, 232, 1, 233, 1, 233, 1, 233, 1, 233, 1, 234, 1, 234, 1, 234, 1, 234, 1, 235, 1, 235, 1, 235, 1, 235, 1, 236, 1, 236, 1, 236, 1, 236, 1, 237, 1, 237, 1, 237, 1, 237, 1, 238, 1, 238, 1, 238, 1, 238, 1, 239, 1, 239, 1, 239, 1, 239, 1, 240, 1, 240, 1, 240, 1, 240, 1, 240, 1, 241, 1, 241, 1, 241, 1, 241, 1, 241, 1, 242, 1, 242, 1, 242, 1, 242, 1, 243, 1, 243, 1, 243, 1, 243, 1, 244, 1, 244, 1, 244, 1, 244, 1, 245, 1, 245, 1, 245, 1, 245, 1, 246, 1, 246, 1, 246, 1, 246, 1, 247, 1, 247, 1, 247, 1, 247, 1, 248, 1, 248, 1, 248, 1, 248, 1, 249, 1, 249, 1, 249, 1, 249, 1, 250, 1, 250, 1, 250, 1, 250, 1, 251, 1, 251, 1, 251, 1, 251, 1, 252, 1, 252, 1, 252, 1, 252, 1, 253, 1, 253, 1, 253, 1, 253, 1, 254, 1, 254, 1, 254, 1, 254, 1, 255, 1, 255, 1, 255, 1, 255, 1, 256, 1, 256, 1, 256, 1, 256, 1, 257, 1, 257, 1, 257, 1, 257, 1, 258, 1, 258, 1, 258, 1, 258, 1, 259, 1, 259, 1, 259, 1, 259, 1, 260, 1, 260, 1, 260, 1, 260, 1, 261, 1, 261, 1, 261, 1, 261, 1, 262, 1, 262, 1, 262, 1, 262, 1, 263, 1, 263, 1, 263, 1, 263, 1, 264, 1, 264, 1, 264, 1, 264, 1, 265, 1, 265, 1, 265, 1, 265, 1, 266, 1, 266, 1, 266, 1, 266, 1, 267, 1, 267, 1, 267, 1, 267, 1, 268, 1, 268, 1, 268, 1, 268, 1, 269, 1, 269, 1, 269, 1, 269, 1, 270, 1, 270, 1, 270, 1, 270, 1, 271, 1, 271, 1, 271, 1, 271, 1, 272, 1, 272, 1, 272, 1, 272, 1, 273, 1, 273, 1, 273, 1, 273, 1, 274, 1, 274, 1, 274, 1, 274, 1, 275, 1, 275, 1, 275, 1, 275, 1, 276, 1, 276, 1, 276, 1, 276, 1, 277, 1, 277, 1, 277, 1, 277, 1, 278, 1, 278, 1, 278, 1, 278, 1, 279, 1, 279, 1, 279, 1, 279, 1, 280, 1, 280, 1, 280, 1, 280, 1, 281, 1, 281, 1, 281, 1, 281, 1, 282, 1, 282, 1, 282, 1, 282, 1, 283, 1, 283, 1, 283, 1, 283, 1, 284, 1, 284, 1, 284, 1, 284, 1, 285, 1, 285, 1, 285, 1, 285, 1, 286, 1, 286, 1, 286, 1, 286, 1, 287, 1, 287, 1, 287, 1, 287, 1, 288, 1, 288, 1, 288, 1, 288, 1, 289, 1, 289, 1, 289, 1, 289, 1, 290, 1, 290, 1, 290, 1, 290, 1, 291, 1, 291, 1, 291, 1, 291, 1, 292, 1, 292, 1, 292, 1, 292, 1, 293, 1, 293, 1, 293, 1, 293, 1, 294, 1, 294, 1, 294, 1, 294, 1, 295, 1, 295, 1, 295, 1, 295, 1, 296, 1, 296, 1, 296, 1, 296, 1, 297, 1, 297, 1, 297, 1, 297, 1, 298, 1, 298, 1, 298, 1, 298, 1, 299, 1, 299, 1, 299, 1, 299, 1, 300, 1, 300, 1, 300, 1, 300, 1, 301, 1, 301, 1, 301, 1, 301, 1, 302, 1, 302, 1, 302, 1, 302, 1, 303, 1, 303, 1, 303, 1, 303, 1, 304, 1, 304, 1, 304, 1, 304, 1, 305, 1, 305, 1, 305, 1, 305, 1, 306, 1, 306, 1, 306, 1, 306, 1, 307, 1, 307, 1, 307, 1, 307, 1, 308, 1, 308, 1, 308, 1, 308, 1, 309, 1, 309, 1, 309, 1, 309, 1, 310, 1, 310, 1, 310, 1, 310, 1, 311, 1, 311, 1, 311, 1, 311, 1, 312, 1, 312, 3, 312, 2239, 8, 312, 1, 312, 1, 312, 1, 313, 1, 313, 1, 313, 1, 313, 1, 314, 1, 314, 1, 314, 1, 314, 1, 315, 1, 315, 1, 653, 0, 316, 5, 1, 7, 2, 9, 3, 11, 4, 13, 5, 15, 0, 17, 6, 19, 7, 21, 8, 23, 9, 25, 10, 27, 11, 29, 12, 31, 13, 33, 14, 35, 15, 37, 16, 39, 17, 41, 18, 43, 19, 45, 20, 47, 21, 49, 22, 51, 23, 53, 24, 55, 25, 57, 26, 59, 27, 61, 28, 63, 29, 65, 30, 67, 31, 69, 32, 71, 33, 73, 34, 75, 35, 77, 36, 79, 37, 81, 38, 83, 39, 85, 40, 87, 41, 89, 42, 91, 43, 93, 44, 95, 45, 97, 46, 99, 47, 101, 48, 103, 49, 105, 50, 107, 51, 109, 52, 111, 53, 113, 54, 115, 55, 117, 56, 119, 57, 121, 58, 123, 59, 125, 60, 127, 61, 129, 62, 131, 63, 133, 64, 135, 65, 137, 66, 139, 67, 141, 68, 143, 69, 145, 70, 147, 71, 149, 72, 151, 73, 153, 74, 155, 75, 157, 76, 159, 77, 161, 78, 163, 79, 165, 80, 167, 81, 169, 82, 171, 83, 173, 84, 175, 85, 177, 86, 179, 87, 181, 88, 183, 89, 185, 90, 187, 91, 189, 92, 191, 93, 193, 94, 195, 95, 197, 96, 199, 97, 201, 98, 203, 99, 205, 100, 207, 101, 209, 102, 211, 103, 213, 104, 215, 105, 217, 106, 219, 107, 221, 108, 223, 109, 225, 110, 227, 111, 229, 112, 231, 113, 233, 114, 235, 115, 237, 116, 239, 117, 241, 118, 243, 119, 245, 120, 247, 121, 249, 122, 251, 123, 253, 124, 255, 125, 257, 126, 259, 127, 261, 128, 263, 129, 265, 130, 267, 131, 269, 132, 271, 133, 273, 134, 275, 135, 277, 136, 279, 0, 281, 0, 283, 0, 285, 0, 287, 0, 289, 137, 291, 138, 293, 139, 295, 140, 297, 0, 299, 0, 301, 141, 303, 0, 305, 0, 307, 142, 309, 143, 311, 144, 313, 145, 315, 146, 317, 147, 319, 0, 321, 148, 323, 149, 325, 150, 327, 0, 329, 0, 331, 0, 333, 0, 335, 151, 337, 152, 339, 153, 341, 154, 343, 155, 345, 156, 347, 157, 349, 158, 351, 159, 353, 160, 355, 161, 357, 162, 359, 163, 361, 164, 363, 165, 365, 166, 367, 167, 369, 168, 371, 169, 373, 0, 375, 0, 377, 0, 379, 0, 381, 0, 383, 0, 385, 0, 387, 0, 389, 0, 391, 0, 393, 0, 395, 0, 397, 0, 399, 0, 401, 0, 403, 0, 405, 0, 407, 0, 409, 0, 411, 0, 413, 0, 415, 0, 417, 0, 419, 0, 421, 0, 423, 0, 425, 0, 427, 0, 429, 0, 431, 0, 433, 0, 435, 0, 437, 0, 439, 0, 441, 0, 443, 0, 445, 0, 447, 0, 449, 0, 451, 0, 453, 0, 455, 0, 457, 0, 459, 0, 461, 0, 463, 0, 465, 0, 467, 0, 469, 0, 471, 0, 473, 0, 475, 0, 477, 0, 479, 0, 481, 0, 483, 0, 485, 0, 487, 0, 489, 0, 491, 0, 493, 0, 495, 0, 497, 0, 499, 0, 501, 0, 503, 0, 505, 0, 507, 0, 509, 0, 511, 0, 513, 0, 515, 0, 517, 0, 519, 0, 521, 0, 523, 0, 525, 0, 527, 0, 529, 0, 531, 0, 533, 0, 535, 0, 537, 0, 539, 0, 541, 0, 543, 0, 545, 0, 547, 0, 549, 0, 551, 0, 553, 0, 555, 0, 557, 0, 559, 0, 561, 0, 563, 0, 565, 0, 567, 0, 569, 0, 571, 0, 573, 0, 575, 0, 577, 0, 579, 0, 581, 0, 583, 0, 585, 0, 587, 0, 589, 0, 591, 0, 593, 0, 595, 0, 597, 0, 599, 0, 601, 0, 603, 0, 605, 0, 607, 0, 609, 0, 611, 0, 613, 0, 615, 0, 617, 0, 619, 0, 621, 0, 623, 0, 625, 0, 627, 0, 629, 170, 631, 171, 633, 172, 635, 173, 5, 0, 1, 2, 3, 4, 23, 2, 0, 10, 10, 13, 13, 3, 0, 9, 9, 12, 12, 32, 32, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 70, 70, 102, 102, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 88, 88, 120, 120, 1, 0, 48, 49, 2, 0, 66, 66, 98, 98, 2, 0, 85, 85, 117, 117, 2, 0, 76, 76, 108, 108, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 3, 0, 10, 10, 13, 13, 96, 96, 8, 0, 34, 34, 36, 36, 39, 39, 92, 92, 98, 98, 110, 110, 114, 114, 116, 116, 582, 0, 97, 122, 181, 181, 223, 246, 248, 255, 257, 257, 259, 259, 261, 261, 263, 263, 265, 265, 267, 267, 269, 269, 271, 271, 273, 273, 275, 275, 277, 277, 279, 279, 281, 281, 283, 283, 285, 285, 287, 287, 289, 289, 291, 291, 293, 293, 295, 295, 297, 297, 299, 299, 301, 301, 303, 303, 305, 305, 307, 307, 309, 309, 311, 312, 314, 314, 316, 316, 318, 318, 320, 320, 322, 322, 324, 324, 326, 326, 328, 329, 331, 331, 333, 333, 335, 335, 337, 337, 339, 339, 341, 341, 343, 343, 345, 345, 347, 347, 349, 349, 351, 351, 353, 353, 355, 355, 357, 357, 359, 359, 361, 361, 363, 363, 365, 365, 367, 367, 369, 369, 371, 371, 373, 373, 375, 375, 378, 378, 380, 380, 382, 384, 387, 387, 389, 389, 392, 392, 396, 397, 402, 402, 405, 405, 409, 411, 414, 414, 417, 417, 419, 419, 421, 421, 424, 424, 426, 427, 429, 429, 432, 432, 436, 436, 438, 438, 441, 442, 445, 447, 454, 454, 457, 457, 460, 460, 462, 462, 464, 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, 476, 477, 479, 479, 481, 481, 483, 483, 485, 485, 487, 487, 489, 489, 491, 491, 493, 493, 495, 496, 499, 499, 501, 501, 505, 505, 507, 507, 509, 509, 511, 511, 513, 513, 515, 515, 517, 517, 519, 519, 521, 521, 523, 523, 525, 525, 527, 527, 529, 529, 531, 531, 533, 533, 535, 535, 537, 537, 539, 539, 541, 541, 543, 543, 545, 545, 547, 547, 549, 549, 551, 551, 553, 553, 555, 555, 557, 557, 559, 559, 561, 561, 563, 569, 572, 572, 575, 576, 578, 578, 583, 583, 585, 585, 587, 587, 589, 589, 591, 659, 661, 687, 881, 881, 883, 883, 887, 887, 891, 893, 912, 912, 940, 974, 976, 977, 981, 983, 985, 985, 987, 987, 989, 989, 991, 991, 993, 993, 995, 995, 997, 997, 999, 999, 1001, 1001, 1003, 1003, 1005, 1005, 1007, 1011, 1013, 1013, 1016, 1016, 1019, 1020, 1072, 1119, 1121, 1121, 1123, 1123, 1125, 1125, 1127, 1127, 1129, 1129, 1131, 1131, 1133, 1133, 1135, 1135, 1137, 1137, 1139, 1139, 1141, 1141, 1143, 1143, 1145, 1145, 1147, 1147, 1149, 1149, 1151, 1151, 1153, 1153, 1163, 1163, 1165, 1165, 1167, 1167, 1169, 1169, 1171, 1171, 1173, 1173, 1175, 1175, 1177, 1177, 1179, 1179, 1181, 1181, 1183, 1183, 1185, 1185, 1187, 1187, 1189, 1189, 1191, 1191, 1193, 1193, 1195, 1195, 1197, 1197, 1199, 1199, 1201, 1201, 1203, 1203, 1205, 1205, 1207, 1207, 1209, 1209, 1211, 1211, 1213, 1213, 1215, 1215, 1218, 1218, 1220, 1220, 1222, 1222, 1224, 1224, 1226, 1226, 1228, 1228, 1230, 1231, 1233, 1233, 1235, 1235, 1237, 1237, 1239, 1239, 1241, 1241, 1243, 1243, 1245, 1245, 1247, 1247, 1249, 1249, 1251, 1251, 1253, 1253, 1255, 1255, 1257, 1257, 1259, 1259, 1261, 1261, 1263, 1263, 1265, 1265, 1267, 1267, 1269, 1269, 1271, 1271, 1273, 1273, 1275, 1275, 1277, 1277, 1279, 1279, 1281, 1281, 1283, 1283, 1285, 1285, 1287, 1287, 1289, 1289, 1291, 1291, 1293, 1293, 1295, 1295, 1297, 1297, 1299, 1299, 1301, 1301, 1303, 1303, 1305, 1305, 1307, 1307, 1309, 1309, 1311, 1311, 1313, 1313, 1315, 1315, 1317, 1317, 1319, 1319, 1377, 1415, 7424, 7467, 7531, 7543, 7545, 7578, 7681, 7681, 7683, 7683, 7685, 7685, 7687, 7687, 7689, 7689, 7691, 7691, 7693, 7693, 7695, 7695, 7697, 7697, 7699, 7699, 7701, 7701, 7703, 7703, 7705, 7705, 7707, 7707, 7709, 7709, 7711, 7711, 7713, 7713, 7715, 7715, 7717, 7717, 7719, 7719, 7721, 7721, 7723, 7723, 7725, 7725, 7727, 7727, 7729, 7729, 7731, 7731, 7733, 7733, 7735, 7735, 7737, 7737, 7739, 7739, 7741, 7741, 7743, 7743, 7745, 7745, 7747, 7747, 7749, 7749, 7751, 7751, 7753, 7753, 7755, 7755, 7757, 7757, 7759, 7759, 7761, 7761, 7763, 7763, 7765, 7765, 7767, 7767, 7769, 7769, 7771, 7771, 7773, 7773, 7775, 7775, 7777, 7777, 7779, 7779, 7781, 7781, 7783, 7783, 7785, 7785, 7787, 7787, 7789, 7789, 7791, 7791, 7793, 7793, 7795, 7795, 7797, 7797, 7799, 7799, 7801, 7801, 7803, 7803, 7805, 7805, 7807, 7807, 7809, 7809, 7811, 7811, 7813, 7813, 7815, 7815, 7817, 7817, 7819, 7819, 7821, 7821, 7823, 7823, 7825, 7825, 7827, 7827, 7829, 7837, 7839, 7839, 7841, 7841, 7843, 7843, 7845, 7845, 7847, 7847, 7849, 7849, 7851, 7851, 7853, 7853, 7855, 7855, 7857, 7857, 7859, 7859, 7861, 7861, 7863, 7863, 7865, 7865, 7867, 7867, 7869, 7869, 7871, 7871, 7873, 7873, 7875, 7875, 7877, 7877, 7879, 7879, 7881, 7881, 7883, 7883, 7885, 7885, 7887, 7887, 7889, 7889, 7891, 7891, 7893, 7893, 7895, 7895, 7897, 7897, 7899, 7899, 7901, 7901, 7903, 7903, 7905, 7905, 7907, 7907, 7909, 7909, 7911, 7911, 7913, 7913, 7915, 7915, 7917, 7917, 7919, 7919, 7921, 7921, 7923, 7923, 7925, 7925, 7927, 7927, 7929, 7929, 7931, 7931, 7933, 7933, 7935, 7943, 7952, 7957, 7968, 7975, 7984, 7991, 8000, 8005, 8016, 8023, 8032, 8039, 8048, 8061, 8064, 8071, 8080, 8087, 8096, 8103, 8112, 8116, 8118, 8119, 8126, 8126, 8130, 8132, 8134, 8135, 8144, 8147, 8150, 8151, 8160, 8167, 8178, 8180, 8182, 8183, 8458, 8458, 8462, 8463, 8467, 8467, 8495, 8495, 8500, 8500, 8505, 8505, 8508, 8509, 8518, 8521, 8526, 8526, 8580, 8580, 11312, 11358, 11361, 11361, 11365, 11366, 11368, 11368, 11370, 11370, 11372, 11372, 11377, 11377, 11379, 11380, 11382, 11387, 11393, 11393, 11395, 11395, 11397, 11397, 11399, 11399, 11401, 11401, 11403, 11403, 11405, 11405, 11407, 11407, 11409, 11409, 11411, 11411, 11413, 11413, 11415, 11415, 11417, 11417, 11419, 11419, 11421, 11421, 11423, 11423, 11425, 11425, 11427, 11427, 11429, 11429, 11431, 11431, 11433, 11433, 11435, 11435, 11437, 11437, 11439, 11439, 11441, 11441, 11443, 11443, 11445, 11445, 11447, 11447, 11449, 11449, 11451, 11451, 11453, 11453, 11455, 11455, 11457, 11457, 11459, 11459, 11461, 11461, 11463, 11463, 11465, 11465, 11467, 11467, 11469, 11469, 11471, 11471, 11473, 11473, 11475, 11475, 11477, 11477, 11479, 11479, 11481, 11481, 11483, 11483, 11485, 11485, 11487, 11487, 11489, 11489, 11491, 11492, 11500, 11500, 11502, 11502, 11507, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 42561, 42561, 42563, 42563, 42565, 42565, 42567, 42567, 42569, 42569, 42571, 42571, 42573, 42573, 42575, 42575, 42577, 42577, 42579, 42579, 42581, 42581, 42583, 42583, 42585, 42585, 42587, 42587, 42589, 42589, 42591, 42591, 42593, 42593, 42595, 42595, 42597, 42597, 42599, 42599, 42601, 42601, 42603, 42603, 42605, 42605, 42625, 42625, 42627, 42627, 42629, 42629, 42631, 42631, 42633, 42633, 42635, 42635, 42637, 42637, 42639, 42639, 42641, 42641, 42643, 42643, 42645, 42645, 42647, 42647, 42787, 42787, 42789, 42789, 42791, 42791, 42793, 42793, 42795, 42795, 42797, 42797, 42799, 42801, 42803, 42803, 42805, 42805, 42807, 42807, 42809, 42809, 42811, 42811, 42813, 42813, 42815, 42815, 42817, 42817, 42819, 42819, 42821, 42821, 42823, 42823, 42825, 42825, 42827, 42827, 42829, 42829, 42831, 42831, 42833, 42833, 42835, 42835, 42837, 42837, 42839, 42839, 42841, 42841, 42843, 42843, 42845, 42845, 42847, 42847, 42849, 42849, 42851, 42851, 42853, 42853, 42855, 42855, 42857, 42857, 42859, 42859, 42861, 42861, 42863, 42863, 42865, 42872, 42874, 42874, 42876, 42876, 42879, 42879, 42881, 42881, 42883, 42883, 42885, 42885, 42887, 42887, 42892, 42892, 42894, 42894, 42897, 42897, 42899, 42899, 42913, 42913, 42915, 42915, 42917, 42917, 42919, 42919, 42921, 42921, 43002, 43002, 64256, 64262, 64275, 64279, 65345, 65370, 51, 0, 688, 705, 710, 721, 736, 740, 748, 748, 750, 750, 884, 884, 890, 890, 1369, 1369, 1600, 1600, 1765, 1766, 2036, 2037, 2042, 2042, 2074, 2074, 2084, 2084, 2088, 2088, 2417, 2417, 3654, 3654, 3782, 3782, 4348, 4348, 6103, 6103, 6211, 6211, 6823, 6823, 7288, 7293, 7468, 7530, 7544, 7544, 7579, 7615, 8305, 8305, 8319, 8319, 8336, 8348, 11388, 11389, 11631, 11631, 11823, 11823, 12293, 12293, 12337, 12341, 12347, 12347, 12445, 12446, 12540, 12542, 40981, 40981, 42232, 42237, 42508, 42508, 42623, 42623, 42775, 42783, 42864, 42864, 42888, 42888, 43000, 43001, 43471, 43471, 43632, 43632, 43741, 43741, 43763, 43764, 65392, 65392, 65438, 65439, 289, 0, 170, 170, 186, 186, 443, 443, 448, 451, 660, 660, 1488, 1514, 1520, 1522, 1568, 1599, 1601, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2048, 2069, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2418, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3653, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4304, 4346, 4349, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6108, 6108, 6176, 6210, 6212, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7287, 7401, 7404, 7406, 7409, 7413, 7414, 8501, 8504, 11568, 11623, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 12294, 12294, 12348, 12348, 12353, 12438, 12447, 12447, 12449, 12538, 12543, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312, 19893, 19893, 19968, 19968, 40908, 40908, 40960, 40980, 40982, 42124, 42192, 42231, 42240, 42507, 42512, 42527, 42538, 42539, 42606, 42606, 42656, 42725, 43003, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43631, 43633, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43740, 43744, 43754, 43762, 43762, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032, 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65382, 65391, 65393, 65437, 65440, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, 10, 0, 453, 453, 456, 456, 459, 459, 498, 498, 8072, 8079, 8088, 8095, 8104, 8111, 8124, 8124, 8140, 8140, 8188, 8188, 576, 0, 65, 90, 192, 214, 216, 222, 256, 256, 258, 258, 260, 260, 262, 262, 264, 264, 266, 266, 268, 268, 270, 270, 272, 272, 274, 274, 276, 276, 278, 278, 280, 280, 282, 282, 284, 284, 286, 286, 288, 288, 290, 290, 292, 292, 294, 294, 296, 296, 298, 298, 300, 300, 302, 302, 304, 304, 306, 306, 308, 308, 310, 310, 313, 313, 315, 315, 317, 317, 319, 319, 321, 321, 323, 323, 325, 325, 327, 327, 330, 330, 332, 332, 334, 334, 336, 336, 338, 338, 340, 340, 342, 342, 344, 344, 346, 346, 348, 348, 350, 350, 352, 352, 354, 354, 356, 356, 358, 358, 360, 360, 362, 362, 364, 364, 366, 366, 368, 368, 370, 370, 372, 372, 374, 374, 376, 377, 379, 379, 381, 381, 385, 386, 388, 388, 390, 391, 393, 395, 398, 401, 403, 404, 406, 408, 412, 413, 415, 416, 418, 418, 420, 420, 422, 423, 425, 425, 428, 428, 430, 431, 433, 435, 437, 437, 439, 440, 444, 444, 452, 452, 455, 455, 458, 458, 461, 461, 463, 463, 465, 465, 467, 467, 469, 469, 471, 471, 473, 473, 475, 475, 478, 478, 480, 480, 482, 482, 484, 484, 486, 486, 488, 488, 490, 490, 492, 492, 494, 494, 497, 497, 500, 500, 502, 504, 506, 506, 508, 508, 510, 510, 512, 512, 514, 514, 516, 516, 518, 518, 520, 520, 522, 522, 524, 524, 526, 526, 528, 528, 530, 530, 532, 532, 534, 534, 536, 536, 538, 538, 540, 540, 542, 542, 544, 544, 546, 546, 548, 548, 550, 550, 552, 552, 554, 554, 556, 556, 558, 558, 560, 560, 562, 562, 570, 571, 573, 574, 577, 577, 579, 582, 584, 584, 586, 586, 588, 588, 590, 590, 880, 880, 882, 882, 886, 886, 902, 902, 904, 906, 908, 908, 910, 911, 913, 929, 931, 939, 975, 975, 978, 980, 984, 984, 986, 986, 988, 988, 990, 990, 992, 992, 994, 994, 996, 996, 998, 998, 1000, 1000, 1002, 1002, 1004, 1004, 1006, 1006, 1012, 1012, 1015, 1015, 1017, 1018, 1021, 1071, 1120, 1120, 1122, 1122, 1124, 1124, 1126, 1126, 1128, 1128, 1130, 1130, 1132, 1132, 1134, 1134, 1136, 1136, 1138, 1138, 1140, 1140, 1142, 1142, 1144, 1144, 1146, 1146, 1148, 1148, 1150, 1150, 1152, 1152, 1162, 1162, 1164, 1164, 1166, 1166, 1168, 1168, 1170, 1170, 1172, 1172, 1174, 1174, 1176, 1176, 1178, 1178, 1180, 1180, 1182, 1182, 1184, 1184, 1186, 1186, 1188, 1188, 1190, 1190, 1192, 1192, 1194, 1194, 1196, 1196, 1198, 1198, 1200, 1200, 1202, 1202, 1204, 1204, 1206, 1206, 1208, 1208, 1210, 1210, 1212, 1212, 1214, 1214, 1216, 1217, 1219, 1219, 1221, 1221, 1223, 1223, 1225, 1225, 1227, 1227, 1229, 1229, 1232, 1232, 1234, 1234, 1236, 1236, 1238, 1238, 1240, 1240, 1242, 1242, 1244, 1244, 1246, 1246, 1248, 1248, 1250, 1250, 1252, 1252, 1254, 1254, 1256, 1256, 1258, 1258, 1260, 1260, 1262, 1262, 1264, 1264, 1266, 1266, 1268, 1268, 1270, 1270, 1272, 1272, 1274, 1274, 1276, 1276, 1278, 1278, 1280, 1280, 1282, 1282, 1284, 1284, 1286, 1286, 1288, 1288, 1290, 1290, 1292, 1292, 1294, 1294, 1296, 1296, 1298, 1298, 1300, 1300, 1302, 1302, 1304, 1304, 1306, 1306, 1308, 1308, 1310, 1310, 1312, 1312, 1314, 1314, 1316, 1316, 1318, 1318, 1329, 1366, 4256, 4293, 4295, 4295, 4301, 4301, 7680, 7680, 7682, 7682, 7684, 7684, 7686, 7686, 7688, 7688, 7690, 7690, 7692, 7692, 7694, 7694, 7696, 7696, 7698, 7698, 7700, 7700, 7702, 7702, 7704, 7704, 7706, 7706, 7708, 7708, 7710, 7710, 7712, 7712, 7714, 7714, 7716, 7716, 7718, 7718, 7720, 7720, 7722, 7722, 7724, 7724, 7726, 7726, 7728, 7728, 7730, 7730, 7732, 7732, 7734, 7734, 7736, 7736, 7738, 7738, 7740, 7740, 7742, 7742, 7744, 7744, 7746, 7746, 7748, 7748, 7750, 7750, 7752, 7752, 7754, 7754, 7756, 7756, 7758, 7758, 7760, 7760, 7762, 7762, 7764, 7764, 7766, 7766, 7768, 7768, 7770, 7770, 7772, 7772, 7774, 7774, 7776, 7776, 7778, 7778, 7780, 7780, 7782, 7782, 7784, 7784, 7786, 7786, 7788, 7788, 7790, 7790, 7792, 7792, 7794, 7794, 7796, 7796, 7798, 7798, 7800, 7800, 7802, 7802, 7804, 7804, 7806, 7806, 7808, 7808, 7810, 7810, 7812, 7812, 7814, 7814, 7816, 7816, 7818, 7818, 7820, 7820, 7822, 7822, 7824, 7824, 7826, 7826, 7828, 7828, 7838, 7838, 7840, 7840, 7842, 7842, 7844, 7844, 7846, 7846, 7848, 7848, 7850, 7850, 7852, 7852, 7854, 7854, 7856, 7856, 7858, 7858, 7860, 7860, 7862, 7862, 7864, 7864, 7866, 7866, 7868, 7868, 7870, 7870, 7872, 7872, 7874, 7874, 7876, 7876, 7878, 7878, 7880, 7880, 7882, 7882, 7884, 7884, 7886, 7886, 7888, 7888, 7890, 7890, 7892, 7892, 7894, 7894, 7896, 7896, 7898, 7898, 7900, 7900, 7902, 7902, 7904, 7904, 7906, 7906, 7908, 7908, 7910, 7910, 7912, 7912, 7914, 7914, 7916, 7916, 7918, 7918, 7920, 7920, 7922, 7922, 7924, 7924, 7926, 7926, 7928, 7928, 7930, 7930, 7932, 7932, 7934, 7934, 7944, 7951, 7960, 7965, 7976, 7983, 7992, 7999, 8008, 8013, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8031, 8040, 8047, 8120, 8123, 8136, 8139, 8152, 8155, 8168, 8172, 8184, 8187, 8450, 8450, 8455, 8455, 8459, 8461, 8464, 8466, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8496, 8499, 8510, 8511, 8517, 8517, 8579, 8579, 11264, 11310, 11360, 11360, 11362, 11364, 11367, 11367, 11369, 11369, 11371, 11371, 11373, 11376, 11378, 11378, 11381, 11381, 11390, 11392, 11394, 11394, 11396, 11396, 11398, 11398, 11400, 11400, 11402, 11402, 11404, 11404, 11406, 11406, 11408, 11408, 11410, 11410, 11412, 11412, 11414, 11414, 11416, 11416, 11418, 11418, 11420, 11420, 11422, 11422, 11424, 11424, 11426, 11426, 11428, 11428, 11430, 11430, 11432, 11432, 11434, 11434, 11436, 11436, 11438, 11438, 11440, 11440, 11442, 11442, 11444, 11444, 11446, 11446, 11448, 11448, 11450, 11450, 11452, 11452, 11454, 11454, 11456, 11456, 11458, 11458, 11460, 11460, 11462, 11462, 11464, 11464, 11466, 11466, 11468, 11468, 11470, 11470, 11472, 11472, 11474, 11474, 11476, 11476, 11478, 11478, 11480, 11480, 11482, 11482, 11484, 11484, 11486, 11486, 11488, 11488, 11490, 11490, 11499, 11499, 11501, 11501, 11506, 11506, 42560, 42560, 42562, 42562, 42564, 42564, 42566, 42566, 42568, 42568, 42570, 42570, 42572, 42572, 42574, 42574, 42576, 42576, 42578, 42578, 42580, 42580, 42582, 42582, 42584, 42584, 42586, 42586, 42588, 42588, 42590, 42590, 42592, 42592, 42594, 42594, 42596, 42596, 42598, 42598, 42600, 42600, 42602, 42602, 42604, 42604, 42624, 42624, 42626, 42626, 42628, 42628, 42630, 42630, 42632, 42632, 42634, 42634, 42636, 42636, 42638, 42638, 42640, 42640, 42642, 42642, 42644, 42644, 42646, 42646, 42786, 42786, 42788, 42788, 42790, 42790, 42792, 42792, 42794, 42794, 42796, 42796, 42798, 42798, 42802, 42802, 42804, 42804, 42806, 42806, 42808, 42808, 42810, 42810, 42812, 42812, 42814, 42814, 42816, 42816, 42818, 42818, 42820, 42820, 42822, 42822, 42824, 42824, 42826, 42826, 42828, 42828, 42830, 42830, 42832, 42832, 42834, 42834, 42836, 42836, 42838, 42838, 42840, 42840, 42842, 42842, 42844, 42844, 42846, 42846, 42848, 42848, 42850, 42850, 42852, 42852, 42854, 42854, 42856, 42856, 42858, 42858, 42860, 42860, 42862, 42862, 42873, 42873, 42875, 42875, 42877, 42878, 42880, 42880, 42882, 42882, 42884, 42884, 42886, 42886, 42891, 42891, 42893, 42893, 42896, 42896, 42898, 42898, 42912, 42912, 42914, 42914, 42916, 42916, 42918, 42918, 42920, 42920, 42922, 42922, 65313, 65338, 35, 0, 48, 57, 1632, 1641, 1776, 1785, 1984, 1993, 2406, 2415, 2534, 2543, 2662, 2671, 2790, 2799, 2918, 2927, 3046, 3055, 3174, 3183, 3302, 3311, 3430, 3439, 3664, 3673, 3792, 3801, 3872, 3881, 4160, 4169, 4240, 4249, 6112, 6121, 6160, 6169, 6470, 6479, 6608, 6617, 6784, 6793, 6800, 6809, 6992, 7001, 7088, 7097, 7232, 7241, 7248, 7257, 42528, 42537, 43216, 43225, 43264, 43273, 43472, 43481, 43600, 43609, 44016, 44025, 65296, 65305, 7, 0, 5870, 5872, 8544, 8578, 8581, 8584, 12295, 12295, 12321, 12329, 12344, 12346, 42726, 42735, 3, 0, 34, 34, 36, 36, 92, 92, 2, 0, 34, 34, 36, 36, 2338, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, 0, 0, 0, 0, 169, 1, 0, 0, 0, 0, 171, 1, 0, 0, 0, 0, 173, 1, 0, 0, 0, 0, 175, 1, 0, 0, 0, 0, 177, 1, 0, 0, 0, 0, 179, 1, 0, 0, 0, 0, 181, 1, 0, 0, 0, 0, 183, 1, 0, 0, 0, 0, 185, 1, 0, 0, 0, 0, 187, 1, 0, 0, 0, 0, 189, 1, 0, 0, 0, 0, 191, 1, 0, 0, 0, 0, 193, 1, 0, 0, 0, 0, 195, 1, 0, 0, 0, 0, 197, 1, 0, 0, 0, 0, 199, 1, 0, 0, 0, 0, 201, 1, 0, 0, 0, 0, 203, 1, 0, 0, 0, 0, 205, 1, 0, 0, 0, 0, 207, 1, 0, 0, 0, 0, 209, 1, 0, 0, 0, 0, 211, 1, 0, 0, 0, 0, 213, 1, 0, 0, 0, 0, 215, 1, 0, 0, 0, 0, 217, 1, 0, 0, 0, 0, 219, 1, 0, 0, 0, 0, 221, 1, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 225, 1, 0, 0, 0, 0, 227, 1, 0, 0, 0, 0, 229, 1, 0, 0, 0, 0, 231, 1, 0, 0, 0, 0, 233, 1, 0, 0, 0, 0, 235, 1, 0, 0, 0, 0, 237, 1, 0, 0, 0, 0, 239, 1, 0, 0, 0, 0, 241, 1, 0, 0, 0, 0, 243, 1, 0, 0, 0, 0, 245, 1, 0, 0, 0, 0, 247, 1, 0, 0, 0, 0, 249, 1, 0, 0, 0, 0, 251, 1, 0, 0, 0, 0, 253, 1, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 257, 1, 0, 0, 0, 0, 259, 1, 0, 0, 0, 0, 261, 1, 0, 0, 0, 0, 263, 1, 0, 0, 0, 0, 265, 1, 0, 0, 0, 0, 267, 1, 0, 0, 0, 0, 269, 1, 0, 0, 0, 0, 271, 1, 0, 0, 0, 0, 273, 1, 0, 0, 0, 0, 275, 1, 0, 0, 0, 0, 277, 1, 0, 0, 0, 0, 289, 1, 0, 0, 0, 0, 291, 1, 0, 0, 0, 0, 293, 1, 0, 0, 0, 0, 295, 1, 0, 0, 0, 0, 301, 1, 0, 0, 0, 0, 307, 1, 0, 0, 0, 0, 309, 1, 0, 0, 0, 0, 311, 1, 0, 0, 0, 0, 313, 1, 0, 0, 0, 0, 315, 1, 0, 0, 0, 0, 317, 1, 0, 0, 0, 0, 321, 1, 0, 0, 0, 0, 323, 1, 0, 0, 0, 0, 325, 1, 0, 0, 0, 0, 335, 1, 0, 0, 0, 0, 337, 1, 0, 0, 0, 0, 339, 1, 0, 0, 0, 0, 341, 1, 0, 0, 0, 0, 343, 1, 0, 0, 0, 0, 345, 1, 0, 0, 0, 0, 347, 1, 0, 0, 0, 0, 349, 1, 0, 0, 0, 0, 351, 1, 0, 0, 0, 1, 353, 1, 0, 0, 0, 1, 355, 1, 0, 0, 0, 1, 357, 1, 0, 0, 0, 1, 359, 1, 0, 0, 0, 1, 361, 1, 0, 0, 0, 2, 363, 1, 0, 0, 0, 2, 365, 1, 0, 0, 0, 2, 367, 1, 0, 0, 0, 2, 369, 1, 0, 0, 0, 2, 371, 1, 0, 0, 0, 3, 373, 1, 0, 0, 0, 3, 375, 1, 0, 0, 0, 3, 377, 1, 0, 0, 0, 3, 379, 1, 0, 0, 0, 3, 381, 1, 0, 0, 0, 3, 383, 1, 0, 0, 0, 3, 385, 1, 0, 0, 0, 3, 387, 1, 0, 0, 0, 3, 389, 1, 0, 0, 0, 3, 391, 1, 0, 0, 0, 3, 393, 1, 0, 0, 0, 3, 395, 1, 0, 0, 0, 3, 397, 1, 0, 0, 0, 3, 399, 1, 0, 0, 0, 3, 401, 1, 0, 0, 0, 3, 403, 1, 0, 0, 0, 3, 405, 1, 0, 0, 0, 3, 407, 1, 0, 0, 0, 3, 409, 1, 0, 0, 0, 3, 411, 1, 0, 0, 0, 3, 413, 1, 0, 0, 0, 3, 415, 1, 0, 0, 0, 3, 417, 1, 0, 0, 0, 3, 419, 1, 0, 0, 0, 3, 421, 1, 0, 0, 0, 3, 423, 1, 0, 0, 0, 3, 425, 1, 0, 0, 0, 3, 427, 1, 0, 0, 0, 3, 429, 1, 0, 0, 0, 3, 431, 1, 0, 0, 0, 3, 433, 1, 0, 0, 0, 3, 435, 1, 0, 0, 0, 3, 437, 1, 0, 0, 0, 3, 439, 1, 0, 0, 0, 3, 441, 1, 0, 0, 0, 3, 443, 1, 0, 0, 0, 3, 445, 1, 0, 0, 0, 3, 447, 1, 0, 0, 0, 3, 449, 1, 0, 0, 0, 3, 451, 1, 0, 0, 0, 3, 453, 1, 0, 0, 0, 3, 455, 1, 0, 0, 0, 3, 457, 1, 0, 0, 0, 3, 459, 1, 0, 0, 0, 3, 461, 1, 0, 0, 0, 3, 463, 1, 0, 0, 0, 3, 465, 1, 0, 0, 0, 3, 467, 1, 0, 0, 0, 3, 469, 1, 0, 0, 0, 3, 471, 1, 0, 0, 0, 3, 473, 1, 0, 0, 0, 3, 475, 1, 0, 0, 0, 3, 477, 1, 0, 0, 0, 3, 479, 1, 0, 0, 0, 3, 481, 1, 0, 0, 0, 3, 483, 1, 0, 0, 0, 3, 485, 1, 0, 0, 0, 3, 487, 1, 0, 0, 0, 3, 489, 1, 0, 0, 0, 3, 491, 1, 0, 0, 0, 3, 493, 1, 0, 0, 0, 3, 495, 1, 0, 0, 0, 3, 497, 1, 0, 0, 0, 3, 499, 1, 0, 0, 0, 3, 501, 1, 0, 0, 0, 3, 503, 1, 0, 0, 0, 3, 505, 1, 0, 0, 0, 3, 507, 1, 0, 0, 0, 3, 509, 1, 0, 0, 0, 3, 511, 1, 0, 0, 0, 3, 513, 1, 0, 0, 0, 3, 515, 1, 0, 0, 0, 3, 517, 1, 0, 0, 0, 3, 519, 1, 0, 0, 0, 3, 521, 1, 0, 0, 0, 3, 523, 1, 0, 0, 0, 3, 525, 1, 0, 0, 0, 3, 527, 1, 0, 0, 0, 3, 529, 1, 0, 0, 0, 3, 531, 1, 0, 0, 0, 3, 533, 1, 0, 0, 0, 3, 535, 1, 0, 0, 0, 3, 537, 1, 0, 0, 0, 3, 539, 1, 0, 0, 0, 3, 541, 1, 0, 0, 0, 3, 543, 1, 0, 0, 0, 3, 545, 1, 0, 0, 0, 3, 547, 1, 0, 0, 0, 3, 549, 1, 0, 0, 0, 3, 551, 1, 0, 0, 0, 3, 553, 1, 0, 0, 0, 3, 555, 1, 0, 0, 0, 3, 557, 1, 0, 0, 0, 3, 559, 1, 0, 0, 0, 3, 561, 1, 0, 0, 0, 3, 563, 1, 0, 0, 0, 3, 565, 1, 0, 0, 0, 3, 567, 1, 0, 0, 0, 3, 569, 1, 0, 0, 0, 3, 571, 1, 0, 0, 0, 3, 573, 1, 0, 0, 0, 3, 575, 1, 0, 0, 0, 3, 577, 1, 0, 0, 0, 3, 579, 1, 0, 0, 0, 3, 581, 1, 0, 0, 0, 3, 583, 1, 0, 0, 0, 3, 585, 1, 0, 0, 0, 3, 587, 1, 0, 0, 0, 3, 589, 1, 0, 0, 0, 3, 591, 1, 0, 0, 0, 3, 593, 1, 0, 0, 0, 3, 595, 1, 0, 0, 0, 3, 597, 1, 0, 0, 0, 3, 599, 1, 0, 0, 0, 3, 601, 1, 0, 0, 0, 3, 603, 1, 0, 0, 0, 3, 605, 1, 0, 0, 0, 3, 607, 1, 0, 0, 0, 3, 609, 1, 0, 0, 0, 3, 611, 1, 0, 0, 0, 3, 613, 1, 0, 0, 0, 3, 615, 1, 0, 0, 0, 3, 617, 1, 0, 0, 0, 3, 619, 1, 0, 0, 0, 3, 621, 1, 0, 0, 0, 3, 623, 1, 0, 0, 0, 3, 625, 1, 0, 0, 0, 3, 627, 1, 0, 0, 0, 3, 629, 1, 0, 0, 0, 3, 631, 1, 0, 0, 0, 3, 633, 1, 0, 0, 0, 4, 635, 1, 0, 0, 0, 5, 637, 1, 0, 0, 0, 7, 646, 1, 0, 0, 0, 9, 661, 1, 0, 0, 0, 11, 672, 1, 0, 0, 0, 13, 681, 1, 0, 0, 0, 15, 686, 1, 0, 0, 0, 17, 688, 1, 0, 0, 0, 19, 692, 1, 0, 0, 0, 21, 694, 1, 0, 0, 0, 23, 696, 1, 0, 0, 0, 25, 700, 1, 0, 0, 0, 27, 702, 1, 0, 0, 0, 29, 706, 1, 0, 0, 0, 31, 708, 1, 0, 0, 0, 33, 712, 1, 0, 0, 0, 35, 716, 1, 0, 0, 0, 37, 718, 1, 0, 0, 0, 39, 720, 1, 0, 0, 0, 41, 722, 1, 0, 0, 0, 43, 724, 1, 0, 0, 0, 45, 726, 1, 0, 0, 0, 47, 729, 1, 0, 0, 0, 49, 732, 1, 0, 0, 0, 51, 735, 1, 0, 0, 0, 53, 738, 1, 0, 0, 0, 55, 741, 1, 0, 0, 0, 57, 743, 1, 0, 0, 0, 59, 745, 1, 0, 0, 0, 61, 747, 1, 0, 0, 0, 63, 749, 1, 0, 0, 0, 65, 752, 1, 0, 0, 0, 67, 755, 1, 0, 0, 0, 69, 758, 1, 0, 0, 0, 71, 761, 1, 0, 0, 0, 73, 764, 1, 0, 0, 0, 75, 767, 1, 0, 0, 0, 77, 770, 1, 0, 0, 0, 79, 773, 1, 0, 0, 0, 81, 777, 1, 0, 0, 0, 83, 780, 1, 0, 0, 0, 85, 783, 1, 0, 0, 0, 87, 785, 1, 0, 0, 0, 89, 787, 1, 0, 0, 0, 91, 794, 1, 0, 0, 0, 93, 800, 1, 0, 0, 0, 95, 807, 1, 0, 0, 0, 97, 810, 1, 0, 0, 0, 99, 812, 1, 0, 0, 0, 101, 814, 1, 0, 0, 0, 103, 816, 1, 0, 0, 0, 105, 819, 1, 0, 0, 0, 107, 822, 1, 0, 0, 0, 109, 825, 1, 0, 0, 0, 111, 829, 1, 0, 0, 0, 113, 833, 1, 0, 0, 0, 115, 836, 1, 0, 0, 0, 117, 840, 1, 0, 0, 0, 119, 842, 1, 0, 0, 0, 121, 844, 1, 0, 0, 0, 123, 854, 1, 0, 0, 0, 125, 866, 1, 0, 0, 0, 127, 875, 1, 0, 0, 0, 129, 883, 1, 0, 0, 0, 131, 892, 1, 0, 0, 0, 133, 897, 1, 0, 0, 0, 135, 903, 1, 0, 0, 0, 137, 912, 1, 0, 0, 0, 139, 916, 1, 0, 0, 0, 141, 920, 1, 0, 0, 0, 143, 929, 1, 0, 0, 0, 145, 935, 1, 0, 0, 0, 147, 944, 1, 0, 0, 0, 149, 953, 1, 0, 0, 0, 151, 961, 1, 0, 0, 0, 153, 968, 1, 0, 0, 0, 155, 974, 1, 0, 0, 0, 157, 984, 1, 0, 0, 0, 159, 988, 1, 0, 0, 0, 161, 995, 1, 0, 0, 0, 163, 999, 1, 0, 0, 0, 165, 1003, 1, 0, 0, 0, 167, 1013, 1, 0, 0, 0, 169, 1025, 1, 0, 0, 0, 171, 1028, 1, 0, 0, 0, 173, 1038, 1, 0, 0, 0, 175, 1043, 1, 0, 0, 0, 177, 1048, 1, 0, 0, 0, 179, 1054, 1, 0, 0, 0, 181, 1061, 1, 0, 0, 0, 183, 1067, 1, 0, 0, 0, 185, 1070, 1, 0, 0, 0, 187, 1075, 1, 0, 0, 0, 189, 1080, 1, 0, 0, 0, 191, 1084, 1, 0, 0, 0, 193, 1090, 1, 0, 0, 0, 195, 1098, 1, 0, 0, 0, 197, 1102, 1, 0, 0, 0, 199, 1105, 1, 0, 0, 0, 201, 1111, 1, 0, 0, 0, 203, 1117, 1, 0, 0, 0, 205, 1124, 1, 0, 0, 0, 207, 1133, 1, 0, 0, 0, 209, 1139, 1, 0, 0, 0, 211, 1142, 1, 0, 0, 0, 213, 1145, 1, 0, 0, 0, 215, 1148, 1, 0, 0, 0, 217, 1156, 1, 0, 0, 0, 219, 1164, 1, 0, 0, 0, 221, 1168, 1, 0, 0, 0, 223, 1176, 1, 0, 0, 0, 225, 1183, 1, 0, 0, 0, 227, 1191, 1, 0, 0, 0, 229, 1201, 1, 0, 0, 0, 231, 1210, 1, 0, 0, 0, 233, 1215, 1, 0, 0, 0, 235, 1222, 1, 0, 0, 0, 237, 1233, 1, 0, 0, 0, 239, 1238, 1, 0, 0, 0, 241, 1244, 1, 0, 0, 0, 243, 1250, 1, 0, 0, 0, 245, 1258, 1, 0, 0, 0, 247, 1267, 1, 0, 0, 0, 249, 1274, 1, 0, 0, 0, 251, 1280, 1, 0, 0, 0, 253, 1289, 1, 0, 0, 0, 255, 1297, 1, 0, 0, 0, 257, 1306, 1, 0, 0, 0, 259, 1315, 1, 0, 0, 0, 261, 1321, 1, 0, 0, 0, 263, 1326, 1, 0, 0, 0, 265, 1332, 1, 0, 0, 0, 267, 1341, 1, 0, 0, 0, 269, 1348, 1, 0, 0, 0, 271, 1357, 1, 0, 0, 0, 273, 1369, 1, 0, 0, 0, 275, 1377, 1, 0, 0, 0, 277, 1384, 1, 0, 0, 0, 279, 1391, 1, 0, 0, 0, 281, 1393, 1, 0, 0, 0, 283, 1397, 1, 0, 0, 0, 285, 1409, 1, 0, 0, 0, 287, 1411, 1, 0, 0, 0, 289, 1419, 1, 0, 0, 0, 291, 1427, 1, 0, 0, 0, 293, 1440, 1, 0, 0, 0, 295, 1452, 1, 0, 0, 0, 297, 1454, 1, 0, 0, 0, 299, 1458, 1, 0, 0, 0, 301, 1474, 1, 0, 0, 0, 303, 1476, 1, 0, 0, 0, 305, 1480, 1, 0, 0, 0, 307, 1496, 1, 0, 0, 0, 309, 1501, 1, 0, 0, 0, 311, 1510, 1, 0, 0, 0, 313, 1523, 1, 0, 0, 0, 315, 1525, 1, 0, 0, 0, 317, 1530, 1, 0, 0, 0, 319, 1537, 1, 0, 0, 0, 321, 1558, 1, 0, 0, 0, 323, 1608, 1, 0, 0, 0, 325, 1610, 1, 0, 0, 0, 327, 1613, 1, 0, 0, 0, 329, 1620, 1, 0, 0, 0, 331, 1625, 1, 0, 0, 0, 333, 1632, 1, 0, 0, 0, 335, 1634, 1, 0, 0, 0, 337, 1638, 1, 0, 0, 0, 339, 1644, 1, 0, 0, 0, 341, 1646, 1, 0, 0, 0, 343, 1648, 1, 0, 0, 0, 345, 1650, 1, 0, 0, 0, 347, 1652, 1, 0, 0, 0, 349, 1654, 1, 0, 0, 0, 351, 1656, 1, 0, 0, 0, 353, 1658, 1, 0, 0, 0, 355, 1662, 1, 0, 0, 0, 357, 1670, 1, 0, 0, 0, 359, 1674, 1, 0, 0, 0, 361, 1676, 1, 0, 0, 0, 363, 1682, 1, 0, 0, 0, 365, 1691, 1, 0, 0, 0, 367, 1695, 1, 0, 0, 0, 369, 1703, 1, 0, 0, 0, 371, 1705, 1, 0, 0, 0, 373, 1710, 1, 0, 0, 0, 375, 1715, 1, 0, 0, 0, 377, 1720, 1, 0, 0, 0, 379, 1725, 1, 0, 0, 0, 381, 1730, 1, 0, 0, 0, 383, 1735, 1, 0, 0, 0, 385, 1740, 1, 0, 0, 0, 387, 1744, 1, 0, 0, 0, 389, 1748, 1, 0, 0, 0, 391, 1752, 1, 0, 0, 0, 393, 1756, 1, 0, 0, 0, 395, 1760, 1, 0, 0, 0, 397, 1764, 1, 0, 0, 0, 399, 1768, 1, 0, 0, 0, 401, 1772, 1, 0, 0, 0, 403, 1776, 1, 0, 0, 0, 405, 1780, 1, 0, 0, 0, 407, 1784, 1, 0, 0, 0, 409, 1791, 1, 0, 0, 0, 411, 1795, 1, 0, 0, 0, 413, 1799, 1, 0, 0, 0, 415, 1803, 1, 0, 0, 0, 417, 1807, 1, 0, 0, 0, 419, 1811, 1, 0, 0, 0, 421, 1815, 1, 0, 0, 0, 423, 1819, 1, 0, 0, 0, 425, 1823, 1, 0, 0, 0, 427, 1827, 1, 0, 0, 0, 429, 1831, 1, 0, 0, 0, 431, 1835, 1, 0, 0, 0, 433, 1839, 1, 0, 0, 0, 435, 1843, 1, 0, 0, 0, 437, 1847, 1, 0, 0, 0, 439, 1851, 1, 0, 0, 0, 441, 1855, 1, 0, 0, 0, 443, 1859, 1, 0, 0, 0, 445, 1863, 1, 0, 0, 0, 447, 1867, 1, 0, 0, 0, 449, 1871, 1, 0, 0, 0, 451, 1875, 1, 0, 0, 0, 453, 1882, 1, 0, 0, 0, 455, 1886, 1, 0, 0, 0, 457, 1890, 1, 0, 0, 0, 459, 1894, 1, 0, 0, 0, 461, 1898, 1, 0, 0, 0, 463, 1902, 1, 0, 0, 0, 465, 1906, 1, 0, 0, 0, 467, 1910, 1, 0, 0, 0, 469, 1914, 1, 0, 0, 0, 471, 1918, 1, 0, 0, 0, 473, 1922, 1, 0, 0, 0, 475, 1926, 1, 0, 0, 0, 477, 1930, 1, 0, 0, 0, 479, 1934, 1, 0, 0, 0, 481, 1938, 1, 0, 0, 0, 483, 1942, 1, 0, 0, 0, 485, 1946, 1, 0, 0, 0, 487, 1951, 1, 0, 0, 0, 489, 1956, 1, 0, 0, 0, 491, 1960, 1, 0, 0, 0, 493, 1964, 1, 0, 0, 0, 495, 1968, 1, 0, 0, 0, 497, 1972, 1, 0, 0, 0, 499, 1976, 1, 0, 0, 0, 501, 1980, 1, 0, 0, 0, 503, 1984, 1, 0, 0, 0, 505, 1988, 1, 0, 0, 0, 507, 1992, 1, 0, 0, 0, 509, 1996, 1, 0, 0, 0, 511, 2000, 1, 0, 0, 0, 513, 2004, 1, 0, 0, 0, 515, 2008, 1, 0, 0, 0, 517, 2012, 1, 0, 0, 0, 519, 2016, 1, 0, 0, 0, 521, 2020, 1, 0, 0, 0, 523, 2024, 1, 0, 0, 0, 525, 2028, 1, 0, 0, 0, 527, 2032, 1, 0, 0, 0, 529, 2036, 1, 0, 0, 0, 531, 2040, 1, 0, 0, 0, 533, 2044, 1, 0, 0, 0, 535, 2048, 1, 0, 0, 0, 537, 2052, 1, 0, 0, 0, 539, 2056, 1, 0, 0, 0, 541, 2060, 1, 0, 0, 0, 543, 2064, 1, 0, 0, 0, 545, 2068, 1, 0, 0, 0, 547, 2072, 1, 0, 0, 0, 549, 2076, 1, 0, 0, 0, 551, 2080, 1, 0, 0, 0, 553, 2084, 1, 0, 0, 0, 555, 2088, 1, 0, 0, 0, 557, 2092, 1, 0, 0, 0, 559, 2096, 1, 0, 0, 0, 561, 2100, 1, 0, 0, 0, 563, 2104, 1, 0, 0, 0, 565, 2108, 1, 0, 0, 0, 567, 2112, 1, 0, 0, 0, 569, 2116, 1, 0, 0, 0, 571, 2120, 1, 0, 0, 0, 573, 2124, 1, 0, 0, 0, 575, 2128, 1, 0, 0, 0, 577, 2132, 1, 0, 0, 0, 579, 2136, 1, 0, 0, 0, 581, 2140, 1, 0, 0, 0, 583, 2144, 1, 0, 0, 0, 585, 2148, 1, 0, 0, 0, 587, 2152, 1, 0, 0, 0, 589, 2156, 1, 0, 0, 0, 591, 2160, 1, 0, 0, 0, 593, 2164, 1, 0, 0, 0, 595, 2168, 1, 0, 0, 0, 597, 2172, 1, 0, 0, 0, 599, 2176, 1, 0, 0, 0, 601, 2180, 1, 0, 0, 0, 603, 2184, 1, 0, 0, 0, 605, 2188, 1, 0, 0, 0, 607, 2192, 1, 0, 0, 0, 609, 2196, 1, 0, 0, 0, 611, 2200, 1, 0, 0, 0, 613, 2204, 1, 0, 0, 0, 615, 2208, 1, 0, 0, 0, 617, 2212, 1, 0, 0, 0, 619, 2216, 1, 0, 0, 0, 621, 2220, 1, 0, 0, 0, 623, 2224, 1, 0, 0, 0, 625, 2228, 1, 0, 0, 0, 627, 2232, 1, 0, 0, 0, 629, 2238, 1, 0, 0, 0, 631, 2242, 1, 0, 0, 0, 633, 2246, 1, 0, 0, 0, 635, 2250, 1, 0, 0, 0, 637, 638, 5, 35, 0, 0, 638, 639, 5, 33, 0, 0, 639, 643, 1, 0, 0, 0, 640, 642, 8, 0, 0, 0, 641, 640, 1, 0, 0, 0, 642, 645, 1, 0, 0, 0, 643, 641, 1, 0, 0, 0, 643, 644, 1, 0, 0, 0, 644, 6, 1, 0, 0, 0, 645, 643, 1, 0, 0, 0, 646, 647, 5, 47, 0, 0, 647, 648, 5, 42, 0, 0, 648, 653, 1, 0, 0, 0, 649, 652, 3, 7, 1, 0, 650, 652, 9, 0, 0, 0, 651, 649, 1, 0, 0, 0, 651, 650, 1, 0, 0, 0, 652, 655, 1, 0, 0, 0, 653, 654, 1, 0, 0, 0, 653, 651, 1, 0, 0, 0, 654, 656, 1, 0, 0, 0, 655, 653, 1, 0, 0, 0, 656, 657, 5, 42, 0, 0, 657, 658, 5, 47, 0, 0, 658, 659, 1, 0, 0, 0, 659, 660, 6, 1, 0, 0, 660, 8, 1, 0, 0, 0, 661, 662, 5, 47, 0, 0, 662, 663, 5, 47, 0, 0, 663, 667, 1, 0, 0, 0, 664, 666, 8, 0, 0, 0, 665, 664, 1, 0, 0, 0, 666, 669, 1, 0, 0, 0, 667, 665, 1, 0, 0, 0, 667, 668, 1, 0, 0, 0, 668, 670, 1, 0, 0, 0, 669, 667, 1, 0, 0, 0, 670, 671, 6, 2, 0, 0, 671, 10, 1, 0, 0, 0, 672, 673, 7, 1, 0, 0, 673, 674, 1, 0, 0, 0, 674, 675, 6, 3, 0, 0, 675, 12, 1, 0, 0, 0, 676, 682, 5, 10, 0, 0, 677, 679, 5, 13, 0, 0, 678, 680, 5, 10, 0, 0, 679, 678, 1, 0, 0, 0, 679, 680, 1, 0, 0, 0, 680, 682, 1, 0, 0, 0, 681, 676, 1, 0, 0, 0, 681, 677, 1, 0, 0, 0, 682, 14, 1, 0, 0, 0, 683, 687, 3, 7, 1, 0, 684, 687, 3, 9, 2, 0, 685, 687, 3, 11, 3, 0, 686, 683, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 686, 685, 1, 0, 0, 0, 687, 16, 1, 0, 0, 0, 688, 689, 5, 46, 0, 0, 689, 690, 5, 46, 0, 0, 690, 691, 5, 46, 0, 0, 691, 18, 1, 0, 0, 0, 692, 693, 5, 46, 0, 0, 693, 20, 1, 0, 0, 0, 694, 695, 5, 44, 0, 0, 695, 22, 1, 0, 0, 0, 696, 697, 5, 40, 0, 0, 697, 698, 1, 0, 0, 0, 698, 699, 6, 9, 1, 0, 699, 24, 1, 0, 0, 0, 700, 701, 5, 41, 0, 0, 701, 26, 1, 0, 0, 0, 702, 703, 5, 91, 0, 0, 703, 704, 1, 0, 0, 0, 704, 705, 6, 11, 1, 0, 705, 28, 1, 0, 0, 0, 706, 707, 5, 93, 0, 0, 707, 30, 1, 0, 0, 0, 708, 709, 5, 123, 0, 0, 709, 710, 1, 0, 0, 0, 710, 711, 6, 13, 2, 0, 711, 32, 1, 0, 0, 0, 712, 713, 5, 125, 0, 0, 713, 714, 1, 0, 0, 0, 714, 715, 6, 14, 3, 0, 715, 34, 1, 0, 0, 0, 716, 717, 5, 42, 0, 0, 717, 36, 1, 0, 0, 0, 718, 719, 5, 37, 0, 0, 719, 38, 1, 0, 0, 0, 720, 721, 5, 47, 0, 0, 721, 40, 1, 0, 0, 0, 722, 723, 5, 43, 0, 0, 723, 42, 1, 0, 0, 0, 724, 725, 5, 45, 0, 0, 725, 44, 1, 0, 0, 0, 726, 727, 5, 43, 0, 0, 727, 728, 5, 43, 0, 0, 728, 46, 1, 0, 0, 0, 729, 730, 5, 45, 0, 0, 730, 731, 5, 45, 0, 0, 731, 48, 1, 0, 0, 0, 732, 733, 5, 38, 0, 0, 733, 734, 5, 38, 0, 0, 734, 50, 1, 0, 0, 0, 735, 736, 5, 124, 0, 0, 736, 737, 5, 124, 0, 0, 737, 52, 1, 0, 0, 0, 738, 739, 5, 33, 0, 0, 739, 740, 3, 15, 5, 0, 740, 54, 1, 0, 0, 0, 741, 742, 5, 33, 0, 0, 742, 56, 1, 0, 0, 0, 743, 744, 5, 58, 0, 0, 744, 58, 1, 0, 0, 0, 745, 746, 5, 59, 0, 0, 746, 60, 1, 0, 0, 0, 747, 748, 5, 61, 0, 0, 748, 62, 1, 0, 0, 0, 749, 750, 5, 43, 0, 0, 750, 751, 5, 61, 0, 0, 751, 64, 1, 0, 0, 0, 752, 753, 5, 45, 0, 0, 753, 754, 5, 61, 0, 0, 754, 66, 1, 0, 0, 0, 755, 756, 5, 42, 0, 0, 756, 757, 5, 61, 0, 0, 757, 68, 1, 0, 0, 0, 758, 759, 5, 47, 0, 0, 759, 760, 5, 61, 0, 0, 760, 70, 1, 0, 0, 0, 761, 762, 5, 37, 0, 0, 762, 763, 5, 61, 0, 0, 763, 72, 1, 0, 0, 0, 764, 765, 5, 45, 0, 0, 765, 766, 5, 62, 0, 0, 766, 74, 1, 0, 0, 0, 767, 768, 5, 61, 0, 0, 768, 769, 5, 62, 0, 0, 769, 76, 1, 0, 0, 0, 770, 771, 5, 46, 0, 0, 771, 772, 5, 46, 0, 0, 772, 78, 1, 0, 0, 0, 773, 774, 5, 46, 0, 0, 774, 775, 5, 46, 0, 0, 775, 776, 5, 60, 0, 0, 776, 80, 1, 0, 0, 0, 777, 778, 5, 58, 0, 0, 778, 779, 5, 58, 0, 0, 779, 82, 1, 0, 0, 0, 780, 781, 5, 59, 0, 0, 781, 782, 5, 59, 0, 0, 782, 84, 1, 0, 0, 0, 783, 784, 5, 35, 0, 0, 784, 86, 1, 0, 0, 0, 785, 786, 5, 64, 0, 0, 786, 88, 1, 0, 0, 0, 787, 790, 5, 64, 0, 0, 788, 791, 3, 15, 5, 0, 789, 791, 3, 13, 4, 0, 790, 788, 1, 0, 0, 0, 790, 789, 1, 0, 0, 0, 791, 90, 1, 0, 0, 0, 792, 795, 3, 15, 5, 0, 793, 795, 3, 13, 4, 0, 794, 792, 1, 0, 0, 0, 794, 793, 1, 0, 0, 0, 795, 796, 1, 0, 0, 0, 796, 797, 5, 64, 0, 0, 797, 92, 1, 0, 0, 0, 798, 801, 3, 15, 5, 0, 799, 801, 3, 13, 4, 0, 800, 798, 1, 0, 0, 0, 800, 799, 1, 0, 0, 0, 801, 802, 1, 0, 0, 0, 802, 805, 5, 64, 0, 0, 803, 806, 3, 15, 5, 0, 804, 806, 3, 13, 4, 0, 805, 803, 1, 0, 0, 0, 805, 804, 1, 0, 0, 0, 806, 94, 1, 0, 0, 0, 807, 808, 5, 63, 0, 0, 808, 809, 3, 15, 5, 0, 809, 96, 1, 0, 0, 0, 810, 811, 5, 63, 0, 0, 811, 98, 1, 0, 0, 0, 812, 813, 5, 60, 0, 0, 813, 100, 1, 0, 0, 0, 814, 815, 5, 62, 0, 0, 815, 102, 1, 0, 0, 0, 816, 817, 5, 60, 0, 0, 817, 818, 5, 61, 0, 0, 818, 104, 1, 0, 0, 0, 819, 820, 5, 62, 0, 0, 820, 821, 5, 61, 0, 0, 821, 106, 1, 0, 0, 0, 822, 823, 5, 33, 0, 0, 823, 824, 5, 61, 0, 0, 824, 108, 1, 0, 0, 0, 825, 826, 5, 33, 0, 0, 826, 827, 5, 61, 0, 0, 827, 828, 5, 61, 0, 0, 828, 110, 1, 0, 0, 0, 829, 830, 5, 97, 0, 0, 830, 831, 5, 115, 0, 0, 831, 832, 5, 63, 0, 0, 832, 112, 1, 0, 0, 0, 833, 834, 5, 61, 0, 0, 834, 835, 5, 61, 0, 0, 835, 114, 1, 0, 0, 0, 836, 837, 5, 61, 0, 0, 837, 838, 5, 61, 0, 0, 838, 839, 5, 61, 0, 0, 839, 116, 1, 0, 0, 0, 840, 841, 5, 39, 0, 0, 841, 118, 1, 0, 0, 0, 842, 843, 5, 38, 0, 0, 843, 120, 1, 0, 0, 0, 844, 845, 5, 114, 0, 0, 845, 846, 5, 101, 0, 0, 846, 847, 5, 116, 0, 0, 847, 848, 5, 117, 0, 0, 848, 849, 5, 114, 0, 0, 849, 850, 5, 110, 0, 0, 850, 851, 5, 64, 0, 0, 851, 852, 1, 0, 0, 0, 852, 853, 3, 321, 158, 0, 853, 122, 1, 0, 0, 0, 854, 855, 5, 99, 0, 0, 855, 856, 5, 111, 0, 0, 856, 857, 5, 110, 0, 0, 857, 858, 5, 116, 0, 0, 858, 859, 5, 105, 0, 0, 859, 860, 5, 110, 0, 0, 860, 861, 5, 117, 0, 0, 861, 862, 5, 101, 0, 0, 862, 863, 5, 64, 0, 0, 863, 864, 1, 0, 0, 0, 864, 865, 3, 321, 158, 0, 865, 124, 1, 0, 0, 0, 866, 867, 5, 98, 0, 0, 867, 868, 5, 114, 0, 0, 868, 869, 5, 101, 0, 0, 869, 870, 5, 97, 0, 0, 870, 871, 5, 107, 0, 0, 871, 872, 5, 64, 0, 0, 872, 873, 1, 0, 0, 0, 873, 874, 3, 321, 158, 0, 874, 126, 1, 0, 0, 0, 875, 876, 5, 116, 0, 0, 876, 877, 5, 104, 0, 0, 877, 878, 5, 105, 0, 0, 878, 879, 5, 115, 0, 0, 879, 880, 5, 64, 0, 0, 880, 881, 1, 0, 0, 0, 881, 882, 3, 321, 158, 0, 882, 128, 1, 0, 0, 0, 883, 884, 5, 115, 0, 0, 884, 885, 5, 117, 0, 0, 885, 886, 5, 112, 0, 0, 886, 887, 5, 101, 0, 0, 887, 888, 5, 114, 0, 0, 888, 889, 5, 64, 0, 0, 889, 890, 1, 0, 0, 0, 890, 891, 3, 321, 158, 0, 891, 130, 1, 0, 0, 0, 892, 893, 5, 102, 0, 0, 893, 894, 5, 105, 0, 0, 894, 895, 5, 108, 0, 0, 895, 896, 5, 101, 0, 0, 896, 132, 1, 0, 0, 0, 897, 898, 5, 102, 0, 0, 898, 899, 5, 105, 0, 0, 899, 900, 5, 101, 0, 0, 900, 901, 5, 108, 0, 0, 901, 902, 5, 100, 0, 0, 902, 134, 1, 0, 0, 0, 903, 904, 5, 112, 0, 0, 904, 905, 5, 114, 0, 0, 905, 906, 5, 111, 0, 0, 906, 907, 5, 112, 0, 0, 907, 908, 5, 101, 0, 0, 908, 909, 5, 114, 0, 0, 909, 910, 5, 116, 0, 0, 910, 911, 5, 121, 0, 0, 911, 136, 1, 0, 0, 0, 912, 913, 5, 103, 0, 0, 913, 914, 5, 101, 0, 0, 914, 915, 5, 116, 0, 0, 915, 138, 1, 0, 0, 0, 916, 917, 5, 115, 0, 0, 917, 918, 5, 101, 0, 0, 918, 919, 5, 116, 0, 0, 919, 140, 1, 0, 0, 0, 920, 921, 5, 114, 0, 0, 921, 922, 5, 101, 0, 0, 922, 923, 5, 99, 0, 0, 923, 924, 5, 101, 0, 0, 924, 925, 5, 105, 0, 0, 925, 926, 5, 118, 0, 0, 926, 927, 5, 101, 0, 0, 927, 928, 5, 114, 0, 0, 928, 142, 1, 0, 0, 0, 929, 930, 5, 112, 0, 0, 930, 931, 5, 97, 0, 0, 931, 932, 5, 114, 0, 0, 932, 933, 5, 97, 0, 0, 933, 934, 5, 109, 0, 0, 934, 144, 1, 0, 0, 0, 935, 936, 5, 115, 0, 0, 936, 937, 5, 101, 0, 0, 937, 938, 5, 116, 0, 0, 938, 939, 5, 112, 0, 0, 939, 940, 5, 97, 0, 0, 940, 941, 5, 114, 0, 0, 941, 942, 5, 97, 0, 0, 942, 943, 5, 109, 0, 0, 943, 146, 1, 0, 0, 0, 944, 945, 5, 100, 0, 0, 945, 946, 5, 101, 0, 0, 946, 947, 5, 108, 0, 0, 947, 948, 5, 101, 0, 0, 948, 949, 5, 103, 0, 0, 949, 950, 5, 97, 0, 0, 950, 951, 5, 116, 0, 0, 951, 952, 5, 101, 0, 0, 952, 148, 1, 0, 0, 0, 953, 954, 5, 112, 0, 0, 954, 955, 5, 97, 0, 0, 955, 956, 5, 99, 0, 0, 956, 957, 5, 107, 0, 0, 957, 958, 5, 97, 0, 0, 958, 959, 5, 103, 0, 0, 959, 960, 5, 101, 0, 0, 960, 150, 1, 0, 0, 0, 961, 962, 5, 105, 0, 0, 962, 963, 5, 109, 0, 0, 963, 964, 5, 112, 0, 0, 964, 965, 5, 111, 0, 0, 965, 966, 5, 114, 0, 0, 966, 967, 5, 116, 0, 0, 967, 152, 1, 0, 0, 0, 968, 969, 5, 99, 0, 0, 969, 970, 5, 108, 0, 0, 970, 971, 5, 97, 0, 0, 971, 972, 5, 115, 0, 0, 972, 973, 5, 115, 0, 0, 973, 154, 1, 0, 0, 0, 974, 975, 5, 105, 0, 0, 975, 976, 5, 110, 0, 0, 976, 977, 5, 116, 0, 0, 977, 978, 5, 101, 0, 0, 978, 979, 5, 114, 0, 0, 979, 980, 5, 102, 0, 0, 980, 981, 5, 97, 0, 0, 981, 982, 5, 99, 0, 0, 982, 983, 5, 101, 0, 0, 983, 156, 1, 0, 0, 0, 984, 985, 5, 102, 0, 0, 985, 986, 5, 117, 0, 0, 986, 987, 5, 110, 0, 0, 987, 158, 1, 0, 0, 0, 988, 989, 5, 111, 0, 0, 989, 990, 5, 98, 0, 0, 990, 991, 5, 106, 0, 0, 991, 992, 5, 101, 0, 0, 992, 993, 5, 99, 0, 0, 993, 994, 5, 116, 0, 0, 994, 160, 1, 0, 0, 0, 995, 996, 5, 118, 0, 0, 996, 997, 5, 97, 0, 0, 997, 998, 5, 108, 0, 0, 998, 162, 1, 0, 0, 0, 999, 1000, 5, 118, 0, 0, 1000, 1001, 5, 97, 0, 0, 1001, 1002, 5, 114, 0, 0, 1002, 164, 1, 0, 0, 0, 1003, 1004, 5, 116, 0, 0, 1004, 1005, 5, 121, 0, 0, 1005, 1006, 5, 112, 0, 0, 1006, 1007, 5, 101, 0, 0, 1007, 1008, 5, 97, 0, 0, 1008, 1009, 5, 108, 0, 0, 1009, 1010, 5, 105, 0, 0, 1010, 1011, 5, 97, 0, 0, 1011, 1012, 5, 115, 0, 0, 1012, 166, 1, 0, 0, 0, 1013, 1014, 5, 99, 0, 0, 1014, 1015, 5, 111, 0, 0, 1015, 1016, 5, 110, 0, 0, 1016, 1017, 5, 115, 0, 0, 1017, 1018, 5, 116, 0, 0, 1018, 1019, 5, 114, 0, 0, 1019, 1020, 5, 117, 0, 0, 1020, 1021, 5, 99, 0, 0, 1021, 1022, 5, 116, 0, 0, 1022, 1023, 5, 111, 0, 0, 1023, 1024, 5, 114, 0, 0, 1024, 168, 1, 0, 0, 0, 1025, 1026, 5, 98, 0, 0, 1026, 1027, 5, 121, 0, 0, 1027, 170, 1, 0, 0, 0, 1028, 1029, 5, 99, 0, 0, 1029, 1030, 5, 111, 0, 0, 1030, 1031, 5, 109, 0, 0, 1031, 1032, 5, 112, 0, 0, 1032, 1033, 5, 97, 0, 0, 1033, 1034, 5, 110, 0, 0, 1034, 1035, 5, 105, 0, 0, 1035, 1036, 5, 111, 0, 0, 1036, 1037, 5, 110, 0, 0, 1037, 172, 1, 0, 0, 0, 1038, 1039, 5, 105, 0, 0, 1039, 1040, 5, 110, 0, 0, 1040, 1041, 5, 105, 0, 0, 1041, 1042, 5, 116, 0, 0, 1042, 174, 1, 0, 0, 0, 1043, 1044, 5, 116, 0, 0, 1044, 1045, 5, 104, 0, 0, 1045, 1046, 5, 105, 0, 0, 1046, 1047, 5, 115, 0, 0, 1047, 176, 1, 0, 0, 0, 1048, 1049, 5, 115, 0, 0, 1049, 1050, 5, 117, 0, 0, 1050, 1051, 5, 112, 0, 0, 1051, 1052, 5, 101, 0, 0, 1052, 1053, 5, 114, 0, 0, 1053, 178, 1, 0, 0, 0, 1054, 1055, 5, 116, 0, 0, 1055, 1056, 5, 121, 0, 0, 1056, 1057, 5, 112, 0, 0, 1057, 1058, 5, 101, 0, 0, 1058, 1059, 5, 111, 0, 0, 1059, 1060, 5, 102, 0, 0, 1060, 180, 1, 0, 0, 0, 1061, 1062, 5, 119, 0, 0, 1062, 1063, 5, 104, 0, 0, 1063, 1064, 5, 101, 0, 0, 1064, 1065, 5, 114, 0, 0, 1065, 1066, 5, 101, 0, 0, 1066, 182, 1, 0, 0, 0, 1067, 1068, 5, 105, 0, 0, 1068, 1069, 5, 102, 0, 0, 1069, 184, 1, 0, 0, 0, 1070, 1071, 5, 101, 0, 0, 1071, 1072, 5, 108, 0, 0, 1072, 1073, 5, 115, 0, 0, 1073, 1074, 5, 101, 0, 0, 1074, 186, 1, 0, 0, 0, 1075, 1076, 5, 119, 0, 0, 1076, 1077, 5, 104, 0, 0, 1077, 1078, 5, 101, 0, 0, 1078, 1079, 5, 110, 0, 0, 1079, 188, 1, 0, 0, 0, 1080, 1081, 5, 116, 0, 0, 1081, 1082, 5, 114, 0, 0, 1082, 1083, 5, 121, 0, 0, 1083, 190, 1, 0, 0, 0, 1084, 1085, 5, 99, 0, 0, 1085, 1086, 5, 97, 0, 0, 1086, 1087, 5, 116, 0, 0, 1087, 1088, 5, 99, 0, 0, 1088, 1089, 5, 104, 0, 0, 1089, 192, 1, 0, 0, 0, 1090, 1091, 5, 102, 0, 0, 1091, 1092, 5, 105, 0, 0, 1092, 1093, 5, 110, 0, 0, 1093, 1094, 5, 97, 0, 0, 1094, 1095, 5, 108, 0, 0, 1095, 1096, 5, 108, 0, 0, 1096, 1097, 5, 121, 0, 0, 1097, 194, 1, 0, 0, 0, 1098, 1099, 5, 102, 0, 0, 1099, 1100, 5, 111, 0, 0, 1100, 1101, 5, 114, 0, 0, 1101, 196, 1, 0, 0, 0, 1102, 1103, 5, 100, 0, 0, 1103, 1104, 5, 111, 0, 0, 1104, 198, 1, 0, 0, 0, 1105, 1106, 5, 119, 0, 0, 1106, 1107, 5, 104, 0, 0, 1107, 1108, 5, 105, 0, 0, 1108, 1109, 5, 108, 0, 0, 1109, 1110, 5, 101, 0, 0, 1110, 200, 1, 0, 0, 0, 1111, 1112, 5, 116, 0, 0, 1112, 1113, 5, 104, 0, 0, 1113, 1114, 5, 114, 0, 0, 1114, 1115, 5, 111, 0, 0, 1115, 1116, 5, 119, 0, 0, 1116, 202, 1, 0, 0, 0, 1117, 1118, 5, 114, 0, 0, 1118, 1119, 5, 101, 0, 0, 1119, 1120, 5, 116, 0, 0, 1120, 1121, 5, 117, 0, 0, 1121, 1122, 5, 114, 0, 0, 1122, 1123, 5, 110, 0, 0, 1123, 204, 1, 0, 0, 0, 1124, 1125, 5, 99, 0, 0, 1125, 1126, 5, 111, 0, 0, 1126, 1127, 5, 110, 0, 0, 1127, 1128, 5, 116, 0, 0, 1128, 1129, 5, 105, 0, 0, 1129, 1130, 5, 110, 0, 0, 1130, 1131, 5, 117, 0, 0, 1131, 1132, 5, 101, 0, 0, 1132, 206, 1, 0, 0, 0, 1133, 1134, 5, 98, 0, 0, 1134, 1135, 5, 114, 0, 0, 1135, 1136, 5, 101, 0, 0, 1136, 1137, 5, 97, 0, 0, 1137, 1138, 5, 107, 0, 0, 1138, 208, 1, 0, 0, 0, 1139, 1140, 5, 97, 0, 0, 1140, 1141, 5, 115, 0, 0, 1141, 210, 1, 0, 0, 0, 1142, 1143, 5, 105, 0, 0, 1143, 1144, 5, 115, 0, 0, 1144, 212, 1, 0, 0, 0, 1145, 1146, 5, 105, 0, 0, 1146, 1147, 5, 110, 0, 0, 1147, 214, 1, 0, 0, 0, 1148, 1149, 5, 33, 0, 0, 1149, 1150, 5, 105, 0, 0, 1150, 1151, 5, 115, 0, 0, 1151, 1154, 1, 0, 0, 0, 1152, 1155, 3, 15, 5, 0, 1153, 1155, 3, 13, 4, 0, 1154, 1152, 1, 0, 0, 0, 1154, 1153, 1, 0, 0, 0, 1155, 216, 1, 0, 0, 0, 1156, 1157, 5, 33, 0, 0, 1157, 1158, 5, 105, 0, 0, 1158, 1159, 5, 110, 0, 0, 1159, 1162, 1, 0, 0, 0, 1160, 1163, 3, 15, 5, 0, 1161, 1163, 3, 13, 4, 0, 1162, 1160, 1, 0, 0, 0, 1162, 1161, 1, 0, 0, 0, 1163, 218, 1, 0, 0, 0, 1164, 1165, 5, 111, 0, 0, 1165, 1166, 5, 117, 0, 0, 1166, 1167, 5, 116, 0, 0, 1167, 220, 1, 0, 0, 0, 1168, 1169, 5, 100, 0, 0, 1169, 1170, 5, 121, 0, 0, 1170, 1171, 5, 110, 0, 0, 1171, 1172, 5, 97, 0, 0, 1172, 1173, 5, 109, 0, 0, 1173, 1174, 5, 105, 0, 0, 1174, 1175, 5, 99, 0, 0, 1175, 222, 1, 0, 0, 0, 1176, 1177, 5, 112, 0, 0, 1177, 1178, 5, 117, 0, 0, 1178, 1179, 5, 98, 0, 0, 1179, 1180, 5, 108, 0, 0, 1180, 1181, 5, 105, 0, 0, 1181, 1182, 5, 99, 0, 0, 1182, 224, 1, 0, 0, 0, 1183, 1184, 5, 112, 0, 0, 1184, 1185, 5, 114, 0, 0, 1185, 1186, 5, 105, 0, 0, 1186, 1187, 5, 118, 0, 0, 1187, 1188, 5, 97, 0, 0, 1188, 1189, 5, 116, 0, 0, 1189, 1190, 5, 101, 0, 0, 1190, 226, 1, 0, 0, 0, 1191, 1192, 5, 112, 0, 0, 1192, 1193, 5, 114, 0, 0, 1193, 1194, 5, 111, 0, 0, 1194, 1195, 5, 116, 0, 0, 1195, 1196, 5, 101, 0, 0, 1196, 1197, 5, 99, 0, 0, 1197, 1198, 5, 116, 0, 0, 1198, 1199, 5, 101, 0, 0, 1199, 1200, 5, 100, 0, 0, 1200, 228, 1, 0, 0, 0, 1201, 1202, 5, 105, 0, 0, 1202, 1203, 5, 110, 0, 0, 1203, 1204, 5, 116, 0, 0, 1204, 1205, 5, 101, 0, 0, 1205, 1206, 5, 114, 0, 0, 1206, 1207, 5, 110, 0, 0, 1207, 1208, 5, 97, 0, 0, 1208, 1209, 5, 108, 0, 0, 1209, 230, 1, 0, 0, 0, 1210, 1211, 5, 101, 0, 0, 1211, 1212, 5, 110, 0, 0, 1212, 1213, 5, 117, 0, 0, 1213, 1214, 5, 109, 0, 0, 1214, 232, 1, 0, 0, 0, 1215, 1216, 5, 115, 0, 0, 1216, 1217, 5, 101, 0, 0, 1217, 1218, 5, 97, 0, 0, 1218, 1219, 5, 108, 0, 0, 1219, 1220, 5, 101, 0, 0, 1220, 1221, 5, 100, 0, 0, 1221, 234, 1, 0, 0, 0, 1222, 1223, 5, 97, 0, 0, 1223, 1224, 5, 110, 0, 0, 1224, 1225, 5, 110, 0, 0, 1225, 1226, 5, 111, 0, 0, 1226, 1227, 5, 116, 0, 0, 1227, 1228, 5, 97, 0, 0, 1228, 1229, 5, 116, 0, 0, 1229, 1230, 5, 105, 0, 0, 1230, 1231, 5, 111, 0, 0, 1231, 1232, 5, 110, 0, 0, 1232, 236, 1, 0, 0, 0, 1233, 1234, 5, 100, 0, 0, 1234, 1235, 5, 97, 0, 0, 1235, 1236, 5, 116, 0, 0, 1236, 1237, 5, 97, 0, 0, 1237, 238, 1, 0, 0, 0, 1238, 1239, 5, 105, 0, 0, 1239, 1240, 5, 110, 0, 0, 1240, 1241, 5, 110, 0, 0, 1241, 1242, 5, 101, 0, 0, 1242, 1243, 5, 114, 0, 0, 1243, 240, 1, 0, 0, 0, 1244, 1245, 5, 118, 0, 0, 1245, 1246, 5, 97, 0, 0, 1246, 1247, 5, 108, 0, 0, 1247, 1248, 5, 117, 0, 0, 1248, 1249, 5, 101, 0, 0, 1249, 242, 1, 0, 0, 0, 1250, 1251, 5, 116, 0, 0, 1251, 1252, 5, 97, 0, 0, 1252, 1253, 5, 105, 0, 0, 1253, 1254, 5, 108, 0, 0, 1254, 1255, 5, 114, 0, 0, 1255, 1256, 5, 101, 0, 0, 1256, 1257, 5, 99, 0, 0, 1257, 244, 1, 0, 0, 0, 1258, 1259, 5, 111, 0, 0, 1259, 1260, 5, 112, 0, 0, 1260, 1261, 5, 101, 0, 0, 1261, 1262, 5, 114, 0, 0, 1262, 1263, 5, 97, 0, 0, 1263, 1264, 5, 116, 0, 0, 1264, 1265, 5, 111, 0, 0, 1265, 1266, 5, 114, 0, 0, 1266, 246, 1, 0, 0, 0, 1267, 1268, 5, 105, 0, 0, 1268, 1269, 5, 110, 0, 0, 1269, 1270, 5, 108, 0, 0, 1270, 1271, 5, 105, 0, 0, 1271, 1272, 5, 110, 0, 0, 1272, 1273, 5, 101, 0, 0, 1273, 248, 1, 0, 0, 0, 1274, 1275, 5, 105, 0, 0, 1275, 1276, 5, 110, 0, 0, 1276, 1277, 5, 102, 0, 0, 1277, 1278, 5, 105, 0, 0, 1278, 1279, 5, 120, 0, 0, 1279, 250, 1, 0, 0, 0, 1280, 1281, 5, 101, 0, 0, 1281, 1282, 5, 120, 0, 0, 1282, 1283, 5, 116, 0, 0, 1283, 1284, 5, 101, 0, 0, 1284, 1285, 5, 114, 0, 0, 1285, 1286, 5, 110, 0, 0, 1286, 1287, 5, 97, 0, 0, 1287, 1288, 5, 108, 0, 0, 1288, 252, 1, 0, 0, 0, 1289, 1290, 5, 115, 0, 0, 1290, 1291, 5, 117, 0, 0, 1291, 1292, 5, 115, 0, 0, 1292, 1293, 5, 112, 0, 0, 1293, 1294, 5, 101, 0, 0, 1294, 1295, 5, 110, 0, 0, 1295, 1296, 5, 100, 0, 0, 1296, 254, 1, 0, 0, 0, 1297, 1298, 5, 111, 0, 0, 1298, 1299, 5, 118, 0, 0, 1299, 1300, 5, 101, 0, 0, 1300, 1301, 5, 114, 0, 0, 1301, 1302, 5, 114, 0, 0, 1302, 1303, 5, 105, 0, 0, 1303, 1304, 5, 100, 0, 0, 1304, 1305, 5, 101, 0, 0, 1305, 256, 1, 0, 0, 0, 1306, 1307, 5, 97, 0, 0, 1307, 1308, 5, 98, 0, 0, 1308, 1309, 5, 115, 0, 0, 1309, 1310, 5, 116, 0, 0, 1310, 1311, 5, 114, 0, 0, 1311, 1312, 5, 97, 0, 0, 1312, 1313, 5, 99, 0, 0, 1313, 1314, 5, 116, 0, 0, 1314, 258, 1, 0, 0, 0, 1315, 1316, 5, 102, 0, 0, 1316, 1317, 5, 105, 0, 0, 1317, 1318, 5, 110, 0, 0, 1318, 1319, 5, 97, 0, 0, 1319, 1320, 5, 108, 0, 0, 1320, 260, 1, 0, 0, 0, 1321, 1322, 5, 111, 0, 0, 1322, 1323, 5, 112, 0, 0, 1323, 1324, 5, 101, 0, 0, 1324, 1325, 5, 110, 0, 0, 1325, 262, 1, 0, 0, 0, 1326, 1327, 5, 99, 0, 0, 1327, 1328, 5, 111, 0, 0, 1328, 1329, 5, 110, 0, 0, 1329, 1330, 5, 115, 0, 0, 1330, 1331, 5, 116, 0, 0, 1331, 264, 1, 0, 0, 0, 1332, 1333, 5, 108, 0, 0, 1333, 1334, 5, 97, 0, 0, 1334, 1335, 5, 116, 0, 0, 1335, 1336, 5, 101, 0, 0, 1336, 1337, 5, 105, 0, 0, 1337, 1338, 5, 110, 0, 0, 1338, 1339, 5, 105, 0, 0, 1339, 1340, 5, 116, 0, 0, 1340, 266, 1, 0, 0, 0, 1341, 1342, 5, 118, 0, 0, 1342, 1343, 5, 97, 0, 0, 1343, 1344, 5, 114, 0, 0, 1344, 1345, 5, 97, 0, 0, 1345, 1346, 5, 114, 0, 0, 1346, 1347, 5, 103, 0, 0, 1347, 268, 1, 0, 0, 0, 1348, 1349, 5, 110, 0, 0, 1349, 1350, 5, 111, 0, 0, 1350, 1351, 5, 105, 0, 0, 1351, 1352, 5, 110, 0, 0, 1352, 1353, 5, 108, 0, 0, 1353, 1354, 5, 105, 0, 0, 1354, 1355, 5, 110, 0, 0, 1355, 1356, 5, 101, 0, 0, 1356, 270, 1, 0, 0, 0, 1357, 1358, 5, 99, 0, 0, 1358, 1359, 5, 114, 0, 0, 1359, 1360, 5, 111, 0, 0, 1360, 1361, 5, 115, 0, 0, 1361, 1362, 5, 115, 0, 0, 1362, 1363, 5, 105, 0, 0, 1363, 1364, 5, 110, 0, 0, 1364, 1365, 5, 108, 0, 0, 1365, 1366, 5, 105, 0, 0, 1366, 1367, 5, 110, 0, 0, 1367, 1368, 5, 101, 0, 0, 1368, 272, 1, 0, 0, 0, 1369, 1370, 5, 114, 0, 0, 1370, 1371, 5, 101, 0, 0, 1371, 1372, 5, 105, 0, 0, 1372, 1373, 5, 102, 0, 0, 1373, 1374, 5, 105, 0, 0, 1374, 1375, 5, 101, 0, 0, 1375, 1376, 5, 100, 0, 0, 1376, 274, 1, 0, 0, 0, 1377, 1378, 5, 101, 0, 0, 1378, 1379, 5, 120, 0, 0, 1379, 1380, 5, 112, 0, 0, 1380, 1381, 5, 101, 0, 0, 1381, 1382, 5, 99, 0, 0, 1382, 1383, 5, 116, 0, 0, 1383, 276, 1, 0, 0, 0, 1384, 1385, 5, 97, 0, 0, 1385, 1386, 5, 99, 0, 0, 1386, 1387, 5, 116, 0, 0, 1387, 1388, 5, 117, 0, 0, 1388, 1389, 5, 97, 0, 0, 1389, 1390, 5, 108, 0, 0, 1390, 278, 1, 0, 0, 0, 1391, 1392, 2, 48, 57, 0, 1392, 280, 1, 0, 0, 0, 1393, 1394, 2, 49, 57, 0, 1394, 282, 1, 0, 0, 0, 1395, 1398, 3, 279, 137, 0, 1396, 1398, 5, 95, 0, 0, 1397, 1395, 1, 0, 0, 0, 1397, 1396, 1, 0, 0, 0, 1398, 284, 1, 0, 0, 0, 1399, 1403, 3, 279, 137, 0, 1400, 1402, 3, 283, 139, 0, 1401, 1400, 1, 0, 0, 0, 1402, 1405, 1, 0, 0, 0, 1403, 1401, 1, 0, 0, 0, 1403, 1404, 1, 0, 0, 0, 1404, 1406, 1, 0, 0, 0, 1405, 1403, 1, 0, 0, 0, 1406, 1407, 3, 279, 137, 0, 1407, 1410, 1, 0, 0, 0, 1408, 1410, 3, 279, 137, 0, 1409, 1399, 1, 0, 0, 0, 1409, 1408, 1, 0, 0, 0, 1410, 286, 1, 0, 0, 0, 1411, 1413, 7, 2, 0, 0, 1412, 1414, 7, 3, 0, 0, 1413, 1412, 1, 0, 0, 0, 1413, 1414, 1, 0, 0, 0, 1414, 1415, 1, 0, 0, 0, 1415, 1416, 3, 285, 140, 0, 1416, 288, 1, 0, 0, 0, 1417, 1420, 3, 291, 143, 0, 1418, 1420, 3, 293, 144, 0, 1419, 1417, 1, 0, 0, 0, 1419, 1418, 1, 0, 0, 0, 1420, 290, 1, 0, 0, 0, 1421, 1422, 3, 293, 144, 0, 1422, 1423, 7, 4, 0, 0, 1423, 1428, 1, 0, 0, 0, 1424, 1425, 3, 285, 140, 0, 1425, 1426, 7, 4, 0, 0, 1426, 1428, 1, 0, 0, 0, 1427, 1421, 1, 0, 0, 0, 1427, 1424, 1, 0, 0, 0, 1428, 292, 1, 0, 0, 0, 1429, 1431, 3, 285, 140, 0, 1430, 1429, 1, 0, 0, 0, 1430, 1431, 1, 0, 0, 0, 1431, 1432, 1, 0, 0, 0, 1432, 1433, 5, 46, 0, 0, 1433, 1435, 3, 285, 140, 0, 1434, 1436, 3, 287, 141, 0, 1435, 1434, 1, 0, 0, 0, 1435, 1436, 1, 0, 0, 0, 1436, 1441, 1, 0, 0, 0, 1437, 1438, 3, 285, 140, 0, 1438, 1439, 3, 287, 141, 0, 1439, 1441, 1, 0, 0, 0, 1440, 1430, 1, 0, 0, 0, 1440, 1437, 1, 0, 0, 0, 1441, 294, 1, 0, 0, 0, 1442, 1446, 3, 281, 138, 0, 1443, 1445, 3, 283, 139, 0, 1444, 1443, 1, 0, 0, 0, 1445, 1448, 1, 0, 0, 0, 1446, 1444, 1, 0, 0, 0, 1446, 1447, 1, 0, 0, 0, 1447, 1449, 1, 0, 0, 0, 1448, 1446, 1, 0, 0, 0, 1449, 1450, 3, 279, 137, 0, 1450, 1453, 1, 0, 0, 0, 1451, 1453, 3, 279, 137, 0, 1452, 1442, 1, 0, 0, 0, 1452, 1451, 1, 0, 0, 0, 1453, 296, 1, 0, 0, 0, 1454, 1455, 7, 5, 0, 0, 1455, 298, 1, 0, 0, 0, 1456, 1459, 3, 297, 146, 0, 1457, 1459, 5, 95, 0, 0, 1458, 1456, 1, 0, 0, 0, 1458, 1457, 1, 0, 0, 0, 1459, 300, 1, 0, 0, 0, 1460, 1461, 5, 48, 0, 0, 1461, 1462, 7, 6, 0, 0, 1462, 1466, 3, 297, 146, 0, 1463, 1465, 3, 299, 147, 0, 1464, 1463, 1, 0, 0, 0, 1465, 1468, 1, 0, 0, 0, 1466, 1464, 1, 0, 0, 0, 1466, 1467, 1, 0, 0, 0, 1467, 1469, 1, 0, 0, 0, 1468, 1466, 1, 0, 0, 0, 1469, 1470, 3, 297, 146, 0, 1470, 1475, 1, 0, 0, 0, 1471, 1472, 5, 48, 0, 0, 1472, 1473, 7, 6, 0, 0, 1473, 1475, 3, 297, 146, 0, 1474, 1460, 1, 0, 0, 0, 1474, 1471, 1, 0, 0, 0, 1475, 302, 1, 0, 0, 0, 1476, 1477, 7, 7, 0, 0, 1477, 304, 1, 0, 0, 0, 1478, 1481, 3, 303, 149, 0, 1479, 1481, 5, 95, 0, 0, 1480, 1478, 1, 0, 0, 0, 1480, 1479, 1, 0, 0, 0, 1481, 306, 1, 0, 0, 0, 1482, 1483, 5, 48, 0, 0, 1483, 1484, 7, 8, 0, 0, 1484, 1488, 3, 303, 149, 0, 1485, 1487, 3, 305, 150, 0, 1486, 1485, 1, 0, 0, 0, 1487, 1490, 1, 0, 0, 0, 1488, 1486, 1, 0, 0, 0, 1488, 1489, 1, 0, 0, 0, 1489, 1491, 1, 0, 0, 0, 1490, 1488, 1, 0, 0, 0, 1491, 1492, 3, 303, 149, 0, 1492, 1497, 1, 0, 0, 0, 1493, 1494, 5, 48, 0, 0, 1494, 1495, 7, 8, 0, 0, 1495, 1497, 3, 303, 149, 0, 1496, 1482, 1, 0, 0, 0, 1496, 1493, 1, 0, 0, 0, 1497, 308, 1, 0, 0, 0, 1498, 1502, 3, 295, 145, 0, 1499, 1502, 3, 301, 148, 0, 1500, 1502, 3, 307, 151, 0, 1501, 1498, 1, 0, 0, 0, 1501, 1499, 1, 0, 0, 0, 1501, 1500, 1, 0, 0, 0, 1502, 1503, 1, 0, 0, 0, 1503, 1505, 7, 9, 0, 0, 1504, 1506, 7, 10, 0, 0, 1505, 1504, 1, 0, 0, 0, 1505, 1506, 1, 0, 0, 0, 1506, 310, 1, 0, 0, 0, 1507, 1511, 3, 295, 145, 0, 1508, 1511, 3, 301, 148, 0, 1509, 1511, 3, 307, 151, 0, 1510, 1507, 1, 0, 0, 0, 1510, 1508, 1, 0, 0, 0, 1510, 1509, 1, 0, 0, 0, 1511, 1512, 1, 0, 0, 0, 1512, 1513, 7, 10, 0, 0, 1513, 312, 1, 0, 0, 0, 1514, 1515, 5, 116, 0, 0, 1515, 1516, 5, 114, 0, 0, 1516, 1517, 5, 117, 0, 0, 1517, 1524, 5, 101, 0, 0, 1518, 1519, 5, 102, 0, 0, 1519, 1520, 5, 97, 0, 0, 1520, 1521, 5, 108, 0, 0, 1521, 1522, 5, 115, 0, 0, 1522, 1524, 5, 101, 0, 0, 1523, 1514, 1, 0, 0, 0, 1523, 1518, 1, 0, 0, 0, 1524, 314, 1, 0, 0, 0, 1525, 1526, 5, 110, 0, 0, 1526, 1527, 5, 117, 0, 0, 1527, 1528, 5, 108, 0, 0, 1528, 1529, 5, 108, 0, 0, 1529, 316, 1, 0, 0, 0, 1530, 1533, 5, 39, 0, 0, 1531, 1534, 3, 331, 163, 0, 1532, 1534, 8, 11, 0, 0, 1533, 1531, 1, 0, 0, 0, 1533, 1532, 1, 0, 0, 0, 1534, 1535, 1, 0, 0, 0, 1535, 1536, 5, 39, 0, 0, 1536, 318, 1, 0, 0, 0, 1537, 1538, 3, 349, 172, 0, 1538, 320, 1, 0, 0, 0, 1539, 1542, 3, 333, 164, 0, 1540, 1542, 5, 95, 0, 0, 1541, 1539, 1, 0, 0, 0, 1541, 1540, 1, 0, 0, 0, 1542, 1548, 1, 0, 0, 0, 1543, 1547, 3, 333, 164, 0, 1544, 1547, 5, 95, 0, 0, 1545, 1547, 3, 319, 157, 0, 1546, 1543, 1, 0, 0, 0, 1546, 1544, 1, 0, 0, 0, 1546, 1545, 1, 0, 0, 0, 1547, 1550, 1, 0, 0, 0, 1548, 1546, 1, 0, 0, 0, 1548, 1549, 1, 0, 0, 0, 1549, 1559, 1, 0, 0, 0, 1550, 1548, 1, 0, 0, 0, 1551, 1553, 5, 96, 0, 0, 1552, 1554, 8, 12, 0, 0, 1553, 1552, 1, 0, 0, 0, 1554, 1555, 1, 0, 0, 0, 1555, 1553, 1, 0, 0, 0, 1555, 1556, 1, 0, 0, 0, 1556, 1557, 1, 0, 0, 0, 1557, 1559, 5, 96, 0, 0, 1558, 1541, 1, 0, 0, 0, 1558, 1551, 1, 0, 0, 0, 1559, 322, 1, 0, 0, 0, 1560, 1609, 3, 321, 158, 0, 1561, 1609, 3, 257, 126, 0, 1562, 1609, 3, 235, 115, 0, 1563, 1609, 3, 169, 82, 0, 1564, 1609, 3, 191, 93, 0, 1565, 1609, 3, 171, 83, 0, 1566, 1609, 3, 167, 81, 0, 1567, 1609, 3, 271, 133, 0, 1568, 1609, 3, 237, 116, 0, 1569, 1609, 3, 221, 108, 0, 1570, 1609, 3, 231, 113, 0, 1571, 1609, 3, 251, 123, 0, 1572, 1609, 3, 259, 127, 0, 1573, 1609, 3, 193, 94, 0, 1574, 1609, 3, 151, 73, 0, 1575, 1609, 3, 249, 122, 0, 1576, 1609, 3, 173, 84, 0, 1577, 1609, 3, 247, 121, 0, 1578, 1609, 3, 239, 117, 0, 1579, 1609, 3, 229, 112, 0, 1580, 1609, 3, 265, 130, 0, 1581, 1609, 3, 269, 132, 0, 1582, 1609, 3, 261, 128, 0, 1583, 1609, 3, 245, 120, 0, 1584, 1609, 3, 219, 107, 0, 1585, 1609, 3, 255, 125, 0, 1586, 1609, 3, 225, 110, 0, 1587, 1609, 3, 227, 111, 0, 1588, 1609, 3, 223, 109, 0, 1589, 1609, 3, 273, 134, 0, 1590, 1609, 3, 233, 114, 0, 1591, 1609, 3, 243, 119, 0, 1592, 1609, 3, 267, 131, 0, 1593, 1609, 3, 181, 88, 0, 1594, 1609, 3, 137, 66, 0, 1595, 1609, 3, 139, 67, 0, 1596, 1609, 3, 133, 64, 0, 1597, 1609, 3, 135, 65, 0, 1598, 1609, 3, 141, 68, 0, 1599, 1609, 3, 143, 69, 0, 1600, 1609, 3, 145, 70, 0, 1601, 1609, 3, 147, 71, 0, 1602, 1609, 3, 131, 63, 0, 1603, 1609, 3, 275, 135, 0, 1604, 1609, 3, 277, 136, 0, 1605, 1609, 3, 241, 118, 0, 1606, 1609, 3, 263, 129, 0, 1607, 1609, 3, 253, 124, 0, 1608, 1560, 1, 0, 0, 0, 1608, 1561, 1, 0, 0, 0, 1608, 1562, 1, 0, 0, 0, 1608, 1563, 1, 0, 0, 0, 1608, 1564, 1, 0, 0, 0, 1608, 1565, 1, 0, 0, 0, 1608, 1566, 1, 0, 0, 0, 1608, 1567, 1, 0, 0, 0, 1608, 1568, 1, 0, 0, 0, 1608, 1569, 1, 0, 0, 0, 1608, 1570, 1, 0, 0, 0, 1608, 1571, 1, 0, 0, 0, 1608, 1572, 1, 0, 0, 0, 1608, 1573, 1, 0, 0, 0, 1608, 1574, 1, 0, 0, 0, 1608, 1575, 1, 0, 0, 0, 1608, 1576, 1, 0, 0, 0, 1608, 1577, 1, 0, 0, 0, 1608, 1578, 1, 0, 0, 0, 1608, 1579, 1, 0, 0, 0, 1608, 1580, 1, 0, 0, 0, 1608, 1581, 1, 0, 0, 0, 1608, 1582, 1, 0, 0, 0, 1608, 1583, 1, 0, 0, 0, 1608, 1584, 1, 0, 0, 0, 1608, 1585, 1, 0, 0, 0, 1608, 1586, 1, 0, 0, 0, 1608, 1587, 1, 0, 0, 0, 1608, 1588, 1, 0, 0, 0, 1608, 1589, 1, 0, 0, 0, 1608, 1590, 1, 0, 0, 0, 1608, 1591, 1, 0, 0, 0, 1608, 1592, 1, 0, 0, 0, 1608, 1593, 1, 0, 0, 0, 1608, 1594, 1, 0, 0, 0, 1608, 1595, 1, 0, 0, 0, 1608, 1596, 1, 0, 0, 0, 1608, 1597, 1, 0, 0, 0, 1608, 1598, 1, 0, 0, 0, 1608, 1599, 1, 0, 0, 0, 1608, 1600, 1, 0, 0, 0, 1608, 1601, 1, 0, 0, 0, 1608, 1602, 1, 0, 0, 0, 1608, 1603, 1, 0, 0, 0, 1608, 1604, 1, 0, 0, 0, 1608, 1605, 1, 0, 0, 0, 1608, 1606, 1, 0, 0, 0, 1608, 1607, 1, 0, 0, 0, 1609, 324, 1, 0, 0, 0, 1610, 1611, 5, 36, 0, 0, 1611, 1612, 3, 323, 159, 0, 1612, 326, 1, 0, 0, 0, 1613, 1614, 5, 92, 0, 0, 1614, 1615, 5, 117, 0, 0, 1615, 1616, 3, 297, 146, 0, 1616, 1617, 3, 297, 146, 0, 1617, 1618, 3, 297, 146, 0, 1618, 1619, 3, 297, 146, 0, 1619, 328, 1, 0, 0, 0, 1620, 1621, 5, 92, 0, 0, 1621, 1622, 7, 13, 0, 0, 1622, 330, 1, 0, 0, 0, 1623, 1626, 3, 327, 161, 0, 1624, 1626, 3, 329, 162, 0, 1625, 1623, 1, 0, 0, 0, 1625, 1624, 1, 0, 0, 0, 1626, 332, 1, 0, 0, 0, 1627, 1633, 3, 347, 171, 0, 1628, 1633, 3, 339, 167, 0, 1629, 1633, 3, 345, 170, 0, 1630, 1633, 3, 341, 168, 0, 1631, 1633, 3, 343, 169, 0, 1632, 1627, 1, 0, 0, 0, 1632, 1628, 1, 0, 0, 0, 1632, 1629, 1, 0, 0, 0, 1632, 1630, 1, 0, 0, 0, 1632, 1631, 1, 0, 0, 0, 1633, 334, 1, 0, 0, 0, 1634, 1635, 5, 34, 0, 0, 1635, 1636, 1, 0, 0, 0, 1636, 1637, 6, 165, 4, 0, 1637, 336, 1, 0, 0, 0, 1638, 1639, 5, 34, 0, 0, 1639, 1640, 5, 34, 0, 0, 1640, 1641, 5, 34, 0, 0, 1641, 1642, 1, 0, 0, 0, 1642, 1643, 6, 166, 5, 0, 1643, 338, 1, 0, 0, 0, 1644, 1645, 7, 14, 0, 0, 1645, 340, 1, 0, 0, 0, 1646, 1647, 7, 15, 0, 0, 1647, 342, 1, 0, 0, 0, 1648, 1649, 7, 16, 0, 0, 1649, 344, 1, 0, 0, 0, 1650, 1651, 7, 17, 0, 0, 1651, 346, 1, 0, 0, 0, 1652, 1653, 7, 18, 0, 0, 1653, 348, 1, 0, 0, 0, 1654, 1655, 7, 19, 0, 0, 1655, 350, 1, 0, 0, 0, 1656, 1657, 7, 20, 0, 0, 1657, 352, 1, 0, 0, 0, 1658, 1659, 5, 34, 0, 0, 1659, 1660, 1, 0, 0, 0, 1660, 1661, 6, 174, 3, 0, 1661, 354, 1, 0, 0, 0, 1662, 1663, 3, 325, 160, 0, 1663, 356, 1, 0, 0, 0, 1664, 1666, 8, 21, 0, 0, 1665, 1664, 1, 0, 0, 0, 1666, 1667, 1, 0, 0, 0, 1667, 1665, 1, 0, 0, 0, 1667, 1668, 1, 0, 0, 0, 1668, 1671, 1, 0, 0, 0, 1669, 1671, 5, 36, 0, 0, 1670, 1665, 1, 0, 0, 0, 1670, 1669, 1, 0, 0, 0, 1671, 358, 1, 0, 0, 0, 1672, 1675, 3, 329, 162, 0, 1673, 1675, 3, 327, 161, 0, 1674, 1672, 1, 0, 0, 0, 1674, 1673, 1, 0, 0, 0, 1675, 360, 1, 0, 0, 0, 1676, 1677, 5, 36, 0, 0, 1677, 1678, 5, 123, 0, 0, 1678, 1679, 1, 0, 0, 0, 1679, 1680, 6, 178, 2, 0, 1680, 362, 1, 0, 0, 0, 1681, 1683, 3, 365, 180, 0, 1682, 1681, 1, 0, 0, 0, 1682, 1683, 1, 0, 0, 0, 1683, 1684, 1, 0, 0, 0, 1684, 1685, 5, 34, 0, 0, 1685, 1686, 5, 34, 0, 0, 1686, 1687, 5, 34, 0, 0, 1687, 1688, 1, 0, 0, 0, 1688, 1689, 6, 179, 3, 0, 1689, 364, 1, 0, 0, 0, 1690, 1692, 5, 34, 0, 0, 1691, 1690, 1, 0, 0, 0, 1692, 1693, 1, 0, 0, 0, 1693, 1691, 1, 0, 0, 0, 1693, 1694, 1, 0, 0, 0, 1694, 366, 1, 0, 0, 0, 1695, 1696, 3, 325, 160, 0, 1696, 368, 1, 0, 0, 0, 1697, 1699, 8, 22, 0, 0, 1698, 1697, 1, 0, 0, 0, 1699, 1700, 1, 0, 0, 0, 1700, 1698, 1, 0, 0, 0, 1700, 1701, 1, 0, 0, 0, 1701, 1704, 1, 0, 0, 0, 1702, 1704, 5, 36, 0, 0, 1703, 1698, 1, 0, 0, 0, 1703, 1702, 1, 0, 0, 0, 1704, 370, 1, 0, 0, 0, 1705, 1706, 5, 36, 0, 0, 1706, 1707, 5, 123, 0, 0, 1707, 1708, 1, 0, 0, 0, 1708, 1709, 6, 183, 2, 0, 1709, 372, 1, 0, 0, 0, 1710, 1711, 3, 25, 10, 0, 1711, 1712, 1, 0, 0, 0, 1712, 1713, 6, 184, 3, 0, 1713, 1714, 6, 184, 6, 0, 1714, 374, 1, 0, 0, 0, 1715, 1716, 3, 29, 12, 0, 1716, 1717, 1, 0, 0, 0, 1717, 1718, 6, 185, 3, 0, 1718, 1719, 6, 185, 7, 0, 1719, 376, 1, 0, 0, 0, 1720, 1721, 3, 23, 9, 0, 1721, 1722, 1, 0, 0, 0, 1722, 1723, 6, 186, 1, 0, 1723, 1724, 6, 186, 8, 0, 1724, 378, 1, 0, 0, 0, 1725, 1726, 3, 27, 11, 0, 1726, 1727, 1, 0, 0, 0, 1727, 1728, 6, 187, 1, 0, 1728, 1729, 6, 187, 9, 0, 1729, 380, 1, 0, 0, 0, 1730, 1731, 3, 31, 13, 0, 1731, 1732, 1, 0, 0, 0, 1732, 1733, 6, 188, 2, 0, 1733, 1734, 6, 188, 10, 0, 1734, 382, 1, 0, 0, 0, 1735, 1736, 3, 33, 14, 0, 1736, 1737, 1, 0, 0, 0, 1737, 1738, 6, 189, 3, 0, 1738, 1739, 6, 189, 11, 0, 1739, 384, 1, 0, 0, 0, 1740, 1741, 3, 19, 7, 0, 1741, 1742, 1, 0, 0, 0, 1742, 1743, 6, 190, 12, 0, 1743, 386, 1, 0, 0, 0, 1744, 1745, 3, 21, 8, 0, 1745, 1746, 1, 0, 0, 0, 1746, 1747, 6, 191, 13, 0, 1747, 388, 1, 0, 0, 0, 1748, 1749, 3, 35, 15, 0, 1749, 1750, 1, 0, 0, 0, 1750, 1751, 6, 192, 14, 0, 1751, 390, 1, 0, 0, 0, 1752, 1753, 3, 37, 16, 0, 1753, 1754, 1, 0, 0, 0, 1754, 1755, 6, 193, 15, 0, 1755, 392, 1, 0, 0, 0, 1756, 1757, 3, 39, 17, 0, 1757, 1758, 1, 0, 0, 0, 1758, 1759, 6, 194, 16, 0, 1759, 394, 1, 0, 0, 0, 1760, 1761, 3, 41, 18, 0, 1761, 1762, 1, 0, 0, 0, 1762, 1763, 6, 195, 17, 0, 1763, 396, 1, 0, 0, 0, 1764, 1765, 3, 43, 19, 0, 1765, 1766, 1, 0, 0, 0, 1766, 1767, 6, 196, 18, 0, 1767, 398, 1, 0, 0, 0, 1768, 1769, 3, 45, 20, 0, 1769, 1770, 1, 0, 0, 0, 1770, 1771, 6, 197, 19, 0, 1771, 400, 1, 0, 0, 0, 1772, 1773, 3, 47, 21, 0, 1773, 1774, 1, 0, 0, 0, 1774, 1775, 6, 198, 20, 0, 1775, 402, 1, 0, 0, 0, 1776, 1777, 3, 49, 22, 0, 1777, 1778, 1, 0, 0, 0, 1778, 1779, 6, 199, 21, 0, 1779, 404, 1, 0, 0, 0, 1780, 1781, 3, 51, 23, 0, 1781, 1782, 1, 0, 0, 0, 1782, 1783, 6, 200, 22, 0, 1783, 406, 1, 0, 0, 0, 1784, 1787, 5, 33, 0, 0, 1785, 1788, 3, 15, 5, 0, 1786, 1788, 3, 13, 4, 0, 1787, 1785, 1, 0, 0, 0, 1787, 1786, 1, 0, 0, 0, 1788, 1789, 1, 0, 0, 0, 1789, 1790, 6, 201, 23, 0, 1790, 408, 1, 0, 0, 0, 1791, 1792, 3, 55, 25, 0, 1792, 1793, 1, 0, 0, 0, 1793, 1794, 6, 202, 24, 0, 1794, 410, 1, 0, 0, 0, 1795, 1796, 3, 57, 26, 0, 1796, 1797, 1, 0, 0, 0, 1797, 1798, 6, 203, 25, 0, 1798, 412, 1, 0, 0, 0, 1799, 1800, 3, 59, 27, 0, 1800, 1801, 1, 0, 0, 0, 1801, 1802, 6, 204, 26, 0, 1802, 414, 1, 0, 0, 0, 1803, 1804, 3, 61, 28, 0, 1804, 1805, 1, 0, 0, 0, 1805, 1806, 6, 205, 27, 0, 1806, 416, 1, 0, 0, 0, 1807, 1808, 3, 63, 29, 0, 1808, 1809, 1, 0, 0, 0, 1809, 1810, 6, 206, 28, 0, 1810, 418, 1, 0, 0, 0, 1811, 1812, 3, 65, 30, 0, 1812, 1813, 1, 0, 0, 0, 1813, 1814, 6, 207, 29, 0, 1814, 420, 1, 0, 0, 0, 1815, 1816, 3, 67, 31, 0, 1816, 1817, 1, 0, 0, 0, 1817, 1818, 6, 208, 30, 0, 1818, 422, 1, 0, 0, 0, 1819, 1820, 3, 69, 32, 0, 1820, 1821, 1, 0, 0, 0, 1821, 1822, 6, 209, 31, 0, 1822, 424, 1, 0, 0, 0, 1823, 1824, 3, 71, 33, 0, 1824, 1825, 1, 0, 0, 0, 1825, 1826, 6, 210, 32, 0, 1826, 426, 1, 0, 0, 0, 1827, 1828, 3, 73, 34, 0, 1828, 1829, 1, 0, 0, 0, 1829, 1830, 6, 211, 33, 0, 1830, 428, 1, 0, 0, 0, 1831, 1832, 3, 75, 35, 0, 1832, 1833, 1, 0, 0, 0, 1833, 1834, 6, 212, 34, 0, 1834, 430, 1, 0, 0, 0, 1835, 1836, 3, 77, 36, 0, 1836, 1837, 1, 0, 0, 0, 1837, 1838, 6, 213, 35, 0, 1838, 432, 1, 0, 0, 0, 1839, 1840, 3, 79, 37, 0, 1840, 1841, 1, 0, 0, 0, 1841, 1842, 6, 214, 36, 0, 1842, 434, 1, 0, 0, 0, 1843, 1844, 3, 17, 6, 0, 1844, 1845, 1, 0, 0, 0, 1845, 1846, 6, 215, 37, 0, 1846, 436, 1, 0, 0, 0, 1847, 1848, 3, 81, 38, 0, 1848, 1849, 1, 0, 0, 0, 1849, 1850, 6, 216, 38, 0, 1850, 438, 1, 0, 0, 0, 1851, 1852, 3, 83, 39, 0, 1852, 1853, 1, 0, 0, 0, 1853, 1854, 6, 217, 39, 0, 1854, 440, 1, 0, 0, 0, 1855, 1856, 3, 85, 40, 0, 1856, 1857, 1, 0, 0, 0, 1857, 1858, 6, 218, 40, 0, 1858, 442, 1, 0, 0, 0, 1859, 1860, 3, 87, 41, 0, 1860, 1861, 1, 0, 0, 0, 1861, 1862, 6, 219, 41, 0, 1862, 444, 1, 0, 0, 0, 1863, 1864, 3, 89, 42, 0, 1864, 1865, 1, 0, 0, 0, 1865, 1866, 6, 220, 42, 0, 1866, 446, 1, 0, 0, 0, 1867, 1868, 3, 91, 43, 0, 1868, 1869, 1, 0, 0, 0, 1869, 1870, 6, 221, 43, 0, 1870, 448, 1, 0, 0, 0, 1871, 1872, 3, 93, 44, 0, 1872, 1873, 1, 0, 0, 0, 1873, 1874, 6, 222, 44, 0, 1874, 450, 1, 0, 0, 0, 1875, 1878, 5, 63, 0, 0, 1876, 1879, 3, 15, 5, 0, 1877, 1879, 3, 13, 4, 0, 1878, 1876, 1, 0, 0, 0, 1878, 1877, 1, 0, 0, 0, 1879, 1880, 1, 0, 0, 0, 1880, 1881, 6, 223, 45, 0, 1881, 452, 1, 0, 0, 0, 1882, 1883, 3, 97, 46, 0, 1883, 1884, 1, 0, 0, 0, 1884, 1885, 6, 224, 46, 0, 1885, 454, 1, 0, 0, 0, 1886, 1887, 3, 99, 47, 0, 1887, 1888, 1, 0, 0, 0, 1888, 1889, 6, 225, 47, 0, 1889, 456, 1, 0, 0, 0, 1890, 1891, 3, 101, 48, 0, 1891, 1892, 1, 0, 0, 0, 1892, 1893, 6, 226, 48, 0, 1893, 458, 1, 0, 0, 0, 1894, 1895, 3, 103, 49, 0, 1895, 1896, 1, 0, 0, 0, 1896, 1897, 6, 227, 49, 0, 1897, 460, 1, 0, 0, 0, 1898, 1899, 3, 105, 50, 0, 1899, 1900, 1, 0, 0, 0, 1900, 1901, 6, 228, 50, 0, 1901, 462, 1, 0, 0, 0, 1902, 1903, 3, 107, 51, 0, 1903, 1904, 1, 0, 0, 0, 1904, 1905, 6, 229, 51, 0, 1905, 464, 1, 0, 0, 0, 1906, 1907, 3, 109, 52, 0, 1907, 1908, 1, 0, 0, 0, 1908, 1909, 6, 230, 52, 0, 1909, 466, 1, 0, 0, 0, 1910, 1911, 3, 211, 103, 0, 1911, 1912, 1, 0, 0, 0, 1912, 1913, 6, 231, 53, 0, 1913, 468, 1, 0, 0, 0, 1914, 1915, 3, 215, 105, 0, 1915, 1916, 1, 0, 0, 0, 1916, 1917, 6, 232, 54, 0, 1917, 470, 1, 0, 0, 0, 1918, 1919, 3, 217, 106, 0, 1919, 1920, 1, 0, 0, 0, 1920, 1921, 6, 233, 55, 0, 1921, 472, 1, 0, 0, 0, 1922, 1923, 3, 209, 102, 0, 1923, 1924, 1, 0, 0, 0, 1924, 1925, 6, 234, 56, 0, 1925, 474, 1, 0, 0, 0, 1926, 1927, 3, 111, 53, 0, 1927, 1928, 1, 0, 0, 0, 1928, 1929, 6, 235, 57, 0, 1929, 476, 1, 0, 0, 0, 1930, 1931, 3, 113, 54, 0, 1931, 1932, 1, 0, 0, 0, 1932, 1933, 6, 236, 58, 0, 1933, 478, 1, 0, 0, 0, 1934, 1935, 3, 115, 55, 0, 1935, 1936, 1, 0, 0, 0, 1936, 1937, 6, 237, 59, 0, 1937, 480, 1, 0, 0, 0, 1938, 1939, 3, 117, 56, 0, 1939, 1940, 1, 0, 0, 0, 1940, 1941, 6, 238, 60, 0, 1941, 482, 1, 0, 0, 0, 1942, 1943, 3, 119, 57, 0, 1943, 1944, 1, 0, 0, 0, 1944, 1945, 6, 239, 61, 0, 1945, 484, 1, 0, 0, 0, 1946, 1947, 3, 335, 165, 0, 1947, 1948, 1, 0, 0, 0, 1948, 1949, 6, 240, 4, 0, 1949, 1950, 6, 240, 62, 0, 1950, 486, 1, 0, 0, 0, 1951, 1952, 3, 337, 166, 0, 1952, 1953, 1, 0, 0, 0, 1953, 1954, 6, 241, 5, 0, 1954, 1955, 6, 241, 63, 0, 1955, 488, 1, 0, 0, 0, 1956, 1957, 3, 161, 78, 0, 1957, 1958, 1, 0, 0, 0, 1958, 1959, 6, 242, 64, 0, 1959, 490, 1, 0, 0, 0, 1960, 1961, 3, 163, 79, 0, 1961, 1962, 1, 0, 0, 0, 1962, 1963, 6, 243, 65, 0, 1963, 492, 1, 0, 0, 0, 1964, 1965, 3, 157, 76, 0, 1965, 1966, 1, 0, 0, 0, 1966, 1967, 6, 244, 66, 0, 1967, 494, 1, 0, 0, 0, 1968, 1969, 3, 159, 77, 0, 1969, 1970, 1, 0, 0, 0, 1970, 1971, 6, 245, 67, 0, 1971, 496, 1, 0, 0, 0, 1972, 1973, 3, 177, 86, 0, 1973, 1974, 1, 0, 0, 0, 1974, 1975, 6, 246, 68, 0, 1975, 498, 1, 0, 0, 0, 1976, 1977, 3, 213, 104, 0, 1977, 1978, 1, 0, 0, 0, 1978, 1979, 6, 247, 69, 0, 1979, 500, 1, 0, 0, 0, 1980, 1981, 3, 219, 107, 0, 1981, 1982, 1, 0, 0, 0, 1982, 1983, 6, 248, 70, 0, 1983, 502, 1, 0, 0, 0, 1984, 1985, 3, 133, 64, 0, 1985, 1986, 1, 0, 0, 0, 1986, 1987, 6, 249, 71, 0, 1987, 504, 1, 0, 0, 0, 1988, 1989, 3, 131, 63, 0, 1989, 1990, 1, 0, 0, 0, 1990, 1991, 6, 250, 72, 0, 1991, 506, 1, 0, 0, 0, 1992, 1993, 3, 135, 65, 0, 1993, 1994, 1, 0, 0, 0, 1994, 1995, 6, 251, 73, 0, 1995, 508, 1, 0, 0, 0, 1996, 1997, 3, 137, 66, 0, 1997, 1998, 1, 0, 0, 0, 1998, 1999, 6, 252, 74, 0, 1999, 510, 1, 0, 0, 0, 2000, 2001, 3, 139, 67, 0, 2001, 2002, 1, 0, 0, 0, 2002, 2003, 6, 253, 75, 0, 2003, 512, 1, 0, 0, 0, 2004, 2005, 3, 141, 68, 0, 2005, 2006, 1, 0, 0, 0, 2006, 2007, 6, 254, 76, 0, 2007, 514, 1, 0, 0, 0, 2008, 2009, 3, 143, 69, 0, 2009, 2010, 1, 0, 0, 0, 2010, 2011, 6, 255, 77, 0, 2011, 516, 1, 0, 0, 0, 2012, 2013, 3, 145, 70, 0, 2013, 2014, 1, 0, 0, 0, 2014, 2015, 6, 256, 78, 0, 2015, 518, 1, 0, 0, 0, 2016, 2017, 3, 147, 71, 0, 2017, 2018, 1, 0, 0, 0, 2018, 2019, 6, 257, 79, 0, 2019, 520, 1, 0, 0, 0, 2020, 2021, 3, 201, 98, 0, 2021, 2022, 1, 0, 0, 0, 2022, 2023, 6, 258, 80, 0, 2023, 522, 1, 0, 0, 0, 2024, 2025, 3, 203, 99, 0, 2025, 2026, 1, 0, 0, 0, 2026, 2027, 6, 259, 81, 0, 2027, 524, 1, 0, 0, 0, 2028, 2029, 3, 205, 100, 0, 2029, 2030, 1, 0, 0, 0, 2030, 2031, 6, 260, 82, 0, 2031, 526, 1, 0, 0, 0, 2032, 2033, 3, 207, 101, 0, 2033, 2034, 1, 0, 0, 0, 2034, 2035, 6, 261, 83, 0, 2035, 528, 1, 0, 0, 0, 2036, 2037, 3, 121, 58, 0, 2037, 2038, 1, 0, 0, 0, 2038, 2039, 6, 262, 84, 0, 2039, 530, 1, 0, 0, 0, 2040, 2041, 3, 123, 59, 0, 2041, 2042, 1, 0, 0, 0, 2042, 2043, 6, 263, 85, 0, 2043, 532, 1, 0, 0, 0, 2044, 2045, 3, 125, 60, 0, 2045, 2046, 1, 0, 0, 0, 2046, 2047, 6, 264, 86, 0, 2047, 534, 1, 0, 0, 0, 2048, 2049, 3, 183, 89, 0, 2049, 2050, 1, 0, 0, 0, 2050, 2051, 6, 265, 87, 0, 2051, 536, 1, 0, 0, 0, 2052, 2053, 3, 185, 90, 0, 2053, 2054, 1, 0, 0, 0, 2054, 2055, 6, 266, 88, 0, 2055, 538, 1, 0, 0, 0, 2056, 2057, 3, 187, 91, 0, 2057, 2058, 1, 0, 0, 0, 2058, 2059, 6, 267, 89, 0, 2059, 540, 1, 0, 0, 0, 2060, 2061, 3, 189, 92, 0, 2061, 2062, 1, 0, 0, 0, 2062, 2063, 6, 268, 90, 0, 2063, 542, 1, 0, 0, 0, 2064, 2065, 3, 191, 93, 0, 2065, 2066, 1, 0, 0, 0, 2066, 2067, 6, 269, 91, 0, 2067, 544, 1, 0, 0, 0, 2068, 2069, 3, 193, 94, 0, 2069, 2070, 1, 0, 0, 0, 2070, 2071, 6, 270, 92, 0, 2071, 546, 1, 0, 0, 0, 2072, 2073, 3, 195, 95, 0, 2073, 2074, 1, 0, 0, 0, 2074, 2075, 6, 271, 93, 0, 2075, 548, 1, 0, 0, 0, 2076, 2077, 3, 197, 96, 0, 2077, 2078, 1, 0, 0, 0, 2078, 2079, 6, 272, 94, 0, 2079, 550, 1, 0, 0, 0, 2080, 2081, 3, 199, 97, 0, 2081, 2082, 1, 0, 0, 0, 2082, 2083, 6, 273, 95, 0, 2083, 552, 1, 0, 0, 0, 2084, 2085, 3, 223, 109, 0, 2085, 2086, 1, 0, 0, 0, 2086, 2087, 6, 274, 96, 0, 2087, 554, 1, 0, 0, 0, 2088, 2089, 3, 225, 110, 0, 2089, 2090, 1, 0, 0, 0, 2090, 2091, 6, 275, 97, 0, 2091, 556, 1, 0, 0, 0, 2092, 2093, 3, 227, 111, 0, 2093, 2094, 1, 0, 0, 0, 2094, 2095, 6, 276, 98, 0, 2095, 558, 1, 0, 0, 0, 2096, 2097, 3, 229, 112, 0, 2097, 2098, 1, 0, 0, 0, 2098, 2099, 6, 277, 99, 0, 2099, 560, 1, 0, 0, 0, 2100, 2101, 3, 231, 113, 0, 2101, 2102, 1, 0, 0, 0, 2102, 2103, 6, 278, 100, 0, 2103, 562, 1, 0, 0, 0, 2104, 2105, 3, 233, 114, 0, 2105, 2106, 1, 0, 0, 0, 2106, 2107, 6, 279, 101, 0, 2107, 564, 1, 0, 0, 0, 2108, 2109, 3, 235, 115, 0, 2109, 2110, 1, 0, 0, 0, 2110, 2111, 6, 280, 102, 0, 2111, 566, 1, 0, 0, 0, 2112, 2113, 3, 237, 116, 0, 2113, 2114, 1, 0, 0, 0, 2114, 2115, 6, 281, 103, 0, 2115, 568, 1, 0, 0, 0, 2116, 2117, 3, 239, 117, 0, 2117, 2118, 1, 0, 0, 0, 2118, 2119, 6, 282, 104, 0, 2119, 570, 1, 0, 0, 0, 2120, 2121, 3, 241, 118, 0, 2121, 2122, 1, 0, 0, 0, 2122, 2123, 6, 283, 105, 0, 2123, 572, 1, 0, 0, 0, 2124, 2125, 3, 243, 119, 0, 2125, 2126, 1, 0, 0, 0, 2126, 2127, 6, 284, 106, 0, 2127, 574, 1, 0, 0, 0, 2128, 2129, 3, 245, 120, 0, 2129, 2130, 1, 0, 0, 0, 2130, 2131, 6, 285, 107, 0, 2131, 576, 1, 0, 0, 0, 2132, 2133, 3, 247, 121, 0, 2133, 2134, 1, 0, 0, 0, 2134, 2135, 6, 286, 108, 0, 2135, 578, 1, 0, 0, 0, 2136, 2137, 3, 249, 122, 0, 2137, 2138, 1, 0, 0, 0, 2138, 2139, 6, 287, 109, 0, 2139, 580, 1, 0, 0, 0, 2140, 2141, 3, 251, 123, 0, 2141, 2142, 1, 0, 0, 0, 2142, 2143, 6, 288, 110, 0, 2143, 582, 1, 0, 0, 0, 2144, 2145, 3, 253, 124, 0, 2145, 2146, 1, 0, 0, 0, 2146, 2147, 6, 289, 111, 0, 2147, 584, 1, 0, 0, 0, 2148, 2149, 3, 255, 125, 0, 2149, 2150, 1, 0, 0, 0, 2150, 2151, 6, 290, 112, 0, 2151, 586, 1, 0, 0, 0, 2152, 2153, 3, 257, 126, 0, 2153, 2154, 1, 0, 0, 0, 2154, 2155, 6, 291, 113, 0, 2155, 588, 1, 0, 0, 0, 2156, 2157, 3, 259, 127, 0, 2157, 2158, 1, 0, 0, 0, 2158, 2159, 6, 292, 114, 0, 2159, 590, 1, 0, 0, 0, 2160, 2161, 3, 261, 128, 0, 2161, 2162, 1, 0, 0, 0, 2162, 2163, 6, 293, 115, 0, 2163, 592, 1, 0, 0, 0, 2164, 2165, 3, 263, 129, 0, 2165, 2166, 1, 0, 0, 0, 2166, 2167, 6, 294, 116, 0, 2167, 594, 1, 0, 0, 0, 2168, 2169, 3, 265, 130, 0, 2169, 2170, 1, 0, 0, 0, 2170, 2171, 6, 295, 117, 0, 2171, 596, 1, 0, 0, 0, 2172, 2173, 3, 267, 131, 0, 2173, 2174, 1, 0, 0, 0, 2174, 2175, 6, 296, 118, 0, 2175, 598, 1, 0, 0, 0, 2176, 2177, 3, 269, 132, 0, 2177, 2178, 1, 0, 0, 0, 2178, 2179, 6, 297, 119, 0, 2179, 600, 1, 0, 0, 0, 2180, 2181, 3, 271, 133, 0, 2181, 2182, 1, 0, 0, 0, 2182, 2183, 6, 298, 120, 0, 2183, 602, 1, 0, 0, 0, 2184, 2185, 3, 273, 134, 0, 2185, 2186, 1, 0, 0, 0, 2186, 2187, 6, 299, 121, 0, 2187, 604, 1, 0, 0, 0, 2188, 2189, 3, 275, 135, 0, 2189, 2190, 1, 0, 0, 0, 2190, 2191, 6, 300, 122, 0, 2191, 606, 1, 0, 0, 0, 2192, 2193, 3, 277, 136, 0, 2193, 2194, 1, 0, 0, 0, 2194, 2195, 6, 301, 123, 0, 2195, 608, 1, 0, 0, 0, 2196, 2197, 3, 313, 154, 0, 2197, 2198, 1, 0, 0, 0, 2198, 2199, 6, 302, 124, 0, 2199, 610, 1, 0, 0, 0, 2200, 2201, 3, 295, 145, 0, 2201, 2202, 1, 0, 0, 0, 2202, 2203, 6, 303, 125, 0, 2203, 612, 1, 0, 0, 0, 2204, 2205, 3, 301, 148, 0, 2205, 2206, 1, 0, 0, 0, 2206, 2207, 6, 304, 126, 0, 2207, 614, 1, 0, 0, 0, 2208, 2209, 3, 307, 151, 0, 2209, 2210, 1, 0, 0, 0, 2210, 2211, 6, 305, 127, 0, 2211, 616, 1, 0, 0, 0, 2212, 2213, 3, 317, 156, 0, 2213, 2214, 1, 0, 0, 0, 2214, 2215, 6, 306, 128, 0, 2215, 618, 1, 0, 0, 0, 2216, 2217, 3, 289, 142, 0, 2217, 2218, 1, 0, 0, 0, 2218, 2219, 6, 307, 129, 0, 2219, 620, 1, 0, 0, 0, 2220, 2221, 3, 315, 155, 0, 2221, 2222, 1, 0, 0, 0, 2222, 2223, 6, 308, 130, 0, 2223, 622, 1, 0, 0, 0, 2224, 2225, 3, 311, 153, 0, 2225, 2226, 1, 0, 0, 0, 2226, 2227, 6, 309, 131, 0, 2227, 624, 1, 0, 0, 0, 2228, 2229, 3, 309, 152, 0, 2229, 2230, 1, 0, 0, 0, 2230, 2231, 6, 310, 132, 0, 2231, 626, 1, 0, 0, 0, 2232, 2233, 3, 321, 158, 0, 2233, 2234, 1, 0, 0, 0, 2234, 2235, 6, 311, 133, 0, 2235, 628, 1, 0, 0, 0, 2236, 2239, 3, 9, 2, 0, 2237, 2239, 3, 7, 1, 0, 2238, 2236, 1, 0, 0, 0, 2238, 2237, 1, 0, 0, 0, 2239, 2240, 1, 0, 0, 0, 2240, 2241, 6, 312, 0, 0, 2241, 630, 1, 0, 0, 0, 2242, 2243, 3, 11, 3, 0, 2243, 2244, 1, 0, 0, 0, 2244, 2245, 6, 313, 0, 0, 2245, 632, 1, 0, 0, 0, 2246, 2247, 3, 13, 4, 0, 2247, 2248, 1, 0, 0, 0, 2248, 2249, 6, 314, 0, 0, 2249, 634, 1, 0, 0, 0, 2250, 2251, 9, 0, 0, 0, 2251, 636, 1, 0, 0, 0, 58, 0, 1, 2, 3, 4, 643, 651, 653, 667, 679, 681, 686, 790, 794, 800, 805, 1154, 1162, 1397, 1403, 1409, 1413, 1419, 1427, 1430, 1435, 1440, 1446, 1452, 1458, 1466, 1474, 1480, 1488, 1496, 1501, 1505, 1510, 1523, 1533, 1541, 1546, 1548, 1555, 1558, 1608, 1625, 1632, 1667, 1670, 1674, 1682, 1693, 1700, 1703, 1787, 1878, 2238, 134, 0, 1, 0, 5, 3, 0, 5, 0, 0, 4, 0, 0, 5, 1, 0, 5, 2, 0, 7, 10, 0, 7, 12, 0, 7, 9, 0, 7, 11, 0, 7, 13, 0, 7, 14, 0, 7, 7, 0, 7, 8, 0, 7, 15, 0, 7, 16, 0, 7, 17, 0, 7, 18, 0, 7, 19, 0, 7, 20, 0, 7, 21, 0, 7, 22, 0, 7, 23, 0, 7, 24, 0, 7, 25, 0, 7, 26, 0, 7, 27, 0, 7, 28, 0, 7, 29, 0, 7, 30, 0, 7, 31, 0, 7, 32, 0, 7, 33, 0, 7, 34, 0, 7, 35, 0, 7, 36, 0, 7, 37, 0, 7, 6, 0, 7, 38, 0, 7, 39, 0, 7, 40, 0, 7, 41, 0, 7, 42, 0, 7, 43, 0, 7, 44, 0, 7, 45, 0, 7, 46, 0, 7, 47, 0, 7, 48, 0, 7, 49, 0, 7, 50, 0, 7, 51, 0, 7, 52, 0, 7, 103, 0, 7, 105, 0, 7, 106, 0, 7, 102, 0, 7, 53, 0, 7, 54, 0, 7, 55, 0, 7, 56, 0, 7, 57, 0, 7, 151, 0, 7, 152, 0, 7, 78, 0, 7, 79, 0, 7, 76, 0, 7, 77, 0, 7, 86, 0, 7, 104, 0, 7, 107, 0, 7, 64, 0, 7, 63, 0, 7, 65, 0, 7, 66, 0, 7, 67, 0, 7, 68, 0, 7, 69, 0, 7, 70, 0, 7, 71, 0, 7, 98, 0, 7, 99, 0, 7, 100, 0, 7, 101, 0, 7, 58, 0, 7, 59, 0, 7, 60, 0, 7, 89, 0, 7, 90, 0, 7, 91, 0, 7, 92, 0, 7, 93, 0, 7, 94, 0, 7, 95, 0, 7, 96, 0, 7, 97, 0, 7, 109, 0, 7, 110, 0, 7, 111, 0, 7, 112, 0, 7, 113, 0, 7, 114, 0, 7, 115, 0, 7, 116, 0, 7, 117, 0, 7, 118, 0, 7, 119, 0, 7, 120, 0, 7, 121, 0, 7, 122, 0, 7, 123, 0, 7, 124, 0, 7, 125, 0, 7, 126, 0, 7, 127, 0, 7, 128, 0, 7, 129, 0, 7, 130, 0, 7, 131, 0, 7, 132, 0, 7, 133, 0, 7, 134, 0, 7, 135, 0, 7, 136, 0, 7, 145, 0, 7, 140, 0, 7, 141, 0, 7, 142, 0, 7, 147, 0, 7, 137, 0, 7, 146, 0, 7, 144, 0, 7, 143, 0, 7, 148, 0], -); - -pub fn metadata() -> &'static GrammarMetadata { - &METADATA -} - -pub fn rule_names() -> &'static [&'static str] { - METADATA.rule_names() -} - -pub use antlr4_runtime::generated::{lex, lex_stream}; - - -static ATN_CELL: OnceLock = OnceLock::new(); - -/// Deserializes and caches the grammar ATN for all lexer instances. -fn atn() -> &'static LexerAtn { - ATN_CELL.get_or_init(|| { - let serialized = metadata().serialized_atn(); - AtnDeserializer::new(&serialized) - .deserialize() - .expect("generated lexer contains a valid ANTLR serialized ATN") - }) -} - -static LEXER_DFA_DATA: &[u32] = &[1280852999,5,0,726,939,1148,1596,1598,0,0,65535,4294967295,1,1,65535,0,1,1,65535,1,2,1,65535,2,3,1,65535,3,4,1,65535,4,5,1,65535,5,6,2,65535,4294967295,7,1,65535,6,8,1,65535,7,9,3,65535,8,10,1,65535,9,10,1,65535,10,11,1,65535,11,12,1,65535,12,10,1,65535,13,13,1,65535,14,14,1,65535,15,15,1,65535,16,16,1,65535,17,17,1,65535,18,18,1,65535,19,19,1,65535,20,20,1,65535,21,21,1,65535,22,22,1,65535,23,23,1,65535,24,24,1,65535,25,25,4,65535,26,10,1,65535,27,10,1,65535,28,25,4,65535,29,26,5,65535,4294967295,27,4,65535,30,28,4,65535,31,29,4,65535,32,30,4,65535,33,31,4,65535,34,32,4,65535,35,33,4,65535,36,25,4,65535,37,34,4,65535,38,35,4,65535,39,36,4,65535,40,37,4,65535,41,38,4,65535,42,39,4,65535,43,40,4,65535,44,41,4,65535,45,42,4,65535,46,43,4,65535,47,10,1,65535,48,44,1,65535,4294967295,10,1,65535,49,25,4,65535,50,25,4,65535,51,25,4,65535,52,10,1,65535,53,10,1,65535,54,45,1,65535,55,10,1,65535,56,46,1,65535,4294967295,47,1,65535,57,48,1,65535,4294967295,49,1,65535,4294967295,50,6,65535,58,51,7,65535,59,52,8,65535,4294967295,53,7,65535,60,51,7,65535,61,54,7,65535,62,55,7,65535,63,56,7,65535,64,57,7,65535,65,58,7,65535,66,59,7,65535,67,60,7,65535,68,61,7,65535,69,62,7,65535,70,63,7,65535,71,64,7,65535,72,65,7,65535,73,66,7,65535,74,67,7,65535,75,68,7,65535,76,10,1,65535,77,10,1,65535,78,69,1,65535,4294967295,70,1,65535,4294967295,10,1,65535,79,10,1,65535,80,10,1,65535,81,10,1,65535,82,10,1,65535,83,10,1,65535,84,71,1,65535,85,72,1,65535,86,73,9,65535,4294967295,74,10,65535,87,10,1,65535,88,75,1,65535,4294967295,76,1,65535,4294967295,77,1,65535,4294967295,78,1,65535,4294967295,10,1,65535,89,10,1,65535,90,79,1,65535,91,80,1,65535,4294967295,81,1,65535,4294967295,17,1,65535,92,82,1,65535,4294967295,10,1,65535,93,10,1,65535,94,10,1,65535,95,83,1,65535,96,10,1,65535,97,10,1,65535,98,10,1,65535,99,84,1,65535,4294967295,10,1,65535,100,85,1,65535,101,86,1,65535,4294967295,87,5,65535,4294967295,88,4,65535,102,89,4,65535,103,90,4,65535,104,91,4,65535,105,92,4,65535,106,25,4,65535,107,93,4,65535,108,94,4,65535,109,95,4,65535,110,96,4,65535,111,97,4,65535,112,98,4,65535,113,25,4,65535,114,99,4,65535,115,100,4,65535,116,101,4,65535,117,102,4,65535,118,103,4,65535,119,104,4,65535,120,105,4,65535,121,106,4,65535,122,107,4,65535,123,25,4,65535,124,108,4,65535,125,109,4,65535,126,25,4,65535,127,110,4,65535,128,111,4,65535,129,112,4,65535,130,113,4,65535,131,114,4,65535,132,115,4,65535,133,116,4,65535,134,117,4,65535,135,118,4,65535,136,119,4,65535,137,120,4,65535,138,121,4,65535,139,122,4,65535,140,123,4,65535,141,124,4,65535,142,125,4,65535,143,126,4,65535,144,127,4,65535,145,128,4,65535,146,10,1,65535,147,10,1,65535,148,129,1,65535,149,130,1,65535,4294967295,131,11,65535,4294967295,132,12,65535,150,10,1,65535,151,133,1,65535,4294967295,134,1,65535,4294967295,10,1,65535,152,135,8,65535,4294967295,136,7,65535,153,137,7,65535,154,138,7,65535,155,139,7,65535,156,140,7,65535,157,141,7,65535,158,142,7,65535,159,143,7,65535,160,144,7,65535,161,145,7,65535,162,146,7,65535,163,147,7,65535,164,51,7,65535,165,148,7,65535,166,149,7,65535,167,150,7,65535,168,151,7,65535,169,152,7,65535,170,51,7,65535,171,153,7,65535,172,154,7,65535,173,155,7,65535,174,156,7,65535,175,157,7,65535,176,158,7,65535,177,159,7,65535,178,160,7,65535,179,161,7,65535,180,162,7,65535,181,10,1,65535,182,163,1,65535,4294967295,10,1,65535,183,10,1,65535,184,164,1,65535,4294967295,165,1,65535,4294967295,166,9,65535,4294967295,167,9,65535,4294967295,168,10,65535,185,169,1,65535,186,170,1,65535,4294967295,171,1,65535,187,10,1,65535,188,172,1,65535,189,10,1,65535,190,173,13,65535,4294967295,174,14,65535,191,175,15,65535,4294967295,176,16,65535,192,10,1,65535,193,177,4,65535,194,178,4,65535,195,179,4,65535,196,10,1,65535,197,180,4,65535,198,181,4,65535,199,182,4,65535,200,183,4,65535,201,184,4,65535,202,185,4,65535,203,186,4,65535,204,187,4,65535,205,188,4,65535,206,189,4,65535,207,190,4,65535,208,191,4,65535,209,192,4,65535,210,193,4,65535,211,194,4,65535,212,195,4,65535,213,196,4,65535,214,25,4,65535,215,25,4,65535,216,25,4,65535,217,197,4,65535,218,198,4,65535,219,199,4,65535,220,200,4,65535,221,201,4,65535,222,202,4,65535,223,203,4,65535,224,204,4,65535,225,205,4,65535,226,206,4,65535,227,207,4,65535,228,25,4,65535,229,208,4,65535,230,209,4,65535,231,210,4,65535,232,211,4,65535,233,212,4,65535,234,213,4,65535,235,214,4,65535,236,215,4,65535,237,216,4,65535,238,217,4,65535,239,218,4,65535,240,219,4,65535,241,220,4,65535,242,221,4,65535,243,222,4,65535,244,223,4,65535,245,224,4,65535,246,25,4,65535,247,225,4,65535,248,226,4,65535,249,227,4,65535,250,228,4,65535,251,229,4,65535,252,230,17,65535,4294967295,231,18,65535,253,232,11,65535,4294967295,233,11,65535,4294967295,10,1,65535,254,234,1,65535,255,235,1,65535,4294967295,10,1,65535,256,236,1,65535,257,237,1,65535,4294967295,10,1,65535,258,238,7,65535,259,239,7,65535,260,240,7,65535,261,241,7,65535,262,242,7,65535,263,243,7,65535,264,244,7,65535,265,51,7,65535,266,245,7,65535,267,246,7,65535,268,51,7,65535,269,247,7,65535,270,248,7,65535,271,249,7,65535,272,51,7,65535,273,250,7,65535,274,251,7,65535,275,252,7,65535,276,51,7,65535,277,253,7,65535,278,254,7,65535,279,255,7,65535,280,256,7,65535,281,257,7,65535,282,258,7,65535,283,259,7,65535,284,260,7,65535,285,261,7,65535,286,262,7,65535,287,263,7,65535,288,264,7,65535,289,265,7,65535,290,266,7,65535,291,267,7,65535,292,268,7,65535,293,269,7,65535,294,270,7,65535,295,271,7,65535,296,272,7,65535,297,273,1,65535,4294967295,274,1,65535,4294967295,275,1,65535,298,276,19,65535,299,74,10,65535,300,277,10,65535,301,278,1,65535,4294967295,279,1,65535,4294967295,280,1,65535,4294967295,281,13,65535,4294967295,282,13,65535,4294967295,283,15,65535,4294967295,284,15,65535,4294967295,285,4,65535,302,286,4,65535,303,287,4,65535,304,288,4,65535,305,289,4,65535,306,290,4,65535,307,291,4,65535,308,292,4,65535,309,293,4,65535,310,294,4,65535,311,25,4,65535,312,295,4,65535,313,296,4,65535,314,25,4,65535,315,25,4,65535,316,297,4,65535,317,298,4,65535,318,224,4,65535,319,299,4,65535,320,25,4,65535,321,300,4,65535,322,301,4,65535,323,302,4,65535,324,25,4,65535,325,303,4,65535,326,304,4,65535,327,305,4,65535,328,306,4,65535,329,307,4,65535,330,25,4,65535,331,308,4,65535,332,25,4,65535,333,309,4,65535,334,310,4,65535,335,311,4,65535,336,312,4,65535,337,313,4,65535,338,314,4,65535,339,315,4,65535,340,316,4,65535,341,317,4,65535,342,318,4,65535,343,319,4,65535,344,320,4,65535,345,321,4,65535,346,322,4,65535,347,323,4,65535,348,324,4,65535,349,325,4,65535,350,326,4,65535,351,25,4,65535,352,327,4,65535,353,328,4,65535,354,329,4,65535,355,25,4,65535,356,330,4,65535,357,331,4,65535,358,332,17,65535,4294967295,333,17,65535,4294967295,10,1,65535,359,334,20,65535,4294967295,335,21,65535,360,336,22,65535,4294967295,337,23,65535,361,338,7,65535,362,339,7,65535,363,340,7,65535,364,51,7,65535,365,341,7,65535,366,342,7,65535,367,343,7,65535,368,344,7,65535,369,345,7,65535,370,346,7,65535,371,347,7,65535,372,51,7,65535,373,348,7,65535,374,349,7,65535,375,51,7,65535,376,350,7,65535,377,51,7,65535,378,351,7,65535,379,352,7,65535,380,353,7,65535,381,354,7,65535,382,355,7,65535,383,51,7,65535,384,356,7,65535,385,357,7,65535,386,358,7,65535,387,359,7,65535,388,360,7,65535,389,361,7,65535,390,362,7,65535,391,363,7,65535,392,364,7,65535,393,365,7,65535,394,51,7,65535,395,366,7,65535,396,51,7,65535,397,367,1,65535,4294967295,368,1,65535,4294967295,369,19,65535,4294967295,370,19,65535,4294967295,371,24,65535,398,372,25,65535,399,373,26,65535,400,10,1,65535,401,10,1,65535,402,374,4,65535,403,375,4,65535,404,376,4,65535,405,377,4,65535,406,25,4,65535,407,25,4,65535,408,378,4,65535,409,379,4,65535,410,380,4,65535,411,381,4,65535,412,382,4,65535,413,383,4,65535,414,384,4,65535,415,385,4,65535,416,25,4,65535,417,386,4,65535,418,387,4,65535,419,25,4,65535,420,388,4,65535,421,25,4,65535,422,389,4,65535,423,390,4,65535,424,391,4,65535,425,392,4,65535,426,393,4,65535,427,394,4,65535,428,395,4,65535,429,25,4,65535,430,396,4,65535,431,397,4,65535,432,398,4,65535,433,399,4,65535,434,400,4,65535,435,401,4,65535,436,402,4,65535,437,403,4,65535,438,404,4,65535,439,405,4,65535,440,406,4,65535,441,407,4,65535,442,408,27,65535,4294967295,25,4,65535,443,409,4,65535,444,410,4,65535,445,25,4,65535,446,411,4,65535,447,25,4,65535,448,25,4,65535,449,10,1,65535,450,412,20,65535,4294967295,413,20,65535,4294967295,414,22,65535,4294967295,415,22,65535,4294967295,416,7,65535,451,51,7,65535,452,417,7,65535,453,418,7,65535,454,419,7,65535,455,420,7,65535,456,421,7,65535,457,422,7,65535,458,51,7,65535,459,423,7,65535,460,424,7,65535,461,51,7,65535,462,51,7,65535,463,425,7,65535,464,426,7,65535,465,427,7,65535,466,428,7,65535,467,429,7,65535,468,430,7,65535,469,431,7,65535,470,432,7,65535,471,51,7,65535,472,433,7,65535,473,434,7,65535,474,51,7,65535,475,435,7,65535,476,436,7,65535,477,437,7,65535,478,51,7,65535,479,438,1,65535,4294967295,439,19,65535,4294967295,440,24,65535,4294967295,441,1,65535,480,442,24,65535,4294967295,443,24,65535,4294967295,444,25,65535,481,445,25,65535,482,446,25,65535,483,447,26,65535,484,448,4,65535,485,25,4,65535,486,449,4,65535,487,450,28,65535,4294967295,451,4,65535,488,452,4,65535,489,453,4,65535,490,454,4,65535,491,455,4,65535,492,456,4,65535,493,25,4,65535,494,457,4,65535,495,458,4,65535,496,25,4,65535,497,25,4,65535,498,459,4,65535,499,460,4,65535,500,461,4,65535,501,462,4,65535,502,25,4,65535,503,463,4,65535,504,464,4,65535,505,465,4,65535,506,466,4,65535,507,467,4,65535,508,468,4,65535,509,25,4,65535,510,469,4,65535,511,470,4,65535,512,471,4,65535,513,25,4,65535,514,472,4,65535,515,473,29,65535,4294967295,474,4,65535,516,475,4,65535,517,476,30,65535,518,477,31,65535,4294967295,478,4,65535,519,25,4,65535,520,25,4,65535,521,10,1,65535,522,10,1,65535,523,479,7,65535,524,480,7,65535,525,481,7,65535,526,482,7,65535,527,483,7,65535,528,484,7,65535,529,51,7,65535,530,485,7,65535,531,51,7,65535,532,486,7,65535,533,487,7,65535,534,488,7,65535,535,489,7,65535,536,490,7,65535,537,51,7,65535,538,491,7,65535,539,492,7,65535,540,493,7,65535,541,51,7,65535,542,494,7,65535,543,51,7,65535,544,51,7,65535,545,276,19,65535,4294967295,495,24,65535,4294967295,496,24,65535,4294967295,497,32,65535,546,74,10,65535,547,498,25,65535,548,373,26,65535,549,499,4,65535,550,500,4,65535,551,501,33,65535,552,502,34,65535,4294967295,503,4,65535,553,504,4,65535,554,505,4,65535,555,506,4,65535,556,507,4,65535,557,25,4,65535,558,508,4,65535,559,25,4,65535,560,509,4,65535,561,510,4,65535,562,511,4,65535,563,512,4,65535,564,513,4,65535,565,514,4,65535,566,25,4,65535,567,25,4,65535,568,515,4,65535,569,516,4,65535,570,517,4,65535,571,25,4,65535,572,518,35,65535,4294967295,519,4,65535,573,520,36,65535,574,521,37,65535,4294967295,25,4,65535,575,25,4,65535,576,522,31,65535,4294967295,523,4,65535,577,51,7,65535,578,524,7,65535,579,525,7,65535,580,526,7,65535,581,527,7,65535,582,51,7,65535,583,51,7,65535,584,51,7,65535,585,51,7,65535,586,51,7,65535,587,51,7,65535,588,51,7,65535,589,51,7,65535,590,528,7,65535,591,51,7,65535,592,51,7,65535,593,371,24,65535,4294967295,25,4,65535,594,529,4,65535,595,530,34,65535,4294967295,531,4,65535,596,532,4,65535,597,533,4,65535,598,534,4,65535,599,25,4,65535,600,25,4,65535,601,535,4,65535,602,25,4,65535,603,25,4,65535,604,25,4,65535,605,25,4,65535,606,25,4,65535,607,25,4,65535,608,536,4,65535,609,25,4,65535,610,537,38,65535,611,538,39,65535,4294967295,25,4,65535,612,539,37,65535,4294967295,10,1,65535,613,540,4,65535,614,541,7,65535,615,51,7,65535,616,542,7,65535,617,543,7,65535,618,51,7,65535,619,544,4,65535,620,10,1,65535,621,25,4,65535,622,545,4,65535,623,546,40,65535,4294967295,547,4,65535,624,25,4,65535,625,25,4,65535,626,548,39,65535,4294967295,10,1,65535,627,25,4,65535,628,51,7,65535,629,549,7,65535,630,550,7,65535,631,25,4,65535,632,551,4,65535,633,552,41,65535,634,553,42,65535,4294967295,554,4,65535,635,10,1,65535,636,51,7,65535,637,51,7,65535,638,25,4,65535,639,555,42,65535,4294967295,25,4,65535,640,10,1,65535,641,556,43,65535,4294967295,557,43,65535,642,10,1,65535,643,558,44,65535,644,559,1,65535,4294967295,560,45,65535,645,561,46,65535,4294967295,562,45,65535,646,560,45,65535,647,563,45,65535,648,564,45,65535,649,565,45,65535,650,566,45,65535,651,567,45,65535,652,568,45,65535,653,569,45,65535,654,570,45,65535,655,571,45,65535,656,572,45,65535,657,573,45,65535,658,574,45,65535,659,575,45,65535,660,576,45,65535,661,577,45,65535,662,10,1,65535,663,10,1,65535,664,578,1,65535,4294967295,579,46,65535,4294967295,580,45,65535,665,581,45,65535,666,582,45,65535,667,583,45,65535,668,584,45,65535,669,585,45,65535,670,586,45,65535,671,587,45,65535,672,588,45,65535,673,589,45,65535,674,590,45,65535,675,591,45,65535,676,560,45,65535,677,592,45,65535,678,593,45,65535,679,594,45,65535,680,595,45,65535,681,596,45,65535,682,560,45,65535,683,597,45,65535,684,598,45,65535,685,599,45,65535,686,600,45,65535,687,601,45,65535,688,602,45,65535,689,603,45,65535,690,604,45,65535,691,605,45,65535,692,606,45,65535,693,607,1,65535,4294967295,10,1,65535,694,608,45,65535,695,609,45,65535,696,610,45,65535,697,611,45,65535,698,612,45,65535,699,613,45,65535,700,614,45,65535,701,560,45,65535,702,615,45,65535,703,616,45,65535,704,560,45,65535,705,617,45,65535,706,618,45,65535,707,619,45,65535,708,560,45,65535,709,620,45,65535,710,621,45,65535,711,622,45,65535,712,560,45,65535,713,623,45,65535,714,624,45,65535,715,625,45,65535,716,626,45,65535,717,627,45,65535,718,628,45,65535,719,629,45,65535,720,630,45,65535,721,631,45,65535,722,632,45,65535,723,633,45,65535,724,634,45,65535,725,635,45,65535,726,636,45,65535,727,637,45,65535,728,638,45,65535,729,639,45,65535,730,640,45,65535,731,641,45,65535,732,642,45,65535,733,643,1,65535,4294967295,644,45,65535,734,645,45,65535,735,646,45,65535,736,560,45,65535,737,647,45,65535,738,648,45,65535,739,649,45,65535,740,650,45,65535,741,651,45,65535,742,652,45,65535,743,653,45,65535,744,560,45,65535,745,654,45,65535,746,655,45,65535,747,560,45,65535,748,656,45,65535,749,560,45,65535,750,657,45,65535,751,658,45,65535,752,659,45,65535,753,660,45,65535,754,661,45,65535,755,560,45,65535,756,662,45,65535,757,663,45,65535,758,664,45,65535,759,665,45,65535,760,666,45,65535,761,667,45,65535,762,668,45,65535,763,669,45,65535,764,670,45,65535,765,671,45,65535,766,560,45,65535,767,672,45,65535,768,560,45,65535,769,673,1,65535,4294967295,674,45,65535,770,560,45,65535,771,675,45,65535,772,676,45,65535,773,677,45,65535,774,678,45,65535,775,679,45,65535,776,680,45,65535,777,560,45,65535,778,681,45,65535,779,682,45,65535,780,560,45,65535,781,560,45,65535,782,683,45,65535,783,684,45,65535,784,685,45,65535,785,686,45,65535,786,687,45,65535,787,688,45,65535,788,689,45,65535,789,690,45,65535,790,560,45,65535,791,691,45,65535,792,692,45,65535,793,560,45,65535,794,693,45,65535,795,694,45,65535,796,695,45,65535,797,560,45,65535,798,696,45,65535,799,697,45,65535,800,698,45,65535,801,699,45,65535,802,700,45,65535,803,701,45,65535,804,560,45,65535,805,702,45,65535,806,560,45,65535,807,703,45,65535,808,704,45,65535,809,705,45,65535,810,706,45,65535,811,707,45,65535,812,560,45,65535,813,708,45,65535,814,709,45,65535,815,710,45,65535,816,560,45,65535,817,711,45,65535,818,560,45,65535,819,560,45,65535,820,560,45,65535,821,712,45,65535,822,713,45,65535,823,714,45,65535,824,715,45,65535,825,560,45,65535,826,560,45,65535,827,560,45,65535,828,560,45,65535,829,560,45,65535,830,560,45,65535,831,560,45,65535,832,560,45,65535,833,716,45,65535,834,560,45,65535,835,560,45,65535,836,717,45,65535,837,560,45,65535,838,718,45,65535,839,719,45,65535,840,560,45,65535,841,560,45,65535,842,720,45,65535,843,721,45,65535,844,560,45,65535,845,560,45,65535,846,722,47,65535,4294967295,723,47,65535,847,724,1,65535,848,725,48,65535,849,726,1,65535,850,727,49,65535,851,728,50,65535,4294967295,729,49,65535,852,727,49,65535,853,730,49,65535,854,731,49,65535,855,732,49,65535,856,733,49,65535,857,734,49,65535,858,735,49,65535,859,736,49,65535,860,737,49,65535,861,738,49,65535,862,739,49,65535,863,740,49,65535,864,741,49,65535,865,742,49,65535,866,743,49,65535,867,744,49,65535,868,10,1,65535,869,726,1,65535,870,745,50,65535,4294967295,746,49,65535,871,747,49,65535,872,748,49,65535,873,749,49,65535,874,750,49,65535,875,751,49,65535,876,752,49,65535,877,753,49,65535,878,754,49,65535,879,755,49,65535,880,756,49,65535,881,757,49,65535,882,727,49,65535,883,758,49,65535,884,759,49,65535,885,760,49,65535,886,761,49,65535,887,762,49,65535,888,727,49,65535,889,763,49,65535,890,764,49,65535,891,765,49,65535,892,766,49,65535,893,767,49,65535,894,768,49,65535,895,769,49,65535,896,770,49,65535,897,771,49,65535,898,772,49,65535,899,10,1,65535,900,773,49,65535,901,774,49,65535,902,775,49,65535,903,776,49,65535,904,777,49,65535,905,778,49,65535,906,779,49,65535,907,727,49,65535,908,780,49,65535,909,781,49,65535,910,727,49,65535,911,782,49,65535,912,783,49,65535,913,784,49,65535,914,727,49,65535,915,785,49,65535,916,786,49,65535,917,787,49,65535,918,727,49,65535,919,788,49,65535,920,789,49,65535,921,790,49,65535,922,791,49,65535,923,792,49,65535,924,793,49,65535,925,794,49,65535,926,795,49,65535,927,796,49,65535,928,797,49,65535,929,798,49,65535,930,799,49,65535,931,800,49,65535,932,801,49,65535,933,802,49,65535,934,803,49,65535,935,804,49,65535,936,805,49,65535,937,806,49,65535,938,807,49,65535,939,808,49,65535,940,809,49,65535,941,810,49,65535,942,727,49,65535,943,811,49,65535,944,812,49,65535,945,813,49,65535,946,814,49,65535,947,815,49,65535,948,816,49,65535,949,817,49,65535,950,727,49,65535,951,818,49,65535,952,819,49,65535,953,727,49,65535,954,820,49,65535,955,727,49,65535,956,821,49,65535,957,822,49,65535,958,823,49,65535,959,824,49,65535,960,825,49,65535,961,727,49,65535,962,826,49,65535,963,827,49,65535,964,828,49,65535,965,829,49,65535,966,830,49,65535,967,831,49,65535,968,832,49,65535,969,833,49,65535,970,834,49,65535,971,835,49,65535,972,727,49,65535,973,836,49,65535,974,727,49,65535,975,837,49,65535,976,727,49,65535,977,838,49,65535,978,839,49,65535,979,840,49,65535,980,841,49,65535,981,842,49,65535,982,843,49,65535,983,727,49,65535,984,844,49,65535,985,845,49,65535,986,727,49,65535,987,727,49,65535,988,846,49,65535,989,847,49,65535,990,848,49,65535,991,849,49,65535,992,850,49,65535,993,851,49,65535,994,852,49,65535,995,853,49,65535,996,727,49,65535,997,854,49,65535,998,855,49,65535,999,727,49,65535,1000,856,49,65535,1001,857,49,65535,1002,858,49,65535,1003,727,49,65535,1004,859,49,65535,1005,860,49,65535,1006,861,49,65535,1007,862,49,65535,1008,863,49,65535,1009,864,49,65535,1010,727,49,65535,1011,865,49,65535,1012,727,49,65535,1013,866,49,65535,1014,867,49,65535,1015,868,49,65535,1016,869,49,65535,1017,870,49,65535,1018,727,49,65535,1019,871,49,65535,1020,872,49,65535,1021,873,49,65535,1022,727,49,65535,1023,874,49,65535,1024,727,49,65535,1025,727,49,65535,1026,727,49,65535,1027,875,49,65535,1028,876,49,65535,1029,877,49,65535,1030,878,49,65535,1031,727,49,65535,1032,727,49,65535,1033,727,49,65535,1034,727,49,65535,1035,727,49,65535,1036,727,49,65535,1037,727,49,65535,1038,727,49,65535,1039,879,49,65535,1040,727,49,65535,1041,727,49,65535,1042,880,49,65535,1043,727,49,65535,1044,881,49,65535,1045,882,49,65535,1046,727,49,65535,1047,727,49,65535,1048,883,49,65535,1049,884,49,65535,1050,727,49,65535,1051,727,49,65535,1052,885,51,65535,4294967295,886,1,65535,1053,886,1,65535,1054,887,1,65535,1055,888,1,65535,1056,889,1,65535,1057,10,1,65535,1058,890,1,65535,1059,891,1,65535,1060,892,52,65535,1061,10,1,65535,1062,10,1,65535,1063,893,1,65535,1064,894,1,65535,1065,10,1,65535,1066,895,1,65535,1067,896,1,65535,1068,897,1,65535,1069,898,1,65535,1070,899,1,65535,1071,900,1,65535,1072,901,1,65535,1073,902,1,65535,1074,903,1,65535,1075,904,1,65535,1076,905,1,65535,1077,906,1,65535,1078,907,53,65535,1079,10,1,65535,1080,10,1,65535,1081,908,54,65535,4294967295,909,53,65535,1082,910,53,65535,1083,911,53,65535,1084,912,53,65535,1085,913,53,65535,1086,914,53,65535,1087,915,53,65535,1088,916,53,65535,1089,917,53,65535,1090,918,53,65535,1091,919,53,65535,1092,920,53,65535,1093,921,53,65535,1094,922,53,65535,1095,923,53,65535,1096,924,53,65535,1097,925,53,65535,1098,10,1,65535,1099,926,1,65535,4294967295,10,1,65535,1100,927,1,65535,1101,10,1,65535,1102,928,1,65535,1103,929,1,65535,4294967295,930,1,65535,1104,931,1,65535,4294967295,932,1,65535,4294967295,10,1,65535,1105,10,1,65535,1106,933,1,65535,4294967295,934,1,65535,4294967295,10,1,65535,1107,10,1,65535,1108,10,1,65535,1109,10,1,65535,1110,10,1,65535,1111,10,1,65535,1112,935,1,65535,1113,936,1,65535,1114,937,55,65535,4294967295,938,56,65535,1115,10,1,65535,1116,939,1,65535,4294967295,940,1,65535,4294967295,941,1,65535,4294967295,942,1,65535,4294967295,10,1,65535,1117,10,1,65535,1118,943,1,65535,1119,944,1,65535,4294967295,945,1,65535,4294967295,946,1,65535,4294967295,10,1,65535,1120,10,1,65535,1121,10,1,65535,1122,947,1,65535,1123,10,1,65535,1124,10,1,65535,1125,10,1,65535,1126,948,1,65535,1127,949,1,65535,4294967295,10,1,65535,1128,950,1,65535,1129,951,1,65535,4294967295,952,54,65535,4294967295,953,53,65535,1130,954,53,65535,1131,955,53,65535,1132,956,53,65535,1133,957,53,65535,1134,958,53,65535,1135,959,53,65535,1136,960,53,65535,1137,961,53,65535,1138,962,53,65535,1139,907,53,65535,1140,963,53,65535,1141,964,53,65535,1142,965,53,65535,1143,966,53,65535,1144,967,53,65535,1145,968,53,65535,1146,969,53,65535,1147,970,53,65535,1148,907,53,65535,1149,971,53,65535,1150,907,53,65535,1151,972,53,65535,1152,973,53,65535,1153,974,53,65535,1154,975,53,65535,1155,976,53,65535,1156,977,53,65535,1157,978,53,65535,1158,979,53,65535,1159,980,53,65535,1160,981,53,65535,1161,982,53,65535,1162,983,53,65535,1163,984,53,65535,1164,985,53,65535,1165,986,53,65535,1166,987,53,65535,1167,988,53,65535,1168,989,53,65535,1169,10,1,65535,1170,10,1,65535,1171,990,1,65535,1172,991,1,65535,4294967295,992,57,65535,4294967295,993,58,65535,1173,10,1,65535,1174,994,1,65535,4294967295,995,1,65535,4294967295,10,1,65535,1175,10,1,65535,1176,996,1,65535,4294967295,10,1,65535,1177,10,1,65535,1178,997,1,65535,4294967295,998,55,65535,4294967295,999,55,65535,4294967295,1000,56,65535,1179,1001,1,65535,1180,1002,1,65535,4294967295,1003,1,65535,1181,10,1,65535,1182,1004,1,65535,1183,10,1,65535,1184,1005,59,65535,4294967295,1006,60,65535,1185,1007,61,65535,4294967295,1008,62,65535,1186,10,1,65535,1187,1009,53,65535,1188,1010,53,65535,1189,1011,53,65535,1190,10,1,65535,1191,1012,53,65535,1192,1013,53,65535,1193,1014,53,65535,1194,1015,53,65535,1195,1016,53,65535,1196,1017,53,65535,1197,1018,53,65535,1198,1019,53,65535,1199,1020,53,65535,1200,1021,53,65535,1201,1022,53,65535,1202,1023,53,65535,1203,1024,53,65535,1204,1025,53,65535,1205,907,53,65535,1206,907,53,65535,1207,907,53,65535,1208,1026,53,65535,1209,1027,53,65535,1210,1028,53,65535,1211,1029,53,65535,1212,1030,53,65535,1213,1031,53,65535,1214,1032,53,65535,1215,1033,53,65535,1216,1034,53,65535,1217,907,53,65535,1218,1035,53,65535,1219,1036,53,65535,1220,1037,53,65535,1221,1038,53,65535,1222,1039,53,65535,1223,1040,53,65535,1224,1041,53,65535,1225,1042,53,65535,1226,1043,53,65535,1227,1044,53,65535,1228,1045,53,65535,1229,1046,53,65535,1230,1047,53,65535,1231,1048,53,65535,1232,1049,53,65535,1233,907,53,65535,1234,1050,53,65535,1235,1051,53,65535,1236,1052,53,65535,1237,1053,53,65535,1238,1054,63,65535,4294967295,1055,64,65535,1239,1056,57,65535,4294967295,1057,57,65535,4294967295,10,1,65535,1240,1058,1,65535,1241,1059,1,65535,4294967295,10,1,65535,1242,1060,1,65535,1243,1061,1,65535,4294967295,1062,1,65535,4294967295,1063,65,65535,1244,938,56,65535,1245,1064,56,65535,1246,1065,1,65535,4294967295,1066,1,65535,4294967295,1067,1,65535,4294967295,1068,59,65535,4294967295,1069,59,65535,4294967295,1070,61,65535,4294967295,1071,61,65535,4294967295,1072,53,65535,1247,1073,53,65535,1248,1074,53,65535,1249,1075,53,65535,1250,1076,53,65535,1251,1077,53,65535,1252,1078,53,65535,1253,1079,53,65535,1254,907,53,65535,1255,1080,53,65535,1256,907,53,65535,1257,907,53,65535,1258,1081,53,65535,1259,1082,53,65535,1260,1049,53,65535,1261,1083,53,65535,1262,907,53,65535,1263,1084,53,65535,1264,1085,53,65535,1265,1086,53,65535,1266,1087,53,65535,1267,1088,53,65535,1268,1089,53,65535,1269,1090,53,65535,1270,907,53,65535,1271,1091,53,65535,1272,907,53,65535,1273,1092,53,65535,1274,1093,53,65535,1275,1094,53,65535,1276,1095,53,65535,1277,1096,53,65535,1278,1097,53,65535,1279,1098,53,65535,1280,1099,53,65535,1281,1100,53,65535,1282,1101,53,65535,1283,1102,53,65535,1284,1103,53,65535,1285,1104,53,65535,1286,1105,53,65535,1287,1106,53,65535,1288,1107,53,65535,1289,907,53,65535,1290,1108,53,65535,1291,1109,53,65535,1292,907,53,65535,1293,1110,53,65535,1294,1111,63,65535,4294967295,1112,63,65535,4294967295,10,1,65535,1295,1113,66,65535,4294967295,1114,67,65535,1296,1115,68,65535,4294967295,1116,69,65535,1297,1117,1,65535,4294967295,1118,65,65535,4294967295,1119,65,65535,4294967295,1120,70,65535,1298,1121,71,65535,1299,1122,72,65535,1300,10,1,65535,1301,10,1,65535,1302,1123,53,65535,1303,1124,53,65535,1304,1125,53,65535,1305,1126,53,65535,1306,907,53,65535,1307,907,53,65535,1308,1127,53,65535,1309,1128,53,65535,1310,1129,53,65535,1311,1130,53,65535,1312,1131,53,65535,1313,907,53,65535,1314,1132,53,65535,1315,907,53,65535,1316,1133,53,65535,1317,907,53,65535,1318,1134,53,65535,1319,1135,53,65535,1320,1136,53,65535,1321,1137,53,65535,1322,1138,53,65535,1323,1139,53,65535,1324,907,53,65535,1325,1140,53,65535,1326,1141,53,65535,1327,1142,53,65535,1328,1143,53,65535,1329,1144,53,65535,1330,1145,53,65535,1331,1146,53,65535,1332,1147,53,65535,1333,1148,53,65535,1334,907,53,65535,1335,1149,53,65535,1336,1150,53,65535,1337,907,53,65535,1338,907,53,65535,1339,1151,53,65535,1340,907,53,65535,1341,10,1,65535,1342,1152,66,65535,4294967295,1153,66,65535,4294967295,1154,68,65535,4294967295,1155,68,65535,4294967295,1156,1,65535,4294967295,1157,65,65535,4294967295,1158,70,65535,4294967295,1159,1,65535,1343,1160,70,65535,4294967295,1161,70,65535,4294967295,1162,71,65535,1344,1163,71,65535,1345,1164,71,65535,1346,1165,72,65535,1347,1166,53,65535,1348,907,53,65535,1349,1167,53,65535,1350,1168,73,65535,4294967295,1169,53,65535,1351,1170,53,65535,1352,1171,53,65535,1353,907,53,65535,1354,1172,53,65535,1355,1173,53,65535,1356,907,53,65535,1357,1174,53,65535,1358,1175,53,65535,1359,1176,53,65535,1360,907,53,65535,1361,1177,53,65535,1362,1178,53,65535,1363,1179,53,65535,1364,1180,53,65535,1365,1181,53,65535,1366,907,53,65535,1367,1182,53,65535,1368,1183,53,65535,1369,1184,53,65535,1370,907,53,65535,1371,1185,53,65535,1372,1186,53,65535,1373,1187,53,65535,1374,907,53,65535,1375,10,1,65535,1376,10,1,65535,1377,1063,65,65535,4294967295,1188,70,65535,4294967295,1189,70,65535,4294967295,1190,74,65535,1378,938,56,65535,1379,1191,71,65535,1380,1122,72,65535,1381,1192,53,65535,1382,1193,53,65535,1383,1194,75,65535,1384,1195,76,65535,4294967295,1196,53,65535,1385,1197,53,65535,1386,1198,53,65535,1387,1199,53,65535,1388,907,53,65535,1389,1200,53,65535,1390,1201,53,65535,1391,1202,53,65535,1392,1203,53,65535,1393,1204,53,65535,1394,907,53,65535,1395,1205,53,65535,1396,1206,53,65535,1397,1207,53,65535,1398,907,53,65535,1399,1208,77,65535,4294967295,1209,53,65535,1400,907,53,65535,1401,907,53,65535,1402,1120,70,65535,4294967295,907,53,65535,1403,1210,53,65535,1404,1211,76,65535,4294967295,1212,53,65535,1405,1213,53,65535,1406,907,53,65535,1407,907,53,65535,1408,907,53,65535,1409,907,53,65535,1410,907,53,65535,1411,907,53,65535,1412,907,53,65535,1413,907,53,65535,1414,1214,53,65535,1415,907,53,65535,1416,1215,78,65535,1417,1216,79,65535,4294967295,907,53,65535,1418,1217,53,65535,1419,10,1,65535,1420,1218,80,65535,4294967295,1219,53,65535,1421,907,53,65535,1422,1220,79,65535,4294967295,907,53,65535,1423,1221,81,65535,1424,1222,82,65535,4294967295,1223,53,65535,1425,10,1,65535,1426,1224,82,65535,4294967295,907,53,65535,1427,10,1,65535,1428,1225,83,65535,4294967295,10,1,65535,1429,1598,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,854531,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,14640,0,3090947,1074596356,0,0,261,14640,0,0,0,0,0,0,0,261,24415,0,261,14640,0,261,24415,0,0,0,0,0,0,0,0,0,0,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3090947,854531,0,0,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,24415,0,261,10794,0,261,12079,0,261,16448,0,261,12592,0,0,261,14640,0,0,773,1178679600,26209,0,3090947,854531,3090947,854531,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3090947,854531,261,10794,0,261,12079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,14640,0,0,0,0,261,24415,0,261,24415,0,261,24415,0,261,10794,0,261,12079,0,261,10794,0,261,12079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,10794,0,261,12079,0,0,3090947,854531,3090947,854531,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,24415,0,3090947,261,12079,0,0,0,1074596356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,10794,0,261,12079,0,261,10794,0,261,12079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,10794,0,3090947,0,261,10794,0,0,261,10794,0,261,12079,0,261,16448,0,261,16448,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,12079,0,0,854531,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1029,1514223920,2053201759,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1611467268,0,0,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,1611467268,0,0,0,1545871876,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2368003,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,8738,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,14640,0,0,0,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,14640,0,3090947,1074596356,0,0,261,14640,0,0,0,0,0,0,0,261,24415,0,261,24415,0,0,0,0,0,0,0,0,0,0,0,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3090947,854531,0,0,0,0,0,0,0,0,261,24415,0,261,10794,0,261,12079,0,261,16448,0,261,12592,0,0,261,14640,0,0,773,1178679600,26209,0,3090947,854531,3090947,854531,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3090947,854531,261,10794,0,261,12079,0,0,0,0,0,0,0,0,0,0,0,261,24415,0,261,24415,0,261,24415,0,261,10794,0,261,12079,0,261,10794,0,261,12079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,10794,0,261,12079,0,0,3090947,854531,3090947,854531,0,3090947,261,12079,0,0,0,1074596356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,10794,0,261,12079,0,261,10794,0,261,12079,0,0,261,10794,0,3090947,0,261,10794,0,0,261,10794,0,261,12079,0,261,16448,0,261,16448,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,261,12079,0,0,854531,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1611467268,0,0,0,0,0,0,0,0,0,0,0,0,1029,1514223920,2053201759,0,0,0,0,0,0,0,1611467268,0,1029,1514223920,2053201759,0,0,0,1611467268,0,0,0,0,1226,4294967295,4294967295,4294967295,4294967295,131071,4294901762,196609,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,262145,393221,524295,655369,786443,917517,1048591,1179665,1310739,1310740,1310740,1310740,1310740,1441813,1572887,1703961,1835035,1835036,1835036,1835036,1835036,1835036,1835036,1835036,1835036,1835036,1835036,1835036,1835036,1900572,2031615,2097151,2162720,2293794,2424868,2555942,2687016,2621480,2621482,2883627,2621485,3080238,2621488,3276849,2621480,3342376,3473460,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901819,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901762,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901819,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,3997695,4294967295,4294901820,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901820,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4063231,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4128767,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4194303,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901824,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325375,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4456515,4587589,4718663,4849737,4915266,4325442,4325452,5111885,4325455,5308496,4325458,5505107,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5636095,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901846,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5701719,5701719,5701719,5701719,5701719,5767167,4294901847,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,4294901847,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701720,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,5701719,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5898239,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5963775,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6029311,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6094847,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6160383,4294901854,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901855,6291552,6291552,6291552,6291552,6291552,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901857,4294967295,6488063,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6553599,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901860,6619237,6619237,6619237,6619237,6619237,4294967295,4294967295,4294967295,4294967295,4294901862,6815743,4294901864,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294901867,4294967295,4294967295,7143423,4294967295,4294901862,6815743,4294901864,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294901867,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901860,7143533,7143533,7143533,7143533,7143533,4294967295,4294967295,4294967295,4294967295,4294967295,6815743,4294901864,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294967295,4294967295,4294967295,7274495,4294967295,4294967295,6815743,4294901864,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901871,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7405567,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7471103,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7536639,4294901875,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7667711,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7733247,4294967295,4294901877,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901877,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7798783,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7864319,4294901879,7864439,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901879,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7995391,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,7995514,7995514,7995514,7995514,7995514,8060927,4294901882,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,8060927,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,8126587,2031647,2031647,2031647,2031647,2031647,2031741,2031647,8257567,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031743,2031647,2031647,8388639,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,8519679,2031647,2031647,2031647,2031647,2031647,2031746,8585247,2031647,2031748,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,8781823,2031647,8781855,2031647,2031647,2031647,2031647,8847391,2031647,2031647,2031647,2031647,8912927,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031753,2031754,2031647,2031647,2031647,2031647,2031755,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,9240575,2031647,2031647,2031647,9240607,2031647,2031647,9306143,2031647,2031647,9371679,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,9437215,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031761,2031647,2031647,9568287,2031763,2031647,9699359,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,9830399,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,9830431,2031647,2031647,9895967,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031768,2031647,2031647,2031647,2031647,2031647,2031647,2031769,2031647,10092575,2031771,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,10289151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031773,10354719,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,10420255,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,10485791,2031647,2031647,2031647,2031647,2031647,2031647,2031647,10551327,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,10682367,2031647,2031647,2031647,2031779,2031647,2031647,2031647,2031647,2031780,2031647,2031647,10813471,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,10944511,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031783,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901928,4294967295,4294967295,4294967295,4294967295,4294967295,11141119,4294901929,11141289,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901929,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,11272191,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901932,4294967295,11403263,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,11468799,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901935,4294967295,11599871,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901937,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4259905,4259905,4259905,4259905,4259905,4325375,4294901825,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4259905,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,11665586,11665586,11665586,11665586,11665586,11730943,4294901938,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11730943,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,11796659,4325442,4325442,4325442,4325442,4325442,4325557,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,11993087,4325442,4325442,4325442,4325442,4325442,4325442,11993154,4325442,4325560,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,12189695,4325442,12189762,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,12255298,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325564,4325442,4325442,4325442,4325442,4325565,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,12451906,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,12517442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,12582978,4325569,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,12779519,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,12779586,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325572,4325442,12910658,4325574,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,13107199,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325576,13172802,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,13238338,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,13303874,4325442,4325442,4325442,4325442,4325442,4325442,4325442,13369410,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,13500415,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,13565951,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325583,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,13697023,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901847,4294901847,5767167,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901847,4294967295,4294967295,4294901847,4294967295,4294967295,4294967295,4294967295,4294967295,4294901847,4294967295,4294901847,13697111,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901970,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901971,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6291552,6291552,6291552,6291552,6291552,4294967295,4294967295,4294967295,4294967295,4294967295,13959167,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14024703,4294967295,4294967295,13959167,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357206,6357089,14090337,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6422626,6422626,6422626,6422626,6422626,6488063,4294901858,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422744,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6291552,6291552,6291552,6291552,6291552,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901860,6619237,6619237,6619237,6619237,6619237,4294967295,4294967295,4294967295,4294967295,4294967295,6815743,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7143423,4294967295,4294967295,6815743,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14221529,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14352383,14352383,4294967295,14352603,14352603,14352603,14352603,14352603,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901980,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901980,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14483677,14483677,14483677,14483677,14483677,4294967295,4294967295,4294967295,14548991,14483677,14483677,4294901981,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14548991,14483677,14483677,4294901981,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6619237,6619237,6619237,6619237,6619237,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7143423,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7143533,7143533,7143533,7143533,7143533,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7274495,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14614527,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901983,4294967295,14745599,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901879,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901985,4294967295,14876671,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,7995514,7995514,7995514,7995514,7995514,8060927,4294901882,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995619,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,7995514,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,14942239,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031845,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031846,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,15204351,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,15204383,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031849,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,15400959,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,15400991,2031852,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,15532063,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031854,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031855,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031856,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,15794207,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,15859743,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031859,2031647,2031860,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031861,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,16121887,2031647,2031647,2031647,2031863,2031864,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031865,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031866,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031867,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031868,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031869,16646175,2031647,2031871,2031872,2031647,2031647,2031873,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031874,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,16973855,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031876,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031877,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,17170463,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031879,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,17301535,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,17367071,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031882,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,17498143,2031647,2031647,17563679,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031885,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,17694751,2031647,2031647,17760287,2031647,2031647,2031647,2031647,2031647,2031888,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,17956863,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031890,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031891,18087967,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,18153503,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,18219039,2031647,2031647,2031647,2031647,2031895,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,18350111,2031647,18415647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031898,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031899,2031647,2031647,2031900,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,18677791,2031647,18743327,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901929,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902047,4294967295,18939903,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272481,11272364,19005612,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11337901,11337901,11337901,11337901,11337901,11403263,4294901933,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,11337901,4294967295,4294967295,4294967295,4294967295,19136511,4294902051,19136803,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902051,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,19267583,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,19333119,4294902054,19333414,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902054,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,19464191,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,11665586,11665586,11665586,11665586,11665586,11730943,4294901938,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665705,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,11665586,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,19529794,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325675,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325676,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325677,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,19791938,4325679,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,19923010,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325681,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325682,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325683,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,20185154,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325685,4325442,4325686,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,20381762,4325442,4325442,4325442,4325688,4325689,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325690,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325691,20709442,4325442,4325693,4325694,4325442,4325442,4325695,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325696,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,21037122,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,21102658,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,21168194,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325700,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,21299266,4325442,4325442,21364802,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325703,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,21495874,4325442,4325442,21561410,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,21692415,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325707,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,21758018,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,21823554,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325710,4325442,4325442,4325711,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,22020162,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22085969,22085969,22085969,22085969,22085969,4294967295,4294967295,4294967295,22151167,22085969,22085969,4294902097,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22151167,22085969,22085969,4294902097,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22216703,22216703,4294967295,22217043,22217043,22217043,22217043,22217043,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6291552,6291552,6291552,6291552,6291552,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14024703,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357206,6357089,22282337,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6422526,6357089,14090337,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6357089,6422626,6422626,6422626,6422626,22347874,6422697,11141461,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422869,6422626,6422626,6422626,6422626,6422626,6422626,22413410,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422744,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14221529,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294967295,4294967295,4294967295,22544383,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14352603,14352603,14352603,14352603,14352603,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14352603,14352603,14352603,14352603,14352603,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22609919,4294967295,4294967295,4294967295,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14483677,14483677,14483677,14483677,14483677,4294967295,4294967295,4294967295,14548991,14483677,14483677,4294901981,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294967295,4294967295,4294967295,22675455,14548991,14483677,14483677,4294901981,4294967295,4294967295,4294901865,4294967295,4294967295,4294967295,7012351,4294967295,4294967295,4294967295,4294967295,4294967295,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614874,14614751,22741215,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14680288,14680288,14680288,14680288,14680288,14745599,4294901984,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14680288,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745948,14745825,22872289,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14811362,14811362,14811362,14811362,14811362,14876671,4294901986,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,14811362,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031966,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,23003167,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,23068703,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,23199743,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,23199775,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,23265311,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031972,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,23396383,2031974,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,23527455,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,23658495,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,23658527,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,23789567,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,23789599,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,23855135,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,23920671,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,23986207,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,24051743,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031984,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,24182815,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,24313855,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,24313887,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,24379423,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031989,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,24510495,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,24576031,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,24641567,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,24707103,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031994,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031995,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,24903711,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031997,2031647,2031998,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031999,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,25165855,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,25296895,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032002,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032003,2031647,2032004,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032005,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,25559071,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2032007,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,25690143,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032009,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032010,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,25886751,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032012,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032013,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,26083359,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,26148895,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,26214431,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,26279967,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,26345503,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,26476543,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032020,2031647,2032021,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032022,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809239,18809119,26738975,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18874656,18874656,18874656,18874656,18874656,18939903,4294902048,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,18874656,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272481,11272364,26804396,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11337726,11272364,19005612,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,11272364,4294967295,4294967295,4294967295,4294967295,4294967295,4294902051,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902170,4294967295,27000831,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902054,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902172,4294967295,27131903,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325790,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,27197506,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,27263042,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,27328578,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325794,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,27459650,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,27525186,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,27590722,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,27721727,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,27721794,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,27787330,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325801,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,27983871,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,27983938,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,28049474,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,28115010,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,28180546,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,28246082,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,28311618,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325809,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325810,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325811,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,28639231,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325813,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325814,4325442,4325815,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325816,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,28901442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325818,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325819,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325820,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325821,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325822,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,29294658,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,29425663,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325825,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,29491650,29491650,29491650,29491650,29491650,4294967295,4294967295,4294967295,29556735,29491650,29491650,4294902210,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,29556735,29491650,29491650,4294902210,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22217043,22217043,22217043,22217043,22217043,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22217043,22217043,22217043,22217043,22217043,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,29622271,4294967295,4294967295,4294967295,4294901864,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29687806,29622724,29688260,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622726,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,6422626,6422626,6422626,6422626,6422626,6488063,4294901858,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422983,6422626,29884514,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422744,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,6422626,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14221529,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22544383,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14352603,14352603,14352603,14352603,14352603,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22609919,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14483677,14483677,14483677,14483677,14483677,4294967295,4294967295,4294967295,14548991,14483677,14483677,4294901981,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22675455,14548991,14483677,14483677,4294901981,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614874,14614751,29950175,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14680062,14614751,22741215,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14614751,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745948,14745825,30015713,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14811134,14745825,22872289,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,14745825,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032075,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,30212095,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032077,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,30277663,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2032079,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,30408735,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,30539775,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032082,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,30605343,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,30670879,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,30736415,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,30801951,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,30867487,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032088,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2032089,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032090,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032091,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032092,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032093,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032094,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032095,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,31457311,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032097,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,31588383,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,31719423,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032100,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,31850495,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,31850527,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,31981567,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,31981599,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,32047135,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,32112671,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,32178207,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,32243743,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032109,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,32374815,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,32505855,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032112,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,32571423,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032114,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2032115,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,32768031,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,32899071,2031647,2031647,2031647,2031647,2031647,2031647,32899103,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,32964639,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032120,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,33095711,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,33161247,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809239,18809119,33227039,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18874366,18809119,26738975,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,18809119,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870268,26870170,33358234,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26935707,26935707,26935707,26935707,26935707,27000831,4294902171,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,26935707,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001342,27001244,33489308,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27066781,27066781,27066781,27066781,27066781,27131903,4294902173,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,27066781,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325888,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,33685503,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325890,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,33816575,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325892,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,33882178,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,33947714,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,34013250,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,34078786,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325897,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325898,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325899,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325900,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325901,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,34472002,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325903,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,34668543,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325905,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,34799615,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,34799682,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,34865218,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,34930754,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,34996290,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,35061826,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,35127362,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,35258367,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,35258434,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325915,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325916,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,35455517,35455517,35455517,35455517,35455517,4294967295,4294967295,4294967295,35520511,35455517,35455517,4294902301,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,35520511,35455517,35455517,4294902301,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,22217043,22217043,22217043,22217043,22217043,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,29622271,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622814,29622724,29688260,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29687806,29622724,29688260,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,35586591,35586591,35586591,35586591,33227295,35586555,35652091,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586555,35586591,35586591,35586591,35586591,35586593,35586591,35783199,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,29819335,29819335,29819335,29819335,29819335,29819167,18809287,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819427,29819335,35914183,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819429,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29884872,29884872,29884872,29884872,29884872,29949951,4294902216,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884966,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,36175871,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032168,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,36306943,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2032170,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032171,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032172,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032173,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,36569119,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,36700159,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,36700191,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032177,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032178,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032179,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032180,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,37027871,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2032182,2031647,2031647,2031647,2032183,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032184,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,37290015,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032186,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032187,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,37486623,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,37552159,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032190,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032191,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,37748767,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,37814303,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032194,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,37945375,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032196,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2032197,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032198,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2032199,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032200,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,38338591,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,38469631,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,4294902346,4294967295,38469631,38404683,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,4294902346,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032204,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2032205,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,38666271,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870268,26870170,38732186,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26935294,26870170,33358234,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,26870170,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001342,27001244,38797724,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27066366,27001244,33489308,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,27001244,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,38928383,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,38993919,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325971,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325972,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,39125058,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,39256063,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,39256130,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325976,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325977,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325978,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325979,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,39583810,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325981,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,39714882,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325983,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325984,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,39911490,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325986,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,40042562,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325988,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325989,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,40239170,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5701719,5701719,5701719,5701719,5701719,4294967295,4294967295,4294967295,5767167,5701719,5701719,4294901847,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,5767167,5701719,5701719,4294901847,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622814,29622724,40305092,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,29622724,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586593,35586591,40370719,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,4294967295,4294967295,4294967295,4294967295,4294967295,4294902267,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586593,35586591,40436255,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35651582,35586591,40501791,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,29819335,29819335,29819335,29819335,29819335,29819167,18809287,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819427,29819335,40567239,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819429,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819167,18809287,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29884414,29819335,35914183,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819429,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,22348231,29819049,11141461,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819221,29819335,29819335,29819335,29819335,29819427,29819335,40632775,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819429,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29884872,29884872,29884872,29884872,29884872,29884585,11141576,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,40698312,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884966,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,29884872,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,40763423,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032239,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,40959999,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,4294902384,4294967295,40959999,40895089,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,4294902384,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,41025567,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,41091103,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,41156639,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032245,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032246,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,41353247,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,41484287,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,41484319,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,41615359,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,41680895,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,41680927,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032253,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,41811999,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2032255,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,41943071,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,42008607,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032258,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032259,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,42205215,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2032261,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2032262,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,42467327,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,42532863,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,4294902408,4294967295,42532863,42467977,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,4294902408,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2032266,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,42663967,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,38404682,38404682,38404682,38404682,38404682,4294967295,4294967295,4294967295,38469631,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,4294902346,4294967295,38469631,38469631,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,38404682,4294902346,4294967295,4294967295,42730124,42730124,42730124,42730124,42730124,42795007,4294902412,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42795007,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,42795039,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,42860610,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4326031,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,42991682,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,43057218,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4326034,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4326035,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,43319295,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,43384831,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,43384898,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4326039,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,43515970,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4326041,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4326042,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4326043,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,43778114,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,43909119,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35651582,35586591,40370719,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35651582,35586591,40370719,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586718,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,35586591,40501866,40501866,40501866,40501866,40501866,40566783,4294902378,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,40501866,29819335,29819335,29819335,29819335,29819335,29819167,18809287,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29884414,29819335,29884871,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819429,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,29819335,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032287,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,44040223,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,40895088,40895088,40895088,40895088,40895088,4294967295,4294967295,4294967295,40959999,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,4294902384,4294967295,40959999,40959999,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,40895088,4294902384,4294967295,4294967295,44106401,44106401,44106401,44106401,44106401,44171263,4294902433,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44171263,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,44171295,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,44236831,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,44302367,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032293,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,44433439,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032295,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,44564511,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2032297,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032298,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,44761119,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032300,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,44892191,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,44957727,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,45023263,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032304,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,45219839,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,4294902449,4294967295,45219839,45154994,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,4294902449,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,45285407,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,42467976,42467976,42467976,42467976,42467976,4294967295,4294967295,4294967295,42532863,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,4294902408,4294967295,42532863,42532863,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,42467976,4294902408,4294967295,4294967295,45351604,45351604,45351604,45351604,45351604,45416447,4294902452,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45416447,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,42730124,42730124,42730124,42730124,42730124,42795007,4294902412,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730165,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,42730124,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,45547519,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,45547586,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,45613122,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,45678658,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4326074,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,45809730,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,45875231,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,44106401,44106401,44106401,44106401,44106401,44171263,4294902433,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106429,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,44106401,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032318,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032319,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2032320,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,46202911,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,46268447,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2032323,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,45154993,45154993,45154993,45154993,45154993,4294967295,4294967295,4294967295,45219839,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,4294902449,4294967295,45219839,45219839,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,45154993,4294902449,4294967295,4294967295,46400196,46400196,46400196,46400196,46400196,46465023,4294902468,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46465023,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,45351604,45351604,45351604,45351604,45351604,45416447,4294902452,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351621,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,45351604,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,46530591,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,46596162,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4326088,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,46727234,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032330,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,46858271,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,46989311,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,4294902476,4294967295,46989311,46924493,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,4294902476,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2032334,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,46400196,46400196,46400196,46400196,46400196,46465023,4294902468,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400207,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,46400196,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,47185986,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4325442,4325442,4325442,4325442,4325442,4294967295,4294967295,4294967295,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4390911,4390911,4325442,4325442,4325442,4325442,4325442,4325442,4326097,4325442,4325442,4325442,4325442,4325442,4294901826,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2032338,2031647,2031647,2031647,4294901791,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,46924492,46924492,46924492,46924492,46924492,4294967295,4294967295,4294967295,46989311,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,4294902476,4294967295,46989311,46989311,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,46924492,4294902476,4294967295,4294967295,47383251,47383251,47383251,47383251,47383251,47448063,4294902483,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47448063,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,2031647,2031647,2031647,2031647,2031647,4294967295,4294967295,4294967295,2097151,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,2097151,2097151,2031647,47448095,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,2031647,4294901791,4294967295,4294967295,47383251,47383251,47383251,47383251,47383251,47448063,4294902483,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383253,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47383251,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645400,47645401,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645402,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47710207,47710207,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47710207,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,47645399,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,48038620,48169694,48300768,48431842,48497371,47907547,47907557,48693990,47907560,48890601,47907563,49087212,47907547,49152731,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902511,4294902511,49283071,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902511,4294967295,4294967295,4294902511,4294967295,4294967295,4294967295,4294967295,4294967295,4294902511,4294967295,4294902511,49283823,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,49349361,49349361,49349361,49349361,49349361,49414143,4294902513,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49414143,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,49480434,47907547,47907547,47907547,47907547,47907547,47907572,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,49676287,47907547,47907547,47907547,47907547,47907547,47907547,49677019,47907547,47907575,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,49872895,47907547,49873627,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,49939163,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907579,47907547,47907547,47907547,47907547,47907580,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,50135771,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,50201307,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,50266843,47907584,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,50462719,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,50463451,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907587,47907547,50594523,47907589,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,50790399,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907591,50856667,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,50922203,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,50987739,47907547,47907547,47907547,47907547,47907547,47907547,47907547,51053275,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,51183615,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,51249151,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907598,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,51315471,51315471,51315471,51315471,51315471,4294967295,4294967295,4294967295,51380223,51315471,51315471,4294902543,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,51380223,51315471,51315471,4294902543,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,49349361,49349361,49349361,49349361,49349361,49414143,4294902513,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349392,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,49349361,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,51446491,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907602,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907603,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907604,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,51708635,47907606,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,51839707,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907608,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907609,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907610,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,52101851,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907612,47907547,47907613,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,52298459,47907547,47907547,47907547,47907615,47907616,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907617,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907618,52626139,47907547,47907620,47907621,47907547,47907547,47907622,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907623,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,52953819,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,53019355,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,53084891,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907627,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,53215963,47907547,47907547,53281499,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907630,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,53412571,47907547,47907547,53478107,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,53608447,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907634,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,53674715,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,53740251,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907637,47907547,47907547,47907638,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,53936859,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,54002488,54002488,54002488,54002488,54002488,4294967295,4294967295,4294967295,54067199,54002488,54002488,4294902584,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,54067199,54002488,54002488,4294902584,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907641,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,54133467,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,54199003,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,54264539,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907645,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,54395611,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,54461147,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,54526683,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,54657023,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,54657755,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,54723291,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907652,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,54919167,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,54919899,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,54985435,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,55050971,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,55116507,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,55182043,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,55247579,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907660,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907661,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907662,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,55574527,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907664,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907665,47907547,47907666,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907667,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,55837403,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907669,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907670,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907671,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907672,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907673,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,56230619,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,56360959,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907676,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,56427357,56427357,56427357,56427357,56427357,4294967295,4294967295,4294967295,56492031,56427357,56427357,4294902621,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,56492031,56427357,56427357,4294902621,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907678,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,56623103,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907680,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,56754175,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907682,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,56820443,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,56885979,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,56951515,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,57017051,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907687,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907688,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907689,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907690,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907691,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,57410267,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907693,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,57606143,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907695,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,57737215,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,57737947,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,57803483,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,57869019,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,57934555,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,58000091,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,58065627,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,58195967,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,58196699,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907705,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907706,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,49218287,49218287,49218287,49218287,49218287,4294967295,4294967295,4294967295,49283071,49218287,49218287,4294902511,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,49283071,49218287,49218287,4294902511,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,58458111,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,58523647,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907709,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907710,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,58655451,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,58785791,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,58786523,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907714,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907715,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907716,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907717,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,59114203,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907719,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,59245275,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907721,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907722,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,59441883,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907724,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,59572955,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907726,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907727,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,59769563,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,59835099,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907730,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,59966171,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,60031707,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907733,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907734,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,60293119,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,60358655,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,60359387,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907738,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,60490459,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907740,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907741,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907742,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,60752603,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,60882943,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,60883675,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,60949211,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,61014747,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907748,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,61145819,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,61211355,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907751,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,61342427,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,61407963,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,47907547,47907547,47907547,47907547,47907547,4294967295,4294967295,4294967295,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,47972351,47972351,47907547,47907547,47907547,47907547,47907547,47907547,47907754,47907547,47907547,47907547,47907547,47907547,4294902491,4294967295,4294967295,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604781,61604782,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61669375,61669375,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,61604780,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902703,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61998001,62129075,62260149,62391223,62456752,61866928,61866938,62653371,61866941,62849982,61866944,63046593,61866928,63112112,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902724,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,63243205,63243205,63243205,63243205,63243205,63307775,4294902725,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63307775,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,63374278,61866928,61866928,61866928,61866928,61866928,61866952,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,63569919,61866928,61866928,61866928,61866928,61866928,61866928,63570864,61866928,61866955,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,63766527,61866928,63767472,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,63833008,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866959,61866928,61866928,61866928,61866928,61866960,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,64029616,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,64095152,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,64160688,61866964,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,64356351,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,64357296,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866967,61866928,64488368,61866969,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,64684031,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866971,64750512,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,64816048,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,64881584,61866928,61866928,61866928,61866928,61866928,61866928,61866928,64947120,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,65077247,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,65142783,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866978,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,63243205,63243205,63243205,63243205,63243205,63307775,4294902725,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243235,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,63243205,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,65274800,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866981,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866982,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866983,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,65536944,61866985,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,65668016,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866987,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866988,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866989,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,65930160,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866991,61866928,61866992,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,66126768,61866928,61866928,61866928,61866994,61866995,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866996,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866997,66454448,61866928,61866999,61867000,61866928,61866928,61867001,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867002,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,66782128,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,66847664,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,66913200,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867006,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,67044272,61866928,61866928,67109808,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61867009,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,67240880,61866928,61866928,67306416,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,67436543,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867013,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,67503024,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,67568560,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867016,61866928,61866928,61867017,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,67765168,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867019,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,67896240,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,67961776,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,68027312,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867023,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,68158384,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,68223920,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,68289456,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,68419583,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,68420528,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,68486064,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867030,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,68681727,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,68682672,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,68748208,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,68813744,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,68879280,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,68944816,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,69010352,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867038,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867039,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867040,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,69337087,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867042,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867043,61866928,61867044,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867045,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,69600176,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61867047,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867048,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867049,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867050,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867051,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,69993392,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,70123519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867054,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867055,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,70320127,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867057,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,70451199,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867059,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,70517680,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,70583216,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,70648752,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,70714288,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867064,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867065,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867066,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867067,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867068,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,71107504,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867070,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,71303167,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867072,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,71434239,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,71435184,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,71500720,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,71566256,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,71631792,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,71697328,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,71762864,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,71892991,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,71893936,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867082,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867083,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,72155135,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,72220671,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867086,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867087,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,72352688,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,72482815,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,72483760,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867091,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867092,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867093,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867094,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,72811440,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867096,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,72942512,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867098,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867099,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,73139120,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867101,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,73270192,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867103,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867104,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,73466800,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,73532336,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867107,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,73663408,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,73728944,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867110,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867111,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,73990143,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,74055679,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,74056624,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867115,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,74187696,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61867117,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867118,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867119,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,74449840,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,74579967,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,74580912,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,74646448,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,74711984,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61867125,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,74843056,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,74908592,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61867128,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,75039664,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,75105200,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,61866928,61866928,61866928,61866928,61866928,4294967295,4294967295,4294967295,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,61931519,61931519,61866928,61866928,61866928,61866928,61866928,61866928,61867131,61866928,61866928,61866928,61866928,61866928,4294902704,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,75366399,4294902910,75433085,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,75498621,75629697,75759615,75826308,75957382,76088456,76219530,76350604,76481678,76481679,76481679,76481679,76481679,76612752,76743826,76874900,77005974,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77071511,77201407,77070335,77268122,77399196,77530270,77661344,77726871,77005975,77005987,77923492,77005990,78120103,77005993,78316714,77005975,78382231,78513325,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902959,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902910,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902959,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,78708735,4294902960,78709936,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902960,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,78839807,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,78905343,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,78970879,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902965,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79101951,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902967,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79168696,79168696,79168696,79168696,79168696,79233023,4294902968,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,4294902968,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168697,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,79168696,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79364095,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79429631,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79495167,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79560703,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79626239,4294902975,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902976,79758529,79758529,79758529,79758529,79758529,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902978,4294967295,79953919,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80019455,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902981,80086214,80086214,80086214,80086214,80086214,4294967295,4294967295,4294967295,4294967295,4294902983,80281599,4294902985,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294902988,4294967295,4294967295,80609279,4294967295,4294902983,80281599,4294902985,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294902988,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902981,76481679,76481679,76481679,76481679,76481679,4294967295,4294967295,4294967295,4294967295,4294967295,80281599,4294902985,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294967295,4294967295,4294967295,80674815,4294967295,4294967295,80281599,4294902985,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902991,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80805887,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80871423,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80936959,4294902995,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,81068031,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,81133567,4294902997,81134805,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902997,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,81264639,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,81330175,4294903000,81331416,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903000,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,81461247,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,81462491,81462491,81462491,81462491,81462491,81526783,4294903003,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81526783,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,81593564,77005975,77005975,77005975,77005975,77005975,77006046,77005975,81724567,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006048,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,81919999,77005975,77005975,77005975,77005975,77005975,77005975,81921175,77005975,77006051,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,82116607,77005975,82117783,77005975,77005975,77005975,77005975,82183319,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006055,77006056,77005975,77005975,77005975,77005975,77006057,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,82509823,77005975,77005975,77005975,82510999,77005975,77005975,82576535,77005975,77005975,82642071,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,82707607,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77006063,77005975,77005975,77005975,77006064,77005975,82904215,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,83034111,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,83035287,77005975,77005975,83100823,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77006069,77005975,77005975,77005975,77005975,77005975,77005975,77006070,77005975,83297431,77006072,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,83492863,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006074,83559575,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,83625111,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,83690647,77005975,77005975,77005975,77005975,77005975,77005975,77005975,83756183,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,83886079,77005975,77005975,77005975,77006080,77005975,77005975,77005975,77005975,77006081,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,84082687,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77006083,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903044,4294967295,4294967295,4294967295,4294967295,4294967295,84279295,4294903045,84280581,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903045,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,84410367,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902960,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903048,4294967295,84541439,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,84606975,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903051,4294967295,84738047,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903053,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,84869119,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902968,4294902968,79233023,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902968,4294967295,4294967295,4294902968,4294967295,4294967295,4294967295,4294967295,4294967295,4294902968,4294967295,4294902968,84870328,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903056,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903057,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79758529,79758529,79758529,79758529,79758529,4294967295,4294967295,4294967295,4294967295,4294967295,80281599,4294902985,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85131263,4294967295,4294967295,80281599,4294902985,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824147,79824066,85198018,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79889603,79889603,79889603,79889603,79889603,79953919,4294902979,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889685,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79758529,79758529,79758529,79758529,79758529,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902981,80086214,80086214,80086214,80086214,80086214,4294967295,4294967295,4294967295,4294967295,4294967295,80281599,4294902985,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80609279,4294967295,4294967295,80281599,4294902985,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85329174,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85458943,85458943,4294967295,85460248,85460248,85460248,85460248,85460248,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903065,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903065,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85591322,85591322,85591322,85591322,85591322,4294967295,4294967295,4294967295,85655551,85591322,85591322,4294903066,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85655551,85591322,85591322,4294903066,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80086214,80086214,80086214,80086214,80086214,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80609279,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,76481679,76481679,76481679,76481679,76481679,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,80674815,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85721087,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902997,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903068,4294967295,85852159,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903000,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903070,4294967295,85983231,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,81462491,81462491,81462491,81462491,81462491,81526783,4294903003,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462560,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,81462491,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,86049943,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006114,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006115,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,86310911,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,86312087,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006118,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006119,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,86508695,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006121,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006122,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,86705303,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,86770839,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006125,77005975,77006126,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006127,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,87032983,77005975,77005975,77005975,77006129,77006130,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006131,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006132,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006133,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77006134,77005975,77005975,77006135,77006136,77005975,77005975,77006137,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006138,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,87753879,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006140,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77006141,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,87950487,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006143,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,88081559,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006145,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,88212631,77005975,77005975,88278167,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77006148,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,88409239,77005975,77005975,88474775,77005975,77005975,77005975,77005975,77005975,77006151,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,88670207,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006153,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006154,88802455,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,88867991,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006157,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,88999063,77005975,89064599,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006160,77005975,77005975,77006161,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,89261207,77005975,89326743,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903045,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903124,4294967295,89522175,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411734,84411656,89589000,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84477193,84477193,84477193,84477193,84477193,84541439,4294903049,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,84477193,4294967295,4294967295,4294967295,4294967295,89718783,4294903128,89720152,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903128,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,89849855,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,89915391,4294903131,89916763,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903131,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,90046463,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,90047838,90047838,90047838,90047838,90047838,4294967295,4294967295,4294967295,90111999,90047838,90047838,4294903134,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,90111999,90047838,90047838,4294903134,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79758529,79758529,79758529,79758529,79758529,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85131263,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824147,79824066,90113218,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79888382,79824066,85198018,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79824066,79889603,79889603,79889603,79889603,90178755,79889669,84280672,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889760,79889603,79889603,79889603,79889603,79889603,79889603,90244291,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889685,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85329174,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294967295,4294967295,4294967295,90374143,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85460248,85460248,85460248,85460248,85460248,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85460248,85460248,85460248,85460248,85460248,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294902985,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,90439679,4294967295,4294967295,4294967295,4294902985,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85591322,85591322,85591322,85591322,85591322,4294967295,4294967295,4294967295,85655551,85591322,85591322,4294903066,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294967295,4294967295,4294967295,90505215,85655551,85591322,85591322,4294903066,4294967295,4294967295,4294902986,4294967295,4294967295,4294967295,80478207,4294967295,4294967295,4294967295,4294967295,4294967295,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722469,85722396,90572060,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85787933,85787933,85787933,85787933,85787933,85852159,4294903069,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85787933,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853543,85853470,90703134,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85919007,85919007,85919007,85919007,85919007,85983231,4294903071,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,85919007,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006185,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,90834071,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,90899607,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,91029503,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,91030679,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,91096215,77006191,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,91227287,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,91357183,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,91358359,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,91423895,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,91489431,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,91554967,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,91620503,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,91686039,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006200,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,91817111,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,91947007,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,91948183,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,92013719,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,92079255,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,92144791,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,92210327,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006208,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006209,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,92406935,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006211,77005975,77006212,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006213,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,92733439,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006215,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006216,77005975,77006217,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006218,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,92996759,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77006220,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,93127831,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006222,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006223,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,93324439,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006225,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006226,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,93521047,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,93586583,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,93652119,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,93782015,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006231,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006232,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392537,89392468,93979988,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89458005,89458005,89458005,89458005,89458005,89522175,4294903125,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,89458005,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411734,84411656,94045448,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84475902,84411656,89589000,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,84411656,4294967295,4294967295,4294967295,4294967295,4294967295,4294903128,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903196,4294967295,94240767,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903131,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294903198,4294967295,94371839,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,94373280,94373280,94373280,94373280,94373280,4294967295,4294967295,4294967295,94437375,94373280,94373280,4294903200,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,94437375,94373280,94373280,4294903200,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94502910,94438817,94504353,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438819,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,79889603,79889603,79889603,79889603,79889603,79953919,4294902979,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889828,79889603,94700739,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889685,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,79889603,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85329174,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,90374143,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85460248,85460248,85460248,85460248,85460248,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,90439679,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85591322,85591322,85591322,85591322,85591322,4294967295,4294967295,4294967295,85655551,85591322,85591322,4294903066,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,90505215,85655551,85591322,85591322,4294903066,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722469,85722396,94766364,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85786622,85722396,90572060,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85722396,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853543,85853470,94831902,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85917694,85853470,90703134,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,85853470,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006248,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,95027199,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006250,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,95093911,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77006252,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006253,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,95290519,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,95356055,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,95421591,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,95487127,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006258,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77006259,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006260,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006261,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006262,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006263,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006264,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,96011415,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006266,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,96142487,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,96272383,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006269,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,96339095,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,96468991,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,96470167,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,96535703,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,96601239,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,96666775,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,96732311,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006277,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,96863383,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,96993279,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006280,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,97059991,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006282,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,97191063,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,97256599,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006285,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,97387671,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392537,89392468,97453396,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89456638,89392468,93979988,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,89392468,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111184,94111132,97584540,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94176669,94176669,94176669,94176669,94176669,94240767,4294903197,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94176669,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242258,94242206,97715614,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94307743,94307743,94307743,94307743,94307743,94371839,4294903199,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,94307743,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,97781204,97781204,97781204,97781204,97781204,4294967295,4294967295,4294967295,97845247,97781204,97781204,4294903252,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,97845247,97781204,97781204,4294903252,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438869,94438817,94504353,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94502910,94438817,94504353,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,97912278,97912278,97912278,97912278,97453526,97912271,97977807,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912271,97912278,97912278,97912278,97912278,97912280,97912278,98108886,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,94635428,94635428,94635428,94635428,94635428,94635348,89392548,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635482,94635428,98239908,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635484,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94700965,94700965,94700965,94700965,94700965,94765055,4294903205,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94701021,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,98500607,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006303,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,98631679,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77006305,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006306,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,98763927,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,98893823,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006309,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006310,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006311,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,99091607,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006313,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006314,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,99288215,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006316,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006317,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,99484823,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006319,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006320,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,99681431,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,99746967,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006323,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,99878039,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006325,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77006326,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006327,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006328,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,100205719,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,100271255,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111184,94111132,100337052,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94175230,94111132,97584540,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94111132,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242258,94242206,100402590,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94306302,94242206,97715614,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,94242206,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79168696,79168696,79168696,79168696,79168696,4294967295,4294967295,4294967295,79233023,79168696,79168696,4294902968,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,79233023,79168696,79168696,4294902968,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438869,94438817,100468129,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,94438817,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912280,97912278,100533718,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,4294967295,4294967295,4294967295,4294967295,4294967295,4294903247,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912280,97912278,100599254,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97976318,97912278,100664790,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,94635428,94635428,94635428,94635428,94635428,94635348,89392548,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635482,94635428,100730276,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635484,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635348,89392548,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94699518,94635428,98239908,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635484,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,90178980,94635269,84280672,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635360,94635428,94635428,94635428,94635428,94635482,94635428,100795812,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635484,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94700965,94700965,94700965,94700965,94700965,94700805,84280741,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,100861349,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94701021,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,94700965,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,100926615,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006341,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,101122047,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,4294903302,4294967295,101122047,101058055,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,4294903302,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,101188759,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006345,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006346,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,101449727,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,101450903,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,101580799,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,101581975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006351,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,101713047,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77006353,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,101844119,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006355,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006356,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,102040727,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77006358,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77006359,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,102301695,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77006361,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,102368407,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97976318,97912278,100533718,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97976318,97912278,100533718,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912347,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,97912278,100664832,100664832,100664832,100664832,100664832,100728831,4294903296,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,100664832,94635428,94635428,94635428,94635428,94635428,94635348,89392548,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94699518,94635428,94700964,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635484,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,94635428,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006364,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,102565015,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,101058054,101058054,101058054,101058054,101058054,4294967295,4294967295,4294967295,101122047,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,4294903302,4294967295,101122047,101122047,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,101058054,4294903302,4294967295,4294967295,102630942,102630942,102630942,102630942,102630942,102694911,4294903326,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102694911,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,102696087,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006368,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,102827159,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006370,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77006371,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006372,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,103089303,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006374,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,103220375,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,103285911,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,103351447,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77006378,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,103546879,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,4294903339,4294967295,103546879,103482924,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,4294903339,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,103613591,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,103679127,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,102630942,102630942,102630942,102630942,102630942,102694911,4294903326,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630959,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,102630942,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77006384,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,103875735,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77006386,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,103482923,103482923,103482923,103482923,103482923,4294967295,4294967295,4294967295,103546879,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,4294903339,4294967295,103546879,103546879,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,103482923,4294903339,4294967295,4294967295,104007219,104007219,104007219,104007219,104007219,104071167,4294903347,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104071167,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006388,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,104202239,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,4294903349,4294967295,104202239,104138294,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,4294903349,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77006391,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,104007219,104007219,104007219,104007219,104007219,104071167,4294903347,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007224,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,104007219,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,104138293,104138293,104138293,104138293,104138293,4294967295,4294967295,4294967295,104202239,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,4294903349,4294967295,104202239,104202239,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,104138293,4294903349,4294967295,4294967295,104400441,104400441,104400441,104400441,104400441,104464383,4294903353,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104464383,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,77005975,77005975,77005975,77005975,77005975,4294967295,4294967295,4294967295,77070335,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,77070335,77070335,77005975,104465559,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,77005975,4294902935,4294967295,4294967295,104400441,104400441,104400441,104400441,104400441,104464383,4294903353,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400443,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104400441,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,104662589,84,1547,170,170,54,181,181,40,186,186,54,192,214,28,216,222,28,223,246,40,248,255,40,256,256,28,257,257,40,258,258,28,259,259,40,260,260,28,261,261,40,262,262,28,263,263,40,264,264,28,265,265,40,266,266,28,267,267,40,268,268,28,269,269,40,270,270,28,271,271,40,272,272,28,273,273,40,274,274,28,275,275,40,276,276,28,277,277,40,278,278,28,279,279,40,280,280,28,281,281,40,282,282,28,283,283,40,284,284,28,285,285,40,286,286,28,287,287,40,288,288,28,289,289,40,290,290,28,291,291,40,292,292,28,293,293,40,294,294,28,295,295,40,296,296,28,297,297,40,298,298,28,299,299,40,300,300,28,301,301,40,302,302,28,303,303,40,304,304,28,305,305,40,306,306,28,307,307,40,308,308,28,309,309,40,310,310,28,311,312,40,313,313,28,314,314,40,315,315,28,316,316,40,317,317,28,318,318,40,319,319,28,320,320,40,321,321,28,322,322,40,323,323,28,324,324,40,325,325,28,326,326,40,327,327,28,328,329,40,330,330,28,331,331,40,332,332,28,333,333,40,334,334,28,335,335,40,336,336,28,337,337,40,338,338,28,339,339,40,340,340,28,341,341,40,342,342,28,343,343,40,344,344,28,345,345,40,346,346,28,347,347,40,348,348,28,349,349,40,350,350,28,351,351,40,352,352,28,353,353,40,354,354,28,355,355,40,356,356,28,357,357,40,358,358,28,359,359,40,360,360,28,361,361,40,362,362,28,363,363,40,364,364,28,365,365,40,366,366,28,367,367,40,368,368,28,369,369,40,370,370,28,371,371,40,372,372,28,373,373,40,374,374,28,375,375,40,376,377,28,378,378,40,379,379,28,380,380,40,381,381,28,382,384,40,385,386,28,387,387,40,388,388,28,389,389,40,390,391,28,392,392,40,393,395,28,396,397,40,398,401,28,402,402,40,403,404,28,405,405,40,406,408,28,409,411,40,412,413,28,414,414,40,415,416,28,417,417,40,418,418,28,419,419,40,420,420,28,421,421,40,422,423,28,424,424,40,425,425,28,426,427,40,428,428,28,429,429,40,430,431,28,432,432,40,433,435,28,436,436,40,437,437,28,438,438,40,439,440,28,441,442,40,443,443,54,444,444,28,445,447,40,448,451,54,452,452,28,453,453,55,454,454,40,455,455,28,456,456,55,457,457,40,458,458,28,459,459,55,460,460,40,461,461,28,462,462,40,463,463,28,464,464,40,465,465,28,466,466,40,467,467,28,468,468,40,469,469,28,470,470,40,471,471,28,472,472,40,473,473,28,474,474,40,475,475,28,476,477,40,478,478,28,479,479,40,480,480,28,481,481,40,482,482,28,483,483,40,484,484,28,485,485,40,486,486,28,487,487,40,488,488,28,489,489,40,490,490,28,491,491,40,492,492,28,493,493,40,494,494,28,495,496,40,497,497,28,498,498,55,499,499,40,500,500,28,501,501,40,502,504,28,505,505,40,506,506,28,507,507,40,508,508,28,509,509,40,510,510,28,511,511,40,512,512,28,513,513,40,514,514,28,515,515,40,516,516,28,517,517,40,518,518,28,519,519,40,520,520,28,521,521,40,522,522,28,523,523,40,524,524,28,525,525,40,526,526,28,527,527,40,528,528,28,529,529,40,530,530,28,531,531,40,532,532,28,533,533,40,534,534,28,535,535,40,536,536,28,537,537,40,538,538,28,539,539,40,540,540,28,541,541,40,542,542,28,543,543,40,544,544,28,545,545,40,546,546,28,547,547,40,548,548,28,549,549,40,550,550,28,551,551,40,552,552,28,553,553,40,554,554,28,555,555,40,556,556,28,557,557,40,558,558,28,559,559,40,560,560,28,561,561,40,562,562,28,563,569,40,570,571,28,572,572,40,573,574,28,575,576,40,577,577,28,578,578,40,579,582,28,583,583,40,584,584,28,585,585,40,586,586,28,587,587,40,588,588,28,589,589,40,590,590,28,591,659,40,660,660,54,661,687,40,688,705,56,710,721,56,736,740,56,748,748,56,750,750,56,880,880,28,881,881,40,882,882,28,883,883,40,884,884,56,886,886,28,887,887,40,890,890,56,891,893,40,902,902,28,904,906,28,908,908,28,910,911,28,912,912,40,913,929,28,931,939,28,940,974,40,975,975,28,976,977,40,978,980,28,981,983,40,984,984,28,985,985,40,986,986,28,987,987,40,988,988,28,989,989,40,990,990,28,991,991,40,992,992,28,993,993,40,994,994,28,995,995,40,996,996,28,997,997,40,998,998,28,999,999,40,1000,1000,28,1001,1001,40,1002,1002,28,1003,1003,40,1004,1004,28,1005,1005,40,1006,1006,28,1007,1011,40,1012,1012,28,1013,1013,40,1015,1015,28,1016,1016,40,1017,1018,28,1019,1020,40,1021,1071,28,1072,1119,40,1120,1120,28,1121,1121,40,1122,1122,28,1123,1123,40,1124,1124,28,1125,1125,40,1126,1126,28,1127,1127,40,1128,1128,28,1129,1129,40,1130,1130,28,1131,1131,40,1132,1132,28,1133,1133,40,1134,1134,28,1135,1135,40,1136,1136,28,1137,1137,40,1138,1138,28,1139,1139,40,1140,1140,28,1141,1141,40,1142,1142,28,1143,1143,40,1144,1144,28,1145,1145,40,1146,1146,28,1147,1147,40,1148,1148,28,1149,1149,40,1150,1150,28,1151,1151,40,1152,1152,28,1153,1153,40,1162,1162,28,1163,1163,40,1164,1164,28,1165,1165,40,1166,1166,28,1167,1167,40,1168,1168,28,1169,1169,40,1170,1170,28,1171,1171,40,1172,1172,28,1173,1173,40,1174,1174,28,1175,1175,40,1176,1176,28,1177,1177,40,1178,1178,28,1179,1179,40,1180,1180,28,1181,1181,40,1182,1182,28,1183,1183,40,1184,1184,28,1185,1185,40,1186,1186,28,1187,1187,40,1188,1188,28,1189,1189,40,1190,1190,28,1191,1191,40,1192,1192,28,1193,1193,40,1194,1194,28,1195,1195,40,1196,1196,28,1197,1197,40,1198,1198,28,1199,1199,40,1200,1200,28,1201,1201,40,1202,1202,28,1203,1203,40,1204,1204,28,1205,1205,40,1206,1206,28,1207,1207,40,1208,1208,28,1209,1209,40,1210,1210,28,1211,1211,40,1212,1212,28,1213,1213,40,1214,1214,28,1215,1215,40,1216,1217,28,1218,1218,40,1219,1219,28,1220,1220,40,1221,1221,28,1222,1222,40,1223,1223,28,1224,1224,40,1225,1225,28,1226,1226,40,1227,1227,28,1228,1228,40,1229,1229,28,1230,1231,40,1232,1232,28,1233,1233,40,1234,1234,28,1235,1235,40,1236,1236,28,1237,1237,40,1238,1238,28,1239,1239,40,1240,1240,28,1241,1241,40,1242,1242,28,1243,1243,40,1244,1244,28,1245,1245,40,1246,1246,28,1247,1247,40,1248,1248,28,1249,1249,40,1250,1250,28,1251,1251,40,1252,1252,28,1253,1253,40,1254,1254,28,1255,1255,40,1256,1256,28,1257,1257,40,1258,1258,28,1259,1259,40,1260,1260,28,1261,1261,40,1262,1262,28,1263,1263,40,1264,1264,28,1265,1265,40,1266,1266,28,1267,1267,40,1268,1268,28,1269,1269,40,1270,1270,28,1271,1271,40,1272,1272,28,1273,1273,40,1274,1274,28,1275,1275,40,1276,1276,28,1277,1277,40,1278,1278,28,1279,1279,40,1280,1280,28,1281,1281,40,1282,1282,28,1283,1283,40,1284,1284,28,1285,1285,40,1286,1286,28,1287,1287,40,1288,1288,28,1289,1289,40,1290,1290,28,1291,1291,40,1292,1292,28,1293,1293,40,1294,1294,28,1295,1295,40,1296,1296,28,1297,1297,40,1298,1298,28,1299,1299,40,1300,1300,28,1301,1301,40,1302,1302,28,1303,1303,40,1304,1304,28,1305,1305,40,1306,1306,28,1307,1307,40,1308,1308,28,1309,1309,40,1310,1310,28,1311,1311,40,1312,1312,28,1313,1313,40,1314,1314,28,1315,1315,40,1316,1316,28,1317,1317,40,1318,1318,28,1319,1319,40,1329,1366,28,1369,1369,56,1377,1415,40,1488,1514,54,1520,1522,54,1568,1599,54,1600,1600,56,1601,1610,54,1632,1641,57,1646,1647,54,1649,1747,54,1749,1749,54,1765,1766,56,1774,1775,54,1776,1785,57,1786,1788,54,1791,1791,54,1808,1808,54,1810,1839,54,1869,1957,54,1969,1969,54,1984,1993,57,1994,2026,54,2036,2037,56,2042,2042,56,2048,2069,54,2074,2074,56,2084,2084,56,2088,2088,56,2112,2136,54,2208,2208,54,2210,2220,54,2308,2361,54,2365,2365,54,2384,2384,54,2392,2401,54,2406,2415,57,2417,2417,56,2418,2423,54,2425,2431,54,2437,2444,54,2447,2448,54,2451,2472,54,2474,2480,54,2482,2482,54,2486,2489,54,2493,2493,54,2510,2510,54,2524,2525,54,2527,2529,54,2534,2543,57,2544,2545,54,2565,2570,54,2575,2576,54,2579,2600,54,2602,2608,54,2610,2611,54,2613,2614,54,2616,2617,54,2649,2652,54,2654,2654,54,2662,2671,57,2674,2676,54,2693,2701,54,2703,2705,54,2707,2728,54,2730,2736,54,2738,2739,54,2741,2745,54,2749,2749,54,2768,2768,54,2784,2785,54,2790,2799,57,2821,2828,54,2831,2832,54,2835,2856,54,2858,2864,54,2866,2867,54,2869,2873,54,2877,2877,54,2908,2909,54,2911,2913,54,2918,2927,57,2929,2929,54,2947,2947,54,2949,2954,54,2958,2960,54,2962,2965,54,2969,2970,54,2972,2972,54,2974,2975,54,2979,2980,54,2984,2986,54,2990,3001,54,3024,3024,54,3046,3055,57,3077,3084,54,3086,3088,54,3090,3112,54,3114,3123,54,3125,3129,54,3133,3133,54,3160,3161,54,3168,3169,54,3174,3183,57,3205,3212,54,3214,3216,54,3218,3240,54,3242,3251,54,3253,3257,54,3261,3261,54,3294,3294,54,3296,3297,54,3302,3311,57,3313,3314,54,3333,3340,54,3342,3344,54,3346,3386,54,3389,3389,54,3406,3406,54,3424,3425,54,3430,3439,57,3450,3455,54,3461,3478,54,3482,3505,54,3507,3515,54,3517,3517,54,3520,3526,54,3585,3632,54,3634,3635,54,3648,3653,54,3654,3654,56,3664,3673,57,3713,3714,54,3716,3716,54,3719,3720,54,3722,3722,54,3725,3725,54,3732,3735,54,3737,3743,54,3745,3747,54,3749,3749,54,3751,3751,54,3754,3755,54,3757,3760,54,3762,3763,54,3773,3773,54,3776,3780,54,3782,3782,56,3792,3801,57,3804,3807,54,3840,3840,54,3872,3881,57,3904,3911,54,3913,3948,54,3976,3980,54,4096,4138,54,4159,4159,54,4160,4169,57,4176,4181,54,4186,4189,54,4193,4193,54,4197,4198,54,4206,4208,54,4213,4225,54,4238,4238,54,4240,4249,57,4256,4293,28,4295,4295,28,4301,4301,28,4304,4346,54,4348,4348,56,4349,4680,54,4682,4685,54,4688,4694,54,4696,4696,54,4698,4701,54,4704,4744,54,4746,4749,54,4752,4784,54,4786,4789,54,4792,4798,54,4800,4800,54,4802,4805,54,4808,4822,54,4824,4880,54,4882,4885,54,4888,4954,54,4992,5007,54,5024,5108,54,5121,5740,54,5743,5759,54,5761,5786,54,5792,5866,54,5870,5872,58,5888,5900,54,5902,5905,54,5920,5937,54,5952,5969,54,5984,5996,54,5998,6000,54,6016,6067,54,6103,6103,56,6108,6108,54,6112,6121,57,6160,6169,57,6176,6210,54,6211,6211,56,6212,6263,54,6272,6312,54,6314,6314,54,6320,6389,54,6400,6428,54,6470,6479,57,6480,6509,54,6512,6516,54,6528,6571,54,6593,6599,54,6608,6617,57,6656,6678,54,6688,6740,54,6784,6793,57,6800,6809,57,6823,6823,56,6917,6963,54,6981,6987,54,6992,7001,57,7043,7072,54,7086,7087,54,7088,7097,57,7098,7141,54,7168,7203,54,7232,7241,57,7245,7247,54,7248,7257,57,7258,7287,54,7288,7293,56,7401,7404,54,7406,7409,54,7413,7414,54,7424,7467,40,7468,7530,56,7531,7543,40,7544,7544,56,7545,7578,40,7579,7615,56,7680,7680,28,7681,7681,40,7682,7682,28,7683,7683,40,7684,7684,28,7685,7685,40,7686,7686,28,7687,7687,40,7688,7688,28,7689,7689,40,7690,7690,28,7691,7691,40,7692,7692,28,7693,7693,40,7694,7694,28,7695,7695,40,7696,7696,28,7697,7697,40,7698,7698,28,7699,7699,40,7700,7700,28,7701,7701,40,7702,7702,28,7703,7703,40,7704,7704,28,7705,7705,40,7706,7706,28,7707,7707,40,7708,7708,28,7709,7709,40,7710,7710,28,7711,7711,40,7712,7712,28,7713,7713,40,7714,7714,28,7715,7715,40,7716,7716,28,7717,7717,40,7718,7718,28,7719,7719,40,7720,7720,28,7721,7721,40,7722,7722,28,7723,7723,40,7724,7724,28,7725,7725,40,7726,7726,28,7727,7727,40,7728,7728,28,7729,7729,40,7730,7730,28,7731,7731,40,7732,7732,28,7733,7733,40,7734,7734,28,7735,7735,40,7736,7736,28,7737,7737,40,7738,7738,28,7739,7739,40,7740,7740,28,7741,7741,40,7742,7742,28,7743,7743,40,7744,7744,28,7745,7745,40,7746,7746,28,7747,7747,40,7748,7748,28,7749,7749,40,7750,7750,28,7751,7751,40,7752,7752,28,7753,7753,40,7754,7754,28,7755,7755,40,7756,7756,28,7757,7757,40,7758,7758,28,7759,7759,40,7760,7760,28,7761,7761,40,7762,7762,28,7763,7763,40,7764,7764,28,7765,7765,40,7766,7766,28,7767,7767,40,7768,7768,28,7769,7769,40,7770,7770,28,7771,7771,40,7772,7772,28,7773,7773,40,7774,7774,28,7775,7775,40,7776,7776,28,7777,7777,40,7778,7778,28,7779,7779,40,7780,7780,28,7781,7781,40,7782,7782,28,7783,7783,40,7784,7784,28,7785,7785,40,7786,7786,28,7787,7787,40,7788,7788,28,7789,7789,40,7790,7790,28,7791,7791,40,7792,7792,28,7793,7793,40,7794,7794,28,7795,7795,40,7796,7796,28,7797,7797,40,7798,7798,28,7799,7799,40,7800,7800,28,7801,7801,40,7802,7802,28,7803,7803,40,7804,7804,28,7805,7805,40,7806,7806,28,7807,7807,40,7808,7808,28,7809,7809,40,7810,7810,28,7811,7811,40,7812,7812,28,7813,7813,40,7814,7814,28,7815,7815,40,7816,7816,28,7817,7817,40,7818,7818,28,7819,7819,40,7820,7820,28,7821,7821,40,7822,7822,28,7823,7823,40,7824,7824,28,7825,7825,40,7826,7826,28,7827,7827,40,7828,7828,28,7829,7837,40,7838,7838,28,7839,7839,40,7840,7840,28,7841,7841,40,7842,7842,28,7843,7843,40,7844,7844,28,7845,7845,40,7846,7846,28,7847,7847,40,7848,7848,28,7849,7849,40,7850,7850,28,7851,7851,40,7852,7852,28,7853,7853,40,7854,7854,28,7855,7855,40,7856,7856,28,7857,7857,40,7858,7858,28,7859,7859,40,7860,7860,28,7861,7861,40,7862,7862,28,7863,7863,40,7864,7864,28,7865,7865,40,7866,7866,28,7867,7867,40,7868,7868,28,7869,7869,40,7870,7870,28,7871,7871,40,7872,7872,28,7873,7873,40,7874,7874,28,7875,7875,40,7876,7876,28,7877,7877,40,7878,7878,28,7879,7879,40,7880,7880,28,7881,7881,40,7882,7882,28,7883,7883,40,7884,7884,28,7885,7885,40,7886,7886,28,7887,7887,40,7888,7888,28,7889,7889,40,7890,7890,28,7891,7891,40,7892,7892,28,7893,7893,40,7894,7894,28,7895,7895,40,7896,7896,28,7897,7897,40,7898,7898,28,7899,7899,40,7900,7900,28,7901,7901,40,7902,7902,28,7903,7903,40,7904,7904,28,7905,7905,40,7906,7906,28,7907,7907,40,7908,7908,28,7909,7909,40,7910,7910,28,7911,7911,40,7912,7912,28,7913,7913,40,7914,7914,28,7915,7915,40,7916,7916,28,7917,7917,40,7918,7918,28,7919,7919,40,7920,7920,28,7921,7921,40,7922,7922,28,7923,7923,40,7924,7924,28,7925,7925,40,7926,7926,28,7927,7927,40,7928,7928,28,7929,7929,40,7930,7930,28,7931,7931,40,7932,7932,28,7933,7933,40,7934,7934,28,7935,7943,40,7944,7951,28,7952,7957,40,7960,7965,28,7968,7975,40,7976,7983,28,7984,7991,40,7992,7999,28,8000,8005,40,8008,8013,28,8016,8023,40,8025,8025,28,8027,8027,28,8029,8029,28,8031,8031,28,8032,8039,40,8040,8047,28,8048,8061,40,8064,8071,40,8072,8079,55,8080,8087,40,8088,8095,55,8096,8103,40,8104,8111,55,8112,8116,40,8118,8119,40,8120,8123,28,8124,8124,55,8126,8126,40,8130,8132,40,8134,8135,40,8136,8139,28,8140,8140,55,8144,8147,40,8150,8151,40,8152,8155,28,8160,8167,40,8168,8172,28,8178,8180,40,8182,8183,40,8184,8187,28,8188,8188,55,8305,8305,56,8319,8319,56,8336,8348,56,8450,8450,28,8455,8455,28,8458,8458,40,8459,8461,28,8462,8463,40,8464,8466,28,8467,8467,40,8469,8469,28,8473,8477,28,8484,8484,28,8486,8486,28,8488,8488,28,8490,8493,28,8495,8495,40,8496,8499,28,8500,8500,40,8501,8504,54,8505,8505,40,8508,8509,40,8510,8511,28,8517,8517,28,8518,8521,40,8526,8526,40,8544,8578,58,8579,8579,28,8580,8580,40,8581,8584,58,11264,11310,28,11312,11358,40,11360,11360,28,11361,11361,40,11362,11364,28,11365,11366,40,11367,11367,28,11368,11368,40,11369,11369,28,11370,11370,40,11371,11371,28,11372,11372,40,11373,11376,28,11377,11377,40,11378,11378,28,11379,11380,40,11381,11381,28,11382,11387,40,11388,11389,56,11390,11392,28,11393,11393,40,11394,11394,28,11395,11395,40,11396,11396,28,11397,11397,40,11398,11398,28,11399,11399,40,11400,11400,28,11401,11401,40,11402,11402,28,11403,11403,40,11404,11404,28,11405,11405,40,11406,11406,28,11407,11407,40,11408,11408,28,11409,11409,40,11410,11410,28,11411,11411,40,11412,11412,28,11413,11413,40,11414,11414,28,11415,11415,40,11416,11416,28,11417,11417,40,11418,11418,28,11419,11419,40,11420,11420,28,11421,11421,40,11422,11422,28,11423,11423,40,11424,11424,28,11425,11425,40,11426,11426,28,11427,11427,40,11428,11428,28,11429,11429,40,11430,11430,28,11431,11431,40,11432,11432,28,11433,11433,40,11434,11434,28,11435,11435,40,11436,11436,28,11437,11437,40,11438,11438,28,11439,11439,40,11440,11440,28,11441,11441,40,11442,11442,28,11443,11443,40,11444,11444,28,11445,11445,40,11446,11446,28,11447,11447,40,11448,11448,28,11449,11449,40,11450,11450,28,11451,11451,40,11452,11452,28,11453,11453,40,11454,11454,28,11455,11455,40,11456,11456,28,11457,11457,40,11458,11458,28,11459,11459,40,11460,11460,28,11461,11461,40,11462,11462,28,11463,11463,40,11464,11464,28,11465,11465,40,11466,11466,28,11467,11467,40,11468,11468,28,11469,11469,40,11470,11470,28,11471,11471,40,11472,11472,28,11473,11473,40,11474,11474,28,11475,11475,40,11476,11476,28,11477,11477,40,11478,11478,28,11479,11479,40,11480,11480,28,11481,11481,40,11482,11482,28,11483,11483,40,11484,11484,28,11485,11485,40,11486,11486,28,11487,11487,40,11488,11488,28,11489,11489,40,11490,11490,28,11491,11492,40,11499,11499,28,11500,11500,40,11501,11501,28,11502,11502,40,11506,11506,28,11507,11507,40,11520,11557,40,11559,11559,40,11565,11565,40,11568,11623,54,11631,11631,56,11648,11670,54,11680,11686,54,11688,11694,54,11696,11702,54,11704,11710,54,11712,11718,54,11720,11726,54,11728,11734,54,11736,11742,54,11823,11823,56,12293,12293,56,12294,12294,54,12295,12295,58,12321,12329,58,12337,12341,56,12344,12346,58,12347,12347,56,12348,12348,54,12353,12438,54,12445,12446,56,12447,12447,54,12449,12538,54,12540,12542,56,12543,12543,54,12549,12589,54,12593,12686,54,12704,12730,54,12784,12799,54,13312,13312,54,19893,19893,54,19968,19968,54,40908,40908,54,40960,40980,54,40981,40981,56,40982,42124,54,42192,42231,54,42232,42237,56,42240,42507,54,42508,42508,56,42512,42527,54,42528,42537,57,42538,42539,54,42560,42560,28,42561,42561,40,42562,42562,28,42563,42563,40,42564,42564,28,42565,42565,40,42566,42566,28,42567,42567,40,42568,42568,28,42569,42569,40,42570,42570,28,42571,42571,40,42572,42572,28,42573,42573,40,42574,42574,28,42575,42575,40,42576,42576,28,42577,42577,40,42578,42578,28,42579,42579,40,42580,42580,28,42581,42581,40,42582,42582,28,42583,42583,40,42584,42584,28,42585,42585,40,42586,42586,28,42587,42587,40,42588,42588,28,42589,42589,40,42590,42590,28,42591,42591,40,42592,42592,28,42593,42593,40,42594,42594,28,42595,42595,40,42596,42596,28,42597,42597,40,42598,42598,28,42599,42599,40,42600,42600,28,42601,42601,40,42602,42602,28,42603,42603,40,42604,42604,28,42605,42605,40,42606,42606,54,42623,42623,56,42624,42624,28,42625,42625,40,42626,42626,28,42627,42627,40,42628,42628,28,42629,42629,40,42630,42630,28,42631,42631,40,42632,42632,28,42633,42633,40,42634,42634,28,42635,42635,40,42636,42636,28,42637,42637,40,42638,42638,28,42639,42639,40,42640,42640,28,42641,42641,40,42642,42642,28,42643,42643,40,42644,42644,28,42645,42645,40,42646,42646,28,42647,42647,40,42656,42725,54,42726,42735,58,42775,42783,56,42786,42786,28,42787,42787,40,42788,42788,28,42789,42789,40,42790,42790,28,42791,42791,40,42792,42792,28,42793,42793,40,42794,42794,28,42795,42795,40,42796,42796,28,42797,42797,40,42798,42798,28,42799,42801,40,42802,42802,28,42803,42803,40,42804,42804,28,42805,42805,40,42806,42806,28,42807,42807,40,42808,42808,28,42809,42809,40,42810,42810,28,42811,42811,40,42812,42812,28,42813,42813,40,42814,42814,28,42815,42815,40,42816,42816,28,42817,42817,40,42818,42818,28,42819,42819,40,42820,42820,28,42821,42821,40,42822,42822,28,42823,42823,40,42824,42824,28,42825,42825,40,42826,42826,28,42827,42827,40,42828,42828,28,42829,42829,40,42830,42830,28,42831,42831,40,42832,42832,28,42833,42833,40,42834,42834,28,42835,42835,40,42836,42836,28,42837,42837,40,42838,42838,28,42839,42839,40,42840,42840,28,42841,42841,40,42842,42842,28,42843,42843,40,42844,42844,28,42845,42845,40,42846,42846,28,42847,42847,40,42848,42848,28,42849,42849,40,42850,42850,28,42851,42851,40,42852,42852,28,42853,42853,40,42854,42854,28,42855,42855,40,42856,42856,28,42857,42857,40,42858,42858,28,42859,42859,40,42860,42860,28,42861,42861,40,42862,42862,28,42863,42863,40,42864,42864,56,42865,42872,40,42873,42873,28,42874,42874,40,42875,42875,28,42876,42876,40,42877,42878,28,42879,42879,40,42880,42880,28,42881,42881,40,42882,42882,28,42883,42883,40,42884,42884,28,42885,42885,40,42886,42886,28,42887,42887,40,42888,42888,56,42891,42891,28,42892,42892,40,42893,42893,28,42894,42894,40,42896,42896,28,42897,42897,40,42898,42898,28,42899,42899,40,42912,42912,28,42913,42913,40,42914,42914,28,42915,42915,40,42916,42916,28,42917,42917,40,42918,42918,28,42919,42919,40,42920,42920,28,42921,42921,40,42922,42922,28,43000,43001,56,43002,43002,40,43003,43009,54,43011,43013,54,43015,43018,54,43020,43042,54,43072,43123,54,43138,43187,54,43216,43225,57,43250,43255,54,43259,43259,54,43264,43273,57,43274,43301,54,43312,43334,54,43360,43388,54,43396,43442,54,43471,43471,56,43472,43481,57,43520,43560,54,43584,43586,54,43588,43595,54,43600,43609,57,43616,43631,54,43632,43632,56,43633,43638,54,43642,43642,54,43648,43695,54,43697,43697,54,43701,43702,54,43705,43709,54,43712,43712,54,43714,43714,54,43739,43740,54,43741,43741,56,43744,43754,54,43762,43762,54,43763,43764,56,43777,43782,54,43785,43790,54,43793,43798,54,43808,43814,54,43816,43822,54,43968,44002,54,44016,44025,57,44032,44032,54,55203,55203,54,55216,55238,54,55243,55291,54,63744,64109,54,64112,64217,54,64256,64262,40,64275,64279,40,64285,64285,54,64287,64296,54,64298,64310,54,64312,64316,54,64318,64318,54,64320,64321,54,64323,64324,54,64326,64433,54,64467,64829,54,64848,64911,54,64914,64967,54,65008,65019,54,65136,65140,54,65142,65276,54,65296,65305,57,65313,65338,28,65345,65370,40,65382,65391,54,65392,65392,56,65393,65437,54,65438,65439,56,65440,65470,54,65474,65479,54,65482,65487,54,65490,65495,54,65498,65500,54,0,371,170,170,66,181,181,66,186,186,66,192,214,66,216,246,66,248,705,66,710,721,66,736,740,66,748,748,66,750,750,66,880,884,66,886,887,66,890,893,66,902,902,66,904,906,66,908,908,66,910,929,66,931,1013,66,1015,1153,66,1162,1319,66,1329,1366,66,1369,1369,66,1377,1415,66,1488,1514,66,1520,1522,66,1568,1610,66,1646,1647,66,1649,1747,66,1749,1749,66,1765,1766,66,1774,1775,66,1786,1788,66,1791,1791,66,1808,1808,66,1810,1839,66,1869,1957,66,1969,1969,66,1994,2026,66,2036,2037,66,2042,2042,66,2048,2069,66,2074,2074,66,2084,2084,66,2088,2088,66,2112,2136,66,2208,2208,66,2210,2220,66,2308,2361,66,2365,2365,66,2384,2384,66,2392,2401,66,2417,2423,66,2425,2431,66,2437,2444,66,2447,2448,66,2451,2472,66,2474,2480,66,2482,2482,66,2486,2489,66,2493,2493,66,2510,2510,66,2524,2525,66,2527,2529,66,2544,2545,66,2565,2570,66,2575,2576,66,2579,2600,66,2602,2608,66,2610,2611,66,2613,2614,66,2616,2617,66,2649,2652,66,2654,2654,66,2674,2676,66,2693,2701,66,2703,2705,66,2707,2728,66,2730,2736,66,2738,2739,66,2741,2745,66,2749,2749,66,2768,2768,66,2784,2785,66,2821,2828,66,2831,2832,66,2835,2856,66,2858,2864,66,2866,2867,66,2869,2873,66,2877,2877,66,2908,2909,66,2911,2913,66,2929,2929,66,2947,2947,66,2949,2954,66,2958,2960,66,2962,2965,66,2969,2970,66,2972,2972,66,2974,2975,66,2979,2980,66,2984,2986,66,2990,3001,66,3024,3024,66,3077,3084,66,3086,3088,66,3090,3112,66,3114,3123,66,3125,3129,66,3133,3133,66,3160,3161,66,3168,3169,66,3205,3212,66,3214,3216,66,3218,3240,66,3242,3251,66,3253,3257,66,3261,3261,66,3294,3294,66,3296,3297,66,3313,3314,66,3333,3340,66,3342,3344,66,3346,3386,66,3389,3389,66,3406,3406,66,3424,3425,66,3450,3455,66,3461,3478,66,3482,3505,66,3507,3515,66,3517,3517,66,3520,3526,66,3585,3632,66,3634,3635,66,3648,3654,66,3713,3714,66,3716,3716,66,3719,3720,66,3722,3722,66,3725,3725,66,3732,3735,66,3737,3743,66,3745,3747,66,3749,3749,66,3751,3751,66,3754,3755,66,3757,3760,66,3762,3763,66,3773,3773,66,3776,3780,66,3782,3782,66,3804,3807,66,3840,3840,66,3904,3911,66,3913,3948,66,3976,3980,66,4096,4138,66,4159,4159,66,4176,4181,66,4186,4189,66,4193,4193,66,4197,4198,66,4206,4208,66,4213,4225,66,4238,4238,66,4256,4293,66,4295,4295,66,4301,4301,66,4304,4346,66,4348,4680,66,4682,4685,66,4688,4694,66,4696,4696,66,4698,4701,66,4704,4744,66,4746,4749,66,4752,4784,66,4786,4789,66,4792,4798,66,4800,4800,66,4802,4805,66,4808,4822,66,4824,4880,66,4882,4885,66,4888,4954,66,4992,5007,66,5024,5108,66,5121,5740,66,5743,5759,66,5761,5786,66,5792,5866,66,5888,5900,66,5902,5905,66,5920,5937,66,5952,5969,66,5984,5996,66,5998,6000,66,6016,6067,66,6103,6103,66,6108,6108,66,6176,6263,66,6272,6312,66,6314,6314,66,6320,6389,66,6400,6428,66,6480,6509,66,6512,6516,66,6528,6571,66,6593,6599,66,6656,6678,66,6688,6740,66,6823,6823,66,6917,6963,66,6981,6987,66,7043,7072,66,7086,7087,66,7098,7141,66,7168,7203,66,7245,7247,66,7258,7293,66,7401,7404,66,7406,7409,66,7413,7414,66,7424,7615,66,7680,7957,66,7960,7965,66,7968,8005,66,8008,8013,66,8016,8023,66,8025,8025,66,8027,8027,66,8029,8029,66,8031,8061,66,8064,8116,66,8118,8124,66,8126,8126,66,8130,8132,66,8134,8140,66,8144,8147,66,8150,8155,66,8160,8172,66,8178,8180,66,8182,8188,66,8305,8305,66,8319,8319,66,8336,8348,66,8450,8450,66,8455,8455,66,8458,8467,66,8469,8469,66,8473,8477,66,8484,8484,66,8486,8486,66,8488,8488,66,8490,8493,66,8495,8505,66,8508,8511,66,8517,8521,66,8526,8526,66,8579,8580,66,11264,11310,66,11312,11358,66,11360,11492,66,11499,11502,66,11506,11507,66,11520,11557,66,11559,11559,66,11565,11565,66,11568,11623,66,11631,11631,66,11648,11670,66,11680,11686,66,11688,11694,66,11696,11702,66,11704,11710,66,11712,11718,66,11720,11726,66,11728,11734,66,11736,11742,66,11823,11823,66,12293,12294,66,12337,12341,66,12347,12348,66,12353,12438,66,12445,12447,66,12449,12538,66,12540,12543,66,12549,12589,66,12593,12686,66,12704,12730,66,12784,12799,66,13312,13312,66,19893,19893,66,19968,19968,66,40908,40908,66,40960,42124,66,42192,42237,66,42240,42508,66,42512,42527,66,42538,42539,66,42560,42606,66,42623,42647,66,42656,42725,66,42775,42783,66,42786,42888,66,42891,42894,66,42896,42899,66,42912,42922,66,43000,43009,66,43011,43013,66,43015,43018,66,43020,43042,66,43072,43123,66,43138,43187,66,43250,43255,66,43259,43259,66,43274,43301,66,43312,43334,66,43360,43388,66,43396,43442,66,43471,43471,66,43520,43560,66,43584,43586,66,43588,43595,66,43616,43638,66,43642,43642,66,43648,43695,66,43697,43697,66,43701,43702,66,43705,43709,66,43712,43712,66,43714,43714,66,43739,43741,66,43744,43754,66,43762,43764,66,43777,43782,66,43785,43790,66,43793,43798,66,43808,43814,66,43816,43822,66,43968,44002,66,44032,44032,66,55203,55203,66,55216,55238,66,55243,55291,66,63744,64109,66,64112,64217,66,64256,64262,66,64275,64279,66,64285,64285,66,64287,64296,66,64298,64310,66,64312,64316,66,64318,64318,66,64320,64321,66,64323,64324,66,64326,64433,66,64467,64829,66,64848,64911,66,64914,64967,66,65008,65019,66,65136,65140,66,65142,65276,66,65313,65338,66,65345,65370,66,65382,65470,66,65474,65479,66,65482,65487,66,65490,65495,66,65498,65500,66,1,128,1114111,87,391,170,170,31,181,181,31,186,186,31,192,214,31,216,246,31,248,705,31,710,721,31,736,740,31,748,748,31,750,750,31,880,884,31,886,887,31,890,893,31,902,902,31,904,906,31,908,908,31,910,929,31,931,1013,31,1015,1153,31,1162,1319,31,1329,1366,31,1369,1369,31,1377,1415,31,1488,1514,31,1520,1522,31,1568,1610,31,1632,1641,31,1646,1647,31,1649,1747,31,1749,1749,31,1765,1766,31,1774,1788,31,1791,1791,31,1808,1808,31,1810,1839,31,1869,1957,31,1969,1969,31,1984,2026,31,2036,2037,31,2042,2042,31,2048,2069,31,2074,2074,31,2084,2084,31,2088,2088,31,2112,2136,31,2208,2208,31,2210,2220,31,2308,2361,31,2365,2365,31,2384,2384,31,2392,2401,31,2406,2415,31,2417,2423,31,2425,2431,31,2437,2444,31,2447,2448,31,2451,2472,31,2474,2480,31,2482,2482,31,2486,2489,31,2493,2493,31,2510,2510,31,2524,2525,31,2527,2529,31,2534,2545,31,2565,2570,31,2575,2576,31,2579,2600,31,2602,2608,31,2610,2611,31,2613,2614,31,2616,2617,31,2649,2652,31,2654,2654,31,2662,2671,31,2674,2676,31,2693,2701,31,2703,2705,31,2707,2728,31,2730,2736,31,2738,2739,31,2741,2745,31,2749,2749,31,2768,2768,31,2784,2785,31,2790,2799,31,2821,2828,31,2831,2832,31,2835,2856,31,2858,2864,31,2866,2867,31,2869,2873,31,2877,2877,31,2908,2909,31,2911,2913,31,2918,2927,31,2929,2929,31,2947,2947,31,2949,2954,31,2958,2960,31,2962,2965,31,2969,2970,31,2972,2972,31,2974,2975,31,2979,2980,31,2984,2986,31,2990,3001,31,3024,3024,31,3046,3055,31,3077,3084,31,3086,3088,31,3090,3112,31,3114,3123,31,3125,3129,31,3133,3133,31,3160,3161,31,3168,3169,31,3174,3183,31,3205,3212,31,3214,3216,31,3218,3240,31,3242,3251,31,3253,3257,31,3261,3261,31,3294,3294,31,3296,3297,31,3302,3311,31,3313,3314,31,3333,3340,31,3342,3344,31,3346,3386,31,3389,3389,31,3406,3406,31,3424,3425,31,3430,3439,31,3450,3455,31,3461,3478,31,3482,3505,31,3507,3515,31,3517,3517,31,3520,3526,31,3585,3632,31,3634,3635,31,3648,3654,31,3664,3673,31,3713,3714,31,3716,3716,31,3719,3720,31,3722,3722,31,3725,3725,31,3732,3735,31,3737,3743,31,3745,3747,31,3749,3749,31,3751,3751,31,3754,3755,31,3757,3760,31,3762,3763,31,3773,3773,31,3776,3780,31,3782,3782,31,3792,3801,31,3804,3807,31,3840,3840,31,3872,3881,31,3904,3911,31,3913,3948,31,3976,3980,31,4096,4138,31,4159,4169,31,4176,4181,31,4186,4189,31,4193,4193,31,4197,4198,31,4206,4208,31,4213,4225,31,4238,4238,31,4240,4249,31,4256,4293,31,4295,4295,31,4301,4301,31,4304,4346,31,4348,4680,31,4682,4685,31,4688,4694,31,4696,4696,31,4698,4701,31,4704,4744,31,4746,4749,31,4752,4784,31,4786,4789,31,4792,4798,31,4800,4800,31,4802,4805,31,4808,4822,31,4824,4880,31,4882,4885,31,4888,4954,31,4992,5007,31,5024,5108,31,5121,5740,31,5743,5759,31,5761,5786,31,5792,5866,31,5888,5900,31,5902,5905,31,5920,5937,31,5952,5969,31,5984,5996,31,5998,6000,31,6016,6067,31,6103,6103,31,6108,6108,31,6112,6121,31,6160,6169,31,6176,6263,31,6272,6312,31,6314,6314,31,6320,6389,31,6400,6428,31,6470,6509,31,6512,6516,31,6528,6571,31,6593,6599,31,6608,6617,31,6656,6678,31,6688,6740,31,6784,6793,31,6800,6809,31,6823,6823,31,6917,6963,31,6981,6987,31,6992,7001,31,7043,7072,31,7086,7141,31,7168,7203,31,7232,7241,31,7245,7293,31,7401,7404,31,7406,7409,31,7413,7414,31,7424,7615,31,7680,7957,31,7960,7965,31,7968,8005,31,8008,8013,31,8016,8023,31,8025,8025,31,8027,8027,31,8029,8029,31,8031,8061,31,8064,8116,31,8118,8124,31,8126,8126,31,8130,8132,31,8134,8140,31,8144,8147,31,8150,8155,31,8160,8172,31,8178,8180,31,8182,8188,31,8305,8305,31,8319,8319,31,8336,8348,31,8450,8450,31,8455,8455,31,8458,8467,31,8469,8469,31,8473,8477,31,8484,8484,31,8486,8486,31,8488,8488,31,8490,8493,31,8495,8505,31,8508,8511,31,8517,8521,31,8526,8526,31,8579,8580,31,11264,11310,31,11312,11358,31,11360,11492,31,11499,11502,31,11506,11507,31,11520,11557,31,11559,11559,31,11565,11565,31,11568,11623,31,11631,11631,31,11648,11670,31,11680,11686,31,11688,11694,31,11696,11702,31,11704,11710,31,11712,11718,31,11720,11726,31,11728,11734,31,11736,11742,31,11823,11823,31,12293,12294,31,12337,12341,31,12347,12348,31,12353,12438,31,12445,12447,31,12449,12538,31,12540,12543,31,12549,12589,31,12593,12686,31,12704,12730,31,12784,12799,31,13312,13312,31,19893,19893,31,19968,19968,31,40908,40908,31,40960,42124,31,42192,42237,31,42240,42508,31,42512,42539,31,42560,42606,31,42623,42647,31,42656,42725,31,42775,42783,31,42786,42888,31,42891,42894,31,42896,42899,31,42912,42922,31,43000,43009,31,43011,43013,31,43015,43018,31,43020,43042,31,43072,43123,31,43138,43187,31,43216,43225,31,43250,43255,31,43259,43259,31,43264,43301,31,43312,43334,31,43360,43388,31,43396,43442,31,43471,43481,31,43520,43560,31,43584,43586,31,43588,43595,31,43600,43609,31,43616,43638,31,43642,43642,31,43648,43695,31,43697,43697,31,43701,43702,31,43705,43709,31,43712,43712,31,43714,43714,31,43739,43741,31,43744,43754,31,43762,43764,31,43777,43782,31,43785,43790,31,43793,43798,31,43808,43814,31,43816,43822,31,43968,44002,31,44016,44025,31,44032,44032,31,55203,55203,31,55216,55238,31,55243,55291,31,63744,64109,31,64112,64217,31,64256,64262,31,64275,64279,31,64285,64285,31,64287,64296,31,64298,64310,31,64312,64316,31,64318,64318,31,64320,64321,31,64323,64324,31,64326,64433,31,64467,64829,31,64848,64911,31,64914,64967,31,65008,65019,31,65136,65140,31,65142,65276,31,65296,65305,31,65313,65338,31,65345,65370,31,65382,65470,31,65474,65479,31,65482,65487,31,65490,65495,31,65498,65500,31,1,128,1114111,122,1,128,1114111,65,391,170,170,66,181,181,66,186,186,66,192,214,66,216,246,66,248,705,66,710,721,66,736,740,66,748,748,66,750,750,66,880,884,66,886,887,66,890,893,66,902,902,66,904,906,66,908,908,66,910,929,66,931,1013,66,1015,1153,66,1162,1319,66,1329,1366,66,1369,1369,66,1377,1415,66,1488,1514,66,1520,1522,66,1568,1610,66,1632,1641,66,1646,1647,66,1649,1747,66,1749,1749,66,1765,1766,66,1774,1788,66,1791,1791,66,1808,1808,66,1810,1839,66,1869,1957,66,1969,1969,66,1984,2026,66,2036,2037,66,2042,2042,66,2048,2069,66,2074,2074,66,2084,2084,66,2088,2088,66,2112,2136,66,2208,2208,66,2210,2220,66,2308,2361,66,2365,2365,66,2384,2384,66,2392,2401,66,2406,2415,66,2417,2423,66,2425,2431,66,2437,2444,66,2447,2448,66,2451,2472,66,2474,2480,66,2482,2482,66,2486,2489,66,2493,2493,66,2510,2510,66,2524,2525,66,2527,2529,66,2534,2545,66,2565,2570,66,2575,2576,66,2579,2600,66,2602,2608,66,2610,2611,66,2613,2614,66,2616,2617,66,2649,2652,66,2654,2654,66,2662,2671,66,2674,2676,66,2693,2701,66,2703,2705,66,2707,2728,66,2730,2736,66,2738,2739,66,2741,2745,66,2749,2749,66,2768,2768,66,2784,2785,66,2790,2799,66,2821,2828,66,2831,2832,66,2835,2856,66,2858,2864,66,2866,2867,66,2869,2873,66,2877,2877,66,2908,2909,66,2911,2913,66,2918,2927,66,2929,2929,66,2947,2947,66,2949,2954,66,2958,2960,66,2962,2965,66,2969,2970,66,2972,2972,66,2974,2975,66,2979,2980,66,2984,2986,66,2990,3001,66,3024,3024,66,3046,3055,66,3077,3084,66,3086,3088,66,3090,3112,66,3114,3123,66,3125,3129,66,3133,3133,66,3160,3161,66,3168,3169,66,3174,3183,66,3205,3212,66,3214,3216,66,3218,3240,66,3242,3251,66,3253,3257,66,3261,3261,66,3294,3294,66,3296,3297,66,3302,3311,66,3313,3314,66,3333,3340,66,3342,3344,66,3346,3386,66,3389,3389,66,3406,3406,66,3424,3425,66,3430,3439,66,3450,3455,66,3461,3478,66,3482,3505,66,3507,3515,66,3517,3517,66,3520,3526,66,3585,3632,66,3634,3635,66,3648,3654,66,3664,3673,66,3713,3714,66,3716,3716,66,3719,3720,66,3722,3722,66,3725,3725,66,3732,3735,66,3737,3743,66,3745,3747,66,3749,3749,66,3751,3751,66,3754,3755,66,3757,3760,66,3762,3763,66,3773,3773,66,3776,3780,66,3782,3782,66,3792,3801,66,3804,3807,66,3840,3840,66,3872,3881,66,3904,3911,66,3913,3948,66,3976,3980,66,4096,4138,66,4159,4169,66,4176,4181,66,4186,4189,66,4193,4193,66,4197,4198,66,4206,4208,66,4213,4225,66,4238,4238,66,4240,4249,66,4256,4293,66,4295,4295,66,4301,4301,66,4304,4346,66,4348,4680,66,4682,4685,66,4688,4694,66,4696,4696,66,4698,4701,66,4704,4744,66,4746,4749,66,4752,4784,66,4786,4789,66,4792,4798,66,4800,4800,66,4802,4805,66,4808,4822,66,4824,4880,66,4882,4885,66,4888,4954,66,4992,5007,66,5024,5108,66,5121,5740,66,5743,5759,66,5761,5786,66,5792,5866,66,5888,5900,66,5902,5905,66,5920,5937,66,5952,5969,66,5984,5996,66,5998,6000,66,6016,6067,66,6103,6103,66,6108,6108,66,6112,6121,66,6160,6169,66,6176,6263,66,6272,6312,66,6314,6314,66,6320,6389,66,6400,6428,66,6470,6509,66,6512,6516,66,6528,6571,66,6593,6599,66,6608,6617,66,6656,6678,66,6688,6740,66,6784,6793,66,6800,6809,66,6823,6823,66,6917,6963,66,6981,6987,66,6992,7001,66,7043,7072,66,7086,7141,66,7168,7203,66,7232,7241,66,7245,7293,66,7401,7404,66,7406,7409,66,7413,7414,66,7424,7615,66,7680,7957,66,7960,7965,66,7968,8005,66,8008,8013,66,8016,8023,66,8025,8025,66,8027,8027,66,8029,8029,66,8031,8061,66,8064,8116,66,8118,8124,66,8126,8126,66,8130,8132,66,8134,8140,66,8144,8147,66,8150,8155,66,8160,8172,66,8178,8180,66,8182,8188,66,8305,8305,66,8319,8319,66,8336,8348,66,8450,8450,66,8455,8455,66,8458,8467,66,8469,8469,66,8473,8477,66,8484,8484,66,8486,8486,66,8488,8488,66,8490,8493,66,8495,8505,66,8508,8511,66,8517,8521,66,8526,8526,66,8579,8580,66,11264,11310,66,11312,11358,66,11360,11492,66,11499,11502,66,11506,11507,66,11520,11557,66,11559,11559,66,11565,11565,66,11568,11623,66,11631,11631,66,11648,11670,66,11680,11686,66,11688,11694,66,11696,11702,66,11704,11710,66,11712,11718,66,11720,11726,66,11728,11734,66,11736,11742,66,11823,11823,66,12293,12294,66,12337,12341,66,12347,12348,66,12353,12438,66,12445,12447,66,12449,12538,66,12540,12543,66,12549,12589,66,12593,12686,66,12704,12730,66,12784,12799,66,13312,13312,66,19893,19893,66,19968,19968,66,40908,40908,66,40960,42124,66,42192,42237,66,42240,42508,66,42512,42539,66,42560,42606,66,42623,42647,66,42656,42725,66,42775,42783,66,42786,42888,66,42891,42894,66,42896,42899,66,42912,42922,66,43000,43009,66,43011,43013,66,43015,43018,66,43020,43042,66,43072,43123,66,43138,43187,66,43216,43225,66,43250,43255,66,43259,43259,66,43264,43301,66,43312,43334,66,43360,43388,66,43396,43442,66,43471,43481,66,43520,43560,66,43584,43586,66,43588,43595,66,43600,43609,66,43616,43638,66,43642,43642,66,43648,43695,66,43697,43697,66,43701,43702,66,43705,43709,66,43712,43712,66,43714,43714,66,43739,43741,66,43744,43754,66,43762,43764,66,43777,43782,66,43785,43790,66,43793,43798,66,43808,43814,66,43816,43822,66,43968,44002,66,44016,44025,66,44032,44032,66,55203,55203,66,55216,55238,66,55243,55291,66,63744,64109,66,64112,64217,66,64256,64262,66,64275,64279,66,64285,64285,66,64287,64296,66,64298,64310,66,64312,64316,66,64318,64318,66,64320,64321,66,64323,64324,66,64326,64433,66,64467,64829,66,64848,64911,66,64914,64967,66,65008,65019,66,65136,65140,66,65142,65276,66,65296,65305,66,65313,65338,66,65345,65370,66,65382,65470,66,65474,65479,66,65482,65487,66,65490,65495,66,65498,65500,66,1,128,1114111,178,1,128,1114111,97,1,128,1114111,98,1,128,1114111,172,1,128,1114111,173,1,128,1114111,223,1,128,1114111,224,1,128,1114111,225,1,128,1114111,226,1,128,1114111,287,1,128,1114111,288,1,128,1114111,452,1,128,1114111,410,1,128,1114111,411,1,128,1114111,412,1,128,1114111,413,1,128,1114111,543,1,128,1114111,455,1,128,1114111,456,371,170,170,586,181,181,586,186,186,586,192,214,586,216,246,586,248,705,586,710,721,586,736,740,586,748,748,586,750,750,586,880,884,586,886,887,586,890,893,586,902,902,586,904,906,586,908,908,586,910,929,586,931,1013,586,1015,1153,586,1162,1319,586,1329,1366,586,1369,1369,586,1377,1415,586,1488,1514,586,1520,1522,586,1568,1610,586,1646,1647,586,1649,1747,586,1749,1749,586,1765,1766,586,1774,1775,586,1786,1788,586,1791,1791,586,1808,1808,586,1810,1839,586,1869,1957,586,1969,1969,586,1994,2026,586,2036,2037,586,2042,2042,586,2048,2069,586,2074,2074,586,2084,2084,586,2088,2088,586,2112,2136,586,2208,2208,586,2210,2220,586,2308,2361,586,2365,2365,586,2384,2384,586,2392,2401,586,2417,2423,586,2425,2431,586,2437,2444,586,2447,2448,586,2451,2472,586,2474,2480,586,2482,2482,586,2486,2489,586,2493,2493,586,2510,2510,586,2524,2525,586,2527,2529,586,2544,2545,586,2565,2570,586,2575,2576,586,2579,2600,586,2602,2608,586,2610,2611,586,2613,2614,586,2616,2617,586,2649,2652,586,2654,2654,586,2674,2676,586,2693,2701,586,2703,2705,586,2707,2728,586,2730,2736,586,2738,2739,586,2741,2745,586,2749,2749,586,2768,2768,586,2784,2785,586,2821,2828,586,2831,2832,586,2835,2856,586,2858,2864,586,2866,2867,586,2869,2873,586,2877,2877,586,2908,2909,586,2911,2913,586,2929,2929,586,2947,2947,586,2949,2954,586,2958,2960,586,2962,2965,586,2969,2970,586,2972,2972,586,2974,2975,586,2979,2980,586,2984,2986,586,2990,3001,586,3024,3024,586,3077,3084,586,3086,3088,586,3090,3112,586,3114,3123,586,3125,3129,586,3133,3133,586,3160,3161,586,3168,3169,586,3205,3212,586,3214,3216,586,3218,3240,586,3242,3251,586,3253,3257,586,3261,3261,586,3294,3294,586,3296,3297,586,3313,3314,586,3333,3340,586,3342,3344,586,3346,3386,586,3389,3389,586,3406,3406,586,3424,3425,586,3450,3455,586,3461,3478,586,3482,3505,586,3507,3515,586,3517,3517,586,3520,3526,586,3585,3632,586,3634,3635,586,3648,3654,586,3713,3714,586,3716,3716,586,3719,3720,586,3722,3722,586,3725,3725,586,3732,3735,586,3737,3743,586,3745,3747,586,3749,3749,586,3751,3751,586,3754,3755,586,3757,3760,586,3762,3763,586,3773,3773,586,3776,3780,586,3782,3782,586,3804,3807,586,3840,3840,586,3904,3911,586,3913,3948,586,3976,3980,586,4096,4138,586,4159,4159,586,4176,4181,586,4186,4189,586,4193,4193,586,4197,4198,586,4206,4208,586,4213,4225,586,4238,4238,586,4256,4293,586,4295,4295,586,4301,4301,586,4304,4346,586,4348,4680,586,4682,4685,586,4688,4694,586,4696,4696,586,4698,4701,586,4704,4744,586,4746,4749,586,4752,4784,586,4786,4789,586,4792,4798,586,4800,4800,586,4802,4805,586,4808,4822,586,4824,4880,586,4882,4885,586,4888,4954,586,4992,5007,586,5024,5108,586,5121,5740,586,5743,5759,586,5761,5786,586,5792,5866,586,5888,5900,586,5902,5905,586,5920,5937,586,5952,5969,586,5984,5996,586,5998,6000,586,6016,6067,586,6103,6103,586,6108,6108,586,6176,6263,586,6272,6312,586,6314,6314,586,6320,6389,586,6400,6428,586,6480,6509,586,6512,6516,586,6528,6571,586,6593,6599,586,6656,6678,586,6688,6740,586,6823,6823,586,6917,6963,586,6981,6987,586,7043,7072,586,7086,7087,586,7098,7141,586,7168,7203,586,7245,7247,586,7258,7293,586,7401,7404,586,7406,7409,586,7413,7414,586,7424,7615,586,7680,7957,586,7960,7965,586,7968,8005,586,8008,8013,586,8016,8023,586,8025,8025,586,8027,8027,586,8029,8029,586,8031,8061,586,8064,8116,586,8118,8124,586,8126,8126,586,8130,8132,586,8134,8140,586,8144,8147,586,8150,8155,586,8160,8172,586,8178,8180,586,8182,8188,586,8305,8305,586,8319,8319,586,8336,8348,586,8450,8450,586,8455,8455,586,8458,8467,586,8469,8469,586,8473,8477,586,8484,8484,586,8486,8486,586,8488,8488,586,8490,8493,586,8495,8505,586,8508,8511,586,8517,8521,586,8526,8526,586,8579,8580,586,11264,11310,586,11312,11358,586,11360,11492,586,11499,11502,586,11506,11507,586,11520,11557,586,11559,11559,586,11565,11565,586,11568,11623,586,11631,11631,586,11648,11670,586,11680,11686,586,11688,11694,586,11696,11702,586,11704,11710,586,11712,11718,586,11720,11726,586,11728,11734,586,11736,11742,586,11823,11823,586,12293,12294,586,12337,12341,586,12347,12348,586,12353,12438,586,12445,12447,586,12449,12538,586,12540,12543,586,12549,12589,586,12593,12686,586,12704,12730,586,12784,12799,586,13312,13312,586,19893,19893,586,19968,19968,586,40908,40908,586,40960,42124,586,42192,42237,586,42240,42508,586,42512,42527,586,42538,42539,586,42560,42606,586,42623,42647,586,42656,42725,586,42775,42783,586,42786,42888,586,42891,42894,586,42896,42899,586,42912,42922,586,43000,43009,586,43011,43013,586,43015,43018,586,43020,43042,586,43072,43123,586,43138,43187,586,43250,43255,586,43259,43259,586,43274,43301,586,43312,43334,586,43360,43388,586,43396,43442,586,43471,43471,586,43520,43560,586,43584,43586,586,43588,43595,586,43616,43638,586,43642,43642,586,43648,43695,586,43697,43697,586,43701,43702,586,43705,43709,586,43712,43712,586,43714,43714,586,43739,43741,586,43744,43754,586,43762,43764,586,43777,43782,586,43785,43790,586,43793,43798,586,43808,43814,586,43816,43822,586,43968,44002,586,44032,44032,586,55203,55203,586,55216,55238,586,55243,55291,586,63744,64109,586,64112,64217,586,64256,64262,586,64275,64279,586,64285,64285,586,64287,64296,586,64298,64310,586,64312,64316,586,64318,64318,586,64320,64321,586,64323,64324,586,64326,64433,586,64467,64829,586,64848,64911,586,64914,64967,586,65008,65019,586,65136,65140,586,65142,65276,586,65313,65338,586,65345,65370,586,65382,65470,586,65474,65479,586,65482,65487,586,65490,65495,586,65498,65500,586,371,170,170,624,181,181,624,186,186,624,192,214,624,216,246,624,248,705,624,710,721,624,736,740,624,748,748,624,750,750,624,880,884,624,886,887,624,890,893,624,902,902,624,904,906,624,908,908,624,910,929,624,931,1013,624,1015,1153,624,1162,1319,624,1329,1366,624,1369,1369,624,1377,1415,624,1488,1514,624,1520,1522,624,1568,1610,624,1646,1647,624,1649,1747,624,1749,1749,624,1765,1766,624,1774,1775,624,1786,1788,624,1791,1791,624,1808,1808,624,1810,1839,624,1869,1957,624,1969,1969,624,1994,2026,624,2036,2037,624,2042,2042,624,2048,2069,624,2074,2074,624,2084,2084,624,2088,2088,624,2112,2136,624,2208,2208,624,2210,2220,624,2308,2361,624,2365,2365,624,2384,2384,624,2392,2401,624,2417,2423,624,2425,2431,624,2437,2444,624,2447,2448,624,2451,2472,624,2474,2480,624,2482,2482,624,2486,2489,624,2493,2493,624,2510,2510,624,2524,2525,624,2527,2529,624,2544,2545,624,2565,2570,624,2575,2576,624,2579,2600,624,2602,2608,624,2610,2611,624,2613,2614,624,2616,2617,624,2649,2652,624,2654,2654,624,2674,2676,624,2693,2701,624,2703,2705,624,2707,2728,624,2730,2736,624,2738,2739,624,2741,2745,624,2749,2749,624,2768,2768,624,2784,2785,624,2821,2828,624,2831,2832,624,2835,2856,624,2858,2864,624,2866,2867,624,2869,2873,624,2877,2877,624,2908,2909,624,2911,2913,624,2929,2929,624,2947,2947,624,2949,2954,624,2958,2960,624,2962,2965,624,2969,2970,624,2972,2972,624,2974,2975,624,2979,2980,624,2984,2986,624,2990,3001,624,3024,3024,624,3077,3084,624,3086,3088,624,3090,3112,624,3114,3123,624,3125,3129,624,3133,3133,624,3160,3161,624,3168,3169,624,3205,3212,624,3214,3216,624,3218,3240,624,3242,3251,624,3253,3257,624,3261,3261,624,3294,3294,624,3296,3297,624,3313,3314,624,3333,3340,624,3342,3344,624,3346,3386,624,3389,3389,624,3406,3406,624,3424,3425,624,3450,3455,624,3461,3478,624,3482,3505,624,3507,3515,624,3517,3517,624,3520,3526,624,3585,3632,624,3634,3635,624,3648,3654,624,3713,3714,624,3716,3716,624,3719,3720,624,3722,3722,624,3725,3725,624,3732,3735,624,3737,3743,624,3745,3747,624,3749,3749,624,3751,3751,624,3754,3755,624,3757,3760,624,3762,3763,624,3773,3773,624,3776,3780,624,3782,3782,624,3804,3807,624,3840,3840,624,3904,3911,624,3913,3948,624,3976,3980,624,4096,4138,624,4159,4159,624,4176,4181,624,4186,4189,624,4193,4193,624,4197,4198,624,4206,4208,624,4213,4225,624,4238,4238,624,4256,4293,624,4295,4295,624,4301,4301,624,4304,4346,624,4348,4680,624,4682,4685,624,4688,4694,624,4696,4696,624,4698,4701,624,4704,4744,624,4746,4749,624,4752,4784,624,4786,4789,624,4792,4798,624,4800,4800,624,4802,4805,624,4808,4822,624,4824,4880,624,4882,4885,624,4888,4954,624,4992,5007,624,5024,5108,624,5121,5740,624,5743,5759,624,5761,5786,624,5792,5866,624,5888,5900,624,5902,5905,624,5920,5937,624,5952,5969,624,5984,5996,624,5998,6000,624,6016,6067,624,6103,6103,624,6108,6108,624,6176,6263,624,6272,6312,624,6314,6314,624,6320,6389,624,6400,6428,624,6480,6509,624,6512,6516,624,6528,6571,624,6593,6599,624,6656,6678,624,6688,6740,624,6823,6823,624,6917,6963,624,6981,6987,624,7043,7072,624,7086,7087,624,7098,7141,624,7168,7203,624,7245,7247,624,7258,7293,624,7401,7404,624,7406,7409,624,7413,7414,624,7424,7615,624,7680,7957,624,7960,7965,624,7968,8005,624,8008,8013,624,8016,8023,624,8025,8025,624,8027,8027,624,8029,8029,624,8031,8061,624,8064,8116,624,8118,8124,624,8126,8126,624,8130,8132,624,8134,8140,624,8144,8147,624,8150,8155,624,8160,8172,624,8178,8180,624,8182,8188,624,8305,8305,624,8319,8319,624,8336,8348,624,8450,8450,624,8455,8455,624,8458,8467,624,8469,8469,624,8473,8477,624,8484,8484,624,8486,8486,624,8488,8488,624,8490,8493,624,8495,8505,624,8508,8511,624,8517,8521,624,8526,8526,624,8579,8580,624,11264,11310,624,11312,11358,624,11360,11492,624,11499,11502,624,11506,11507,624,11520,11557,624,11559,11559,624,11565,11565,624,11568,11623,624,11631,11631,624,11648,11670,624,11680,11686,624,11688,11694,624,11696,11702,624,11704,11710,624,11712,11718,624,11720,11726,624,11728,11734,624,11736,11742,624,11823,11823,624,12293,12294,624,12337,12341,624,12347,12348,624,12353,12438,624,12445,12447,624,12449,12538,624,12540,12543,624,12549,12589,624,12593,12686,624,12704,12730,624,12784,12799,624,13312,13312,624,19893,19893,624,19968,19968,624,40908,40908,624,40960,42124,624,42192,42237,624,42240,42508,624,42512,42527,624,42538,42539,624,42560,42606,624,42623,42647,624,42656,42725,624,42775,42783,624,42786,42888,624,42891,42894,624,42896,42899,624,42912,42922,624,43000,43009,624,43011,43013,624,43015,43018,624,43020,43042,624,43072,43123,624,43138,43187,624,43250,43255,624,43259,43259,624,43274,43301,624,43312,43334,624,43360,43388,624,43396,43442,624,43471,43471,624,43520,43560,624,43584,43586,624,43588,43595,624,43616,43638,624,43642,43642,624,43648,43695,624,43697,43697,624,43701,43702,624,43705,43709,624,43712,43712,624,43714,43714,624,43739,43741,624,43744,43754,624,43762,43764,624,43777,43782,624,43785,43790,624,43793,43798,624,43808,43814,624,43816,43822,624,43968,44002,624,44032,44032,624,55203,55203,624,55216,55238,624,55243,55291,624,63744,64109,624,64112,64217,624,64256,64262,624,64275,64279,624,64285,64285,624,64287,64296,624,64298,64310,624,64312,64316,624,64318,64318,624,64320,64321,624,64323,64324,624,64326,64433,624,64467,64829,624,64848,64911,624,64914,64967,624,65008,65019,624,65136,65140,624,65142,65276,624,65313,65338,624,65345,65370,624,65382,65470,624,65474,65479,624,65482,65487,624,65490,65495,624,65498,65500,624,371,170,170,648,181,181,648,186,186,648,192,214,648,216,246,648,248,705,648,710,721,648,736,740,648,748,748,648,750,750,648,880,884,648,886,887,648,890,893,648,902,902,648,904,906,648,908,908,648,910,929,648,931,1013,648,1015,1153,648,1162,1319,648,1329,1366,648,1369,1369,648,1377,1415,648,1488,1514,648,1520,1522,648,1568,1610,648,1646,1647,648,1649,1747,648,1749,1749,648,1765,1766,648,1774,1775,648,1786,1788,648,1791,1791,648,1808,1808,648,1810,1839,648,1869,1957,648,1969,1969,648,1994,2026,648,2036,2037,648,2042,2042,648,2048,2069,648,2074,2074,648,2084,2084,648,2088,2088,648,2112,2136,648,2208,2208,648,2210,2220,648,2308,2361,648,2365,2365,648,2384,2384,648,2392,2401,648,2417,2423,648,2425,2431,648,2437,2444,648,2447,2448,648,2451,2472,648,2474,2480,648,2482,2482,648,2486,2489,648,2493,2493,648,2510,2510,648,2524,2525,648,2527,2529,648,2544,2545,648,2565,2570,648,2575,2576,648,2579,2600,648,2602,2608,648,2610,2611,648,2613,2614,648,2616,2617,648,2649,2652,648,2654,2654,648,2674,2676,648,2693,2701,648,2703,2705,648,2707,2728,648,2730,2736,648,2738,2739,648,2741,2745,648,2749,2749,648,2768,2768,648,2784,2785,648,2821,2828,648,2831,2832,648,2835,2856,648,2858,2864,648,2866,2867,648,2869,2873,648,2877,2877,648,2908,2909,648,2911,2913,648,2929,2929,648,2947,2947,648,2949,2954,648,2958,2960,648,2962,2965,648,2969,2970,648,2972,2972,648,2974,2975,648,2979,2980,648,2984,2986,648,2990,3001,648,3024,3024,648,3077,3084,648,3086,3088,648,3090,3112,648,3114,3123,648,3125,3129,648,3133,3133,648,3160,3161,648,3168,3169,648,3205,3212,648,3214,3216,648,3218,3240,648,3242,3251,648,3253,3257,648,3261,3261,648,3294,3294,648,3296,3297,648,3313,3314,648,3333,3340,648,3342,3344,648,3346,3386,648,3389,3389,648,3406,3406,648,3424,3425,648,3450,3455,648,3461,3478,648,3482,3505,648,3507,3515,648,3517,3517,648,3520,3526,648,3585,3632,648,3634,3635,648,3648,3654,648,3713,3714,648,3716,3716,648,3719,3720,648,3722,3722,648,3725,3725,648,3732,3735,648,3737,3743,648,3745,3747,648,3749,3749,648,3751,3751,648,3754,3755,648,3757,3760,648,3762,3763,648,3773,3773,648,3776,3780,648,3782,3782,648,3804,3807,648,3840,3840,648,3904,3911,648,3913,3948,648,3976,3980,648,4096,4138,648,4159,4159,648,4176,4181,648,4186,4189,648,4193,4193,648,4197,4198,648,4206,4208,648,4213,4225,648,4238,4238,648,4256,4293,648,4295,4295,648,4301,4301,648,4304,4346,648,4348,4680,648,4682,4685,648,4688,4694,648,4696,4696,648,4698,4701,648,4704,4744,648,4746,4749,648,4752,4784,648,4786,4789,648,4792,4798,648,4800,4800,648,4802,4805,648,4808,4822,648,4824,4880,648,4882,4885,648,4888,4954,648,4992,5007,648,5024,5108,648,5121,5740,648,5743,5759,648,5761,5786,648,5792,5866,648,5888,5900,648,5902,5905,648,5920,5937,648,5952,5969,648,5984,5996,648,5998,6000,648,6016,6067,648,6103,6103,648,6108,6108,648,6176,6263,648,6272,6312,648,6314,6314,648,6320,6389,648,6400,6428,648,6480,6509,648,6512,6516,648,6528,6571,648,6593,6599,648,6656,6678,648,6688,6740,648,6823,6823,648,6917,6963,648,6981,6987,648,7043,7072,648,7086,7087,648,7098,7141,648,7168,7203,648,7245,7247,648,7258,7293,648,7401,7404,648,7406,7409,648,7413,7414,648,7424,7615,648,7680,7957,648,7960,7965,648,7968,8005,648,8008,8013,648,8016,8023,648,8025,8025,648,8027,8027,648,8029,8029,648,8031,8061,648,8064,8116,648,8118,8124,648,8126,8126,648,8130,8132,648,8134,8140,648,8144,8147,648,8150,8155,648,8160,8172,648,8178,8180,648,8182,8188,648,8305,8305,648,8319,8319,648,8336,8348,648,8450,8450,648,8455,8455,648,8458,8467,648,8469,8469,648,8473,8477,648,8484,8484,648,8486,8486,648,8488,8488,648,8490,8493,648,8495,8505,648,8508,8511,648,8517,8521,648,8526,8526,648,8579,8580,648,11264,11310,648,11312,11358,648,11360,11492,648,11499,11502,648,11506,11507,648,11520,11557,648,11559,11559,648,11565,11565,648,11568,11623,648,11631,11631,648,11648,11670,648,11680,11686,648,11688,11694,648,11696,11702,648,11704,11710,648,11712,11718,648,11720,11726,648,11728,11734,648,11736,11742,648,11823,11823,648,12293,12294,648,12337,12341,648,12347,12348,648,12353,12438,648,12445,12447,648,12449,12538,648,12540,12543,648,12549,12589,648,12593,12686,648,12704,12730,648,12784,12799,648,13312,13312,648,19893,19893,648,19968,19968,648,40908,40908,648,40960,42124,648,42192,42237,648,42240,42508,648,42512,42527,648,42538,42539,648,42560,42606,648,42623,42647,648,42656,42725,648,42775,42783,648,42786,42888,648,42891,42894,648,42896,42899,648,42912,42922,648,43000,43009,648,43011,43013,648,43015,43018,648,43020,43042,648,43072,43123,648,43138,43187,648,43250,43255,648,43259,43259,648,43274,43301,648,43312,43334,648,43360,43388,648,43396,43442,648,43471,43471,648,43520,43560,648,43584,43586,648,43588,43595,648,43616,43638,648,43642,43642,648,43648,43695,648,43697,43697,648,43701,43702,648,43705,43709,648,43712,43712,648,43714,43714,648,43739,43741,648,43744,43754,648,43762,43764,648,43777,43782,648,43785,43790,648,43793,43798,648,43808,43814,648,43816,43822,648,43968,44002,648,44032,44032,648,55203,55203,648,55216,55238,648,55243,55291,648,63744,64109,648,64112,64217,648,64256,64262,648,64275,64279,648,64285,64285,648,64287,64296,648,64298,64310,648,64312,64316,648,64318,64318,648,64320,64321,648,64323,64324,648,64326,64433,648,64467,64829,648,64848,64911,648,64914,64967,648,65008,65019,648,65136,65140,648,65142,65276,648,65313,65338,648,65345,65370,648,65382,65470,648,65474,65479,648,65482,65487,648,65490,65495,648,65498,65500,648,391,170,170,586,181,181,586,186,186,586,192,214,586,216,246,586,248,705,586,710,721,586,736,740,586,748,748,586,750,750,586,880,884,586,886,887,586,890,893,586,902,902,586,904,906,586,908,908,586,910,929,586,931,1013,586,1015,1153,586,1162,1319,586,1329,1366,586,1369,1369,586,1377,1415,586,1488,1514,586,1520,1522,586,1568,1610,586,1632,1641,586,1646,1647,586,1649,1747,586,1749,1749,586,1765,1766,586,1774,1788,586,1791,1791,586,1808,1808,586,1810,1839,586,1869,1957,586,1969,1969,586,1984,2026,586,2036,2037,586,2042,2042,586,2048,2069,586,2074,2074,586,2084,2084,586,2088,2088,586,2112,2136,586,2208,2208,586,2210,2220,586,2308,2361,586,2365,2365,586,2384,2384,586,2392,2401,586,2406,2415,586,2417,2423,586,2425,2431,586,2437,2444,586,2447,2448,586,2451,2472,586,2474,2480,586,2482,2482,586,2486,2489,586,2493,2493,586,2510,2510,586,2524,2525,586,2527,2529,586,2534,2545,586,2565,2570,586,2575,2576,586,2579,2600,586,2602,2608,586,2610,2611,586,2613,2614,586,2616,2617,586,2649,2652,586,2654,2654,586,2662,2671,586,2674,2676,586,2693,2701,586,2703,2705,586,2707,2728,586,2730,2736,586,2738,2739,586,2741,2745,586,2749,2749,586,2768,2768,586,2784,2785,586,2790,2799,586,2821,2828,586,2831,2832,586,2835,2856,586,2858,2864,586,2866,2867,586,2869,2873,586,2877,2877,586,2908,2909,586,2911,2913,586,2918,2927,586,2929,2929,586,2947,2947,586,2949,2954,586,2958,2960,586,2962,2965,586,2969,2970,586,2972,2972,586,2974,2975,586,2979,2980,586,2984,2986,586,2990,3001,586,3024,3024,586,3046,3055,586,3077,3084,586,3086,3088,586,3090,3112,586,3114,3123,586,3125,3129,586,3133,3133,586,3160,3161,586,3168,3169,586,3174,3183,586,3205,3212,586,3214,3216,586,3218,3240,586,3242,3251,586,3253,3257,586,3261,3261,586,3294,3294,586,3296,3297,586,3302,3311,586,3313,3314,586,3333,3340,586,3342,3344,586,3346,3386,586,3389,3389,586,3406,3406,586,3424,3425,586,3430,3439,586,3450,3455,586,3461,3478,586,3482,3505,586,3507,3515,586,3517,3517,586,3520,3526,586,3585,3632,586,3634,3635,586,3648,3654,586,3664,3673,586,3713,3714,586,3716,3716,586,3719,3720,586,3722,3722,586,3725,3725,586,3732,3735,586,3737,3743,586,3745,3747,586,3749,3749,586,3751,3751,586,3754,3755,586,3757,3760,586,3762,3763,586,3773,3773,586,3776,3780,586,3782,3782,586,3792,3801,586,3804,3807,586,3840,3840,586,3872,3881,586,3904,3911,586,3913,3948,586,3976,3980,586,4096,4138,586,4159,4169,586,4176,4181,586,4186,4189,586,4193,4193,586,4197,4198,586,4206,4208,586,4213,4225,586,4238,4238,586,4240,4249,586,4256,4293,586,4295,4295,586,4301,4301,586,4304,4346,586,4348,4680,586,4682,4685,586,4688,4694,586,4696,4696,586,4698,4701,586,4704,4744,586,4746,4749,586,4752,4784,586,4786,4789,586,4792,4798,586,4800,4800,586,4802,4805,586,4808,4822,586,4824,4880,586,4882,4885,586,4888,4954,586,4992,5007,586,5024,5108,586,5121,5740,586,5743,5759,586,5761,5786,586,5792,5866,586,5888,5900,586,5902,5905,586,5920,5937,586,5952,5969,586,5984,5996,586,5998,6000,586,6016,6067,586,6103,6103,586,6108,6108,586,6112,6121,586,6160,6169,586,6176,6263,586,6272,6312,586,6314,6314,586,6320,6389,586,6400,6428,586,6470,6509,586,6512,6516,586,6528,6571,586,6593,6599,586,6608,6617,586,6656,6678,586,6688,6740,586,6784,6793,586,6800,6809,586,6823,6823,586,6917,6963,586,6981,6987,586,6992,7001,586,7043,7072,586,7086,7141,586,7168,7203,586,7232,7241,586,7245,7293,586,7401,7404,586,7406,7409,586,7413,7414,586,7424,7615,586,7680,7957,586,7960,7965,586,7968,8005,586,8008,8013,586,8016,8023,586,8025,8025,586,8027,8027,586,8029,8029,586,8031,8061,586,8064,8116,586,8118,8124,586,8126,8126,586,8130,8132,586,8134,8140,586,8144,8147,586,8150,8155,586,8160,8172,586,8178,8180,586,8182,8188,586,8305,8305,586,8319,8319,586,8336,8348,586,8450,8450,586,8455,8455,586,8458,8467,586,8469,8469,586,8473,8477,586,8484,8484,586,8486,8486,586,8488,8488,586,8490,8493,586,8495,8505,586,8508,8511,586,8517,8521,586,8526,8526,586,8579,8580,586,11264,11310,586,11312,11358,586,11360,11492,586,11499,11502,586,11506,11507,586,11520,11557,586,11559,11559,586,11565,11565,586,11568,11623,586,11631,11631,586,11648,11670,586,11680,11686,586,11688,11694,586,11696,11702,586,11704,11710,586,11712,11718,586,11720,11726,586,11728,11734,586,11736,11742,586,11823,11823,586,12293,12294,586,12337,12341,586,12347,12348,586,12353,12438,586,12445,12447,586,12449,12538,586,12540,12543,586,12549,12589,586,12593,12686,586,12704,12730,586,12784,12799,586,13312,13312,586,19893,19893,586,19968,19968,586,40908,40908,586,40960,42124,586,42192,42237,586,42240,42508,586,42512,42539,586,42560,42606,586,42623,42647,586,42656,42725,586,42775,42783,586,42786,42888,586,42891,42894,586,42896,42899,586,42912,42922,586,43000,43009,586,43011,43013,586,43015,43018,586,43020,43042,586,43072,43123,586,43138,43187,586,43216,43225,586,43250,43255,586,43259,43259,586,43264,43301,586,43312,43334,586,43360,43388,586,43396,43442,586,43471,43481,586,43520,43560,586,43584,43586,586,43588,43595,586,43600,43609,586,43616,43638,586,43642,43642,586,43648,43695,586,43697,43697,586,43701,43702,586,43705,43709,586,43712,43712,586,43714,43714,586,43739,43741,586,43744,43754,586,43762,43764,586,43777,43782,586,43785,43790,586,43793,43798,586,43808,43814,586,43816,43822,586,43968,44002,586,44016,44025,586,44032,44032,586,55203,55203,586,55216,55238,586,55243,55291,586,63744,64109,586,64112,64217,586,64256,64262,586,64275,64279,586,64285,64285,586,64287,64296,586,64298,64310,586,64312,64316,586,64318,64318,586,64320,64321,586,64323,64324,586,64326,64433,586,64467,64829,586,64848,64911,586,64914,64967,586,65008,65019,586,65136,65140,586,65142,65276,586,65296,65305,586,65313,65338,586,65345,65370,586,65382,65470,586,65474,65479,586,65482,65487,586,65490,65495,586,65498,65500,586,1,128,1114111,652,1,128,1114111,618,391,170,170,624,181,181,624,186,186,624,192,214,624,216,246,624,248,705,624,710,721,624,736,740,624,748,748,624,750,750,624,880,884,624,886,887,624,890,893,624,902,902,624,904,906,624,908,908,624,910,929,624,931,1013,624,1015,1153,624,1162,1319,624,1329,1366,624,1369,1369,624,1377,1415,624,1488,1514,624,1520,1522,624,1568,1610,624,1632,1641,624,1646,1647,624,1649,1747,624,1749,1749,624,1765,1766,624,1774,1788,624,1791,1791,624,1808,1808,624,1810,1839,624,1869,1957,624,1969,1969,624,1984,2026,624,2036,2037,624,2042,2042,624,2048,2069,624,2074,2074,624,2084,2084,624,2088,2088,624,2112,2136,624,2208,2208,624,2210,2220,624,2308,2361,624,2365,2365,624,2384,2384,624,2392,2401,624,2406,2415,624,2417,2423,624,2425,2431,624,2437,2444,624,2447,2448,624,2451,2472,624,2474,2480,624,2482,2482,624,2486,2489,624,2493,2493,624,2510,2510,624,2524,2525,624,2527,2529,624,2534,2545,624,2565,2570,624,2575,2576,624,2579,2600,624,2602,2608,624,2610,2611,624,2613,2614,624,2616,2617,624,2649,2652,624,2654,2654,624,2662,2671,624,2674,2676,624,2693,2701,624,2703,2705,624,2707,2728,624,2730,2736,624,2738,2739,624,2741,2745,624,2749,2749,624,2768,2768,624,2784,2785,624,2790,2799,624,2821,2828,624,2831,2832,624,2835,2856,624,2858,2864,624,2866,2867,624,2869,2873,624,2877,2877,624,2908,2909,624,2911,2913,624,2918,2927,624,2929,2929,624,2947,2947,624,2949,2954,624,2958,2960,624,2962,2965,624,2969,2970,624,2972,2972,624,2974,2975,624,2979,2980,624,2984,2986,624,2990,3001,624,3024,3024,624,3046,3055,624,3077,3084,624,3086,3088,624,3090,3112,624,3114,3123,624,3125,3129,624,3133,3133,624,3160,3161,624,3168,3169,624,3174,3183,624,3205,3212,624,3214,3216,624,3218,3240,624,3242,3251,624,3253,3257,624,3261,3261,624,3294,3294,624,3296,3297,624,3302,3311,624,3313,3314,624,3333,3340,624,3342,3344,624,3346,3386,624,3389,3389,624,3406,3406,624,3424,3425,624,3430,3439,624,3450,3455,624,3461,3478,624,3482,3505,624,3507,3515,624,3517,3517,624,3520,3526,624,3585,3632,624,3634,3635,624,3648,3654,624,3664,3673,624,3713,3714,624,3716,3716,624,3719,3720,624,3722,3722,624,3725,3725,624,3732,3735,624,3737,3743,624,3745,3747,624,3749,3749,624,3751,3751,624,3754,3755,624,3757,3760,624,3762,3763,624,3773,3773,624,3776,3780,624,3782,3782,624,3792,3801,624,3804,3807,624,3840,3840,624,3872,3881,624,3904,3911,624,3913,3948,624,3976,3980,624,4096,4138,624,4159,4169,624,4176,4181,624,4186,4189,624,4193,4193,624,4197,4198,624,4206,4208,624,4213,4225,624,4238,4238,624,4240,4249,624,4256,4293,624,4295,4295,624,4301,4301,624,4304,4346,624,4348,4680,624,4682,4685,624,4688,4694,624,4696,4696,624,4698,4701,624,4704,4744,624,4746,4749,624,4752,4784,624,4786,4789,624,4792,4798,624,4800,4800,624,4802,4805,624,4808,4822,624,4824,4880,624,4882,4885,624,4888,4954,624,4992,5007,624,5024,5108,624,5121,5740,624,5743,5759,624,5761,5786,624,5792,5866,624,5888,5900,624,5902,5905,624,5920,5937,624,5952,5969,624,5984,5996,624,5998,6000,624,6016,6067,624,6103,6103,624,6108,6108,624,6112,6121,624,6160,6169,624,6176,6263,624,6272,6312,624,6314,6314,624,6320,6389,624,6400,6428,624,6470,6509,624,6512,6516,624,6528,6571,624,6593,6599,624,6608,6617,624,6656,6678,624,6688,6740,624,6784,6793,624,6800,6809,624,6823,6823,624,6917,6963,624,6981,6987,624,6992,7001,624,7043,7072,624,7086,7141,624,7168,7203,624,7232,7241,624,7245,7293,624,7401,7404,624,7406,7409,624,7413,7414,624,7424,7615,624,7680,7957,624,7960,7965,624,7968,8005,624,8008,8013,624,8016,8023,624,8025,8025,624,8027,8027,624,8029,8029,624,8031,8061,624,8064,8116,624,8118,8124,624,8126,8126,624,8130,8132,624,8134,8140,624,8144,8147,624,8150,8155,624,8160,8172,624,8178,8180,624,8182,8188,624,8305,8305,624,8319,8319,624,8336,8348,624,8450,8450,624,8455,8455,624,8458,8467,624,8469,8469,624,8473,8477,624,8484,8484,624,8486,8486,624,8488,8488,624,8490,8493,624,8495,8505,624,8508,8511,624,8517,8521,624,8526,8526,624,8579,8580,624,11264,11310,624,11312,11358,624,11360,11492,624,11499,11502,624,11506,11507,624,11520,11557,624,11559,11559,624,11565,11565,624,11568,11623,624,11631,11631,624,11648,11670,624,11680,11686,624,11688,11694,624,11696,11702,624,11704,11710,624,11712,11718,624,11720,11726,624,11728,11734,624,11736,11742,624,11823,11823,624,12293,12294,624,12337,12341,624,12347,12348,624,12353,12438,624,12445,12447,624,12449,12538,624,12540,12543,624,12549,12589,624,12593,12686,624,12704,12730,624,12784,12799,624,13312,13312,624,19893,19893,624,19968,19968,624,40908,40908,624,40960,42124,624,42192,42237,624,42240,42508,624,42512,42539,624,42560,42606,624,42623,42647,624,42656,42725,624,42775,42783,624,42786,42888,624,42891,42894,624,42896,42899,624,42912,42922,624,43000,43009,624,43011,43013,624,43015,43018,624,43020,43042,624,43072,43123,624,43138,43187,624,43216,43225,624,43250,43255,624,43259,43259,624,43264,43301,624,43312,43334,624,43360,43388,624,43396,43442,624,43471,43481,624,43520,43560,624,43584,43586,624,43588,43595,624,43600,43609,624,43616,43638,624,43642,43642,624,43648,43695,624,43697,43697,624,43701,43702,624,43705,43709,624,43712,43712,624,43714,43714,624,43739,43741,624,43744,43754,624,43762,43764,624,43777,43782,624,43785,43790,624,43793,43798,624,43808,43814,624,43816,43822,624,43968,44002,624,44016,44025,624,44032,44032,624,55203,55203,624,55216,55238,624,55243,55291,624,63744,64109,624,64112,64217,624,64256,64262,624,64275,64279,624,64285,64285,624,64287,64296,624,64298,64310,624,64312,64316,624,64318,64318,624,64320,64321,624,64323,64324,624,64326,64433,624,64467,64829,624,64848,64911,624,64914,64967,624,65008,65019,624,65136,65140,624,65142,65276,624,65296,65305,624,65313,65338,624,65345,65370,624,65382,65470,624,65474,65479,624,65482,65487,624,65490,65495,624,65498,65500,624,1,128,1114111,673,371,170,170,689,181,181,689,186,186,689,192,214,689,216,246,689,248,705,689,710,721,689,736,740,689,748,748,689,750,750,689,880,884,689,886,887,689,890,893,689,902,902,689,904,906,689,908,908,689,910,929,689,931,1013,689,1015,1153,689,1162,1319,689,1329,1366,689,1369,1369,689,1377,1415,689,1488,1514,689,1520,1522,689,1568,1610,689,1646,1647,689,1649,1747,689,1749,1749,689,1765,1766,689,1774,1775,689,1786,1788,689,1791,1791,689,1808,1808,689,1810,1839,689,1869,1957,689,1969,1969,689,1994,2026,689,2036,2037,689,2042,2042,689,2048,2069,689,2074,2074,689,2084,2084,689,2088,2088,689,2112,2136,689,2208,2208,689,2210,2220,689,2308,2361,689,2365,2365,689,2384,2384,689,2392,2401,689,2417,2423,689,2425,2431,689,2437,2444,689,2447,2448,689,2451,2472,689,2474,2480,689,2482,2482,689,2486,2489,689,2493,2493,689,2510,2510,689,2524,2525,689,2527,2529,689,2544,2545,689,2565,2570,689,2575,2576,689,2579,2600,689,2602,2608,689,2610,2611,689,2613,2614,689,2616,2617,689,2649,2652,689,2654,2654,689,2674,2676,689,2693,2701,689,2703,2705,689,2707,2728,689,2730,2736,689,2738,2739,689,2741,2745,689,2749,2749,689,2768,2768,689,2784,2785,689,2821,2828,689,2831,2832,689,2835,2856,689,2858,2864,689,2866,2867,689,2869,2873,689,2877,2877,689,2908,2909,689,2911,2913,689,2929,2929,689,2947,2947,689,2949,2954,689,2958,2960,689,2962,2965,689,2969,2970,689,2972,2972,689,2974,2975,689,2979,2980,689,2984,2986,689,2990,3001,689,3024,3024,689,3077,3084,689,3086,3088,689,3090,3112,689,3114,3123,689,3125,3129,689,3133,3133,689,3160,3161,689,3168,3169,689,3205,3212,689,3214,3216,689,3218,3240,689,3242,3251,689,3253,3257,689,3261,3261,689,3294,3294,689,3296,3297,689,3313,3314,689,3333,3340,689,3342,3344,689,3346,3386,689,3389,3389,689,3406,3406,689,3424,3425,689,3450,3455,689,3461,3478,689,3482,3505,689,3507,3515,689,3517,3517,689,3520,3526,689,3585,3632,689,3634,3635,689,3648,3654,689,3713,3714,689,3716,3716,689,3719,3720,689,3722,3722,689,3725,3725,689,3732,3735,689,3737,3743,689,3745,3747,689,3749,3749,689,3751,3751,689,3754,3755,689,3757,3760,689,3762,3763,689,3773,3773,689,3776,3780,689,3782,3782,689,3804,3807,689,3840,3840,689,3904,3911,689,3913,3948,689,3976,3980,689,4096,4138,689,4159,4159,689,4176,4181,689,4186,4189,689,4193,4193,689,4197,4198,689,4206,4208,689,4213,4225,689,4238,4238,689,4256,4293,689,4295,4295,689,4301,4301,689,4304,4346,689,4348,4680,689,4682,4685,689,4688,4694,689,4696,4696,689,4698,4701,689,4704,4744,689,4746,4749,689,4752,4784,689,4786,4789,689,4792,4798,689,4800,4800,689,4802,4805,689,4808,4822,689,4824,4880,689,4882,4885,689,4888,4954,689,4992,5007,689,5024,5108,689,5121,5740,689,5743,5759,689,5761,5786,689,5792,5866,689,5888,5900,689,5902,5905,689,5920,5937,689,5952,5969,689,5984,5996,689,5998,6000,689,6016,6067,689,6103,6103,689,6108,6108,689,6176,6263,689,6272,6312,689,6314,6314,689,6320,6389,689,6400,6428,689,6480,6509,689,6512,6516,689,6528,6571,689,6593,6599,689,6656,6678,689,6688,6740,689,6823,6823,689,6917,6963,689,6981,6987,689,7043,7072,689,7086,7087,689,7098,7141,689,7168,7203,689,7245,7247,689,7258,7293,689,7401,7404,689,7406,7409,689,7413,7414,689,7424,7615,689,7680,7957,689,7960,7965,689,7968,8005,689,8008,8013,689,8016,8023,689,8025,8025,689,8027,8027,689,8029,8029,689,8031,8061,689,8064,8116,689,8118,8124,689,8126,8126,689,8130,8132,689,8134,8140,689,8144,8147,689,8150,8155,689,8160,8172,689,8178,8180,689,8182,8188,689,8305,8305,689,8319,8319,689,8336,8348,689,8450,8450,689,8455,8455,689,8458,8467,689,8469,8469,689,8473,8477,689,8484,8484,689,8486,8486,689,8488,8488,689,8490,8493,689,8495,8505,689,8508,8511,689,8517,8521,689,8526,8526,689,8579,8580,689,11264,11310,689,11312,11358,689,11360,11492,689,11499,11502,689,11506,11507,689,11520,11557,689,11559,11559,689,11565,11565,689,11568,11623,689,11631,11631,689,11648,11670,689,11680,11686,689,11688,11694,689,11696,11702,689,11704,11710,689,11712,11718,689,11720,11726,689,11728,11734,689,11736,11742,689,11823,11823,689,12293,12294,689,12337,12341,689,12347,12348,689,12353,12438,689,12445,12447,689,12449,12538,689,12540,12543,689,12549,12589,689,12593,12686,689,12704,12730,689,12784,12799,689,13312,13312,689,19893,19893,689,19968,19968,689,40908,40908,689,40960,42124,689,42192,42237,689,42240,42508,689,42512,42527,689,42538,42539,689,42560,42606,689,42623,42647,689,42656,42725,689,42775,42783,689,42786,42888,689,42891,42894,689,42896,42899,689,42912,42922,689,43000,43009,689,43011,43013,689,43015,43018,689,43020,43042,689,43072,43123,689,43138,43187,689,43250,43255,689,43259,43259,689,43274,43301,689,43312,43334,689,43360,43388,689,43396,43442,689,43471,43471,689,43520,43560,689,43584,43586,689,43588,43595,689,43616,43638,689,43642,43642,689,43648,43695,689,43697,43697,689,43701,43702,689,43705,43709,689,43712,43712,689,43714,43714,689,43739,43741,689,43744,43754,689,43762,43764,689,43777,43782,689,43785,43790,689,43793,43798,689,43808,43814,689,43816,43822,689,43968,44002,689,44032,44032,689,55203,55203,689,55216,55238,689,55243,55291,689,63744,64109,689,64112,64217,689,64256,64262,689,64275,64279,689,64285,64285,689,64287,64296,689,64298,64310,689,64312,64316,689,64318,64318,689,64320,64321,689,64323,64324,689,64326,64433,689,64467,64829,689,64848,64911,689,64914,64967,689,65008,65019,689,65136,65140,689,65142,65276,689,65313,65338,689,65345,65370,689,65382,65470,689,65474,65479,689,65482,65487,689,65490,65495,689,65498,65500,689,391,170,170,648,181,181,648,186,186,648,192,214,648,216,246,648,248,705,648,710,721,648,736,740,648,748,748,648,750,750,648,880,884,648,886,887,648,890,893,648,902,902,648,904,906,648,908,908,648,910,929,648,931,1013,648,1015,1153,648,1162,1319,648,1329,1366,648,1369,1369,648,1377,1415,648,1488,1514,648,1520,1522,648,1568,1610,648,1632,1641,648,1646,1647,648,1649,1747,648,1749,1749,648,1765,1766,648,1774,1788,648,1791,1791,648,1808,1808,648,1810,1839,648,1869,1957,648,1969,1969,648,1984,2026,648,2036,2037,648,2042,2042,648,2048,2069,648,2074,2074,648,2084,2084,648,2088,2088,648,2112,2136,648,2208,2208,648,2210,2220,648,2308,2361,648,2365,2365,648,2384,2384,648,2392,2401,648,2406,2415,648,2417,2423,648,2425,2431,648,2437,2444,648,2447,2448,648,2451,2472,648,2474,2480,648,2482,2482,648,2486,2489,648,2493,2493,648,2510,2510,648,2524,2525,648,2527,2529,648,2534,2545,648,2565,2570,648,2575,2576,648,2579,2600,648,2602,2608,648,2610,2611,648,2613,2614,648,2616,2617,648,2649,2652,648,2654,2654,648,2662,2671,648,2674,2676,648,2693,2701,648,2703,2705,648,2707,2728,648,2730,2736,648,2738,2739,648,2741,2745,648,2749,2749,648,2768,2768,648,2784,2785,648,2790,2799,648,2821,2828,648,2831,2832,648,2835,2856,648,2858,2864,648,2866,2867,648,2869,2873,648,2877,2877,648,2908,2909,648,2911,2913,648,2918,2927,648,2929,2929,648,2947,2947,648,2949,2954,648,2958,2960,648,2962,2965,648,2969,2970,648,2972,2972,648,2974,2975,648,2979,2980,648,2984,2986,648,2990,3001,648,3024,3024,648,3046,3055,648,3077,3084,648,3086,3088,648,3090,3112,648,3114,3123,648,3125,3129,648,3133,3133,648,3160,3161,648,3168,3169,648,3174,3183,648,3205,3212,648,3214,3216,648,3218,3240,648,3242,3251,648,3253,3257,648,3261,3261,648,3294,3294,648,3296,3297,648,3302,3311,648,3313,3314,648,3333,3340,648,3342,3344,648,3346,3386,648,3389,3389,648,3406,3406,648,3424,3425,648,3430,3439,648,3450,3455,648,3461,3478,648,3482,3505,648,3507,3515,648,3517,3517,648,3520,3526,648,3585,3632,648,3634,3635,648,3648,3654,648,3664,3673,648,3713,3714,648,3716,3716,648,3719,3720,648,3722,3722,648,3725,3725,648,3732,3735,648,3737,3743,648,3745,3747,648,3749,3749,648,3751,3751,648,3754,3755,648,3757,3760,648,3762,3763,648,3773,3773,648,3776,3780,648,3782,3782,648,3792,3801,648,3804,3807,648,3840,3840,648,3872,3881,648,3904,3911,648,3913,3948,648,3976,3980,648,4096,4138,648,4159,4169,648,4176,4181,648,4186,4189,648,4193,4193,648,4197,4198,648,4206,4208,648,4213,4225,648,4238,4238,648,4240,4249,648,4256,4293,648,4295,4295,648,4301,4301,648,4304,4346,648,4348,4680,648,4682,4685,648,4688,4694,648,4696,4696,648,4698,4701,648,4704,4744,648,4746,4749,648,4752,4784,648,4786,4789,648,4792,4798,648,4800,4800,648,4802,4805,648,4808,4822,648,4824,4880,648,4882,4885,648,4888,4954,648,4992,5007,648,5024,5108,648,5121,5740,648,5743,5759,648,5761,5786,648,5792,5866,648,5888,5900,648,5902,5905,648,5920,5937,648,5952,5969,648,5984,5996,648,5998,6000,648,6016,6067,648,6103,6103,648,6108,6108,648,6112,6121,648,6160,6169,648,6176,6263,648,6272,6312,648,6314,6314,648,6320,6389,648,6400,6428,648,6470,6509,648,6512,6516,648,6528,6571,648,6593,6599,648,6608,6617,648,6656,6678,648,6688,6740,648,6784,6793,648,6800,6809,648,6823,6823,648,6917,6963,648,6981,6987,648,6992,7001,648,7043,7072,648,7086,7141,648,7168,7203,648,7232,7241,648,7245,7293,648,7401,7404,648,7406,7409,648,7413,7414,648,7424,7615,648,7680,7957,648,7960,7965,648,7968,8005,648,8008,8013,648,8016,8023,648,8025,8025,648,8027,8027,648,8029,8029,648,8031,8061,648,8064,8116,648,8118,8124,648,8126,8126,648,8130,8132,648,8134,8140,648,8144,8147,648,8150,8155,648,8160,8172,648,8178,8180,648,8182,8188,648,8305,8305,648,8319,8319,648,8336,8348,648,8450,8450,648,8455,8455,648,8458,8467,648,8469,8469,648,8473,8477,648,8484,8484,648,8486,8486,648,8488,8488,648,8490,8493,648,8495,8505,648,8508,8511,648,8517,8521,648,8526,8526,648,8579,8580,648,11264,11310,648,11312,11358,648,11360,11492,648,11499,11502,648,11506,11507,648,11520,11557,648,11559,11559,648,11565,11565,648,11568,11623,648,11631,11631,648,11648,11670,648,11680,11686,648,11688,11694,648,11696,11702,648,11704,11710,648,11712,11718,648,11720,11726,648,11728,11734,648,11736,11742,648,11823,11823,648,12293,12294,648,12337,12341,648,12347,12348,648,12353,12438,648,12445,12447,648,12449,12538,648,12540,12543,648,12549,12589,648,12593,12686,648,12704,12730,648,12784,12799,648,13312,13312,648,19893,19893,648,19968,19968,648,40908,40908,648,40960,42124,648,42192,42237,648,42240,42508,648,42512,42539,648,42560,42606,648,42623,42647,648,42656,42725,648,42775,42783,648,42786,42888,648,42891,42894,648,42896,42899,648,42912,42922,648,43000,43009,648,43011,43013,648,43015,43018,648,43020,43042,648,43072,43123,648,43138,43187,648,43216,43225,648,43250,43255,648,43259,43259,648,43264,43301,648,43312,43334,648,43360,43388,648,43396,43442,648,43471,43481,648,43520,43560,648,43584,43586,648,43588,43595,648,43600,43609,648,43616,43638,648,43642,43642,648,43648,43695,648,43697,43697,648,43701,43702,648,43705,43709,648,43712,43712,648,43714,43714,648,43739,43741,648,43744,43754,648,43762,43764,648,43777,43782,648,43785,43790,648,43793,43798,648,43808,43814,648,43816,43822,648,43968,44002,648,44016,44025,648,44032,44032,648,55203,55203,648,55216,55238,648,55243,55291,648,63744,64109,648,64112,64217,648,64256,64262,648,64275,64279,648,64285,64285,648,64287,64296,648,64298,64310,648,64312,64316,648,64318,64318,648,64320,64321,648,64323,64324,648,64326,64433,648,64467,64829,648,64848,64911,648,64914,64967,648,65008,65019,648,65136,65140,648,65142,65276,648,65296,65305,648,65313,65338,648,65345,65370,648,65382,65470,648,65474,65479,648,65482,65487,648,65490,65495,648,65498,65500,648,1,128,1114111,692,391,170,170,689,181,181,689,186,186,689,192,214,689,216,246,689,248,705,689,710,721,689,736,740,689,748,748,689,750,750,689,880,884,689,886,887,689,890,893,689,902,902,689,904,906,689,908,908,689,910,929,689,931,1013,689,1015,1153,689,1162,1319,689,1329,1366,689,1369,1369,689,1377,1415,689,1488,1514,689,1520,1522,689,1568,1610,689,1632,1641,689,1646,1647,689,1649,1747,689,1749,1749,689,1765,1766,689,1774,1788,689,1791,1791,689,1808,1808,689,1810,1839,689,1869,1957,689,1969,1969,689,1984,2026,689,2036,2037,689,2042,2042,689,2048,2069,689,2074,2074,689,2084,2084,689,2088,2088,689,2112,2136,689,2208,2208,689,2210,2220,689,2308,2361,689,2365,2365,689,2384,2384,689,2392,2401,689,2406,2415,689,2417,2423,689,2425,2431,689,2437,2444,689,2447,2448,689,2451,2472,689,2474,2480,689,2482,2482,689,2486,2489,689,2493,2493,689,2510,2510,689,2524,2525,689,2527,2529,689,2534,2545,689,2565,2570,689,2575,2576,689,2579,2600,689,2602,2608,689,2610,2611,689,2613,2614,689,2616,2617,689,2649,2652,689,2654,2654,689,2662,2671,689,2674,2676,689,2693,2701,689,2703,2705,689,2707,2728,689,2730,2736,689,2738,2739,689,2741,2745,689,2749,2749,689,2768,2768,689,2784,2785,689,2790,2799,689,2821,2828,689,2831,2832,689,2835,2856,689,2858,2864,689,2866,2867,689,2869,2873,689,2877,2877,689,2908,2909,689,2911,2913,689,2918,2927,689,2929,2929,689,2947,2947,689,2949,2954,689,2958,2960,689,2962,2965,689,2969,2970,689,2972,2972,689,2974,2975,689,2979,2980,689,2984,2986,689,2990,3001,689,3024,3024,689,3046,3055,689,3077,3084,689,3086,3088,689,3090,3112,689,3114,3123,689,3125,3129,689,3133,3133,689,3160,3161,689,3168,3169,689,3174,3183,689,3205,3212,689,3214,3216,689,3218,3240,689,3242,3251,689,3253,3257,689,3261,3261,689,3294,3294,689,3296,3297,689,3302,3311,689,3313,3314,689,3333,3340,689,3342,3344,689,3346,3386,689,3389,3389,689,3406,3406,689,3424,3425,689,3430,3439,689,3450,3455,689,3461,3478,689,3482,3505,689,3507,3515,689,3517,3517,689,3520,3526,689,3585,3632,689,3634,3635,689,3648,3654,689,3664,3673,689,3713,3714,689,3716,3716,689,3719,3720,689,3722,3722,689,3725,3725,689,3732,3735,689,3737,3743,689,3745,3747,689,3749,3749,689,3751,3751,689,3754,3755,689,3757,3760,689,3762,3763,689,3773,3773,689,3776,3780,689,3782,3782,689,3792,3801,689,3804,3807,689,3840,3840,689,3872,3881,689,3904,3911,689,3913,3948,689,3976,3980,689,4096,4138,689,4159,4169,689,4176,4181,689,4186,4189,689,4193,4193,689,4197,4198,689,4206,4208,689,4213,4225,689,4238,4238,689,4240,4249,689,4256,4293,689,4295,4295,689,4301,4301,689,4304,4346,689,4348,4680,689,4682,4685,689,4688,4694,689,4696,4696,689,4698,4701,689,4704,4744,689,4746,4749,689,4752,4784,689,4786,4789,689,4792,4798,689,4800,4800,689,4802,4805,689,4808,4822,689,4824,4880,689,4882,4885,689,4888,4954,689,4992,5007,689,5024,5108,689,5121,5740,689,5743,5759,689,5761,5786,689,5792,5866,689,5888,5900,689,5902,5905,689,5920,5937,689,5952,5969,689,5984,5996,689,5998,6000,689,6016,6067,689,6103,6103,689,6108,6108,689,6112,6121,689,6160,6169,689,6176,6263,689,6272,6312,689,6314,6314,689,6320,6389,689,6400,6428,689,6470,6509,689,6512,6516,689,6528,6571,689,6593,6599,689,6608,6617,689,6656,6678,689,6688,6740,689,6784,6793,689,6800,6809,689,6823,6823,689,6917,6963,689,6981,6987,689,6992,7001,689,7043,7072,689,7086,7141,689,7168,7203,689,7232,7241,689,7245,7293,689,7401,7404,689,7406,7409,689,7413,7414,689,7424,7615,689,7680,7957,689,7960,7965,689,7968,8005,689,8008,8013,689,8016,8023,689,8025,8025,689,8027,8027,689,8029,8029,689,8031,8061,689,8064,8116,689,8118,8124,689,8126,8126,689,8130,8132,689,8134,8140,689,8144,8147,689,8150,8155,689,8160,8172,689,8178,8180,689,8182,8188,689,8305,8305,689,8319,8319,689,8336,8348,689,8450,8450,689,8455,8455,689,8458,8467,689,8469,8469,689,8473,8477,689,8484,8484,689,8486,8486,689,8488,8488,689,8490,8493,689,8495,8505,689,8508,8511,689,8517,8521,689,8526,8526,689,8579,8580,689,11264,11310,689,11312,11358,689,11360,11492,689,11499,11502,689,11506,11507,689,11520,11557,689,11559,11559,689,11565,11565,689,11568,11623,689,11631,11631,689,11648,11670,689,11680,11686,689,11688,11694,689,11696,11702,689,11704,11710,689,11712,11718,689,11720,11726,689,11728,11734,689,11736,11742,689,11823,11823,689,12293,12294,689,12337,12341,689,12347,12348,689,12353,12438,689,12445,12447,689,12449,12538,689,12540,12543,689,12549,12589,689,12593,12686,689,12704,12730,689,12784,12799,689,13312,13312,689,19893,19893,689,19968,19968,689,40908,40908,689,40960,42124,689,42192,42237,689,42240,42508,689,42512,42539,689,42560,42606,689,42623,42647,689,42656,42725,689,42775,42783,689,42786,42888,689,42891,42894,689,42896,42899,689,42912,42922,689,43000,43009,689,43011,43013,689,43015,43018,689,43020,43042,689,43072,43123,689,43138,43187,689,43216,43225,689,43250,43255,689,43259,43259,689,43264,43301,689,43312,43334,689,43360,43388,689,43396,43442,689,43471,43481,689,43520,43560,689,43584,43586,689,43588,43595,689,43600,43609,689,43616,43638,689,43642,43642,689,43648,43695,689,43697,43697,689,43701,43702,689,43705,43709,689,43712,43712,689,43714,43714,689,43739,43741,689,43744,43754,689,43762,43764,689,43777,43782,689,43785,43790,689,43793,43798,689,43808,43814,689,43816,43822,689,43968,44002,689,44016,44025,689,44032,44032,689,55203,55203,689,55216,55238,689,55243,55291,689,63744,64109,689,64112,64217,689,64256,64262,689,64275,64279,689,64285,64285,689,64287,64296,689,64298,64310,689,64312,64316,689,64318,64318,689,64320,64321,689,64323,64324,689,64326,64433,689,64467,64829,689,64848,64911,689,64914,64967,689,65008,65019,689,65136,65140,689,65142,65276,689,65296,65305,689,65313,65338,689,65345,65370,689,65382,65470,689,65474,65479,689,65482,65487,689,65490,65495,689,65498,65500,689,1,128,1114111,708,371,170,170,716,181,181,716,186,186,716,192,214,716,216,246,716,248,705,716,710,721,716,736,740,716,748,748,716,750,750,716,880,884,716,886,887,716,890,893,716,902,902,716,904,906,716,908,908,716,910,929,716,931,1013,716,1015,1153,716,1162,1319,716,1329,1366,716,1369,1369,716,1377,1415,716,1488,1514,716,1520,1522,716,1568,1610,716,1646,1647,716,1649,1747,716,1749,1749,716,1765,1766,716,1774,1775,716,1786,1788,716,1791,1791,716,1808,1808,716,1810,1839,716,1869,1957,716,1969,1969,716,1994,2026,716,2036,2037,716,2042,2042,716,2048,2069,716,2074,2074,716,2084,2084,716,2088,2088,716,2112,2136,716,2208,2208,716,2210,2220,716,2308,2361,716,2365,2365,716,2384,2384,716,2392,2401,716,2417,2423,716,2425,2431,716,2437,2444,716,2447,2448,716,2451,2472,716,2474,2480,716,2482,2482,716,2486,2489,716,2493,2493,716,2510,2510,716,2524,2525,716,2527,2529,716,2544,2545,716,2565,2570,716,2575,2576,716,2579,2600,716,2602,2608,716,2610,2611,716,2613,2614,716,2616,2617,716,2649,2652,716,2654,2654,716,2674,2676,716,2693,2701,716,2703,2705,716,2707,2728,716,2730,2736,716,2738,2739,716,2741,2745,716,2749,2749,716,2768,2768,716,2784,2785,716,2821,2828,716,2831,2832,716,2835,2856,716,2858,2864,716,2866,2867,716,2869,2873,716,2877,2877,716,2908,2909,716,2911,2913,716,2929,2929,716,2947,2947,716,2949,2954,716,2958,2960,716,2962,2965,716,2969,2970,716,2972,2972,716,2974,2975,716,2979,2980,716,2984,2986,716,2990,3001,716,3024,3024,716,3077,3084,716,3086,3088,716,3090,3112,716,3114,3123,716,3125,3129,716,3133,3133,716,3160,3161,716,3168,3169,716,3205,3212,716,3214,3216,716,3218,3240,716,3242,3251,716,3253,3257,716,3261,3261,716,3294,3294,716,3296,3297,716,3313,3314,716,3333,3340,716,3342,3344,716,3346,3386,716,3389,3389,716,3406,3406,716,3424,3425,716,3450,3455,716,3461,3478,716,3482,3505,716,3507,3515,716,3517,3517,716,3520,3526,716,3585,3632,716,3634,3635,716,3648,3654,716,3713,3714,716,3716,3716,716,3719,3720,716,3722,3722,716,3725,3725,716,3732,3735,716,3737,3743,716,3745,3747,716,3749,3749,716,3751,3751,716,3754,3755,716,3757,3760,716,3762,3763,716,3773,3773,716,3776,3780,716,3782,3782,716,3804,3807,716,3840,3840,716,3904,3911,716,3913,3948,716,3976,3980,716,4096,4138,716,4159,4159,716,4176,4181,716,4186,4189,716,4193,4193,716,4197,4198,716,4206,4208,716,4213,4225,716,4238,4238,716,4256,4293,716,4295,4295,716,4301,4301,716,4304,4346,716,4348,4680,716,4682,4685,716,4688,4694,716,4696,4696,716,4698,4701,716,4704,4744,716,4746,4749,716,4752,4784,716,4786,4789,716,4792,4798,716,4800,4800,716,4802,4805,716,4808,4822,716,4824,4880,716,4882,4885,716,4888,4954,716,4992,5007,716,5024,5108,716,5121,5740,716,5743,5759,716,5761,5786,716,5792,5866,716,5888,5900,716,5902,5905,716,5920,5937,716,5952,5969,716,5984,5996,716,5998,6000,716,6016,6067,716,6103,6103,716,6108,6108,716,6176,6263,716,6272,6312,716,6314,6314,716,6320,6389,716,6400,6428,716,6480,6509,716,6512,6516,716,6528,6571,716,6593,6599,716,6656,6678,716,6688,6740,716,6823,6823,716,6917,6963,716,6981,6987,716,7043,7072,716,7086,7087,716,7098,7141,716,7168,7203,716,7245,7247,716,7258,7293,716,7401,7404,716,7406,7409,716,7413,7414,716,7424,7615,716,7680,7957,716,7960,7965,716,7968,8005,716,8008,8013,716,8016,8023,716,8025,8025,716,8027,8027,716,8029,8029,716,8031,8061,716,8064,8116,716,8118,8124,716,8126,8126,716,8130,8132,716,8134,8140,716,8144,8147,716,8150,8155,716,8160,8172,716,8178,8180,716,8182,8188,716,8305,8305,716,8319,8319,716,8336,8348,716,8450,8450,716,8455,8455,716,8458,8467,716,8469,8469,716,8473,8477,716,8484,8484,716,8486,8486,716,8488,8488,716,8490,8493,716,8495,8505,716,8508,8511,716,8517,8521,716,8526,8526,716,8579,8580,716,11264,11310,716,11312,11358,716,11360,11492,716,11499,11502,716,11506,11507,716,11520,11557,716,11559,11559,716,11565,11565,716,11568,11623,716,11631,11631,716,11648,11670,716,11680,11686,716,11688,11694,716,11696,11702,716,11704,11710,716,11712,11718,716,11720,11726,716,11728,11734,716,11736,11742,716,11823,11823,716,12293,12294,716,12337,12341,716,12347,12348,716,12353,12438,716,12445,12447,716,12449,12538,716,12540,12543,716,12549,12589,716,12593,12686,716,12704,12730,716,12784,12799,716,13312,13312,716,19893,19893,716,19968,19968,716,40908,40908,716,40960,42124,716,42192,42237,716,42240,42508,716,42512,42527,716,42538,42539,716,42560,42606,716,42623,42647,716,42656,42725,716,42775,42783,716,42786,42888,716,42891,42894,716,42896,42899,716,42912,42922,716,43000,43009,716,43011,43013,716,43015,43018,716,43020,43042,716,43072,43123,716,43138,43187,716,43250,43255,716,43259,43259,716,43274,43301,716,43312,43334,716,43360,43388,716,43396,43442,716,43471,43471,716,43520,43560,716,43584,43586,716,43588,43595,716,43616,43638,716,43642,43642,716,43648,43695,716,43697,43697,716,43701,43702,716,43705,43709,716,43712,43712,716,43714,43714,716,43739,43741,716,43744,43754,716,43762,43764,716,43777,43782,716,43785,43790,716,43793,43798,716,43808,43814,716,43816,43822,716,43968,44002,716,44032,44032,716,55203,55203,716,55216,55238,716,55243,55291,716,63744,64109,716,64112,64217,716,64256,64262,716,64275,64279,716,64285,64285,716,64287,64296,716,64298,64310,716,64312,64316,716,64318,64318,716,64320,64321,716,64323,64324,716,64326,64433,716,64467,64829,716,64848,64911,716,64914,64967,716,65008,65019,716,65136,65140,716,65142,65276,716,65313,65338,716,65345,65370,716,65382,65470,716,65474,65479,716,65482,65487,716,65490,65495,716,65498,65500,716,391,170,170,716,181,181,716,186,186,716,192,214,716,216,246,716,248,705,716,710,721,716,736,740,716,748,748,716,750,750,716,880,884,716,886,887,716,890,893,716,902,902,716,904,906,716,908,908,716,910,929,716,931,1013,716,1015,1153,716,1162,1319,716,1329,1366,716,1369,1369,716,1377,1415,716,1488,1514,716,1520,1522,716,1568,1610,716,1632,1641,716,1646,1647,716,1649,1747,716,1749,1749,716,1765,1766,716,1774,1788,716,1791,1791,716,1808,1808,716,1810,1839,716,1869,1957,716,1969,1969,716,1984,2026,716,2036,2037,716,2042,2042,716,2048,2069,716,2074,2074,716,2084,2084,716,2088,2088,716,2112,2136,716,2208,2208,716,2210,2220,716,2308,2361,716,2365,2365,716,2384,2384,716,2392,2401,716,2406,2415,716,2417,2423,716,2425,2431,716,2437,2444,716,2447,2448,716,2451,2472,716,2474,2480,716,2482,2482,716,2486,2489,716,2493,2493,716,2510,2510,716,2524,2525,716,2527,2529,716,2534,2545,716,2565,2570,716,2575,2576,716,2579,2600,716,2602,2608,716,2610,2611,716,2613,2614,716,2616,2617,716,2649,2652,716,2654,2654,716,2662,2671,716,2674,2676,716,2693,2701,716,2703,2705,716,2707,2728,716,2730,2736,716,2738,2739,716,2741,2745,716,2749,2749,716,2768,2768,716,2784,2785,716,2790,2799,716,2821,2828,716,2831,2832,716,2835,2856,716,2858,2864,716,2866,2867,716,2869,2873,716,2877,2877,716,2908,2909,716,2911,2913,716,2918,2927,716,2929,2929,716,2947,2947,716,2949,2954,716,2958,2960,716,2962,2965,716,2969,2970,716,2972,2972,716,2974,2975,716,2979,2980,716,2984,2986,716,2990,3001,716,3024,3024,716,3046,3055,716,3077,3084,716,3086,3088,716,3090,3112,716,3114,3123,716,3125,3129,716,3133,3133,716,3160,3161,716,3168,3169,716,3174,3183,716,3205,3212,716,3214,3216,716,3218,3240,716,3242,3251,716,3253,3257,716,3261,3261,716,3294,3294,716,3296,3297,716,3302,3311,716,3313,3314,716,3333,3340,716,3342,3344,716,3346,3386,716,3389,3389,716,3406,3406,716,3424,3425,716,3430,3439,716,3450,3455,716,3461,3478,716,3482,3505,716,3507,3515,716,3517,3517,716,3520,3526,716,3585,3632,716,3634,3635,716,3648,3654,716,3664,3673,716,3713,3714,716,3716,3716,716,3719,3720,716,3722,3722,716,3725,3725,716,3732,3735,716,3737,3743,716,3745,3747,716,3749,3749,716,3751,3751,716,3754,3755,716,3757,3760,716,3762,3763,716,3773,3773,716,3776,3780,716,3782,3782,716,3792,3801,716,3804,3807,716,3840,3840,716,3872,3881,716,3904,3911,716,3913,3948,716,3976,3980,716,4096,4138,716,4159,4169,716,4176,4181,716,4186,4189,716,4193,4193,716,4197,4198,716,4206,4208,716,4213,4225,716,4238,4238,716,4240,4249,716,4256,4293,716,4295,4295,716,4301,4301,716,4304,4346,716,4348,4680,716,4682,4685,716,4688,4694,716,4696,4696,716,4698,4701,716,4704,4744,716,4746,4749,716,4752,4784,716,4786,4789,716,4792,4798,716,4800,4800,716,4802,4805,716,4808,4822,716,4824,4880,716,4882,4885,716,4888,4954,716,4992,5007,716,5024,5108,716,5121,5740,716,5743,5759,716,5761,5786,716,5792,5866,716,5888,5900,716,5902,5905,716,5920,5937,716,5952,5969,716,5984,5996,716,5998,6000,716,6016,6067,716,6103,6103,716,6108,6108,716,6112,6121,716,6160,6169,716,6176,6263,716,6272,6312,716,6314,6314,716,6320,6389,716,6400,6428,716,6470,6509,716,6512,6516,716,6528,6571,716,6593,6599,716,6608,6617,716,6656,6678,716,6688,6740,716,6784,6793,716,6800,6809,716,6823,6823,716,6917,6963,716,6981,6987,716,6992,7001,716,7043,7072,716,7086,7141,716,7168,7203,716,7232,7241,716,7245,7293,716,7401,7404,716,7406,7409,716,7413,7414,716,7424,7615,716,7680,7957,716,7960,7965,716,7968,8005,716,8008,8013,716,8016,8023,716,8025,8025,716,8027,8027,716,8029,8029,716,8031,8061,716,8064,8116,716,8118,8124,716,8126,8126,716,8130,8132,716,8134,8140,716,8144,8147,716,8150,8155,716,8160,8172,716,8178,8180,716,8182,8188,716,8305,8305,716,8319,8319,716,8336,8348,716,8450,8450,716,8455,8455,716,8458,8467,716,8469,8469,716,8473,8477,716,8484,8484,716,8486,8486,716,8488,8488,716,8490,8493,716,8495,8505,716,8508,8511,716,8517,8521,716,8526,8526,716,8579,8580,716,11264,11310,716,11312,11358,716,11360,11492,716,11499,11502,716,11506,11507,716,11520,11557,716,11559,11559,716,11565,11565,716,11568,11623,716,11631,11631,716,11648,11670,716,11680,11686,716,11688,11694,716,11696,11702,716,11704,11710,716,11712,11718,716,11720,11726,716,11728,11734,716,11736,11742,716,11823,11823,716,12293,12294,716,12337,12341,716,12347,12348,716,12353,12438,716,12445,12447,716,12449,12538,716,12540,12543,716,12549,12589,716,12593,12686,716,12704,12730,716,12784,12799,716,13312,13312,716,19893,19893,716,19968,19968,716,40908,40908,716,40960,42124,716,42192,42237,716,42240,42508,716,42512,42539,716,42560,42606,716,42623,42647,716,42656,42725,716,42775,42783,716,42786,42888,716,42891,42894,716,42896,42899,716,42912,42922,716,43000,43009,716,43011,43013,716,43015,43018,716,43020,43042,716,43072,43123,716,43138,43187,716,43216,43225,716,43250,43255,716,43259,43259,716,43264,43301,716,43312,43334,716,43360,43388,716,43396,43442,716,43471,43481,716,43520,43560,716,43584,43586,716,43588,43595,716,43600,43609,716,43616,43638,716,43642,43642,716,43648,43695,716,43697,43697,716,43701,43702,716,43705,43709,716,43712,43712,716,43714,43714,716,43739,43741,716,43744,43754,716,43762,43764,716,43777,43782,716,43785,43790,716,43793,43798,716,43808,43814,716,43816,43822,716,43968,44002,716,44016,44025,716,44032,44032,716,55203,55203,716,55216,55238,716,55243,55291,716,63744,64109,716,64112,64217,716,64256,64262,716,64275,64279,716,64285,64285,716,64287,64296,716,64298,64310,716,64312,64316,716,64318,64318,716,64320,64321,716,64323,64324,716,64326,64433,716,64467,64829,716,64848,64911,716,64914,64967,716,65008,65019,716,65136,65140,716,65142,65276,716,65296,65305,716,65313,65338,716,65345,65370,716,65382,65470,716,65474,65479,716,65482,65487,716,65490,65495,716,65498,65500,716,1,128,1114111,723,1,128,1114111,727,371,170,170,731,181,181,731,186,186,731,192,214,731,216,246,731,248,705,731,710,721,731,736,740,731,748,748,731,750,750,731,880,884,731,886,887,731,890,893,731,902,902,731,904,906,731,908,908,731,910,929,731,931,1013,731,1015,1153,731,1162,1319,731,1329,1366,731,1369,1369,731,1377,1415,731,1488,1514,731,1520,1522,731,1568,1610,731,1646,1647,731,1649,1747,731,1749,1749,731,1765,1766,731,1774,1775,731,1786,1788,731,1791,1791,731,1808,1808,731,1810,1839,731,1869,1957,731,1969,1969,731,1994,2026,731,2036,2037,731,2042,2042,731,2048,2069,731,2074,2074,731,2084,2084,731,2088,2088,731,2112,2136,731,2208,2208,731,2210,2220,731,2308,2361,731,2365,2365,731,2384,2384,731,2392,2401,731,2417,2423,731,2425,2431,731,2437,2444,731,2447,2448,731,2451,2472,731,2474,2480,731,2482,2482,731,2486,2489,731,2493,2493,731,2510,2510,731,2524,2525,731,2527,2529,731,2544,2545,731,2565,2570,731,2575,2576,731,2579,2600,731,2602,2608,731,2610,2611,731,2613,2614,731,2616,2617,731,2649,2652,731,2654,2654,731,2674,2676,731,2693,2701,731,2703,2705,731,2707,2728,731,2730,2736,731,2738,2739,731,2741,2745,731,2749,2749,731,2768,2768,731,2784,2785,731,2821,2828,731,2831,2832,731,2835,2856,731,2858,2864,731,2866,2867,731,2869,2873,731,2877,2877,731,2908,2909,731,2911,2913,731,2929,2929,731,2947,2947,731,2949,2954,731,2958,2960,731,2962,2965,731,2969,2970,731,2972,2972,731,2974,2975,731,2979,2980,731,2984,2986,731,2990,3001,731,3024,3024,731,3077,3084,731,3086,3088,731,3090,3112,731,3114,3123,731,3125,3129,731,3133,3133,731,3160,3161,731,3168,3169,731,3205,3212,731,3214,3216,731,3218,3240,731,3242,3251,731,3253,3257,731,3261,3261,731,3294,3294,731,3296,3297,731,3313,3314,731,3333,3340,731,3342,3344,731,3346,3386,731,3389,3389,731,3406,3406,731,3424,3425,731,3450,3455,731,3461,3478,731,3482,3505,731,3507,3515,731,3517,3517,731,3520,3526,731,3585,3632,731,3634,3635,731,3648,3654,731,3713,3714,731,3716,3716,731,3719,3720,731,3722,3722,731,3725,3725,731,3732,3735,731,3737,3743,731,3745,3747,731,3749,3749,731,3751,3751,731,3754,3755,731,3757,3760,731,3762,3763,731,3773,3773,731,3776,3780,731,3782,3782,731,3804,3807,731,3840,3840,731,3904,3911,731,3913,3948,731,3976,3980,731,4096,4138,731,4159,4159,731,4176,4181,731,4186,4189,731,4193,4193,731,4197,4198,731,4206,4208,731,4213,4225,731,4238,4238,731,4256,4293,731,4295,4295,731,4301,4301,731,4304,4346,731,4348,4680,731,4682,4685,731,4688,4694,731,4696,4696,731,4698,4701,731,4704,4744,731,4746,4749,731,4752,4784,731,4786,4789,731,4792,4798,731,4800,4800,731,4802,4805,731,4808,4822,731,4824,4880,731,4882,4885,731,4888,4954,731,4992,5007,731,5024,5108,731,5121,5740,731,5743,5759,731,5761,5786,731,5792,5866,731,5888,5900,731,5902,5905,731,5920,5937,731,5952,5969,731,5984,5996,731,5998,6000,731,6016,6067,731,6103,6103,731,6108,6108,731,6176,6263,731,6272,6312,731,6314,6314,731,6320,6389,731,6400,6428,731,6480,6509,731,6512,6516,731,6528,6571,731,6593,6599,731,6656,6678,731,6688,6740,731,6823,6823,731,6917,6963,731,6981,6987,731,7043,7072,731,7086,7087,731,7098,7141,731,7168,7203,731,7245,7247,731,7258,7293,731,7401,7404,731,7406,7409,731,7413,7414,731,7424,7615,731,7680,7957,731,7960,7965,731,7968,8005,731,8008,8013,731,8016,8023,731,8025,8025,731,8027,8027,731,8029,8029,731,8031,8061,731,8064,8116,731,8118,8124,731,8126,8126,731,8130,8132,731,8134,8140,731,8144,8147,731,8150,8155,731,8160,8172,731,8178,8180,731,8182,8188,731,8305,8305,731,8319,8319,731,8336,8348,731,8450,8450,731,8455,8455,731,8458,8467,731,8469,8469,731,8473,8477,731,8484,8484,731,8486,8486,731,8488,8488,731,8490,8493,731,8495,8505,731,8508,8511,731,8517,8521,731,8526,8526,731,8579,8580,731,11264,11310,731,11312,11358,731,11360,11492,731,11499,11502,731,11506,11507,731,11520,11557,731,11559,11559,731,11565,11565,731,11568,11623,731,11631,11631,731,11648,11670,731,11680,11686,731,11688,11694,731,11696,11702,731,11704,11710,731,11712,11718,731,11720,11726,731,11728,11734,731,11736,11742,731,11823,11823,731,12293,12294,731,12337,12341,731,12347,12348,731,12353,12438,731,12445,12447,731,12449,12538,731,12540,12543,731,12549,12589,731,12593,12686,731,12704,12730,731,12784,12799,731,13312,13312,731,19893,19893,731,19968,19968,731,40908,40908,731,40960,42124,731,42192,42237,731,42240,42508,731,42512,42527,731,42538,42539,731,42560,42606,731,42623,42647,731,42656,42725,731,42775,42783,731,42786,42888,731,42891,42894,731,42896,42899,731,42912,42922,731,43000,43009,731,43011,43013,731,43015,43018,731,43020,43042,731,43072,43123,731,43138,43187,731,43250,43255,731,43259,43259,731,43274,43301,731,43312,43334,731,43360,43388,731,43396,43442,731,43471,43471,731,43520,43560,731,43584,43586,731,43588,43595,731,43616,43638,731,43642,43642,731,43648,43695,731,43697,43697,731,43701,43702,731,43705,43709,731,43712,43712,731,43714,43714,731,43739,43741,731,43744,43754,731,43762,43764,731,43777,43782,731,43785,43790,731,43793,43798,731,43808,43814,731,43816,43822,731,43968,44002,731,44032,44032,731,55203,55203,731,55216,55238,731,55243,55291,731,63744,64109,731,64112,64217,731,64256,64262,731,64275,64279,731,64285,64285,731,64287,64296,731,64298,64310,731,64312,64316,731,64318,64318,731,64320,64321,731,64323,64324,731,64326,64433,731,64467,64829,731,64848,64911,731,64914,64967,731,65008,65019,731,65136,65140,731,65142,65276,731,65313,65338,731,65345,65370,731,65382,65470,731,65474,65479,731,65482,65487,731,65490,65495,731,65498,65500,731,391,170,170,731,181,181,731,186,186,731,192,214,731,216,246,731,248,705,731,710,721,731,736,740,731,748,748,731,750,750,731,880,884,731,886,887,731,890,893,731,902,902,731,904,906,731,908,908,731,910,929,731,931,1013,731,1015,1153,731,1162,1319,731,1329,1366,731,1369,1369,731,1377,1415,731,1488,1514,731,1520,1522,731,1568,1610,731,1632,1641,731,1646,1647,731,1649,1747,731,1749,1749,731,1765,1766,731,1774,1788,731,1791,1791,731,1808,1808,731,1810,1839,731,1869,1957,731,1969,1969,731,1984,2026,731,2036,2037,731,2042,2042,731,2048,2069,731,2074,2074,731,2084,2084,731,2088,2088,731,2112,2136,731,2208,2208,731,2210,2220,731,2308,2361,731,2365,2365,731,2384,2384,731,2392,2401,731,2406,2415,731,2417,2423,731,2425,2431,731,2437,2444,731,2447,2448,731,2451,2472,731,2474,2480,731,2482,2482,731,2486,2489,731,2493,2493,731,2510,2510,731,2524,2525,731,2527,2529,731,2534,2545,731,2565,2570,731,2575,2576,731,2579,2600,731,2602,2608,731,2610,2611,731,2613,2614,731,2616,2617,731,2649,2652,731,2654,2654,731,2662,2671,731,2674,2676,731,2693,2701,731,2703,2705,731,2707,2728,731,2730,2736,731,2738,2739,731,2741,2745,731,2749,2749,731,2768,2768,731,2784,2785,731,2790,2799,731,2821,2828,731,2831,2832,731,2835,2856,731,2858,2864,731,2866,2867,731,2869,2873,731,2877,2877,731,2908,2909,731,2911,2913,731,2918,2927,731,2929,2929,731,2947,2947,731,2949,2954,731,2958,2960,731,2962,2965,731,2969,2970,731,2972,2972,731,2974,2975,731,2979,2980,731,2984,2986,731,2990,3001,731,3024,3024,731,3046,3055,731,3077,3084,731,3086,3088,731,3090,3112,731,3114,3123,731,3125,3129,731,3133,3133,731,3160,3161,731,3168,3169,731,3174,3183,731,3205,3212,731,3214,3216,731,3218,3240,731,3242,3251,731,3253,3257,731,3261,3261,731,3294,3294,731,3296,3297,731,3302,3311,731,3313,3314,731,3333,3340,731,3342,3344,731,3346,3386,731,3389,3389,731,3406,3406,731,3424,3425,731,3430,3439,731,3450,3455,731,3461,3478,731,3482,3505,731,3507,3515,731,3517,3517,731,3520,3526,731,3585,3632,731,3634,3635,731,3648,3654,731,3664,3673,731,3713,3714,731,3716,3716,731,3719,3720,731,3722,3722,731,3725,3725,731,3732,3735,731,3737,3743,731,3745,3747,731,3749,3749,731,3751,3751,731,3754,3755,731,3757,3760,731,3762,3763,731,3773,3773,731,3776,3780,731,3782,3782,731,3792,3801,731,3804,3807,731,3840,3840,731,3872,3881,731,3904,3911,731,3913,3948,731,3976,3980,731,4096,4138,731,4159,4169,731,4176,4181,731,4186,4189,731,4193,4193,731,4197,4198,731,4206,4208,731,4213,4225,731,4238,4238,731,4240,4249,731,4256,4293,731,4295,4295,731,4301,4301,731,4304,4346,731,4348,4680,731,4682,4685,731,4688,4694,731,4696,4696,731,4698,4701,731,4704,4744,731,4746,4749,731,4752,4784,731,4786,4789,731,4792,4798,731,4800,4800,731,4802,4805,731,4808,4822,731,4824,4880,731,4882,4885,731,4888,4954,731,4992,5007,731,5024,5108,731,5121,5740,731,5743,5759,731,5761,5786,731,5792,5866,731,5888,5900,731,5902,5905,731,5920,5937,731,5952,5969,731,5984,5996,731,5998,6000,731,6016,6067,731,6103,6103,731,6108,6108,731,6112,6121,731,6160,6169,731,6176,6263,731,6272,6312,731,6314,6314,731,6320,6389,731,6400,6428,731,6470,6509,731,6512,6516,731,6528,6571,731,6593,6599,731,6608,6617,731,6656,6678,731,6688,6740,731,6784,6793,731,6800,6809,731,6823,6823,731,6917,6963,731,6981,6987,731,6992,7001,731,7043,7072,731,7086,7141,731,7168,7203,731,7232,7241,731,7245,7293,731,7401,7404,731,7406,7409,731,7413,7414,731,7424,7615,731,7680,7957,731,7960,7965,731,7968,8005,731,8008,8013,731,8016,8023,731,8025,8025,731,8027,8027,731,8029,8029,731,8031,8061,731,8064,8116,731,8118,8124,731,8126,8126,731,8130,8132,731,8134,8140,731,8144,8147,731,8150,8155,731,8160,8172,731,8178,8180,731,8182,8188,731,8305,8305,731,8319,8319,731,8336,8348,731,8450,8450,731,8455,8455,731,8458,8467,731,8469,8469,731,8473,8477,731,8484,8484,731,8486,8486,731,8488,8488,731,8490,8493,731,8495,8505,731,8508,8511,731,8517,8521,731,8526,8526,731,8579,8580,731,11264,11310,731,11312,11358,731,11360,11492,731,11499,11502,731,11506,11507,731,11520,11557,731,11559,11559,731,11565,11565,731,11568,11623,731,11631,11631,731,11648,11670,731,11680,11686,731,11688,11694,731,11696,11702,731,11704,11710,731,11712,11718,731,11720,11726,731,11728,11734,731,11736,11742,731,11823,11823,731,12293,12294,731,12337,12341,731,12347,12348,731,12353,12438,731,12445,12447,731,12449,12538,731,12540,12543,731,12549,12589,731,12593,12686,731,12704,12730,731,12784,12799,731,13312,13312,731,19893,19893,731,19968,19968,731,40908,40908,731,40960,42124,731,42192,42237,731,42240,42508,731,42512,42539,731,42560,42606,731,42623,42647,731,42656,42725,731,42775,42783,731,42786,42888,731,42891,42894,731,42896,42899,731,42912,42922,731,43000,43009,731,43011,43013,731,43015,43018,731,43020,43042,731,43072,43123,731,43138,43187,731,43216,43225,731,43250,43255,731,43259,43259,731,43264,43301,731,43312,43334,731,43360,43388,731,43396,43442,731,43471,43481,731,43520,43560,731,43584,43586,731,43588,43595,731,43600,43609,731,43616,43638,731,43642,43642,731,43648,43695,731,43697,43697,731,43701,43702,731,43705,43709,731,43712,43712,731,43714,43714,731,43739,43741,731,43744,43754,731,43762,43764,731,43777,43782,731,43785,43790,731,43793,43798,731,43808,43814,731,43816,43822,731,43968,44002,731,44016,44025,731,44032,44032,731,55203,55203,731,55216,55238,731,55243,55291,731,63744,64109,731,64112,64217,731,64256,64262,731,64275,64279,731,64285,64285,731,64287,64296,731,64298,64310,731,64312,64316,731,64318,64318,731,64320,64321,731,64323,64324,731,64326,64433,731,64467,64829,731,64848,64911,731,64914,64967,731,65008,65019,731,65136,65140,731,65142,65276,731,65296,65305,731,65313,65338,731,65345,65370,731,65382,65470,731,65474,65479,731,65482,65487,731,65490,65495,731,65498,65500,731,1,128,1114111,753,1,128,1114111,940,371,170,170,944,181,181,944,186,186,944,192,214,944,216,246,944,248,705,944,710,721,944,736,740,944,748,748,944,750,750,944,880,884,944,886,887,944,890,893,944,902,902,944,904,906,944,908,908,944,910,929,944,931,1013,944,1015,1153,944,1162,1319,944,1329,1366,944,1369,1369,944,1377,1415,944,1488,1514,944,1520,1522,944,1568,1610,944,1646,1647,944,1649,1747,944,1749,1749,944,1765,1766,944,1774,1775,944,1786,1788,944,1791,1791,944,1808,1808,944,1810,1839,944,1869,1957,944,1969,1969,944,1994,2026,944,2036,2037,944,2042,2042,944,2048,2069,944,2074,2074,944,2084,2084,944,2088,2088,944,2112,2136,944,2208,2208,944,2210,2220,944,2308,2361,944,2365,2365,944,2384,2384,944,2392,2401,944,2417,2423,944,2425,2431,944,2437,2444,944,2447,2448,944,2451,2472,944,2474,2480,944,2482,2482,944,2486,2489,944,2493,2493,944,2510,2510,944,2524,2525,944,2527,2529,944,2544,2545,944,2565,2570,944,2575,2576,944,2579,2600,944,2602,2608,944,2610,2611,944,2613,2614,944,2616,2617,944,2649,2652,944,2654,2654,944,2674,2676,944,2693,2701,944,2703,2705,944,2707,2728,944,2730,2736,944,2738,2739,944,2741,2745,944,2749,2749,944,2768,2768,944,2784,2785,944,2821,2828,944,2831,2832,944,2835,2856,944,2858,2864,944,2866,2867,944,2869,2873,944,2877,2877,944,2908,2909,944,2911,2913,944,2929,2929,944,2947,2947,944,2949,2954,944,2958,2960,944,2962,2965,944,2969,2970,944,2972,2972,944,2974,2975,944,2979,2980,944,2984,2986,944,2990,3001,944,3024,3024,944,3077,3084,944,3086,3088,944,3090,3112,944,3114,3123,944,3125,3129,944,3133,3133,944,3160,3161,944,3168,3169,944,3205,3212,944,3214,3216,944,3218,3240,944,3242,3251,944,3253,3257,944,3261,3261,944,3294,3294,944,3296,3297,944,3313,3314,944,3333,3340,944,3342,3344,944,3346,3386,944,3389,3389,944,3406,3406,944,3424,3425,944,3450,3455,944,3461,3478,944,3482,3505,944,3507,3515,944,3517,3517,944,3520,3526,944,3585,3632,944,3634,3635,944,3648,3654,944,3713,3714,944,3716,3716,944,3719,3720,944,3722,3722,944,3725,3725,944,3732,3735,944,3737,3743,944,3745,3747,944,3749,3749,944,3751,3751,944,3754,3755,944,3757,3760,944,3762,3763,944,3773,3773,944,3776,3780,944,3782,3782,944,3804,3807,944,3840,3840,944,3904,3911,944,3913,3948,944,3976,3980,944,4096,4138,944,4159,4159,944,4176,4181,944,4186,4189,944,4193,4193,944,4197,4198,944,4206,4208,944,4213,4225,944,4238,4238,944,4256,4293,944,4295,4295,944,4301,4301,944,4304,4346,944,4348,4680,944,4682,4685,944,4688,4694,944,4696,4696,944,4698,4701,944,4704,4744,944,4746,4749,944,4752,4784,944,4786,4789,944,4792,4798,944,4800,4800,944,4802,4805,944,4808,4822,944,4824,4880,944,4882,4885,944,4888,4954,944,4992,5007,944,5024,5108,944,5121,5740,944,5743,5759,944,5761,5786,944,5792,5866,944,5888,5900,944,5902,5905,944,5920,5937,944,5952,5969,944,5984,5996,944,5998,6000,944,6016,6067,944,6103,6103,944,6108,6108,944,6176,6263,944,6272,6312,944,6314,6314,944,6320,6389,944,6400,6428,944,6480,6509,944,6512,6516,944,6528,6571,944,6593,6599,944,6656,6678,944,6688,6740,944,6823,6823,944,6917,6963,944,6981,6987,944,7043,7072,944,7086,7087,944,7098,7141,944,7168,7203,944,7245,7247,944,7258,7293,944,7401,7404,944,7406,7409,944,7413,7414,944,7424,7615,944,7680,7957,944,7960,7965,944,7968,8005,944,8008,8013,944,8016,8023,944,8025,8025,944,8027,8027,944,8029,8029,944,8031,8061,944,8064,8116,944,8118,8124,944,8126,8126,944,8130,8132,944,8134,8140,944,8144,8147,944,8150,8155,944,8160,8172,944,8178,8180,944,8182,8188,944,8305,8305,944,8319,8319,944,8336,8348,944,8450,8450,944,8455,8455,944,8458,8467,944,8469,8469,944,8473,8477,944,8484,8484,944,8486,8486,944,8488,8488,944,8490,8493,944,8495,8505,944,8508,8511,944,8517,8521,944,8526,8526,944,8579,8580,944,11264,11310,944,11312,11358,944,11360,11492,944,11499,11502,944,11506,11507,944,11520,11557,944,11559,11559,944,11565,11565,944,11568,11623,944,11631,11631,944,11648,11670,944,11680,11686,944,11688,11694,944,11696,11702,944,11704,11710,944,11712,11718,944,11720,11726,944,11728,11734,944,11736,11742,944,11823,11823,944,12293,12294,944,12337,12341,944,12347,12348,944,12353,12438,944,12445,12447,944,12449,12538,944,12540,12543,944,12549,12589,944,12593,12686,944,12704,12730,944,12784,12799,944,13312,13312,944,19893,19893,944,19968,19968,944,40908,40908,944,40960,42124,944,42192,42237,944,42240,42508,944,42512,42527,944,42538,42539,944,42560,42606,944,42623,42647,944,42656,42725,944,42775,42783,944,42786,42888,944,42891,42894,944,42896,42899,944,42912,42922,944,43000,43009,944,43011,43013,944,43015,43018,944,43020,43042,944,43072,43123,944,43138,43187,944,43250,43255,944,43259,43259,944,43274,43301,944,43312,43334,944,43360,43388,944,43396,43442,944,43471,43471,944,43520,43560,944,43584,43586,944,43588,43595,944,43616,43638,944,43642,43642,944,43648,43695,944,43697,43697,944,43701,43702,944,43705,43709,944,43712,43712,944,43714,43714,944,43739,43741,944,43744,43754,944,43762,43764,944,43777,43782,944,43785,43790,944,43793,43798,944,43808,43814,944,43816,43822,944,43968,44002,944,44032,44032,944,55203,55203,944,55216,55238,944,55243,55291,944,63744,64109,944,64112,64217,944,64256,64262,944,64275,64279,944,64285,64285,944,64287,64296,944,64298,64310,944,64312,64316,944,64318,64318,944,64320,64321,944,64323,64324,944,64326,64433,944,64467,64829,944,64848,64911,944,64914,64967,944,65008,65019,944,65136,65140,944,65142,65276,944,65313,65338,944,65345,65370,944,65382,65470,944,65474,65479,944,65482,65487,944,65490,65495,944,65498,65500,944,391,170,170,944,181,181,944,186,186,944,192,214,944,216,246,944,248,705,944,710,721,944,736,740,944,748,748,944,750,750,944,880,884,944,886,887,944,890,893,944,902,902,944,904,906,944,908,908,944,910,929,944,931,1013,944,1015,1153,944,1162,1319,944,1329,1366,944,1369,1369,944,1377,1415,944,1488,1514,944,1520,1522,944,1568,1610,944,1632,1641,944,1646,1647,944,1649,1747,944,1749,1749,944,1765,1766,944,1774,1788,944,1791,1791,944,1808,1808,944,1810,1839,944,1869,1957,944,1969,1969,944,1984,2026,944,2036,2037,944,2042,2042,944,2048,2069,944,2074,2074,944,2084,2084,944,2088,2088,944,2112,2136,944,2208,2208,944,2210,2220,944,2308,2361,944,2365,2365,944,2384,2384,944,2392,2401,944,2406,2415,944,2417,2423,944,2425,2431,944,2437,2444,944,2447,2448,944,2451,2472,944,2474,2480,944,2482,2482,944,2486,2489,944,2493,2493,944,2510,2510,944,2524,2525,944,2527,2529,944,2534,2545,944,2565,2570,944,2575,2576,944,2579,2600,944,2602,2608,944,2610,2611,944,2613,2614,944,2616,2617,944,2649,2652,944,2654,2654,944,2662,2671,944,2674,2676,944,2693,2701,944,2703,2705,944,2707,2728,944,2730,2736,944,2738,2739,944,2741,2745,944,2749,2749,944,2768,2768,944,2784,2785,944,2790,2799,944,2821,2828,944,2831,2832,944,2835,2856,944,2858,2864,944,2866,2867,944,2869,2873,944,2877,2877,944,2908,2909,944,2911,2913,944,2918,2927,944,2929,2929,944,2947,2947,944,2949,2954,944,2958,2960,944,2962,2965,944,2969,2970,944,2972,2972,944,2974,2975,944,2979,2980,944,2984,2986,944,2990,3001,944,3024,3024,944,3046,3055,944,3077,3084,944,3086,3088,944,3090,3112,944,3114,3123,944,3125,3129,944,3133,3133,944,3160,3161,944,3168,3169,944,3174,3183,944,3205,3212,944,3214,3216,944,3218,3240,944,3242,3251,944,3253,3257,944,3261,3261,944,3294,3294,944,3296,3297,944,3302,3311,944,3313,3314,944,3333,3340,944,3342,3344,944,3346,3386,944,3389,3389,944,3406,3406,944,3424,3425,944,3430,3439,944,3450,3455,944,3461,3478,944,3482,3505,944,3507,3515,944,3517,3517,944,3520,3526,944,3585,3632,944,3634,3635,944,3648,3654,944,3664,3673,944,3713,3714,944,3716,3716,944,3719,3720,944,3722,3722,944,3725,3725,944,3732,3735,944,3737,3743,944,3745,3747,944,3749,3749,944,3751,3751,944,3754,3755,944,3757,3760,944,3762,3763,944,3773,3773,944,3776,3780,944,3782,3782,944,3792,3801,944,3804,3807,944,3840,3840,944,3872,3881,944,3904,3911,944,3913,3948,944,3976,3980,944,4096,4138,944,4159,4169,944,4176,4181,944,4186,4189,944,4193,4193,944,4197,4198,944,4206,4208,944,4213,4225,944,4238,4238,944,4240,4249,944,4256,4293,944,4295,4295,944,4301,4301,944,4304,4346,944,4348,4680,944,4682,4685,944,4688,4694,944,4696,4696,944,4698,4701,944,4704,4744,944,4746,4749,944,4752,4784,944,4786,4789,944,4792,4798,944,4800,4800,944,4802,4805,944,4808,4822,944,4824,4880,944,4882,4885,944,4888,4954,944,4992,5007,944,5024,5108,944,5121,5740,944,5743,5759,944,5761,5786,944,5792,5866,944,5888,5900,944,5902,5905,944,5920,5937,944,5952,5969,944,5984,5996,944,5998,6000,944,6016,6067,944,6103,6103,944,6108,6108,944,6112,6121,944,6160,6169,944,6176,6263,944,6272,6312,944,6314,6314,944,6320,6389,944,6400,6428,944,6470,6509,944,6512,6516,944,6528,6571,944,6593,6599,944,6608,6617,944,6656,6678,944,6688,6740,944,6784,6793,944,6800,6809,944,6823,6823,944,6917,6963,944,6981,6987,944,6992,7001,944,7043,7072,944,7086,7141,944,7168,7203,944,7232,7241,944,7245,7293,944,7401,7404,944,7406,7409,944,7413,7414,944,7424,7615,944,7680,7957,944,7960,7965,944,7968,8005,944,8008,8013,944,8016,8023,944,8025,8025,944,8027,8027,944,8029,8029,944,8031,8061,944,8064,8116,944,8118,8124,944,8126,8126,944,8130,8132,944,8134,8140,944,8144,8147,944,8150,8155,944,8160,8172,944,8178,8180,944,8182,8188,944,8305,8305,944,8319,8319,944,8336,8348,944,8450,8450,944,8455,8455,944,8458,8467,944,8469,8469,944,8473,8477,944,8484,8484,944,8486,8486,944,8488,8488,944,8490,8493,944,8495,8505,944,8508,8511,944,8517,8521,944,8526,8526,944,8579,8580,944,11264,11310,944,11312,11358,944,11360,11492,944,11499,11502,944,11506,11507,944,11520,11557,944,11559,11559,944,11565,11565,944,11568,11623,944,11631,11631,944,11648,11670,944,11680,11686,944,11688,11694,944,11696,11702,944,11704,11710,944,11712,11718,944,11720,11726,944,11728,11734,944,11736,11742,944,11823,11823,944,12293,12294,944,12337,12341,944,12347,12348,944,12353,12438,944,12445,12447,944,12449,12538,944,12540,12543,944,12549,12589,944,12593,12686,944,12704,12730,944,12784,12799,944,13312,13312,944,19893,19893,944,19968,19968,944,40908,40908,944,40960,42124,944,42192,42237,944,42240,42508,944,42512,42539,944,42560,42606,944,42623,42647,944,42656,42725,944,42775,42783,944,42786,42888,944,42891,42894,944,42896,42899,944,42912,42922,944,43000,43009,944,43011,43013,944,43015,43018,944,43020,43042,944,43072,43123,944,43138,43187,944,43216,43225,944,43250,43255,944,43259,43259,944,43264,43301,944,43312,43334,944,43360,43388,944,43396,43442,944,43471,43481,944,43520,43560,944,43584,43586,944,43588,43595,944,43600,43609,944,43616,43638,944,43642,43642,944,43648,43695,944,43697,43697,944,43701,43702,944,43705,43709,944,43712,43712,944,43714,43714,944,43739,43741,944,43744,43754,944,43762,43764,944,43777,43782,944,43785,43790,944,43793,43798,944,43808,43814,944,43816,43822,944,43968,44002,944,44016,44025,944,44032,44032,944,55203,55203,944,55216,55238,944,55243,55291,944,63744,64109,944,64112,64217,944,64256,64262,944,64275,64279,944,64285,64285,944,64287,64296,944,64298,64310,944,64312,64316,944,64318,64318,944,64320,64321,944,64323,64324,944,64326,64433,944,64467,64829,944,64848,64911,944,64914,64967,944,65008,65019,944,65136,65140,944,65142,65276,944,65296,65305,944,65313,65338,944,65345,65370,944,65382,65470,944,65474,65479,944,65482,65487,944,65490,65495,944,65498,65500,944,1,128,1114111,965,371,170,170,1175,181,181,1175,186,186,1175,192,214,1175,216,246,1175,248,705,1175,710,721,1175,736,740,1175,748,748,1175,750,750,1175,880,884,1175,886,887,1175,890,893,1175,902,902,1175,904,906,1175,908,908,1175,910,929,1175,931,1013,1175,1015,1153,1175,1162,1319,1175,1329,1366,1175,1369,1369,1175,1377,1415,1175,1488,1514,1175,1520,1522,1175,1568,1610,1175,1646,1647,1175,1649,1747,1175,1749,1749,1175,1765,1766,1175,1774,1775,1175,1786,1788,1175,1791,1791,1175,1808,1808,1175,1810,1839,1175,1869,1957,1175,1969,1969,1175,1994,2026,1175,2036,2037,1175,2042,2042,1175,2048,2069,1175,2074,2074,1175,2084,2084,1175,2088,2088,1175,2112,2136,1175,2208,2208,1175,2210,2220,1175,2308,2361,1175,2365,2365,1175,2384,2384,1175,2392,2401,1175,2417,2423,1175,2425,2431,1175,2437,2444,1175,2447,2448,1175,2451,2472,1175,2474,2480,1175,2482,2482,1175,2486,2489,1175,2493,2493,1175,2510,2510,1175,2524,2525,1175,2527,2529,1175,2544,2545,1175,2565,2570,1175,2575,2576,1175,2579,2600,1175,2602,2608,1175,2610,2611,1175,2613,2614,1175,2616,2617,1175,2649,2652,1175,2654,2654,1175,2674,2676,1175,2693,2701,1175,2703,2705,1175,2707,2728,1175,2730,2736,1175,2738,2739,1175,2741,2745,1175,2749,2749,1175,2768,2768,1175,2784,2785,1175,2821,2828,1175,2831,2832,1175,2835,2856,1175,2858,2864,1175,2866,2867,1175,2869,2873,1175,2877,2877,1175,2908,2909,1175,2911,2913,1175,2929,2929,1175,2947,2947,1175,2949,2954,1175,2958,2960,1175,2962,2965,1175,2969,2970,1175,2972,2972,1175,2974,2975,1175,2979,2980,1175,2984,2986,1175,2990,3001,1175,3024,3024,1175,3077,3084,1175,3086,3088,1175,3090,3112,1175,3114,3123,1175,3125,3129,1175,3133,3133,1175,3160,3161,1175,3168,3169,1175,3205,3212,1175,3214,3216,1175,3218,3240,1175,3242,3251,1175,3253,3257,1175,3261,3261,1175,3294,3294,1175,3296,3297,1175,3313,3314,1175,3333,3340,1175,3342,3344,1175,3346,3386,1175,3389,3389,1175,3406,3406,1175,3424,3425,1175,3450,3455,1175,3461,3478,1175,3482,3505,1175,3507,3515,1175,3517,3517,1175,3520,3526,1175,3585,3632,1175,3634,3635,1175,3648,3654,1175,3713,3714,1175,3716,3716,1175,3719,3720,1175,3722,3722,1175,3725,3725,1175,3732,3735,1175,3737,3743,1175,3745,3747,1175,3749,3749,1175,3751,3751,1175,3754,3755,1175,3757,3760,1175,3762,3763,1175,3773,3773,1175,3776,3780,1175,3782,3782,1175,3804,3807,1175,3840,3840,1175,3904,3911,1175,3913,3948,1175,3976,3980,1175,4096,4138,1175,4159,4159,1175,4176,4181,1175,4186,4189,1175,4193,4193,1175,4197,4198,1175,4206,4208,1175,4213,4225,1175,4238,4238,1175,4256,4293,1175,4295,4295,1175,4301,4301,1175,4304,4346,1175,4348,4680,1175,4682,4685,1175,4688,4694,1175,4696,4696,1175,4698,4701,1175,4704,4744,1175,4746,4749,1175,4752,4784,1175,4786,4789,1175,4792,4798,1175,4800,4800,1175,4802,4805,1175,4808,4822,1175,4824,4880,1175,4882,4885,1175,4888,4954,1175,4992,5007,1175,5024,5108,1175,5121,5740,1175,5743,5759,1175,5761,5786,1175,5792,5866,1175,5888,5900,1175,5902,5905,1175,5920,5937,1175,5952,5969,1175,5984,5996,1175,5998,6000,1175,6016,6067,1175,6103,6103,1175,6108,6108,1175,6176,6263,1175,6272,6312,1175,6314,6314,1175,6320,6389,1175,6400,6428,1175,6480,6509,1175,6512,6516,1175,6528,6571,1175,6593,6599,1175,6656,6678,1175,6688,6740,1175,6823,6823,1175,6917,6963,1175,6981,6987,1175,7043,7072,1175,7086,7087,1175,7098,7141,1175,7168,7203,1175,7245,7247,1175,7258,7293,1175,7401,7404,1175,7406,7409,1175,7413,7414,1175,7424,7615,1175,7680,7957,1175,7960,7965,1175,7968,8005,1175,8008,8013,1175,8016,8023,1175,8025,8025,1175,8027,8027,1175,8029,8029,1175,8031,8061,1175,8064,8116,1175,8118,8124,1175,8126,8126,1175,8130,8132,1175,8134,8140,1175,8144,8147,1175,8150,8155,1175,8160,8172,1175,8178,8180,1175,8182,8188,1175,8305,8305,1175,8319,8319,1175,8336,8348,1175,8450,8450,1175,8455,8455,1175,8458,8467,1175,8469,8469,1175,8473,8477,1175,8484,8484,1175,8486,8486,1175,8488,8488,1175,8490,8493,1175,8495,8505,1175,8508,8511,1175,8517,8521,1175,8526,8526,1175,8579,8580,1175,11264,11310,1175,11312,11358,1175,11360,11492,1175,11499,11502,1175,11506,11507,1175,11520,11557,1175,11559,11559,1175,11565,11565,1175,11568,11623,1175,11631,11631,1175,11648,11670,1175,11680,11686,1175,11688,11694,1175,11696,11702,1175,11704,11710,1175,11712,11718,1175,11720,11726,1175,11728,11734,1175,11736,11742,1175,11823,11823,1175,12293,12294,1175,12337,12341,1175,12347,12348,1175,12353,12438,1175,12445,12447,1175,12449,12538,1175,12540,12543,1175,12549,12589,1175,12593,12686,1175,12704,12730,1175,12784,12799,1175,13312,13312,1175,19893,19893,1175,19968,19968,1175,40908,40908,1175,40960,42124,1175,42192,42237,1175,42240,42508,1175,42512,42527,1175,42538,42539,1175,42560,42606,1175,42623,42647,1175,42656,42725,1175,42775,42783,1175,42786,42888,1175,42891,42894,1175,42896,42899,1175,42912,42922,1175,43000,43009,1175,43011,43013,1175,43015,43018,1175,43020,43042,1175,43072,43123,1175,43138,43187,1175,43250,43255,1175,43259,43259,1175,43274,43301,1175,43312,43334,1175,43360,43388,1175,43396,43442,1175,43471,43471,1175,43520,43560,1175,43584,43586,1175,43588,43595,1175,43616,43638,1175,43642,43642,1175,43648,43695,1175,43697,43697,1175,43701,43702,1175,43705,43709,1175,43712,43712,1175,43714,43714,1175,43739,43741,1175,43744,43754,1175,43762,43764,1175,43777,43782,1175,43785,43790,1175,43793,43798,1175,43808,43814,1175,43816,43822,1175,43968,44002,1175,44032,44032,1175,55203,55203,1175,55216,55238,1175,55243,55291,1175,63744,64109,1175,64112,64217,1175,64256,64262,1175,64275,64279,1175,64285,64285,1175,64287,64296,1175,64298,64310,1175,64312,64316,1175,64318,64318,1175,64320,64321,1175,64323,64324,1175,64326,64433,1175,64467,64829,1175,64848,64911,1175,64914,64967,1175,65008,65019,1175,65136,65140,1175,65142,65276,1175,65313,65338,1175,65345,65370,1175,65382,65470,1175,65474,65479,1175,65482,65487,1175,65490,65495,1175,65498,65500,1175,1,128,1114111,1208,391,170,170,1175,181,181,1175,186,186,1175,192,214,1175,216,246,1175,248,705,1175,710,721,1175,736,740,1175,748,748,1175,750,750,1175,880,884,1175,886,887,1175,890,893,1175,902,902,1175,904,906,1175,908,908,1175,910,929,1175,931,1013,1175,1015,1153,1175,1162,1319,1175,1329,1366,1175,1369,1369,1175,1377,1415,1175,1488,1514,1175,1520,1522,1175,1568,1610,1175,1632,1641,1175,1646,1647,1175,1649,1747,1175,1749,1749,1175,1765,1766,1175,1774,1788,1175,1791,1791,1175,1808,1808,1175,1810,1839,1175,1869,1957,1175,1969,1969,1175,1984,2026,1175,2036,2037,1175,2042,2042,1175,2048,2069,1175,2074,2074,1175,2084,2084,1175,2088,2088,1175,2112,2136,1175,2208,2208,1175,2210,2220,1175,2308,2361,1175,2365,2365,1175,2384,2384,1175,2392,2401,1175,2406,2415,1175,2417,2423,1175,2425,2431,1175,2437,2444,1175,2447,2448,1175,2451,2472,1175,2474,2480,1175,2482,2482,1175,2486,2489,1175,2493,2493,1175,2510,2510,1175,2524,2525,1175,2527,2529,1175,2534,2545,1175,2565,2570,1175,2575,2576,1175,2579,2600,1175,2602,2608,1175,2610,2611,1175,2613,2614,1175,2616,2617,1175,2649,2652,1175,2654,2654,1175,2662,2671,1175,2674,2676,1175,2693,2701,1175,2703,2705,1175,2707,2728,1175,2730,2736,1175,2738,2739,1175,2741,2745,1175,2749,2749,1175,2768,2768,1175,2784,2785,1175,2790,2799,1175,2821,2828,1175,2831,2832,1175,2835,2856,1175,2858,2864,1175,2866,2867,1175,2869,2873,1175,2877,2877,1175,2908,2909,1175,2911,2913,1175,2918,2927,1175,2929,2929,1175,2947,2947,1175,2949,2954,1175,2958,2960,1175,2962,2965,1175,2969,2970,1175,2972,2972,1175,2974,2975,1175,2979,2980,1175,2984,2986,1175,2990,3001,1175,3024,3024,1175,3046,3055,1175,3077,3084,1175,3086,3088,1175,3090,3112,1175,3114,3123,1175,3125,3129,1175,3133,3133,1175,3160,3161,1175,3168,3169,1175,3174,3183,1175,3205,3212,1175,3214,3216,1175,3218,3240,1175,3242,3251,1175,3253,3257,1175,3261,3261,1175,3294,3294,1175,3296,3297,1175,3302,3311,1175,3313,3314,1175,3333,3340,1175,3342,3344,1175,3346,3386,1175,3389,3389,1175,3406,3406,1175,3424,3425,1175,3430,3439,1175,3450,3455,1175,3461,3478,1175,3482,3505,1175,3507,3515,1175,3517,3517,1175,3520,3526,1175,3585,3632,1175,3634,3635,1175,3648,3654,1175,3664,3673,1175,3713,3714,1175,3716,3716,1175,3719,3720,1175,3722,3722,1175,3725,3725,1175,3732,3735,1175,3737,3743,1175,3745,3747,1175,3749,3749,1175,3751,3751,1175,3754,3755,1175,3757,3760,1175,3762,3763,1175,3773,3773,1175,3776,3780,1175,3782,3782,1175,3792,3801,1175,3804,3807,1175,3840,3840,1175,3872,3881,1175,3904,3911,1175,3913,3948,1175,3976,3980,1175,4096,4138,1175,4159,4169,1175,4176,4181,1175,4186,4189,1175,4193,4193,1175,4197,4198,1175,4206,4208,1175,4213,4225,1175,4238,4238,1175,4240,4249,1175,4256,4293,1175,4295,4295,1175,4301,4301,1175,4304,4346,1175,4348,4680,1175,4682,4685,1175,4688,4694,1175,4696,4696,1175,4698,4701,1175,4704,4744,1175,4746,4749,1175,4752,4784,1175,4786,4789,1175,4792,4798,1175,4800,4800,1175,4802,4805,1175,4808,4822,1175,4824,4880,1175,4882,4885,1175,4888,4954,1175,4992,5007,1175,5024,5108,1175,5121,5740,1175,5743,5759,1175,5761,5786,1175,5792,5866,1175,5888,5900,1175,5902,5905,1175,5920,5937,1175,5952,5969,1175,5984,5996,1175,5998,6000,1175,6016,6067,1175,6103,6103,1175,6108,6108,1175,6112,6121,1175,6160,6169,1175,6176,6263,1175,6272,6312,1175,6314,6314,1175,6320,6389,1175,6400,6428,1175,6470,6509,1175,6512,6516,1175,6528,6571,1175,6593,6599,1175,6608,6617,1175,6656,6678,1175,6688,6740,1175,6784,6793,1175,6800,6809,1175,6823,6823,1175,6917,6963,1175,6981,6987,1175,6992,7001,1175,7043,7072,1175,7086,7141,1175,7168,7203,1175,7232,7241,1175,7245,7293,1175,7401,7404,1175,7406,7409,1175,7413,7414,1175,7424,7615,1175,7680,7957,1175,7960,7965,1175,7968,8005,1175,8008,8013,1175,8016,8023,1175,8025,8025,1175,8027,8027,1175,8029,8029,1175,8031,8061,1175,8064,8116,1175,8118,8124,1175,8126,8126,1175,8130,8132,1175,8134,8140,1175,8144,8147,1175,8150,8155,1175,8160,8172,1175,8178,8180,1175,8182,8188,1175,8305,8305,1175,8319,8319,1175,8336,8348,1175,8450,8450,1175,8455,8455,1175,8458,8467,1175,8469,8469,1175,8473,8477,1175,8484,8484,1175,8486,8486,1175,8488,8488,1175,8490,8493,1175,8495,8505,1175,8508,8511,1175,8517,8521,1175,8526,8526,1175,8579,8580,1175,11264,11310,1175,11312,11358,1175,11360,11492,1175,11499,11502,1175,11506,11507,1175,11520,11557,1175,11559,11559,1175,11565,11565,1175,11568,11623,1175,11631,11631,1175,11648,11670,1175,11680,11686,1175,11688,11694,1175,11696,11702,1175,11704,11710,1175,11712,11718,1175,11720,11726,1175,11728,11734,1175,11736,11742,1175,11823,11823,1175,12293,12294,1175,12337,12341,1175,12347,12348,1175,12353,12438,1175,12445,12447,1175,12449,12538,1175,12540,12543,1175,12549,12589,1175,12593,12686,1175,12704,12730,1175,12784,12799,1175,13312,13312,1175,19893,19893,1175,19968,19968,1175,40908,40908,1175,40960,42124,1175,42192,42237,1175,42240,42508,1175,42512,42539,1175,42560,42606,1175,42623,42647,1175,42656,42725,1175,42775,42783,1175,42786,42888,1175,42891,42894,1175,42896,42899,1175,42912,42922,1175,43000,43009,1175,43011,43013,1175,43015,43018,1175,43020,43042,1175,43072,43123,1175,43138,43187,1175,43216,43225,1175,43250,43255,1175,43259,43259,1175,43264,43301,1175,43312,43334,1175,43360,43388,1175,43396,43442,1175,43471,43481,1175,43520,43560,1175,43584,43586,1175,43588,43595,1175,43600,43609,1175,43616,43638,1175,43642,43642,1175,43648,43695,1175,43697,43697,1175,43701,43702,1175,43705,43709,1175,43712,43712,1175,43714,43714,1175,43739,43741,1175,43744,43754,1175,43762,43764,1175,43777,43782,1175,43785,43790,1175,43793,43798,1175,43808,43814,1175,43816,43822,1175,43968,44002,1175,44016,44025,1175,44032,44032,1175,55203,55203,1175,55216,55238,1175,55243,55291,1175,63744,64109,1175,64112,64217,1175,64256,64262,1175,64275,64279,1175,64285,64285,1175,64287,64296,1175,64298,64310,1175,64312,64316,1175,64318,64318,1175,64320,64321,1175,64323,64324,1175,64326,64433,1175,64467,64829,1175,64848,64911,1175,64914,64967,1175,65008,65019,1175,65136,65140,1175,65142,65276,1175,65296,65305,1175,65313,65338,1175,65345,65370,1175,65382,65470,1175,65474,65479,1175,65482,65487,1175,65490,65495,1175,65498,65500,1175,1,128,1114111,1243,1,128,1114111,1218,1,128,1114111,1219,1,128,1114111,1288,1,128,1114111,1289,1,128,1114111,1308,1,128,1114111,1309,1,128,1114111,1310,1,128,1114111,1311,1,128,1114111,1364,1,128,1114111,1365,1,128,1114111,1441,1,128,1114111,1436,1,128,1114111,1437,1,128,1114111,1438,1,128,1114111,1439,1,128,1114111,1494,1,128,1114111,1444,1,128,1114111,1445,371,170,170,1542,181,181,1542,186,186,1542,192,214,1542,216,246,1542,248,705,1542,710,721,1542,736,740,1542,748,748,1542,750,750,1542,880,884,1542,886,887,1542,890,893,1542,902,902,1542,904,906,1542,908,908,1542,910,929,1542,931,1013,1542,1015,1153,1542,1162,1319,1542,1329,1366,1542,1369,1369,1542,1377,1415,1542,1488,1514,1542,1520,1522,1542,1568,1610,1542,1646,1647,1542,1649,1747,1542,1749,1749,1542,1765,1766,1542,1774,1775,1542,1786,1788,1542,1791,1791,1542,1808,1808,1542,1810,1839,1542,1869,1957,1542,1969,1969,1542,1994,2026,1542,2036,2037,1542,2042,2042,1542,2048,2069,1542,2074,2074,1542,2084,2084,1542,2088,2088,1542,2112,2136,1542,2208,2208,1542,2210,2220,1542,2308,2361,1542,2365,2365,1542,2384,2384,1542,2392,2401,1542,2417,2423,1542,2425,2431,1542,2437,2444,1542,2447,2448,1542,2451,2472,1542,2474,2480,1542,2482,2482,1542,2486,2489,1542,2493,2493,1542,2510,2510,1542,2524,2525,1542,2527,2529,1542,2544,2545,1542,2565,2570,1542,2575,2576,1542,2579,2600,1542,2602,2608,1542,2610,2611,1542,2613,2614,1542,2616,2617,1542,2649,2652,1542,2654,2654,1542,2674,2676,1542,2693,2701,1542,2703,2705,1542,2707,2728,1542,2730,2736,1542,2738,2739,1542,2741,2745,1542,2749,2749,1542,2768,2768,1542,2784,2785,1542,2821,2828,1542,2831,2832,1542,2835,2856,1542,2858,2864,1542,2866,2867,1542,2869,2873,1542,2877,2877,1542,2908,2909,1542,2911,2913,1542,2929,2929,1542,2947,2947,1542,2949,2954,1542,2958,2960,1542,2962,2965,1542,2969,2970,1542,2972,2972,1542,2974,2975,1542,2979,2980,1542,2984,2986,1542,2990,3001,1542,3024,3024,1542,3077,3084,1542,3086,3088,1542,3090,3112,1542,3114,3123,1542,3125,3129,1542,3133,3133,1542,3160,3161,1542,3168,3169,1542,3205,3212,1542,3214,3216,1542,3218,3240,1542,3242,3251,1542,3253,3257,1542,3261,3261,1542,3294,3294,1542,3296,3297,1542,3313,3314,1542,3333,3340,1542,3342,3344,1542,3346,3386,1542,3389,3389,1542,3406,3406,1542,3424,3425,1542,3450,3455,1542,3461,3478,1542,3482,3505,1542,3507,3515,1542,3517,3517,1542,3520,3526,1542,3585,3632,1542,3634,3635,1542,3648,3654,1542,3713,3714,1542,3716,3716,1542,3719,3720,1542,3722,3722,1542,3725,3725,1542,3732,3735,1542,3737,3743,1542,3745,3747,1542,3749,3749,1542,3751,3751,1542,3754,3755,1542,3757,3760,1542,3762,3763,1542,3773,3773,1542,3776,3780,1542,3782,3782,1542,3804,3807,1542,3840,3840,1542,3904,3911,1542,3913,3948,1542,3976,3980,1542,4096,4138,1542,4159,4159,1542,4176,4181,1542,4186,4189,1542,4193,4193,1542,4197,4198,1542,4206,4208,1542,4213,4225,1542,4238,4238,1542,4256,4293,1542,4295,4295,1542,4301,4301,1542,4304,4346,1542,4348,4680,1542,4682,4685,1542,4688,4694,1542,4696,4696,1542,4698,4701,1542,4704,4744,1542,4746,4749,1542,4752,4784,1542,4786,4789,1542,4792,4798,1542,4800,4800,1542,4802,4805,1542,4808,4822,1542,4824,4880,1542,4882,4885,1542,4888,4954,1542,4992,5007,1542,5024,5108,1542,5121,5740,1542,5743,5759,1542,5761,5786,1542,5792,5866,1542,5888,5900,1542,5902,5905,1542,5920,5937,1542,5952,5969,1542,5984,5996,1542,5998,6000,1542,6016,6067,1542,6103,6103,1542,6108,6108,1542,6176,6263,1542,6272,6312,1542,6314,6314,1542,6320,6389,1542,6400,6428,1542,6480,6509,1542,6512,6516,1542,6528,6571,1542,6593,6599,1542,6656,6678,1542,6688,6740,1542,6823,6823,1542,6917,6963,1542,6981,6987,1542,7043,7072,1542,7086,7087,1542,7098,7141,1542,7168,7203,1542,7245,7247,1542,7258,7293,1542,7401,7404,1542,7406,7409,1542,7413,7414,1542,7424,7615,1542,7680,7957,1542,7960,7965,1542,7968,8005,1542,8008,8013,1542,8016,8023,1542,8025,8025,1542,8027,8027,1542,8029,8029,1542,8031,8061,1542,8064,8116,1542,8118,8124,1542,8126,8126,1542,8130,8132,1542,8134,8140,1542,8144,8147,1542,8150,8155,1542,8160,8172,1542,8178,8180,1542,8182,8188,1542,8305,8305,1542,8319,8319,1542,8336,8348,1542,8450,8450,1542,8455,8455,1542,8458,8467,1542,8469,8469,1542,8473,8477,1542,8484,8484,1542,8486,8486,1542,8488,8488,1542,8490,8493,1542,8495,8505,1542,8508,8511,1542,8517,8521,1542,8526,8526,1542,8579,8580,1542,11264,11310,1542,11312,11358,1542,11360,11492,1542,11499,11502,1542,11506,11507,1542,11520,11557,1542,11559,11559,1542,11565,11565,1542,11568,11623,1542,11631,11631,1542,11648,11670,1542,11680,11686,1542,11688,11694,1542,11696,11702,1542,11704,11710,1542,11712,11718,1542,11720,11726,1542,11728,11734,1542,11736,11742,1542,11823,11823,1542,12293,12294,1542,12337,12341,1542,12347,12348,1542,12353,12438,1542,12445,12447,1542,12449,12538,1542,12540,12543,1542,12549,12589,1542,12593,12686,1542,12704,12730,1542,12784,12799,1542,13312,13312,1542,19893,19893,1542,19968,19968,1542,40908,40908,1542,40960,42124,1542,42192,42237,1542,42240,42508,1542,42512,42527,1542,42538,42539,1542,42560,42606,1542,42623,42647,1542,42656,42725,1542,42775,42783,1542,42786,42888,1542,42891,42894,1542,42896,42899,1542,42912,42922,1542,43000,43009,1542,43011,43013,1542,43015,43018,1542,43020,43042,1542,43072,43123,1542,43138,43187,1542,43250,43255,1542,43259,43259,1542,43274,43301,1542,43312,43334,1542,43360,43388,1542,43396,43442,1542,43471,43471,1542,43520,43560,1542,43584,43586,1542,43588,43595,1542,43616,43638,1542,43642,43642,1542,43648,43695,1542,43697,43697,1542,43701,43702,1542,43705,43709,1542,43712,43712,1542,43714,43714,1542,43739,43741,1542,43744,43754,1542,43762,43764,1542,43777,43782,1542,43785,43790,1542,43793,43798,1542,43808,43814,1542,43816,43822,1542,43968,44002,1542,44032,44032,1542,55203,55203,1542,55216,55238,1542,55243,55291,1542,63744,64109,1542,64112,64217,1542,64256,64262,1542,64275,64279,1542,64285,64285,1542,64287,64296,1542,64298,64310,1542,64312,64316,1542,64318,64318,1542,64320,64321,1542,64323,64324,1542,64326,64433,1542,64467,64829,1542,64848,64911,1542,64914,64967,1542,65008,65019,1542,65136,65140,1542,65142,65276,1542,65313,65338,1542,65345,65370,1542,65382,65470,1542,65474,65479,1542,65482,65487,1542,65490,65495,1542,65498,65500,1542,1,128,1114111,1536,391,170,170,1542,181,181,1542,186,186,1542,192,214,1542,216,246,1542,248,705,1542,710,721,1542,736,740,1542,748,748,1542,750,750,1542,880,884,1542,886,887,1542,890,893,1542,902,902,1542,904,906,1542,908,908,1542,910,929,1542,931,1013,1542,1015,1153,1542,1162,1319,1542,1329,1366,1542,1369,1369,1542,1377,1415,1542,1488,1514,1542,1520,1522,1542,1568,1610,1542,1632,1641,1542,1646,1647,1542,1649,1747,1542,1749,1749,1542,1765,1766,1542,1774,1788,1542,1791,1791,1542,1808,1808,1542,1810,1839,1542,1869,1957,1542,1969,1969,1542,1984,2026,1542,2036,2037,1542,2042,2042,1542,2048,2069,1542,2074,2074,1542,2084,2084,1542,2088,2088,1542,2112,2136,1542,2208,2208,1542,2210,2220,1542,2308,2361,1542,2365,2365,1542,2384,2384,1542,2392,2401,1542,2406,2415,1542,2417,2423,1542,2425,2431,1542,2437,2444,1542,2447,2448,1542,2451,2472,1542,2474,2480,1542,2482,2482,1542,2486,2489,1542,2493,2493,1542,2510,2510,1542,2524,2525,1542,2527,2529,1542,2534,2545,1542,2565,2570,1542,2575,2576,1542,2579,2600,1542,2602,2608,1542,2610,2611,1542,2613,2614,1542,2616,2617,1542,2649,2652,1542,2654,2654,1542,2662,2671,1542,2674,2676,1542,2693,2701,1542,2703,2705,1542,2707,2728,1542,2730,2736,1542,2738,2739,1542,2741,2745,1542,2749,2749,1542,2768,2768,1542,2784,2785,1542,2790,2799,1542,2821,2828,1542,2831,2832,1542,2835,2856,1542,2858,2864,1542,2866,2867,1542,2869,2873,1542,2877,2877,1542,2908,2909,1542,2911,2913,1542,2918,2927,1542,2929,2929,1542,2947,2947,1542,2949,2954,1542,2958,2960,1542,2962,2965,1542,2969,2970,1542,2972,2972,1542,2974,2975,1542,2979,2980,1542,2984,2986,1542,2990,3001,1542,3024,3024,1542,3046,3055,1542,3077,3084,1542,3086,3088,1542,3090,3112,1542,3114,3123,1542,3125,3129,1542,3133,3133,1542,3160,3161,1542,3168,3169,1542,3174,3183,1542,3205,3212,1542,3214,3216,1542,3218,3240,1542,3242,3251,1542,3253,3257,1542,3261,3261,1542,3294,3294,1542,3296,3297,1542,3302,3311,1542,3313,3314,1542,3333,3340,1542,3342,3344,1542,3346,3386,1542,3389,3389,1542,3406,3406,1542,3424,3425,1542,3430,3439,1542,3450,3455,1542,3461,3478,1542,3482,3505,1542,3507,3515,1542,3517,3517,1542,3520,3526,1542,3585,3632,1542,3634,3635,1542,3648,3654,1542,3664,3673,1542,3713,3714,1542,3716,3716,1542,3719,3720,1542,3722,3722,1542,3725,3725,1542,3732,3735,1542,3737,3743,1542,3745,3747,1542,3749,3749,1542,3751,3751,1542,3754,3755,1542,3757,3760,1542,3762,3763,1542,3773,3773,1542,3776,3780,1542,3782,3782,1542,3792,3801,1542,3804,3807,1542,3840,3840,1542,3872,3881,1542,3904,3911,1542,3913,3948,1542,3976,3980,1542,4096,4138,1542,4159,4169,1542,4176,4181,1542,4186,4189,1542,4193,4193,1542,4197,4198,1542,4206,4208,1542,4213,4225,1542,4238,4238,1542,4240,4249,1542,4256,4293,1542,4295,4295,1542,4301,4301,1542,4304,4346,1542,4348,4680,1542,4682,4685,1542,4688,4694,1542,4696,4696,1542,4698,4701,1542,4704,4744,1542,4746,4749,1542,4752,4784,1542,4786,4789,1542,4792,4798,1542,4800,4800,1542,4802,4805,1542,4808,4822,1542,4824,4880,1542,4882,4885,1542,4888,4954,1542,4992,5007,1542,5024,5108,1542,5121,5740,1542,5743,5759,1542,5761,5786,1542,5792,5866,1542,5888,5900,1542,5902,5905,1542,5920,5937,1542,5952,5969,1542,5984,5996,1542,5998,6000,1542,6016,6067,1542,6103,6103,1542,6108,6108,1542,6112,6121,1542,6160,6169,1542,6176,6263,1542,6272,6312,1542,6314,6314,1542,6320,6389,1542,6400,6428,1542,6470,6509,1542,6512,6516,1542,6528,6571,1542,6593,6599,1542,6608,6617,1542,6656,6678,1542,6688,6740,1542,6784,6793,1542,6800,6809,1542,6823,6823,1542,6917,6963,1542,6981,6987,1542,6992,7001,1542,7043,7072,1542,7086,7141,1542,7168,7203,1542,7232,7241,1542,7245,7293,1542,7401,7404,1542,7406,7409,1542,7413,7414,1542,7424,7615,1542,7680,7957,1542,7960,7965,1542,7968,8005,1542,8008,8013,1542,8016,8023,1542,8025,8025,1542,8027,8027,1542,8029,8029,1542,8031,8061,1542,8064,8116,1542,8118,8124,1542,8126,8126,1542,8130,8132,1542,8134,8140,1542,8144,8147,1542,8150,8155,1542,8160,8172,1542,8178,8180,1542,8182,8188,1542,8305,8305,1542,8319,8319,1542,8336,8348,1542,8450,8450,1542,8455,8455,1542,8458,8467,1542,8469,8469,1542,8473,8477,1542,8484,8484,1542,8486,8486,1542,8488,8488,1542,8490,8493,1542,8495,8505,1542,8508,8511,1542,8517,8521,1542,8526,8526,1542,8579,8580,1542,11264,11310,1542,11312,11358,1542,11360,11492,1542,11499,11502,1542,11506,11507,1542,11520,11557,1542,11559,11559,1542,11565,11565,1542,11568,11623,1542,11631,11631,1542,11648,11670,1542,11680,11686,1542,11688,11694,1542,11696,11702,1542,11704,11710,1542,11712,11718,1542,11720,11726,1542,11728,11734,1542,11736,11742,1542,11823,11823,1542,12293,12294,1542,12337,12341,1542,12347,12348,1542,12353,12438,1542,12445,12447,1542,12449,12538,1542,12540,12543,1542,12549,12589,1542,12593,12686,1542,12704,12730,1542,12784,12799,1542,13312,13312,1542,19893,19893,1542,19968,19968,1542,40908,40908,1542,40960,42124,1542,42192,42237,1542,42240,42508,1542,42512,42539,1542,42560,42606,1542,42623,42647,1542,42656,42725,1542,42775,42783,1542,42786,42888,1542,42891,42894,1542,42896,42899,1542,42912,42922,1542,43000,43009,1542,43011,43013,1542,43015,43018,1542,43020,43042,1542,43072,43123,1542,43138,43187,1542,43216,43225,1542,43250,43255,1542,43259,43259,1542,43264,43301,1542,43312,43334,1542,43360,43388,1542,43396,43442,1542,43471,43481,1542,43520,43560,1542,43584,43586,1542,43588,43595,1542,43600,43609,1542,43616,43638,1542,43642,43642,1542,43648,43695,1542,43697,43697,1542,43701,43702,1542,43705,43709,1542,43712,43712,1542,43714,43714,1542,43739,43741,1542,43744,43754,1542,43762,43764,1542,43777,43782,1542,43785,43790,1542,43793,43798,1542,43808,43814,1542,43816,43822,1542,43968,44002,1542,44016,44025,1542,44032,44032,1542,55203,55203,1542,55216,55238,1542,55243,55291,1542,63744,64109,1542,64112,64217,1542,64256,64262,1542,64275,64279,1542,64285,64285,1542,64287,64296,1542,64298,64310,1542,64312,64316,1542,64318,64318,1542,64320,64321,1542,64323,64324,1542,64326,64433,1542,64467,64829,1542,64848,64911,1542,64914,64967,1542,65008,65019,1542,65136,65140,1542,65142,65276,1542,65296,65305,1542,65313,65338,1542,65345,65370,1542,65382,65470,1542,65474,65479,1542,65482,65487,1542,65490,65495,1542,65498,65500,1542,1,128,1114111,1566,371,170,170,1579,181,181,1579,186,186,1579,192,214,1579,216,246,1579,248,705,1579,710,721,1579,736,740,1579,748,748,1579,750,750,1579,880,884,1579,886,887,1579,890,893,1579,902,902,1579,904,906,1579,908,908,1579,910,929,1579,931,1013,1579,1015,1153,1579,1162,1319,1579,1329,1366,1579,1369,1369,1579,1377,1415,1579,1488,1514,1579,1520,1522,1579,1568,1610,1579,1646,1647,1579,1649,1747,1579,1749,1749,1579,1765,1766,1579,1774,1775,1579,1786,1788,1579,1791,1791,1579,1808,1808,1579,1810,1839,1579,1869,1957,1579,1969,1969,1579,1994,2026,1579,2036,2037,1579,2042,2042,1579,2048,2069,1579,2074,2074,1579,2084,2084,1579,2088,2088,1579,2112,2136,1579,2208,2208,1579,2210,2220,1579,2308,2361,1579,2365,2365,1579,2384,2384,1579,2392,2401,1579,2417,2423,1579,2425,2431,1579,2437,2444,1579,2447,2448,1579,2451,2472,1579,2474,2480,1579,2482,2482,1579,2486,2489,1579,2493,2493,1579,2510,2510,1579,2524,2525,1579,2527,2529,1579,2544,2545,1579,2565,2570,1579,2575,2576,1579,2579,2600,1579,2602,2608,1579,2610,2611,1579,2613,2614,1579,2616,2617,1579,2649,2652,1579,2654,2654,1579,2674,2676,1579,2693,2701,1579,2703,2705,1579,2707,2728,1579,2730,2736,1579,2738,2739,1579,2741,2745,1579,2749,2749,1579,2768,2768,1579,2784,2785,1579,2821,2828,1579,2831,2832,1579,2835,2856,1579,2858,2864,1579,2866,2867,1579,2869,2873,1579,2877,2877,1579,2908,2909,1579,2911,2913,1579,2929,2929,1579,2947,2947,1579,2949,2954,1579,2958,2960,1579,2962,2965,1579,2969,2970,1579,2972,2972,1579,2974,2975,1579,2979,2980,1579,2984,2986,1579,2990,3001,1579,3024,3024,1579,3077,3084,1579,3086,3088,1579,3090,3112,1579,3114,3123,1579,3125,3129,1579,3133,3133,1579,3160,3161,1579,3168,3169,1579,3205,3212,1579,3214,3216,1579,3218,3240,1579,3242,3251,1579,3253,3257,1579,3261,3261,1579,3294,3294,1579,3296,3297,1579,3313,3314,1579,3333,3340,1579,3342,3344,1579,3346,3386,1579,3389,3389,1579,3406,3406,1579,3424,3425,1579,3450,3455,1579,3461,3478,1579,3482,3505,1579,3507,3515,1579,3517,3517,1579,3520,3526,1579,3585,3632,1579,3634,3635,1579,3648,3654,1579,3713,3714,1579,3716,3716,1579,3719,3720,1579,3722,3722,1579,3725,3725,1579,3732,3735,1579,3737,3743,1579,3745,3747,1579,3749,3749,1579,3751,3751,1579,3754,3755,1579,3757,3760,1579,3762,3763,1579,3773,3773,1579,3776,3780,1579,3782,3782,1579,3804,3807,1579,3840,3840,1579,3904,3911,1579,3913,3948,1579,3976,3980,1579,4096,4138,1579,4159,4159,1579,4176,4181,1579,4186,4189,1579,4193,4193,1579,4197,4198,1579,4206,4208,1579,4213,4225,1579,4238,4238,1579,4256,4293,1579,4295,4295,1579,4301,4301,1579,4304,4346,1579,4348,4680,1579,4682,4685,1579,4688,4694,1579,4696,4696,1579,4698,4701,1579,4704,4744,1579,4746,4749,1579,4752,4784,1579,4786,4789,1579,4792,4798,1579,4800,4800,1579,4802,4805,1579,4808,4822,1579,4824,4880,1579,4882,4885,1579,4888,4954,1579,4992,5007,1579,5024,5108,1579,5121,5740,1579,5743,5759,1579,5761,5786,1579,5792,5866,1579,5888,5900,1579,5902,5905,1579,5920,5937,1579,5952,5969,1579,5984,5996,1579,5998,6000,1579,6016,6067,1579,6103,6103,1579,6108,6108,1579,6176,6263,1579,6272,6312,1579,6314,6314,1579,6320,6389,1579,6400,6428,1579,6480,6509,1579,6512,6516,1579,6528,6571,1579,6593,6599,1579,6656,6678,1579,6688,6740,1579,6823,6823,1579,6917,6963,1579,6981,6987,1579,7043,7072,1579,7086,7087,1579,7098,7141,1579,7168,7203,1579,7245,7247,1579,7258,7293,1579,7401,7404,1579,7406,7409,1579,7413,7414,1579,7424,7615,1579,7680,7957,1579,7960,7965,1579,7968,8005,1579,8008,8013,1579,8016,8023,1579,8025,8025,1579,8027,8027,1579,8029,8029,1579,8031,8061,1579,8064,8116,1579,8118,8124,1579,8126,8126,1579,8130,8132,1579,8134,8140,1579,8144,8147,1579,8150,8155,1579,8160,8172,1579,8178,8180,1579,8182,8188,1579,8305,8305,1579,8319,8319,1579,8336,8348,1579,8450,8450,1579,8455,8455,1579,8458,8467,1579,8469,8469,1579,8473,8477,1579,8484,8484,1579,8486,8486,1579,8488,8488,1579,8490,8493,1579,8495,8505,1579,8508,8511,1579,8517,8521,1579,8526,8526,1579,8579,8580,1579,11264,11310,1579,11312,11358,1579,11360,11492,1579,11499,11502,1579,11506,11507,1579,11520,11557,1579,11559,11559,1579,11565,11565,1579,11568,11623,1579,11631,11631,1579,11648,11670,1579,11680,11686,1579,11688,11694,1579,11696,11702,1579,11704,11710,1579,11712,11718,1579,11720,11726,1579,11728,11734,1579,11736,11742,1579,11823,11823,1579,12293,12294,1579,12337,12341,1579,12347,12348,1579,12353,12438,1579,12445,12447,1579,12449,12538,1579,12540,12543,1579,12549,12589,1579,12593,12686,1579,12704,12730,1579,12784,12799,1579,13312,13312,1579,19893,19893,1579,19968,19968,1579,40908,40908,1579,40960,42124,1579,42192,42237,1579,42240,42508,1579,42512,42527,1579,42538,42539,1579,42560,42606,1579,42623,42647,1579,42656,42725,1579,42775,42783,1579,42786,42888,1579,42891,42894,1579,42896,42899,1579,42912,42922,1579,43000,43009,1579,43011,43013,1579,43015,43018,1579,43020,43042,1579,43072,43123,1579,43138,43187,1579,43250,43255,1579,43259,43259,1579,43274,43301,1579,43312,43334,1579,43360,43388,1579,43396,43442,1579,43471,43471,1579,43520,43560,1579,43584,43586,1579,43588,43595,1579,43616,43638,1579,43642,43642,1579,43648,43695,1579,43697,43697,1579,43701,43702,1579,43705,43709,1579,43712,43712,1579,43714,43714,1579,43739,43741,1579,43744,43754,1579,43762,43764,1579,43777,43782,1579,43785,43790,1579,43793,43798,1579,43808,43814,1579,43816,43822,1579,43968,44002,1579,44032,44032,1579,55203,55203,1579,55216,55238,1579,55243,55291,1579,63744,64109,1579,64112,64217,1579,64256,64262,1579,64275,64279,1579,64285,64285,1579,64287,64296,1579,64298,64310,1579,64312,64316,1579,64318,64318,1579,64320,64321,1579,64323,64324,1579,64326,64433,1579,64467,64829,1579,64848,64911,1579,64914,64967,1579,65008,65019,1579,65136,65140,1579,65142,65276,1579,65313,65338,1579,65345,65370,1579,65382,65470,1579,65474,65479,1579,65482,65487,1579,65490,65495,1579,65498,65500,1579,391,170,170,1579,181,181,1579,186,186,1579,192,214,1579,216,246,1579,248,705,1579,710,721,1579,736,740,1579,748,748,1579,750,750,1579,880,884,1579,886,887,1579,890,893,1579,902,902,1579,904,906,1579,908,908,1579,910,929,1579,931,1013,1579,1015,1153,1579,1162,1319,1579,1329,1366,1579,1369,1369,1579,1377,1415,1579,1488,1514,1579,1520,1522,1579,1568,1610,1579,1632,1641,1579,1646,1647,1579,1649,1747,1579,1749,1749,1579,1765,1766,1579,1774,1788,1579,1791,1791,1579,1808,1808,1579,1810,1839,1579,1869,1957,1579,1969,1969,1579,1984,2026,1579,2036,2037,1579,2042,2042,1579,2048,2069,1579,2074,2074,1579,2084,2084,1579,2088,2088,1579,2112,2136,1579,2208,2208,1579,2210,2220,1579,2308,2361,1579,2365,2365,1579,2384,2384,1579,2392,2401,1579,2406,2415,1579,2417,2423,1579,2425,2431,1579,2437,2444,1579,2447,2448,1579,2451,2472,1579,2474,2480,1579,2482,2482,1579,2486,2489,1579,2493,2493,1579,2510,2510,1579,2524,2525,1579,2527,2529,1579,2534,2545,1579,2565,2570,1579,2575,2576,1579,2579,2600,1579,2602,2608,1579,2610,2611,1579,2613,2614,1579,2616,2617,1579,2649,2652,1579,2654,2654,1579,2662,2671,1579,2674,2676,1579,2693,2701,1579,2703,2705,1579,2707,2728,1579,2730,2736,1579,2738,2739,1579,2741,2745,1579,2749,2749,1579,2768,2768,1579,2784,2785,1579,2790,2799,1579,2821,2828,1579,2831,2832,1579,2835,2856,1579,2858,2864,1579,2866,2867,1579,2869,2873,1579,2877,2877,1579,2908,2909,1579,2911,2913,1579,2918,2927,1579,2929,2929,1579,2947,2947,1579,2949,2954,1579,2958,2960,1579,2962,2965,1579,2969,2970,1579,2972,2972,1579,2974,2975,1579,2979,2980,1579,2984,2986,1579,2990,3001,1579,3024,3024,1579,3046,3055,1579,3077,3084,1579,3086,3088,1579,3090,3112,1579,3114,3123,1579,3125,3129,1579,3133,3133,1579,3160,3161,1579,3168,3169,1579,3174,3183,1579,3205,3212,1579,3214,3216,1579,3218,3240,1579,3242,3251,1579,3253,3257,1579,3261,3261,1579,3294,3294,1579,3296,3297,1579,3302,3311,1579,3313,3314,1579,3333,3340,1579,3342,3344,1579,3346,3386,1579,3389,3389,1579,3406,3406,1579,3424,3425,1579,3430,3439,1579,3450,3455,1579,3461,3478,1579,3482,3505,1579,3507,3515,1579,3517,3517,1579,3520,3526,1579,3585,3632,1579,3634,3635,1579,3648,3654,1579,3664,3673,1579,3713,3714,1579,3716,3716,1579,3719,3720,1579,3722,3722,1579,3725,3725,1579,3732,3735,1579,3737,3743,1579,3745,3747,1579,3749,3749,1579,3751,3751,1579,3754,3755,1579,3757,3760,1579,3762,3763,1579,3773,3773,1579,3776,3780,1579,3782,3782,1579,3792,3801,1579,3804,3807,1579,3840,3840,1579,3872,3881,1579,3904,3911,1579,3913,3948,1579,3976,3980,1579,4096,4138,1579,4159,4169,1579,4176,4181,1579,4186,4189,1579,4193,4193,1579,4197,4198,1579,4206,4208,1579,4213,4225,1579,4238,4238,1579,4240,4249,1579,4256,4293,1579,4295,4295,1579,4301,4301,1579,4304,4346,1579,4348,4680,1579,4682,4685,1579,4688,4694,1579,4696,4696,1579,4698,4701,1579,4704,4744,1579,4746,4749,1579,4752,4784,1579,4786,4789,1579,4792,4798,1579,4800,4800,1579,4802,4805,1579,4808,4822,1579,4824,4880,1579,4882,4885,1579,4888,4954,1579,4992,5007,1579,5024,5108,1579,5121,5740,1579,5743,5759,1579,5761,5786,1579,5792,5866,1579,5888,5900,1579,5902,5905,1579,5920,5937,1579,5952,5969,1579,5984,5996,1579,5998,6000,1579,6016,6067,1579,6103,6103,1579,6108,6108,1579,6112,6121,1579,6160,6169,1579,6176,6263,1579,6272,6312,1579,6314,6314,1579,6320,6389,1579,6400,6428,1579,6470,6509,1579,6512,6516,1579,6528,6571,1579,6593,6599,1579,6608,6617,1579,6656,6678,1579,6688,6740,1579,6784,6793,1579,6800,6809,1579,6823,6823,1579,6917,6963,1579,6981,6987,1579,6992,7001,1579,7043,7072,1579,7086,7141,1579,7168,7203,1579,7232,7241,1579,7245,7293,1579,7401,7404,1579,7406,7409,1579,7413,7414,1579,7424,7615,1579,7680,7957,1579,7960,7965,1579,7968,8005,1579,8008,8013,1579,8016,8023,1579,8025,8025,1579,8027,8027,1579,8029,8029,1579,8031,8061,1579,8064,8116,1579,8118,8124,1579,8126,8126,1579,8130,8132,1579,8134,8140,1579,8144,8147,1579,8150,8155,1579,8160,8172,1579,8178,8180,1579,8182,8188,1579,8305,8305,1579,8319,8319,1579,8336,8348,1579,8450,8450,1579,8455,8455,1579,8458,8467,1579,8469,8469,1579,8473,8477,1579,8484,8484,1579,8486,8486,1579,8488,8488,1579,8490,8493,1579,8495,8505,1579,8508,8511,1579,8517,8521,1579,8526,8526,1579,8579,8580,1579,11264,11310,1579,11312,11358,1579,11360,11492,1579,11499,11502,1579,11506,11507,1579,11520,11557,1579,11559,11559,1579,11565,11565,1579,11568,11623,1579,11631,11631,1579,11648,11670,1579,11680,11686,1579,11688,11694,1579,11696,11702,1579,11704,11710,1579,11712,11718,1579,11720,11726,1579,11728,11734,1579,11736,11742,1579,11823,11823,1579,12293,12294,1579,12337,12341,1579,12347,12348,1579,12353,12438,1579,12445,12447,1579,12449,12538,1579,12540,12543,1579,12549,12589,1579,12593,12686,1579,12704,12730,1579,12784,12799,1579,13312,13312,1579,19893,19893,1579,19968,19968,1579,40908,40908,1579,40960,42124,1579,42192,42237,1579,42240,42508,1579,42512,42539,1579,42560,42606,1579,42623,42647,1579,42656,42725,1579,42775,42783,1579,42786,42888,1579,42891,42894,1579,42896,42899,1579,42912,42922,1579,43000,43009,1579,43011,43013,1579,43015,43018,1579,43020,43042,1579,43072,43123,1579,43138,43187,1579,43216,43225,1579,43250,43255,1579,43259,43259,1579,43264,43301,1579,43312,43334,1579,43360,43388,1579,43396,43442,1579,43471,43481,1579,43520,43560,1579,43584,43586,1579,43588,43595,1579,43600,43609,1579,43616,43638,1579,43642,43642,1579,43648,43695,1579,43697,43697,1579,43701,43702,1579,43705,43709,1579,43712,43712,1579,43714,43714,1579,43739,43741,1579,43744,43754,1579,43762,43764,1579,43777,43782,1579,43785,43790,1579,43793,43798,1579,43808,43814,1579,43816,43822,1579,43968,44002,1579,44016,44025,1579,44032,44032,1579,55203,55203,1579,55216,55238,1579,55243,55291,1579,63744,64109,1579,64112,64217,1579,64256,64262,1579,64275,64279,1579,64285,64285,1579,64287,64296,1579,64298,64310,1579,64312,64316,1579,64318,64318,1579,64320,64321,1579,64323,64324,1579,64326,64433,1579,64467,64829,1579,64848,64911,1579,64914,64967,1579,65008,65019,1579,65136,65140,1579,65142,65276,1579,65296,65305,1579,65313,65338,1579,65345,65370,1579,65382,65470,1579,65474,65479,1579,65482,65487,1579,65490,65495,1579,65498,65500,1579,1,128,1114111,1587,371,170,170,1589,181,181,1589,186,186,1589,192,214,1589,216,246,1589,248,705,1589,710,721,1589,736,740,1589,748,748,1589,750,750,1589,880,884,1589,886,887,1589,890,893,1589,902,902,1589,904,906,1589,908,908,1589,910,929,1589,931,1013,1589,1015,1153,1589,1162,1319,1589,1329,1366,1589,1369,1369,1589,1377,1415,1589,1488,1514,1589,1520,1522,1589,1568,1610,1589,1646,1647,1589,1649,1747,1589,1749,1749,1589,1765,1766,1589,1774,1775,1589,1786,1788,1589,1791,1791,1589,1808,1808,1589,1810,1839,1589,1869,1957,1589,1969,1969,1589,1994,2026,1589,2036,2037,1589,2042,2042,1589,2048,2069,1589,2074,2074,1589,2084,2084,1589,2088,2088,1589,2112,2136,1589,2208,2208,1589,2210,2220,1589,2308,2361,1589,2365,2365,1589,2384,2384,1589,2392,2401,1589,2417,2423,1589,2425,2431,1589,2437,2444,1589,2447,2448,1589,2451,2472,1589,2474,2480,1589,2482,2482,1589,2486,2489,1589,2493,2493,1589,2510,2510,1589,2524,2525,1589,2527,2529,1589,2544,2545,1589,2565,2570,1589,2575,2576,1589,2579,2600,1589,2602,2608,1589,2610,2611,1589,2613,2614,1589,2616,2617,1589,2649,2652,1589,2654,2654,1589,2674,2676,1589,2693,2701,1589,2703,2705,1589,2707,2728,1589,2730,2736,1589,2738,2739,1589,2741,2745,1589,2749,2749,1589,2768,2768,1589,2784,2785,1589,2821,2828,1589,2831,2832,1589,2835,2856,1589,2858,2864,1589,2866,2867,1589,2869,2873,1589,2877,2877,1589,2908,2909,1589,2911,2913,1589,2929,2929,1589,2947,2947,1589,2949,2954,1589,2958,2960,1589,2962,2965,1589,2969,2970,1589,2972,2972,1589,2974,2975,1589,2979,2980,1589,2984,2986,1589,2990,3001,1589,3024,3024,1589,3077,3084,1589,3086,3088,1589,3090,3112,1589,3114,3123,1589,3125,3129,1589,3133,3133,1589,3160,3161,1589,3168,3169,1589,3205,3212,1589,3214,3216,1589,3218,3240,1589,3242,3251,1589,3253,3257,1589,3261,3261,1589,3294,3294,1589,3296,3297,1589,3313,3314,1589,3333,3340,1589,3342,3344,1589,3346,3386,1589,3389,3389,1589,3406,3406,1589,3424,3425,1589,3450,3455,1589,3461,3478,1589,3482,3505,1589,3507,3515,1589,3517,3517,1589,3520,3526,1589,3585,3632,1589,3634,3635,1589,3648,3654,1589,3713,3714,1589,3716,3716,1589,3719,3720,1589,3722,3722,1589,3725,3725,1589,3732,3735,1589,3737,3743,1589,3745,3747,1589,3749,3749,1589,3751,3751,1589,3754,3755,1589,3757,3760,1589,3762,3763,1589,3773,3773,1589,3776,3780,1589,3782,3782,1589,3804,3807,1589,3840,3840,1589,3904,3911,1589,3913,3948,1589,3976,3980,1589,4096,4138,1589,4159,4159,1589,4176,4181,1589,4186,4189,1589,4193,4193,1589,4197,4198,1589,4206,4208,1589,4213,4225,1589,4238,4238,1589,4256,4293,1589,4295,4295,1589,4301,4301,1589,4304,4346,1589,4348,4680,1589,4682,4685,1589,4688,4694,1589,4696,4696,1589,4698,4701,1589,4704,4744,1589,4746,4749,1589,4752,4784,1589,4786,4789,1589,4792,4798,1589,4800,4800,1589,4802,4805,1589,4808,4822,1589,4824,4880,1589,4882,4885,1589,4888,4954,1589,4992,5007,1589,5024,5108,1589,5121,5740,1589,5743,5759,1589,5761,5786,1589,5792,5866,1589,5888,5900,1589,5902,5905,1589,5920,5937,1589,5952,5969,1589,5984,5996,1589,5998,6000,1589,6016,6067,1589,6103,6103,1589,6108,6108,1589,6176,6263,1589,6272,6312,1589,6314,6314,1589,6320,6389,1589,6400,6428,1589,6480,6509,1589,6512,6516,1589,6528,6571,1589,6593,6599,1589,6656,6678,1589,6688,6740,1589,6823,6823,1589,6917,6963,1589,6981,6987,1589,7043,7072,1589,7086,7087,1589,7098,7141,1589,7168,7203,1589,7245,7247,1589,7258,7293,1589,7401,7404,1589,7406,7409,1589,7413,7414,1589,7424,7615,1589,7680,7957,1589,7960,7965,1589,7968,8005,1589,8008,8013,1589,8016,8023,1589,8025,8025,1589,8027,8027,1589,8029,8029,1589,8031,8061,1589,8064,8116,1589,8118,8124,1589,8126,8126,1589,8130,8132,1589,8134,8140,1589,8144,8147,1589,8150,8155,1589,8160,8172,1589,8178,8180,1589,8182,8188,1589,8305,8305,1589,8319,8319,1589,8336,8348,1589,8450,8450,1589,8455,8455,1589,8458,8467,1589,8469,8469,1589,8473,8477,1589,8484,8484,1589,8486,8486,1589,8488,8488,1589,8490,8493,1589,8495,8505,1589,8508,8511,1589,8517,8521,1589,8526,8526,1589,8579,8580,1589,11264,11310,1589,11312,11358,1589,11360,11492,1589,11499,11502,1589,11506,11507,1589,11520,11557,1589,11559,11559,1589,11565,11565,1589,11568,11623,1589,11631,11631,1589,11648,11670,1589,11680,11686,1589,11688,11694,1589,11696,11702,1589,11704,11710,1589,11712,11718,1589,11720,11726,1589,11728,11734,1589,11736,11742,1589,11823,11823,1589,12293,12294,1589,12337,12341,1589,12347,12348,1589,12353,12438,1589,12445,12447,1589,12449,12538,1589,12540,12543,1589,12549,12589,1589,12593,12686,1589,12704,12730,1589,12784,12799,1589,13312,13312,1589,19893,19893,1589,19968,19968,1589,40908,40908,1589,40960,42124,1589,42192,42237,1589,42240,42508,1589,42512,42527,1589,42538,42539,1589,42560,42606,1589,42623,42647,1589,42656,42725,1589,42775,42783,1589,42786,42888,1589,42891,42894,1589,42896,42899,1589,42912,42922,1589,43000,43009,1589,43011,43013,1589,43015,43018,1589,43020,43042,1589,43072,43123,1589,43138,43187,1589,43250,43255,1589,43259,43259,1589,43274,43301,1589,43312,43334,1589,43360,43388,1589,43396,43442,1589,43471,43471,1589,43520,43560,1589,43584,43586,1589,43588,43595,1589,43616,43638,1589,43642,43642,1589,43648,43695,1589,43697,43697,1589,43701,43702,1589,43705,43709,1589,43712,43712,1589,43714,43714,1589,43739,43741,1589,43744,43754,1589,43762,43764,1589,43777,43782,1589,43785,43790,1589,43793,43798,1589,43808,43814,1589,43816,43822,1589,43968,44002,1589,44032,44032,1589,55203,55203,1589,55216,55238,1589,55243,55291,1589,63744,64109,1589,64112,64217,1589,64256,64262,1589,64275,64279,1589,64285,64285,1589,64287,64296,1589,64298,64310,1589,64312,64316,1589,64318,64318,1589,64320,64321,1589,64323,64324,1589,64326,64433,1589,64467,64829,1589,64848,64911,1589,64914,64967,1589,65008,65019,1589,65136,65140,1589,65142,65276,1589,65313,65338,1589,65345,65370,1589,65382,65470,1589,65474,65479,1589,65482,65487,1589,65490,65495,1589,65498,65500,1589,391,170,170,1589,181,181,1589,186,186,1589,192,214,1589,216,246,1589,248,705,1589,710,721,1589,736,740,1589,748,748,1589,750,750,1589,880,884,1589,886,887,1589,890,893,1589,902,902,1589,904,906,1589,908,908,1589,910,929,1589,931,1013,1589,1015,1153,1589,1162,1319,1589,1329,1366,1589,1369,1369,1589,1377,1415,1589,1488,1514,1589,1520,1522,1589,1568,1610,1589,1632,1641,1589,1646,1647,1589,1649,1747,1589,1749,1749,1589,1765,1766,1589,1774,1788,1589,1791,1791,1589,1808,1808,1589,1810,1839,1589,1869,1957,1589,1969,1969,1589,1984,2026,1589,2036,2037,1589,2042,2042,1589,2048,2069,1589,2074,2074,1589,2084,2084,1589,2088,2088,1589,2112,2136,1589,2208,2208,1589,2210,2220,1589,2308,2361,1589,2365,2365,1589,2384,2384,1589,2392,2401,1589,2406,2415,1589,2417,2423,1589,2425,2431,1589,2437,2444,1589,2447,2448,1589,2451,2472,1589,2474,2480,1589,2482,2482,1589,2486,2489,1589,2493,2493,1589,2510,2510,1589,2524,2525,1589,2527,2529,1589,2534,2545,1589,2565,2570,1589,2575,2576,1589,2579,2600,1589,2602,2608,1589,2610,2611,1589,2613,2614,1589,2616,2617,1589,2649,2652,1589,2654,2654,1589,2662,2671,1589,2674,2676,1589,2693,2701,1589,2703,2705,1589,2707,2728,1589,2730,2736,1589,2738,2739,1589,2741,2745,1589,2749,2749,1589,2768,2768,1589,2784,2785,1589,2790,2799,1589,2821,2828,1589,2831,2832,1589,2835,2856,1589,2858,2864,1589,2866,2867,1589,2869,2873,1589,2877,2877,1589,2908,2909,1589,2911,2913,1589,2918,2927,1589,2929,2929,1589,2947,2947,1589,2949,2954,1589,2958,2960,1589,2962,2965,1589,2969,2970,1589,2972,2972,1589,2974,2975,1589,2979,2980,1589,2984,2986,1589,2990,3001,1589,3024,3024,1589,3046,3055,1589,3077,3084,1589,3086,3088,1589,3090,3112,1589,3114,3123,1589,3125,3129,1589,3133,3133,1589,3160,3161,1589,3168,3169,1589,3174,3183,1589,3205,3212,1589,3214,3216,1589,3218,3240,1589,3242,3251,1589,3253,3257,1589,3261,3261,1589,3294,3294,1589,3296,3297,1589,3302,3311,1589,3313,3314,1589,3333,3340,1589,3342,3344,1589,3346,3386,1589,3389,3389,1589,3406,3406,1589,3424,3425,1589,3430,3439,1589,3450,3455,1589,3461,3478,1589,3482,3505,1589,3507,3515,1589,3517,3517,1589,3520,3526,1589,3585,3632,1589,3634,3635,1589,3648,3654,1589,3664,3673,1589,3713,3714,1589,3716,3716,1589,3719,3720,1589,3722,3722,1589,3725,3725,1589,3732,3735,1589,3737,3743,1589,3745,3747,1589,3749,3749,1589,3751,3751,1589,3754,3755,1589,3757,3760,1589,3762,3763,1589,3773,3773,1589,3776,3780,1589,3782,3782,1589,3792,3801,1589,3804,3807,1589,3840,3840,1589,3872,3881,1589,3904,3911,1589,3913,3948,1589,3976,3980,1589,4096,4138,1589,4159,4169,1589,4176,4181,1589,4186,4189,1589,4193,4193,1589,4197,4198,1589,4206,4208,1589,4213,4225,1589,4238,4238,1589,4240,4249,1589,4256,4293,1589,4295,4295,1589,4301,4301,1589,4304,4346,1589,4348,4680,1589,4682,4685,1589,4688,4694,1589,4696,4696,1589,4698,4701,1589,4704,4744,1589,4746,4749,1589,4752,4784,1589,4786,4789,1589,4792,4798,1589,4800,4800,1589,4802,4805,1589,4808,4822,1589,4824,4880,1589,4882,4885,1589,4888,4954,1589,4992,5007,1589,5024,5108,1589,5121,5740,1589,5743,5759,1589,5761,5786,1589,5792,5866,1589,5888,5900,1589,5902,5905,1589,5920,5937,1589,5952,5969,1589,5984,5996,1589,5998,6000,1589,6016,6067,1589,6103,6103,1589,6108,6108,1589,6112,6121,1589,6160,6169,1589,6176,6263,1589,6272,6312,1589,6314,6314,1589,6320,6389,1589,6400,6428,1589,6470,6509,1589,6512,6516,1589,6528,6571,1589,6593,6599,1589,6608,6617,1589,6656,6678,1589,6688,6740,1589,6784,6793,1589,6800,6809,1589,6823,6823,1589,6917,6963,1589,6981,6987,1589,6992,7001,1589,7043,7072,1589,7086,7141,1589,7168,7203,1589,7232,7241,1589,7245,7293,1589,7401,7404,1589,7406,7409,1589,7413,7414,1589,7424,7615,1589,7680,7957,1589,7960,7965,1589,7968,8005,1589,8008,8013,1589,8016,8023,1589,8025,8025,1589,8027,8027,1589,8029,8029,1589,8031,8061,1589,8064,8116,1589,8118,8124,1589,8126,8126,1589,8130,8132,1589,8134,8140,1589,8144,8147,1589,8150,8155,1589,8160,8172,1589,8178,8180,1589,8182,8188,1589,8305,8305,1589,8319,8319,1589,8336,8348,1589,8450,8450,1589,8455,8455,1589,8458,8467,1589,8469,8469,1589,8473,8477,1589,8484,8484,1589,8486,8486,1589,8488,8488,1589,8490,8493,1589,8495,8505,1589,8508,8511,1589,8517,8521,1589,8526,8526,1589,8579,8580,1589,11264,11310,1589,11312,11358,1589,11360,11492,1589,11499,11502,1589,11506,11507,1589,11520,11557,1589,11559,11559,1589,11565,11565,1589,11568,11623,1589,11631,11631,1589,11648,11670,1589,11680,11686,1589,11688,11694,1589,11696,11702,1589,11704,11710,1589,11712,11718,1589,11720,11726,1589,11728,11734,1589,11736,11742,1589,11823,11823,1589,12293,12294,1589,12337,12341,1589,12347,12348,1589,12353,12438,1589,12445,12447,1589,12449,12538,1589,12540,12543,1589,12549,12589,1589,12593,12686,1589,12704,12730,1589,12784,12799,1589,13312,13312,1589,19893,19893,1589,19968,19968,1589,40908,40908,1589,40960,42124,1589,42192,42237,1589,42240,42508,1589,42512,42539,1589,42560,42606,1589,42623,42647,1589,42656,42725,1589,42775,42783,1589,42786,42888,1589,42891,42894,1589,42896,42899,1589,42912,42922,1589,43000,43009,1589,43011,43013,1589,43015,43018,1589,43020,43042,1589,43072,43123,1589,43138,43187,1589,43216,43225,1589,43250,43255,1589,43259,43259,1589,43264,43301,1589,43312,43334,1589,43360,43388,1589,43396,43442,1589,43471,43481,1589,43520,43560,1589,43584,43586,1589,43588,43595,1589,43600,43609,1589,43616,43638,1589,43642,43642,1589,43648,43695,1589,43697,43697,1589,43701,43702,1589,43705,43709,1589,43712,43712,1589,43714,43714,1589,43739,43741,1589,43744,43754,1589,43762,43764,1589,43777,43782,1589,43785,43790,1589,43793,43798,1589,43808,43814,1589,43816,43822,1589,43968,44002,1589,44016,44025,1589,44032,44032,1589,55203,55203,1589,55216,55238,1589,55243,55291,1589,63744,64109,1589,64112,64217,1589,64256,64262,1589,64275,64279,1589,64285,64285,1589,64287,64296,1589,64298,64310,1589,64312,64316,1589,64318,64318,1589,64320,64321,1589,64323,64324,1589,64326,64433,1589,64467,64829,1589,64848,64911,1589,64914,64967,1589,65008,65019,1589,65136,65140,1589,65142,65276,1589,65296,65305,1589,65313,65338,1589,65345,65370,1589,65382,65470,1589,65474,65479,1589,65482,65487,1589,65490,65495,1589,65498,65500,1589,1,128,1114111,1593,1,128,1114111,1597,1430,3,0,1,0,3,0,4,0,0,4,0,0,25,0,0,165,0,1,4,165,0,40,0,0,16,0,0,57,0,0,56,0,0,9,0,1,1,9,0,10,0,0,15,0,0,18,0,0,8,0,0,19,0,0,7,0,0,17,0,0,145,0,0,145,0,0,26,0,0,27,0,0,47,0,0,28,0,0,48,0,0,46,0,0,41,0,0,158,0,0,11,0,1,1,11,0,12,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,13,0,1,2,13,0,14,0,1,3,14,0,158,0,0,158,0,0,158,0,0,172,0,0,173,0,0,43,0,0,24,0,0,51,0,0,0,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,33,0,0,22,0,0,31,0,0,20,0,0,29,0,0,21,0,0,30,0,0,34,0,0,36,0,0,142,0,0,2,0,1,0,2,0,32,0,0,142,0,0,153,0,0,152,0,0,145,0,0,38,0,0,39,0,0,49,0,0,54,0,0,35,0,0,50,0,0,45,0,0,42,0,0,42,0,0,158,0,0,158,0,0,158,0,0,102,0,0,158,0,0,82,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,96,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,89,0,0,158,0,0,104,0,0,103,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,23,0,0,44,0,0,44,0,0,24,0,0,52,0,0,166,0,1,5,166,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,156,0,0,6,0,0,37,0,0,2,0,1,0,2,0,151,0,0,142,0,0,152,0,0,148,0,0,55,0,0,45,0,0,42,0,0,158,0,0,158,0,0,158,0,0,158,0,0,53,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,95,0,0,76,0,0,66,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,107,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,67,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,92,0,0,158,0,0,78,0,0,79,0,0,158,0,0,158,0,0,44,0,0,106,0,0,106,0,0,105,0,0,105,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,142,0,0,1,0,1,0,1,0,2,0,1,0,2,0,2,0,1,0,2,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,116,0,0,158,0,0,158,0,0,90,0,0,113,0,0,158,0,0,158,0,0,158,0,0,158,0,0,63,0,0,158,0,0,158,0,0,158,0,0,84,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,155,0,0,158,0,0,128,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,85,0,0,158,0,0,154,0,0,158,0,0,158,0,0,158,0,0,91,0,0,158,0,0,158,0,0,24,0,0,106,0,0,105,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,43,0,0,2,0,1,0,2,0,2,0,1,0,2,0,45,0,0,42,0,0,158,0,0,158,0,0,158,0,0,101,0,0,93,0,0,74,0,0,158,0,0,129,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,64,0,0,127,0,0,158,0,0,122,0,0,158,0,0,117,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,69,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,86,0,0,158,0,0,158,0,0,98,0,0,158,0,0,158,0,0,118,0,0,158,0,0,88,0,0,97,0,0,44,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,44,0,0,2,0,1,0,2,0,2,0,1,0,2,0,2,0,1,0,2,0,2,0,1,0,2,0,158,0,0,136,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,135,0,0,158,0,0,158,0,0,73,0,0,121,0,0,158,0,0,158,0,0,158,0,0,158,0,0,77,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,109,0,0,158,0,0,158,0,0,99,0,0,114,0,0,158,0,0,158,0,0,158,0,0,61,0,0,158,0,0,87,0,0,131,0,0,106,0,0,105,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,44,0,0,2,0,1,0,2,0,2,0,1,0,2,0,2,0,1,0,2,0,158,0,0,158,0,0,60,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,108,0,0,158,0,0,94,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,158,0,0,72,0,0,110,0,0,158,0,0,158,0,0,158,0,0,134,0,0,158,0,0,62,0,0,124,0,0,119,0,0,158,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,126,0,0,158,0,0,158,0,0,158,0,0,100,0,0,158,0,0,71,0,0,123,0,0,158,0,0,112,0,0,130,0,0,132,0,0,120,0,0,125,0,0,65,0,0,158,0,0,68,0,0,58,0,0,70,0,0,61,0,0,158,0,0,160,0,0,160,0,0,160,0,0,160,0,0,160,0,0,158,0,0,60,0,0,83,0,0,158,0,0,158,0,0,75,0,0,111,0,0,62,0,0,80,0,0,160,0,0,160,0,0,160,0,0,115,0,0,158,0,0,59,0,0,158,0,0,58,0,0,160,0,0,160,0,0,81,0,0,133,0,0,59,0,0,176,0,0,174,0,1,3,174,0,176,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,178,0,1,2,178,0,177,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,175,0,0,182,0,0,180,0,0,182,0,0,180,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,183,0,1,2,183,0,179,0,1,3,179,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,181,0,0,313,0,1,0,313,0,314,0,1,0,314,0,314,0,1,0,314,0,202,0,1,24,202,0,240,0,2,4,240,0,62,240,0,218,0,1,40,218,0,193,0,1,15,193,0,239,0,1,61,239,0,238,0,1,60,238,0,186,0,2,1,186,0,8,186,0,184,0,2,3,184,0,6,184,0,192,0,1,14,192,0,195,0,1,17,195,0,191,0,1,13,191,0,196,0,1,18,196,0,190,0,1,12,190,0,194,0,1,16,194,0,303,0,1,125,303,0,303,0,1,125,303,0,203,0,1,25,203,0,204,0,1,26,204,0,225,0,1,47,225,0,205,0,1,27,205,0,226,0,1,48,226,0,224,0,1,46,224,0,219,0,1,41,219,0,311,0,1,133,311,0,187,0,2,1,187,0,9,187,0,185,0,2,3,185,0,7,185,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,188,0,2,2,188,0,10,188,0,189,0,2,3,189,0,11,189,0,221,0,1,43,221,0,201,0,1,23,201,0,201,0,1,23,201,0,229,0,1,51,229,0,210,0,1,32,210,0,199,0,1,21,199,0,208,0,1,30,208,0,197,0,1,19,197,0,206,0,1,28,206,0,198,0,1,20,198,0,207,0,1,29,207,0,211,0,1,33,211,0,213,0,1,35,213,0,307,0,1,129,307,0,312,0,1,0,312,0,209,0,1,31,209,0,307,0,1,129,307,0,309,0,1,131,309,0,310,0,1,132,310,0,216,0,1,38,216,0,217,0,1,39,217,0,227,0,1,49,227,0,236,0,1,58,236,0,212,0,1,34,212,0,228,0,1,50,228,0,223,0,1,45,223,0,223,0,1,45,223,0,220,0,1,42,220,0,220,0,1,42,220,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,234,0,1,56,234,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,272,0,1,94,272,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,265,0,1,87,265,0,247,0,1,69,247,0,231,0,1,53,231,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,200,0,1,22,200,0,222,0,1,44,222,0,222,0,1,44,222,0,201,0,1,23,201,0,230,0,1,52,230,0,241,0,2,5,241,0,63,241,0,306,0,1,128,306,0,215,0,1,37,215,0,214,0,1,36,214,0,221,0,1,43,221,0,305,0,1,127,305,0,307,0,1,129,307,0,310,0,1,132,310,0,304,0,1,126,304,0,237,0,1,59,237,0,223,0,1,45,223,0,220,0,1,42,220,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,235,0,1,57,235,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,271,0,1,93,271,0,244,0,1,66,244,0,252,0,1,74,252,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,248,0,1,70,248,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,253,0,1,75,253,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,268,0,1,90,268,0,242,0,1,64,242,0,243,0,1,65,243,0,311,0,1,133,311,0,311,0,1,133,311,0,222,0,1,44,222,0,233,0,1,55,233,0,233,0,1,55,233,0,232,0,1,54,232,0,232,0,1,54,232,0,312,0,1,0,312,0,222,0,1,44,222,0,312,0,1,0,312,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,281,0,1,103,281,0,311,0,1,133,311,0,266,0,1,88,266,0,278,0,1,100,278,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,250,0,1,72,250,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,308,0,1,130,308,0,311,0,1,133,311,0,293,0,1,115,293,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,302,0,1,124,302,0,311,0,1,133,311,0,311,0,1,133,311,0,267,0,1,89,267,0,311,0,1,133,311,0,201,0,1,23,201,0,233,0,1,55,233,0,232,0,1,54,232,0,221,0,1,43,221,0,312,0,1,0,312,0,222,0,1,44,222,0,223,0,1,45,223,0,220,0,1,42,220,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,261,0,1,83,261,0,269,0,1,91,269,0,294,0,1,116,294,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,249,0,1,71,249,0,292,0,1,114,292,0,287,0,1,109,287,0,311,0,1,133,311,0,282,0,1,104,282,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,255,0,1,77,255,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,246,0,1,68,246,0,311,0,1,133,311,0,311,0,1,133,311,0,258,0,1,80,258,0,283,0,1,105,283,0,311,0,1,133,311,0,273,0,1,95,273,0,222,0,1,44,222,0,222,0,1,44,222,0,312,0,1,0,312,0,312,0,1,0,312,0,221,0,1,43,221,0,221,0,1,43,221,0,311,0,1,133,311,0,301,0,1,123,301,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,300,0,1,122,300,0,311,0,1,133,311,0,311,0,1,133,311,0,286,0,1,108,286,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,245,0,1,67,245,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,274,0,1,96,274,0,311,0,1,133,311,0,311,0,1,133,311,0,259,0,1,81,259,0,279,0,1,101,279,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,296,0,1,118,296,0,233,0,1,55,233,0,232,0,1,54,232,0,222,0,1,44,222,0,222,0,1,44,222,0,312,0,1,0,312,0,222,0,1,44,222,0,311,0,1,133,311,0,311,0,1,133,311,0,264,0,1,86,264,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,270,0,1,92,270,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,275,0,1,97,275,0,311,0,1,133,311,0,311,0,1,133,311,0,311,0,1,133,311,0,299,0,1,121,299,0,311,0,1,133,311,0,289,0,1,111,289,0,284,0,1,106,284,0,291,0,1,113,291,0,311,0,1,133,311,0,260,0,1,82,260,0,311,0,1,133,311,0,257,0,1,79,257,0,288,0,1,110,288,0,277,0,1,99,277,0,295,0,1,117,295,0,297,0,1,119,297,0,285,0,1,107,285,0,290,0,1,112,290,0,251,0,1,73,251,0,311,0,1,133,311,0,254,0,1,76,254,0,262,0,1,84,262,0,256,0,1,78,256,0,311,0,1,133,311,0,264,0,1,86,264,0,311,0,1,133,311,0,276,0,1,98,276,0,280,0,1,102,280,0,263,0,1,85,263,0,311,0,1,133,311,0,262,0,1,84,262,0,298,0,1,120,298,0,263,0,1,85,263,0,315,0,0,1598,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,1,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,2,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,3,4294967295,0,4294967295,1,42,42,4,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,5,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,6,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,7,4294967295,0,4294967295,1,42,42,8,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,9,4294967295,0,4294967295,1,42,42,10,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,11,4294967295,1,42,42,12,4294967295,1,42,42,13,4294967295,0,4294967295,0,4294967295,1,42,42,14,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,15,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,16,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,17,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,18,4294967295,0,4294967295,1,42,42,19,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,20,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,21,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,22,4294967295,0,4294967295,1,42,42,23,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,24,4294967295,0,4294967295,1,42,42,25,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,1,42,42,26,4294967295,1,42,42,27,4294967295,1,42,42,28,4294967295,0,4294967295,0,4294967295,1,42,42,29,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,4294967295,0,30,5,0,0,652,0,0,795,0,2,652,0,0,801,0,4,652,9,648,1,0,1,1,0,657,1,0,1,0,0,652,1,0,1,0,0,648,43,0,1,3,0,657,43,0,1,2,0,652,43,0,1,2,0,648,44,0,1,5,0,657,44,0,1,4,0,652,44,0,1,4,0,2,0,0,740,0,1,652,3,648,24,0,1,2,0,657,24,0,1,1,0,652,24,0,1,1,0,4,0,0,795,0,1,652,0,0,801,0,3,652,6,648,43,0,1,2,0,657,43,0,1,1,0,652,43,0,1,1,0,648,44,0,1,4,0,657,44,0,1,3,0,652,44,0,1,3,0,2,0,0,809,0,1,652,3,648,45,0,1,2,0,657,45,0,1,1,0,652,45,0,1,1,0,2,0,0,791,0,1,652,3,648,42,0,1,2,0,657,42,0,1,1,0,652,42,0,1,1,0,2,0,0,806,0,1,652,3,648,44,0,1,2,0,657,44,0,1,1,0,652,44,0,1,1,0,4,0,0,795,0,1,652,0,0,801,0,3,652,6,648,43,0,1,2,0,657,43,0,1,1,0,652,43,0,1,1,0,648,44,0,1,4,0,657,44,0,1,3,0,652,44,0,1,3,0,2,0,0,1163,0,1,652,3,648,106,0,1,2,0,657,106,0,1,1,0,652,106,0,1,1,0,2,0,0,1155,0,1,652,3,648,105,0,1,2,0,657,105,0,1,1,0,652,105,0,1,1,0,4,0,0,806,0,0,801,0,2,652,1,1,3,3,648,44,0,1,4,0,657,44,0,1,2,0,652,44,0,1,2,0,4,0,0,795,0,0,801,0,0,806,0,3,652,6,666,2,0,0,0,0,666,43,0,0,1,0,666,44,0,0,2,0,648,44,0,1,4,0,657,44,0,1,3,0,652,44,0,1,3,0,4,0,0,795,0,1,652,0,0,801,0,3,652,6,648,43,0,1,2,0,657,43,0,1,1,0,652,43,0,1,1,0,648,44,0,1,4,0,657,44,0,1,3,0,652,44,0,1,3,0,2,0,0,801,0,1,652,3,648,44,0,1,2,0,657,44,0,1,1,0,652,44,0,1,1,0,2,0,0,801,0,1,652,3,648,44,0,1,2,0,657,44,0,1,1,0,652,44,0,1,1,0,4,0,0,795,0,0,801,0,0,806,0,3,652,7,666,2,0,0,0,0,666,43,0,0,1,0,666,44,0,0,2,0,648,44,0,0,3,0,648,44,0,1,4,0,657,44,0,1,3,0,652,44,0,1,3,0,8,0,0,1868,0,1,795,0,2,652,0,0,1872,0,4,801,0,5,652,0,0,2239,0,7,652,9,648,221,0,1,3,0,657,221,0,1,2,0,652,221,0,1,2,0,648,222,0,1,6,0,657,222,0,1,5,0,652,222,0,1,5,0,648,312,0,1,8,0,657,312,0,1,7,0,652,312,0,1,7,0,2,0,0,1788,0,1,652,3,648,201,0,1,2,0,657,201,0,1,1,0,652,201,0,1,1,0,6,0,0,1868,0,1,795,0,2,652,0,0,1872,0,4,801,0,5,652,6,648,221,0,1,3,0,657,221,0,1,2,0,652,221,0,1,2,0,648,222,0,1,6,0,657,222,0,1,5,0,652,222,0,1,5,0,2,0,0,1879,0,1,652,3,648,223,0,1,2,0,657,223,0,1,1,0,652,223,0,1,1,0,2,0,0,1864,0,1,652,3,648,220,0,1,2,0,657,220,0,1,1,0,652,220,0,1,1,0,2,0,0,1872,0,1,652,3,648,222,0,1,2,0,657,222,0,1,1,0,652,222,0,1,1,0,6,0,0,1868,0,1,795,0,2,652,0,0,1872,0,4,801,0,5,652,6,648,221,0,1,3,0,657,221,0,1,2,0,652,221,0,1,2,0,648,222,0,1,6,0,657,222,0,1,5,0,652,222,0,1,5,0,2,0,0,1919,0,1,652,3,648,233,0,1,2,0,657,233,0,1,1,0,652,233,0,1,1,0,2,0,0,1915,0,1,652,3,648,232,0,1,2,0,657,232,0,1,1,0,652,232,0,1,1,0,4,0,0,1872,0,1,801,0,2,652,1,1,3,3,648,222,0,1,4,0,657,222,0,1,2,0,652,222,0,1,2,0,6,0,0,1868,0,1,795,0,0,1872,0,3,801,0,3,652,0,0,2239,6,666,221,0,0,2,0,666,222,0,0,4,0,648,222,0,1,5,0,657,222,0,1,3,0,652,222,0,1,3,0,666,312,0,0,6,0,6,0,0,1868,0,1,795,0,2,652,0,0,1872,0,4,801,0,5,652,6,648,221,0,1,3,0,657,221,0,1,2,0,652,221,0,1,2,0,648,222,0,1,6,0,657,222,0,1,5,0,652,222,0,1,5,0,3,0,0,1872,0,1,801,0,2,652,3,648,222,0,1,3,0,657,222,0,1,2,0,652,222,0,1,2,0,3,0,0,1872,0,1,801,0,2,652,3,648,222,0,1,3,0,657,222,0,1,2,0,652,222,0,1,2,0,6,0,0,1868,0,1,795,0,0,1872,0,3,801,0,3,652,0,0,2239,7,666,221,0,0,2,0,666,222,0,0,4,0,648,222,0,0,3,0,648,222,0,1,5,0,657,222,0,1,3,0,652,222,0,1,3,0,666,312,0,0,6,0]; - -static LEXER_DFA_CELL: OnceLock = OnceLock::new(); - -/// Ahead-of-time lexer DFA tables compiled by antlr4-rust-gen, embedded so -/// runtime startup only deserializes them. Rebuilt from the ATN instead when -/// the embedded stream comes from a different runtime version. -fn lexer_dfa() -> &'static CompiledLexerDfa { - LEXER_DFA_CELL.get_or_init(|| { - CompiledLexerDfa::from_serialized(LEXER_DFA_DATA) - .unwrap_or_else(|| CompiledLexerDfa::compile(atn())) - }) -} - -#[derive(Clone, Debug)] -pub struct KotlinLexer -where - I: CharStream, - H: antlr4_runtime::SemanticHooks, -{ - base: BaseLexer, - hooks: H, -} - -impl KotlinLexer -where - I: CharStream, -{ - pub fn new(input: I) -> Self { - Self::with_hooks(input, antlr4_runtime::NoSemanticHooks) - } -} - -impl KotlinLexer -where - I: CharStream, - H: antlr4_runtime::SemanticHooks, -{ - pub fn with_hooks(input: I, hooks: H) -> Self { - let grammar_metadata = metadata(); - let data = grammar_metadata.recognizer_data(); - Self { base: BaseLexer::new(input, data).with_shared_dfa(atn()), hooks } - } - - - -} - - - -antlr4_runtime::__antlr4_rust_lexer_facade! { - type: KotlinLexer, - fields: { - base: base, - hooks: hooks, - }, - metadata: metadata, - next_token(lexer, sink) { - if H::ENABLES_LEXER_LIFECYCLE { - antlr4_runtime::atn::lexer::next_token_compiled_with_semantic_dispatch(&mut lexer.base, sink, atn(), lexer_dfa(), &mut lexer.hooks, |_, _| false, |_, _| None, antlr4_runtime::UnknownSemanticPolicy::Error, |_, _, _| {}) - } else { - antlr4_runtime::atn::lexer::next_token_compiled(&mut lexer.base, sink, atn(), lexer_dfa()) - } - } -} -} - -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -pub use self::__antlr4_rust_generated::*; diff --git a/crates/mehen-kotlin-parser/src/generated/kotlin_parser.rs b/crates/mehen-kotlin-parser/src/generated/kotlin_parser.rs deleted file mode 100644 index 94e2e8c0..00000000 --- a/crates/mehen-kotlin-parser/src/generated/kotlin_parser.rs +++ /dev/null @@ -1,27323 +0,0 @@ -// @generated by antlr-rust-codegen v0.33.1 - do not edit -// project: https://github.com/ophi-dev/antlr-rust-runtime -antlr4_runtime::__antlr4_rust_require_codegen_api!(14, "0.33.1"); -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -#[rustfmt::skip] -mod __antlr4_rust_generated { - -use antlr4_runtime::token::TokenSource; -use antlr4_runtime::token_stream::CommonTokenStream; -use antlr4_runtime::atn::parser_atn::ParserAtn; -use antlr4_runtime::generated::GeneratedRuleError; -use antlr4_runtime::{BaseParser, GrammarMetadata, Parser, Recognizer}; -use std::sync::OnceLock; -#[allow(unused_imports)] -use std::io::Write as _; -#[allow(unused_imports)] -use antlr4_runtime::{java_style_list, PredictionMode, BailErrorStrategy, TerminalNodeView as RuntimeTerminalNode, ErrorNodeView as RuntimeErrorNode, RuleNodeView, AsRuleNode, FromRuleNode, MissingChildError, Token as _}; -pub use antlr4_runtime::generated::{ErrorNode, StoredTreeContext, TerminalNode, __GeneratedInput, __GeneratedTokenView}; -#[allow(unused_imports)] -use antlr4_runtime::generated::{__ActiveParserContext, __FromActiveRuleContext, __GeneratedRuleContext, __RecoveryContextState, __active_context_view, __active_context_view_with_attrs, __context_children, __labeled_token_children, __labeled_token_children_matching, __rule_children, __terminal_children, __token_children, __token_children_matching, __write_invocation_states}; - - -pub const EOF: i32 = antlr4_runtime::TOKEN_EOF; -pub const SHEBANG_LINE: i32 = 1; -pub const DELIMITED_COMMENT: i32 = 2; -pub const LINE_COMMENT: i32 = 3; -pub const WS: i32 = 4; -pub const NL: i32 = 5; -pub const RESERVED: i32 = 6; -pub const DOT: i32 = 7; -pub const COMMA: i32 = 8; -pub const LPAREN: i32 = 9; -pub const RPAREN: i32 = 10; -pub const LSQUARE: i32 = 11; -pub const RSQUARE: i32 = 12; -pub const LCURL: i32 = 13; -pub const RCURL: i32 = 14; -pub const MULT: i32 = 15; -pub const MOD: i32 = 16; -pub const DIV: i32 = 17; -pub const ADD: i32 = 18; -pub const SUB: i32 = 19; -pub const INCR: i32 = 20; -pub const DECR: i32 = 21; -pub const CONJ: i32 = 22; -pub const DISJ: i32 = 23; -pub const EXCL_WS: i32 = 24; -pub const EXCL_NO_WS: i32 = 25; -pub const COLON: i32 = 26; -pub const SEMICOLON: i32 = 27; -pub const ASSIGNMENT: i32 = 28; -pub const ADD_ASSIGNMENT: i32 = 29; -pub const SUB_ASSIGNMENT: i32 = 30; -pub const MULT_ASSIGNMENT: i32 = 31; -pub const DIV_ASSIGNMENT: i32 = 32; -pub const MOD_ASSIGNMENT: i32 = 33; -pub const ARROW: i32 = 34; -pub const DOUBLE_ARROW: i32 = 35; -pub const RANGE: i32 = 36; -pub const RANGE_UNTIL: i32 = 37; -pub const COLONCOLON: i32 = 38; -pub const DOUBLE_SEMICOLON: i32 = 39; -pub const HASH: i32 = 40; -pub const AT_NO_WS: i32 = 41; -pub const AT_POST_WS: i32 = 42; -pub const AT_PRE_WS: i32 = 43; -pub const AT_BOTH_WS: i32 = 44; -pub const QUEST_WS: i32 = 45; -pub const QUEST_NO_WS: i32 = 46; -pub const LANGLE: i32 = 47; -pub const RANGLE: i32 = 48; -pub const LE: i32 = 49; -pub const GE: i32 = 50; -pub const EXCL_EQ: i32 = 51; -pub const EXCL_EQEQ: i32 = 52; -pub const AS_SAFE: i32 = 53; -pub const EQEQ: i32 = 54; -pub const EQEQEQ: i32 = 55; -pub const SINGLE_QUOTE: i32 = 56; -pub const AMP: i32 = 57; -pub const RETURN_AT: i32 = 58; -pub const CONTINUE_AT: i32 = 59; -pub const BREAK_AT: i32 = 60; -pub const THIS_AT: i32 = 61; -pub const SUPER_AT: i32 = 62; -pub const FILE: i32 = 63; -pub const FIELD: i32 = 64; -pub const PROPERTY: i32 = 65; -pub const GET: i32 = 66; -pub const SET: i32 = 67; -pub const RECEIVER: i32 = 68; -pub const PARAM: i32 = 69; -pub const SETPARAM: i32 = 70; -pub const DELEGATE: i32 = 71; -pub const PACKAGE: i32 = 72; -pub const IMPORT: i32 = 73; -pub const CLASS: i32 = 74; -pub const INTERFACE: i32 = 75; -pub const FUN: i32 = 76; -pub const OBJECT: i32 = 77; -pub const VAL: i32 = 78; -pub const VAR: i32 = 79; -pub const TYPE_ALIAS: i32 = 80; -pub const CONSTRUCTOR: i32 = 81; -pub const BY: i32 = 82; -pub const COMPANION: i32 = 83; -pub const INIT: i32 = 84; -pub const THIS: i32 = 85; -pub const SUPER: i32 = 86; -pub const TYPEOF: i32 = 87; -pub const WHERE: i32 = 88; -pub const IF: i32 = 89; -pub const ELSE: i32 = 90; -pub const WHEN: i32 = 91; -pub const TRY: i32 = 92; -pub const CATCH: i32 = 93; -pub const FINALLY: i32 = 94; -pub const FOR: i32 = 95; -pub const DO: i32 = 96; -pub const WHILE: i32 = 97; -pub const THROW: i32 = 98; -pub const RETURN: i32 = 99; -pub const CONTINUE: i32 = 100; -pub const BREAK: i32 = 101; -pub const AS: i32 = 102; -pub const IS: i32 = 103; -pub const IN: i32 = 104; -pub const NOT_IS: i32 = 105; -pub const NOT_IN: i32 = 106; -pub const OUT: i32 = 107; -pub const DYNAMIC: i32 = 108; -pub const PUBLIC: i32 = 109; -pub const PRIVATE: i32 = 110; -pub const PROTECTED: i32 = 111; -pub const INTERNAL: i32 = 112; -pub const ENUM: i32 = 113; -pub const SEALED: i32 = 114; -pub const ANNOTATION: i32 = 115; -pub const DATA: i32 = 116; -pub const INNER: i32 = 117; -pub const VALUE: i32 = 118; -pub const TAILREC: i32 = 119; -pub const OPERATOR: i32 = 120; -pub const INLINE: i32 = 121; -pub const INFIX: i32 = 122; -pub const EXTERNAL: i32 = 123; -pub const SUSPEND: i32 = 124; -pub const OVERRIDE: i32 = 125; -pub const ABSTRACT: i32 = 126; -pub const FINAL: i32 = 127; -pub const OPEN: i32 = 128; -pub const CONST: i32 = 129; -pub const LATEINIT: i32 = 130; -pub const VARARG: i32 = 131; -pub const NOINLINE: i32 = 132; -pub const CROSSINLINE: i32 = 133; -pub const REIFIED: i32 = 134; -pub const EXPECT: i32 = 135; -pub const ACTUAL: i32 = 136; -pub const REAL_LITERAL: i32 = 137; -pub const FLOAT_LITERAL: i32 = 138; -pub const DOUBLE_LITERAL: i32 = 139; -pub const INTEGER_LITERAL: i32 = 140; -pub const HEX_LITERAL: i32 = 141; -pub const BIN_LITERAL: i32 = 142; -pub const UNSIGNED_LITERAL: i32 = 143; -pub const LONG_LITERAL: i32 = 144; -pub const BOOLEAN_LITERAL: i32 = 145; -pub const NULL_LITERAL: i32 = 146; -pub const CHARACTER_LITERAL: i32 = 147; -pub const IDENTIFIER: i32 = 148; -pub const IDENTIFIER_OR_SOFT_KEY: i32 = 149; -pub const FIELD_IDENTIFIER: i32 = 150; -pub const QUOTE_OPEN: i32 = 151; -pub const TRIPLE_QUOTE_OPEN: i32 = 152; -pub const UNICODE_CLASS_LL: i32 = 153; -pub const UNICODE_CLASS_LM: i32 = 154; -pub const UNICODE_CLASS_LO: i32 = 155; -pub const UNICODE_CLASS_LT: i32 = 156; -pub const UNICODE_CLASS_LU: i32 = 157; -pub const UNICODE_CLASS_ND: i32 = 158; -pub const UNICODE_CLASS_NL: i32 = 159; -pub const QUOTE_CLOSE: i32 = 160; -pub const LINE_STR_REF: i32 = 161; -pub const LINE_STR_TEXT: i32 = 162; -pub const LINE_STR_ESCAPED_CHAR: i32 = 163; -pub const LINE_STR_EXPR_START: i32 = 164; -pub const TRIPLE_QUOTE_CLOSE: i32 = 165; -pub const MULTI_LINE_STRING_QUOTE: i32 = 166; -pub const MULTI_LINE_STR_REF: i32 = 167; -pub const MULTI_LINE_STR_TEXT: i32 = 168; -pub const MULTI_LINE_STR_EXPR_START: i32 = 169; -pub const INSIDE_COMMENT: i32 = 170; -pub const INSIDE_WS: i32 = 171; -pub const INSIDE_NL: i32 = 172; -pub const ERROR_CHARACTER: i32 = 173; - -pub const RULE_KOTLIN_FILE: usize = 0; -pub const RULE_SCRIPT: usize = 1; -pub const RULE_SHEBANG_LINE: usize = 2; -pub const RULE_FILE_ANNOTATION: usize = 3; -pub const RULE_PACKAGE_HEADER: usize = 4; -pub const RULE_IMPORT_LIST: usize = 5; -pub const RULE_IMPORT_HEADER: usize = 6; -pub const RULE_IMPORT_ALIAS: usize = 7; -pub const RULE_TOP_LEVEL_OBJECT: usize = 8; -pub const RULE_TYPE_ALIAS: usize = 9; -pub const RULE_DECLARATION: usize = 10; -pub const RULE_CLASS_DECLARATION: usize = 11; -pub const RULE_PRIMARY_CONSTRUCTOR: usize = 12; -pub const RULE_CLASS_BODY: usize = 13; -pub const RULE_CLASS_PARAMETERS: usize = 14; -pub const RULE_CLASS_PARAMETER: usize = 15; -pub const RULE_DELEGATION_SPECIFIERS: usize = 16; -pub const RULE_DELEGATION_SPECIFIER: usize = 17; -pub const RULE_CONSTRUCTOR_INVOCATION: usize = 18; -pub const RULE_ANNOTATED_DELEGATION_SPECIFIER: usize = 19; -pub const RULE_EXPLICIT_DELEGATION: usize = 20; -pub const RULE_TYPE_PARAMETERS: usize = 21; -pub const RULE_TYPE_PARAMETER: usize = 22; -pub const RULE_TYPE_CONSTRAINTS: usize = 23; -pub const RULE_TYPE_CONSTRAINT: usize = 24; -pub const RULE_CLASS_MEMBER_DECLARATIONS: usize = 25; -pub const RULE_CLASS_MEMBER_DECLARATION: usize = 26; -pub const RULE_ANONYMOUS_INITIALIZER: usize = 27; -pub const RULE_COMPANION_OBJECT: usize = 28; -pub const RULE_FUNCTION_VALUE_PARAMETERS: usize = 29; -pub const RULE_FUNCTION_VALUE_PARAMETER: usize = 30; -pub const RULE_FUNCTION_DECLARATION: usize = 31; -pub const RULE_FUNCTION_BODY: usize = 32; -pub const RULE_VARIABLE_DECLARATION: usize = 33; -pub const RULE_MULTI_VARIABLE_DECLARATION: usize = 34; -pub const RULE_PROPERTY_DECLARATION: usize = 35; -pub const RULE_PROPERTY_DELEGATE: usize = 36; -pub const RULE_GETTER: usize = 37; -pub const RULE_SETTER: usize = 38; -pub const RULE_PARAMETERS_WITH_OPTIONAL_TYPE: usize = 39; -pub const RULE_FUNCTION_VALUE_PARAMETER_WITH_OPTIONAL_TYPE: usize = 40; -pub const RULE_PARAMETER_WITH_OPTIONAL_TYPE: usize = 41; -pub const RULE_PARAMETER: usize = 42; -pub const RULE_OBJECT_DECLARATION: usize = 43; -pub const RULE_SECONDARY_CONSTRUCTOR: usize = 44; -pub const RULE_CONSTRUCTOR_DELEGATION_CALL: usize = 45; -pub const RULE_ENUM_CLASS_BODY: usize = 46; -pub const RULE_ENUM_ENTRIES: usize = 47; -pub const RULE_ENUM_ENTRY: usize = 48; -pub const RULE_TYPE: usize = 49; -pub const RULE_TYPE_REFERENCE: usize = 50; -pub const RULE_NULLABLE_TYPE: usize = 51; -pub const RULE_QUEST: usize = 52; -pub const RULE_USER_TYPE: usize = 53; -pub const RULE_SIMPLE_USER_TYPE: usize = 54; -pub const RULE_TYPE_PROJECTION: usize = 55; -pub const RULE_TYPE_PROJECTION_MODIFIERS: usize = 56; -pub const RULE_TYPE_PROJECTION_MODIFIER: usize = 57; -pub const RULE_FUNCTION_TYPE: usize = 58; -pub const RULE_FUNCTION_TYPE_PARAMETERS: usize = 59; -pub const RULE_PARENTHESIZED_TYPE: usize = 60; -pub const RULE_RECEIVER_TYPE: usize = 61; -pub const RULE_PARENTHESIZED_USER_TYPE: usize = 62; -pub const RULE_DEFINITELY_NON_NULLABLE_TYPE: usize = 63; -pub const RULE_STATEMENTS: usize = 64; -pub const RULE_STATEMENT: usize = 65; -pub const RULE_LABEL: usize = 66; -pub const RULE_CONTROL_STRUCTURE_BODY: usize = 67; -pub const RULE_BLOCK: usize = 68; -pub const RULE_LOOP_STATEMENT: usize = 69; -pub const RULE_FOR_STATEMENT: usize = 70; -pub const RULE_WHILE_STATEMENT: usize = 71; -pub const RULE_DO_WHILE_STATEMENT: usize = 72; -pub const RULE_ASSIGNMENT: usize = 73; -pub const RULE_SEMI: usize = 74; -pub const RULE_SEMIS: usize = 75; -pub const RULE_EXPRESSION: usize = 76; -pub const RULE_DISJUNCTION: usize = 77; -pub const RULE_CONJUNCTION: usize = 78; -pub const RULE_EQUALITY: usize = 79; -pub const RULE_COMPARISON: usize = 80; -pub const RULE_GENERIC_CALL_LIKE_COMPARISON: usize = 81; -pub const RULE_INFIX_OPERATION: usize = 82; -pub const RULE_ELVIS_EXPRESSION: usize = 83; -pub const RULE_ELVIS: usize = 84; -pub const RULE_INFIX_FUNCTION_CALL: usize = 85; -pub const RULE_RANGE_EXPRESSION: usize = 86; -pub const RULE_ADDITIVE_EXPRESSION: usize = 87; -pub const RULE_MULTIPLICATIVE_EXPRESSION: usize = 88; -pub const RULE_AS_EXPRESSION: usize = 89; -pub const RULE_PREFIX_UNARY_EXPRESSION: usize = 90; -pub const RULE_UNARY_PREFIX: usize = 91; -pub const RULE_POSTFIX_UNARY_EXPRESSION: usize = 92; -pub const RULE_POSTFIX_UNARY_SUFFIX: usize = 93; -pub const RULE_DIRECTLY_ASSIGNABLE_EXPRESSION: usize = 94; -pub const RULE_PARENTHESIZED_DIRECTLY_ASSIGNABLE_EXPRESSION: usize = 95; -pub const RULE_ASSIGNABLE_EXPRESSION: usize = 96; -pub const RULE_PARENTHESIZED_ASSIGNABLE_EXPRESSION: usize = 97; -pub const RULE_ASSIGNABLE_SUFFIX: usize = 98; -pub const RULE_INDEXING_SUFFIX: usize = 99; -pub const RULE_NAVIGATION_SUFFIX: usize = 100; -pub const RULE_CALL_SUFFIX: usize = 101; -pub const RULE_ANNOTATED_LAMBDA: usize = 102; -pub const RULE_TYPE_ARGUMENTS: usize = 103; -pub const RULE_VALUE_ARGUMENTS: usize = 104; -pub const RULE_VALUE_ARGUMENT: usize = 105; -pub const RULE_PRIMARY_EXPRESSION: usize = 106; -pub const RULE_PARENTHESIZED_EXPRESSION: usize = 107; -pub const RULE_COLLECTION_LITERAL: usize = 108; -pub const RULE_LITERAL_CONSTANT: usize = 109; -pub const RULE_STRING_LITERAL: usize = 110; -pub const RULE_LINE_STRING_LITERAL: usize = 111; -pub const RULE_MULTI_LINE_STRING_LITERAL: usize = 112; -pub const RULE_LINE_STRING_CONTENT: usize = 113; -pub const RULE_LINE_STRING_EXPRESSION: usize = 114; -pub const RULE_MULTI_LINE_STRING_CONTENT: usize = 115; -pub const RULE_MULTI_LINE_STRING_EXPRESSION: usize = 116; -pub const RULE_LAMBDA_LITERAL: usize = 117; -pub const RULE_LAMBDA_PARAMETERS: usize = 118; -pub const RULE_LAMBDA_PARAMETER: usize = 119; -pub const RULE_ANONYMOUS_FUNCTION: usize = 120; -pub const RULE_FUNCTION_LITERAL: usize = 121; -pub const RULE_OBJECT_LITERAL: usize = 122; -pub const RULE_THIS_EXPRESSION: usize = 123; -pub const RULE_SUPER_EXPRESSION: usize = 124; -pub const RULE_IF_EXPRESSION: usize = 125; -pub const RULE_WHEN_SUBJECT: usize = 126; -pub const RULE_WHEN_EXPRESSION: usize = 127; -pub const RULE_WHEN_ENTRY: usize = 128; -pub const RULE_WHEN_CONDITION: usize = 129; -pub const RULE_RANGE_TEST: usize = 130; -pub const RULE_TYPE_TEST: usize = 131; -pub const RULE_TRY_EXPRESSION: usize = 132; -pub const RULE_CATCH_BLOCK: usize = 133; -pub const RULE_FINALLY_BLOCK: usize = 134; -pub const RULE_JUMP_EXPRESSION: usize = 135; -pub const RULE_CALLABLE_REFERENCE: usize = 136; -pub const RULE_ASSIGNMENT_AND_OPERATOR: usize = 137; -pub const RULE_EQUALITY_OPERATOR: usize = 138; -pub const RULE_COMPARISON_OPERATOR: usize = 139; -pub const RULE_IN_OPERATOR: usize = 140; -pub const RULE_IS_OPERATOR: usize = 141; -pub const RULE_ADDITIVE_OPERATOR: usize = 142; -pub const RULE_MULTIPLICATIVE_OPERATOR: usize = 143; -pub const RULE_AS_OPERATOR: usize = 144; -pub const RULE_PREFIX_UNARY_OPERATOR: usize = 145; -pub const RULE_POSTFIX_UNARY_OPERATOR: usize = 146; -pub const RULE_EXCL: usize = 147; -pub const RULE_MEMBER_ACCESS_OPERATOR: usize = 148; -pub const RULE_SAFE_NAV: usize = 149; -pub const RULE_MODIFIERS: usize = 150; -pub const RULE_PARAMETER_MODIFIERS: usize = 151; -pub const RULE_MODIFIER: usize = 152; -pub const RULE_TYPE_MODIFIERS: usize = 153; -pub const RULE_TYPE_MODIFIER: usize = 154; -pub const RULE_CLASS_MODIFIER: usize = 155; -pub const RULE_MEMBER_MODIFIER: usize = 156; -pub const RULE_VISIBILITY_MODIFIER: usize = 157; -pub const RULE_VARIANCE_MODIFIER: usize = 158; -pub const RULE_TYPE_PARAMETER_MODIFIERS: usize = 159; -pub const RULE_TYPE_PARAMETER_MODIFIER: usize = 160; -pub const RULE_FUNCTION_MODIFIER: usize = 161; -pub const RULE_PROPERTY_MODIFIER: usize = 162; -pub const RULE_INHERITANCE_MODIFIER: usize = 163; -pub const RULE_PARAMETER_MODIFIER: usize = 164; -pub const RULE_REIFICATION_MODIFIER: usize = 165; -pub const RULE_PLATFORM_MODIFIER: usize = 166; -pub const RULE_ANNOTATION: usize = 167; -pub const RULE_SINGLE_ANNOTATION: usize = 168; -pub const RULE_MULTI_ANNOTATION: usize = 169; -pub const RULE_ANNOTATION_USE_SITE_TARGET: usize = 170; -pub const RULE_UNESCAPED_ANNOTATION: usize = 171; -pub const RULE_SIMPLE_IDENTIFIER: usize = 172; -pub const RULE_IDENTIFIER: usize = 173; - -pub static METADATA: GrammarMetadata = GrammarMetadata::new( - "KotlinParser", - &["kotlinFile", "script", "shebangLine", "fileAnnotation", "packageHeader", "importList", "importHeader", "importAlias", "topLevelObject", "typeAlias", "declaration", "classDeclaration", "primaryConstructor", "classBody", "classParameters", "classParameter", "delegationSpecifiers", "delegationSpecifier", "constructorInvocation", "annotatedDelegationSpecifier", "explicitDelegation", "typeParameters", "typeParameter", "typeConstraints", "typeConstraint", "classMemberDeclarations", "classMemberDeclaration", "anonymousInitializer", "companionObject", "functionValueParameters", "functionValueParameter", "functionDeclaration", "functionBody", "variableDeclaration", "multiVariableDeclaration", "propertyDeclaration", "propertyDelegate", "getter", "setter", "parametersWithOptionalType", "functionValueParameterWithOptionalType", "parameterWithOptionalType", "parameter", "objectDeclaration", "secondaryConstructor", "constructorDelegationCall", "enumClassBody", "enumEntries", "enumEntry", "type", "typeReference", "nullableType", "quest", "userType", "simpleUserType", "typeProjection", "typeProjectionModifiers", "typeProjectionModifier", "functionType", "functionTypeParameters", "parenthesizedType", "receiverType", "parenthesizedUserType", "definitelyNonNullableType", "statements", "statement", "label", "controlStructureBody", "block", "loopStatement", "forStatement", "whileStatement", "doWhileStatement", "assignment", "semi", "semis", "expression", "disjunction", "conjunction", "equality", "comparison", "genericCallLikeComparison", "infixOperation", "elvisExpression", "elvis", "infixFunctionCall", "rangeExpression", "additiveExpression", "multiplicativeExpression", "asExpression", "prefixUnaryExpression", "unaryPrefix", "postfixUnaryExpression", "postfixUnarySuffix", "directlyAssignableExpression", "parenthesizedDirectlyAssignableExpression", "assignableExpression", "parenthesizedAssignableExpression", "assignableSuffix", "indexingSuffix", "navigationSuffix", "callSuffix", "annotatedLambda", "typeArguments", "valueArguments", "valueArgument", "primaryExpression", "parenthesizedExpression", "collectionLiteral", "literalConstant", "stringLiteral", "lineStringLiteral", "multiLineStringLiteral", "lineStringContent", "lineStringExpression", "multiLineStringContent", "multiLineStringExpression", "lambdaLiteral", "lambdaParameters", "lambdaParameter", "anonymousFunction", "functionLiteral", "objectLiteral", "thisExpression", "superExpression", "ifExpression", "whenSubject", "whenExpression", "whenEntry", "whenCondition", "rangeTest", "typeTest", "tryExpression", "catchBlock", "finallyBlock", "jumpExpression", "callableReference", "assignmentAndOperator", "equalityOperator", "comparisonOperator", "inOperator", "isOperator", "additiveOperator", "multiplicativeOperator", "asOperator", "prefixUnaryOperator", "postfixUnaryOperator", "excl", "memberAccessOperator", "safeNav", "modifiers", "parameterModifiers", "modifier", "typeModifiers", "typeModifier", "classModifier", "memberModifier", "visibilityModifier", "varianceModifier", "typeParameterModifiers", "typeParameterModifier", "functionModifier", "propertyModifier", "inheritanceModifier", "parameterModifier", "reificationModifier", "platformModifier", "annotation", "singleAnnotation", "multiAnnotation", "annotationUseSiteTarget", "unescapedAnnotation", "simpleIdentifier", "identifier"], - &[None, None, None, None, None, None, Some("\'...\'"), Some("\'.\'"), Some("\',\'"), Some("\'(\'"), Some("\')\'"), Some("\'[\'"), Some("\']\'"), Some("\'{\'"), Some("\'}\'"), Some("\'*\'"), Some("\'%\'"), Some("\'/\'"), Some("\'+\'"), Some("\'-\'"), Some("\'++\'"), Some("\'--\'"), Some("\'&&\'"), Some("\'||\'"), None, Some("\'!\'"), Some("\':\'"), Some("\';\'"), Some("\'=\'"), Some("\'+=\'"), Some("\'-=\'"), Some("\'*=\'"), Some("\'/=\'"), Some("\'%=\'"), Some("\'->\'"), Some("\'=>\'"), Some("\'..\'"), Some("\'..<\'"), Some("\'::\'"), Some("\';;\'"), Some("\'#\'"), Some("\'@\'"), None, None, None, None, Some("\'?\'"), Some("\'<\'"), Some("\'>\'"), Some("\'<=\'"), Some("\'>=\'"), Some("\'!=\'"), Some("\'!==\'"), Some("\'as?\'"), Some("\'==\'"), Some("\'===\'"), Some("\'\\\'\'"), Some("\'&\'"), None, None, None, None, None, Some("\'file\'"), Some("\'field\'"), Some("\'property\'"), Some("\'get\'"), Some("\'set\'"), Some("\'receiver\'"), Some("\'param\'"), Some("\'setparam\'"), Some("\'delegate\'"), Some("\'package\'"), Some("\'import\'"), Some("\'class\'"), Some("\'interface\'"), Some("\'fun\'"), Some("\'object\'"), Some("\'val\'"), Some("\'var\'"), Some("\'typealias\'"), Some("\'constructor\'"), Some("\'by\'"), Some("\'companion\'"), Some("\'init\'"), Some("\'this\'"), Some("\'super\'"), Some("\'typeof\'"), Some("\'where\'"), Some("\'if\'"), Some("\'else\'"), Some("\'when\'"), Some("\'try\'"), Some("\'catch\'"), Some("\'finally\'"), Some("\'for\'"), Some("\'do\'"), Some("\'while\'"), Some("\'throw\'"), Some("\'return\'"), Some("\'continue\'"), Some("\'break\'"), Some("\'as\'"), Some("\'is\'"), Some("\'in\'"), None, None, Some("\'out\'"), Some("\'dynamic\'"), Some("\'public\'"), Some("\'private\'"), Some("\'protected\'"), Some("\'internal\'"), Some("\'enum\'"), Some("\'sealed\'"), Some("\'annotation\'"), Some("\'data\'"), Some("\'inner\'"), Some("\'value\'"), Some("\'tailrec\'"), Some("\'operator\'"), Some("\'inline\'"), Some("\'infix\'"), Some("\'external\'"), Some("\'suspend\'"), Some("\'override\'"), Some("\'abstract\'"), Some("\'final\'"), Some("\'open\'"), Some("\'const\'"), Some("\'lateinit\'"), Some("\'vararg\'"), Some("\'noinline\'"), Some("\'crossinline\'"), Some("\'reified\'"), Some("\'expect\'"), Some("\'actual\'"), None, None, None, None, None, None, None, None, None, Some("\'null\'"), None, None, None, None, None, Some("\'\"\"\"\'"), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &[None, Some("ShebangLine"), Some("DelimitedComment"), Some("LineComment"), Some("WS"), Some("NL"), Some("RESERVED"), Some("DOT"), Some("COMMA"), Some("LPAREN"), Some("RPAREN"), Some("LSQUARE"), Some("RSQUARE"), Some("LCURL"), Some("RCURL"), Some("MULT"), Some("MOD"), Some("DIV"), Some("ADD"), Some("SUB"), Some("INCR"), Some("DECR"), Some("CONJ"), Some("DISJ"), Some("EXCL_WS"), Some("EXCL_NO_WS"), Some("COLON"), Some("SEMICOLON"), Some("ASSIGNMENT"), Some("ADD_ASSIGNMENT"), Some("SUB_ASSIGNMENT"), Some("MULT_ASSIGNMENT"), Some("DIV_ASSIGNMENT"), Some("MOD_ASSIGNMENT"), Some("ARROW"), Some("DOUBLE_ARROW"), Some("RANGE"), Some("RANGE_UNTIL"), Some("COLONCOLON"), Some("DOUBLE_SEMICOLON"), Some("HASH"), Some("AT_NO_WS"), Some("AT_POST_WS"), Some("AT_PRE_WS"), Some("AT_BOTH_WS"), Some("QUEST_WS"), Some("QUEST_NO_WS"), Some("LANGLE"), Some("RANGLE"), Some("LE"), Some("GE"), Some("EXCL_EQ"), Some("EXCL_EQEQ"), Some("AS_SAFE"), Some("EQEQ"), Some("EQEQEQ"), Some("SINGLE_QUOTE"), Some("AMP"), Some("RETURN_AT"), Some("CONTINUE_AT"), Some("BREAK_AT"), Some("THIS_AT"), Some("SUPER_AT"), Some("FILE"), Some("FIELD"), Some("PROPERTY"), Some("GET"), Some("SET"), Some("RECEIVER"), Some("PARAM"), Some("SETPARAM"), Some("DELEGATE"), Some("PACKAGE"), Some("IMPORT"), Some("CLASS"), Some("INTERFACE"), Some("FUN"), Some("OBJECT"), Some("VAL"), Some("VAR"), Some("TYPE_ALIAS"), Some("CONSTRUCTOR"), Some("BY"), Some("COMPANION"), Some("INIT"), Some("THIS"), Some("SUPER"), Some("TYPEOF"), Some("WHERE"), Some("IF"), Some("ELSE"), Some("WHEN"), Some("TRY"), Some("CATCH"), Some("FINALLY"), Some("FOR"), Some("DO"), Some("WHILE"), Some("THROW"), Some("RETURN"), Some("CONTINUE"), Some("BREAK"), Some("AS"), Some("IS"), Some("IN"), Some("NOT_IS"), Some("NOT_IN"), Some("OUT"), Some("DYNAMIC"), Some("PUBLIC"), Some("PRIVATE"), Some("PROTECTED"), Some("INTERNAL"), Some("ENUM"), Some("SEALED"), Some("ANNOTATION"), Some("DATA"), Some("INNER"), Some("VALUE"), Some("TAILREC"), Some("OPERATOR"), Some("INLINE"), Some("INFIX"), Some("EXTERNAL"), Some("SUSPEND"), Some("OVERRIDE"), Some("ABSTRACT"), Some("FINAL"), Some("OPEN"), Some("CONST"), Some("LATEINIT"), Some("VARARG"), Some("NOINLINE"), Some("CROSSINLINE"), Some("REIFIED"), Some("EXPECT"), Some("ACTUAL"), Some("RealLiteral"), Some("FloatLiteral"), Some("DoubleLiteral"), Some("IntegerLiteral"), Some("HexLiteral"), Some("BinLiteral"), Some("UnsignedLiteral"), Some("LongLiteral"), Some("BooleanLiteral"), Some("NullLiteral"), Some("CharacterLiteral"), Some("Identifier"), Some("IdentifierOrSoftKey"), Some("FieldIdentifier"), Some("QUOTE_OPEN"), Some("TRIPLE_QUOTE_OPEN"), Some("UNICODE_CLASS_LL"), Some("UNICODE_CLASS_LM"), Some("UNICODE_CLASS_LO"), Some("UNICODE_CLASS_LT"), Some("UNICODE_CLASS_LU"), Some("UNICODE_CLASS_ND"), Some("UNICODE_CLASS_NL"), Some("QUOTE_CLOSE"), Some("LineStrRef"), Some("LineStrText"), Some("LineStrEscapedChar"), Some("LineStrExprStart"), Some("TRIPLE_QUOTE_CLOSE"), Some("MultiLineStringQuote"), Some("MultiLineStrRef"), Some("MultiLineStrText"), Some("MultiLineStrExprStart"), Some("Inside_Comment"), Some("Inside_WS"), Some("Inside_NL"), Some("ErrorCharacter")], - &[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None], - &[], - &[], - &[], -); - -pub fn metadata() -> &'static GrammarMetadata { - &METADATA -} - -pub fn rule_names() -> &'static [&'static str] { - METADATA.rule_names() -} - -fn parser_semantics() -> &'static antlr4_runtime::ParserSemantics { - static SEMANTICS_CELL: OnceLock = OnceLock::new(); - SEMANTICS_CELL.get_or_init(|| { - let mut ir = antlr4_runtime::semir::SemIr::new(); - let mut predicates = Vec::new(); - - let actions = Vec::new(); - antlr4_runtime::ParserSemantics { ir, predicates, actions } - }) -} - - - -/// Marker carried by generated contexts whose required-child -/// invariants were checked after a syntax-clean parse, and grammar brand of -/// this module's validated tree and rule-node types. -/// -/// This marker stays module-local (unlike the runtime-owned support items) -/// so rustc can prove it never implements the runtime's -/// `__RecoveryContextState`, keeping the recovery-oriented and validated -/// accessor impls coherent — and so the runtime's branded validated types -/// stay nominally distinct per grammar. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct ValidatedTreeContext { - __private: (), -} - -/// A completed, syntax-clean parse tree whose generated child cardinalities -/// have been structurally validated. -/// -/// Alias of the runtime's grammar-agnostic `antlr4_runtime::ValidatedTree` -/// branded with this module's [`ValidatedTreeContext`] marker, so validated -/// trees of different grammars remain distinct types. -pub type KotlinValidatedTree = antlr4_runtime::ValidatedTree; - -/// A rule node borrowed from a [`KotlinValidatedTree`]. -/// -/// Alias of the runtime's `antlr4_runtime::ValidatedRuleNode` branded with -/// this module's [`ValidatedTreeContext`] marker. -pub type ValidatedRuleNode<'a> = antlr4_runtime::ValidatedRuleNode<'a, ValidatedTreeContext>; - -pub use antlr4_runtime::FromValidatedRuleNode; - -/// Failure to recognize or validate a strict generated parse. -/// -/// Alias of the grammar-agnostic `antlr4_runtime::ValidationError`; unlike -/// the branded tree types, the validation errors of every generated parser -/// are deliberately one shared type. -pub type KotlinValidationError = antlr4_runtime::ValidationError; - -#[allow(dead_code)] -fn __context_kind(context: RuleNodeView<'_>) -> usize { - context.rule_index() -} - -#[allow(dead_code)] -fn __active_context_kind( - context: &antlr4_runtime::ParserRuleContext, - _storage: &antlr4_runtime::ParseTreeStorage, - _tokens: &antlr4_runtime::TokenStore, -) -> usize { - context.rule_index() -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct KotlinFileContext { - rule_index: 0, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - KotlinFileContext { - rule shebang_line: optional(ShebangLineContext[2]), - rule file_annotation_children: many(FileAnnotationContext[3]), - rule package_header: required(PackageHeaderContext[4], "packageHeader"), - rule import_list: required(ImportListContext[5], "importList"), - rule top_level_object_children: many(TopLevelObjectContext[8]), - token eof_token: required(-1, "EOF"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ScriptContext { - rule_index: 1, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ScriptContext { - rule shebang_line: optional(ShebangLineContext[2]), - rule file_annotation_children: many(FileAnnotationContext[3]), - rule package_header: required(PackageHeaderContext[4], "packageHeader"), - rule import_list: required(ImportListContext[5], "importList"), - rule statement_children: many(StatementContext[65]), - rule semi_children: many(SemiContext[74]), - token eof_token: required(-1, "EOF"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ShebangLineContext { - rule_index: 2, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ShebangLineContext { - token shebang_line_token: required(1, "ShebangLine"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FileAnnotationContext { - rule_index: 3, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FileAnnotationContext { - rule unescaped_annotation_children: many(UnescapedAnnotationContext[171]), - token nl_tokens: many(5), - token lsquare_token: optional(11), - token rsquare_token: optional(12), - token colon_token: required(26, "COLON"), - token at_no_ws_token: optional(41), - token at_pre_ws_token: optional(43), - token file_token: required(63, "FILE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PackageHeaderContext { - rule_index: 4, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PackageHeaderContext { - rule semi: optional(SemiContext[74]), - rule identifier: optional(IdentifierContext[173]), - token package_token: optional(72), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImportListContext { - rule_index: 5, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImportListContext { - rule import_header_children: many(ImportHeaderContext[6]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImportHeaderContext { - rule_index: 6, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImportHeaderContext { - rule import_alias: optional(ImportAliasContext[7]), - rule semi: optional(SemiContext[74]), - rule identifier: required(IdentifierContext[173], "identifier"), - token dot_token: optional(7), - token mult_token: optional(15), - token import_token: required(73, "IMPORT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ImportAliasContext { - rule_index: 7, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ImportAliasContext { - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token as_token: required(102, "AS"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TopLevelObjectContext { - rule_index: 8, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TopLevelObjectContext { - rule declaration: required(DeclarationContext[10], "declaration"), - rule semis: optional(SemisContext[75]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeAliasContext { - rule_index: 9, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeAliasContext { - rule type_parameters: optional(TypeParametersContext[21]), - rule r#type: required(TypeContext[49], "type"), - rule modifiers: optional(ModifiersContext[150]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token assignment_token: required(28, "ASSIGNMENT"), - token type_alias_token: required(80, "TYPE_ALIAS"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DeclarationContext { - rule_index: 10, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DeclarationContext { - rule type_alias: optional(TypeAliasContext[9]), - rule class_declaration: optional(ClassDeclarationContext[11]), - rule function_declaration: optional(FunctionDeclarationContext[31]), - rule property_declaration: optional(PropertyDeclarationContext[35]), - rule object_declaration: optional(ObjectDeclarationContext[43]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassDeclarationContext { - rule_index: 11, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassDeclarationContext { - rule primary_constructor: optional(PrimaryConstructorContext[12]), - rule class_body: optional(ClassBodyContext[13]), - rule delegation_specifiers: optional(DelegationSpecifiersContext[16]), - rule type_parameters: optional(TypeParametersContext[21]), - rule type_constraints: optional(TypeConstraintsContext[23]), - rule enum_class_body: optional(EnumClassBodyContext[46]), - rule modifiers: optional(ModifiersContext[150]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: optional(26), - token class_token: optional(74), - token interface_token: optional(75), - token fun_token: optional(76), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrimaryConstructorContext { - rule_index: 12, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrimaryConstructorContext { - rule class_parameters: required(ClassParametersContext[14], "classParameters"), - rule modifiers: optional(ModifiersContext[150]), - token nl_tokens: many(5), - token constructor_token: optional(81), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassBodyContext { - rule_index: 13, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassBodyContext { - rule class_member_declarations: required(ClassMemberDeclarationsContext[25], "classMemberDeclarations"), - token nl_tokens: many(5), - token lcurl_token: required(13, "LCURL"), - token rcurl_token: required(14, "RCURL"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassParametersContext { - rule_index: 14, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassParametersContext { - rule class_parameter_children: many(ClassParameterContext[15]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassParameterContext { - rule_index: 15, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassParameterContext { - rule r#type: required(TypeContext[49], "type"), - rule expression: optional(ExpressionContext[76]), - rule modifiers: optional(ModifiersContext[150]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: required(26, "COLON"), - token assignment_token: optional(28), - token val_token: optional(78), - token var_token: optional(79), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DelegationSpecifiersContext { - rule_index: 16, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DelegationSpecifiersContext { - rule annotated_delegation_specifier_children: many(AnnotatedDelegationSpecifierContext[19]), - token nl_tokens: many(5), - token comma_tokens: many(8), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DelegationSpecifierContext { - rule_index: 17, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DelegationSpecifierContext { - rule constructor_invocation: optional(ConstructorInvocationContext[18]), - rule explicit_delegation: optional(ExplicitDelegationContext[20]), - rule user_type: optional(UserTypeContext[53]), - rule function_type: optional(FunctionTypeContext[58]), - token nl_tokens: many(5), - token suspend_token: optional(124), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstructorInvocationContext { - rule_index: 18, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstructorInvocationContext { - rule user_type: required(UserTypeContext[53], "userType"), - rule value_arguments: required(ValueArgumentsContext[104], "valueArguments"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotatedDelegationSpecifierContext { - rule_index: 19, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotatedDelegationSpecifierContext { - rule delegation_specifier: required(DelegationSpecifierContext[17], "delegationSpecifier"), - rule annotation_children: many(AnnotationContext[167]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExplicitDelegationContext { - rule_index: 20, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExplicitDelegationContext { - rule user_type: optional(UserTypeContext[53]), - rule function_type: optional(FunctionTypeContext[58]), - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token by_token: required(82, "BY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParametersContext { - rule_index: 21, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParametersContext { - rule type_parameter_children: many(TypeParameterContext[22]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token langle_token: required(47, "LANGLE"), - token rangle_token: required(48, "RANGLE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterContext { - rule_index: 22, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterContext { - rule r#type: optional(TypeContext[49]), - rule type_parameter_modifiers: optional(TypeParameterModifiersContext[159]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: optional(26), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeConstraintsContext { - rule_index: 23, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeConstraintsContext { - rule type_constraint_children: many(TypeConstraintContext[24]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token where_token: required(88, "WHERE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeConstraintContext { - rule_index: 24, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeConstraintContext { - rule r#type: required(TypeContext[49], "type"), - rule annotation_children: many(AnnotationContext[167]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: required(26, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassMemberDeclarationsContext { - rule_index: 25, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassMemberDeclarationsContext { - rule class_member_declaration_children: many(ClassMemberDeclarationContext[26]), - rule semis_children: many(SemisContext[75]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassMemberDeclarationContext { - rule_index: 26, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassMemberDeclarationContext { - rule declaration: optional(DeclarationContext[10]), - rule anonymous_initializer: optional(AnonymousInitializerContext[27]), - rule companion_object: optional(CompanionObjectContext[28]), - rule secondary_constructor: optional(SecondaryConstructorContext[44]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnonymousInitializerContext { - rule_index: 27, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnonymousInitializerContext { - rule block: required(BlockContext[68], "block"), - token nl_tokens: many(5), - token init_token: required(84, "INIT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CompanionObjectContext { - rule_index: 28, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CompanionObjectContext { - rule class_body: optional(ClassBodyContext[13]), - rule delegation_specifiers: optional(DelegationSpecifiersContext[16]), - rule modifiers: optional(ModifiersContext[150]), - rule simple_identifier: optional(SimpleIdentifierContext[172]), - token nl_tokens: many(5), - token colon_token: optional(26), - token object_token: required(77, "OBJECT"), - token companion_token: required(83, "COMPANION"), - token data_token: optional(116), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionValueParametersContext { - rule_index: 29, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionValueParametersContext { - rule function_value_parameter_children: many(FunctionValueParameterContext[30]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionValueParameterContext { - rule_index: 30, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionValueParameterContext { - rule parameter: required(ParameterContext[42], "parameter"), - rule expression: optional(ExpressionContext[76]), - rule parameter_modifiers: optional(ParameterModifiersContext[151]), - token nl_tokens: many(5), - token assignment_token: optional(28), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionDeclarationContext { - rule_index: 31, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionDeclarationContext { - rule type_parameters: optional(TypeParametersContext[21]), - rule type_constraints: optional(TypeConstraintsContext[23]), - rule function_value_parameters: required(FunctionValueParametersContext[29], "functionValueParameters"), - rule function_body: optional(FunctionBodyContext[32]), - rule r#type: optional(TypeContext[49]), - rule receiver_type: optional(ReceiverTypeContext[61]), - rule modifiers: optional(ModifiersContext[150]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token dot_token: optional(7), - token colon_token: optional(26), - token fun_token: required(76, "FUN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionBodyContext { - rule_index: 32, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionBodyContext { - rule block: optional(BlockContext[68]), - rule expression: optional(ExpressionContext[76]), - token nl_tokens: many(5), - token assignment_token: optional(28), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VariableDeclarationContext { - rule_index: 33, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VariableDeclarationContext { - rule r#type: optional(TypeContext[49]), - rule annotation_children: many(AnnotationContext[167]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: optional(26), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiVariableDeclarationContext { - rule_index: 34, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiVariableDeclarationContext { - rule variable_declaration_children: many(VariableDeclarationContext[33]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PropertyDeclarationContext { - rule_index: 35, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PropertyDeclarationContext { - rule type_parameters: optional(TypeParametersContext[21]), - rule type_constraints: optional(TypeConstraintsContext[23]), - rule variable_declaration: optional(VariableDeclarationContext[33]), - rule multi_variable_declaration: optional(MultiVariableDeclarationContext[34]), - rule property_delegate: optional(PropertyDelegateContext[36]), - rule getter: optional(GetterContext[37]), - rule setter: optional(SetterContext[38]), - rule receiver_type: optional(ReceiverTypeContext[61]), - rule semi: optional(SemiContext[74]), - rule expression: optional(ExpressionContext[76]), - rule modifiers: optional(ModifiersContext[150]), - token nl_tokens: many(5), - token dot_token: optional(7), - token semicolon_token: optional(27), - token assignment_token: optional(28), - token val_token: optional(78), - token var_token: optional(79), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PropertyDelegateContext { - rule_index: 36, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PropertyDelegateContext { - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token by_token: required(82, "BY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GetterContext { - rule_index: 37, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GetterContext { - rule function_body: optional(FunctionBodyContext[32]), - rule r#type: optional(TypeContext[49]), - rule modifiers: optional(ModifiersContext[150]), - token nl_tokens: many(5), - token lparen_token: optional(9), - token rparen_token: optional(10), - token colon_token: optional(26), - token get_token: required(66, "GET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SetterContext { - rule_index: 38, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SetterContext { - rule function_body: optional(FunctionBodyContext[32]), - rule function_value_parameter_with_optional_type: optional(FunctionValueParameterWithOptionalTypeContext[40]), - rule r#type: optional(TypeContext[49]), - rule modifiers: optional(ModifiersContext[150]), - token nl_tokens: many(5), - token comma_token: optional(8), - token lparen_token: optional(9), - token rparen_token: optional(10), - token colon_token: optional(26), - token set_token: required(67, "SET"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParametersWithOptionalTypeContext { - rule_index: 39, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParametersWithOptionalTypeContext { - rule function_value_parameter_with_optional_type_children: many(FunctionValueParameterWithOptionalTypeContext[40]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionValueParameterWithOptionalTypeContext { - rule_index: 40, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionValueParameterWithOptionalTypeContext { - rule parameter_with_optional_type: required(ParameterWithOptionalTypeContext[41], "parameterWithOptionalType"), - rule expression: optional(ExpressionContext[76]), - rule parameter_modifiers: optional(ParameterModifiersContext[151]), - token nl_tokens: many(5), - token assignment_token: optional(28), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParameterWithOptionalTypeContext { - rule_index: 41, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParameterWithOptionalTypeContext { - rule r#type: optional(TypeContext[49]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: optional(26), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParameterContext { - rule_index: 42, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParameterContext { - rule r#type: required(TypeContext[49], "type"), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: required(26, "COLON"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ObjectDeclarationContext { - rule_index: 43, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ObjectDeclarationContext { - rule class_body: optional(ClassBodyContext[13]), - rule delegation_specifiers: optional(DelegationSpecifiersContext[16]), - rule modifiers: optional(ModifiersContext[150]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token colon_token: optional(26), - token object_token: required(77, "OBJECT"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SecondaryConstructorContext { - rule_index: 44, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SecondaryConstructorContext { - rule function_value_parameters: required(FunctionValueParametersContext[29], "functionValueParameters"), - rule constructor_delegation_call: optional(ConstructorDelegationCallContext[45]), - rule block: optional(BlockContext[68]), - rule modifiers: optional(ModifiersContext[150]), - token nl_tokens: many(5), - token colon_token: optional(26), - token constructor_token: required(81, "CONSTRUCTOR"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConstructorDelegationCallContext { - rule_index: 45, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConstructorDelegationCallContext { - rule value_arguments: required(ValueArgumentsContext[104], "valueArguments"), - token nl_tokens: many(5), - token this_token: optional(85), - token super__token: optional(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumClassBodyContext { - rule_index: 46, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumClassBodyContext { - rule class_member_declarations: optional(ClassMemberDeclarationsContext[25]), - rule enum_entries: optional(EnumEntriesContext[47]), - token nl_tokens: many(5), - token lcurl_token: required(13, "LCURL"), - token rcurl_token: required(14, "RCURL"), - token semicolon_token: optional(27), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumEntriesContext { - rule_index: 47, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumEntriesContext { - rule enum_entry_children: many(EnumEntryContext[48]), - token nl_tokens: many(5), - token comma_tokens: many(8), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EnumEntryContext { - rule_index: 48, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EnumEntryContext { - rule class_body: optional(ClassBodyContext[13]), - rule value_arguments: optional(ValueArgumentsContext[104]), - rule modifiers: optional(ModifiersContext[150]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeContext { - rule_index: 49, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeContext { - rule type_reference: optional(TypeReferenceContext[50]), - rule nullable_type: optional(NullableTypeContext[51]), - rule function_type: optional(FunctionTypeContext[58]), - rule parenthesized_type: optional(ParenthesizedTypeContext[60]), - rule definitely_non_nullable_type: optional(DefinitelyNonNullableTypeContext[63]), - rule type_modifiers: optional(TypeModifiersContext[153]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeReferenceContext { - rule_index: 50, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeReferenceContext { - rule user_type: optional(UserTypeContext[53]), - token dynamic_token: optional(108), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NullableTypeContext { - rule_index: 51, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NullableTypeContext { - rule type_reference: optional(TypeReferenceContext[50]), - rule quest_children: many(QuestContext[52]), - rule parenthesized_type: optional(ParenthesizedTypeContext[60]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct QuestContext { - rule_index: 52, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - QuestContext { - token quest_ws_token: optional(45), - token quest_no_ws_token: optional(46), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UserTypeContext { - rule_index: 53, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UserTypeContext { - rule simple_user_type_children: many(SimpleUserTypeContext[54]), - token nl_tokens: many(5), - token dot_tokens: many(7), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SimpleUserTypeContext { - rule_index: 54, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SimpleUserTypeContext { - rule type_arguments: optional(TypeArgumentsContext[103]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeProjectionContext { - rule_index: 55, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeProjectionContext { - rule r#type: optional(TypeContext[49]), - rule type_projection_modifiers: optional(TypeProjectionModifiersContext[56]), - token mult_token: optional(15), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeProjectionModifiersContext { - rule_index: 56, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeProjectionModifiersContext { - rule type_projection_modifier_children: many(TypeProjectionModifierContext[57]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeProjectionModifierContext { - rule_index: 57, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeProjectionModifierContext { - rule variance_modifier: optional(VarianceModifierContext[158]), - rule annotation: optional(AnnotationContext[167]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionTypeContext { - rule_index: 58, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionTypeContext { - rule r#type: required(TypeContext[49], "type"), - rule function_type_parameters: required(FunctionTypeParametersContext[59], "functionTypeParameters"), - rule receiver_type: optional(ReceiverTypeContext[61]), - token nl_tokens: many(5), - token dot_token: optional(7), - token arrow_token: required(34, "ARROW"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionTypeParametersContext { - rule_index: 59, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionTypeParametersContext { - rule parameter_children: many(ParameterContext[42]), - rule type_children: many(TypeContext[49]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedTypeContext { - rule_index: 60, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedTypeContext { - rule r#type: required(TypeContext[49], "type"), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ReceiverTypeContext { - rule_index: 61, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ReceiverTypeContext { - rule type_reference: optional(TypeReferenceContext[50]), - rule nullable_type: optional(NullableTypeContext[51]), - rule parenthesized_type: optional(ParenthesizedTypeContext[60]), - rule type_modifiers: optional(TypeModifiersContext[153]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedUserTypeContext { - rule_index: 62, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedUserTypeContext { - rule user_type: optional(UserTypeContext[53]), - rule parenthesized_user_type: optional(ParenthesizedUserTypeContext[62]), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DefinitelyNonNullableTypeContext { - rule_index: 63, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DefinitelyNonNullableTypeContext { - rule user_type_children: many(UserTypeContext[53]), - rule parenthesized_user_type_children: many(ParenthesizedUserTypeContext[62]), - rule type_modifiers_children: many(TypeModifiersContext[153]), - token nl_tokens: many(5), - token amp_token: required(57, "AMP"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StatementsContext { - rule_index: 64, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StatementsContext { - rule statement_children: many(StatementContext[65]), - rule semis_children: many(SemisContext[75]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StatementContext { - rule_index: 65, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StatementContext { - rule declaration: optional(DeclarationContext[10]), - rule label_children: many(LabelContext[66]), - rule loop_statement: optional(LoopStatementContext[69]), - rule assignment: optional(AssignmentContext[73]), - rule expression: optional(ExpressionContext[76]), - rule annotation_children: many(AnnotationContext[167]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LabelContext { - rule_index: 66, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LabelContext { - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token at_no_ws_token: optional(41), - token at_post_ws_token: optional(42), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ControlStructureBodyContext { - rule_index: 67, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ControlStructureBodyContext { - rule statement: optional(StatementContext[65]), - rule block: optional(BlockContext[68]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct BlockContext { - rule_index: 68, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - BlockContext { - rule statements: required(StatementsContext[64], "statements"), - token nl_tokens: many(5), - token lcurl_token: required(13, "LCURL"), - token rcurl_token: required(14, "RCURL"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LoopStatementContext { - rule_index: 69, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LoopStatementContext { - rule for_statement: optional(ForStatementContext[70]), - rule while_statement: optional(WhileStatementContext[71]), - rule do_while_statement: optional(DoWhileStatementContext[72]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ForStatementContext { - rule_index: 70, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ForStatementContext { - rule variable_declaration: optional(VariableDeclarationContext[33]), - rule multi_variable_declaration: optional(MultiVariableDeclarationContext[34]), - rule control_structure_body: optional(ControlStructureBodyContext[67]), - rule expression: required(ExpressionContext[76], "expression"), - rule annotation_children: many(AnnotationContext[167]), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - token for_token: required(95, "FOR"), - token in_token: required(104, "IN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhileStatementContext { - rule_index: 71, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhileStatementContext { - rule control_structure_body: optional(ControlStructureBodyContext[67]), - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - token semicolon_token: optional(27), - token while_token: required(97, "WHILE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DoWhileStatementContext { - rule_index: 72, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DoWhileStatementContext { - rule control_structure_body: optional(ControlStructureBodyContext[67]), - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - token do_token: required(96, "DO"), - token while_token: required(97, "WHILE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AssignmentContext { - rule_index: 73, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AssignmentContext { - rule expression: required(ExpressionContext[76], "expression"), - rule directly_assignable_expression: optional(DirectlyAssignableExpressionContext[94]), - rule assignable_expression: optional(AssignableExpressionContext[96]), - rule assignment_and_operator: optional(AssignmentAndOperatorContext[137]), - token nl_tokens: many(5), - token assignment_token: optional(28), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SemiContext { - rule_index: 74, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SemiContext { - token nl_tokens: many(5), - token semicolon_token: optional(27), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SemisContext { - rule_index: 75, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SemisContext { - token nl_tokens: many(5), - token semicolon_tokens: many(27), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExpressionContext { - rule_index: 76, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExpressionContext { - rule disjunction: required(DisjunctionContext[77], "disjunction"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DisjunctionContext { - rule_index: 77, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DisjunctionContext { - rule conjunction_children: many(ConjunctionContext[78]), - token nl_tokens: many(5), - token disj_tokens: many(23), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ConjunctionContext { - rule_index: 78, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ConjunctionContext { - rule equality_children: many(EqualityContext[79]), - token nl_tokens: many(5), - token conj_tokens: many(22), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EqualityContext { - rule_index: 79, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EqualityContext { - rule comparison_children: many(ComparisonContext[80]), - rule equality_operator_children: many(EqualityOperatorContext[138]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ComparisonContext { - rule_index: 80, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ComparisonContext { - rule generic_call_like_comparison_children: many(GenericCallLikeComparisonContext[81]), - rule comparison_operator_children: many(ComparisonOperatorContext[139]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct GenericCallLikeComparisonContext { - rule_index: 81, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - GenericCallLikeComparisonContext { - rule infix_operation: required(InfixOperationContext[82], "infixOperation"), - rule call_suffix_children: many(CallSuffixContext[101]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InfixOperationContext { - rule_index: 82, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InfixOperationContext { - rule type_children: many(TypeContext[49]), - rule elvis_expression_children: many(ElvisExpressionContext[83]), - rule in_operator_children: many(InOperatorContext[140]), - rule is_operator_children: many(IsOperatorContext[141]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ElvisExpressionContext { - rule_index: 83, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ElvisExpressionContext { - rule elvis_children: many(ElvisContext[84]), - rule infix_function_call_children: many(InfixFunctionCallContext[85]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ElvisContext { - rule_index: 84, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ElvisContext { - token colon_token: required(26, "COLON"), - token quest_no_ws_token: required(46, "QUEST_NO_WS"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InfixFunctionCallContext { - rule_index: 85, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InfixFunctionCallContext { - rule range_expression_children: many(RangeExpressionContext[86]), - rule simple_identifier_children: many(SimpleIdentifierContext[172]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RangeExpressionContext { - rule_index: 86, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RangeExpressionContext { - rule additive_expression_children: many(AdditiveExpressionContext[87]), - token nl_tokens: many(5), - token range_tokens: many(36), - token range_until_tokens: many(37), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AdditiveExpressionContext { - rule_index: 87, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AdditiveExpressionContext { - rule multiplicative_expression_children: many(MultiplicativeExpressionContext[88]), - rule additive_operator_children: many(AdditiveOperatorContext[142]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiplicativeExpressionContext { - rule_index: 88, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiplicativeExpressionContext { - rule as_expression_children: many(AsExpressionContext[89]), - rule multiplicative_operator_children: many(MultiplicativeOperatorContext[143]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AsExpressionContext { - rule_index: 89, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AsExpressionContext { - rule type_children: many(TypeContext[49]), - rule prefix_unary_expression: required(PrefixUnaryExpressionContext[90], "prefixUnaryExpression"), - rule as_operator_children: many(AsOperatorContext[144]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrefixUnaryExpressionContext { - rule_index: 90, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrefixUnaryExpressionContext { - rule unary_prefix_children: many(UnaryPrefixContext[91]), - rule postfix_unary_expression: required(PostfixUnaryExpressionContext[92], "postfixUnaryExpression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnaryPrefixContext { - rule_index: 91, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnaryPrefixContext { - rule label: optional(LabelContext[66]), - rule prefix_unary_operator: optional(PrefixUnaryOperatorContext[145]), - rule annotation: optional(AnnotationContext[167]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PostfixUnaryExpressionContext { - rule_index: 92, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PostfixUnaryExpressionContext { - rule postfix_unary_suffix_children: many(PostfixUnarySuffixContext[93]), - rule primary_expression: required(PrimaryExpressionContext[106], "primaryExpression"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PostfixUnarySuffixContext { - rule_index: 93, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PostfixUnarySuffixContext { - rule indexing_suffix: optional(IndexingSuffixContext[99]), - rule navigation_suffix: optional(NavigationSuffixContext[100]), - rule call_suffix: optional(CallSuffixContext[101]), - rule type_arguments: optional(TypeArgumentsContext[103]), - rule postfix_unary_operator: optional(PostfixUnaryOperatorContext[146]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct DirectlyAssignableExpressionContext { - rule_index: 94, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - DirectlyAssignableExpressionContext { - rule postfix_unary_expression: optional(PostfixUnaryExpressionContext[92]), - rule parenthesized_directly_assignable_expression: optional(ParenthesizedDirectlyAssignableExpressionContext[95]), - rule assignable_suffix: optional(AssignableSuffixContext[98]), - rule simple_identifier: optional(SimpleIdentifierContext[172]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedDirectlyAssignableExpressionContext { - rule_index: 95, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedDirectlyAssignableExpressionContext { - rule directly_assignable_expression: required(DirectlyAssignableExpressionContext[94], "directlyAssignableExpression"), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AssignableExpressionContext { - rule_index: 96, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AssignableExpressionContext { - rule prefix_unary_expression: optional(PrefixUnaryExpressionContext[90]), - rule parenthesized_assignable_expression: optional(ParenthesizedAssignableExpressionContext[97]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedAssignableExpressionContext { - rule_index: 97, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedAssignableExpressionContext { - rule assignable_expression: required(AssignableExpressionContext[96], "assignableExpression"), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AssignableSuffixContext { - rule_index: 98, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AssignableSuffixContext { - rule indexing_suffix: optional(IndexingSuffixContext[99]), - rule navigation_suffix: optional(NavigationSuffixContext[100]), - rule type_arguments: optional(TypeArgumentsContext[103]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IndexingSuffixContext { - rule_index: 99, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IndexingSuffixContext { - rule expression_children: many(ExpressionContext[76]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lsquare_token: required(11, "LSQUARE"), - token rsquare_token: required(12, "RSQUARE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct NavigationSuffixContext { - rule_index: 100, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - NavigationSuffixContext { - rule parenthesized_expression: optional(ParenthesizedExpressionContext[107]), - rule member_access_operator: required(MemberAccessOperatorContext[148], "memberAccessOperator"), - rule simple_identifier: optional(SimpleIdentifierContext[172]), - token nl_tokens: many(5), - token class_token: optional(74), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CallSuffixContext { - rule_index: 101, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CallSuffixContext { - rule annotated_lambda: optional(AnnotatedLambdaContext[102]), - rule type_arguments: optional(TypeArgumentsContext[103]), - rule value_arguments: optional(ValueArgumentsContext[104]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotatedLambdaContext { - rule_index: 102, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotatedLambdaContext { - rule label: optional(LabelContext[66]), - rule lambda_literal: required(LambdaLiteralContext[117], "lambdaLiteral"), - rule annotation_children: many(AnnotationContext[167]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeArgumentsContext { - rule_index: 103, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeArgumentsContext { - rule type_projection_children: many(TypeProjectionContext[55]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token langle_token: required(47, "LANGLE"), - token rangle_token: required(48, "RANGLE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ValueArgumentsContext { - rule_index: 104, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ValueArgumentsContext { - rule value_argument_children: many(ValueArgumentContext[105]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ValueArgumentContext { - rule_index: 105, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ValueArgumentContext { - rule expression: required(ExpressionContext[76], "expression"), - rule annotation: optional(AnnotationContext[167]), - rule simple_identifier: optional(SimpleIdentifierContext[172]), - token nl_tokens: many(5), - token mult_token: optional(15), - token assignment_token: optional(28), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrimaryExpressionContext { - rule_index: 106, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrimaryExpressionContext { - rule parenthesized_expression: optional(ParenthesizedExpressionContext[107]), - rule collection_literal: optional(CollectionLiteralContext[108]), - rule literal_constant: optional(LiteralConstantContext[109]), - rule string_literal: optional(StringLiteralContext[110]), - rule function_literal: optional(FunctionLiteralContext[121]), - rule object_literal: optional(ObjectLiteralContext[122]), - rule this_expression: optional(ThisExpressionContext[123]), - rule super_expression: optional(SuperExpressionContext[124]), - rule if_expression: optional(IfExpressionContext[125]), - rule when_expression: optional(WhenExpressionContext[127]), - rule try_expression: optional(TryExpressionContext[132]), - rule jump_expression: optional(JumpExpressionContext[135]), - rule callable_reference: optional(CallableReferenceContext[136]), - rule simple_identifier: optional(SimpleIdentifierContext[172]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParenthesizedExpressionContext { - rule_index: 107, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParenthesizedExpressionContext { - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CollectionLiteralContext { - rule_index: 108, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CollectionLiteralContext { - rule expression_children: many(ExpressionContext[76]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token lsquare_token: required(11, "LSQUARE"), - token rsquare_token: required(12, "RSQUARE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LiteralConstantContext { - rule_index: 109, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LiteralConstantContext { - token real_literal_token: optional(137), - token integer_literal_token: optional(140), - token hex_literal_token: optional(141), - token bin_literal_token: optional(142), - token unsigned_literal_token: optional(143), - token long_literal_token: optional(144), - token boolean_literal_token: optional(145), - token null_literal_token: optional(146), - token character_literal_token: optional(147), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct StringLiteralContext { - rule_index: 110, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - StringLiteralContext { - rule line_string_literal: optional(LineStringLiteralContext[111]), - rule multi_line_string_literal: optional(MultiLineStringLiteralContext[112]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LineStringLiteralContext { - rule_index: 111, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LineStringLiteralContext { - rule line_string_content_children: many(LineStringContentContext[113]), - rule line_string_expression_children: many(LineStringExpressionContext[114]), - token quote_open_token: required(151, "QUOTE_OPEN"), - token quote_close_token: required(160, "QUOTE_CLOSE"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiLineStringLiteralContext { - rule_index: 112, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiLineStringLiteralContext { - rule multi_line_string_content_children: many(MultiLineStringContentContext[115]), - rule multi_line_string_expression_children: many(MultiLineStringExpressionContext[116]), - token triple_quote_open_token: required(152, "TRIPLE_QUOTE_OPEN"), - token triple_quote_close_token: required(165, "TRIPLE_QUOTE_CLOSE"), - token multi_line_string_quote_tokens: many(166), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LineStringContentContext { - rule_index: 113, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LineStringContentContext { - token line_str_ref_token: optional(161), - token line_str_text_token: optional(162), - token line_str_escaped_char_token: optional(163), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LineStringExpressionContext { - rule_index: 114, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LineStringExpressionContext { - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token rcurl_token: required(14, "RCURL"), - token line_str_expr_start_token: required(164, "LineStrExprStart"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiLineStringContentContext { - rule_index: 115, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiLineStringContentContext { - token multi_line_string_quote_token: optional(166), - token multi_line_str_ref_token: optional(167), - token multi_line_str_text_token: optional(168), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiLineStringExpressionContext { - rule_index: 116, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiLineStringExpressionContext { - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token rcurl_token: required(14, "RCURL"), - token multi_line_str_expr_start_token: required(169, "MultiLineStrExprStart"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaLiteralContext { - rule_index: 117, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaLiteralContext { - rule statements: required(StatementsContext[64], "statements"), - rule lambda_parameters: optional(LambdaParametersContext[118]), - token nl_tokens: many(5), - token lcurl_token: required(13, "LCURL"), - token rcurl_token: required(14, "RCURL"), - token arrow_token: optional(34), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaParametersContext { - rule_index: 118, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaParametersContext { - rule lambda_parameter_children: many(LambdaParameterContext[119]), - token nl_tokens: many(5), - token comma_tokens: many(8), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct LambdaParameterContext { - rule_index: 119, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - LambdaParameterContext { - rule variable_declaration: optional(VariableDeclarationContext[33]), - rule multi_variable_declaration: optional(MultiVariableDeclarationContext[34]), - rule r#type: optional(TypeContext[49]), - token nl_tokens: many(5), - token colon_token: optional(26), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnonymousFunctionContext { - rule_index: 120, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnonymousFunctionContext { - rule type_constraints: optional(TypeConstraintsContext[23]), - rule function_body: optional(FunctionBodyContext[32]), - rule parameters_with_optional_type: required(ParametersWithOptionalTypeContext[39], "parametersWithOptionalType"), - rule type_children: many(TypeContext[49]), - token nl_tokens: many(5), - token dot_token: optional(7), - token colon_token: optional(26), - token fun_token: required(76, "FUN"), - token suspend_token: optional(124), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionLiteralContext { - rule_index: 121, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionLiteralContext { - rule lambda_literal: optional(LambdaLiteralContext[117]), - rule anonymous_function: optional(AnonymousFunctionContext[120]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ObjectLiteralContext { - rule_index: 122, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ObjectLiteralContext { - rule class_body: optional(ClassBodyContext[13]), - rule delegation_specifiers: optional(DelegationSpecifiersContext[16]), - token nl_tokens: many(5), - token colon_token: optional(26), - token object_token: required(77, "OBJECT"), - token data_token: optional(116), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ThisExpressionContext { - rule_index: 123, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ThisExpressionContext { - token this_at_token: optional(61), - token this_token: optional(85), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SuperExpressionContext { - rule_index: 124, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SuperExpressionContext { - rule r#type: optional(TypeContext[49]), - rule simple_identifier: optional(SimpleIdentifierContext[172]), - token nl_tokens: many(5), - token at_no_ws_token: optional(41), - token langle_token: optional(47), - token rangle_token: optional(48), - token super_at_token: optional(62), - token super__token: optional(86), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IfExpressionContext { - rule_index: 125, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IfExpressionContext { - rule control_structure_body_children: many(ControlStructureBodyContext[67]), - rule expression: required(ExpressionContext[76], "expression"), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - token semicolon_tokens: many(27), - token if_token: required(89, "IF"), - token else_token: optional(90), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhenSubjectContext { - rule_index: 126, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhenSubjectContext { - rule variable_declaration: optional(VariableDeclarationContext[33]), - rule expression: required(ExpressionContext[76], "expression"), - rule annotation_children: many(AnnotationContext[167]), - token nl_tokens: many(5), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - token assignment_token: optional(28), - token val_token: optional(78), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhenExpressionContext { - rule_index: 127, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhenExpressionContext { - rule when_subject: optional(WhenSubjectContext[126]), - rule when_entry_children: many(WhenEntryContext[128]), - token nl_tokens: many(5), - token lcurl_token: required(13, "LCURL"), - token rcurl_token: required(14, "RCURL"), - token when_token: required(91, "WHEN"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhenEntryContext { - rule_index: 128, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhenEntryContext { - rule control_structure_body: required(ControlStructureBodyContext[67], "controlStructureBody"), - rule semi: optional(SemiContext[74]), - rule when_condition_children: many(WhenConditionContext[129]), - token nl_tokens: many(5), - token comma_tokens: many(8), - token arrow_token: required(34, "ARROW"), - token else_token: optional(90), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct WhenConditionContext { - rule_index: 129, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - WhenConditionContext { - rule expression: optional(ExpressionContext[76]), - rule range_test: optional(RangeTestContext[130]), - rule type_test: optional(TypeTestContext[131]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct RangeTestContext { - rule_index: 130, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - RangeTestContext { - rule expression: required(ExpressionContext[76], "expression"), - rule in_operator: required(InOperatorContext[140], "inOperator"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeTestContext { - rule_index: 131, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeTestContext { - rule r#type: required(TypeContext[49], "type"), - rule is_operator: required(IsOperatorContext[141], "isOperator"), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TryExpressionContext { - rule_index: 132, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TryExpressionContext { - rule block: required(BlockContext[68], "block"), - rule catch_block_children: many(CatchBlockContext[133]), - rule finally_block: optional(FinallyBlockContext[134]), - token nl_tokens: many(5), - token try_token: required(92, "TRY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CatchBlockContext { - rule_index: 133, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CatchBlockContext { - rule r#type: required(TypeContext[49], "type"), - rule block: required(BlockContext[68], "block"), - rule annotation_children: many(AnnotationContext[167]), - rule simple_identifier: required(SimpleIdentifierContext[172], "simpleIdentifier"), - token nl_tokens: many(5), - token comma_token: optional(8), - token lparen_token: required(9, "LPAREN"), - token rparen_token: required(10, "RPAREN"), - token colon_token: required(26, "COLON"), - token catch_token: required(93, "CATCH"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FinallyBlockContext { - rule_index: 134, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FinallyBlockContext { - rule block: required(BlockContext[68], "block"), - token nl_tokens: many(5), - token finally_token: required(94, "FINALLY"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct JumpExpressionContext { - rule_index: 135, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - JumpExpressionContext { - rule expression: optional(ExpressionContext[76]), - token nl_tokens: many(5), - token return_at_token: optional(58), - token continue_at_token: optional(59), - token break_at_token: optional(60), - token throw_token: optional(98), - token return_token: optional(99), - token continue_token: optional(100), - token break_token: optional(101), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct CallableReferenceContext { - rule_index: 136, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - CallableReferenceContext { - rule receiver_type: optional(ReceiverTypeContext[61]), - rule simple_identifier: optional(SimpleIdentifierContext[172]), - token nl_tokens: many(5), - token coloncolon_token: required(38, "COLONCOLON"), - token class_token: optional(74), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AssignmentAndOperatorContext { - rule_index: 137, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AssignmentAndOperatorContext { - token add_assignment_token: optional(29), - token sub_assignment_token: optional(30), - token mult_assignment_token: optional(31), - token div_assignment_token: optional(32), - token mod_assignment_token: optional(33), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct EqualityOperatorContext { - rule_index: 138, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - EqualityOperatorContext { - token excl_eq_token: optional(51), - token excl_eqeq_token: optional(52), - token eqeq_token: optional(54), - token eqeqeq_token: optional(55), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ComparisonOperatorContext { - rule_index: 139, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ComparisonOperatorContext { - token langle_token: optional(47), - token rangle_token: optional(48), - token le_token: optional(49), - token ge_token: optional(50), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InOperatorContext { - rule_index: 140, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InOperatorContext { - token in_token: optional(104), - token not_in_token: optional(106), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IsOperatorContext { - rule_index: 141, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IsOperatorContext { - token is_token: optional(103), - token not_is_token: optional(105), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AdditiveOperatorContext { - rule_index: 142, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AdditiveOperatorContext { - token add_token: optional(18), - token sub_token: optional(19), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiplicativeOperatorContext { - rule_index: 143, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiplicativeOperatorContext { - token mult_token: optional(15), - token mod_token: optional(16), - token div_token: optional(17), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AsOperatorContext { - rule_index: 144, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AsOperatorContext { - token as_safe_token: optional(53), - token as_token: optional(102), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PrefixUnaryOperatorContext { - rule_index: 145, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PrefixUnaryOperatorContext { - rule excl: optional(ExclContext[147]), - token add_token: optional(18), - token sub_token: optional(19), - token incr_token: optional(20), - token decr_token: optional(21), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PostfixUnaryOperatorContext { - rule_index: 146, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PostfixUnaryOperatorContext { - rule excl: optional(ExclContext[147]), - token incr_token: optional(20), - token decr_token: optional(21), - token excl_no_ws_token: optional(25), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ExclContext { - rule_index: 147, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ExclContext { - token excl_ws_token: optional(24), - token excl_no_ws_token: optional(25), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MemberAccessOperatorContext { - rule_index: 148, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MemberAccessOperatorContext { - rule safe_nav: optional(SafeNavContext[149]), - token nl_tokens: many(5), - token dot_token: optional(7), - token coloncolon_token: optional(38), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SafeNavContext { - rule_index: 149, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SafeNavContext { - token dot_token: required(7, "DOT"), - token quest_no_ws_token: required(46, "QUEST_NO_WS"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ModifiersContext { - rule_index: 150, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ModifiersContext { - rule modifier_children: many(ModifierContext[152]), - rule annotation_children: many(AnnotationContext[167]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParameterModifiersContext { - rule_index: 151, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParameterModifiersContext { - rule parameter_modifier_children: many(ParameterModifierContext[164]), - rule annotation_children: many(AnnotationContext[167]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ModifierContext { - rule_index: 152, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ModifierContext { - rule class_modifier: optional(ClassModifierContext[155]), - rule member_modifier: optional(MemberModifierContext[156]), - rule visibility_modifier: optional(VisibilityModifierContext[157]), - rule function_modifier: optional(FunctionModifierContext[161]), - rule property_modifier: optional(PropertyModifierContext[162]), - rule inheritance_modifier: optional(InheritanceModifierContext[163]), - rule parameter_modifier: optional(ParameterModifierContext[164]), - rule platform_modifier: optional(PlatformModifierContext[166]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeModifiersContext { - rule_index: 153, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeModifiersContext { - rule type_modifier_children: many(TypeModifierContext[154]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeModifierContext { - rule_index: 154, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeModifierContext { - rule annotation: optional(AnnotationContext[167]), - token nl_tokens: many(5), - token suspend_token: optional(124), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ClassModifierContext { - rule_index: 155, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ClassModifierContext { - token enum_token: optional(113), - token sealed_token: optional(114), - token annotation_token: optional(115), - token data_token: optional(116), - token inner_token: optional(117), - token value_token: optional(118), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MemberModifierContext { - rule_index: 156, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MemberModifierContext { - token override_token: optional(125), - token lateinit_token: optional(130), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VisibilityModifierContext { - rule_index: 157, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VisibilityModifierContext { - token public_token: optional(109), - token private_token: optional(110), - token protected_token: optional(111), - token internal_token: optional(112), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct VarianceModifierContext { - rule_index: 158, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - VarianceModifierContext { - token in_token: optional(104), - token out_token: optional(107), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterModifiersContext { - rule_index: 159, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterModifiersContext { - rule type_parameter_modifier_children: many(TypeParameterModifierContext[160]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct TypeParameterModifierContext { - rule_index: 160, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - TypeParameterModifierContext { - rule variance_modifier: optional(VarianceModifierContext[158]), - rule reification_modifier: optional(ReificationModifierContext[165]), - rule annotation: optional(AnnotationContext[167]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct FunctionModifierContext { - rule_index: 161, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - FunctionModifierContext { - token tailrec_token: optional(119), - token operator_token: optional(120), - token inline_token: optional(121), - token infix_token: optional(122), - token external_token: optional(123), - token suspend_token: optional(124), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PropertyModifierContext { - rule_index: 162, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PropertyModifierContext { - token const_token: required(129, "CONST"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct InheritanceModifierContext { - rule_index: 163, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - InheritanceModifierContext { - token abstract_token: optional(126), - token final_token: optional(127), - token open_token: optional(128), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ParameterModifierContext { - rule_index: 164, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ParameterModifierContext { - token vararg_token: optional(131), - token noinline_token: optional(132), - token crossinline_token: optional(133), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct ReificationModifierContext { - rule_index: 165, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - ReificationModifierContext { - token reified_token: required(134, "REIFIED"), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct PlatformModifierContext { - rule_index: 166, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - PlatformModifierContext { - token expect_token: optional(135), - token actual_token: optional(136), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationContext { - rule_index: 167, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationContext { - rule single_annotation: optional(SingleAnnotationContext[168]), - rule multi_annotation: optional(MultiAnnotationContext[169]), - token nl_tokens: many(5), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SingleAnnotationContext { - rule_index: 168, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SingleAnnotationContext { - rule annotation_use_site_target: optional(AnnotationUseSiteTargetContext[170]), - rule unescaped_annotation: required(UnescapedAnnotationContext[171], "unescapedAnnotation"), - token nl_tokens: many(5), - token at_no_ws_token: optional(41), - token at_pre_ws_token: optional(43), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct MultiAnnotationContext { - rule_index: 169, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - MultiAnnotationContext { - rule annotation_use_site_target: optional(AnnotationUseSiteTargetContext[170]), - rule unescaped_annotation_children: many(UnescapedAnnotationContext[171]), - token nl_tokens: many(5), - token lsquare_token: required(11, "LSQUARE"), - token rsquare_token: required(12, "RSQUARE"), - token at_no_ws_token: optional(41), - token at_pre_ws_token: optional(43), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct AnnotationUseSiteTargetContext { - rule_index: 170, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - AnnotationUseSiteTargetContext { - token nl_tokens: many(5), - token colon_token: required(26, "COLON"), - token at_no_ws_token: optional(41), - token at_pre_ws_token: optional(43), - token field_token: optional(64), - token property_token: optional(65), - token get_token: optional(66), - token set_token: optional(67), - token receiver_token: optional(68), - token param_token: optional(69), - token setparam_token: optional(70), - token delegate_token: optional(71), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct UnescapedAnnotationContext { - rule_index: 171, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - UnescapedAnnotationContext { - rule constructor_invocation: optional(ConstructorInvocationContext[18]), - rule user_type: optional(UserTypeContext[53]), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct SimpleIdentifierContext { - rule_index: 172, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - SimpleIdentifierContext { - token file_token: optional(63), - token field_token: optional(64), - token property_token: optional(65), - token get_token: optional(66), - token set_token: optional(67), - token receiver_token: optional(68), - token param_token: optional(69), - token setparam_token: optional(70), - token delegate_token: optional(71), - token import_token: optional(73), - token constructor_token: optional(81), - token by_token: optional(82), - token companion_token: optional(83), - token init_token: optional(84), - token where_token: optional(88), - token catch_token: optional(93), - token finally_token: optional(94), - token out_token: optional(107), - token dynamic_token: optional(108), - token public_token: optional(109), - token private_token: optional(110), - token protected_token: optional(111), - token internal_token: optional(112), - token enum_token: optional(113), - token sealed_token: optional(114), - token annotation_token: optional(115), - token data_token: optional(116), - token inner_token: optional(117), - token value_token: optional(118), - token tailrec_token: optional(119), - token operator_token: optional(120), - token inline_token: optional(121), - token infix_token: optional(122), - token external_token: optional(123), - token suspend_token: optional(124), - token override_token: optional(125), - token abstract_token: optional(126), - token final_token: optional(127), - token open_token: optional(128), - token const_token: optional(129), - token lateinit_token: optional(130), - token vararg_token: optional(131), - token noinline_token: optional(132), - token crossinline_token: optional(133), - token reified_token: optional(134), - token expect_token: optional(135), - token actual_token: optional(136), - token identifier_token: optional(148), - } -} - -antlr4_runtime::__antlr4_rust_context! { - pub struct IdentifierContext { - rule_index: 173, - context_kind: any, - validated_downcast: branded, - attributes: { - }, - methods: { - rule_node: rule_node, - child_count: child_count, - direct_terminals: direct_terminals, - start: start, - text: text, - } - } -} - -antlr4_runtime::__antlr4_rust_context_accessors! { - IdentifierContext { - rule simple_identifier_children: many(SimpleIdentifierContext[172]), - token nl_tokens: many(5), - token dot_tokens: many(7), - } -} - -/// Checks generated required-child invariants without changing the -/// recovery-oriented tree's type. -/// -/// Strict parsing calls this after proving that lexer and parser syntax-error -/// counts are both zero. It is public so structural runtime/codegen invariant -/// failures can be diagnosed independently. -pub fn validate_tree_structure( - parsed: &antlr4_runtime::ParsedFile, -) -> Result<(), KotlinValidationError> { - let tree = parsed.tree(); - if tree.as_rule().is_none() { - return Err(KotlinValidationError::InvalidRoot); - } - for node in tree.descendants() { - match node.kind() { - antlr4_runtime::NodeKind::Terminal => {} - antlr4_runtime::NodeKind::Error => { - let symbol = node - .as_error() - .expect("error node kind checked") - .symbol(); - return Err(KotlinValidationError::RecoveredErrorNode { - line: symbol.line(), - column: symbol.column(), - text: symbol.text_or_empty().to_owned(), - }); - } - antlr4_runtime::NodeKind::Rule => { - let context = node.as_rule().expect("rule node kind checked"); - match __context_kind(context) { - 0 => { - let context = KotlinFileContext::__from_listener_node(context, None); - context.package_header()?; - context.import_list()?; - context.eof_token()?; - }, - 1 => { - let context = ScriptContext::__from_listener_node(context, None); - context.package_header()?; - context.import_list()?; - context.eof_token()?; - }, - 2 => { - let context = ShebangLineContext::__from_listener_node(context, None); - context.shebang_line_token()?; - antlr4_runtime::require_min_count(context.nl_tokens().count(), 1, "ShebangLineContext", "NL")?; - }, - 3 => { - let context = FileAnnotationContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.unescaped_annotation_children().count(), 1, "FileAnnotationContext", "unescapedAnnotation")?; - context.colon_token()?; - context.file_token()?; - }, - 4 => { - }, - 5 => { - }, - 6 => { - let context = ImportHeaderContext::__from_listener_node(context, None); - context.identifier()?; - context.import_token()?; - }, - 7 => { - let context = ImportAliasContext::__from_listener_node(context, None); - context.simple_identifier()?; - context.as_token()?; - }, - 8 => { - let context = TopLevelObjectContext::__from_listener_node(context, None); - context.declaration()?; - }, - 9 => { - let context = TypeAliasContext::__from_listener_node(context, None); - context.r#type()?; - context.simple_identifier()?; - context.assignment_token()?; - context.type_alias_token()?; - }, - 10 => { - }, - 11 => { - let context = ClassDeclarationContext::__from_listener_node(context, None); - context.simple_identifier()?; - }, - 12 => { - let context = PrimaryConstructorContext::__from_listener_node(context, None); - context.class_parameters()?; - }, - 13 => { - let context = ClassBodyContext::__from_listener_node(context, None); - context.class_member_declarations()?; - context.lcurl_token()?; - context.rcurl_token()?; - }, - 14 => { - let context = ClassParametersContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 15 => { - let context = ClassParameterContext::__from_listener_node(context, None); - context.r#type()?; - context.simple_identifier()?; - context.colon_token()?; - }, - 16 => { - let context = DelegationSpecifiersContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.annotated_delegation_specifier_children().count(), 1, "DelegationSpecifiersContext", "annotatedDelegationSpecifier")?; - }, - 17 => { - }, - 18 => { - let context = ConstructorInvocationContext::__from_listener_node(context, None); - context.user_type()?; - context.value_arguments()?; - }, - 19 => { - let context = AnnotatedDelegationSpecifierContext::__from_listener_node(context, None); - context.delegation_specifier()?; - }, - 20 => { - let context = ExplicitDelegationContext::__from_listener_node(context, None); - context.expression()?; - context.by_token()?; - }, - 21 => { - let context = TypeParametersContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_parameter_children().count(), 1, "TypeParametersContext", "typeParameter")?; - context.langle_token()?; - context.rangle_token()?; - }, - 22 => { - let context = TypeParameterContext::__from_listener_node(context, None); - context.simple_identifier()?; - }, - 23 => { - let context = TypeConstraintsContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_constraint_children().count(), 1, "TypeConstraintsContext", "typeConstraint")?; - context.where_token()?; - }, - 24 => { - let context = TypeConstraintContext::__from_listener_node(context, None); - context.r#type()?; - context.simple_identifier()?; - context.colon_token()?; - }, - 25 => { - }, - 26 => { - }, - 27 => { - let context = AnonymousInitializerContext::__from_listener_node(context, None); - context.block()?; - context.init_token()?; - }, - 28 => { - let context = CompanionObjectContext::__from_listener_node(context, None); - context.object_token()?; - context.companion_token()?; - }, - 29 => { - let context = FunctionValueParametersContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 30 => { - let context = FunctionValueParameterContext::__from_listener_node(context, None); - context.parameter()?; - }, - 31 => { - let context = FunctionDeclarationContext::__from_listener_node(context, None); - context.function_value_parameters()?; - context.simple_identifier()?; - context.fun_token()?; - }, - 32 => { - }, - 33 => { - let context = VariableDeclarationContext::__from_listener_node(context, None); - context.simple_identifier()?; - }, - 34 => { - let context = MultiVariableDeclarationContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.variable_declaration_children().count(), 1, "MultiVariableDeclarationContext", "variableDeclaration")?; - context.lparen_token()?; - context.rparen_token()?; - }, - 35 => { - }, - 36 => { - let context = PropertyDelegateContext::__from_listener_node(context, None); - context.expression()?; - context.by_token()?; - }, - 37 => { - let context = GetterContext::__from_listener_node(context, None); - context.get_token()?; - }, - 38 => { - let context = SetterContext::__from_listener_node(context, None); - context.set_token()?; - }, - 39 => { - let context = ParametersWithOptionalTypeContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 40 => { - let context = FunctionValueParameterWithOptionalTypeContext::__from_listener_node(context, None); - context.parameter_with_optional_type()?; - }, - 41 => { - let context = ParameterWithOptionalTypeContext::__from_listener_node(context, None); - context.simple_identifier()?; - }, - 42 => { - let context = ParameterContext::__from_listener_node(context, None); - context.r#type()?; - context.simple_identifier()?; - context.colon_token()?; - }, - 43 => { - let context = ObjectDeclarationContext::__from_listener_node(context, None); - context.simple_identifier()?; - context.object_token()?; - }, - 44 => { - let context = SecondaryConstructorContext::__from_listener_node(context, None); - context.function_value_parameters()?; - context.constructor_token()?; - }, - 45 => { - let context = ConstructorDelegationCallContext::__from_listener_node(context, None); - context.value_arguments()?; - }, - 46 => { - let context = EnumClassBodyContext::__from_listener_node(context, None); - context.lcurl_token()?; - context.rcurl_token()?; - }, - 47 => { - let context = EnumEntriesContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.enum_entry_children().count(), 1, "EnumEntriesContext", "enumEntry")?; - }, - 48 => { - let context = EnumEntryContext::__from_listener_node(context, None); - context.simple_identifier()?; - }, - 49 => { - }, - 50 => { - }, - 51 => { - let context = NullableTypeContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.quest_children().count(), 1, "NullableTypeContext", "quest")?; - }, - 52 => { - }, - 53 => { - let context = UserTypeContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.simple_user_type_children().count(), 1, "UserTypeContext", "simpleUserType")?; - }, - 54 => { - let context = SimpleUserTypeContext::__from_listener_node(context, None); - context.simple_identifier()?; - }, - 55 => { - }, - 56 => { - let context = TypeProjectionModifiersContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_projection_modifier_children().count(), 1, "TypeProjectionModifiersContext", "typeProjectionModifier")?; - }, - 57 => { - }, - 58 => { - let context = FunctionTypeContext::__from_listener_node(context, None); - context.r#type()?; - context.function_type_parameters()?; - context.arrow_token()?; - }, - 59 => { - let context = FunctionTypeParametersContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 60 => { - let context = ParenthesizedTypeContext::__from_listener_node(context, None); - context.r#type()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 61 => { - }, - 62 => { - let context = ParenthesizedUserTypeContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 63 => { - let context = DefinitelyNonNullableTypeContext::__from_listener_node(context, None); - context.amp_token()?; - }, - 64 => { - }, - 65 => { - }, - 66 => { - let context = LabelContext::__from_listener_node(context, None); - context.simple_identifier()?; - }, - 67 => { - }, - 68 => { - let context = BlockContext::__from_listener_node(context, None); - context.statements()?; - context.lcurl_token()?; - context.rcurl_token()?; - }, - 69 => { - }, - 70 => { - let context = ForStatementContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - context.for_token()?; - context.in_token()?; - }, - 71 => { - let context = WhileStatementContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - context.while_token()?; - }, - 72 => { - let context = DoWhileStatementContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - context.do_token()?; - context.while_token()?; - }, - 73 => { - let context = AssignmentContext::__from_listener_node(context, None); - context.expression()?; - }, - 74 => { - }, - 75 => { - }, - 76 => { - let context = ExpressionContext::__from_listener_node(context, None); - context.disjunction()?; - }, - 77 => { - let context = DisjunctionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.conjunction_children().count(), 1, "DisjunctionContext", "conjunction")?; - }, - 78 => { - let context = ConjunctionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.equality_children().count(), 1, "ConjunctionContext", "equality")?; - }, - 79 => { - let context = EqualityContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.comparison_children().count(), 1, "EqualityContext", "comparison")?; - }, - 80 => { - let context = ComparisonContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.generic_call_like_comparison_children().count(), 1, "ComparisonContext", "genericCallLikeComparison")?; - }, - 81 => { - let context = GenericCallLikeComparisonContext::__from_listener_node(context, None); - context.infix_operation()?; - }, - 82 => { - let context = InfixOperationContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.elvis_expression_children().count(), 1, "InfixOperationContext", "elvisExpression")?; - }, - 83 => { - let context = ElvisExpressionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.infix_function_call_children().count(), 1, "ElvisExpressionContext", "infixFunctionCall")?; - }, - 84 => { - let context = ElvisContext::__from_listener_node(context, None); - context.colon_token()?; - context.quest_no_ws_token()?; - }, - 85 => { - let context = InfixFunctionCallContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.range_expression_children().count(), 1, "InfixFunctionCallContext", "rangeExpression")?; - }, - 86 => { - let context = RangeExpressionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.additive_expression_children().count(), 1, "RangeExpressionContext", "additiveExpression")?; - }, - 87 => { - let context = AdditiveExpressionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.multiplicative_expression_children().count(), 1, "AdditiveExpressionContext", "multiplicativeExpression")?; - }, - 88 => { - let context = MultiplicativeExpressionContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.as_expression_children().count(), 1, "MultiplicativeExpressionContext", "asExpression")?; - }, - 89 => { - let context = AsExpressionContext::__from_listener_node(context, None); - context.prefix_unary_expression()?; - }, - 90 => { - let context = PrefixUnaryExpressionContext::__from_listener_node(context, None); - context.postfix_unary_expression()?; - }, - 91 => { - }, - 92 => { - let context = PostfixUnaryExpressionContext::__from_listener_node(context, None); - context.primary_expression()?; - }, - 93 => { - }, - 94 => { - }, - 95 => { - let context = ParenthesizedDirectlyAssignableExpressionContext::__from_listener_node(context, None); - context.directly_assignable_expression()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 96 => { - }, - 97 => { - let context = ParenthesizedAssignableExpressionContext::__from_listener_node(context, None); - context.assignable_expression()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 98 => { - }, - 99 => { - let context = IndexingSuffixContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.expression_children().count(), 1, "IndexingSuffixContext", "expression")?; - context.lsquare_token()?; - context.rsquare_token()?; - }, - 100 => { - let context = NavigationSuffixContext::__from_listener_node(context, None); - context.member_access_operator()?; - }, - 101 => { - }, - 102 => { - let context = AnnotatedLambdaContext::__from_listener_node(context, None); - context.lambda_literal()?; - }, - 103 => { - let context = TypeArgumentsContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_projection_children().count(), 1, "TypeArgumentsContext", "typeProjection")?; - context.langle_token()?; - context.rangle_token()?; - }, - 104 => { - let context = ValueArgumentsContext::__from_listener_node(context, None); - context.lparen_token()?; - context.rparen_token()?; - }, - 105 => { - let context = ValueArgumentContext::__from_listener_node(context, None); - context.expression()?; - }, - 106 => { - }, - 107 => { - let context = ParenthesizedExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 108 => { - let context = CollectionLiteralContext::__from_listener_node(context, None); - context.lsquare_token()?; - context.rsquare_token()?; - }, - 109 => { - }, - 110 => { - }, - 111 => { - let context = LineStringLiteralContext::__from_listener_node(context, None); - context.quote_open_token()?; - context.quote_close_token()?; - }, - 112 => { - let context = MultiLineStringLiteralContext::__from_listener_node(context, None); - context.triple_quote_open_token()?; - context.triple_quote_close_token()?; - }, - 113 => { - }, - 114 => { - let context = LineStringExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.rcurl_token()?; - context.line_str_expr_start_token()?; - }, - 115 => { - }, - 116 => { - let context = MultiLineStringExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.rcurl_token()?; - context.multi_line_str_expr_start_token()?; - }, - 117 => { - let context = LambdaLiteralContext::__from_listener_node(context, None); - context.statements()?; - context.lcurl_token()?; - context.rcurl_token()?; - }, - 118 => { - let context = LambdaParametersContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.lambda_parameter_children().count(), 1, "LambdaParametersContext", "lambdaParameter")?; - }, - 119 => { - }, - 120 => { - let context = AnonymousFunctionContext::__from_listener_node(context, None); - context.parameters_with_optional_type()?; - context.fun_token()?; - }, - 121 => { - }, - 122 => { - let context = ObjectLiteralContext::__from_listener_node(context, None); - context.object_token()?; - }, - 123 => { - }, - 124 => { - }, - 125 => { - let context = IfExpressionContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - context.if_token()?; - }, - 126 => { - let context = WhenSubjectContext::__from_listener_node(context, None); - context.expression()?; - context.lparen_token()?; - context.rparen_token()?; - }, - 127 => { - let context = WhenExpressionContext::__from_listener_node(context, None); - context.lcurl_token()?; - context.rcurl_token()?; - context.when_token()?; - }, - 128 => { - let context = WhenEntryContext::__from_listener_node(context, None); - context.control_structure_body()?; - context.arrow_token()?; - }, - 129 => { - }, - 130 => { - let context = RangeTestContext::__from_listener_node(context, None); - context.expression()?; - context.in_operator()?; - }, - 131 => { - let context = TypeTestContext::__from_listener_node(context, None); - context.r#type()?; - context.is_operator()?; - }, - 132 => { - let context = TryExpressionContext::__from_listener_node(context, None); - context.block()?; - context.try_token()?; - }, - 133 => { - let context = CatchBlockContext::__from_listener_node(context, None); - context.r#type()?; - context.block()?; - context.simple_identifier()?; - context.lparen_token()?; - context.rparen_token()?; - context.colon_token()?; - context.catch_token()?; - }, - 134 => { - let context = FinallyBlockContext::__from_listener_node(context, None); - context.block()?; - context.finally_token()?; - }, - 135 => { - }, - 136 => { - let context = CallableReferenceContext::__from_listener_node(context, None); - context.coloncolon_token()?; - }, - 137 => { - }, - 138 => { - }, - 139 => { - }, - 140 => { - }, - 141 => { - }, - 142 => { - }, - 143 => { - }, - 144 => { - }, - 145 => { - }, - 146 => { - }, - 147 => { - }, - 148 => { - }, - 149 => { - let context = SafeNavContext::__from_listener_node(context, None); - context.dot_token()?; - context.quest_no_ws_token()?; - }, - 150 => { - }, - 151 => { - }, - 152 => { - }, - 153 => { - let context = TypeModifiersContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_modifier_children().count(), 1, "TypeModifiersContext", "typeModifier")?; - }, - 154 => { - }, - 155 => { - }, - 156 => { - }, - 157 => { - }, - 158 => { - }, - 159 => { - let context = TypeParameterModifiersContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.type_parameter_modifier_children().count(), 1, "TypeParameterModifiersContext", "typeParameterModifier")?; - }, - 160 => { - }, - 161 => { - }, - 162 => { - let context = PropertyModifierContext::__from_listener_node(context, None); - context.const_token()?; - }, - 163 => { - }, - 164 => { - }, - 165 => { - let context = ReificationModifierContext::__from_listener_node(context, None); - context.reified_token()?; - }, - 166 => { - }, - 167 => { - }, - 168 => { - let context = SingleAnnotationContext::__from_listener_node(context, None); - context.unescaped_annotation()?; - }, - 169 => { - let context = MultiAnnotationContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.unescaped_annotation_children().count(), 1, "MultiAnnotationContext", "unescapedAnnotation")?; - context.lsquare_token()?; - context.rsquare_token()?; - }, - 170 => { - let context = AnnotationUseSiteTargetContext::__from_listener_node(context, None); - context.colon_token()?; - }, - 171 => { - }, - 172 => { - }, - 173 => { - let context = IdentifierContext::__from_listener_node(context, None); - antlr4_runtime::require_min_count(context.simple_identifier_children().count(), 1, "IdentifierContext", "simpleIdentifier")?; - }, - _ => { - return Err(KotlinValidationError::UnknownRule { - rule_index: context.rule_index(), - }); - } - } - } - } - } - Ok(()) -} - -#[allow(dead_code, unused_variables)] -pub trait KotlinListener { - fn walk(&mut self, tree: antlr4_runtime::Node<'_>) -> Result<(), E> - where - Self: Sized, - { - KotlinTreeWalker::walk(self, tree) - } - - fn enter_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), E> { Ok(()) } - fn exit_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), E> { Ok(()) } - - fn enter_kotlin_file(&mut self, _ctx: &KotlinFileContext) -> Result<(), E> { Ok(()) } - fn exit_kotlin_file(&mut self, _ctx: &KotlinFileContext) -> Result<(), E> { Ok(()) } - fn enter_script(&mut self, _ctx: &ScriptContext) -> Result<(), E> { Ok(()) } - fn exit_script(&mut self, _ctx: &ScriptContext) -> Result<(), E> { Ok(()) } - fn enter_shebang_line(&mut self, _ctx: &ShebangLineContext) -> Result<(), E> { Ok(()) } - fn exit_shebang_line(&mut self, _ctx: &ShebangLineContext) -> Result<(), E> { Ok(()) } - fn enter_file_annotation(&mut self, _ctx: &FileAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_file_annotation(&mut self, _ctx: &FileAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_package_header(&mut self, _ctx: &PackageHeaderContext) -> Result<(), E> { Ok(()) } - fn exit_package_header(&mut self, _ctx: &PackageHeaderContext) -> Result<(), E> { Ok(()) } - fn enter_import_list(&mut self, _ctx: &ImportListContext) -> Result<(), E> { Ok(()) } - fn exit_import_list(&mut self, _ctx: &ImportListContext) -> Result<(), E> { Ok(()) } - fn enter_import_header(&mut self, _ctx: &ImportHeaderContext) -> Result<(), E> { Ok(()) } - fn exit_import_header(&mut self, _ctx: &ImportHeaderContext) -> Result<(), E> { Ok(()) } - fn enter_import_alias(&mut self, _ctx: &ImportAliasContext) -> Result<(), E> { Ok(()) } - fn exit_import_alias(&mut self, _ctx: &ImportAliasContext) -> Result<(), E> { Ok(()) } - fn enter_top_level_object(&mut self, _ctx: &TopLevelObjectContext) -> Result<(), E> { Ok(()) } - fn exit_top_level_object(&mut self, _ctx: &TopLevelObjectContext) -> Result<(), E> { Ok(()) } - fn enter_type_alias(&mut self, _ctx: &TypeAliasContext) -> Result<(), E> { Ok(()) } - fn exit_type_alias(&mut self, _ctx: &TypeAliasContext) -> Result<(), E> { Ok(()) } - fn enter_declaration(&mut self, _ctx: &DeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_declaration(&mut self, _ctx: &DeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_primary_constructor(&mut self, _ctx: &PrimaryConstructorContext) -> Result<(), E> { Ok(()) } - fn exit_primary_constructor(&mut self, _ctx: &PrimaryConstructorContext) -> Result<(), E> { Ok(()) } - fn enter_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn exit_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn enter_class_parameters(&mut self, _ctx: &ClassParametersContext) -> Result<(), E> { Ok(()) } - fn exit_class_parameters(&mut self, _ctx: &ClassParametersContext) -> Result<(), E> { Ok(()) } - fn enter_class_parameter(&mut self, _ctx: &ClassParameterContext) -> Result<(), E> { Ok(()) } - fn exit_class_parameter(&mut self, _ctx: &ClassParameterContext) -> Result<(), E> { Ok(()) } - fn enter_delegation_specifiers(&mut self, _ctx: &DelegationSpecifiersContext) -> Result<(), E> { Ok(()) } - fn exit_delegation_specifiers(&mut self, _ctx: &DelegationSpecifiersContext) -> Result<(), E> { Ok(()) } - fn enter_delegation_specifier(&mut self, _ctx: &DelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_delegation_specifier(&mut self, _ctx: &DelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_invocation(&mut self, _ctx: &ConstructorInvocationContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_invocation(&mut self, _ctx: &ConstructorInvocationContext) -> Result<(), E> { Ok(()) } - fn enter_annotated_delegation_specifier(&mut self, _ctx: &AnnotatedDelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_annotated_delegation_specifier(&mut self, _ctx: &AnnotatedDelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_delegation(&mut self, _ctx: &ExplicitDelegationContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_delegation(&mut self, _ctx: &ExplicitDelegationContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn enter_type_constraints(&mut self, _ctx: &TypeConstraintsContext) -> Result<(), E> { Ok(()) } - fn exit_type_constraints(&mut self, _ctx: &TypeConstraintsContext) -> Result<(), E> { Ok(()) } - fn enter_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_class_member_declarations(&mut self, _ctx: &ClassMemberDeclarationsContext) -> Result<(), E> { Ok(()) } - fn exit_class_member_declarations(&mut self, _ctx: &ClassMemberDeclarationsContext) -> Result<(), E> { Ok(()) } - fn enter_class_member_declaration(&mut self, _ctx: &ClassMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_member_declaration(&mut self, _ctx: &ClassMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_initializer(&mut self, _ctx: &AnonymousInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_initializer(&mut self, _ctx: &AnonymousInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_companion_object(&mut self, _ctx: &CompanionObjectContext) -> Result<(), E> { Ok(()) } - fn exit_companion_object(&mut self, _ctx: &CompanionObjectContext) -> Result<(), E> { Ok(()) } - fn enter_function_value_parameters(&mut self, _ctx: &FunctionValueParametersContext) -> Result<(), E> { Ok(()) } - fn exit_function_value_parameters(&mut self, _ctx: &FunctionValueParametersContext) -> Result<(), E> { Ok(()) } - fn enter_function_value_parameter(&mut self, _ctx: &FunctionValueParameterContext) -> Result<(), E> { Ok(()) } - fn exit_function_value_parameter(&mut self, _ctx: &FunctionValueParameterContext) -> Result<(), E> { Ok(()) } - fn enter_function_declaration(&mut self, _ctx: &FunctionDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_function_declaration(&mut self, _ctx: &FunctionDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_function_body(&mut self, _ctx: &FunctionBodyContext) -> Result<(), E> { Ok(()) } - fn exit_function_body(&mut self, _ctx: &FunctionBodyContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_multi_variable_declaration(&mut self, _ctx: &MultiVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_multi_variable_declaration(&mut self, _ctx: &MultiVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_property_delegate(&mut self, _ctx: &PropertyDelegateContext) -> Result<(), E> { Ok(()) } - fn exit_property_delegate(&mut self, _ctx: &PropertyDelegateContext) -> Result<(), E> { Ok(()) } - fn enter_getter(&mut self, _ctx: &GetterContext) -> Result<(), E> { Ok(()) } - fn exit_getter(&mut self, _ctx: &GetterContext) -> Result<(), E> { Ok(()) } - fn enter_setter(&mut self, _ctx: &SetterContext) -> Result<(), E> { Ok(()) } - fn exit_setter(&mut self, _ctx: &SetterContext) -> Result<(), E> { Ok(()) } - fn enter_parameters_with_optional_type(&mut self, _ctx: &ParametersWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parameters_with_optional_type(&mut self, _ctx: &ParametersWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn enter_function_value_parameter_with_optional_type(&mut self, _ctx: &FunctionValueParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn exit_function_value_parameter_with_optional_type(&mut self, _ctx: &FunctionValueParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_with_optional_type(&mut self, _ctx: &ParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_with_optional_type(&mut self, _ctx: &ParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn enter_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn exit_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn enter_object_declaration(&mut self, _ctx: &ObjectDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_object_declaration(&mut self, _ctx: &ObjectDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_secondary_constructor(&mut self, _ctx: &SecondaryConstructorContext) -> Result<(), E> { Ok(()) } - fn exit_secondary_constructor(&mut self, _ctx: &SecondaryConstructorContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_delegation_call(&mut self, _ctx: &ConstructorDelegationCallContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_delegation_call(&mut self, _ctx: &ConstructorDelegationCallContext) -> Result<(), E> { Ok(()) } - fn enter_enum_class_body(&mut self, _ctx: &EnumClassBodyContext) -> Result<(), E> { Ok(()) } - fn exit_enum_class_body(&mut self, _ctx: &EnumClassBodyContext) -> Result<(), E> { Ok(()) } - fn enter_enum_entries(&mut self, _ctx: &EnumEntriesContext) -> Result<(), E> { Ok(()) } - fn exit_enum_entries(&mut self, _ctx: &EnumEntriesContext) -> Result<(), E> { Ok(()) } - fn enter_enum_entry(&mut self, _ctx: &EnumEntryContext) -> Result<(), E> { Ok(()) } - fn exit_enum_entry(&mut self, _ctx: &EnumEntryContext) -> Result<(), E> { Ok(()) } - fn enter_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn exit_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn enter_type_reference(&mut self, _ctx: &TypeReferenceContext) -> Result<(), E> { Ok(()) } - fn exit_type_reference(&mut self, _ctx: &TypeReferenceContext) -> Result<(), E> { Ok(()) } - fn enter_nullable_type(&mut self, _ctx: &NullableTypeContext) -> Result<(), E> { Ok(()) } - fn exit_nullable_type(&mut self, _ctx: &NullableTypeContext) -> Result<(), E> { Ok(()) } - fn enter_quest(&mut self, _ctx: &QuestContext) -> Result<(), E> { Ok(()) } - fn exit_quest(&mut self, _ctx: &QuestContext) -> Result<(), E> { Ok(()) } - fn enter_user_type(&mut self, _ctx: &UserTypeContext) -> Result<(), E> { Ok(()) } - fn exit_user_type(&mut self, _ctx: &UserTypeContext) -> Result<(), E> { Ok(()) } - fn enter_simple_user_type(&mut self, _ctx: &SimpleUserTypeContext) -> Result<(), E> { Ok(()) } - fn exit_simple_user_type(&mut self, _ctx: &SimpleUserTypeContext) -> Result<(), E> { Ok(()) } - fn enter_type_projection(&mut self, _ctx: &TypeProjectionContext) -> Result<(), E> { Ok(()) } - fn exit_type_projection(&mut self, _ctx: &TypeProjectionContext) -> Result<(), E> { Ok(()) } - fn enter_type_projection_modifiers(&mut self, _ctx: &TypeProjectionModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_type_projection_modifiers(&mut self, _ctx: &TypeProjectionModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_type_projection_modifier(&mut self, _ctx: &TypeProjectionModifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_projection_modifier(&mut self, _ctx: &TypeProjectionModifierContext) -> Result<(), E> { Ok(()) } - fn enter_function_type(&mut self, _ctx: &FunctionTypeContext) -> Result<(), E> { Ok(()) } - fn exit_function_type(&mut self, _ctx: &FunctionTypeContext) -> Result<(), E> { Ok(()) } - fn enter_function_type_parameters(&mut self, _ctx: &FunctionTypeParametersContext) -> Result<(), E> { Ok(()) } - fn exit_function_type_parameters(&mut self, _ctx: &FunctionTypeParametersContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_type(&mut self, _ctx: &ParenthesizedTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_type(&mut self, _ctx: &ParenthesizedTypeContext) -> Result<(), E> { Ok(()) } - fn enter_receiver_type(&mut self, _ctx: &ReceiverTypeContext) -> Result<(), E> { Ok(()) } - fn exit_receiver_type(&mut self, _ctx: &ReceiverTypeContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_user_type(&mut self, _ctx: &ParenthesizedUserTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_user_type(&mut self, _ctx: &ParenthesizedUserTypeContext) -> Result<(), E> { Ok(()) } - fn enter_definitely_non_nullable_type(&mut self, _ctx: &DefinitelyNonNullableTypeContext) -> Result<(), E> { Ok(()) } - fn exit_definitely_non_nullable_type(&mut self, _ctx: &DefinitelyNonNullableTypeContext) -> Result<(), E> { Ok(()) } - fn enter_statements(&mut self, _ctx: &StatementsContext) -> Result<(), E> { Ok(()) } - fn exit_statements(&mut self, _ctx: &StatementsContext) -> Result<(), E> { Ok(()) } - fn enter_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn exit_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn enter_label(&mut self, _ctx: &LabelContext) -> Result<(), E> { Ok(()) } - fn exit_label(&mut self, _ctx: &LabelContext) -> Result<(), E> { Ok(()) } - fn enter_control_structure_body(&mut self, _ctx: &ControlStructureBodyContext) -> Result<(), E> { Ok(()) } - fn exit_control_structure_body(&mut self, _ctx: &ControlStructureBodyContext) -> Result<(), E> { Ok(()) } - fn enter_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn exit_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn enter_loop_statement(&mut self, _ctx: &LoopStatementContext) -> Result<(), E> { Ok(()) } - fn exit_loop_statement(&mut self, _ctx: &LoopStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn enter_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn exit_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn enter_do_while_statement(&mut self, _ctx: &DoWhileStatementContext) -> Result<(), E> { Ok(()) } - fn exit_do_while_statement(&mut self, _ctx: &DoWhileStatementContext) -> Result<(), E> { Ok(()) } - fn enter_assignment(&mut self, _ctx: &AssignmentContext) -> Result<(), E> { Ok(()) } - fn exit_assignment(&mut self, _ctx: &AssignmentContext) -> Result<(), E> { Ok(()) } - fn enter_semi(&mut self, _ctx: &SemiContext) -> Result<(), E> { Ok(()) } - fn exit_semi(&mut self, _ctx: &SemiContext) -> Result<(), E> { Ok(()) } - fn enter_semis(&mut self, _ctx: &SemisContext) -> Result<(), E> { Ok(()) } - fn exit_semis(&mut self, _ctx: &SemisContext) -> Result<(), E> { Ok(()) } - fn enter_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_disjunction(&mut self, _ctx: &DisjunctionContext) -> Result<(), E> { Ok(()) } - fn exit_disjunction(&mut self, _ctx: &DisjunctionContext) -> Result<(), E> { Ok(()) } - fn enter_conjunction(&mut self, _ctx: &ConjunctionContext) -> Result<(), E> { Ok(()) } - fn exit_conjunction(&mut self, _ctx: &ConjunctionContext) -> Result<(), E> { Ok(()) } - fn enter_equality(&mut self, _ctx: &EqualityContext) -> Result<(), E> { Ok(()) } - fn exit_equality(&mut self, _ctx: &EqualityContext) -> Result<(), E> { Ok(()) } - fn enter_comparison(&mut self, _ctx: &ComparisonContext) -> Result<(), E> { Ok(()) } - fn exit_comparison(&mut self, _ctx: &ComparisonContext) -> Result<(), E> { Ok(()) } - fn enter_generic_call_like_comparison(&mut self, _ctx: &GenericCallLikeComparisonContext) -> Result<(), E> { Ok(()) } - fn exit_generic_call_like_comparison(&mut self, _ctx: &GenericCallLikeComparisonContext) -> Result<(), E> { Ok(()) } - fn enter_infix_operation(&mut self, _ctx: &InfixOperationContext) -> Result<(), E> { Ok(()) } - fn exit_infix_operation(&mut self, _ctx: &InfixOperationContext) -> Result<(), E> { Ok(()) } - fn enter_elvis_expression(&mut self, _ctx: &ElvisExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_elvis_expression(&mut self, _ctx: &ElvisExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_elvis(&mut self, _ctx: &ElvisContext) -> Result<(), E> { Ok(()) } - fn exit_elvis(&mut self, _ctx: &ElvisContext) -> Result<(), E> { Ok(()) } - fn enter_infix_function_call(&mut self, _ctx: &InfixFunctionCallContext) -> Result<(), E> { Ok(()) } - fn exit_infix_function_call(&mut self, _ctx: &InfixFunctionCallContext) -> Result<(), E> { Ok(()) } - fn enter_range_expression(&mut self, _ctx: &RangeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_range_expression(&mut self, _ctx: &RangeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_additive_expression(&mut self, _ctx: &AdditiveExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_additive_expression(&mut self, _ctx: &AdditiveExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_multiplicative_expression(&mut self, _ctx: &MultiplicativeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_multiplicative_expression(&mut self, _ctx: &MultiplicativeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_as_expression(&mut self, _ctx: &AsExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_as_expression(&mut self, _ctx: &AsExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_unary_prefix(&mut self, _ctx: &UnaryPrefixContext) -> Result<(), E> { Ok(()) } - fn exit_unary_prefix(&mut self, _ctx: &UnaryPrefixContext) -> Result<(), E> { Ok(()) } - fn enter_postfix_unary_expression(&mut self, _ctx: &PostfixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_postfix_unary_expression(&mut self, _ctx: &PostfixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_postfix_unary_suffix(&mut self, _ctx: &PostfixUnarySuffixContext) -> Result<(), E> { Ok(()) } - fn exit_postfix_unary_suffix(&mut self, _ctx: &PostfixUnarySuffixContext) -> Result<(), E> { Ok(()) } - fn enter_directly_assignable_expression(&mut self, _ctx: &DirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_directly_assignable_expression(&mut self, _ctx: &DirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_directly_assignable_expression(&mut self, _ctx: &ParenthesizedDirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_directly_assignable_expression(&mut self, _ctx: &ParenthesizedDirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_assignable_expression(&mut self, _ctx: &AssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_assignable_expression(&mut self, _ctx: &AssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_assignable_expression(&mut self, _ctx: &ParenthesizedAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_assignable_expression(&mut self, _ctx: &ParenthesizedAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_assignable_suffix(&mut self, _ctx: &AssignableSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_assignable_suffix(&mut self, _ctx: &AssignableSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_indexing_suffix(&mut self, _ctx: &IndexingSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_indexing_suffix(&mut self, _ctx: &IndexingSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_navigation_suffix(&mut self, _ctx: &NavigationSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_navigation_suffix(&mut self, _ctx: &NavigationSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_call_suffix(&mut self, _ctx: &CallSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_call_suffix(&mut self, _ctx: &CallSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_annotated_lambda(&mut self, _ctx: &AnnotatedLambdaContext) -> Result<(), E> { Ok(()) } - fn exit_annotated_lambda(&mut self, _ctx: &AnnotatedLambdaContext) -> Result<(), E> { Ok(()) } - fn enter_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_value_arguments(&mut self, _ctx: &ValueArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_value_arguments(&mut self, _ctx: &ValueArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_value_argument(&mut self, _ctx: &ValueArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_value_argument(&mut self, _ctx: &ValueArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_primary_expression(&mut self, _ctx: &PrimaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_primary_expression(&mut self, _ctx: &PrimaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_collection_literal(&mut self, _ctx: &CollectionLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_collection_literal(&mut self, _ctx: &CollectionLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_literal_constant(&mut self, _ctx: &LiteralConstantContext) -> Result<(), E> { Ok(()) } - fn exit_literal_constant(&mut self, _ctx: &LiteralConstantContext) -> Result<(), E> { Ok(()) } - fn enter_string_literal(&mut self, _ctx: &StringLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_string_literal(&mut self, _ctx: &StringLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_line_string_literal(&mut self, _ctx: &LineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_line_string_literal(&mut self, _ctx: &LineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_string_literal(&mut self, _ctx: &MultiLineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_string_literal(&mut self, _ctx: &MultiLineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_line_string_content(&mut self, _ctx: &LineStringContentContext) -> Result<(), E> { Ok(()) } - fn exit_line_string_content(&mut self, _ctx: &LineStringContentContext) -> Result<(), E> { Ok(()) } - fn enter_line_string_expression(&mut self, _ctx: &LineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_line_string_expression(&mut self, _ctx: &LineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_string_content(&mut self, _ctx: &MultiLineStringContentContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_string_content(&mut self, _ctx: &MultiLineStringContentContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_string_expression(&mut self, _ctx: &MultiLineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_string_expression(&mut self, _ctx: &MultiLineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_literal(&mut self, _ctx: &LambdaLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_literal(&mut self, _ctx: &LambdaLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_parameter(&mut self, _ctx: &LambdaParameterContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_parameter(&mut self, _ctx: &LambdaParameterContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_function(&mut self, _ctx: &AnonymousFunctionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_function(&mut self, _ctx: &AnonymousFunctionContext) -> Result<(), E> { Ok(()) } - fn enter_function_literal(&mut self, _ctx: &FunctionLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_function_literal(&mut self, _ctx: &FunctionLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_object_literal(&mut self, _ctx: &ObjectLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_object_literal(&mut self, _ctx: &ObjectLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_super_expression(&mut self, _ctx: &SuperExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_super_expression(&mut self, _ctx: &SuperExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_if_expression(&mut self, _ctx: &IfExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_if_expression(&mut self, _ctx: &IfExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_when_subject(&mut self, _ctx: &WhenSubjectContext) -> Result<(), E> { Ok(()) } - fn exit_when_subject(&mut self, _ctx: &WhenSubjectContext) -> Result<(), E> { Ok(()) } - fn enter_when_expression(&mut self, _ctx: &WhenExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_when_expression(&mut self, _ctx: &WhenExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_when_entry(&mut self, _ctx: &WhenEntryContext) -> Result<(), E> { Ok(()) } - fn exit_when_entry(&mut self, _ctx: &WhenEntryContext) -> Result<(), E> { Ok(()) } - fn enter_when_condition(&mut self, _ctx: &WhenConditionContext) -> Result<(), E> { Ok(()) } - fn exit_when_condition(&mut self, _ctx: &WhenConditionContext) -> Result<(), E> { Ok(()) } - fn enter_range_test(&mut self, _ctx: &RangeTestContext) -> Result<(), E> { Ok(()) } - fn exit_range_test(&mut self, _ctx: &RangeTestContext) -> Result<(), E> { Ok(()) } - fn enter_type_test(&mut self, _ctx: &TypeTestContext) -> Result<(), E> { Ok(()) } - fn exit_type_test(&mut self, _ctx: &TypeTestContext) -> Result<(), E> { Ok(()) } - fn enter_try_expression(&mut self, _ctx: &TryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_try_expression(&mut self, _ctx: &TryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_catch_block(&mut self, _ctx: &CatchBlockContext) -> Result<(), E> { Ok(()) } - fn exit_catch_block(&mut self, _ctx: &CatchBlockContext) -> Result<(), E> { Ok(()) } - fn enter_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn exit_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn enter_jump_expression(&mut self, _ctx: &JumpExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_jump_expression(&mut self, _ctx: &JumpExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_callable_reference(&mut self, _ctx: &CallableReferenceContext) -> Result<(), E> { Ok(()) } - fn exit_callable_reference(&mut self, _ctx: &CallableReferenceContext) -> Result<(), E> { Ok(()) } - fn enter_assignment_and_operator(&mut self, _ctx: &AssignmentAndOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_assignment_and_operator(&mut self, _ctx: &AssignmentAndOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_equality_operator(&mut self, _ctx: &EqualityOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_equality_operator(&mut self, _ctx: &EqualityOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_comparison_operator(&mut self, _ctx: &ComparisonOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_comparison_operator(&mut self, _ctx: &ComparisonOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_in_operator(&mut self, _ctx: &InOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_in_operator(&mut self, _ctx: &InOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_is_operator(&mut self, _ctx: &IsOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_is_operator(&mut self, _ctx: &IsOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_additive_operator(&mut self, _ctx: &AdditiveOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_additive_operator(&mut self, _ctx: &AdditiveOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_multiplicative_operator(&mut self, _ctx: &MultiplicativeOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_multiplicative_operator(&mut self, _ctx: &MultiplicativeOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_as_operator(&mut self, _ctx: &AsOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_as_operator(&mut self, _ctx: &AsOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_prefix_unary_operator(&mut self, _ctx: &PrefixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_prefix_unary_operator(&mut self, _ctx: &PrefixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_postfix_unary_operator(&mut self, _ctx: &PostfixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_postfix_unary_operator(&mut self, _ctx: &PostfixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_excl(&mut self, _ctx: &ExclContext) -> Result<(), E> { Ok(()) } - fn exit_excl(&mut self, _ctx: &ExclContext) -> Result<(), E> { Ok(()) } - fn enter_member_access_operator(&mut self, _ctx: &MemberAccessOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_member_access_operator(&mut self, _ctx: &MemberAccessOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_safe_nav(&mut self, _ctx: &SafeNavContext) -> Result<(), E> { Ok(()) } - fn exit_safe_nav(&mut self, _ctx: &SafeNavContext) -> Result<(), E> { Ok(()) } - fn enter_modifiers(&mut self, _ctx: &ModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_modifiers(&mut self, _ctx: &ModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_modifiers(&mut self, _ctx: &ParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_modifiers(&mut self, _ctx: &ParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn exit_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn enter_type_modifiers(&mut self, _ctx: &TypeModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_type_modifiers(&mut self, _ctx: &TypeModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_type_modifier(&mut self, _ctx: &TypeModifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_modifier(&mut self, _ctx: &TypeModifierContext) -> Result<(), E> { Ok(()) } - fn enter_class_modifier(&mut self, _ctx: &ClassModifierContext) -> Result<(), E> { Ok(()) } - fn exit_class_modifier(&mut self, _ctx: &ClassModifierContext) -> Result<(), E> { Ok(()) } - fn enter_member_modifier(&mut self, _ctx: &MemberModifierContext) -> Result<(), E> { Ok(()) } - fn exit_member_modifier(&mut self, _ctx: &MemberModifierContext) -> Result<(), E> { Ok(()) } - fn enter_visibility_modifier(&mut self, _ctx: &VisibilityModifierContext) -> Result<(), E> { Ok(()) } - fn exit_visibility_modifier(&mut self, _ctx: &VisibilityModifierContext) -> Result<(), E> { Ok(()) } - fn enter_variance_modifier(&mut self, _ctx: &VarianceModifierContext) -> Result<(), E> { Ok(()) } - fn exit_variance_modifier(&mut self, _ctx: &VarianceModifierContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_modifiers(&mut self, _ctx: &TypeParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_modifiers(&mut self, _ctx: &TypeParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_modifier(&mut self, _ctx: &TypeParameterModifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_modifier(&mut self, _ctx: &TypeParameterModifierContext) -> Result<(), E> { Ok(()) } - fn enter_function_modifier(&mut self, _ctx: &FunctionModifierContext) -> Result<(), E> { Ok(()) } - fn exit_function_modifier(&mut self, _ctx: &FunctionModifierContext) -> Result<(), E> { Ok(()) } - fn enter_property_modifier(&mut self, _ctx: &PropertyModifierContext) -> Result<(), E> { Ok(()) } - fn exit_property_modifier(&mut self, _ctx: &PropertyModifierContext) -> Result<(), E> { Ok(()) } - fn enter_inheritance_modifier(&mut self, _ctx: &InheritanceModifierContext) -> Result<(), E> { Ok(()) } - fn exit_inheritance_modifier(&mut self, _ctx: &InheritanceModifierContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_modifier(&mut self, _ctx: &ParameterModifierContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_modifier(&mut self, _ctx: &ParameterModifierContext) -> Result<(), E> { Ok(()) } - fn enter_reification_modifier(&mut self, _ctx: &ReificationModifierContext) -> Result<(), E> { Ok(()) } - fn exit_reification_modifier(&mut self, _ctx: &ReificationModifierContext) -> Result<(), E> { Ok(()) } - fn enter_platform_modifier(&mut self, _ctx: &PlatformModifierContext) -> Result<(), E> { Ok(()) } - fn exit_platform_modifier(&mut self, _ctx: &PlatformModifierContext) -> Result<(), E> { Ok(()) } - fn enter_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_single_annotation(&mut self, _ctx: &SingleAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_single_annotation(&mut self, _ctx: &SingleAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_multi_annotation(&mut self, _ctx: &MultiAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_multi_annotation(&mut self, _ctx: &MultiAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_use_site_target(&mut self, _ctx: &AnnotationUseSiteTargetContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_use_site_target(&mut self, _ctx: &AnnotationUseSiteTargetContext) -> Result<(), E> { Ok(()) } - fn enter_unescaped_annotation(&mut self, _ctx: &UnescapedAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_unescaped_annotation(&mut self, _ctx: &UnescapedAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_simple_identifier(&mut self, _ctx: &SimpleIdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_simple_identifier(&mut self, _ctx: &SimpleIdentifierContext) -> Result<(), E> { Ok(()) } - fn enter_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), E> { Ok(()) } - fn visit_error_node(&mut self, _node: &ErrorNode) -> Result<(), E> { Ok(()) } - fn output(&mut self) -> std::io::Stdout { std::io::stdout() } -} - -antlr4_runtime::__antlr4_rust_generated_walk_callbacks! { - callbacks: __KotlinTreeWalkerCallbacks, - listener: KotlinListener, - enter: |listener, context, invocation_states| { - listener.enter_every_rule(context)?; - match __context_kind(context) { - 0 => listener.enter_kotlin_file(&KotlinFileContext::__from_listener_node(context, invocation_states))?, - 1 => listener.enter_script(&ScriptContext::__from_listener_node(context, invocation_states))?, - 2 => listener.enter_shebang_line(&ShebangLineContext::__from_listener_node(context, invocation_states))?, - 3 => listener.enter_file_annotation(&FileAnnotationContext::__from_listener_node(context, invocation_states))?, - 4 => listener.enter_package_header(&PackageHeaderContext::__from_listener_node(context, invocation_states))?, - 5 => listener.enter_import_list(&ImportListContext::__from_listener_node(context, invocation_states))?, - 6 => listener.enter_import_header(&ImportHeaderContext::__from_listener_node(context, invocation_states))?, - 7 => listener.enter_import_alias(&ImportAliasContext::__from_listener_node(context, invocation_states))?, - 8 => listener.enter_top_level_object(&TopLevelObjectContext::__from_listener_node(context, invocation_states))?, - 9 => listener.enter_type_alias(&TypeAliasContext::__from_listener_node(context, invocation_states))?, - 10 => listener.enter_declaration(&DeclarationContext::__from_listener_node(context, invocation_states))?, - 11 => listener.enter_class_declaration(&ClassDeclarationContext::__from_listener_node(context, invocation_states))?, - 12 => listener.enter_primary_constructor(&PrimaryConstructorContext::__from_listener_node(context, invocation_states))?, - 13 => listener.enter_class_body(&ClassBodyContext::__from_listener_node(context, invocation_states))?, - 14 => listener.enter_class_parameters(&ClassParametersContext::__from_listener_node(context, invocation_states))?, - 15 => listener.enter_class_parameter(&ClassParameterContext::__from_listener_node(context, invocation_states))?, - 16 => listener.enter_delegation_specifiers(&DelegationSpecifiersContext::__from_listener_node(context, invocation_states))?, - 17 => listener.enter_delegation_specifier(&DelegationSpecifierContext::__from_listener_node(context, invocation_states))?, - 18 => listener.enter_constructor_invocation(&ConstructorInvocationContext::__from_listener_node(context, invocation_states))?, - 19 => listener.enter_annotated_delegation_specifier(&AnnotatedDelegationSpecifierContext::__from_listener_node(context, invocation_states))?, - 20 => listener.enter_explicit_delegation(&ExplicitDelegationContext::__from_listener_node(context, invocation_states))?, - 21 => listener.enter_type_parameters(&TypeParametersContext::__from_listener_node(context, invocation_states))?, - 22 => listener.enter_type_parameter(&TypeParameterContext::__from_listener_node(context, invocation_states))?, - 23 => listener.enter_type_constraints(&TypeConstraintsContext::__from_listener_node(context, invocation_states))?, - 24 => listener.enter_type_constraint(&TypeConstraintContext::__from_listener_node(context, invocation_states))?, - 25 => listener.enter_class_member_declarations(&ClassMemberDeclarationsContext::__from_listener_node(context, invocation_states))?, - 26 => listener.enter_class_member_declaration(&ClassMemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 27 => listener.enter_anonymous_initializer(&AnonymousInitializerContext::__from_listener_node(context, invocation_states))?, - 28 => listener.enter_companion_object(&CompanionObjectContext::__from_listener_node(context, invocation_states))?, - 29 => listener.enter_function_value_parameters(&FunctionValueParametersContext::__from_listener_node(context, invocation_states))?, - 30 => listener.enter_function_value_parameter(&FunctionValueParameterContext::__from_listener_node(context, invocation_states))?, - 31 => listener.enter_function_declaration(&FunctionDeclarationContext::__from_listener_node(context, invocation_states))?, - 32 => listener.enter_function_body(&FunctionBodyContext::__from_listener_node(context, invocation_states))?, - 33 => listener.enter_variable_declaration(&VariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 34 => listener.enter_multi_variable_declaration(&MultiVariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 35 => listener.enter_property_declaration(&PropertyDeclarationContext::__from_listener_node(context, invocation_states))?, - 36 => listener.enter_property_delegate(&PropertyDelegateContext::__from_listener_node(context, invocation_states))?, - 37 => listener.enter_getter(&GetterContext::__from_listener_node(context, invocation_states))?, - 38 => listener.enter_setter(&SetterContext::__from_listener_node(context, invocation_states))?, - 39 => listener.enter_parameters_with_optional_type(&ParametersWithOptionalTypeContext::__from_listener_node(context, invocation_states))?, - 40 => listener.enter_function_value_parameter_with_optional_type(&FunctionValueParameterWithOptionalTypeContext::__from_listener_node(context, invocation_states))?, - 41 => listener.enter_parameter_with_optional_type(&ParameterWithOptionalTypeContext::__from_listener_node(context, invocation_states))?, - 42 => listener.enter_parameter(&ParameterContext::__from_listener_node(context, invocation_states))?, - 43 => listener.enter_object_declaration(&ObjectDeclarationContext::__from_listener_node(context, invocation_states))?, - 44 => listener.enter_secondary_constructor(&SecondaryConstructorContext::__from_listener_node(context, invocation_states))?, - 45 => listener.enter_constructor_delegation_call(&ConstructorDelegationCallContext::__from_listener_node(context, invocation_states))?, - 46 => listener.enter_enum_class_body(&EnumClassBodyContext::__from_listener_node(context, invocation_states))?, - 47 => listener.enter_enum_entries(&EnumEntriesContext::__from_listener_node(context, invocation_states))?, - 48 => listener.enter_enum_entry(&EnumEntryContext::__from_listener_node(context, invocation_states))?, - 49 => listener.enter_type(&TypeContext::__from_listener_node(context, invocation_states))?, - 50 => listener.enter_type_reference(&TypeReferenceContext::__from_listener_node(context, invocation_states))?, - 51 => listener.enter_nullable_type(&NullableTypeContext::__from_listener_node(context, invocation_states))?, - 52 => listener.enter_quest(&QuestContext::__from_listener_node(context, invocation_states))?, - 53 => listener.enter_user_type(&UserTypeContext::__from_listener_node(context, invocation_states))?, - 54 => listener.enter_simple_user_type(&SimpleUserTypeContext::__from_listener_node(context, invocation_states))?, - 55 => listener.enter_type_projection(&TypeProjectionContext::__from_listener_node(context, invocation_states))?, - 56 => listener.enter_type_projection_modifiers(&TypeProjectionModifiersContext::__from_listener_node(context, invocation_states))?, - 57 => listener.enter_type_projection_modifier(&TypeProjectionModifierContext::__from_listener_node(context, invocation_states))?, - 58 => listener.enter_function_type(&FunctionTypeContext::__from_listener_node(context, invocation_states))?, - 59 => listener.enter_function_type_parameters(&FunctionTypeParametersContext::__from_listener_node(context, invocation_states))?, - 60 => listener.enter_parenthesized_type(&ParenthesizedTypeContext::__from_listener_node(context, invocation_states))?, - 61 => listener.enter_receiver_type(&ReceiverTypeContext::__from_listener_node(context, invocation_states))?, - 62 => listener.enter_parenthesized_user_type(&ParenthesizedUserTypeContext::__from_listener_node(context, invocation_states))?, - 63 => listener.enter_definitely_non_nullable_type(&DefinitelyNonNullableTypeContext::__from_listener_node(context, invocation_states))?, - 64 => listener.enter_statements(&StatementsContext::__from_listener_node(context, invocation_states))?, - 65 => listener.enter_statement(&StatementContext::__from_listener_node(context, invocation_states))?, - 66 => listener.enter_label(&LabelContext::__from_listener_node(context, invocation_states))?, - 67 => listener.enter_control_structure_body(&ControlStructureBodyContext::__from_listener_node(context, invocation_states))?, - 68 => listener.enter_block(&BlockContext::__from_listener_node(context, invocation_states))?, - 69 => listener.enter_loop_statement(&LoopStatementContext::__from_listener_node(context, invocation_states))?, - 70 => listener.enter_for_statement(&ForStatementContext::__from_listener_node(context, invocation_states))?, - 71 => listener.enter_while_statement(&WhileStatementContext::__from_listener_node(context, invocation_states))?, - 72 => listener.enter_do_while_statement(&DoWhileStatementContext::__from_listener_node(context, invocation_states))?, - 73 => listener.enter_assignment(&AssignmentContext::__from_listener_node(context, invocation_states))?, - 74 => listener.enter_semi(&SemiContext::__from_listener_node(context, invocation_states))?, - 75 => listener.enter_semis(&SemisContext::__from_listener_node(context, invocation_states))?, - 76 => listener.enter_expression(&ExpressionContext::__from_listener_node(context, invocation_states))?, - 77 => listener.enter_disjunction(&DisjunctionContext::__from_listener_node(context, invocation_states))?, - 78 => listener.enter_conjunction(&ConjunctionContext::__from_listener_node(context, invocation_states))?, - 79 => listener.enter_equality(&EqualityContext::__from_listener_node(context, invocation_states))?, - 80 => listener.enter_comparison(&ComparisonContext::__from_listener_node(context, invocation_states))?, - 81 => listener.enter_generic_call_like_comparison(&GenericCallLikeComparisonContext::__from_listener_node(context, invocation_states))?, - 82 => listener.enter_infix_operation(&InfixOperationContext::__from_listener_node(context, invocation_states))?, - 83 => listener.enter_elvis_expression(&ElvisExpressionContext::__from_listener_node(context, invocation_states))?, - 84 => listener.enter_elvis(&ElvisContext::__from_listener_node(context, invocation_states))?, - 85 => listener.enter_infix_function_call(&InfixFunctionCallContext::__from_listener_node(context, invocation_states))?, - 86 => listener.enter_range_expression(&RangeExpressionContext::__from_listener_node(context, invocation_states))?, - 87 => listener.enter_additive_expression(&AdditiveExpressionContext::__from_listener_node(context, invocation_states))?, - 88 => listener.enter_multiplicative_expression(&MultiplicativeExpressionContext::__from_listener_node(context, invocation_states))?, - 89 => listener.enter_as_expression(&AsExpressionContext::__from_listener_node(context, invocation_states))?, - 90 => listener.enter_prefix_unary_expression(&PrefixUnaryExpressionContext::__from_listener_node(context, invocation_states))?, - 91 => listener.enter_unary_prefix(&UnaryPrefixContext::__from_listener_node(context, invocation_states))?, - 92 => listener.enter_postfix_unary_expression(&PostfixUnaryExpressionContext::__from_listener_node(context, invocation_states))?, - 93 => listener.enter_postfix_unary_suffix(&PostfixUnarySuffixContext::__from_listener_node(context, invocation_states))?, - 94 => listener.enter_directly_assignable_expression(&DirectlyAssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 95 => listener.enter_parenthesized_directly_assignable_expression(&ParenthesizedDirectlyAssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 96 => listener.enter_assignable_expression(&AssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 97 => listener.enter_parenthesized_assignable_expression(&ParenthesizedAssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 98 => listener.enter_assignable_suffix(&AssignableSuffixContext::__from_listener_node(context, invocation_states))?, - 99 => listener.enter_indexing_suffix(&IndexingSuffixContext::__from_listener_node(context, invocation_states))?, - 100 => listener.enter_navigation_suffix(&NavigationSuffixContext::__from_listener_node(context, invocation_states))?, - 101 => listener.enter_call_suffix(&CallSuffixContext::__from_listener_node(context, invocation_states))?, - 102 => listener.enter_annotated_lambda(&AnnotatedLambdaContext::__from_listener_node(context, invocation_states))?, - 103 => listener.enter_type_arguments(&TypeArgumentsContext::__from_listener_node(context, invocation_states))?, - 104 => listener.enter_value_arguments(&ValueArgumentsContext::__from_listener_node(context, invocation_states))?, - 105 => listener.enter_value_argument(&ValueArgumentContext::__from_listener_node(context, invocation_states))?, - 106 => listener.enter_primary_expression(&PrimaryExpressionContext::__from_listener_node(context, invocation_states))?, - 107 => listener.enter_parenthesized_expression(&ParenthesizedExpressionContext::__from_listener_node(context, invocation_states))?, - 108 => listener.enter_collection_literal(&CollectionLiteralContext::__from_listener_node(context, invocation_states))?, - 109 => listener.enter_literal_constant(&LiteralConstantContext::__from_listener_node(context, invocation_states))?, - 110 => listener.enter_string_literal(&StringLiteralContext::__from_listener_node(context, invocation_states))?, - 111 => listener.enter_line_string_literal(&LineStringLiteralContext::__from_listener_node(context, invocation_states))?, - 112 => listener.enter_multi_line_string_literal(&MultiLineStringLiteralContext::__from_listener_node(context, invocation_states))?, - 113 => listener.enter_line_string_content(&LineStringContentContext::__from_listener_node(context, invocation_states))?, - 114 => listener.enter_line_string_expression(&LineStringExpressionContext::__from_listener_node(context, invocation_states))?, - 115 => listener.enter_multi_line_string_content(&MultiLineStringContentContext::__from_listener_node(context, invocation_states))?, - 116 => listener.enter_multi_line_string_expression(&MultiLineStringExpressionContext::__from_listener_node(context, invocation_states))?, - 117 => listener.enter_lambda_literal(&LambdaLiteralContext::__from_listener_node(context, invocation_states))?, - 118 => listener.enter_lambda_parameters(&LambdaParametersContext::__from_listener_node(context, invocation_states))?, - 119 => listener.enter_lambda_parameter(&LambdaParameterContext::__from_listener_node(context, invocation_states))?, - 120 => listener.enter_anonymous_function(&AnonymousFunctionContext::__from_listener_node(context, invocation_states))?, - 121 => listener.enter_function_literal(&FunctionLiteralContext::__from_listener_node(context, invocation_states))?, - 122 => listener.enter_object_literal(&ObjectLiteralContext::__from_listener_node(context, invocation_states))?, - 123 => listener.enter_this_expression(&ThisExpressionContext::__from_listener_node(context, invocation_states))?, - 124 => listener.enter_super_expression(&SuperExpressionContext::__from_listener_node(context, invocation_states))?, - 125 => listener.enter_if_expression(&IfExpressionContext::__from_listener_node(context, invocation_states))?, - 126 => listener.enter_when_subject(&WhenSubjectContext::__from_listener_node(context, invocation_states))?, - 127 => listener.enter_when_expression(&WhenExpressionContext::__from_listener_node(context, invocation_states))?, - 128 => listener.enter_when_entry(&WhenEntryContext::__from_listener_node(context, invocation_states))?, - 129 => listener.enter_when_condition(&WhenConditionContext::__from_listener_node(context, invocation_states))?, - 130 => listener.enter_range_test(&RangeTestContext::__from_listener_node(context, invocation_states))?, - 131 => listener.enter_type_test(&TypeTestContext::__from_listener_node(context, invocation_states))?, - 132 => listener.enter_try_expression(&TryExpressionContext::__from_listener_node(context, invocation_states))?, - 133 => listener.enter_catch_block(&CatchBlockContext::__from_listener_node(context, invocation_states))?, - 134 => listener.enter_finally_block(&FinallyBlockContext::__from_listener_node(context, invocation_states))?, - 135 => listener.enter_jump_expression(&JumpExpressionContext::__from_listener_node(context, invocation_states))?, - 136 => listener.enter_callable_reference(&CallableReferenceContext::__from_listener_node(context, invocation_states))?, - 137 => listener.enter_assignment_and_operator(&AssignmentAndOperatorContext::__from_listener_node(context, invocation_states))?, - 138 => listener.enter_equality_operator(&EqualityOperatorContext::__from_listener_node(context, invocation_states))?, - 139 => listener.enter_comparison_operator(&ComparisonOperatorContext::__from_listener_node(context, invocation_states))?, - 140 => listener.enter_in_operator(&InOperatorContext::__from_listener_node(context, invocation_states))?, - 141 => listener.enter_is_operator(&IsOperatorContext::__from_listener_node(context, invocation_states))?, - 142 => listener.enter_additive_operator(&AdditiveOperatorContext::__from_listener_node(context, invocation_states))?, - 143 => listener.enter_multiplicative_operator(&MultiplicativeOperatorContext::__from_listener_node(context, invocation_states))?, - 144 => listener.enter_as_operator(&AsOperatorContext::__from_listener_node(context, invocation_states))?, - 145 => listener.enter_prefix_unary_operator(&PrefixUnaryOperatorContext::__from_listener_node(context, invocation_states))?, - 146 => listener.enter_postfix_unary_operator(&PostfixUnaryOperatorContext::__from_listener_node(context, invocation_states))?, - 147 => listener.enter_excl(&ExclContext::__from_listener_node(context, invocation_states))?, - 148 => listener.enter_member_access_operator(&MemberAccessOperatorContext::__from_listener_node(context, invocation_states))?, - 149 => listener.enter_safe_nav(&SafeNavContext::__from_listener_node(context, invocation_states))?, - 150 => listener.enter_modifiers(&ModifiersContext::__from_listener_node(context, invocation_states))?, - 151 => listener.enter_parameter_modifiers(&ParameterModifiersContext::__from_listener_node(context, invocation_states))?, - 152 => listener.enter_modifier(&ModifierContext::__from_listener_node(context, invocation_states))?, - 153 => listener.enter_type_modifiers(&TypeModifiersContext::__from_listener_node(context, invocation_states))?, - 154 => listener.enter_type_modifier(&TypeModifierContext::__from_listener_node(context, invocation_states))?, - 155 => listener.enter_class_modifier(&ClassModifierContext::__from_listener_node(context, invocation_states))?, - 156 => listener.enter_member_modifier(&MemberModifierContext::__from_listener_node(context, invocation_states))?, - 157 => listener.enter_visibility_modifier(&VisibilityModifierContext::__from_listener_node(context, invocation_states))?, - 158 => listener.enter_variance_modifier(&VarianceModifierContext::__from_listener_node(context, invocation_states))?, - 159 => listener.enter_type_parameter_modifiers(&TypeParameterModifiersContext::__from_listener_node(context, invocation_states))?, - 160 => listener.enter_type_parameter_modifier(&TypeParameterModifierContext::__from_listener_node(context, invocation_states))?, - 161 => listener.enter_function_modifier(&FunctionModifierContext::__from_listener_node(context, invocation_states))?, - 162 => listener.enter_property_modifier(&PropertyModifierContext::__from_listener_node(context, invocation_states))?, - 163 => listener.enter_inheritance_modifier(&InheritanceModifierContext::__from_listener_node(context, invocation_states))?, - 164 => listener.enter_parameter_modifier(&ParameterModifierContext::__from_listener_node(context, invocation_states))?, - 165 => listener.enter_reification_modifier(&ReificationModifierContext::__from_listener_node(context, invocation_states))?, - 166 => listener.enter_platform_modifier(&PlatformModifierContext::__from_listener_node(context, invocation_states))?, - 167 => listener.enter_annotation(&AnnotationContext::__from_listener_node(context, invocation_states))?, - 168 => listener.enter_single_annotation(&SingleAnnotationContext::__from_listener_node(context, invocation_states))?, - 169 => listener.enter_multi_annotation(&MultiAnnotationContext::__from_listener_node(context, invocation_states))?, - 170 => listener.enter_annotation_use_site_target(&AnnotationUseSiteTargetContext::__from_listener_node(context, invocation_states))?, - 171 => listener.enter_unescaped_annotation(&UnescapedAnnotationContext::__from_listener_node(context, invocation_states))?, - 172 => listener.enter_simple_identifier(&SimpleIdentifierContext::__from_listener_node(context, invocation_states))?, - 173 => listener.enter_identifier(&IdentifierContext::__from_listener_node(context, invocation_states))?, - _ => {} - } - Ok(()) - }, - exit: |listener, context, invocation_states| { - match __context_kind(context) { - 0 => listener.exit_kotlin_file(&KotlinFileContext::__from_listener_node(context, invocation_states))?, - 1 => listener.exit_script(&ScriptContext::__from_listener_node(context, invocation_states))?, - 2 => listener.exit_shebang_line(&ShebangLineContext::__from_listener_node(context, invocation_states))?, - 3 => listener.exit_file_annotation(&FileAnnotationContext::__from_listener_node(context, invocation_states))?, - 4 => listener.exit_package_header(&PackageHeaderContext::__from_listener_node(context, invocation_states))?, - 5 => listener.exit_import_list(&ImportListContext::__from_listener_node(context, invocation_states))?, - 6 => listener.exit_import_header(&ImportHeaderContext::__from_listener_node(context, invocation_states))?, - 7 => listener.exit_import_alias(&ImportAliasContext::__from_listener_node(context, invocation_states))?, - 8 => listener.exit_top_level_object(&TopLevelObjectContext::__from_listener_node(context, invocation_states))?, - 9 => listener.exit_type_alias(&TypeAliasContext::__from_listener_node(context, invocation_states))?, - 10 => listener.exit_declaration(&DeclarationContext::__from_listener_node(context, invocation_states))?, - 11 => listener.exit_class_declaration(&ClassDeclarationContext::__from_listener_node(context, invocation_states))?, - 12 => listener.exit_primary_constructor(&PrimaryConstructorContext::__from_listener_node(context, invocation_states))?, - 13 => listener.exit_class_body(&ClassBodyContext::__from_listener_node(context, invocation_states))?, - 14 => listener.exit_class_parameters(&ClassParametersContext::__from_listener_node(context, invocation_states))?, - 15 => listener.exit_class_parameter(&ClassParameterContext::__from_listener_node(context, invocation_states))?, - 16 => listener.exit_delegation_specifiers(&DelegationSpecifiersContext::__from_listener_node(context, invocation_states))?, - 17 => listener.exit_delegation_specifier(&DelegationSpecifierContext::__from_listener_node(context, invocation_states))?, - 18 => listener.exit_constructor_invocation(&ConstructorInvocationContext::__from_listener_node(context, invocation_states))?, - 19 => listener.exit_annotated_delegation_specifier(&AnnotatedDelegationSpecifierContext::__from_listener_node(context, invocation_states))?, - 20 => listener.exit_explicit_delegation(&ExplicitDelegationContext::__from_listener_node(context, invocation_states))?, - 21 => listener.exit_type_parameters(&TypeParametersContext::__from_listener_node(context, invocation_states))?, - 22 => listener.exit_type_parameter(&TypeParameterContext::__from_listener_node(context, invocation_states))?, - 23 => listener.exit_type_constraints(&TypeConstraintsContext::__from_listener_node(context, invocation_states))?, - 24 => listener.exit_type_constraint(&TypeConstraintContext::__from_listener_node(context, invocation_states))?, - 25 => listener.exit_class_member_declarations(&ClassMemberDeclarationsContext::__from_listener_node(context, invocation_states))?, - 26 => listener.exit_class_member_declaration(&ClassMemberDeclarationContext::__from_listener_node(context, invocation_states))?, - 27 => listener.exit_anonymous_initializer(&AnonymousInitializerContext::__from_listener_node(context, invocation_states))?, - 28 => listener.exit_companion_object(&CompanionObjectContext::__from_listener_node(context, invocation_states))?, - 29 => listener.exit_function_value_parameters(&FunctionValueParametersContext::__from_listener_node(context, invocation_states))?, - 30 => listener.exit_function_value_parameter(&FunctionValueParameterContext::__from_listener_node(context, invocation_states))?, - 31 => listener.exit_function_declaration(&FunctionDeclarationContext::__from_listener_node(context, invocation_states))?, - 32 => listener.exit_function_body(&FunctionBodyContext::__from_listener_node(context, invocation_states))?, - 33 => listener.exit_variable_declaration(&VariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 34 => listener.exit_multi_variable_declaration(&MultiVariableDeclarationContext::__from_listener_node(context, invocation_states))?, - 35 => listener.exit_property_declaration(&PropertyDeclarationContext::__from_listener_node(context, invocation_states))?, - 36 => listener.exit_property_delegate(&PropertyDelegateContext::__from_listener_node(context, invocation_states))?, - 37 => listener.exit_getter(&GetterContext::__from_listener_node(context, invocation_states))?, - 38 => listener.exit_setter(&SetterContext::__from_listener_node(context, invocation_states))?, - 39 => listener.exit_parameters_with_optional_type(&ParametersWithOptionalTypeContext::__from_listener_node(context, invocation_states))?, - 40 => listener.exit_function_value_parameter_with_optional_type(&FunctionValueParameterWithOptionalTypeContext::__from_listener_node(context, invocation_states))?, - 41 => listener.exit_parameter_with_optional_type(&ParameterWithOptionalTypeContext::__from_listener_node(context, invocation_states))?, - 42 => listener.exit_parameter(&ParameterContext::__from_listener_node(context, invocation_states))?, - 43 => listener.exit_object_declaration(&ObjectDeclarationContext::__from_listener_node(context, invocation_states))?, - 44 => listener.exit_secondary_constructor(&SecondaryConstructorContext::__from_listener_node(context, invocation_states))?, - 45 => listener.exit_constructor_delegation_call(&ConstructorDelegationCallContext::__from_listener_node(context, invocation_states))?, - 46 => listener.exit_enum_class_body(&EnumClassBodyContext::__from_listener_node(context, invocation_states))?, - 47 => listener.exit_enum_entries(&EnumEntriesContext::__from_listener_node(context, invocation_states))?, - 48 => listener.exit_enum_entry(&EnumEntryContext::__from_listener_node(context, invocation_states))?, - 49 => listener.exit_type(&TypeContext::__from_listener_node(context, invocation_states))?, - 50 => listener.exit_type_reference(&TypeReferenceContext::__from_listener_node(context, invocation_states))?, - 51 => listener.exit_nullable_type(&NullableTypeContext::__from_listener_node(context, invocation_states))?, - 52 => listener.exit_quest(&QuestContext::__from_listener_node(context, invocation_states))?, - 53 => listener.exit_user_type(&UserTypeContext::__from_listener_node(context, invocation_states))?, - 54 => listener.exit_simple_user_type(&SimpleUserTypeContext::__from_listener_node(context, invocation_states))?, - 55 => listener.exit_type_projection(&TypeProjectionContext::__from_listener_node(context, invocation_states))?, - 56 => listener.exit_type_projection_modifiers(&TypeProjectionModifiersContext::__from_listener_node(context, invocation_states))?, - 57 => listener.exit_type_projection_modifier(&TypeProjectionModifierContext::__from_listener_node(context, invocation_states))?, - 58 => listener.exit_function_type(&FunctionTypeContext::__from_listener_node(context, invocation_states))?, - 59 => listener.exit_function_type_parameters(&FunctionTypeParametersContext::__from_listener_node(context, invocation_states))?, - 60 => listener.exit_parenthesized_type(&ParenthesizedTypeContext::__from_listener_node(context, invocation_states))?, - 61 => listener.exit_receiver_type(&ReceiverTypeContext::__from_listener_node(context, invocation_states))?, - 62 => listener.exit_parenthesized_user_type(&ParenthesizedUserTypeContext::__from_listener_node(context, invocation_states))?, - 63 => listener.exit_definitely_non_nullable_type(&DefinitelyNonNullableTypeContext::__from_listener_node(context, invocation_states))?, - 64 => listener.exit_statements(&StatementsContext::__from_listener_node(context, invocation_states))?, - 65 => listener.exit_statement(&StatementContext::__from_listener_node(context, invocation_states))?, - 66 => listener.exit_label(&LabelContext::__from_listener_node(context, invocation_states))?, - 67 => listener.exit_control_structure_body(&ControlStructureBodyContext::__from_listener_node(context, invocation_states))?, - 68 => listener.exit_block(&BlockContext::__from_listener_node(context, invocation_states))?, - 69 => listener.exit_loop_statement(&LoopStatementContext::__from_listener_node(context, invocation_states))?, - 70 => listener.exit_for_statement(&ForStatementContext::__from_listener_node(context, invocation_states))?, - 71 => listener.exit_while_statement(&WhileStatementContext::__from_listener_node(context, invocation_states))?, - 72 => listener.exit_do_while_statement(&DoWhileStatementContext::__from_listener_node(context, invocation_states))?, - 73 => listener.exit_assignment(&AssignmentContext::__from_listener_node(context, invocation_states))?, - 74 => listener.exit_semi(&SemiContext::__from_listener_node(context, invocation_states))?, - 75 => listener.exit_semis(&SemisContext::__from_listener_node(context, invocation_states))?, - 76 => listener.exit_expression(&ExpressionContext::__from_listener_node(context, invocation_states))?, - 77 => listener.exit_disjunction(&DisjunctionContext::__from_listener_node(context, invocation_states))?, - 78 => listener.exit_conjunction(&ConjunctionContext::__from_listener_node(context, invocation_states))?, - 79 => listener.exit_equality(&EqualityContext::__from_listener_node(context, invocation_states))?, - 80 => listener.exit_comparison(&ComparisonContext::__from_listener_node(context, invocation_states))?, - 81 => listener.exit_generic_call_like_comparison(&GenericCallLikeComparisonContext::__from_listener_node(context, invocation_states))?, - 82 => listener.exit_infix_operation(&InfixOperationContext::__from_listener_node(context, invocation_states))?, - 83 => listener.exit_elvis_expression(&ElvisExpressionContext::__from_listener_node(context, invocation_states))?, - 84 => listener.exit_elvis(&ElvisContext::__from_listener_node(context, invocation_states))?, - 85 => listener.exit_infix_function_call(&InfixFunctionCallContext::__from_listener_node(context, invocation_states))?, - 86 => listener.exit_range_expression(&RangeExpressionContext::__from_listener_node(context, invocation_states))?, - 87 => listener.exit_additive_expression(&AdditiveExpressionContext::__from_listener_node(context, invocation_states))?, - 88 => listener.exit_multiplicative_expression(&MultiplicativeExpressionContext::__from_listener_node(context, invocation_states))?, - 89 => listener.exit_as_expression(&AsExpressionContext::__from_listener_node(context, invocation_states))?, - 90 => listener.exit_prefix_unary_expression(&PrefixUnaryExpressionContext::__from_listener_node(context, invocation_states))?, - 91 => listener.exit_unary_prefix(&UnaryPrefixContext::__from_listener_node(context, invocation_states))?, - 92 => listener.exit_postfix_unary_expression(&PostfixUnaryExpressionContext::__from_listener_node(context, invocation_states))?, - 93 => listener.exit_postfix_unary_suffix(&PostfixUnarySuffixContext::__from_listener_node(context, invocation_states))?, - 94 => listener.exit_directly_assignable_expression(&DirectlyAssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 95 => listener.exit_parenthesized_directly_assignable_expression(&ParenthesizedDirectlyAssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 96 => listener.exit_assignable_expression(&AssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 97 => listener.exit_parenthesized_assignable_expression(&ParenthesizedAssignableExpressionContext::__from_listener_node(context, invocation_states))?, - 98 => listener.exit_assignable_suffix(&AssignableSuffixContext::__from_listener_node(context, invocation_states))?, - 99 => listener.exit_indexing_suffix(&IndexingSuffixContext::__from_listener_node(context, invocation_states))?, - 100 => listener.exit_navigation_suffix(&NavigationSuffixContext::__from_listener_node(context, invocation_states))?, - 101 => listener.exit_call_suffix(&CallSuffixContext::__from_listener_node(context, invocation_states))?, - 102 => listener.exit_annotated_lambda(&AnnotatedLambdaContext::__from_listener_node(context, invocation_states))?, - 103 => listener.exit_type_arguments(&TypeArgumentsContext::__from_listener_node(context, invocation_states))?, - 104 => listener.exit_value_arguments(&ValueArgumentsContext::__from_listener_node(context, invocation_states))?, - 105 => listener.exit_value_argument(&ValueArgumentContext::__from_listener_node(context, invocation_states))?, - 106 => listener.exit_primary_expression(&PrimaryExpressionContext::__from_listener_node(context, invocation_states))?, - 107 => listener.exit_parenthesized_expression(&ParenthesizedExpressionContext::__from_listener_node(context, invocation_states))?, - 108 => listener.exit_collection_literal(&CollectionLiteralContext::__from_listener_node(context, invocation_states))?, - 109 => listener.exit_literal_constant(&LiteralConstantContext::__from_listener_node(context, invocation_states))?, - 110 => listener.exit_string_literal(&StringLiteralContext::__from_listener_node(context, invocation_states))?, - 111 => listener.exit_line_string_literal(&LineStringLiteralContext::__from_listener_node(context, invocation_states))?, - 112 => listener.exit_multi_line_string_literal(&MultiLineStringLiteralContext::__from_listener_node(context, invocation_states))?, - 113 => listener.exit_line_string_content(&LineStringContentContext::__from_listener_node(context, invocation_states))?, - 114 => listener.exit_line_string_expression(&LineStringExpressionContext::__from_listener_node(context, invocation_states))?, - 115 => listener.exit_multi_line_string_content(&MultiLineStringContentContext::__from_listener_node(context, invocation_states))?, - 116 => listener.exit_multi_line_string_expression(&MultiLineStringExpressionContext::__from_listener_node(context, invocation_states))?, - 117 => listener.exit_lambda_literal(&LambdaLiteralContext::__from_listener_node(context, invocation_states))?, - 118 => listener.exit_lambda_parameters(&LambdaParametersContext::__from_listener_node(context, invocation_states))?, - 119 => listener.exit_lambda_parameter(&LambdaParameterContext::__from_listener_node(context, invocation_states))?, - 120 => listener.exit_anonymous_function(&AnonymousFunctionContext::__from_listener_node(context, invocation_states))?, - 121 => listener.exit_function_literal(&FunctionLiteralContext::__from_listener_node(context, invocation_states))?, - 122 => listener.exit_object_literal(&ObjectLiteralContext::__from_listener_node(context, invocation_states))?, - 123 => listener.exit_this_expression(&ThisExpressionContext::__from_listener_node(context, invocation_states))?, - 124 => listener.exit_super_expression(&SuperExpressionContext::__from_listener_node(context, invocation_states))?, - 125 => listener.exit_if_expression(&IfExpressionContext::__from_listener_node(context, invocation_states))?, - 126 => listener.exit_when_subject(&WhenSubjectContext::__from_listener_node(context, invocation_states))?, - 127 => listener.exit_when_expression(&WhenExpressionContext::__from_listener_node(context, invocation_states))?, - 128 => listener.exit_when_entry(&WhenEntryContext::__from_listener_node(context, invocation_states))?, - 129 => listener.exit_when_condition(&WhenConditionContext::__from_listener_node(context, invocation_states))?, - 130 => listener.exit_range_test(&RangeTestContext::__from_listener_node(context, invocation_states))?, - 131 => listener.exit_type_test(&TypeTestContext::__from_listener_node(context, invocation_states))?, - 132 => listener.exit_try_expression(&TryExpressionContext::__from_listener_node(context, invocation_states))?, - 133 => listener.exit_catch_block(&CatchBlockContext::__from_listener_node(context, invocation_states))?, - 134 => listener.exit_finally_block(&FinallyBlockContext::__from_listener_node(context, invocation_states))?, - 135 => listener.exit_jump_expression(&JumpExpressionContext::__from_listener_node(context, invocation_states))?, - 136 => listener.exit_callable_reference(&CallableReferenceContext::__from_listener_node(context, invocation_states))?, - 137 => listener.exit_assignment_and_operator(&AssignmentAndOperatorContext::__from_listener_node(context, invocation_states))?, - 138 => listener.exit_equality_operator(&EqualityOperatorContext::__from_listener_node(context, invocation_states))?, - 139 => listener.exit_comparison_operator(&ComparisonOperatorContext::__from_listener_node(context, invocation_states))?, - 140 => listener.exit_in_operator(&InOperatorContext::__from_listener_node(context, invocation_states))?, - 141 => listener.exit_is_operator(&IsOperatorContext::__from_listener_node(context, invocation_states))?, - 142 => listener.exit_additive_operator(&AdditiveOperatorContext::__from_listener_node(context, invocation_states))?, - 143 => listener.exit_multiplicative_operator(&MultiplicativeOperatorContext::__from_listener_node(context, invocation_states))?, - 144 => listener.exit_as_operator(&AsOperatorContext::__from_listener_node(context, invocation_states))?, - 145 => listener.exit_prefix_unary_operator(&PrefixUnaryOperatorContext::__from_listener_node(context, invocation_states))?, - 146 => listener.exit_postfix_unary_operator(&PostfixUnaryOperatorContext::__from_listener_node(context, invocation_states))?, - 147 => listener.exit_excl(&ExclContext::__from_listener_node(context, invocation_states))?, - 148 => listener.exit_member_access_operator(&MemberAccessOperatorContext::__from_listener_node(context, invocation_states))?, - 149 => listener.exit_safe_nav(&SafeNavContext::__from_listener_node(context, invocation_states))?, - 150 => listener.exit_modifiers(&ModifiersContext::__from_listener_node(context, invocation_states))?, - 151 => listener.exit_parameter_modifiers(&ParameterModifiersContext::__from_listener_node(context, invocation_states))?, - 152 => listener.exit_modifier(&ModifierContext::__from_listener_node(context, invocation_states))?, - 153 => listener.exit_type_modifiers(&TypeModifiersContext::__from_listener_node(context, invocation_states))?, - 154 => listener.exit_type_modifier(&TypeModifierContext::__from_listener_node(context, invocation_states))?, - 155 => listener.exit_class_modifier(&ClassModifierContext::__from_listener_node(context, invocation_states))?, - 156 => listener.exit_member_modifier(&MemberModifierContext::__from_listener_node(context, invocation_states))?, - 157 => listener.exit_visibility_modifier(&VisibilityModifierContext::__from_listener_node(context, invocation_states))?, - 158 => listener.exit_variance_modifier(&VarianceModifierContext::__from_listener_node(context, invocation_states))?, - 159 => listener.exit_type_parameter_modifiers(&TypeParameterModifiersContext::__from_listener_node(context, invocation_states))?, - 160 => listener.exit_type_parameter_modifier(&TypeParameterModifierContext::__from_listener_node(context, invocation_states))?, - 161 => listener.exit_function_modifier(&FunctionModifierContext::__from_listener_node(context, invocation_states))?, - 162 => listener.exit_property_modifier(&PropertyModifierContext::__from_listener_node(context, invocation_states))?, - 163 => listener.exit_inheritance_modifier(&InheritanceModifierContext::__from_listener_node(context, invocation_states))?, - 164 => listener.exit_parameter_modifier(&ParameterModifierContext::__from_listener_node(context, invocation_states))?, - 165 => listener.exit_reification_modifier(&ReificationModifierContext::__from_listener_node(context, invocation_states))?, - 166 => listener.exit_platform_modifier(&PlatformModifierContext::__from_listener_node(context, invocation_states))?, - 167 => listener.exit_annotation(&AnnotationContext::__from_listener_node(context, invocation_states))?, - 168 => listener.exit_single_annotation(&SingleAnnotationContext::__from_listener_node(context, invocation_states))?, - 169 => listener.exit_multi_annotation(&MultiAnnotationContext::__from_listener_node(context, invocation_states))?, - 170 => listener.exit_annotation_use_site_target(&AnnotationUseSiteTargetContext::__from_listener_node(context, invocation_states))?, - 171 => listener.exit_unescaped_annotation(&UnescapedAnnotationContext::__from_listener_node(context, invocation_states))?, - 172 => listener.exit_simple_identifier(&SimpleIdentifierContext::__from_listener_node(context, invocation_states))?, - 173 => listener.exit_identifier(&IdentifierContext::__from_listener_node(context, invocation_states))?, - _ => {} - } - listener.exit_every_rule(context) - }, - terminal: |listener, node| { - listener.visit_terminal(&TerminalNode::new(node)) - }, - error: |listener, node| { - listener.visit_error_node(&ErrorNode::new(node)) - }, -} - -#[allow(dead_code)] -pub struct KotlinTreeWalker; - -#[allow(dead_code)] -impl KotlinTreeWalker { - pub fn walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - ) -> Result<(), E> { - Self::__walk(listener, tree, None) - } - - pub fn walk_with_invocation_states>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - parent_invocation_states: Vec, - ) -> Result<(), E> { - Self::__walk(listener, tree, Some(parent_invocation_states)) - } - - fn __walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - invocation_states: Option>, - ) -> Result<(), E> { - let mut callbacks = __KotlinTreeWalkerCallbacks(listener); - antlr4_runtime::generated::walk_generated(tree, invocation_states, &mut callbacks) - } -} - -pub type ParseTreeWalker = KotlinTreeWalker; - -#[allow(dead_code, unused_variables)] -pub trait KotlinValidatedListener { - fn walk(&mut self, tree: ValidatedRuleNode<'_>) -> Result<(), E> - where - Self: Sized, - { - KotlinValidatedTreeWalker::walk(self, tree) - } - - fn enter_every_rule(&mut self, _ctx: ValidatedRuleNode<'_>) -> Result<(), E> { Ok(()) } - fn exit_every_rule(&mut self, _ctx: ValidatedRuleNode<'_>) -> Result<(), E> { Ok(()) } - - fn enter_kotlin_file(&mut self, _ctx: &KotlinFileContext) -> Result<(), E> { Ok(()) } - fn exit_kotlin_file(&mut self, _ctx: &KotlinFileContext) -> Result<(), E> { Ok(()) } - fn enter_script(&mut self, _ctx: &ScriptContext) -> Result<(), E> { Ok(()) } - fn exit_script(&mut self, _ctx: &ScriptContext) -> Result<(), E> { Ok(()) } - fn enter_shebang_line(&mut self, _ctx: &ShebangLineContext) -> Result<(), E> { Ok(()) } - fn exit_shebang_line(&mut self, _ctx: &ShebangLineContext) -> Result<(), E> { Ok(()) } - fn enter_file_annotation(&mut self, _ctx: &FileAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_file_annotation(&mut self, _ctx: &FileAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_package_header(&mut self, _ctx: &PackageHeaderContext) -> Result<(), E> { Ok(()) } - fn exit_package_header(&mut self, _ctx: &PackageHeaderContext) -> Result<(), E> { Ok(()) } - fn enter_import_list(&mut self, _ctx: &ImportListContext) -> Result<(), E> { Ok(()) } - fn exit_import_list(&mut self, _ctx: &ImportListContext) -> Result<(), E> { Ok(()) } - fn enter_import_header(&mut self, _ctx: &ImportHeaderContext) -> Result<(), E> { Ok(()) } - fn exit_import_header(&mut self, _ctx: &ImportHeaderContext) -> Result<(), E> { Ok(()) } - fn enter_import_alias(&mut self, _ctx: &ImportAliasContext) -> Result<(), E> { Ok(()) } - fn exit_import_alias(&mut self, _ctx: &ImportAliasContext) -> Result<(), E> { Ok(()) } - fn enter_top_level_object(&mut self, _ctx: &TopLevelObjectContext) -> Result<(), E> { Ok(()) } - fn exit_top_level_object(&mut self, _ctx: &TopLevelObjectContext) -> Result<(), E> { Ok(()) } - fn enter_type_alias(&mut self, _ctx: &TypeAliasContext) -> Result<(), E> { Ok(()) } - fn exit_type_alias(&mut self, _ctx: &TypeAliasContext) -> Result<(), E> { Ok(()) } - fn enter_declaration(&mut self, _ctx: &DeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_declaration(&mut self, _ctx: &DeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_declaration(&mut self, _ctx: &ClassDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_primary_constructor(&mut self, _ctx: &PrimaryConstructorContext) -> Result<(), E> { Ok(()) } - fn exit_primary_constructor(&mut self, _ctx: &PrimaryConstructorContext) -> Result<(), E> { Ok(()) } - fn enter_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn exit_class_body(&mut self, _ctx: &ClassBodyContext) -> Result<(), E> { Ok(()) } - fn enter_class_parameters(&mut self, _ctx: &ClassParametersContext) -> Result<(), E> { Ok(()) } - fn exit_class_parameters(&mut self, _ctx: &ClassParametersContext) -> Result<(), E> { Ok(()) } - fn enter_class_parameter(&mut self, _ctx: &ClassParameterContext) -> Result<(), E> { Ok(()) } - fn exit_class_parameter(&mut self, _ctx: &ClassParameterContext) -> Result<(), E> { Ok(()) } - fn enter_delegation_specifiers(&mut self, _ctx: &DelegationSpecifiersContext) -> Result<(), E> { Ok(()) } - fn exit_delegation_specifiers(&mut self, _ctx: &DelegationSpecifiersContext) -> Result<(), E> { Ok(()) } - fn enter_delegation_specifier(&mut self, _ctx: &DelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_delegation_specifier(&mut self, _ctx: &DelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_invocation(&mut self, _ctx: &ConstructorInvocationContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_invocation(&mut self, _ctx: &ConstructorInvocationContext) -> Result<(), E> { Ok(()) } - fn enter_annotated_delegation_specifier(&mut self, _ctx: &AnnotatedDelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn exit_annotated_delegation_specifier(&mut self, _ctx: &AnnotatedDelegationSpecifierContext) -> Result<(), E> { Ok(()) } - fn enter_explicit_delegation(&mut self, _ctx: &ExplicitDelegationContext) -> Result<(), E> { Ok(()) } - fn exit_explicit_delegation(&mut self, _ctx: &ExplicitDelegationContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameters(&mut self, _ctx: &TypeParametersContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter(&mut self, _ctx: &TypeParameterContext) -> Result<(), E> { Ok(()) } - fn enter_type_constraints(&mut self, _ctx: &TypeConstraintsContext) -> Result<(), E> { Ok(()) } - fn exit_type_constraints(&mut self, _ctx: &TypeConstraintsContext) -> Result<(), E> { Ok(()) } - fn enter_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn exit_type_constraint(&mut self, _ctx: &TypeConstraintContext) -> Result<(), E> { Ok(()) } - fn enter_class_member_declarations(&mut self, _ctx: &ClassMemberDeclarationsContext) -> Result<(), E> { Ok(()) } - fn exit_class_member_declarations(&mut self, _ctx: &ClassMemberDeclarationsContext) -> Result<(), E> { Ok(()) } - fn enter_class_member_declaration(&mut self, _ctx: &ClassMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_class_member_declaration(&mut self, _ctx: &ClassMemberDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_initializer(&mut self, _ctx: &AnonymousInitializerContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_initializer(&mut self, _ctx: &AnonymousInitializerContext) -> Result<(), E> { Ok(()) } - fn enter_companion_object(&mut self, _ctx: &CompanionObjectContext) -> Result<(), E> { Ok(()) } - fn exit_companion_object(&mut self, _ctx: &CompanionObjectContext) -> Result<(), E> { Ok(()) } - fn enter_function_value_parameters(&mut self, _ctx: &FunctionValueParametersContext) -> Result<(), E> { Ok(()) } - fn exit_function_value_parameters(&mut self, _ctx: &FunctionValueParametersContext) -> Result<(), E> { Ok(()) } - fn enter_function_value_parameter(&mut self, _ctx: &FunctionValueParameterContext) -> Result<(), E> { Ok(()) } - fn exit_function_value_parameter(&mut self, _ctx: &FunctionValueParameterContext) -> Result<(), E> { Ok(()) } - fn enter_function_declaration(&mut self, _ctx: &FunctionDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_function_declaration(&mut self, _ctx: &FunctionDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_function_body(&mut self, _ctx: &FunctionBodyContext) -> Result<(), E> { Ok(()) } - fn exit_function_body(&mut self, _ctx: &FunctionBodyContext) -> Result<(), E> { Ok(()) } - fn enter_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_variable_declaration(&mut self, _ctx: &VariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_multi_variable_declaration(&mut self, _ctx: &MultiVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_multi_variable_declaration(&mut self, _ctx: &MultiVariableDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_property_declaration(&mut self, _ctx: &PropertyDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_property_delegate(&mut self, _ctx: &PropertyDelegateContext) -> Result<(), E> { Ok(()) } - fn exit_property_delegate(&mut self, _ctx: &PropertyDelegateContext) -> Result<(), E> { Ok(()) } - fn enter_getter(&mut self, _ctx: &GetterContext) -> Result<(), E> { Ok(()) } - fn exit_getter(&mut self, _ctx: &GetterContext) -> Result<(), E> { Ok(()) } - fn enter_setter(&mut self, _ctx: &SetterContext) -> Result<(), E> { Ok(()) } - fn exit_setter(&mut self, _ctx: &SetterContext) -> Result<(), E> { Ok(()) } - fn enter_parameters_with_optional_type(&mut self, _ctx: &ParametersWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parameters_with_optional_type(&mut self, _ctx: &ParametersWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn enter_function_value_parameter_with_optional_type(&mut self, _ctx: &FunctionValueParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn exit_function_value_parameter_with_optional_type(&mut self, _ctx: &FunctionValueParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_with_optional_type(&mut self, _ctx: &ParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_with_optional_type(&mut self, _ctx: &ParameterWithOptionalTypeContext) -> Result<(), E> { Ok(()) } - fn enter_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn exit_parameter(&mut self, _ctx: &ParameterContext) -> Result<(), E> { Ok(()) } - fn enter_object_declaration(&mut self, _ctx: &ObjectDeclarationContext) -> Result<(), E> { Ok(()) } - fn exit_object_declaration(&mut self, _ctx: &ObjectDeclarationContext) -> Result<(), E> { Ok(()) } - fn enter_secondary_constructor(&mut self, _ctx: &SecondaryConstructorContext) -> Result<(), E> { Ok(()) } - fn exit_secondary_constructor(&mut self, _ctx: &SecondaryConstructorContext) -> Result<(), E> { Ok(()) } - fn enter_constructor_delegation_call(&mut self, _ctx: &ConstructorDelegationCallContext) -> Result<(), E> { Ok(()) } - fn exit_constructor_delegation_call(&mut self, _ctx: &ConstructorDelegationCallContext) -> Result<(), E> { Ok(()) } - fn enter_enum_class_body(&mut self, _ctx: &EnumClassBodyContext) -> Result<(), E> { Ok(()) } - fn exit_enum_class_body(&mut self, _ctx: &EnumClassBodyContext) -> Result<(), E> { Ok(()) } - fn enter_enum_entries(&mut self, _ctx: &EnumEntriesContext) -> Result<(), E> { Ok(()) } - fn exit_enum_entries(&mut self, _ctx: &EnumEntriesContext) -> Result<(), E> { Ok(()) } - fn enter_enum_entry(&mut self, _ctx: &EnumEntryContext) -> Result<(), E> { Ok(()) } - fn exit_enum_entry(&mut self, _ctx: &EnumEntryContext) -> Result<(), E> { Ok(()) } - fn enter_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn exit_type(&mut self, _ctx: &TypeContext) -> Result<(), E> { Ok(()) } - fn enter_type_reference(&mut self, _ctx: &TypeReferenceContext) -> Result<(), E> { Ok(()) } - fn exit_type_reference(&mut self, _ctx: &TypeReferenceContext) -> Result<(), E> { Ok(()) } - fn enter_nullable_type(&mut self, _ctx: &NullableTypeContext) -> Result<(), E> { Ok(()) } - fn exit_nullable_type(&mut self, _ctx: &NullableTypeContext) -> Result<(), E> { Ok(()) } - fn enter_quest(&mut self, _ctx: &QuestContext) -> Result<(), E> { Ok(()) } - fn exit_quest(&mut self, _ctx: &QuestContext) -> Result<(), E> { Ok(()) } - fn enter_user_type(&mut self, _ctx: &UserTypeContext) -> Result<(), E> { Ok(()) } - fn exit_user_type(&mut self, _ctx: &UserTypeContext) -> Result<(), E> { Ok(()) } - fn enter_simple_user_type(&mut self, _ctx: &SimpleUserTypeContext) -> Result<(), E> { Ok(()) } - fn exit_simple_user_type(&mut self, _ctx: &SimpleUserTypeContext) -> Result<(), E> { Ok(()) } - fn enter_type_projection(&mut self, _ctx: &TypeProjectionContext) -> Result<(), E> { Ok(()) } - fn exit_type_projection(&mut self, _ctx: &TypeProjectionContext) -> Result<(), E> { Ok(()) } - fn enter_type_projection_modifiers(&mut self, _ctx: &TypeProjectionModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_type_projection_modifiers(&mut self, _ctx: &TypeProjectionModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_type_projection_modifier(&mut self, _ctx: &TypeProjectionModifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_projection_modifier(&mut self, _ctx: &TypeProjectionModifierContext) -> Result<(), E> { Ok(()) } - fn enter_function_type(&mut self, _ctx: &FunctionTypeContext) -> Result<(), E> { Ok(()) } - fn exit_function_type(&mut self, _ctx: &FunctionTypeContext) -> Result<(), E> { Ok(()) } - fn enter_function_type_parameters(&mut self, _ctx: &FunctionTypeParametersContext) -> Result<(), E> { Ok(()) } - fn exit_function_type_parameters(&mut self, _ctx: &FunctionTypeParametersContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_type(&mut self, _ctx: &ParenthesizedTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_type(&mut self, _ctx: &ParenthesizedTypeContext) -> Result<(), E> { Ok(()) } - fn enter_receiver_type(&mut self, _ctx: &ReceiverTypeContext) -> Result<(), E> { Ok(()) } - fn exit_receiver_type(&mut self, _ctx: &ReceiverTypeContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_user_type(&mut self, _ctx: &ParenthesizedUserTypeContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_user_type(&mut self, _ctx: &ParenthesizedUserTypeContext) -> Result<(), E> { Ok(()) } - fn enter_definitely_non_nullable_type(&mut self, _ctx: &DefinitelyNonNullableTypeContext) -> Result<(), E> { Ok(()) } - fn exit_definitely_non_nullable_type(&mut self, _ctx: &DefinitelyNonNullableTypeContext) -> Result<(), E> { Ok(()) } - fn enter_statements(&mut self, _ctx: &StatementsContext) -> Result<(), E> { Ok(()) } - fn exit_statements(&mut self, _ctx: &StatementsContext) -> Result<(), E> { Ok(()) } - fn enter_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn exit_statement(&mut self, _ctx: &StatementContext) -> Result<(), E> { Ok(()) } - fn enter_label(&mut self, _ctx: &LabelContext) -> Result<(), E> { Ok(()) } - fn exit_label(&mut self, _ctx: &LabelContext) -> Result<(), E> { Ok(()) } - fn enter_control_structure_body(&mut self, _ctx: &ControlStructureBodyContext) -> Result<(), E> { Ok(()) } - fn exit_control_structure_body(&mut self, _ctx: &ControlStructureBodyContext) -> Result<(), E> { Ok(()) } - fn enter_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn exit_block(&mut self, _ctx: &BlockContext) -> Result<(), E> { Ok(()) } - fn enter_loop_statement(&mut self, _ctx: &LoopStatementContext) -> Result<(), E> { Ok(()) } - fn exit_loop_statement(&mut self, _ctx: &LoopStatementContext) -> Result<(), E> { Ok(()) } - fn enter_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn exit_for_statement(&mut self, _ctx: &ForStatementContext) -> Result<(), E> { Ok(()) } - fn enter_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn exit_while_statement(&mut self, _ctx: &WhileStatementContext) -> Result<(), E> { Ok(()) } - fn enter_do_while_statement(&mut self, _ctx: &DoWhileStatementContext) -> Result<(), E> { Ok(()) } - fn exit_do_while_statement(&mut self, _ctx: &DoWhileStatementContext) -> Result<(), E> { Ok(()) } - fn enter_assignment(&mut self, _ctx: &AssignmentContext) -> Result<(), E> { Ok(()) } - fn exit_assignment(&mut self, _ctx: &AssignmentContext) -> Result<(), E> { Ok(()) } - fn enter_semi(&mut self, _ctx: &SemiContext) -> Result<(), E> { Ok(()) } - fn exit_semi(&mut self, _ctx: &SemiContext) -> Result<(), E> { Ok(()) } - fn enter_semis(&mut self, _ctx: &SemisContext) -> Result<(), E> { Ok(()) } - fn exit_semis(&mut self, _ctx: &SemisContext) -> Result<(), E> { Ok(()) } - fn enter_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_expression(&mut self, _ctx: &ExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_disjunction(&mut self, _ctx: &DisjunctionContext) -> Result<(), E> { Ok(()) } - fn exit_disjunction(&mut self, _ctx: &DisjunctionContext) -> Result<(), E> { Ok(()) } - fn enter_conjunction(&mut self, _ctx: &ConjunctionContext) -> Result<(), E> { Ok(()) } - fn exit_conjunction(&mut self, _ctx: &ConjunctionContext) -> Result<(), E> { Ok(()) } - fn enter_equality(&mut self, _ctx: &EqualityContext) -> Result<(), E> { Ok(()) } - fn exit_equality(&mut self, _ctx: &EqualityContext) -> Result<(), E> { Ok(()) } - fn enter_comparison(&mut self, _ctx: &ComparisonContext) -> Result<(), E> { Ok(()) } - fn exit_comparison(&mut self, _ctx: &ComparisonContext) -> Result<(), E> { Ok(()) } - fn enter_generic_call_like_comparison(&mut self, _ctx: &GenericCallLikeComparisonContext) -> Result<(), E> { Ok(()) } - fn exit_generic_call_like_comparison(&mut self, _ctx: &GenericCallLikeComparisonContext) -> Result<(), E> { Ok(()) } - fn enter_infix_operation(&mut self, _ctx: &InfixOperationContext) -> Result<(), E> { Ok(()) } - fn exit_infix_operation(&mut self, _ctx: &InfixOperationContext) -> Result<(), E> { Ok(()) } - fn enter_elvis_expression(&mut self, _ctx: &ElvisExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_elvis_expression(&mut self, _ctx: &ElvisExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_elvis(&mut self, _ctx: &ElvisContext) -> Result<(), E> { Ok(()) } - fn exit_elvis(&mut self, _ctx: &ElvisContext) -> Result<(), E> { Ok(()) } - fn enter_infix_function_call(&mut self, _ctx: &InfixFunctionCallContext) -> Result<(), E> { Ok(()) } - fn exit_infix_function_call(&mut self, _ctx: &InfixFunctionCallContext) -> Result<(), E> { Ok(()) } - fn enter_range_expression(&mut self, _ctx: &RangeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_range_expression(&mut self, _ctx: &RangeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_additive_expression(&mut self, _ctx: &AdditiveExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_additive_expression(&mut self, _ctx: &AdditiveExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_multiplicative_expression(&mut self, _ctx: &MultiplicativeExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_multiplicative_expression(&mut self, _ctx: &MultiplicativeExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_as_expression(&mut self, _ctx: &AsExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_as_expression(&mut self, _ctx: &AsExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_prefix_unary_expression(&mut self, _ctx: &PrefixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_unary_prefix(&mut self, _ctx: &UnaryPrefixContext) -> Result<(), E> { Ok(()) } - fn exit_unary_prefix(&mut self, _ctx: &UnaryPrefixContext) -> Result<(), E> { Ok(()) } - fn enter_postfix_unary_expression(&mut self, _ctx: &PostfixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_postfix_unary_expression(&mut self, _ctx: &PostfixUnaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_postfix_unary_suffix(&mut self, _ctx: &PostfixUnarySuffixContext) -> Result<(), E> { Ok(()) } - fn exit_postfix_unary_suffix(&mut self, _ctx: &PostfixUnarySuffixContext) -> Result<(), E> { Ok(()) } - fn enter_directly_assignable_expression(&mut self, _ctx: &DirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_directly_assignable_expression(&mut self, _ctx: &DirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_directly_assignable_expression(&mut self, _ctx: &ParenthesizedDirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_directly_assignable_expression(&mut self, _ctx: &ParenthesizedDirectlyAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_assignable_expression(&mut self, _ctx: &AssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_assignable_expression(&mut self, _ctx: &AssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_assignable_expression(&mut self, _ctx: &ParenthesizedAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_assignable_expression(&mut self, _ctx: &ParenthesizedAssignableExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_assignable_suffix(&mut self, _ctx: &AssignableSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_assignable_suffix(&mut self, _ctx: &AssignableSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_indexing_suffix(&mut self, _ctx: &IndexingSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_indexing_suffix(&mut self, _ctx: &IndexingSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_navigation_suffix(&mut self, _ctx: &NavigationSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_navigation_suffix(&mut self, _ctx: &NavigationSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_call_suffix(&mut self, _ctx: &CallSuffixContext) -> Result<(), E> { Ok(()) } - fn exit_call_suffix(&mut self, _ctx: &CallSuffixContext) -> Result<(), E> { Ok(()) } - fn enter_annotated_lambda(&mut self, _ctx: &AnnotatedLambdaContext) -> Result<(), E> { Ok(()) } - fn exit_annotated_lambda(&mut self, _ctx: &AnnotatedLambdaContext) -> Result<(), E> { Ok(()) } - fn enter_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_type_arguments(&mut self, _ctx: &TypeArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_value_arguments(&mut self, _ctx: &ValueArgumentsContext) -> Result<(), E> { Ok(()) } - fn exit_value_arguments(&mut self, _ctx: &ValueArgumentsContext) -> Result<(), E> { Ok(()) } - fn enter_value_argument(&mut self, _ctx: &ValueArgumentContext) -> Result<(), E> { Ok(()) } - fn exit_value_argument(&mut self, _ctx: &ValueArgumentContext) -> Result<(), E> { Ok(()) } - fn enter_primary_expression(&mut self, _ctx: &PrimaryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_primary_expression(&mut self, _ctx: &PrimaryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_parenthesized_expression(&mut self, _ctx: &ParenthesizedExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_collection_literal(&mut self, _ctx: &CollectionLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_collection_literal(&mut self, _ctx: &CollectionLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_literal_constant(&mut self, _ctx: &LiteralConstantContext) -> Result<(), E> { Ok(()) } - fn exit_literal_constant(&mut self, _ctx: &LiteralConstantContext) -> Result<(), E> { Ok(()) } - fn enter_string_literal(&mut self, _ctx: &StringLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_string_literal(&mut self, _ctx: &StringLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_line_string_literal(&mut self, _ctx: &LineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_line_string_literal(&mut self, _ctx: &LineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_string_literal(&mut self, _ctx: &MultiLineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_string_literal(&mut self, _ctx: &MultiLineStringLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_line_string_content(&mut self, _ctx: &LineStringContentContext) -> Result<(), E> { Ok(()) } - fn exit_line_string_content(&mut self, _ctx: &LineStringContentContext) -> Result<(), E> { Ok(()) } - fn enter_line_string_expression(&mut self, _ctx: &LineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_line_string_expression(&mut self, _ctx: &LineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_string_content(&mut self, _ctx: &MultiLineStringContentContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_string_content(&mut self, _ctx: &MultiLineStringContentContext) -> Result<(), E> { Ok(()) } - fn enter_multi_line_string_expression(&mut self, _ctx: &MultiLineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_multi_line_string_expression(&mut self, _ctx: &MultiLineStringExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_literal(&mut self, _ctx: &LambdaLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_literal(&mut self, _ctx: &LambdaLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_parameters(&mut self, _ctx: &LambdaParametersContext) -> Result<(), E> { Ok(()) } - fn enter_lambda_parameter(&mut self, _ctx: &LambdaParameterContext) -> Result<(), E> { Ok(()) } - fn exit_lambda_parameter(&mut self, _ctx: &LambdaParameterContext) -> Result<(), E> { Ok(()) } - fn enter_anonymous_function(&mut self, _ctx: &AnonymousFunctionContext) -> Result<(), E> { Ok(()) } - fn exit_anonymous_function(&mut self, _ctx: &AnonymousFunctionContext) -> Result<(), E> { Ok(()) } - fn enter_function_literal(&mut self, _ctx: &FunctionLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_function_literal(&mut self, _ctx: &FunctionLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_object_literal(&mut self, _ctx: &ObjectLiteralContext) -> Result<(), E> { Ok(()) } - fn exit_object_literal(&mut self, _ctx: &ObjectLiteralContext) -> Result<(), E> { Ok(()) } - fn enter_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_this_expression(&mut self, _ctx: &ThisExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_super_expression(&mut self, _ctx: &SuperExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_super_expression(&mut self, _ctx: &SuperExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_if_expression(&mut self, _ctx: &IfExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_if_expression(&mut self, _ctx: &IfExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_when_subject(&mut self, _ctx: &WhenSubjectContext) -> Result<(), E> { Ok(()) } - fn exit_when_subject(&mut self, _ctx: &WhenSubjectContext) -> Result<(), E> { Ok(()) } - fn enter_when_expression(&mut self, _ctx: &WhenExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_when_expression(&mut self, _ctx: &WhenExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_when_entry(&mut self, _ctx: &WhenEntryContext) -> Result<(), E> { Ok(()) } - fn exit_when_entry(&mut self, _ctx: &WhenEntryContext) -> Result<(), E> { Ok(()) } - fn enter_when_condition(&mut self, _ctx: &WhenConditionContext) -> Result<(), E> { Ok(()) } - fn exit_when_condition(&mut self, _ctx: &WhenConditionContext) -> Result<(), E> { Ok(()) } - fn enter_range_test(&mut self, _ctx: &RangeTestContext) -> Result<(), E> { Ok(()) } - fn exit_range_test(&mut self, _ctx: &RangeTestContext) -> Result<(), E> { Ok(()) } - fn enter_type_test(&mut self, _ctx: &TypeTestContext) -> Result<(), E> { Ok(()) } - fn exit_type_test(&mut self, _ctx: &TypeTestContext) -> Result<(), E> { Ok(()) } - fn enter_try_expression(&mut self, _ctx: &TryExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_try_expression(&mut self, _ctx: &TryExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_catch_block(&mut self, _ctx: &CatchBlockContext) -> Result<(), E> { Ok(()) } - fn exit_catch_block(&mut self, _ctx: &CatchBlockContext) -> Result<(), E> { Ok(()) } - fn enter_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn exit_finally_block(&mut self, _ctx: &FinallyBlockContext) -> Result<(), E> { Ok(()) } - fn enter_jump_expression(&mut self, _ctx: &JumpExpressionContext) -> Result<(), E> { Ok(()) } - fn exit_jump_expression(&mut self, _ctx: &JumpExpressionContext) -> Result<(), E> { Ok(()) } - fn enter_callable_reference(&mut self, _ctx: &CallableReferenceContext) -> Result<(), E> { Ok(()) } - fn exit_callable_reference(&mut self, _ctx: &CallableReferenceContext) -> Result<(), E> { Ok(()) } - fn enter_assignment_and_operator(&mut self, _ctx: &AssignmentAndOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_assignment_and_operator(&mut self, _ctx: &AssignmentAndOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_equality_operator(&mut self, _ctx: &EqualityOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_equality_operator(&mut self, _ctx: &EqualityOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_comparison_operator(&mut self, _ctx: &ComparisonOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_comparison_operator(&mut self, _ctx: &ComparisonOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_in_operator(&mut self, _ctx: &InOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_in_operator(&mut self, _ctx: &InOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_is_operator(&mut self, _ctx: &IsOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_is_operator(&mut self, _ctx: &IsOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_additive_operator(&mut self, _ctx: &AdditiveOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_additive_operator(&mut self, _ctx: &AdditiveOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_multiplicative_operator(&mut self, _ctx: &MultiplicativeOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_multiplicative_operator(&mut self, _ctx: &MultiplicativeOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_as_operator(&mut self, _ctx: &AsOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_as_operator(&mut self, _ctx: &AsOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_prefix_unary_operator(&mut self, _ctx: &PrefixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_prefix_unary_operator(&mut self, _ctx: &PrefixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_postfix_unary_operator(&mut self, _ctx: &PostfixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_postfix_unary_operator(&mut self, _ctx: &PostfixUnaryOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_excl(&mut self, _ctx: &ExclContext) -> Result<(), E> { Ok(()) } - fn exit_excl(&mut self, _ctx: &ExclContext) -> Result<(), E> { Ok(()) } - fn enter_member_access_operator(&mut self, _ctx: &MemberAccessOperatorContext) -> Result<(), E> { Ok(()) } - fn exit_member_access_operator(&mut self, _ctx: &MemberAccessOperatorContext) -> Result<(), E> { Ok(()) } - fn enter_safe_nav(&mut self, _ctx: &SafeNavContext) -> Result<(), E> { Ok(()) } - fn exit_safe_nav(&mut self, _ctx: &SafeNavContext) -> Result<(), E> { Ok(()) } - fn enter_modifiers(&mut self, _ctx: &ModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_modifiers(&mut self, _ctx: &ModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_modifiers(&mut self, _ctx: &ParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_modifiers(&mut self, _ctx: &ParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn exit_modifier(&mut self, _ctx: &ModifierContext) -> Result<(), E> { Ok(()) } - fn enter_type_modifiers(&mut self, _ctx: &TypeModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_type_modifiers(&mut self, _ctx: &TypeModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_type_modifier(&mut self, _ctx: &TypeModifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_modifier(&mut self, _ctx: &TypeModifierContext) -> Result<(), E> { Ok(()) } - fn enter_class_modifier(&mut self, _ctx: &ClassModifierContext) -> Result<(), E> { Ok(()) } - fn exit_class_modifier(&mut self, _ctx: &ClassModifierContext) -> Result<(), E> { Ok(()) } - fn enter_member_modifier(&mut self, _ctx: &MemberModifierContext) -> Result<(), E> { Ok(()) } - fn exit_member_modifier(&mut self, _ctx: &MemberModifierContext) -> Result<(), E> { Ok(()) } - fn enter_visibility_modifier(&mut self, _ctx: &VisibilityModifierContext) -> Result<(), E> { Ok(()) } - fn exit_visibility_modifier(&mut self, _ctx: &VisibilityModifierContext) -> Result<(), E> { Ok(()) } - fn enter_variance_modifier(&mut self, _ctx: &VarianceModifierContext) -> Result<(), E> { Ok(()) } - fn exit_variance_modifier(&mut self, _ctx: &VarianceModifierContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_modifiers(&mut self, _ctx: &TypeParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_modifiers(&mut self, _ctx: &TypeParameterModifiersContext) -> Result<(), E> { Ok(()) } - fn enter_type_parameter_modifier(&mut self, _ctx: &TypeParameterModifierContext) -> Result<(), E> { Ok(()) } - fn exit_type_parameter_modifier(&mut self, _ctx: &TypeParameterModifierContext) -> Result<(), E> { Ok(()) } - fn enter_function_modifier(&mut self, _ctx: &FunctionModifierContext) -> Result<(), E> { Ok(()) } - fn exit_function_modifier(&mut self, _ctx: &FunctionModifierContext) -> Result<(), E> { Ok(()) } - fn enter_property_modifier(&mut self, _ctx: &PropertyModifierContext) -> Result<(), E> { Ok(()) } - fn exit_property_modifier(&mut self, _ctx: &PropertyModifierContext) -> Result<(), E> { Ok(()) } - fn enter_inheritance_modifier(&mut self, _ctx: &InheritanceModifierContext) -> Result<(), E> { Ok(()) } - fn exit_inheritance_modifier(&mut self, _ctx: &InheritanceModifierContext) -> Result<(), E> { Ok(()) } - fn enter_parameter_modifier(&mut self, _ctx: &ParameterModifierContext) -> Result<(), E> { Ok(()) } - fn exit_parameter_modifier(&mut self, _ctx: &ParameterModifierContext) -> Result<(), E> { Ok(()) } - fn enter_reification_modifier(&mut self, _ctx: &ReificationModifierContext) -> Result<(), E> { Ok(()) } - fn exit_reification_modifier(&mut self, _ctx: &ReificationModifierContext) -> Result<(), E> { Ok(()) } - fn enter_platform_modifier(&mut self, _ctx: &PlatformModifierContext) -> Result<(), E> { Ok(()) } - fn exit_platform_modifier(&mut self, _ctx: &PlatformModifierContext) -> Result<(), E> { Ok(()) } - fn enter_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_annotation(&mut self, _ctx: &AnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_single_annotation(&mut self, _ctx: &SingleAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_single_annotation(&mut self, _ctx: &SingleAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_multi_annotation(&mut self, _ctx: &MultiAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_multi_annotation(&mut self, _ctx: &MultiAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_annotation_use_site_target(&mut self, _ctx: &AnnotationUseSiteTargetContext) -> Result<(), E> { Ok(()) } - fn exit_annotation_use_site_target(&mut self, _ctx: &AnnotationUseSiteTargetContext) -> Result<(), E> { Ok(()) } - fn enter_unescaped_annotation(&mut self, _ctx: &UnescapedAnnotationContext) -> Result<(), E> { Ok(()) } - fn exit_unescaped_annotation(&mut self, _ctx: &UnescapedAnnotationContext) -> Result<(), E> { Ok(()) } - fn enter_simple_identifier(&mut self, _ctx: &SimpleIdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_simple_identifier(&mut self, _ctx: &SimpleIdentifierContext) -> Result<(), E> { Ok(()) } - fn enter_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn exit_identifier(&mut self, _ctx: &IdentifierContext) -> Result<(), E> { Ok(()) } - fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), E> { Ok(()) } - fn output(&mut self) -> std::io::Stdout { std::io::stdout() } -} - -antlr4_runtime::__antlr4_rust_generated_walk_callbacks! { - callbacks: __KotlinValidatedTreeWalkerCallbacks, - listener: KotlinValidatedListener, - enter: |listener, context, invocation_states| { - listener.enter_every_rule(ValidatedRuleNode::__new(context))?; - match __context_kind(context) { - 0 => listener.enter_kotlin_file(&KotlinFileContext::::__from_validated_listener_node(context, invocation_states))?, - 1 => listener.enter_script(&ScriptContext::::__from_validated_listener_node(context, invocation_states))?, - 2 => listener.enter_shebang_line(&ShebangLineContext::::__from_validated_listener_node(context, invocation_states))?, - 3 => listener.enter_file_annotation(&FileAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 4 => listener.enter_package_header(&PackageHeaderContext::::__from_validated_listener_node(context, invocation_states))?, - 5 => listener.enter_import_list(&ImportListContext::::__from_validated_listener_node(context, invocation_states))?, - 6 => listener.enter_import_header(&ImportHeaderContext::::__from_validated_listener_node(context, invocation_states))?, - 7 => listener.enter_import_alias(&ImportAliasContext::::__from_validated_listener_node(context, invocation_states))?, - 8 => listener.enter_top_level_object(&TopLevelObjectContext::::__from_validated_listener_node(context, invocation_states))?, - 9 => listener.enter_type_alias(&TypeAliasContext::::__from_validated_listener_node(context, invocation_states))?, - 10 => listener.enter_declaration(&DeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 11 => listener.enter_class_declaration(&ClassDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 12 => listener.enter_primary_constructor(&PrimaryConstructorContext::::__from_validated_listener_node(context, invocation_states))?, - 13 => listener.enter_class_body(&ClassBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 14 => listener.enter_class_parameters(&ClassParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 15 => listener.enter_class_parameter(&ClassParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 16 => listener.enter_delegation_specifiers(&DelegationSpecifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 17 => listener.enter_delegation_specifier(&DelegationSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 18 => listener.enter_constructor_invocation(&ConstructorInvocationContext::::__from_validated_listener_node(context, invocation_states))?, - 19 => listener.enter_annotated_delegation_specifier(&AnnotatedDelegationSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 20 => listener.enter_explicit_delegation(&ExplicitDelegationContext::::__from_validated_listener_node(context, invocation_states))?, - 21 => listener.enter_type_parameters(&TypeParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 22 => listener.enter_type_parameter(&TypeParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 23 => listener.enter_type_constraints(&TypeConstraintsContext::::__from_validated_listener_node(context, invocation_states))?, - 24 => listener.enter_type_constraint(&TypeConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 25 => listener.enter_class_member_declarations(&ClassMemberDeclarationsContext::::__from_validated_listener_node(context, invocation_states))?, - 26 => listener.enter_class_member_declaration(&ClassMemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 27 => listener.enter_anonymous_initializer(&AnonymousInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 28 => listener.enter_companion_object(&CompanionObjectContext::::__from_validated_listener_node(context, invocation_states))?, - 29 => listener.enter_function_value_parameters(&FunctionValueParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 30 => listener.enter_function_value_parameter(&FunctionValueParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 31 => listener.enter_function_declaration(&FunctionDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 32 => listener.enter_function_body(&FunctionBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 33 => listener.enter_variable_declaration(&VariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 34 => listener.enter_multi_variable_declaration(&MultiVariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 35 => listener.enter_property_declaration(&PropertyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 36 => listener.enter_property_delegate(&PropertyDelegateContext::::__from_validated_listener_node(context, invocation_states))?, - 37 => listener.enter_getter(&GetterContext::::__from_validated_listener_node(context, invocation_states))?, - 38 => listener.enter_setter(&SetterContext::::__from_validated_listener_node(context, invocation_states))?, - 39 => listener.enter_parameters_with_optional_type(&ParametersWithOptionalTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 40 => listener.enter_function_value_parameter_with_optional_type(&FunctionValueParameterWithOptionalTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 41 => listener.enter_parameter_with_optional_type(&ParameterWithOptionalTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 42 => listener.enter_parameter(&ParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 43 => listener.enter_object_declaration(&ObjectDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 44 => listener.enter_secondary_constructor(&SecondaryConstructorContext::::__from_validated_listener_node(context, invocation_states))?, - 45 => listener.enter_constructor_delegation_call(&ConstructorDelegationCallContext::::__from_validated_listener_node(context, invocation_states))?, - 46 => listener.enter_enum_class_body(&EnumClassBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 47 => listener.enter_enum_entries(&EnumEntriesContext::::__from_validated_listener_node(context, invocation_states))?, - 48 => listener.enter_enum_entry(&EnumEntryContext::::__from_validated_listener_node(context, invocation_states))?, - 49 => listener.enter_type(&TypeContext::::__from_validated_listener_node(context, invocation_states))?, - 50 => listener.enter_type_reference(&TypeReferenceContext::::__from_validated_listener_node(context, invocation_states))?, - 51 => listener.enter_nullable_type(&NullableTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 52 => listener.enter_quest(&QuestContext::::__from_validated_listener_node(context, invocation_states))?, - 53 => listener.enter_user_type(&UserTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 54 => listener.enter_simple_user_type(&SimpleUserTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 55 => listener.enter_type_projection(&TypeProjectionContext::::__from_validated_listener_node(context, invocation_states))?, - 56 => listener.enter_type_projection_modifiers(&TypeProjectionModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 57 => listener.enter_type_projection_modifier(&TypeProjectionModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 58 => listener.enter_function_type(&FunctionTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 59 => listener.enter_function_type_parameters(&FunctionTypeParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 60 => listener.enter_parenthesized_type(&ParenthesizedTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 61 => listener.enter_receiver_type(&ReceiverTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 62 => listener.enter_parenthesized_user_type(&ParenthesizedUserTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 63 => listener.enter_definitely_non_nullable_type(&DefinitelyNonNullableTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 64 => listener.enter_statements(&StatementsContext::::__from_validated_listener_node(context, invocation_states))?, - 65 => listener.enter_statement(&StatementContext::::__from_validated_listener_node(context, invocation_states))?, - 66 => listener.enter_label(&LabelContext::::__from_validated_listener_node(context, invocation_states))?, - 67 => listener.enter_control_structure_body(&ControlStructureBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 68 => listener.enter_block(&BlockContext::::__from_validated_listener_node(context, invocation_states))?, - 69 => listener.enter_loop_statement(&LoopStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 70 => listener.enter_for_statement(&ForStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 71 => listener.enter_while_statement(&WhileStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 72 => listener.enter_do_while_statement(&DoWhileStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 73 => listener.enter_assignment(&AssignmentContext::::__from_validated_listener_node(context, invocation_states))?, - 74 => listener.enter_semi(&SemiContext::::__from_validated_listener_node(context, invocation_states))?, - 75 => listener.enter_semis(&SemisContext::::__from_validated_listener_node(context, invocation_states))?, - 76 => listener.enter_expression(&ExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 77 => listener.enter_disjunction(&DisjunctionContext::::__from_validated_listener_node(context, invocation_states))?, - 78 => listener.enter_conjunction(&ConjunctionContext::::__from_validated_listener_node(context, invocation_states))?, - 79 => listener.enter_equality(&EqualityContext::::__from_validated_listener_node(context, invocation_states))?, - 80 => listener.enter_comparison(&ComparisonContext::::__from_validated_listener_node(context, invocation_states))?, - 81 => listener.enter_generic_call_like_comparison(&GenericCallLikeComparisonContext::::__from_validated_listener_node(context, invocation_states))?, - 82 => listener.enter_infix_operation(&InfixOperationContext::::__from_validated_listener_node(context, invocation_states))?, - 83 => listener.enter_elvis_expression(&ElvisExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 84 => listener.enter_elvis(&ElvisContext::::__from_validated_listener_node(context, invocation_states))?, - 85 => listener.enter_infix_function_call(&InfixFunctionCallContext::::__from_validated_listener_node(context, invocation_states))?, - 86 => listener.enter_range_expression(&RangeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 87 => listener.enter_additive_expression(&AdditiveExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 88 => listener.enter_multiplicative_expression(&MultiplicativeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 89 => listener.enter_as_expression(&AsExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 90 => listener.enter_prefix_unary_expression(&PrefixUnaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 91 => listener.enter_unary_prefix(&UnaryPrefixContext::::__from_validated_listener_node(context, invocation_states))?, - 92 => listener.enter_postfix_unary_expression(&PostfixUnaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 93 => listener.enter_postfix_unary_suffix(&PostfixUnarySuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 94 => listener.enter_directly_assignable_expression(&DirectlyAssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 95 => listener.enter_parenthesized_directly_assignable_expression(&ParenthesizedDirectlyAssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 96 => listener.enter_assignable_expression(&AssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 97 => listener.enter_parenthesized_assignable_expression(&ParenthesizedAssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 98 => listener.enter_assignable_suffix(&AssignableSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 99 => listener.enter_indexing_suffix(&IndexingSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 100 => listener.enter_navigation_suffix(&NavigationSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 101 => listener.enter_call_suffix(&CallSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 102 => listener.enter_annotated_lambda(&AnnotatedLambdaContext::::__from_validated_listener_node(context, invocation_states))?, - 103 => listener.enter_type_arguments(&TypeArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 104 => listener.enter_value_arguments(&ValueArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 105 => listener.enter_value_argument(&ValueArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 106 => listener.enter_primary_expression(&PrimaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 107 => listener.enter_parenthesized_expression(&ParenthesizedExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 108 => listener.enter_collection_literal(&CollectionLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 109 => listener.enter_literal_constant(&LiteralConstantContext::::__from_validated_listener_node(context, invocation_states))?, - 110 => listener.enter_string_literal(&StringLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 111 => listener.enter_line_string_literal(&LineStringLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 112 => listener.enter_multi_line_string_literal(&MultiLineStringLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 113 => listener.enter_line_string_content(&LineStringContentContext::::__from_validated_listener_node(context, invocation_states))?, - 114 => listener.enter_line_string_expression(&LineStringExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 115 => listener.enter_multi_line_string_content(&MultiLineStringContentContext::::__from_validated_listener_node(context, invocation_states))?, - 116 => listener.enter_multi_line_string_expression(&MultiLineStringExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 117 => listener.enter_lambda_literal(&LambdaLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 118 => listener.enter_lambda_parameters(&LambdaParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 119 => listener.enter_lambda_parameter(&LambdaParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 120 => listener.enter_anonymous_function(&AnonymousFunctionContext::::__from_validated_listener_node(context, invocation_states))?, - 121 => listener.enter_function_literal(&FunctionLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 122 => listener.enter_object_literal(&ObjectLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 123 => listener.enter_this_expression(&ThisExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 124 => listener.enter_super_expression(&SuperExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 125 => listener.enter_if_expression(&IfExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 126 => listener.enter_when_subject(&WhenSubjectContext::::__from_validated_listener_node(context, invocation_states))?, - 127 => listener.enter_when_expression(&WhenExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 128 => listener.enter_when_entry(&WhenEntryContext::::__from_validated_listener_node(context, invocation_states))?, - 129 => listener.enter_when_condition(&WhenConditionContext::::__from_validated_listener_node(context, invocation_states))?, - 130 => listener.enter_range_test(&RangeTestContext::::__from_validated_listener_node(context, invocation_states))?, - 131 => listener.enter_type_test(&TypeTestContext::::__from_validated_listener_node(context, invocation_states))?, - 132 => listener.enter_try_expression(&TryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 133 => listener.enter_catch_block(&CatchBlockContext::::__from_validated_listener_node(context, invocation_states))?, - 134 => listener.enter_finally_block(&FinallyBlockContext::::__from_validated_listener_node(context, invocation_states))?, - 135 => listener.enter_jump_expression(&JumpExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 136 => listener.enter_callable_reference(&CallableReferenceContext::::__from_validated_listener_node(context, invocation_states))?, - 137 => listener.enter_assignment_and_operator(&AssignmentAndOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 138 => listener.enter_equality_operator(&EqualityOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 139 => listener.enter_comparison_operator(&ComparisonOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 140 => listener.enter_in_operator(&InOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 141 => listener.enter_is_operator(&IsOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 142 => listener.enter_additive_operator(&AdditiveOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 143 => listener.enter_multiplicative_operator(&MultiplicativeOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 144 => listener.enter_as_operator(&AsOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 145 => listener.enter_prefix_unary_operator(&PrefixUnaryOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 146 => listener.enter_postfix_unary_operator(&PostfixUnaryOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 147 => listener.enter_excl(&ExclContext::::__from_validated_listener_node(context, invocation_states))?, - 148 => listener.enter_member_access_operator(&MemberAccessOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 149 => listener.enter_safe_nav(&SafeNavContext::::__from_validated_listener_node(context, invocation_states))?, - 150 => listener.enter_modifiers(&ModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 151 => listener.enter_parameter_modifiers(&ParameterModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 152 => listener.enter_modifier(&ModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 153 => listener.enter_type_modifiers(&TypeModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 154 => listener.enter_type_modifier(&TypeModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 155 => listener.enter_class_modifier(&ClassModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 156 => listener.enter_member_modifier(&MemberModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 157 => listener.enter_visibility_modifier(&VisibilityModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 158 => listener.enter_variance_modifier(&VarianceModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 159 => listener.enter_type_parameter_modifiers(&TypeParameterModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 160 => listener.enter_type_parameter_modifier(&TypeParameterModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 161 => listener.enter_function_modifier(&FunctionModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 162 => listener.enter_property_modifier(&PropertyModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 163 => listener.enter_inheritance_modifier(&InheritanceModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 164 => listener.enter_parameter_modifier(&ParameterModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 165 => listener.enter_reification_modifier(&ReificationModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 166 => listener.enter_platform_modifier(&PlatformModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 167 => listener.enter_annotation(&AnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 168 => listener.enter_single_annotation(&SingleAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 169 => listener.enter_multi_annotation(&MultiAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 170 => listener.enter_annotation_use_site_target(&AnnotationUseSiteTargetContext::::__from_validated_listener_node(context, invocation_states))?, - 171 => listener.enter_unescaped_annotation(&UnescapedAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 172 => listener.enter_simple_identifier(&SimpleIdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - 173 => listener.enter_identifier(&IdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - _ => {} - } - Ok(()) - }, - exit: |listener, context, invocation_states| { - match __context_kind(context) { - 0 => listener.exit_kotlin_file(&KotlinFileContext::::__from_validated_listener_node(context, invocation_states))?, - 1 => listener.exit_script(&ScriptContext::::__from_validated_listener_node(context, invocation_states))?, - 2 => listener.exit_shebang_line(&ShebangLineContext::::__from_validated_listener_node(context, invocation_states))?, - 3 => listener.exit_file_annotation(&FileAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 4 => listener.exit_package_header(&PackageHeaderContext::::__from_validated_listener_node(context, invocation_states))?, - 5 => listener.exit_import_list(&ImportListContext::::__from_validated_listener_node(context, invocation_states))?, - 6 => listener.exit_import_header(&ImportHeaderContext::::__from_validated_listener_node(context, invocation_states))?, - 7 => listener.exit_import_alias(&ImportAliasContext::::__from_validated_listener_node(context, invocation_states))?, - 8 => listener.exit_top_level_object(&TopLevelObjectContext::::__from_validated_listener_node(context, invocation_states))?, - 9 => listener.exit_type_alias(&TypeAliasContext::::__from_validated_listener_node(context, invocation_states))?, - 10 => listener.exit_declaration(&DeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 11 => listener.exit_class_declaration(&ClassDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 12 => listener.exit_primary_constructor(&PrimaryConstructorContext::::__from_validated_listener_node(context, invocation_states))?, - 13 => listener.exit_class_body(&ClassBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 14 => listener.exit_class_parameters(&ClassParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 15 => listener.exit_class_parameter(&ClassParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 16 => listener.exit_delegation_specifiers(&DelegationSpecifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 17 => listener.exit_delegation_specifier(&DelegationSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 18 => listener.exit_constructor_invocation(&ConstructorInvocationContext::::__from_validated_listener_node(context, invocation_states))?, - 19 => listener.exit_annotated_delegation_specifier(&AnnotatedDelegationSpecifierContext::::__from_validated_listener_node(context, invocation_states))?, - 20 => listener.exit_explicit_delegation(&ExplicitDelegationContext::::__from_validated_listener_node(context, invocation_states))?, - 21 => listener.exit_type_parameters(&TypeParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 22 => listener.exit_type_parameter(&TypeParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 23 => listener.exit_type_constraints(&TypeConstraintsContext::::__from_validated_listener_node(context, invocation_states))?, - 24 => listener.exit_type_constraint(&TypeConstraintContext::::__from_validated_listener_node(context, invocation_states))?, - 25 => listener.exit_class_member_declarations(&ClassMemberDeclarationsContext::::__from_validated_listener_node(context, invocation_states))?, - 26 => listener.exit_class_member_declaration(&ClassMemberDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 27 => listener.exit_anonymous_initializer(&AnonymousInitializerContext::::__from_validated_listener_node(context, invocation_states))?, - 28 => listener.exit_companion_object(&CompanionObjectContext::::__from_validated_listener_node(context, invocation_states))?, - 29 => listener.exit_function_value_parameters(&FunctionValueParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 30 => listener.exit_function_value_parameter(&FunctionValueParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 31 => listener.exit_function_declaration(&FunctionDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 32 => listener.exit_function_body(&FunctionBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 33 => listener.exit_variable_declaration(&VariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 34 => listener.exit_multi_variable_declaration(&MultiVariableDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 35 => listener.exit_property_declaration(&PropertyDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 36 => listener.exit_property_delegate(&PropertyDelegateContext::::__from_validated_listener_node(context, invocation_states))?, - 37 => listener.exit_getter(&GetterContext::::__from_validated_listener_node(context, invocation_states))?, - 38 => listener.exit_setter(&SetterContext::::__from_validated_listener_node(context, invocation_states))?, - 39 => listener.exit_parameters_with_optional_type(&ParametersWithOptionalTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 40 => listener.exit_function_value_parameter_with_optional_type(&FunctionValueParameterWithOptionalTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 41 => listener.exit_parameter_with_optional_type(&ParameterWithOptionalTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 42 => listener.exit_parameter(&ParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 43 => listener.exit_object_declaration(&ObjectDeclarationContext::::__from_validated_listener_node(context, invocation_states))?, - 44 => listener.exit_secondary_constructor(&SecondaryConstructorContext::::__from_validated_listener_node(context, invocation_states))?, - 45 => listener.exit_constructor_delegation_call(&ConstructorDelegationCallContext::::__from_validated_listener_node(context, invocation_states))?, - 46 => listener.exit_enum_class_body(&EnumClassBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 47 => listener.exit_enum_entries(&EnumEntriesContext::::__from_validated_listener_node(context, invocation_states))?, - 48 => listener.exit_enum_entry(&EnumEntryContext::::__from_validated_listener_node(context, invocation_states))?, - 49 => listener.exit_type(&TypeContext::::__from_validated_listener_node(context, invocation_states))?, - 50 => listener.exit_type_reference(&TypeReferenceContext::::__from_validated_listener_node(context, invocation_states))?, - 51 => listener.exit_nullable_type(&NullableTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 52 => listener.exit_quest(&QuestContext::::__from_validated_listener_node(context, invocation_states))?, - 53 => listener.exit_user_type(&UserTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 54 => listener.exit_simple_user_type(&SimpleUserTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 55 => listener.exit_type_projection(&TypeProjectionContext::::__from_validated_listener_node(context, invocation_states))?, - 56 => listener.exit_type_projection_modifiers(&TypeProjectionModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 57 => listener.exit_type_projection_modifier(&TypeProjectionModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 58 => listener.exit_function_type(&FunctionTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 59 => listener.exit_function_type_parameters(&FunctionTypeParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 60 => listener.exit_parenthesized_type(&ParenthesizedTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 61 => listener.exit_receiver_type(&ReceiverTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 62 => listener.exit_parenthesized_user_type(&ParenthesizedUserTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 63 => listener.exit_definitely_non_nullable_type(&DefinitelyNonNullableTypeContext::::__from_validated_listener_node(context, invocation_states))?, - 64 => listener.exit_statements(&StatementsContext::::__from_validated_listener_node(context, invocation_states))?, - 65 => listener.exit_statement(&StatementContext::::__from_validated_listener_node(context, invocation_states))?, - 66 => listener.exit_label(&LabelContext::::__from_validated_listener_node(context, invocation_states))?, - 67 => listener.exit_control_structure_body(&ControlStructureBodyContext::::__from_validated_listener_node(context, invocation_states))?, - 68 => listener.exit_block(&BlockContext::::__from_validated_listener_node(context, invocation_states))?, - 69 => listener.exit_loop_statement(&LoopStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 70 => listener.exit_for_statement(&ForStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 71 => listener.exit_while_statement(&WhileStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 72 => listener.exit_do_while_statement(&DoWhileStatementContext::::__from_validated_listener_node(context, invocation_states))?, - 73 => listener.exit_assignment(&AssignmentContext::::__from_validated_listener_node(context, invocation_states))?, - 74 => listener.exit_semi(&SemiContext::::__from_validated_listener_node(context, invocation_states))?, - 75 => listener.exit_semis(&SemisContext::::__from_validated_listener_node(context, invocation_states))?, - 76 => listener.exit_expression(&ExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 77 => listener.exit_disjunction(&DisjunctionContext::::__from_validated_listener_node(context, invocation_states))?, - 78 => listener.exit_conjunction(&ConjunctionContext::::__from_validated_listener_node(context, invocation_states))?, - 79 => listener.exit_equality(&EqualityContext::::__from_validated_listener_node(context, invocation_states))?, - 80 => listener.exit_comparison(&ComparisonContext::::__from_validated_listener_node(context, invocation_states))?, - 81 => listener.exit_generic_call_like_comparison(&GenericCallLikeComparisonContext::::__from_validated_listener_node(context, invocation_states))?, - 82 => listener.exit_infix_operation(&InfixOperationContext::::__from_validated_listener_node(context, invocation_states))?, - 83 => listener.exit_elvis_expression(&ElvisExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 84 => listener.exit_elvis(&ElvisContext::::__from_validated_listener_node(context, invocation_states))?, - 85 => listener.exit_infix_function_call(&InfixFunctionCallContext::::__from_validated_listener_node(context, invocation_states))?, - 86 => listener.exit_range_expression(&RangeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 87 => listener.exit_additive_expression(&AdditiveExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 88 => listener.exit_multiplicative_expression(&MultiplicativeExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 89 => listener.exit_as_expression(&AsExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 90 => listener.exit_prefix_unary_expression(&PrefixUnaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 91 => listener.exit_unary_prefix(&UnaryPrefixContext::::__from_validated_listener_node(context, invocation_states))?, - 92 => listener.exit_postfix_unary_expression(&PostfixUnaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 93 => listener.exit_postfix_unary_suffix(&PostfixUnarySuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 94 => listener.exit_directly_assignable_expression(&DirectlyAssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 95 => listener.exit_parenthesized_directly_assignable_expression(&ParenthesizedDirectlyAssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 96 => listener.exit_assignable_expression(&AssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 97 => listener.exit_parenthesized_assignable_expression(&ParenthesizedAssignableExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 98 => listener.exit_assignable_suffix(&AssignableSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 99 => listener.exit_indexing_suffix(&IndexingSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 100 => listener.exit_navigation_suffix(&NavigationSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 101 => listener.exit_call_suffix(&CallSuffixContext::::__from_validated_listener_node(context, invocation_states))?, - 102 => listener.exit_annotated_lambda(&AnnotatedLambdaContext::::__from_validated_listener_node(context, invocation_states))?, - 103 => listener.exit_type_arguments(&TypeArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 104 => listener.exit_value_arguments(&ValueArgumentsContext::::__from_validated_listener_node(context, invocation_states))?, - 105 => listener.exit_value_argument(&ValueArgumentContext::::__from_validated_listener_node(context, invocation_states))?, - 106 => listener.exit_primary_expression(&PrimaryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 107 => listener.exit_parenthesized_expression(&ParenthesizedExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 108 => listener.exit_collection_literal(&CollectionLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 109 => listener.exit_literal_constant(&LiteralConstantContext::::__from_validated_listener_node(context, invocation_states))?, - 110 => listener.exit_string_literal(&StringLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 111 => listener.exit_line_string_literal(&LineStringLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 112 => listener.exit_multi_line_string_literal(&MultiLineStringLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 113 => listener.exit_line_string_content(&LineStringContentContext::::__from_validated_listener_node(context, invocation_states))?, - 114 => listener.exit_line_string_expression(&LineStringExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 115 => listener.exit_multi_line_string_content(&MultiLineStringContentContext::::__from_validated_listener_node(context, invocation_states))?, - 116 => listener.exit_multi_line_string_expression(&MultiLineStringExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 117 => listener.exit_lambda_literal(&LambdaLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 118 => listener.exit_lambda_parameters(&LambdaParametersContext::::__from_validated_listener_node(context, invocation_states))?, - 119 => listener.exit_lambda_parameter(&LambdaParameterContext::::__from_validated_listener_node(context, invocation_states))?, - 120 => listener.exit_anonymous_function(&AnonymousFunctionContext::::__from_validated_listener_node(context, invocation_states))?, - 121 => listener.exit_function_literal(&FunctionLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 122 => listener.exit_object_literal(&ObjectLiteralContext::::__from_validated_listener_node(context, invocation_states))?, - 123 => listener.exit_this_expression(&ThisExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 124 => listener.exit_super_expression(&SuperExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 125 => listener.exit_if_expression(&IfExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 126 => listener.exit_when_subject(&WhenSubjectContext::::__from_validated_listener_node(context, invocation_states))?, - 127 => listener.exit_when_expression(&WhenExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 128 => listener.exit_when_entry(&WhenEntryContext::::__from_validated_listener_node(context, invocation_states))?, - 129 => listener.exit_when_condition(&WhenConditionContext::::__from_validated_listener_node(context, invocation_states))?, - 130 => listener.exit_range_test(&RangeTestContext::::__from_validated_listener_node(context, invocation_states))?, - 131 => listener.exit_type_test(&TypeTestContext::::__from_validated_listener_node(context, invocation_states))?, - 132 => listener.exit_try_expression(&TryExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 133 => listener.exit_catch_block(&CatchBlockContext::::__from_validated_listener_node(context, invocation_states))?, - 134 => listener.exit_finally_block(&FinallyBlockContext::::__from_validated_listener_node(context, invocation_states))?, - 135 => listener.exit_jump_expression(&JumpExpressionContext::::__from_validated_listener_node(context, invocation_states))?, - 136 => listener.exit_callable_reference(&CallableReferenceContext::::__from_validated_listener_node(context, invocation_states))?, - 137 => listener.exit_assignment_and_operator(&AssignmentAndOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 138 => listener.exit_equality_operator(&EqualityOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 139 => listener.exit_comparison_operator(&ComparisonOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 140 => listener.exit_in_operator(&InOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 141 => listener.exit_is_operator(&IsOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 142 => listener.exit_additive_operator(&AdditiveOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 143 => listener.exit_multiplicative_operator(&MultiplicativeOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 144 => listener.exit_as_operator(&AsOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 145 => listener.exit_prefix_unary_operator(&PrefixUnaryOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 146 => listener.exit_postfix_unary_operator(&PostfixUnaryOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 147 => listener.exit_excl(&ExclContext::::__from_validated_listener_node(context, invocation_states))?, - 148 => listener.exit_member_access_operator(&MemberAccessOperatorContext::::__from_validated_listener_node(context, invocation_states))?, - 149 => listener.exit_safe_nav(&SafeNavContext::::__from_validated_listener_node(context, invocation_states))?, - 150 => listener.exit_modifiers(&ModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 151 => listener.exit_parameter_modifiers(&ParameterModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 152 => listener.exit_modifier(&ModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 153 => listener.exit_type_modifiers(&TypeModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 154 => listener.exit_type_modifier(&TypeModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 155 => listener.exit_class_modifier(&ClassModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 156 => listener.exit_member_modifier(&MemberModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 157 => listener.exit_visibility_modifier(&VisibilityModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 158 => listener.exit_variance_modifier(&VarianceModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 159 => listener.exit_type_parameter_modifiers(&TypeParameterModifiersContext::::__from_validated_listener_node(context, invocation_states))?, - 160 => listener.exit_type_parameter_modifier(&TypeParameterModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 161 => listener.exit_function_modifier(&FunctionModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 162 => listener.exit_property_modifier(&PropertyModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 163 => listener.exit_inheritance_modifier(&InheritanceModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 164 => listener.exit_parameter_modifier(&ParameterModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 165 => listener.exit_reification_modifier(&ReificationModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 166 => listener.exit_platform_modifier(&PlatformModifierContext::::__from_validated_listener_node(context, invocation_states))?, - 167 => listener.exit_annotation(&AnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 168 => listener.exit_single_annotation(&SingleAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 169 => listener.exit_multi_annotation(&MultiAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 170 => listener.exit_annotation_use_site_target(&AnnotationUseSiteTargetContext::::__from_validated_listener_node(context, invocation_states))?, - 171 => listener.exit_unescaped_annotation(&UnescapedAnnotationContext::::__from_validated_listener_node(context, invocation_states))?, - 172 => listener.exit_simple_identifier(&SimpleIdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - 173 => listener.exit_identifier(&IdentifierContext::::__from_validated_listener_node(context, invocation_states))?, - _ => {} - } - listener.exit_every_rule(ValidatedRuleNode::__new(context)) - }, - terminal: |listener, node| { - listener.visit_terminal(&TerminalNode::new(node)) - }, - error: |_listener, _node| { - unreachable!("validated parse tree contains an error node") - }, -} - -#[allow(dead_code)] -pub struct KotlinValidatedTreeWalker; - -#[allow(dead_code)] -impl KotlinValidatedTreeWalker { - pub fn walk>( - listener: &mut T, - tree: ValidatedRuleNode<'_>, - ) -> Result<(), E> { - Self::__walk(listener, tree.node(), None) - } - - pub fn walk_with_invocation_states>( - listener: &mut T, - tree: ValidatedRuleNode<'_>, - parent_invocation_states: Vec, - ) -> Result<(), E> { - Self::__walk(listener, tree.node(), Some(parent_invocation_states)) - } - - fn __walk>( - listener: &mut T, - tree: antlr4_runtime::Node<'_>, - invocation_states: Option>, - ) -> Result<(), E> { - let mut callbacks = __KotlinValidatedTreeWalkerCallbacks(listener); - antlr4_runtime::generated::walk_generated(tree, invocation_states, &mut callbacks) - } -} - -pub type ValidatedParseTreeWalker = KotlinValidatedTreeWalker; - - - -static PARSER_ATN_DATA: &[u32] = &[1346458702, 3, 16909060, 29, 173, 3520, 4350, 31, 48, 542, 174, 29, 24640, 24669, 21750, 46419, 155, 46574, 96, 46768, 542, 47310, 174, 47484, 174, 47658, 49, 46670, 98, 2, 0, 8, 0, 1, 4294967295, 4294967295, 7, 0, 16, 1, 0, 4294967295, 4294967295, 2, 1, 8, 1, 1, 4294967295, 4294967295, 7, 1, 16, 2, 0, 4294967295, 4294967295, 2, 2, 8, 2, 1, 4294967295, 4294967295, 7, 2, 24, 3, 2, 4294967295, 4294967295, 2, 3, 8, 5, 1, 4294967295, 4294967295, 7, 3, 24, 6, 2, 4294967295, 4294967295, 2, 4, 8, 8, 1, 4294967295, 4294967295, 7, 4, 24, 9, 2, 4294967295, 4294967295, 2, 5, 8, 11, 1, 4294967295, 4294967295, 7, 5, 24, 12, 2, 4294967295, 4294967295, 2, 6, 8, 14, 1, 4294967295, 4294967295, 7, 6, 24, 15, 1, 4294967295, 4294967295, 2, 7, 8, 16, 1, 4294967295, 4294967295, 7, 7, 24, 17, 1, 4294967295, 4294967295, 2, 8, 8, 18, 1, 4294967295, 4294967295, 7, 8, 24, 19, 1, 4294967295, 4294967295, 2, 9, 8, 20, 1, 4294967295, 4294967295, 7, 9, 24, 21, 1, 4294967295, 4294967295, 2, 10, 8, 22, 1, 4294967295, 4294967295, 7, 10, 24, 23, 3, 4294967295, 4294967295, 2, 11, 8, 26, 1, 4294967295, 4294967295, 7, 11, 24, 27, 1, 4294967295, 4294967295, 2, 12, 8, 28, 1, 4294967295, 4294967295, 7, 12, 24, 29, 1, 4294967295, 4294967295, 2, 13, 8, 30, 1, 4294967295, 4294967295, 7, 13, 24, 31, 5, 4294967295, 4294967295, 2, 14, 8, 36, 1, 4294967295, 4294967295, 7, 14, 24, 37, 1, 4294967295, 4294967295, 2, 15, 8, 38, 1, 4294967295, 4294967295, 7, 15, 24, 39, 2, 4294967295, 4294967295, 2, 16, 8, 41, 1, 4294967295, 4294967295, 7, 16, 24, 42, 4, 4294967295, 4294967295, 2, 17, 8, 46, 1, 4294967295, 4294967295, 7, 17, 24, 47, 1, 4294967295, 4294967295, 2, 18, 8, 48, 1, 4294967295, 4294967295, 7, 18, 24, 49, 2, 4294967295, 4294967295, 2, 19, 8, 51, 1, 4294967295, 4294967295, 7, 19, 24, 52, 2, 4294967295, 4294967295, 2, 20, 8, 54, 1, 4294967295, 4294967295, 7, 20, 24, 55, 1, 4294967295, 4294967295, 2, 21, 8, 56, 1, 4294967295, 4294967295, 7, 21, 24, 57, 4, 4294967295, 4294967295, 2, 22, 8, 61, 1, 4294967295, 4294967295, 7, 22, 24, 62, 2, 4294967295, 4294967295, 2, 23, 8, 64, 1, 4294967295, 4294967295, 7, 23, 24, 65, 4, 4294967295, 4294967295, 2, 24, 8, 69, 1, 4294967295, 4294967295, 7, 24, 24, 70, 2, 4294967295, 4294967295, 2, 25, 8, 72, 1, 4294967295, 4294967295, 7, 25, 24, 73, 2, 4294967295, 4294967295, 2, 26, 8, 75, 1, 4294967295, 4294967295, 7, 26, 24, 76, 1, 4294967295, 4294967295, 2, 27, 8, 77, 1, 4294967295, 4294967295, 7, 27, 24, 78, 1, 4294967295, 4294967295, 2, 28, 8, 79, 1, 4294967295, 4294967295, 7, 28, 24, 80, 1, 4294967295, 4294967295, 2, 29, 8, 81, 1, 4294967295, 4294967295, 7, 29, 24, 82, 2, 4294967295, 4294967295, 2, 30, 8, 84, 1, 4294967295, 4294967295, 7, 30, 24, 85, 2, 4294967295, 4294967295, 2, 31, 8, 87, 1, 4294967295, 4294967295, 7, 31, 24, 88, 1, 4294967295, 4294967295, 2, 32, 8, 89, 1, 4294967295, 4294967295, 7, 32, 24, 90, 4, 4294967295, 4294967295, 2, 33, 8, 94, 1, 4294967295, 4294967295, 7, 33, 24, 95, 6, 4294967295, 4294967295, 2, 34, 8, 101, 1, 4294967295, 4294967295, 7, 34, 24, 102, 3, 4294967295, 4294967295, 2, 35, 8, 105, 1, 4294967295, 4294967295, 7, 35, 24, 106, 1, 4294967295, 4294967295, 2, 36, 8, 107, 1, 4294967295, 4294967295, 7, 36, 24, 108, 1, 4294967295, 4294967295, 2, 37, 8, 109, 1, 4294967295, 4294967295, 7, 37, 24, 110, 2, 4294967295, 4294967295, 2, 38, 8, 112, 1, 4294967295, 4294967295, 7, 38, 24, 113, 2, 4294967295, 4294967295, 2, 39, 8, 115, 1, 4294967295, 4294967295, 7, 39, 24, 116, 1, 4294967295, 4294967295, 2, 40, 8, 117, 1, 4294967295, 4294967295, 7, 40, 24, 118, 3, 4294967295, 4294967295, 2, 41, 8, 121, 1, 4294967295, 4294967295, 7, 41, 24, 122, 1, 4294967295, 4294967295, 2, 42, 8, 123, 1, 4294967295, 4294967295, 7, 42, 24, 124, 3, 4294967295, 4294967295, 2, 43, 8, 127, 1, 4294967295, 4294967295, 7, 43, 24, 128, 1, 4294967295, 4294967295, 2, 44, 8, 129, 1, 4294967295, 4294967295, 7, 44, 24, 130, 1, 4294967295, 4294967295, 2, 45, 8, 131, 1, 4294967295, 4294967295, 7, 45, 24, 132, 1, 4294967295, 4294967295, 2, 46, 8, 133, 1, 4294967295, 4294967295, 7, 46, 24, 134, 1, 4294967295, 4294967295, 2, 47, 8, 135, 1, 4294967295, 4294967295, 7, 47, 24, 136, 1, 4294967295, 4294967295, 2, 48, 8, 137, 1, 4294967295, 4294967295, 7, 48, 24, 138, 2, 4294967295, 4294967295, 2, 49, 8, 140, 1, 4294967295, 4294967295, 7, 49, 24, 141, 23, 4294967295, 4294967295, 2, 50, 8, 164, 1, 4294967295, 4294967295, 7, 50, 24, 165, 3, 4294967295, 4294967295, 2, 51, 8, 168, 1, 4294967295, 4294967295, 7, 51, 24, 169, 2, 4294967295, 4294967295, 2, 52, 8, 171, 1, 4294967295, 4294967295, 7, 52, 24, 172, 1, 4294967295, 4294967295, 2, 53, 8, 173, 1, 4294967295, 4294967295, 7, 53, 24, 174, 8, 4294967295, 4294967295, 2, 54, 8, 182, 1, 4294967295, 4294967295, 7, 54, 24, 183, 2, 4294967295, 4294967295, 2, 55, 8, 185, 1, 4294967295, 4294967295, 7, 55, 24, 186, 2, 4294967295, 4294967295, 2, 56, 8, 188, 1, 4294967295, 4294967295, 7, 56, 24, 189, 1, 4294967295, 4294967295, 2, 57, 8, 190, 1, 4294967295, 4294967295, 7, 57, 24, 191, 1, 4294967295, 4294967295, 2, 58, 8, 192, 1, 4294967295, 4294967295, 7, 58, 24, 193, 3, 4294967295, 4294967295, 2, 59, 8, 196, 1, 4294967295, 4294967295, 7, 59, 24, 197, 1, 4294967295, 4294967295, 2, 60, 8, 198, 1, 4294967295, 4294967295, 7, 60, 24, 199, 3, 4294967295, 4294967295, 2, 61, 8, 202, 1, 4294967295, 4294967295, 7, 61, 24, 203, 4, 4294967295, 4294967295, 2, 62, 8, 207, 1, 4294967295, 4294967295, 7, 62, 24, 208, 3, 4294967295, 4294967295, 2, 63, 8, 211, 1, 4294967295, 4294967295, 7, 63, 24, 212, 1, 4294967295, 4294967295, 2, 64, 8, 213, 1, 4294967295, 4294967295, 7, 64, 24, 214, 2, 4294967295, 4294967295, 2, 65, 8, 216, 1, 4294967295, 4294967295, 7, 65, 24, 217, 4, 4294967295, 4294967295, 2, 66, 8, 221, 1, 4294967295, 4294967295, 7, 66, 24, 222, 3, 4294967295, 4294967295, 2, 67, 8, 225, 1, 4294967295, 4294967295, 7, 67, 24, 226, 8, 4294967295, 4294967295, 2, 68, 8, 234, 1, 4294967295, 4294967295, 7, 68, 24, 235, 7, 4294967295, 4294967295, 2, 69, 8, 242, 1, 4294967295, 4294967295, 7, 69, 24, 243, 1, 4294967295, 4294967295, 2, 70, 8, 244, 1, 4294967295, 4294967295, 7, 70, 24, 245, 1, 4294967295, 4294967295, 2, 71, 8, 246, 1, 4294967295, 4294967295, 7, 71, 24, 247, 1, 4294967295, 4294967295, 2, 72, 8, 248, 1, 4294967295, 4294967295, 7, 72, 24, 249, 1, 4294967295, 4294967295, 2, 73, 8, 250, 1, 4294967295, 4294967295, 7, 73, 24, 251, 1, 4294967295, 4294967295, 2, 74, 8, 252, 1, 4294967295, 4294967295, 7, 74, 24, 253, 7, 4294967295, 4294967295, 2, 75, 8, 260, 1, 4294967295, 4294967295, 7, 75, 24, 261, 4, 4294967295, 4294967295, 2, 76, 8, 265, 1, 4294967295, 4294967295, 7, 76, 24, 266, 26, 4294967295, 4294967295, 2, 77, 8, 292, 1, 4294967295, 4294967295, 7, 77, 24, 293, 1, 4294967295, 4294967295, 2, 78, 8, 294, 1, 4294967295, 4294967295, 7, 78, 24, 295, 2, 4294967295, 4294967295, 2, 79, 8, 297, 1, 4294967295, 4294967295, 7, 79, 24, 298, 2, 4294967295, 4294967295, 2, 80, 8, 300, 1, 4294967295, 4294967295, 7, 80, 24, 301, 2, 4294967295, 4294967295, 2, 81, 8, 303, 1, 4294967295, 4294967295, 7, 81, 24, 304, 2, 4294967295, 4294967295, 2, 82, 8, 306, 1, 4294967295, 4294967295, 7, 82, 24, 307, 1, 4294967295, 4294967295, 2, 83, 8, 308, 1, 4294967295, 4294967295, 7, 83, 24, 309, 2, 4294967295, 4294967295, 2, 84, 8, 311, 1, 4294967295, 4294967295, 7, 84, 24, 312, 1, 4294967295, 4294967295, 2, 85, 8, 313, 1, 4294967295, 4294967295, 7, 85, 24, 314, 2, 4294967295, 4294967295, 2, 86, 8, 316, 1, 4294967295, 4294967295, 7, 86, 24, 317, 2, 4294967295, 4294967295, 2, 87, 8, 319, 1, 4294967295, 4294967295, 7, 87, 24, 320, 2, 4294967295, 4294967295, 2, 88, 8, 322, 1, 4294967295, 4294967295, 7, 88, 24, 323, 2, 4294967295, 4294967295, 2, 89, 8, 325, 1, 4294967295, 4294967295, 7, 89, 24, 326, 2, 4294967295, 4294967295, 2, 90, 8, 328, 1, 4294967295, 4294967295, 7, 90, 24, 329, 2, 4294967295, 4294967295, 2, 91, 8, 331, 1, 4294967295, 4294967295, 7, 91, 24, 332, 1, 4294967295, 4294967295, 2, 92, 8, 333, 1, 4294967295, 4294967295, 7, 92, 24, 334, 2, 4294967295, 4294967295, 2, 93, 8, 336, 1, 4294967295, 4294967295, 7, 93, 24, 337, 1, 4294967295, 4294967295, 2, 94, 8, 338, 1, 4294967295, 4294967295, 7, 94, 24, 339, 2, 4294967295, 4294967295, 2, 95, 8, 341, 1, 4294967295, 4294967295, 7, 95, 24, 342, 1, 4294967295, 4294967295, 2, 96, 8, 343, 1, 4294967295, 4294967295, 7, 96, 24, 344, 2, 4294967295, 4294967295, 2, 97, 8, 346, 1, 4294967295, 4294967295, 7, 97, 24, 347, 1, 4294967295, 4294967295, 2, 98, 8, 348, 1, 4294967295, 4294967295, 7, 98, 24, 349, 1, 4294967295, 4294967295, 2, 99, 8, 350, 1, 4294967295, 4294967295, 7, 99, 24, 351, 2, 4294967295, 4294967295, 2, 100, 8, 353, 1, 4294967295, 4294967295, 7, 100, 24, 354, 2, 4294967295, 4294967295, 2, 101, 8, 356, 1, 4294967295, 4294967295, 7, 101, 24, 357, 2, 4294967295, 4294967295, 2, 102, 8, 359, 1, 4294967295, 4294967295, 7, 102, 24, 360, 1, 4294967295, 4294967295, 2, 103, 8, 361, 1, 4294967295, 4294967295, 7, 103, 24, 362, 4, 4294967295, 4294967295, 2, 104, 8, 366, 1, 4294967295, 4294967295, 7, 104, 24, 367, 5, 4294967295, 4294967295, 2, 105, 8, 372, 1, 4294967295, 4294967295, 7, 105, 24, 373, 2, 4294967295, 4294967295, 2, 106, 8, 375, 1, 4294967295, 4294967295, 7, 106, 24, 376, 1, 4294967295, 4294967295, 2, 107, 8, 377, 1, 4294967295, 4294967295, 7, 107, 24, 378, 2, 4294967295, 4294967295, 2, 108, 8, 380, 1, 4294967295, 4294967295, 7, 108, 24, 381, 1, 4294967295, 4294967295, 2, 109, 8, 382, 1, 4294967295, 4294967295, 7, 109, 24, 383, 1, 4294967295, 4294967295, 2, 110, 8, 384, 1, 4294967295, 4294967295, 7, 110, 24, 385, 1, 4294967295, 4294967295, 2, 111, 8, 386, 1, 4294967295, 4294967295, 7, 111, 24, 387, 1, 4294967295, 4294967295, 2, 112, 8, 388, 1, 4294967295, 4294967295, 7, 112, 24, 389, 1, 4294967295, 4294967295, 2, 113, 8, 390, 1, 4294967295, 4294967295, 7, 113, 24, 391, 1, 4294967295, 4294967295, 2, 114, 8, 392, 1, 4294967295, 4294967295, 7, 114, 24, 393, 1, 4294967295, 4294967295, 2, 115, 8, 394, 1, 4294967295, 4294967295, 7, 115, 24, 395, 1, 4294967295, 4294967295, 2, 116, 8, 396, 1, 4294967295, 4294967295, 7, 116, 24, 397, 1, 4294967295, 4294967295, 2, 117, 8, 398, 1, 4294967295, 4294967295, 7, 117, 24, 399, 2, 4294967295, 4294967295, 2, 118, 8, 401, 1, 4294967295, 4294967295, 7, 118, 24, 402, 1, 4294967295, 4294967295, 2, 119, 8, 403, 1, 4294967295, 4294967295, 7, 119, 24, 404, 2, 4294967295, 4294967295, 2, 120, 8, 406, 1, 4294967295, 4294967295, 7, 120, 24, 407, 1, 4294967295, 4294967295, 2, 121, 8, 408, 1, 4294967295, 4294967295, 7, 121, 24, 409, 1, 4294967295, 4294967295, 2, 122, 8, 410, 1, 4294967295, 4294967295, 7, 122, 24, 411, 1, 4294967295, 4294967295, 2, 123, 8, 412, 1, 4294967295, 4294967295, 7, 123, 24, 413, 1, 4294967295, 4294967295, 2, 124, 8, 414, 1, 4294967295, 4294967295, 7, 124, 24, 415, 1, 4294967295, 4294967295, 2, 125, 8, 416, 1, 4294967295, 4294967295, 7, 125, 24, 417, 1, 4294967295, 4294967295, 2, 126, 8, 418, 1, 4294967295, 4294967295, 7, 126, 24, 419, 1, 4294967295, 4294967295, 2, 127, 8, 420, 1, 4294967295, 4294967295, 7, 127, 24, 421, 1, 4294967295, 4294967295, 2, 128, 8, 422, 1, 4294967295, 4294967295, 7, 128, 24, 423, 1, 4294967295, 4294967295, 2, 129, 8, 424, 1, 4294967295, 4294967295, 7, 129, 24, 425, 2, 4294967295, 4294967295, 2, 130, 8, 427, 1, 4294967295, 4294967295, 7, 130, 24, 428, 1, 4294967295, 4294967295, 2, 131, 8, 429, 1, 4294967295, 4294967295, 7, 131, 24, 430, 1, 4294967295, 4294967295, 2, 132, 8, 431, 1, 4294967295, 4294967295, 7, 132, 24, 432, 1, 4294967295, 4294967295, 2, 133, 8, 433, 1, 4294967295, 4294967295, 7, 133, 24, 434, 1, 4294967295, 4294967295, 2, 134, 8, 435, 1, 4294967295, 4294967295, 7, 134, 24, 436, 2, 4294967295, 4294967295, 2, 135, 8, 438, 1, 4294967295, 4294967295, 7, 135, 24, 439, 1, 4294967295, 4294967295, 2, 136, 8, 440, 1, 4294967295, 4294967295, 7, 136, 24, 441, 1, 4294967295, 4294967295, 2, 137, 8, 442, 1, 4294967295, 4294967295, 7, 137, 24, 443, 1, 4294967295, 4294967295, 2, 138, 8, 444, 1, 4294967295, 4294967295, 7, 138, 24, 445, 1, 4294967295, 4294967295, 2, 139, 8, 446, 1, 4294967295, 4294967295, 7, 139, 24, 447, 1, 4294967295, 4294967295, 2, 140, 8, 448, 1, 4294967295, 4294967295, 7, 140, 24, 449, 2, 4294967295, 4294967295, 2, 141, 8, 451, 1, 4294967295, 4294967295, 7, 141, 24, 452, 2, 4294967295, 4294967295, 2, 142, 8, 454, 1, 4294967295, 4294967295, 7, 142, 24, 455, 1, 4294967295, 4294967295, 2, 143, 8, 456, 1, 4294967295, 4294967295, 7, 143, 24, 457, 1, 4294967295, 4294967295, 2, 144, 8, 458, 1, 4294967295, 4294967295, 7, 144, 24, 459, 1, 4294967295, 4294967295, 2, 145, 8, 460, 1, 4294967295, 4294967295, 7, 145, 24, 461, 1, 4294967295, 4294967295, 2, 146, 8, 462, 1, 4294967295, 4294967295, 7, 146, 24, 463, 1, 4294967295, 4294967295, 2, 147, 8, 464, 1, 4294967295, 4294967295, 7, 147, 24, 465, 2, 4294967295, 4294967295, 2, 148, 8, 467, 1, 4294967295, 4294967295, 7, 148, 24, 468, 1, 4294967295, 4294967295, 2, 149, 8, 469, 1, 4294967295, 4294967295, 7, 149, 24, 470, 1, 4294967295, 4294967295, 2, 150, 8, 471, 1, 4294967295, 4294967295, 7, 150, 24, 472, 12, 4294967295, 4294967295, 2, 151, 8, 484, 1, 4294967295, 4294967295, 7, 151, 24, 485, 2, 4294967295, 4294967295, 2, 152, 8, 487, 1, 4294967295, 4294967295, 7, 152, 24, 488, 1, 4294967295, 4294967295, 2, 153, 8, 489, 1, 4294967295, 4294967295, 7, 153, 24, 490, 4, 4294967295, 4294967295, 2, 154, 8, 494, 1, 4294967295, 4294967295, 7, 154, 24, 495, 1, 4294967295, 4294967295, 2, 155, 8, 496, 1, 4294967295, 4294967295, 7, 155, 24, 497, 1, 4294967295, 4294967295, 2, 156, 8, 498, 1, 4294967295, 4294967295, 7, 156, 24, 499, 1, 4294967295, 4294967295, 2, 157, 8, 500, 1, 4294967295, 4294967295, 7, 157, 24, 501, 1, 4294967295, 4294967295, 2, 158, 8, 502, 1, 4294967295, 4294967295, 7, 158, 24, 503, 2, 4294967295, 4294967295, 2, 159, 8, 505, 1, 4294967295, 4294967295, 7, 159, 24, 506, 1, 4294967295, 4294967295, 2, 160, 8, 507, 1, 4294967295, 4294967295, 7, 160, 24, 508, 1, 4294967295, 4294967295, 2, 161, 8, 509, 1, 4294967295, 4294967295, 7, 161, 24, 510, 1, 4294967295, 4294967295, 2, 162, 8, 511, 1, 4294967295, 4294967295, 7, 162, 24, 512, 1, 4294967295, 4294967295, 2, 163, 8, 513, 1, 4294967295, 4294967295, 7, 163, 24, 514, 1, 4294967295, 4294967295, 2, 164, 8, 515, 1, 4294967295, 4294967295, 7, 164, 24, 516, 2, 4294967295, 4294967295, 2, 165, 8, 518, 1, 4294967295, 4294967295, 7, 165, 24, 519, 1, 4294967295, 4294967295, 2, 166, 8, 520, 1, 4294967295, 4294967295, 7, 166, 24, 521, 1, 4294967295, 4294967295, 2, 167, 8, 522, 1, 4294967295, 4294967295, 7, 167, 24, 523, 15, 4294967295, 4294967295, 2, 168, 8, 538, 1, 4294967295, 4294967295, 7, 168, 24, 539, 1, 4294967295, 4294967295, 2, 169, 8, 540, 1, 4294967295, 4294967295, 7, 169, 24, 541, 1, 4294967295, 4294967295, 2, 170, 8, 542, 1, 4294967295, 4294967295, 7, 170, 24, 543, 2, 4294967295, 4294967295, 2, 171, 8, 545, 1, 4294967295, 4294967295, 7, 171, 24, 546, 4, 4294967295, 4294967295, 2, 172, 8, 550, 1, 4294967295, 4294967295, 7, 172, 24, 551, 25, 4294967295, 4294967295, 2, 173, 8, 576, 1, 4294967295, 4294967295, 7, 173, 24, 577, 2, 4294967295, 4294967295, 1, 0, 8, 579, 1, 4294967295, 4294967295, 3, 0, 8, 580, 2, 350, 4294967295, 8, 0, 8, 582, 1, 4294967295, 4294967295, 1, 0, 32, 583, 1, 4294967295, 4294967295, 5, 0, 8, 584, 1, 353, 4294967295, 8, 0, 8, 585, 1, 4294967295, 4294967295, 10, 0, 8, 586, 2, 4294967295, 4294967295, 12, 0, 8, 588, 1, 4294967295, 356, 9, 0, 8, 589, 1, 4294967295, 4294967295, 1, 0, 8, 590, 1, 4294967295, 4294967295, 5, 0, 8, 591, 1, 359, 4294967295, 8, 0, 8, 592, 1, 4294967295, 4294967295, 10, 0, 8, 593, 2, 4294967295, 4294967295, 12, 0, 8, 595, 1, 4294967295, 362, 9, 0, 8, 596, 1, 4294967295, 4294967295, 1, 0, 8, 597, 1, 4294967295, 4294967295, 1, 0, 8, 598, 1, 4294967295, 4294967295, 1, 0, 8, 599, 1, 4294967295, 4294967295, 5, 0, 8, 600, 1, 367, 4294967295, 8, 0, 8, 601, 1, 4294967295, 4294967295, 10, 0, 8, 602, 2, 4294967295, 4294967295, 12, 0, 8, 604, 1, 4294967295, 370, 9, 0, 8, 605, 1, 4294967295, 4294967295, 1, 0, 32, 606, 1, 4294967295, 4294967295, 1, 0, 8, 607, 1, 4294967295, 4294967295, 1, 1, 8, 608, 1, 4294967295, 4294967295, 3, 1, 8, 609, 2, 375, 4294967295, 8, 1, 8, 611, 1, 4294967295, 4294967295, 1, 1, 32, 612, 1, 4294967295, 4294967295, 5, 1, 8, 613, 1, 378, 4294967295, 8, 1, 8, 614, 1, 4294967295, 4294967295, 10, 1, 8, 615, 2, 4294967295, 4294967295, 12, 1, 8, 617, 1, 4294967295, 381, 9, 1, 8, 618, 1, 4294967295, 4294967295, 1, 1, 8, 619, 1, 4294967295, 4294967295, 5, 1, 8, 620, 1, 384, 4294967295, 8, 1, 8, 621, 1, 4294967295, 4294967295, 10, 1, 8, 622, 2, 4294967295, 4294967295, 12, 1, 8, 624, 1, 4294967295, 387, 9, 1, 8, 625, 1, 4294967295, 4294967295, 1, 1, 8, 626, 1, 4294967295, 4294967295, 1, 1, 8, 627, 1, 4294967295, 4294967295, 1, 1, 8, 628, 1, 4294967295, 4294967295, 1, 1, 8, 629, 1, 4294967295, 4294967295, 1, 1, 8, 630, 1, 4294967295, 4294967295, 5, 1, 8, 631, 1, 394, 4294967295, 8, 1, 8, 632, 1, 4294967295, 4294967295, 10, 1, 8, 633, 2, 4294967295, 4294967295, 12, 1, 8, 635, 1, 4294967295, 397, 9, 1, 8, 636, 1, 4294967295, 4294967295, 1, 1, 32, 637, 1, 4294967295, 4294967295, 1, 1, 8, 638, 1, 4294967295, 4294967295, 1, 2, 32, 639, 1, 4294967295, 4294967295, 1, 2, 32, 640, 1, 4294967295, 4294967295, 4, 2, 8, 641, 1, 403, 4294967295, 8, 2, 8, 642, 1, 4294967295, 4294967295, 11, 2, 8, 643, 2, 4294967295, 4294967295, 12, 2, 8, 645, 1, 4294967295, 404, 1, 3, 32, 646, 1, 4294967295, 4294967295, 1, 3, 32, 647, 1, 4294967295, 4294967295, 1, 3, 32, 648, 1, 4294967295, 4294967295, 5, 3, 8, 649, 1, 410, 4294967295, 8, 3, 8, 650, 1, 4294967295, 4294967295, 10, 3, 8, 651, 2, 4294967295, 4294967295, 12, 3, 8, 653, 1, 4294967295, 413, 9, 3, 8, 654, 1, 4294967295, 4294967295, 1, 3, 32, 655, 1, 4294967295, 4294967295, 1, 3, 32, 656, 1, 4294967295, 4294967295, 5, 3, 8, 657, 1, 417, 4294967295, 8, 3, 8, 658, 1, 4294967295, 4294967295, 10, 3, 8, 659, 2, 4294967295, 4294967295, 12, 3, 8, 661, 1, 4294967295, 420, 9, 3, 8, 662, 1, 4294967295, 4294967295, 1, 3, 32, 663, 1, 4294967295, 4294967295, 1, 3, 8, 664, 1, 4294967295, 4294967295, 4, 3, 8, 665, 1, 424, 4294967295, 8, 3, 8, 666, 1, 4294967295, 4294967295, 11, 3, 8, 667, 2, 4294967295, 4294967295, 12, 3, 8, 669, 1, 4294967295, 425, 1, 3, 32, 670, 1, 4294967295, 4294967295, 1, 3, 8, 671, 1, 4294967295, 4294967295, 1, 3, 8, 672, 1, 4294967295, 4294967295, 3, 3, 8, 673, 2, 431, 4294967295, 8, 3, 8, 675, 1, 4294967295, 4294967295, 1, 3, 32, 676, 1, 4294967295, 4294967295, 5, 3, 8, 677, 1, 434, 4294967295, 8, 3, 8, 678, 1, 4294967295, 4294967295, 10, 3, 8, 679, 2, 4294967295, 4294967295, 12, 3, 8, 681, 1, 4294967295, 437, 9, 3, 8, 682, 1, 4294967295, 4294967295, 1, 4, 32, 683, 1, 4294967295, 4294967295, 1, 4, 8, 684, 1, 4294967295, 4294967295, 1, 4, 8, 685, 1, 4294967295, 4294967295, 3, 4, 8, 686, 2, 442, 4294967295, 8, 4, 8, 688, 1, 4294967295, 4294967295, 3, 4, 8, 689, 2, 444, 4294967295, 8, 4, 8, 691, 1, 4294967295, 4294967295, 1, 5, 8, 692, 1, 4294967295, 4294967295, 5, 5, 8, 693, 1, 447, 4294967295, 8, 5, 8, 694, 1, 4294967295, 4294967295, 10, 5, 8, 695, 2, 4294967295, 4294967295, 12, 5, 8, 697, 1, 4294967295, 450, 9, 5, 8, 698, 1, 4294967295, 4294967295, 1, 6, 32, 699, 1, 4294967295, 4294967295, 1, 6, 8, 700, 1, 4294967295, 4294967295, 1, 6, 32, 701, 1, 4294967295, 4294967295, 1, 6, 32, 702, 1, 4294967295, 4294967295, 1, 6, 8, 703, 1, 4294967295, 4294967295, 3, 6, 8, 704, 3, 457, 4294967295, 8, 6, 8, 707, 1, 4294967295, 4294967295, 1, 6, 8, 708, 1, 4294967295, 4294967295, 3, 6, 8, 709, 2, 460, 4294967295, 8, 6, 8, 711, 1, 4294967295, 4294967295, 1, 7, 32, 712, 1, 4294967295, 4294967295, 1, 7, 8, 713, 1, 4294967295, 4294967295, 1, 7, 8, 714, 1, 4294967295, 4294967295, 1, 8, 8, 715, 1, 4294967295, 4294967295, 1, 8, 8, 716, 1, 4294967295, 4294967295, 3, 8, 8, 717, 2, 467, 4294967295, 8, 8, 8, 719, 1, 4294967295, 4294967295, 1, 9, 8, 720, 1, 4294967295, 4294967295, 3, 9, 8, 721, 2, 470, 4294967295, 8, 9, 8, 723, 1, 4294967295, 4294967295, 1, 9, 32, 724, 1, 4294967295, 4294967295, 1, 9, 32, 725, 1, 4294967295, 4294967295, 5, 9, 8, 726, 1, 474, 4294967295, 8, 9, 8, 727, 1, 4294967295, 4294967295, 10, 9, 8, 728, 2, 4294967295, 4294967295, 12, 9, 8, 730, 1, 4294967295, 477, 9, 9, 8, 731, 1, 4294967295, 4294967295, 1, 9, 8, 732, 1, 4294967295, 4294967295, 1, 9, 32, 733, 1, 4294967295, 4294967295, 5, 9, 8, 734, 1, 481, 4294967295, 8, 9, 8, 735, 1, 4294967295, 4294967295, 10, 9, 8, 736, 2, 4294967295, 4294967295, 12, 9, 8, 738, 1, 4294967295, 484, 9, 9, 8, 739, 1, 4294967295, 4294967295, 1, 9, 8, 740, 1, 4294967295, 4294967295, 3, 9, 8, 741, 2, 487, 4294967295, 8, 9, 8, 743, 1, 4294967295, 4294967295, 1, 9, 32, 744, 1, 4294967295, 4294967295, 5, 9, 8, 745, 1, 490, 4294967295, 8, 9, 8, 746, 1, 4294967295, 4294967295, 10, 9, 8, 747, 2, 4294967295, 4294967295, 12, 9, 8, 749, 1, 4294967295, 493, 9, 9, 8, 750, 1, 4294967295, 4294967295, 1, 9, 32, 751, 1, 4294967295, 4294967295, 1, 9, 32, 752, 1, 4294967295, 4294967295, 5, 9, 8, 753, 1, 497, 4294967295, 8, 9, 8, 754, 1, 4294967295, 4294967295, 10, 9, 8, 755, 2, 4294967295, 4294967295, 12, 9, 8, 757, 1, 4294967295, 500, 9, 9, 8, 758, 1, 4294967295, 4294967295, 1, 9, 8, 759, 1, 4294967295, 4294967295, 1, 9, 8, 760, 1, 4294967295, 4294967295, 1, 10, 8, 761, 1, 4294967295, 4294967295, 1, 10, 8, 762, 1, 4294967295, 4294967295, 1, 10, 8, 763, 1, 4294967295, 4294967295, 1, 10, 8, 764, 1, 4294967295, 4294967295, 1, 10, 8, 765, 1, 4294967295, 4294967295, 3, 10, 8, 766, 5, 509, 4294967295, 8, 10, 8, 771, 1, 4294967295, 4294967295, 1, 11, 8, 772, 1, 4294967295, 4294967295, 3, 11, 8, 773, 2, 512, 4294967295, 8, 11, 8, 775, 1, 4294967295, 4294967295, 1, 11, 32, 776, 1, 4294967295, 4294967295, 1, 11, 32, 777, 1, 4294967295, 4294967295, 1, 11, 32, 778, 1, 4294967295, 4294967295, 5, 11, 8, 779, 1, 517, 4294967295, 8, 11, 8, 780, 1, 4294967295, 4294967295, 10, 11, 8, 781, 2, 4294967295, 4294967295, 12, 11, 8, 783, 1, 4294967295, 520, 9, 11, 8, 784, 1, 4294967295, 4294967295, 3, 11, 8, 785, 2, 522, 4294967295, 8, 11, 8, 787, 1, 4294967295, 4294967295, 1, 11, 32, 788, 1, 4294967295, 4294967295, 3, 11, 8, 789, 2, 525, 4294967295, 8, 11, 8, 791, 1, 4294967295, 4294967295, 1, 11, 32, 792, 1, 4294967295, 4294967295, 5, 11, 8, 793, 1, 528, 4294967295, 8, 11, 8, 794, 1, 4294967295, 4294967295, 10, 11, 8, 795, 2, 4294967295, 4294967295, 12, 11, 8, 797, 1, 4294967295, 531, 9, 11, 8, 798, 1, 4294967295, 4294967295, 1, 11, 8, 799, 1, 4294967295, 4294967295, 1, 11, 32, 800, 1, 4294967295, 4294967295, 5, 11, 8, 801, 1, 535, 4294967295, 8, 11, 8, 802, 1, 4294967295, 4294967295, 10, 11, 8, 803, 2, 4294967295, 4294967295, 12, 11, 8, 805, 1, 4294967295, 538, 9, 11, 8, 806, 1, 4294967295, 4294967295, 1, 11, 8, 807, 1, 4294967295, 4294967295, 3, 11, 8, 808, 2, 541, 4294967295, 8, 11, 8, 810, 1, 4294967295, 4294967295, 1, 11, 32, 811, 1, 4294967295, 4294967295, 5, 11, 8, 812, 1, 544, 4294967295, 8, 11, 8, 813, 1, 4294967295, 4294967295, 10, 11, 8, 814, 2, 4294967295, 4294967295, 12, 11, 8, 816, 1, 4294967295, 547, 9, 11, 8, 817, 1, 4294967295, 4294967295, 1, 11, 8, 818, 1, 4294967295, 4294967295, 3, 11, 8, 819, 2, 550, 4294967295, 8, 11, 8, 821, 1, 4294967295, 4294967295, 1, 11, 32, 822, 1, 4294967295, 4294967295, 5, 11, 8, 823, 1, 553, 4294967295, 8, 11, 8, 824, 1, 4294967295, 4294967295, 10, 11, 8, 825, 2, 4294967295, 4294967295, 12, 11, 8, 827, 1, 4294967295, 556, 9, 11, 8, 828, 1, 4294967295, 4294967295, 1, 11, 32, 829, 1, 4294967295, 4294967295, 1, 11, 32, 830, 1, 4294967295, 4294967295, 5, 11, 8, 831, 1, 560, 4294967295, 8, 11, 8, 832, 1, 4294967295, 4294967295, 10, 11, 8, 833, 2, 4294967295, 4294967295, 12, 11, 8, 835, 1, 4294967295, 563, 9, 11, 8, 836, 1, 4294967295, 4294967295, 1, 11, 8, 837, 1, 4294967295, 4294967295, 3, 11, 8, 838, 2, 566, 4294967295, 8, 11, 8, 840, 1, 4294967295, 4294967295, 1, 11, 32, 841, 1, 4294967295, 4294967295, 5, 11, 8, 842, 1, 569, 4294967295, 8, 11, 8, 843, 1, 4294967295, 4294967295, 10, 11, 8, 844, 2, 4294967295, 4294967295, 12, 11, 8, 846, 1, 4294967295, 572, 9, 11, 8, 847, 1, 4294967295, 4294967295, 1, 11, 8, 848, 1, 4294967295, 4294967295, 3, 11, 8, 849, 2, 575, 4294967295, 8, 11, 8, 851, 1, 4294967295, 4294967295, 1, 11, 32, 852, 1, 4294967295, 4294967295, 5, 11, 8, 853, 1, 578, 4294967295, 8, 11, 8, 854, 1, 4294967295, 4294967295, 10, 11, 8, 855, 2, 4294967295, 4294967295, 12, 11, 8, 857, 1, 4294967295, 581, 9, 11, 8, 858, 1, 4294967295, 4294967295, 1, 11, 8, 859, 1, 4294967295, 4294967295, 1, 11, 32, 860, 1, 4294967295, 4294967295, 5, 11, 8, 861, 1, 585, 4294967295, 8, 11, 8, 862, 1, 4294967295, 4294967295, 10, 11, 8, 863, 2, 4294967295, 4294967295, 12, 11, 8, 865, 1, 4294967295, 588, 9, 11, 8, 866, 1, 4294967295, 4294967295, 1, 11, 8, 867, 1, 4294967295, 4294967295, 3, 11, 8, 868, 3, 591, 4294967295, 8, 11, 8, 871, 1, 4294967295, 4294967295, 1, 12, 8, 872, 1, 4294967295, 4294967295, 3, 12, 8, 873, 2, 594, 4294967295, 8, 12, 8, 875, 1, 4294967295, 4294967295, 1, 12, 32, 876, 1, 4294967295, 4294967295, 1, 12, 32, 877, 1, 4294967295, 4294967295, 5, 12, 8, 878, 1, 598, 4294967295, 8, 12, 8, 879, 1, 4294967295, 4294967295, 10, 12, 8, 880, 2, 4294967295, 4294967295, 12, 12, 8, 882, 1, 4294967295, 601, 9, 12, 8, 883, 1, 4294967295, 4294967295, 3, 12, 8, 884, 2, 603, 4294967295, 8, 12, 8, 886, 1, 4294967295, 4294967295, 1, 12, 8, 887, 1, 4294967295, 4294967295, 1, 12, 8, 888, 1, 4294967295, 4294967295, 1, 13, 32, 889, 1, 4294967295, 4294967295, 1, 13, 32, 890, 1, 4294967295, 4294967295, 5, 13, 8, 891, 1, 609, 4294967295, 8, 13, 8, 892, 1, 4294967295, 4294967295, 10, 13, 8, 893, 2, 4294967295, 4294967295, 12, 13, 8, 895, 1, 4294967295, 612, 9, 13, 8, 896, 1, 4294967295, 4294967295, 1, 13, 8, 897, 1, 4294967295, 4294967295, 1, 13, 32, 898, 1, 4294967295, 4294967295, 5, 13, 8, 899, 1, 616, 4294967295, 8, 13, 8, 900, 1, 4294967295, 4294967295, 10, 13, 8, 901, 2, 4294967295, 4294967295, 12, 13, 8, 903, 1, 4294967295, 619, 9, 13, 8, 904, 1, 4294967295, 4294967295, 1, 13, 32, 905, 1, 4294967295, 4294967295, 1, 13, 8, 906, 1, 4294967295, 4294967295, 1, 14, 32, 907, 1, 4294967295, 4294967295, 1, 14, 32, 908, 1, 4294967295, 4294967295, 5, 14, 8, 909, 1, 625, 4294967295, 8, 14, 8, 910, 1, 4294967295, 4294967295, 10, 14, 8, 911, 2, 4294967295, 4294967295, 12, 14, 8, 913, 1, 4294967295, 628, 9, 14, 8, 914, 1, 4294967295, 4294967295, 1, 14, 8, 915, 1, 4294967295, 4294967295, 1, 14, 32, 916, 1, 4294967295, 4294967295, 5, 14, 8, 917, 1, 632, 4294967295, 8, 14, 8, 918, 1, 4294967295, 4294967295, 10, 14, 8, 919, 2, 4294967295, 4294967295, 12, 14, 8, 921, 1, 4294967295, 635, 9, 14, 8, 922, 1, 4294967295, 4294967295, 1, 14, 32, 923, 1, 4294967295, 4294967295, 1, 14, 32, 924, 1, 4294967295, 4294967295, 5, 14, 8, 925, 1, 639, 4294967295, 8, 14, 8, 926, 1, 4294967295, 4294967295, 10, 14, 8, 927, 2, 4294967295, 4294967295, 12, 14, 8, 929, 1, 4294967295, 642, 9, 14, 8, 930, 1, 4294967295, 4294967295, 1, 14, 8, 931, 1, 4294967295, 4294967295, 5, 14, 8, 932, 1, 645, 4294967295, 8, 14, 8, 933, 1, 4294967295, 4294967295, 10, 14, 8, 934, 2, 4294967295, 4294967295, 12, 14, 8, 936, 1, 4294967295, 648, 9, 14, 8, 937, 1, 4294967295, 4294967295, 1, 14, 32, 938, 1, 4294967295, 4294967295, 5, 14, 8, 939, 1, 651, 4294967295, 8, 14, 8, 940, 1, 4294967295, 4294967295, 10, 14, 8, 941, 2, 4294967295, 4294967295, 12, 14, 8, 943, 1, 4294967295, 654, 9, 14, 8, 944, 1, 4294967295, 4294967295, 1, 14, 32, 945, 1, 4294967295, 4294967295, 3, 14, 8, 946, 2, 657, 4294967295, 8, 14, 8, 948, 1, 4294967295, 4294967295, 3, 14, 8, 949, 2, 659, 4294967295, 8, 14, 8, 951, 1, 4294967295, 4294967295, 1, 14, 32, 952, 1, 4294967295, 4294967295, 5, 14, 8, 953, 1, 662, 4294967295, 8, 14, 8, 954, 1, 4294967295, 4294967295, 10, 14, 8, 955, 2, 4294967295, 4294967295, 12, 14, 8, 957, 1, 4294967295, 665, 9, 14, 8, 958, 1, 4294967295, 4294967295, 1, 14, 32, 959, 1, 4294967295, 4294967295, 1, 14, 8, 960, 1, 4294967295, 4294967295, 1, 15, 8, 961, 1, 4294967295, 4294967295, 3, 15, 8, 962, 2, 670, 4294967295, 8, 15, 8, 964, 1, 4294967295, 4294967295, 1, 15, 32, 965, 1, 4294967295, 4294967295, 3, 15, 8, 966, 2, 673, 4294967295, 8, 15, 8, 968, 1, 4294967295, 4294967295, 1, 15, 32, 969, 1, 4294967295, 4294967295, 5, 15, 8, 970, 1, 676, 4294967295, 8, 15, 8, 971, 1, 4294967295, 4294967295, 10, 15, 8, 972, 2, 4294967295, 4294967295, 12, 15, 8, 974, 1, 4294967295, 679, 9, 15, 8, 975, 1, 4294967295, 4294967295, 1, 15, 8, 976, 1, 4294967295, 4294967295, 1, 15, 32, 977, 1, 4294967295, 4294967295, 1, 15, 32, 978, 1, 4294967295, 4294967295, 5, 15, 8, 979, 1, 684, 4294967295, 8, 15, 8, 980, 1, 4294967295, 4294967295, 10, 15, 8, 981, 2, 4294967295, 4294967295, 12, 15, 8, 983, 1, 4294967295, 687, 9, 15, 8, 984, 1, 4294967295, 4294967295, 1, 15, 8, 985, 1, 4294967295, 4294967295, 1, 15, 32, 986, 1, 4294967295, 4294967295, 5, 15, 8, 987, 1, 691, 4294967295, 8, 15, 8, 988, 1, 4294967295, 4294967295, 10, 15, 8, 989, 2, 4294967295, 4294967295, 12, 15, 8, 991, 1, 4294967295, 694, 9, 15, 8, 992, 1, 4294967295, 4294967295, 1, 15, 32, 993, 1, 4294967295, 4294967295, 1, 15, 32, 994, 1, 4294967295, 4294967295, 5, 15, 8, 995, 1, 698, 4294967295, 8, 15, 8, 996, 1, 4294967295, 4294967295, 10, 15, 8, 997, 2, 4294967295, 4294967295, 12, 15, 8, 999, 1, 4294967295, 701, 9, 15, 8, 1000, 1, 4294967295, 4294967295, 1, 15, 8, 1001, 1, 4294967295, 4294967295, 3, 15, 8, 1002, 2, 704, 4294967295, 8, 15, 8, 1004, 1, 4294967295, 4294967295, 1, 16, 8, 1005, 1, 4294967295, 4294967295, 1, 16, 32, 1006, 1, 4294967295, 4294967295, 5, 16, 8, 1007, 1, 708, 4294967295, 8, 16, 8, 1008, 1, 4294967295, 4294967295, 10, 16, 8, 1009, 2, 4294967295, 4294967295, 12, 16, 8, 1011, 1, 4294967295, 711, 9, 16, 8, 1012, 1, 4294967295, 4294967295, 1, 16, 32, 1013, 1, 4294967295, 4294967295, 1, 16, 32, 1014, 1, 4294967295, 4294967295, 5, 16, 8, 1015, 1, 715, 4294967295, 8, 16, 8, 1016, 1, 4294967295, 4294967295, 10, 16, 8, 1017, 2, 4294967295, 4294967295, 12, 16, 8, 1019, 1, 4294967295, 718, 9, 16, 8, 1020, 1, 4294967295, 4294967295, 1, 16, 8, 1021, 1, 4294967295, 4294967295, 5, 16, 8, 1022, 1, 721, 4294967295, 8, 16, 8, 1023, 1, 4294967295, 4294967295, 10, 16, 8, 1024, 2, 4294967295, 4294967295, 12, 16, 8, 1026, 1, 4294967295, 724, 9, 16, 8, 1027, 1, 4294967295, 4294967295, 1, 17, 8, 1028, 1, 4294967295, 4294967295, 1, 17, 8, 1029, 1, 4294967295, 4294967295, 1, 17, 8, 1030, 1, 4294967295, 4294967295, 1, 17, 8, 1031, 1, 4294967295, 4294967295, 1, 17, 32, 1032, 1, 4294967295, 4294967295, 1, 17, 32, 1033, 1, 4294967295, 4294967295, 5, 17, 8, 1034, 1, 732, 4294967295, 8, 17, 8, 1035, 1, 4294967295, 4294967295, 10, 17, 8, 1036, 2, 4294967295, 4294967295, 12, 17, 8, 1038, 1, 4294967295, 735, 9, 17, 8, 1039, 1, 4294967295, 4294967295, 1, 17, 8, 1040, 1, 4294967295, 4294967295, 3, 17, 8, 1041, 5, 738, 4294967295, 8, 17, 8, 1046, 1, 4294967295, 4294967295, 1, 18, 8, 1047, 1, 4294967295, 4294967295, 1, 18, 32, 1048, 1, 4294967295, 4294967295, 5, 18, 8, 1049, 1, 742, 4294967295, 8, 18, 8, 1050, 1, 4294967295, 4294967295, 10, 18, 8, 1051, 2, 4294967295, 4294967295, 12, 18, 8, 1053, 1, 4294967295, 745, 9, 18, 8, 1054, 1, 4294967295, 4294967295, 1, 18, 8, 1055, 1, 4294967295, 4294967295, 1, 18, 8, 1056, 1, 4294967295, 4294967295, 1, 19, 8, 1057, 1, 4294967295, 4294967295, 5, 19, 8, 1058, 1, 750, 4294967295, 8, 19, 8, 1059, 1, 4294967295, 4294967295, 10, 19, 8, 1060, 2, 4294967295, 4294967295, 12, 19, 8, 1062, 1, 4294967295, 753, 9, 19, 8, 1063, 1, 4294967295, 4294967295, 1, 19, 32, 1064, 1, 4294967295, 4294967295, 5, 19, 8, 1065, 1, 756, 4294967295, 8, 19, 8, 1066, 1, 4294967295, 4294967295, 10, 19, 8, 1067, 2, 4294967295, 4294967295, 12, 19, 8, 1069, 1, 4294967295, 759, 9, 19, 8, 1070, 1, 4294967295, 4294967295, 1, 19, 8, 1071, 1, 4294967295, 4294967295, 1, 19, 8, 1072, 1, 4294967295, 4294967295, 1, 20, 8, 1073, 1, 4294967295, 4294967295, 1, 20, 8, 1074, 1, 4294967295, 4294967295, 3, 20, 8, 1075, 2, 765, 4294967295, 8, 20, 8, 1077, 1, 4294967295, 4294967295, 1, 20, 32, 1078, 1, 4294967295, 4294967295, 5, 20, 8, 1079, 1, 768, 4294967295, 8, 20, 8, 1080, 1, 4294967295, 4294967295, 10, 20, 8, 1081, 2, 4294967295, 4294967295, 12, 20, 8, 1083, 1, 4294967295, 771, 9, 20, 8, 1084, 1, 4294967295, 4294967295, 1, 20, 32, 1085, 1, 4294967295, 4294967295, 1, 20, 32, 1086, 1, 4294967295, 4294967295, 5, 20, 8, 1087, 1, 775, 4294967295, 8, 20, 8, 1088, 1, 4294967295, 4294967295, 10, 20, 8, 1089, 2, 4294967295, 4294967295, 12, 20, 8, 1091, 1, 4294967295, 778, 9, 20, 8, 1092, 1, 4294967295, 4294967295, 1, 20, 8, 1093, 1, 4294967295, 4294967295, 1, 20, 8, 1094, 1, 4294967295, 4294967295, 1, 21, 32, 1095, 1, 4294967295, 4294967295, 1, 21, 32, 1096, 1, 4294967295, 4294967295, 5, 21, 8, 1097, 1, 784, 4294967295, 8, 21, 8, 1098, 1, 4294967295, 4294967295, 10, 21, 8, 1099, 2, 4294967295, 4294967295, 12, 21, 8, 1101, 1, 4294967295, 787, 9, 21, 8, 1102, 1, 4294967295, 4294967295, 1, 21, 8, 1103, 1, 4294967295, 4294967295, 1, 21, 32, 1104, 1, 4294967295, 4294967295, 5, 21, 8, 1105, 1, 791, 4294967295, 8, 21, 8, 1106, 1, 4294967295, 4294967295, 10, 21, 8, 1107, 2, 4294967295, 4294967295, 12, 21, 8, 1109, 1, 4294967295, 794, 9, 21, 8, 1110, 1, 4294967295, 4294967295, 1, 21, 32, 1111, 1, 4294967295, 4294967295, 1, 21, 32, 1112, 1, 4294967295, 4294967295, 5, 21, 8, 1113, 1, 798, 4294967295, 8, 21, 8, 1114, 1, 4294967295, 4294967295, 10, 21, 8, 1115, 2, 4294967295, 4294967295, 12, 21, 8, 1117, 1, 4294967295, 801, 9, 21, 8, 1118, 1, 4294967295, 4294967295, 1, 21, 8, 1119, 1, 4294967295, 4294967295, 5, 21, 8, 1120, 1, 804, 4294967295, 8, 21, 8, 1121, 1, 4294967295, 4294967295, 10, 21, 8, 1122, 2, 4294967295, 4294967295, 12, 21, 8, 1124, 1, 4294967295, 807, 9, 21, 8, 1125, 1, 4294967295, 4294967295, 1, 21, 32, 1126, 1, 4294967295, 4294967295, 5, 21, 8, 1127, 1, 810, 4294967295, 8, 21, 8, 1128, 1, 4294967295, 4294967295, 10, 21, 8, 1129, 2, 4294967295, 4294967295, 12, 21, 8, 1131, 1, 4294967295, 813, 9, 21, 8, 1132, 1, 4294967295, 4294967295, 1, 21, 32, 1133, 1, 4294967295, 4294967295, 3, 21, 8, 1134, 2, 816, 4294967295, 8, 21, 8, 1136, 1, 4294967295, 4294967295, 1, 21, 32, 1137, 1, 4294967295, 4294967295, 5, 21, 8, 1138, 1, 819, 4294967295, 8, 21, 8, 1139, 1, 4294967295, 4294967295, 10, 21, 8, 1140, 2, 4294967295, 4294967295, 12, 21, 8, 1142, 1, 4294967295, 822, 9, 21, 8, 1143, 1, 4294967295, 4294967295, 1, 21, 32, 1144, 1, 4294967295, 4294967295, 1, 21, 8, 1145, 1, 4294967295, 4294967295, 1, 22, 8, 1146, 1, 4294967295, 4294967295, 3, 22, 8, 1147, 2, 827, 4294967295, 8, 22, 8, 1149, 1, 4294967295, 4294967295, 1, 22, 32, 1150, 1, 4294967295, 4294967295, 5, 22, 8, 1151, 1, 830, 4294967295, 8, 22, 8, 1152, 1, 4294967295, 4294967295, 10, 22, 8, 1153, 2, 4294967295, 4294967295, 12, 22, 8, 1155, 1, 4294967295, 833, 9, 22, 8, 1156, 1, 4294967295, 4294967295, 1, 22, 8, 1157, 1, 4294967295, 4294967295, 1, 22, 32, 1158, 1, 4294967295, 4294967295, 5, 22, 8, 1159, 1, 837, 4294967295, 8, 22, 8, 1160, 1, 4294967295, 4294967295, 10, 22, 8, 1161, 2, 4294967295, 4294967295, 12, 22, 8, 1163, 1, 4294967295, 840, 9, 22, 8, 1164, 1, 4294967295, 4294967295, 1, 22, 32, 1165, 1, 4294967295, 4294967295, 1, 22, 32, 1166, 1, 4294967295, 4294967295, 5, 22, 8, 1167, 1, 844, 4294967295, 8, 22, 8, 1168, 1, 4294967295, 4294967295, 10, 22, 8, 1169, 2, 4294967295, 4294967295, 12, 22, 8, 1171, 1, 4294967295, 847, 9, 22, 8, 1172, 1, 4294967295, 4294967295, 1, 22, 8, 1173, 1, 4294967295, 4294967295, 3, 22, 8, 1174, 2, 850, 4294967295, 8, 22, 8, 1176, 1, 4294967295, 4294967295, 1, 23, 32, 1177, 1, 4294967295, 4294967295, 1, 23, 32, 1178, 1, 4294967295, 4294967295, 5, 23, 8, 1179, 1, 854, 4294967295, 8, 23, 8, 1180, 1, 4294967295, 4294967295, 10, 23, 8, 1181, 2, 4294967295, 4294967295, 12, 23, 8, 1183, 1, 4294967295, 857, 9, 23, 8, 1184, 1, 4294967295, 4294967295, 1, 23, 8, 1185, 1, 4294967295, 4294967295, 1, 23, 32, 1186, 1, 4294967295, 4294967295, 5, 23, 8, 1187, 1, 861, 4294967295, 8, 23, 8, 1188, 1, 4294967295, 4294967295, 10, 23, 8, 1189, 2, 4294967295, 4294967295, 12, 23, 8, 1191, 1, 4294967295, 864, 9, 23, 8, 1192, 1, 4294967295, 4294967295, 1, 23, 32, 1193, 1, 4294967295, 4294967295, 1, 23, 32, 1194, 1, 4294967295, 4294967295, 5, 23, 8, 1195, 1, 868, 4294967295, 8, 23, 8, 1196, 1, 4294967295, 4294967295, 10, 23, 8, 1197, 2, 4294967295, 4294967295, 12, 23, 8, 1199, 1, 4294967295, 871, 9, 23, 8, 1200, 1, 4294967295, 4294967295, 1, 23, 8, 1201, 1, 4294967295, 4294967295, 5, 23, 8, 1202, 1, 874, 4294967295, 8, 23, 8, 1203, 1, 4294967295, 4294967295, 10, 23, 8, 1204, 2, 4294967295, 4294967295, 12, 23, 8, 1206, 1, 4294967295, 877, 9, 23, 8, 1207, 1, 4294967295, 4294967295, 1, 24, 8, 1208, 1, 4294967295, 4294967295, 5, 24, 8, 1209, 1, 880, 4294967295, 8, 24, 8, 1210, 1, 4294967295, 4294967295, 10, 24, 8, 1211, 2, 4294967295, 4294967295, 12, 24, 8, 1213, 1, 4294967295, 883, 9, 24, 8, 1214, 1, 4294967295, 4294967295, 1, 24, 8, 1215, 1, 4294967295, 4294967295, 1, 24, 32, 1216, 1, 4294967295, 4294967295, 5, 24, 8, 1217, 1, 887, 4294967295, 8, 24, 8, 1218, 1, 4294967295, 4294967295, 10, 24, 8, 1219, 2, 4294967295, 4294967295, 12, 24, 8, 1221, 1, 4294967295, 890, 9, 24, 8, 1222, 1, 4294967295, 4294967295, 1, 24, 32, 1223, 1, 4294967295, 4294967295, 1, 24, 32, 1224, 1, 4294967295, 4294967295, 5, 24, 8, 1225, 1, 894, 4294967295, 8, 24, 8, 1226, 1, 4294967295, 4294967295, 10, 24, 8, 1227, 2, 4294967295, 4294967295, 12, 24, 8, 1229, 1, 4294967295, 897, 9, 24, 8, 1230, 1, 4294967295, 4294967295, 1, 24, 8, 1231, 1, 4294967295, 4294967295, 1, 24, 8, 1232, 1, 4294967295, 4294967295, 1, 25, 8, 1233, 1, 4294967295, 4294967295, 1, 25, 8, 1234, 1, 4294967295, 4294967295, 3, 25, 8, 1235, 2, 903, 4294967295, 8, 25, 8, 1237, 1, 4294967295, 4294967295, 5, 25, 8, 1238, 1, 905, 4294967295, 8, 25, 8, 1239, 1, 4294967295, 4294967295, 10, 25, 8, 1240, 2, 4294967295, 4294967295, 12, 25, 8, 1242, 1, 4294967295, 908, 9, 25, 8, 1243, 1, 4294967295, 4294967295, 1, 26, 8, 1244, 1, 4294967295, 4294967295, 1, 26, 8, 1245, 1, 4294967295, 4294967295, 1, 26, 8, 1246, 1, 4294967295, 4294967295, 1, 26, 8, 1247, 1, 4294967295, 4294967295, 3, 26, 8, 1248, 4, 914, 4294967295, 8, 26, 8, 1252, 1, 4294967295, 4294967295, 1, 27, 32, 1253, 1, 4294967295, 4294967295, 1, 27, 32, 1254, 1, 4294967295, 4294967295, 5, 27, 8, 1255, 1, 918, 4294967295, 8, 27, 8, 1256, 1, 4294967295, 4294967295, 10, 27, 8, 1257, 2, 4294967295, 4294967295, 12, 27, 8, 1259, 1, 4294967295, 921, 9, 27, 8, 1260, 1, 4294967295, 4294967295, 1, 27, 8, 1261, 1, 4294967295, 4294967295, 1, 27, 8, 1262, 1, 4294967295, 4294967295, 1, 28, 8, 1263, 1, 4294967295, 4294967295, 3, 28, 8, 1264, 2, 926, 4294967295, 8, 28, 8, 1266, 1, 4294967295, 4294967295, 1, 28, 32, 1267, 1, 4294967295, 4294967295, 1, 28, 32, 1268, 1, 4294967295, 4294967295, 5, 28, 8, 1269, 1, 930, 4294967295, 8, 28, 8, 1270, 1, 4294967295, 4294967295, 10, 28, 8, 1271, 2, 4294967295, 4294967295, 12, 28, 8, 1273, 1, 4294967295, 933, 9, 28, 8, 1274, 1, 4294967295, 4294967295, 1, 28, 32, 1275, 1, 4294967295, 4294967295, 3, 28, 8, 1276, 2, 936, 4294967295, 8, 28, 8, 1278, 1, 4294967295, 4294967295, 1, 28, 32, 1279, 1, 4294967295, 4294967295, 5, 28, 8, 1280, 1, 939, 4294967295, 8, 28, 8, 1281, 1, 4294967295, 4294967295, 10, 28, 8, 1282, 2, 4294967295, 4294967295, 12, 28, 8, 1284, 1, 4294967295, 942, 9, 28, 8, 1285, 1, 4294967295, 4294967295, 1, 28, 32, 1286, 1, 4294967295, 4294967295, 1, 28, 32, 1287, 1, 4294967295, 4294967295, 5, 28, 8, 1288, 1, 946, 4294967295, 8, 28, 8, 1289, 1, 4294967295, 4294967295, 10, 28, 8, 1290, 2, 4294967295, 4294967295, 12, 28, 8, 1292, 1, 4294967295, 949, 9, 28, 8, 1293, 1, 4294967295, 4294967295, 1, 28, 8, 1294, 1, 4294967295, 4294967295, 3, 28, 8, 1295, 2, 952, 4294967295, 8, 28, 8, 1297, 1, 4294967295, 4294967295, 1, 28, 32, 1298, 1, 4294967295, 4294967295, 5, 28, 8, 1299, 1, 955, 4294967295, 8, 28, 8, 1300, 1, 4294967295, 4294967295, 10, 28, 8, 1301, 2, 4294967295, 4294967295, 12, 28, 8, 1303, 1, 4294967295, 958, 9, 28, 8, 1304, 1, 4294967295, 4294967295, 1, 28, 32, 1305, 1, 4294967295, 4294967295, 1, 28, 32, 1306, 1, 4294967295, 4294967295, 5, 28, 8, 1307, 1, 962, 4294967295, 8, 28, 8, 1308, 1, 4294967295, 4294967295, 10, 28, 8, 1309, 2, 4294967295, 4294967295, 12, 28, 8, 1311, 1, 4294967295, 965, 9, 28, 8, 1312, 1, 4294967295, 4294967295, 1, 28, 8, 1313, 1, 4294967295, 4294967295, 3, 28, 8, 1314, 2, 968, 4294967295, 8, 28, 8, 1316, 1, 4294967295, 4294967295, 1, 28, 32, 1317, 1, 4294967295, 4294967295, 5, 28, 8, 1318, 1, 971, 4294967295, 8, 28, 8, 1319, 1, 4294967295, 4294967295, 10, 28, 8, 1320, 2, 4294967295, 4294967295, 12, 28, 8, 1322, 1, 4294967295, 974, 9, 28, 8, 1323, 1, 4294967295, 4294967295, 1, 28, 8, 1324, 1, 4294967295, 4294967295, 3, 28, 8, 1325, 2, 977, 4294967295, 8, 28, 8, 1327, 1, 4294967295, 4294967295, 1, 29, 32, 1328, 1, 4294967295, 4294967295, 1, 29, 32, 1329, 1, 4294967295, 4294967295, 5, 29, 8, 1330, 1, 981, 4294967295, 8, 29, 8, 1331, 1, 4294967295, 4294967295, 10, 29, 8, 1332, 2, 4294967295, 4294967295, 12, 29, 8, 1334, 1, 4294967295, 984, 9, 29, 8, 1335, 1, 4294967295, 4294967295, 1, 29, 8, 1336, 1, 4294967295, 4294967295, 1, 29, 32, 1337, 1, 4294967295, 4294967295, 5, 29, 8, 1338, 1, 988, 4294967295, 8, 29, 8, 1339, 1, 4294967295, 4294967295, 10, 29, 8, 1340, 2, 4294967295, 4294967295, 12, 29, 8, 1342, 1, 4294967295, 991, 9, 29, 8, 1343, 1, 4294967295, 4294967295, 1, 29, 32, 1344, 1, 4294967295, 4294967295, 1, 29, 32, 1345, 1, 4294967295, 4294967295, 5, 29, 8, 1346, 1, 995, 4294967295, 8, 29, 8, 1347, 1, 4294967295, 4294967295, 10, 29, 8, 1348, 2, 4294967295, 4294967295, 12, 29, 8, 1350, 1, 4294967295, 998, 9, 29, 8, 1351, 1, 4294967295, 4294967295, 1, 29, 8, 1352, 1, 4294967295, 4294967295, 5, 29, 8, 1353, 1, 1001, 4294967295, 8, 29, 8, 1354, 1, 4294967295, 4294967295, 10, 29, 8, 1355, 2, 4294967295, 4294967295, 12, 29, 8, 1357, 1, 4294967295, 1004, 9, 29, 8, 1358, 1, 4294967295, 4294967295, 1, 29, 32, 1359, 1, 4294967295, 4294967295, 5, 29, 8, 1360, 1, 1007, 4294967295, 8, 29, 8, 1361, 1, 4294967295, 4294967295, 10, 29, 8, 1362, 2, 4294967295, 4294967295, 12, 29, 8, 1364, 1, 4294967295, 1010, 9, 29, 8, 1365, 1, 4294967295, 4294967295, 1, 29, 32, 1366, 1, 4294967295, 4294967295, 3, 29, 8, 1367, 2, 1013, 4294967295, 8, 29, 8, 1369, 1, 4294967295, 4294967295, 3, 29, 8, 1370, 2, 1015, 4294967295, 8, 29, 8, 1372, 1, 4294967295, 4294967295, 1, 29, 32, 1373, 1, 4294967295, 4294967295, 5, 29, 8, 1374, 1, 1018, 4294967295, 8, 29, 8, 1375, 1, 4294967295, 4294967295, 10, 29, 8, 1376, 2, 4294967295, 4294967295, 12, 29, 8, 1378, 1, 4294967295, 1021, 9, 29, 8, 1379, 1, 4294967295, 4294967295, 1, 29, 32, 1380, 1, 4294967295, 4294967295, 1, 29, 8, 1381, 1, 4294967295, 4294967295, 1, 30, 8, 1382, 1, 4294967295, 4294967295, 3, 30, 8, 1383, 2, 1026, 4294967295, 8, 30, 8, 1385, 1, 4294967295, 4294967295, 1, 30, 8, 1386, 1, 4294967295, 4294967295, 1, 30, 32, 1387, 1, 4294967295, 4294967295, 5, 30, 8, 1388, 1, 1030, 4294967295, 8, 30, 8, 1389, 1, 4294967295, 4294967295, 10, 30, 8, 1390, 2, 4294967295, 4294967295, 12, 30, 8, 1392, 1, 4294967295, 1033, 9, 30, 8, 1393, 1, 4294967295, 4294967295, 1, 30, 32, 1394, 1, 4294967295, 4294967295, 1, 30, 32, 1395, 1, 4294967295, 4294967295, 5, 30, 8, 1396, 1, 1037, 4294967295, 8, 30, 8, 1397, 1, 4294967295, 4294967295, 10, 30, 8, 1398, 2, 4294967295, 4294967295, 12, 30, 8, 1400, 1, 4294967295, 1040, 9, 30, 8, 1401, 1, 4294967295, 4294967295, 1, 30, 8, 1402, 1, 4294967295, 4294967295, 3, 30, 8, 1403, 2, 1043, 4294967295, 8, 30, 8, 1405, 1, 4294967295, 4294967295, 1, 31, 8, 1406, 1, 4294967295, 4294967295, 3, 31, 8, 1407, 2, 1046, 4294967295, 8, 31, 8, 1409, 1, 4294967295, 4294967295, 1, 31, 32, 1410, 1, 4294967295, 4294967295, 1, 31, 32, 1411, 1, 4294967295, 4294967295, 5, 31, 8, 1412, 1, 1050, 4294967295, 8, 31, 8, 1413, 1, 4294967295, 4294967295, 10, 31, 8, 1414, 2, 4294967295, 4294967295, 12, 31, 8, 1416, 1, 4294967295, 1053, 9, 31, 8, 1417, 1, 4294967295, 4294967295, 1, 31, 8, 1418, 1, 4294967295, 4294967295, 3, 31, 8, 1419, 2, 1056, 4294967295, 8, 31, 8, 1421, 1, 4294967295, 4294967295, 1, 31, 32, 1422, 1, 4294967295, 4294967295, 5, 31, 8, 1423, 1, 1059, 4294967295, 8, 31, 8, 1424, 1, 4294967295, 4294967295, 10, 31, 8, 1425, 2, 4294967295, 4294967295, 12, 31, 8, 1427, 1, 4294967295, 1062, 9, 31, 8, 1428, 1, 4294967295, 4294967295, 1, 31, 8, 1429, 1, 4294967295, 4294967295, 1, 31, 32, 1430, 1, 4294967295, 4294967295, 5, 31, 8, 1431, 1, 1066, 4294967295, 8, 31, 8, 1432, 1, 4294967295, 4294967295, 10, 31, 8, 1433, 2, 4294967295, 4294967295, 12, 31, 8, 1435, 1, 4294967295, 1069, 9, 31, 8, 1436, 1, 4294967295, 4294967295, 1, 31, 32, 1437, 1, 4294967295, 4294967295, 1, 31, 8, 1438, 1, 4294967295, 4294967295, 3, 31, 8, 1439, 2, 1073, 4294967295, 8, 31, 8, 1441, 1, 4294967295, 4294967295, 1, 31, 32, 1442, 1, 4294967295, 4294967295, 5, 31, 8, 1443, 1, 1076, 4294967295, 8, 31, 8, 1444, 1, 4294967295, 4294967295, 10, 31, 8, 1445, 2, 4294967295, 4294967295, 12, 31, 8, 1447, 1, 4294967295, 1079, 9, 31, 8, 1448, 1, 4294967295, 4294967295, 1, 31, 8, 1449, 1, 4294967295, 4294967295, 1, 31, 32, 1450, 1, 4294967295, 4294967295, 5, 31, 8, 1451, 1, 1083, 4294967295, 8, 31, 8, 1452, 1, 4294967295, 4294967295, 10, 31, 8, 1453, 2, 4294967295, 4294967295, 12, 31, 8, 1455, 1, 4294967295, 1086, 9, 31, 8, 1456, 1, 4294967295, 4294967295, 1, 31, 8, 1457, 1, 4294967295, 4294967295, 1, 31, 32, 1458, 1, 4294967295, 4294967295, 5, 31, 8, 1459, 1, 1090, 4294967295, 8, 31, 8, 1460, 1, 4294967295, 4294967295, 10, 31, 8, 1461, 2, 4294967295, 4294967295, 12, 31, 8, 1463, 1, 4294967295, 1093, 9, 31, 8, 1464, 1, 4294967295, 4294967295, 1, 31, 32, 1465, 1, 4294967295, 4294967295, 1, 31, 32, 1466, 1, 4294967295, 4294967295, 5, 31, 8, 1467, 1, 1097, 4294967295, 8, 31, 8, 1468, 1, 4294967295, 4294967295, 10, 31, 8, 1469, 2, 4294967295, 4294967295, 12, 31, 8, 1471, 1, 4294967295, 1100, 9, 31, 8, 1472, 1, 4294967295, 4294967295, 1, 31, 8, 1473, 1, 4294967295, 4294967295, 3, 31, 8, 1474, 2, 1103, 4294967295, 8, 31, 8, 1476, 1, 4294967295, 4294967295, 1, 31, 32, 1477, 1, 4294967295, 4294967295, 5, 31, 8, 1478, 1, 1106, 4294967295, 8, 31, 8, 1479, 1, 4294967295, 4294967295, 10, 31, 8, 1480, 2, 4294967295, 4294967295, 12, 31, 8, 1482, 1, 4294967295, 1109, 9, 31, 8, 1483, 1, 4294967295, 4294967295, 1, 31, 8, 1484, 1, 4294967295, 4294967295, 3, 31, 8, 1485, 2, 1112, 4294967295, 8, 31, 8, 1487, 1, 4294967295, 4294967295, 1, 31, 32, 1488, 1, 4294967295, 4294967295, 5, 31, 8, 1489, 1, 1115, 4294967295, 8, 31, 8, 1490, 1, 4294967295, 4294967295, 10, 31, 8, 1491, 2, 4294967295, 4294967295, 12, 31, 8, 1493, 1, 4294967295, 1118, 9, 31, 8, 1494, 1, 4294967295, 4294967295, 1, 31, 8, 1495, 1, 4294967295, 4294967295, 3, 31, 8, 1496, 2, 1121, 4294967295, 8, 31, 8, 1498, 1, 4294967295, 4294967295, 1, 32, 8, 1499, 1, 4294967295, 4294967295, 1, 32, 32, 1500, 1, 4294967295, 4294967295, 1, 32, 32, 1501, 1, 4294967295, 4294967295, 5, 32, 8, 1502, 1, 1126, 4294967295, 8, 32, 8, 1503, 1, 4294967295, 4294967295, 10, 32, 8, 1504, 2, 4294967295, 4294967295, 12, 32, 8, 1506, 1, 4294967295, 1129, 9, 32, 8, 1507, 1, 4294967295, 4294967295, 1, 32, 8, 1508, 1, 4294967295, 4294967295, 3, 32, 8, 1509, 2, 1132, 4294967295, 8, 32, 8, 1511, 1, 4294967295, 4294967295, 1, 33, 8, 1512, 1, 4294967295, 4294967295, 5, 33, 8, 1513, 1, 1135, 4294967295, 8, 33, 8, 1514, 1, 4294967295, 4294967295, 10, 33, 8, 1515, 2, 4294967295, 4294967295, 12, 33, 8, 1517, 1, 4294967295, 1138, 9, 33, 8, 1518, 1, 4294967295, 4294967295, 1, 33, 32, 1519, 1, 4294967295, 4294967295, 5, 33, 8, 1520, 1, 1141, 4294967295, 8, 33, 8, 1521, 1, 4294967295, 4294967295, 10, 33, 8, 1522, 2, 4294967295, 4294967295, 12, 33, 8, 1524, 1, 4294967295, 1144, 9, 33, 8, 1525, 1, 4294967295, 4294967295, 1, 33, 8, 1526, 1, 4294967295, 4294967295, 1, 33, 32, 1527, 1, 4294967295, 4294967295, 5, 33, 8, 1528, 1, 1148, 4294967295, 8, 33, 8, 1529, 1, 4294967295, 4294967295, 10, 33, 8, 1530, 2, 4294967295, 4294967295, 12, 33, 8, 1532, 1, 4294967295, 1151, 9, 33, 8, 1533, 1, 4294967295, 4294967295, 1, 33, 32, 1534, 1, 4294967295, 4294967295, 1, 33, 32, 1535, 1, 4294967295, 4294967295, 5, 33, 8, 1536, 1, 1155, 4294967295, 8, 33, 8, 1537, 1, 4294967295, 4294967295, 10, 33, 8, 1538, 2, 4294967295, 4294967295, 12, 33, 8, 1540, 1, 4294967295, 1158, 9, 33, 8, 1541, 1, 4294967295, 4294967295, 1, 33, 8, 1542, 1, 4294967295, 4294967295, 3, 33, 8, 1543, 2, 1161, 4294967295, 8, 33, 8, 1545, 1, 4294967295, 4294967295, 1, 34, 32, 1546, 1, 4294967295, 4294967295, 1, 34, 32, 1547, 1, 4294967295, 4294967295, 5, 34, 8, 1548, 1, 1165, 4294967295, 8, 34, 8, 1549, 1, 4294967295, 4294967295, 10, 34, 8, 1550, 2, 4294967295, 4294967295, 12, 34, 8, 1552, 1, 4294967295, 1168, 9, 34, 8, 1553, 1, 4294967295, 4294967295, 1, 34, 8, 1554, 1, 4294967295, 4294967295, 1, 34, 32, 1555, 1, 4294967295, 4294967295, 5, 34, 8, 1556, 1, 1172, 4294967295, 8, 34, 8, 1557, 1, 4294967295, 4294967295, 10, 34, 8, 1558, 2, 4294967295, 4294967295, 12, 34, 8, 1560, 1, 4294967295, 1175, 9, 34, 8, 1561, 1, 4294967295, 4294967295, 1, 34, 32, 1562, 1, 4294967295, 4294967295, 1, 34, 32, 1563, 1, 4294967295, 4294967295, 5, 34, 8, 1564, 1, 1179, 4294967295, 8, 34, 8, 1565, 1, 4294967295, 4294967295, 10, 34, 8, 1566, 2, 4294967295, 4294967295, 12, 34, 8, 1568, 1, 4294967295, 1182, 9, 34, 8, 1569, 1, 4294967295, 4294967295, 1, 34, 8, 1570, 1, 4294967295, 4294967295, 5, 34, 8, 1571, 1, 1185, 4294967295, 8, 34, 8, 1572, 1, 4294967295, 4294967295, 10, 34, 8, 1573, 2, 4294967295, 4294967295, 12, 34, 8, 1575, 1, 4294967295, 1188, 9, 34, 8, 1576, 1, 4294967295, 4294967295, 1, 34, 32, 1577, 1, 4294967295, 4294967295, 5, 34, 8, 1578, 1, 1191, 4294967295, 8, 34, 8, 1579, 1, 4294967295, 4294967295, 10, 34, 8, 1580, 2, 4294967295, 4294967295, 12, 34, 8, 1582, 1, 4294967295, 1194, 9, 34, 8, 1583, 1, 4294967295, 4294967295, 1, 34, 32, 1584, 1, 4294967295, 4294967295, 3, 34, 8, 1585, 2, 1197, 4294967295, 8, 34, 8, 1587, 1, 4294967295, 4294967295, 1, 34, 32, 1588, 1, 4294967295, 4294967295, 5, 34, 8, 1589, 1, 1200, 4294967295, 8, 34, 8, 1590, 1, 4294967295, 4294967295, 10, 34, 8, 1591, 2, 4294967295, 4294967295, 12, 34, 8, 1593, 1, 4294967295, 1203, 9, 34, 8, 1594, 1, 4294967295, 4294967295, 1, 34, 32, 1595, 1, 4294967295, 4294967295, 1, 34, 8, 1596, 1, 4294967295, 4294967295, 1, 35, 8, 1597, 1, 4294967295, 4294967295, 3, 35, 8, 1598, 2, 1208, 4294967295, 8, 35, 8, 1600, 1, 4294967295, 4294967295, 1, 35, 32, 1601, 1, 4294967295, 4294967295, 1, 35, 32, 1602, 1, 4294967295, 4294967295, 5, 35, 8, 1603, 1, 1212, 4294967295, 8, 35, 8, 1604, 1, 4294967295, 4294967295, 10, 35, 8, 1605, 2, 4294967295, 4294967295, 12, 35, 8, 1607, 1, 4294967295, 1215, 9, 35, 8, 1608, 1, 4294967295, 4294967295, 1, 35, 8, 1609, 1, 4294967295, 4294967295, 3, 35, 8, 1610, 2, 1218, 4294967295, 8, 35, 8, 1612, 1, 4294967295, 4294967295, 1, 35, 32, 1613, 1, 4294967295, 4294967295, 5, 35, 8, 1614, 1, 1221, 4294967295, 8, 35, 8, 1615, 1, 4294967295, 4294967295, 10, 35, 8, 1616, 2, 4294967295, 4294967295, 12, 35, 8, 1618, 1, 4294967295, 1224, 9, 35, 8, 1619, 1, 4294967295, 4294967295, 1, 35, 8, 1620, 1, 4294967295, 4294967295, 1, 35, 32, 1621, 1, 4294967295, 4294967295, 5, 35, 8, 1622, 1, 1228, 4294967295, 8, 35, 8, 1623, 1, 4294967295, 4294967295, 10, 35, 8, 1624, 2, 4294967295, 4294967295, 12, 35, 8, 1626, 1, 4294967295, 1231, 9, 35, 8, 1627, 1, 4294967295, 4294967295, 1, 35, 32, 1628, 1, 4294967295, 4294967295, 1, 35, 8, 1629, 1, 4294967295, 4294967295, 3, 35, 8, 1630, 2, 1235, 4294967295, 8, 35, 8, 1632, 1, 4294967295, 4294967295, 1, 35, 32, 1633, 1, 4294967295, 4294967295, 5, 35, 8, 1634, 1, 1238, 4294967295, 8, 35, 8, 1635, 1, 4294967295, 4294967295, 10, 35, 8, 1636, 2, 4294967295, 4294967295, 12, 35, 8, 1638, 1, 4294967295, 1241, 9, 35, 8, 1639, 1, 4294967295, 4294967295, 1, 35, 8, 1640, 1, 4294967295, 4294967295, 1, 35, 8, 1641, 1, 4294967295, 4294967295, 3, 35, 8, 1642, 2, 1245, 4294967295, 8, 35, 8, 1644, 1, 4294967295, 4294967295, 1, 35, 32, 1645, 1, 4294967295, 4294967295, 5, 35, 8, 1646, 1, 1248, 4294967295, 8, 35, 8, 1647, 1, 4294967295, 4294967295, 10, 35, 8, 1648, 2, 4294967295, 4294967295, 12, 35, 8, 1650, 1, 4294967295, 1251, 9, 35, 8, 1651, 1, 4294967295, 4294967295, 1, 35, 8, 1652, 1, 4294967295, 4294967295, 3, 35, 8, 1653, 2, 1254, 4294967295, 8, 35, 8, 1655, 1, 4294967295, 4294967295, 1, 35, 32, 1656, 1, 4294967295, 4294967295, 5, 35, 8, 1657, 1, 1257, 4294967295, 8, 35, 8, 1658, 1, 4294967295, 4294967295, 10, 35, 8, 1659, 2, 4294967295, 4294967295, 12, 35, 8, 1661, 1, 4294967295, 1260, 9, 35, 8, 1662, 1, 4294967295, 4294967295, 1, 35, 32, 1663, 1, 4294967295, 4294967295, 1, 35, 32, 1664, 1, 4294967295, 4294967295, 5, 35, 8, 1665, 1, 1264, 4294967295, 8, 35, 8, 1666, 1, 4294967295, 4294967295, 10, 35, 8, 1667, 2, 4294967295, 4294967295, 12, 35, 8, 1669, 1, 4294967295, 1267, 9, 35, 8, 1670, 1, 4294967295, 4294967295, 1, 35, 8, 1671, 1, 4294967295, 4294967295, 1, 35, 8, 1672, 1, 4294967295, 4294967295, 3, 35, 8, 1673, 2, 1271, 4294967295, 8, 35, 8, 1675, 1, 4294967295, 4294967295, 3, 35, 8, 1676, 2, 1273, 4294967295, 8, 35, 8, 1678, 1, 4294967295, 4294967295, 1, 35, 32, 1679, 1, 4294967295, 4294967295, 5, 35, 8, 1680, 1, 1276, 4294967295, 8, 35, 8, 1681, 1, 4294967295, 4294967295, 10, 35, 8, 1682, 2, 4294967295, 4294967295, 12, 35, 8, 1684, 1, 4294967295, 1279, 9, 35, 8, 1685, 1, 4294967295, 4294967295, 1, 35, 32, 1686, 1, 4294967295, 4294967295, 3, 35, 8, 1687, 2, 1282, 4294967295, 8, 35, 8, 1689, 1, 4294967295, 4294967295, 1, 35, 32, 1690, 1, 4294967295, 4294967295, 5, 35, 8, 1691, 1, 1285, 4294967295, 8, 35, 8, 1692, 1, 4294967295, 4294967295, 10, 35, 8, 1693, 2, 4294967295, 4294967295, 12, 35, 8, 1695, 1, 4294967295, 1288, 9, 35, 8, 1696, 1, 4294967295, 4294967295, 1, 35, 8, 1697, 1, 4294967295, 4294967295, 3, 35, 8, 1698, 2, 1291, 4294967295, 8, 35, 8, 1700, 1, 4294967295, 4294967295, 1, 35, 32, 1701, 1, 4294967295, 4294967295, 5, 35, 8, 1702, 1, 1294, 4294967295, 8, 35, 8, 1703, 1, 4294967295, 4294967295, 10, 35, 8, 1704, 2, 4294967295, 4294967295, 12, 35, 8, 1706, 1, 4294967295, 1297, 9, 35, 8, 1707, 1, 4294967295, 4294967295, 1, 35, 8, 1708, 1, 4294967295, 4294967295, 3, 35, 8, 1709, 2, 1300, 4294967295, 8, 35, 8, 1711, 1, 4294967295, 4294967295, 1, 35, 8, 1712, 1, 4294967295, 4294967295, 3, 35, 8, 1713, 2, 1303, 4294967295, 8, 35, 8, 1715, 1, 4294967295, 4294967295, 1, 35, 8, 1716, 1, 4294967295, 4294967295, 3, 35, 8, 1717, 2, 1306, 4294967295, 8, 35, 8, 1719, 1, 4294967295, 4294967295, 1, 35, 32, 1720, 1, 4294967295, 4294967295, 5, 35, 8, 1721, 1, 1309, 4294967295, 8, 35, 8, 1722, 1, 4294967295, 4294967295, 10, 35, 8, 1723, 2, 4294967295, 4294967295, 12, 35, 8, 1725, 1, 4294967295, 1312, 9, 35, 8, 1726, 1, 4294967295, 4294967295, 1, 35, 8, 1727, 1, 4294967295, 4294967295, 3, 35, 8, 1728, 2, 1315, 4294967295, 8, 35, 8, 1730, 1, 4294967295, 4294967295, 1, 35, 8, 1731, 1, 4294967295, 4294967295, 3, 35, 8, 1732, 2, 1318, 4294967295, 8, 35, 8, 1734, 1, 4294967295, 4294967295, 3, 35, 8, 1735, 2, 1320, 4294967295, 8, 35, 8, 1737, 1, 4294967295, 4294967295, 1, 36, 32, 1738, 1, 4294967295, 4294967295, 1, 36, 32, 1739, 1, 4294967295, 4294967295, 5, 36, 8, 1740, 1, 1324, 4294967295, 8, 36, 8, 1741, 1, 4294967295, 4294967295, 10, 36, 8, 1742, 2, 4294967295, 4294967295, 12, 36, 8, 1744, 1, 4294967295, 1327, 9, 36, 8, 1745, 1, 4294967295, 4294967295, 1, 36, 8, 1746, 1, 4294967295, 4294967295, 1, 36, 8, 1747, 1, 4294967295, 4294967295, 1, 37, 8, 1748, 1, 4294967295, 4294967295, 3, 37, 8, 1749, 2, 1332, 4294967295, 8, 37, 8, 1751, 1, 4294967295, 4294967295, 1, 37, 32, 1752, 1, 4294967295, 4294967295, 1, 37, 32, 1753, 1, 4294967295, 4294967295, 5, 37, 8, 1754, 1, 1336, 4294967295, 8, 37, 8, 1755, 1, 4294967295, 4294967295, 10, 37, 8, 1756, 2, 4294967295, 4294967295, 12, 37, 8, 1758, 1, 4294967295, 1339, 9, 37, 8, 1759, 1, 4294967295, 4294967295, 1, 37, 32, 1760, 1, 4294967295, 4294967295, 1, 37, 32, 1761, 1, 4294967295, 4294967295, 5, 37, 8, 1762, 1, 1343, 4294967295, 8, 37, 8, 1763, 1, 4294967295, 4294967295, 10, 37, 8, 1764, 2, 4294967295, 4294967295, 12, 37, 8, 1766, 1, 4294967295, 1346, 9, 37, 8, 1767, 1, 4294967295, 4294967295, 1, 37, 32, 1768, 1, 4294967295, 4294967295, 1, 37, 32, 1769, 1, 4294967295, 4294967295, 5, 37, 8, 1770, 1, 1350, 4294967295, 8, 37, 8, 1771, 1, 4294967295, 4294967295, 10, 37, 8, 1772, 2, 4294967295, 4294967295, 12, 37, 8, 1774, 1, 4294967295, 1353, 9, 37, 8, 1775, 1, 4294967295, 4294967295, 1, 37, 32, 1776, 1, 4294967295, 4294967295, 1, 37, 32, 1777, 1, 4294967295, 4294967295, 5, 37, 8, 1778, 1, 1357, 4294967295, 8, 37, 8, 1779, 1, 4294967295, 4294967295, 10, 37, 8, 1780, 2, 4294967295, 4294967295, 12, 37, 8, 1782, 1, 4294967295, 1360, 9, 37, 8, 1783, 1, 4294967295, 4294967295, 1, 37, 8, 1784, 1, 4294967295, 4294967295, 3, 37, 8, 1785, 2, 1363, 4294967295, 8, 37, 8, 1787, 1, 4294967295, 4294967295, 1, 37, 32, 1788, 1, 4294967295, 4294967295, 5, 37, 8, 1789, 1, 1366, 4294967295, 8, 37, 8, 1790, 1, 4294967295, 4294967295, 10, 37, 8, 1791, 2, 4294967295, 4294967295, 12, 37, 8, 1793, 1, 4294967295, 1369, 9, 37, 8, 1794, 1, 4294967295, 4294967295, 1, 37, 8, 1795, 1, 4294967295, 4294967295, 3, 37, 8, 1796, 2, 1372, 4294967295, 8, 37, 8, 1798, 1, 4294967295, 4294967295, 1, 38, 8, 1799, 1, 4294967295, 4294967295, 3, 38, 8, 1800, 2, 1375, 4294967295, 8, 38, 8, 1802, 1, 4294967295, 4294967295, 1, 38, 32, 1803, 1, 4294967295, 4294967295, 1, 38, 32, 1804, 1, 4294967295, 4294967295, 5, 38, 8, 1805, 1, 1379, 4294967295, 8, 38, 8, 1806, 1, 4294967295, 4294967295, 10, 38, 8, 1807, 2, 4294967295, 4294967295, 12, 38, 8, 1809, 1, 4294967295, 1382, 9, 38, 8, 1810, 1, 4294967295, 4294967295, 1, 38, 32, 1811, 1, 4294967295, 4294967295, 1, 38, 32, 1812, 1, 4294967295, 4294967295, 5, 38, 8, 1813, 1, 1386, 4294967295, 8, 38, 8, 1814, 1, 4294967295, 4294967295, 10, 38, 8, 1815, 2, 4294967295, 4294967295, 12, 38, 8, 1817, 1, 4294967295, 1389, 9, 38, 8, 1818, 1, 4294967295, 4294967295, 1, 38, 8, 1819, 1, 4294967295, 4294967295, 1, 38, 32, 1820, 1, 4294967295, 4294967295, 5, 38, 8, 1821, 1, 1393, 4294967295, 8, 38, 8, 1822, 1, 4294967295, 4294967295, 10, 38, 8, 1823, 2, 4294967295, 4294967295, 12, 38, 8, 1825, 1, 4294967295, 1396, 9, 38, 8, 1826, 1, 4294967295, 4294967295, 1, 38, 32, 1827, 1, 4294967295, 4294967295, 3, 38, 8, 1828, 2, 1399, 4294967295, 8, 38, 8, 1830, 1, 4294967295, 4294967295, 1, 38, 32, 1831, 1, 4294967295, 4294967295, 5, 38, 8, 1832, 1, 1402, 4294967295, 8, 38, 8, 1833, 1, 4294967295, 4294967295, 10, 38, 8, 1834, 2, 4294967295, 4294967295, 12, 38, 8, 1836, 1, 4294967295, 1405, 9, 38, 8, 1837, 1, 4294967295, 4294967295, 1, 38, 32, 1838, 1, 4294967295, 4294967295, 1, 38, 32, 1839, 1, 4294967295, 4294967295, 5, 38, 8, 1840, 1, 1409, 4294967295, 8, 38, 8, 1841, 1, 4294967295, 4294967295, 10, 38, 8, 1842, 2, 4294967295, 4294967295, 12, 38, 8, 1844, 1, 4294967295, 1412, 9, 38, 8, 1845, 1, 4294967295, 4294967295, 1, 38, 32, 1846, 1, 4294967295, 4294967295, 1, 38, 32, 1847, 1, 4294967295, 4294967295, 5, 38, 8, 1848, 1, 1416, 4294967295, 8, 38, 8, 1849, 1, 4294967295, 4294967295, 10, 38, 8, 1850, 2, 4294967295, 4294967295, 12, 38, 8, 1852, 1, 4294967295, 1419, 9, 38, 8, 1853, 1, 4294967295, 4294967295, 1, 38, 8, 1854, 1, 4294967295, 4294967295, 3, 38, 8, 1855, 2, 1422, 4294967295, 8, 38, 8, 1857, 1, 4294967295, 4294967295, 1, 38, 32, 1858, 1, 4294967295, 4294967295, 5, 38, 8, 1859, 1, 1425, 4294967295, 8, 38, 8, 1860, 1, 4294967295, 4294967295, 10, 38, 8, 1861, 2, 4294967295, 4294967295, 12, 38, 8, 1863, 1, 4294967295, 1428, 9, 38, 8, 1864, 1, 4294967295, 4294967295, 1, 38, 8, 1865, 1, 4294967295, 4294967295, 1, 38, 8, 1866, 1, 4294967295, 4294967295, 3, 38, 8, 1867, 2, 1432, 4294967295, 8, 38, 8, 1869, 1, 4294967295, 4294967295, 1, 39, 32, 1870, 1, 4294967295, 4294967295, 1, 39, 32, 1871, 1, 4294967295, 4294967295, 5, 39, 8, 1872, 1, 1436, 4294967295, 8, 39, 8, 1873, 1, 4294967295, 4294967295, 10, 39, 8, 1874, 2, 4294967295, 4294967295, 12, 39, 8, 1876, 1, 4294967295, 1439, 9, 39, 8, 1877, 1, 4294967295, 4294967295, 1, 39, 8, 1878, 1, 4294967295, 4294967295, 1, 39, 32, 1879, 1, 4294967295, 4294967295, 5, 39, 8, 1880, 1, 1443, 4294967295, 8, 39, 8, 1881, 1, 4294967295, 4294967295, 10, 39, 8, 1882, 2, 4294967295, 4294967295, 12, 39, 8, 1884, 1, 4294967295, 1446, 9, 39, 8, 1885, 1, 4294967295, 4294967295, 1, 39, 32, 1886, 1, 4294967295, 4294967295, 1, 39, 32, 1887, 1, 4294967295, 4294967295, 5, 39, 8, 1888, 1, 1450, 4294967295, 8, 39, 8, 1889, 1, 4294967295, 4294967295, 10, 39, 8, 1890, 2, 4294967295, 4294967295, 12, 39, 8, 1892, 1, 4294967295, 1453, 9, 39, 8, 1893, 1, 4294967295, 4294967295, 1, 39, 8, 1894, 1, 4294967295, 4294967295, 5, 39, 8, 1895, 1, 1456, 4294967295, 8, 39, 8, 1896, 1, 4294967295, 4294967295, 10, 39, 8, 1897, 2, 4294967295, 4294967295, 12, 39, 8, 1899, 1, 4294967295, 1459, 9, 39, 8, 1900, 1, 4294967295, 4294967295, 1, 39, 32, 1901, 1, 4294967295, 4294967295, 5, 39, 8, 1902, 1, 1462, 4294967295, 8, 39, 8, 1903, 1, 4294967295, 4294967295, 10, 39, 8, 1904, 2, 4294967295, 4294967295, 12, 39, 8, 1906, 1, 4294967295, 1465, 9, 39, 8, 1907, 1, 4294967295, 4294967295, 1, 39, 32, 1908, 1, 4294967295, 4294967295, 3, 39, 8, 1909, 2, 1468, 4294967295, 8, 39, 8, 1911, 1, 4294967295, 4294967295, 3, 39, 8, 1912, 2, 1470, 4294967295, 8, 39, 8, 1914, 1, 4294967295, 4294967295, 1, 39, 32, 1915, 1, 4294967295, 4294967295, 5, 39, 8, 1916, 1, 1473, 4294967295, 8, 39, 8, 1917, 1, 4294967295, 4294967295, 10, 39, 8, 1918, 2, 4294967295, 4294967295, 12, 39, 8, 1920, 1, 4294967295, 1476, 9, 39, 8, 1921, 1, 4294967295, 4294967295, 1, 39, 32, 1922, 1, 4294967295, 4294967295, 1, 39, 8, 1923, 1, 4294967295, 4294967295, 1, 40, 8, 1924, 1, 4294967295, 4294967295, 3, 40, 8, 1925, 2, 1481, 4294967295, 8, 40, 8, 1927, 1, 4294967295, 4294967295, 1, 40, 8, 1928, 1, 4294967295, 4294967295, 1, 40, 32, 1929, 1, 4294967295, 4294967295, 5, 40, 8, 1930, 1, 1485, 4294967295, 8, 40, 8, 1931, 1, 4294967295, 4294967295, 10, 40, 8, 1932, 2, 4294967295, 4294967295, 12, 40, 8, 1934, 1, 4294967295, 1488, 9, 40, 8, 1935, 1, 4294967295, 4294967295, 1, 40, 32, 1936, 1, 4294967295, 4294967295, 1, 40, 32, 1937, 1, 4294967295, 4294967295, 5, 40, 8, 1938, 1, 1492, 4294967295, 8, 40, 8, 1939, 1, 4294967295, 4294967295, 10, 40, 8, 1940, 2, 4294967295, 4294967295, 12, 40, 8, 1942, 1, 4294967295, 1495, 9, 40, 8, 1943, 1, 4294967295, 4294967295, 1, 40, 8, 1944, 1, 4294967295, 4294967295, 3, 40, 8, 1945, 2, 1498, 4294967295, 8, 40, 8, 1947, 1, 4294967295, 4294967295, 1, 41, 8, 1948, 1, 4294967295, 4294967295, 1, 41, 32, 1949, 1, 4294967295, 4294967295, 5, 41, 8, 1950, 1, 1502, 4294967295, 8, 41, 8, 1951, 1, 4294967295, 4294967295, 10, 41, 8, 1952, 2, 4294967295, 4294967295, 12, 41, 8, 1954, 1, 4294967295, 1505, 9, 41, 8, 1955, 1, 4294967295, 4294967295, 1, 41, 32, 1956, 1, 4294967295, 4294967295, 1, 41, 32, 1957, 1, 4294967295, 4294967295, 5, 41, 8, 1958, 1, 1509, 4294967295, 8, 41, 8, 1959, 1, 4294967295, 4294967295, 10, 41, 8, 1960, 2, 4294967295, 4294967295, 12, 41, 8, 1962, 1, 4294967295, 1512, 9, 41, 8, 1963, 1, 4294967295, 4294967295, 1, 41, 8, 1964, 1, 4294967295, 4294967295, 3, 41, 8, 1965, 2, 1515, 4294967295, 8, 41, 8, 1967, 1, 4294967295, 4294967295, 1, 42, 8, 1968, 1, 4294967295, 4294967295, 1, 42, 32, 1969, 1, 4294967295, 4294967295, 5, 42, 8, 1970, 1, 1519, 4294967295, 8, 42, 8, 1971, 1, 4294967295, 4294967295, 10, 42, 8, 1972, 2, 4294967295, 4294967295, 12, 42, 8, 1974, 1, 4294967295, 1522, 9, 42, 8, 1975, 1, 4294967295, 4294967295, 1, 42, 32, 1976, 1, 4294967295, 4294967295, 1, 42, 32, 1977, 1, 4294967295, 4294967295, 5, 42, 8, 1978, 1, 1526, 4294967295, 8, 42, 8, 1979, 1, 4294967295, 4294967295, 10, 42, 8, 1980, 2, 4294967295, 4294967295, 12, 42, 8, 1982, 1, 4294967295, 1529, 9, 42, 8, 1983, 1, 4294967295, 4294967295, 1, 42, 8, 1984, 1, 4294967295, 4294967295, 1, 42, 8, 1985, 1, 4294967295, 4294967295, 1, 43, 8, 1986, 1, 4294967295, 4294967295, 3, 43, 8, 1987, 2, 1534, 4294967295, 8, 43, 8, 1989, 1, 4294967295, 4294967295, 1, 43, 32, 1990, 1, 4294967295, 4294967295, 1, 43, 32, 1991, 1, 4294967295, 4294967295, 5, 43, 8, 1992, 1, 1538, 4294967295, 8, 43, 8, 1993, 1, 4294967295, 4294967295, 10, 43, 8, 1994, 2, 4294967295, 4294967295, 12, 43, 8, 1996, 1, 4294967295, 1541, 9, 43, 8, 1997, 1, 4294967295, 4294967295, 1, 43, 8, 1998, 1, 4294967295, 4294967295, 1, 43, 32, 1999, 1, 4294967295, 4294967295, 5, 43, 8, 2000, 1, 1545, 4294967295, 8, 43, 8, 2001, 1, 4294967295, 4294967295, 10, 43, 8, 2002, 2, 4294967295, 4294967295, 12, 43, 8, 2004, 1, 4294967295, 1548, 9, 43, 8, 2005, 1, 4294967295, 4294967295, 1, 43, 32, 2006, 1, 4294967295, 4294967295, 1, 43, 32, 2007, 1, 4294967295, 4294967295, 5, 43, 8, 2008, 1, 1552, 4294967295, 8, 43, 8, 2009, 1, 4294967295, 4294967295, 10, 43, 8, 2010, 2, 4294967295, 4294967295, 12, 43, 8, 2012, 1, 4294967295, 1555, 9, 43, 8, 2013, 1, 4294967295, 4294967295, 1, 43, 8, 2014, 1, 4294967295, 4294967295, 3, 43, 8, 2015, 2, 1558, 4294967295, 8, 43, 8, 2017, 1, 4294967295, 4294967295, 1, 43, 32, 2018, 1, 4294967295, 4294967295, 5, 43, 8, 2019, 1, 1561, 4294967295, 8, 43, 8, 2020, 1, 4294967295, 4294967295, 10, 43, 8, 2021, 2, 4294967295, 4294967295, 12, 43, 8, 2023, 1, 4294967295, 1564, 9, 43, 8, 2024, 1, 4294967295, 4294967295, 1, 43, 8, 2025, 1, 4294967295, 4294967295, 3, 43, 8, 2026, 2, 1567, 4294967295, 8, 43, 8, 2028, 1, 4294967295, 4294967295, 1, 44, 8, 2029, 1, 4294967295, 4294967295, 3, 44, 8, 2030, 2, 1570, 4294967295, 8, 44, 8, 2032, 1, 4294967295, 4294967295, 1, 44, 32, 2033, 1, 4294967295, 4294967295, 1, 44, 32, 2034, 1, 4294967295, 4294967295, 5, 44, 8, 2035, 1, 1574, 4294967295, 8, 44, 8, 2036, 1, 4294967295, 4294967295, 10, 44, 8, 2037, 2, 4294967295, 4294967295, 12, 44, 8, 2039, 1, 4294967295, 1577, 9, 44, 8, 2040, 1, 4294967295, 4294967295, 1, 44, 8, 2041, 1, 4294967295, 4294967295, 1, 44, 32, 2042, 1, 4294967295, 4294967295, 5, 44, 8, 2043, 1, 1581, 4294967295, 8, 44, 8, 2044, 1, 4294967295, 4294967295, 10, 44, 8, 2045, 2, 4294967295, 4294967295, 12, 44, 8, 2047, 1, 4294967295, 1584, 9, 44, 8, 2048, 1, 4294967295, 4294967295, 1, 44, 32, 2049, 1, 4294967295, 4294967295, 1, 44, 32, 2050, 1, 4294967295, 4294967295, 5, 44, 8, 2051, 1, 1588, 4294967295, 8, 44, 8, 2052, 1, 4294967295, 4294967295, 10, 44, 8, 2053, 2, 4294967295, 4294967295, 12, 44, 8, 2055, 1, 4294967295, 1591, 9, 44, 8, 2056, 1, 4294967295, 4294967295, 1, 44, 8, 2057, 1, 4294967295, 4294967295, 3, 44, 8, 2058, 2, 1594, 4294967295, 8, 44, 8, 2060, 1, 4294967295, 4294967295, 1, 44, 32, 2061, 1, 4294967295, 4294967295, 5, 44, 8, 2062, 1, 1597, 4294967295, 8, 44, 8, 2063, 1, 4294967295, 4294967295, 10, 44, 8, 2064, 2, 4294967295, 4294967295, 12, 44, 8, 2066, 1, 4294967295, 1600, 9, 44, 8, 2067, 1, 4294967295, 4294967295, 1, 44, 8, 2068, 1, 4294967295, 4294967295, 3, 44, 8, 2069, 2, 1603, 4294967295, 8, 44, 8, 2071, 1, 4294967295, 4294967295, 1, 45, 32, 2072, 1, 4294967295, 4294967295, 1, 45, 32, 2073, 1, 4294967295, 4294967295, 5, 45, 8, 2074, 1, 1607, 4294967295, 8, 45, 8, 2075, 1, 4294967295, 4294967295, 10, 45, 8, 2076, 2, 4294967295, 4294967295, 12, 45, 8, 2078, 1, 4294967295, 1610, 9, 45, 8, 2079, 1, 4294967295, 4294967295, 1, 45, 8, 2080, 1, 4294967295, 4294967295, 1, 45, 8, 2081, 1, 4294967295, 4294967295, 1, 46, 32, 2082, 1, 4294967295, 4294967295, 1, 46, 32, 2083, 1, 4294967295, 4294967295, 5, 46, 8, 2084, 1, 1616, 4294967295, 8, 46, 8, 2085, 1, 4294967295, 4294967295, 10, 46, 8, 2086, 2, 4294967295, 4294967295, 12, 46, 8, 2088, 1, 4294967295, 1619, 9, 46, 8, 2089, 1, 4294967295, 4294967295, 1, 46, 8, 2090, 1, 4294967295, 4294967295, 3, 46, 8, 2091, 2, 1622, 4294967295, 8, 46, 8, 2093, 1, 4294967295, 4294967295, 1, 46, 32, 2094, 1, 4294967295, 4294967295, 5, 46, 8, 2095, 1, 1625, 4294967295, 8, 46, 8, 2096, 1, 4294967295, 4294967295, 10, 46, 8, 2097, 2, 4294967295, 4294967295, 12, 46, 8, 2099, 1, 4294967295, 1628, 9, 46, 8, 2100, 1, 4294967295, 4294967295, 1, 46, 32, 2101, 1, 4294967295, 4294967295, 1, 46, 32, 2102, 1, 4294967295, 4294967295, 5, 46, 8, 2103, 1, 1632, 4294967295, 8, 46, 8, 2104, 1, 4294967295, 4294967295, 10, 46, 8, 2105, 2, 4294967295, 4294967295, 12, 46, 8, 2107, 1, 4294967295, 1635, 9, 46, 8, 2108, 1, 4294967295, 4294967295, 1, 46, 8, 2109, 1, 4294967295, 4294967295, 3, 46, 8, 2110, 2, 1638, 4294967295, 8, 46, 8, 2112, 1, 4294967295, 4294967295, 1, 46, 32, 2113, 1, 4294967295, 4294967295, 5, 46, 8, 2114, 1, 1641, 4294967295, 8, 46, 8, 2115, 1, 4294967295, 4294967295, 10, 46, 8, 2116, 2, 4294967295, 4294967295, 12, 46, 8, 2118, 1, 4294967295, 1644, 9, 46, 8, 2119, 1, 4294967295, 4294967295, 1, 46, 32, 2120, 1, 4294967295, 4294967295, 1, 46, 8, 2121, 1, 4294967295, 4294967295, 1, 47, 8, 2122, 1, 4294967295, 4294967295, 1, 47, 32, 2123, 1, 4294967295, 4294967295, 5, 47, 8, 2124, 1, 1650, 4294967295, 8, 47, 8, 2125, 1, 4294967295, 4294967295, 10, 47, 8, 2126, 2, 4294967295, 4294967295, 12, 47, 8, 2128, 1, 4294967295, 1653, 9, 47, 8, 2129, 1, 4294967295, 4294967295, 1, 47, 32, 2130, 1, 4294967295, 4294967295, 1, 47, 32, 2131, 1, 4294967295, 4294967295, 5, 47, 8, 2132, 1, 1657, 4294967295, 8, 47, 8, 2133, 1, 4294967295, 4294967295, 10, 47, 8, 2134, 2, 4294967295, 4294967295, 12, 47, 8, 2136, 1, 4294967295, 1660, 9, 47, 8, 2137, 1, 4294967295, 4294967295, 1, 47, 8, 2138, 1, 4294967295, 4294967295, 5, 47, 8, 2139, 1, 1663, 4294967295, 8, 47, 8, 2140, 1, 4294967295, 4294967295, 10, 47, 8, 2141, 2, 4294967295, 4294967295, 12, 47, 8, 2143, 1, 4294967295, 1666, 9, 47, 8, 2144, 1, 4294967295, 4294967295, 1, 47, 32, 2145, 1, 4294967295, 4294967295, 5, 47, 8, 2146, 1, 1669, 4294967295, 8, 47, 8, 2147, 1, 4294967295, 4294967295, 10, 47, 8, 2148, 2, 4294967295, 4294967295, 12, 47, 8, 2150, 1, 4294967295, 1672, 9, 47, 8, 2151, 1, 4294967295, 4294967295, 1, 47, 32, 2152, 1, 4294967295, 4294967295, 3, 47, 8, 2153, 2, 1675, 4294967295, 8, 47, 8, 2155, 1, 4294967295, 4294967295, 1, 48, 8, 2156, 1, 4294967295, 4294967295, 1, 48, 32, 2157, 1, 4294967295, 4294967295, 5, 48, 8, 2158, 1, 1679, 4294967295, 8, 48, 8, 2159, 1, 4294967295, 4294967295, 10, 48, 8, 2160, 2, 4294967295, 4294967295, 12, 48, 8, 2162, 1, 4294967295, 1682, 9, 48, 8, 2163, 1, 4294967295, 4294967295, 3, 48, 8, 2164, 2, 1684, 4294967295, 8, 48, 8, 2166, 1, 4294967295, 4294967295, 1, 48, 8, 2167, 1, 4294967295, 4294967295, 1, 48, 32, 2168, 1, 4294967295, 4294967295, 5, 48, 8, 2169, 1, 1688, 4294967295, 8, 48, 8, 2170, 1, 4294967295, 4294967295, 10, 48, 8, 2171, 2, 4294967295, 4294967295, 12, 48, 8, 2173, 1, 4294967295, 1691, 9, 48, 8, 2174, 1, 4294967295, 4294967295, 1, 48, 8, 2175, 1, 4294967295, 4294967295, 3, 48, 8, 2176, 2, 1694, 4294967295, 8, 48, 8, 2178, 1, 4294967295, 4294967295, 1, 48, 32, 2179, 1, 4294967295, 4294967295, 5, 48, 8, 2180, 1, 1697, 4294967295, 8, 48, 8, 2181, 1, 4294967295, 4294967295, 10, 48, 8, 2182, 2, 4294967295, 4294967295, 12, 48, 8, 2184, 1, 4294967295, 1700, 9, 48, 8, 2185, 1, 4294967295, 4294967295, 1, 48, 8, 2186, 1, 4294967295, 4294967295, 3, 48, 8, 2187, 2, 1703, 4294967295, 8, 48, 8, 2189, 1, 4294967295, 4294967295, 1, 49, 8, 2190, 1, 4294967295, 4294967295, 3, 49, 8, 2191, 2, 1706, 4294967295, 8, 49, 8, 2193, 1, 4294967295, 4294967295, 1, 49, 8, 2194, 1, 4294967295, 4294967295, 1, 49, 8, 2195, 1, 4294967295, 4294967295, 1, 49, 8, 2196, 1, 4294967295, 4294967295, 1, 49, 8, 2197, 1, 4294967295, 4294967295, 1, 49, 8, 2198, 1, 4294967295, 4294967295, 3, 49, 8, 2199, 5, 1713, 4294967295, 8, 49, 8, 2204, 1, 4294967295, 4294967295, 1, 50, 8, 2205, 1, 4294967295, 4294967295, 1, 50, 32, 2206, 1, 4294967295, 4294967295, 3, 50, 8, 2207, 2, 1717, 4294967295, 8, 50, 8, 2209, 1, 4294967295, 4294967295, 1, 51, 8, 2210, 1, 4294967295, 4294967295, 1, 51, 8, 2211, 1, 4294967295, 4294967295, 3, 51, 8, 2212, 2, 1721, 4294967295, 8, 51, 8, 2214, 1, 4294967295, 4294967295, 1, 51, 32, 2215, 1, 4294967295, 4294967295, 5, 51, 8, 2216, 1, 1724, 4294967295, 8, 51, 8, 2217, 1, 4294967295, 4294967295, 10, 51, 8, 2218, 2, 4294967295, 4294967295, 12, 51, 8, 2220, 1, 4294967295, 1727, 9, 51, 8, 2221, 1, 4294967295, 4294967295, 1, 51, 8, 2222, 1, 4294967295, 4294967295, 4, 51, 8, 2223, 1, 1730, 4294967295, 8, 51, 8, 2224, 1, 4294967295, 4294967295, 11, 51, 8, 2225, 2, 4294967295, 4294967295, 12, 51, 8, 2227, 1, 4294967295, 1731, 1, 52, 32, 2228, 1, 4294967295, 4294967295, 1, 52, 8, 2229, 1, 4294967295, 4294967295, 1, 53, 8, 2230, 1, 4294967295, 4294967295, 1, 53, 32, 2231, 1, 4294967295, 4294967295, 5, 53, 8, 2232, 1, 1738, 4294967295, 8, 53, 8, 2233, 1, 4294967295, 4294967295, 10, 53, 8, 2234, 2, 4294967295, 4294967295, 12, 53, 8, 2236, 1, 4294967295, 1741, 9, 53, 8, 2237, 1, 4294967295, 4294967295, 1, 53, 32, 2238, 1, 4294967295, 4294967295, 1, 53, 32, 2239, 1, 4294967295, 4294967295, 5, 53, 8, 2240, 1, 1745, 4294967295, 8, 53, 8, 2241, 1, 4294967295, 4294967295, 10, 53, 8, 2242, 2, 4294967295, 4294967295, 12, 53, 8, 2244, 1, 4294967295, 1748, 9, 53, 8, 2245, 1, 4294967295, 4294967295, 1, 53, 8, 2246, 1, 4294967295, 4294967295, 5, 53, 8, 2247, 1, 1751, 4294967295, 8, 53, 8, 2248, 1, 4294967295, 4294967295, 10, 53, 8, 2249, 2, 4294967295, 4294967295, 12, 53, 8, 2251, 1, 4294967295, 1754, 9, 53, 8, 2252, 1, 4294967295, 4294967295, 1, 54, 8, 2253, 1, 4294967295, 4294967295, 1, 54, 32, 2254, 1, 4294967295, 4294967295, 5, 54, 8, 2255, 1, 1758, 4294967295, 8, 54, 8, 2256, 1, 4294967295, 4294967295, 10, 54, 8, 2257, 2, 4294967295, 4294967295, 12, 54, 8, 2259, 1, 4294967295, 1761, 9, 54, 8, 2260, 1, 4294967295, 4294967295, 1, 54, 8, 2261, 1, 4294967295, 4294967295, 3, 54, 8, 2262, 2, 1764, 4294967295, 8, 54, 8, 2264, 1, 4294967295, 4294967295, 1, 55, 8, 2265, 1, 4294967295, 4294967295, 3, 55, 8, 2266, 2, 1767, 4294967295, 8, 55, 8, 2268, 1, 4294967295, 4294967295, 1, 55, 8, 2269, 1, 4294967295, 4294967295, 1, 55, 32, 2270, 1, 4294967295, 4294967295, 3, 55, 8, 2271, 2, 1771, 4294967295, 8, 55, 8, 2273, 1, 4294967295, 4294967295, 1, 56, 8, 2274, 1, 4294967295, 4294967295, 4, 56, 8, 2275, 1, 1774, 4294967295, 8, 56, 8, 2276, 1, 4294967295, 4294967295, 11, 56, 8, 2277, 2, 4294967295, 4294967295, 12, 56, 8, 2279, 1, 4294967295, 1775, 1, 57, 8, 2280, 1, 4294967295, 4294967295, 1, 57, 32, 2281, 1, 4294967295, 4294967295, 5, 57, 8, 2282, 1, 1780, 4294967295, 8, 57, 8, 2283, 1, 4294967295, 4294967295, 10, 57, 8, 2284, 2, 4294967295, 4294967295, 12, 57, 8, 2286, 1, 4294967295, 1783, 9, 57, 8, 2287, 1, 4294967295, 4294967295, 1, 57, 8, 2288, 1, 4294967295, 4294967295, 3, 57, 8, 2289, 2, 1786, 4294967295, 8, 57, 8, 2291, 1, 4294967295, 4294967295, 1, 58, 8, 2292, 1, 4294967295, 4294967295, 1, 58, 32, 2293, 1, 4294967295, 4294967295, 5, 58, 8, 2294, 1, 1790, 4294967295, 8, 58, 8, 2295, 1, 4294967295, 4294967295, 10, 58, 8, 2296, 2, 4294967295, 4294967295, 12, 58, 8, 2298, 1, 4294967295, 1793, 9, 58, 8, 2299, 1, 4294967295, 4294967295, 1, 58, 32, 2300, 1, 4294967295, 4294967295, 1, 58, 32, 2301, 1, 4294967295, 4294967295, 5, 58, 8, 2302, 1, 1797, 4294967295, 8, 58, 8, 2303, 1, 4294967295, 4294967295, 10, 58, 8, 2304, 2, 4294967295, 4294967295, 12, 58, 8, 2306, 1, 4294967295, 1800, 9, 58, 8, 2307, 1, 4294967295, 4294967295, 3, 58, 8, 2308, 2, 1802, 4294967295, 8, 58, 8, 2310, 1, 4294967295, 4294967295, 1, 58, 8, 2311, 1, 4294967295, 4294967295, 1, 58, 32, 2312, 1, 4294967295, 4294967295, 5, 58, 8, 2313, 1, 1806, 4294967295, 8, 58, 8, 2314, 1, 4294967295, 4294967295, 10, 58, 8, 2315, 2, 4294967295, 4294967295, 12, 58, 8, 2317, 1, 4294967295, 1809, 9, 58, 8, 2318, 1, 4294967295, 4294967295, 1, 58, 32, 2319, 1, 4294967295, 4294967295, 1, 58, 32, 2320, 1, 4294967295, 4294967295, 5, 58, 8, 2321, 1, 1813, 4294967295, 8, 58, 8, 2322, 1, 4294967295, 4294967295, 10, 58, 8, 2323, 2, 4294967295, 4294967295, 12, 58, 8, 2325, 1, 4294967295, 1816, 9, 58, 8, 2326, 1, 4294967295, 4294967295, 1, 58, 8, 2327, 1, 4294967295, 4294967295, 1, 58, 8, 2328, 1, 4294967295, 4294967295, 1, 59, 32, 2329, 1, 4294967295, 4294967295, 1, 59, 32, 2330, 1, 4294967295, 4294967295, 5, 59, 8, 2331, 1, 1822, 4294967295, 8, 59, 8, 2332, 1, 4294967295, 4294967295, 10, 59, 8, 2333, 2, 4294967295, 4294967295, 12, 59, 8, 2335, 1, 4294967295, 1825, 9, 59, 8, 2336, 1, 4294967295, 4294967295, 1, 59, 8, 2337, 1, 4294967295, 4294967295, 1, 59, 8, 2338, 1, 4294967295, 4294967295, 3, 59, 8, 2339, 3, 1829, 4294967295, 8, 59, 8, 2342, 1, 4294967295, 4294967295, 1, 59, 32, 2343, 1, 4294967295, 4294967295, 5, 59, 8, 2344, 1, 1832, 4294967295, 8, 59, 8, 2345, 1, 4294967295, 4294967295, 10, 59, 8, 2346, 2, 4294967295, 4294967295, 12, 59, 8, 2348, 1, 4294967295, 1835, 9, 59, 8, 2349, 1, 4294967295, 4294967295, 1, 59, 32, 2350, 1, 4294967295, 4294967295, 1, 59, 32, 2351, 1, 4294967295, 4294967295, 5, 59, 8, 2352, 1, 1839, 4294967295, 8, 59, 8, 2353, 1, 4294967295, 4294967295, 10, 59, 8, 2354, 2, 4294967295, 4294967295, 12, 59, 8, 2356, 1, 4294967295, 1842, 9, 59, 8, 2357, 1, 4294967295, 4294967295, 1, 59, 8, 2358, 1, 4294967295, 4294967295, 1, 59, 8, 2359, 1, 4294967295, 4294967295, 3, 59, 8, 2360, 2, 1846, 4294967295, 8, 59, 8, 2362, 1, 4294967295, 4294967295, 5, 59, 8, 2363, 1, 1848, 4294967295, 8, 59, 8, 2364, 1, 4294967295, 4294967295, 10, 59, 8, 2365, 2, 4294967295, 4294967295, 12, 59, 8, 2367, 1, 4294967295, 1851, 9, 59, 8, 2368, 1, 4294967295, 4294967295, 1, 59, 32, 2369, 1, 4294967295, 4294967295, 5, 59, 8, 2370, 1, 1854, 4294967295, 8, 59, 8, 2371, 1, 4294967295, 4294967295, 10, 59, 8, 2372, 2, 4294967295, 4294967295, 12, 59, 8, 2374, 1, 4294967295, 1857, 9, 59, 8, 2375, 1, 4294967295, 4294967295, 1, 59, 32, 2376, 1, 4294967295, 4294967295, 3, 59, 8, 2377, 2, 1860, 4294967295, 8, 59, 8, 2379, 1, 4294967295, 4294967295, 1, 59, 32, 2380, 1, 4294967295, 4294967295, 5, 59, 8, 2381, 1, 1863, 4294967295, 8, 59, 8, 2382, 1, 4294967295, 4294967295, 10, 59, 8, 2383, 2, 4294967295, 4294967295, 12, 59, 8, 2385, 1, 4294967295, 1866, 9, 59, 8, 2386, 1, 4294967295, 4294967295, 1, 59, 32, 2387, 1, 4294967295, 4294967295, 1, 59, 8, 2388, 1, 4294967295, 4294967295, 1, 60, 32, 2389, 1, 4294967295, 4294967295, 1, 60, 32, 2390, 1, 4294967295, 4294967295, 5, 60, 8, 2391, 1, 1872, 4294967295, 8, 60, 8, 2392, 1, 4294967295, 4294967295, 10, 60, 8, 2393, 2, 4294967295, 4294967295, 12, 60, 8, 2395, 1, 4294967295, 1875, 9, 60, 8, 2396, 1, 4294967295, 4294967295, 1, 60, 8, 2397, 1, 4294967295, 4294967295, 1, 60, 32, 2398, 1, 4294967295, 4294967295, 5, 60, 8, 2399, 1, 1879, 4294967295, 8, 60, 8, 2400, 1, 4294967295, 4294967295, 10, 60, 8, 2401, 2, 4294967295, 4294967295, 12, 60, 8, 2403, 1, 4294967295, 1882, 9, 60, 8, 2404, 1, 4294967295, 4294967295, 1, 60, 32, 2405, 1, 4294967295, 4294967295, 1, 60, 8, 2406, 1, 4294967295, 4294967295, 1, 61, 8, 2407, 1, 4294967295, 4294967295, 3, 61, 8, 2408, 2, 1887, 4294967295, 8, 61, 8, 2410, 1, 4294967295, 4294967295, 1, 61, 8, 2411, 1, 4294967295, 4294967295, 1, 61, 8, 2412, 1, 4294967295, 4294967295, 1, 61, 8, 2413, 1, 4294967295, 4294967295, 3, 61, 8, 2414, 3, 1892, 4294967295, 8, 61, 8, 2417, 1, 4294967295, 4294967295, 1, 62, 32, 2418, 1, 4294967295, 4294967295, 1, 62, 32, 2419, 1, 4294967295, 4294967295, 5, 62, 8, 2420, 1, 1896, 4294967295, 8, 62, 8, 2421, 1, 4294967295, 4294967295, 10, 62, 8, 2422, 2, 4294967295, 4294967295, 12, 62, 8, 2424, 1, 4294967295, 1899, 9, 62, 8, 2425, 1, 4294967295, 4294967295, 1, 62, 8, 2426, 1, 4294967295, 4294967295, 1, 62, 8, 2427, 1, 4294967295, 4294967295, 3, 62, 8, 2428, 2, 1903, 4294967295, 8, 62, 8, 2430, 1, 4294967295, 4294967295, 1, 62, 32, 2431, 1, 4294967295, 4294967295, 5, 62, 8, 2432, 1, 1906, 4294967295, 8, 62, 8, 2433, 1, 4294967295, 4294967295, 10, 62, 8, 2434, 2, 4294967295, 4294967295, 12, 62, 8, 2436, 1, 4294967295, 1909, 9, 62, 8, 2437, 1, 4294967295, 4294967295, 1, 62, 32, 2438, 1, 4294967295, 4294967295, 1, 62, 8, 2439, 1, 4294967295, 4294967295, 1, 63, 8, 2440, 1, 4294967295, 4294967295, 3, 63, 8, 2441, 2, 1914, 4294967295, 8, 63, 8, 2443, 1, 4294967295, 4294967295, 1, 63, 8, 2444, 1, 4294967295, 4294967295, 1, 63, 8, 2445, 1, 4294967295, 4294967295, 3, 63, 8, 2446, 2, 1918, 4294967295, 8, 63, 8, 2448, 1, 4294967295, 4294967295, 1, 63, 32, 2449, 1, 4294967295, 4294967295, 5, 63, 8, 2450, 1, 1921, 4294967295, 8, 63, 8, 2451, 1, 4294967295, 4294967295, 10, 63, 8, 2452, 2, 4294967295, 4294967295, 12, 63, 8, 2454, 1, 4294967295, 1924, 9, 63, 8, 2455, 1, 4294967295, 4294967295, 1, 63, 32, 2456, 1, 4294967295, 4294967295, 1, 63, 32, 2457, 1, 4294967295, 4294967295, 5, 63, 8, 2458, 1, 1928, 4294967295, 8, 63, 8, 2459, 1, 4294967295, 4294967295, 10, 63, 8, 2460, 2, 4294967295, 4294967295, 12, 63, 8, 2462, 1, 4294967295, 1931, 9, 63, 8, 2463, 1, 4294967295, 4294967295, 1, 63, 8, 2464, 1, 4294967295, 4294967295, 3, 63, 8, 2465, 2, 1934, 4294967295, 8, 63, 8, 2467, 1, 4294967295, 4294967295, 1, 63, 8, 2468, 1, 4294967295, 4294967295, 1, 63, 8, 2469, 1, 4294967295, 4294967295, 3, 63, 8, 2470, 2, 1938, 4294967295, 8, 63, 8, 2472, 1, 4294967295, 4294967295, 1, 64, 8, 2473, 1, 4294967295, 4294967295, 1, 64, 8, 2474, 1, 4294967295, 4294967295, 1, 64, 8, 2475, 1, 4294967295, 4294967295, 1, 64, 8, 2476, 1, 4294967295, 4294967295, 5, 64, 8, 2477, 1, 1944, 4294967295, 8, 64, 8, 2478, 1, 4294967295, 4294967295, 10, 64, 8, 2479, 2, 4294967295, 4294967295, 12, 64, 8, 2481, 1, 4294967295, 1947, 9, 64, 8, 2482, 1, 4294967295, 4294967295, 3, 64, 8, 2483, 2, 1949, 4294967295, 8, 64, 8, 2485, 1, 4294967295, 4294967295, 1, 64, 8, 2486, 1, 4294967295, 4294967295, 3, 64, 8, 2487, 2, 1952, 4294967295, 8, 64, 8, 2489, 1, 4294967295, 4294967295, 1, 65, 8, 2490, 1, 4294967295, 4294967295, 1, 65, 8, 2491, 1, 4294967295, 4294967295, 5, 65, 8, 2492, 2, 1956, 4294967295, 8, 65, 8, 2494, 1, 4294967295, 4294967295, 10, 65, 8, 2495, 2, 4294967295, 4294967295, 12, 65, 8, 2497, 1, 4294967295, 1959, 9, 65, 8, 2498, 1, 4294967295, 4294967295, 1, 65, 8, 2499, 1, 4294967295, 4294967295, 1, 65, 8, 2500, 1, 4294967295, 4294967295, 1, 65, 8, 2501, 1, 4294967295, 4294967295, 1, 65, 8, 2502, 1, 4294967295, 4294967295, 3, 65, 8, 2503, 4, 1965, 4294967295, 8, 65, 8, 2507, 1, 4294967295, 4294967295, 1, 66, 8, 2508, 1, 4294967295, 4294967295, 1, 66, 32, 2509, 1, 4294967295, 4294967295, 1, 66, 32, 2510, 1, 4294967295, 4294967295, 5, 66, 8, 2511, 1, 1970, 4294967295, 8, 66, 8, 2512, 1, 4294967295, 4294967295, 10, 66, 8, 2513, 2, 4294967295, 4294967295, 12, 66, 8, 2515, 1, 4294967295, 1973, 9, 66, 8, 2516, 1, 4294967295, 4294967295, 1, 67, 8, 2517, 1, 4294967295, 4294967295, 1, 67, 8, 2518, 1, 4294967295, 4294967295, 3, 67, 8, 2519, 2, 1977, 4294967295, 8, 67, 8, 2521, 1, 4294967295, 4294967295, 1, 68, 32, 2522, 1, 4294967295, 4294967295, 1, 68, 32, 2523, 1, 4294967295, 4294967295, 5, 68, 8, 2524, 1, 1981, 4294967295, 8, 68, 8, 2525, 1, 4294967295, 4294967295, 10, 68, 8, 2526, 2, 4294967295, 4294967295, 12, 68, 8, 2528, 1, 4294967295, 1984, 9, 68, 8, 2529, 1, 4294967295, 4294967295, 1, 68, 8, 2530, 1, 4294967295, 4294967295, 1, 68, 32, 2531, 1, 4294967295, 4294967295, 5, 68, 8, 2532, 1, 1988, 4294967295, 8, 68, 8, 2533, 1, 4294967295, 4294967295, 10, 68, 8, 2534, 2, 4294967295, 4294967295, 12, 68, 8, 2536, 1, 4294967295, 1991, 9, 68, 8, 2537, 1, 4294967295, 4294967295, 1, 68, 32, 2538, 1, 4294967295, 4294967295, 1, 68, 8, 2539, 1, 4294967295, 4294967295, 1, 69, 8, 2540, 1, 4294967295, 4294967295, 1, 69, 8, 2541, 1, 4294967295, 4294967295, 1, 69, 8, 2542, 1, 4294967295, 4294967295, 3, 69, 8, 2543, 3, 1998, 4294967295, 8, 69, 8, 2546, 1, 4294967295, 4294967295, 1, 70, 32, 2547, 1, 4294967295, 4294967295, 1, 70, 32, 2548, 1, 4294967295, 4294967295, 5, 70, 8, 2549, 1, 2002, 4294967295, 8, 70, 8, 2550, 1, 4294967295, 4294967295, 10, 70, 8, 2551, 2, 4294967295, 4294967295, 12, 70, 8, 2553, 1, 4294967295, 2005, 9, 70, 8, 2554, 1, 4294967295, 4294967295, 1, 70, 32, 2555, 1, 4294967295, 4294967295, 1, 70, 8, 2556, 1, 4294967295, 4294967295, 5, 70, 8, 2557, 1, 2009, 4294967295, 8, 70, 8, 2558, 1, 4294967295, 4294967295, 10, 70, 8, 2559, 2, 4294967295, 4294967295, 12, 70, 8, 2561, 1, 4294967295, 2012, 9, 70, 8, 2562, 1, 4294967295, 4294967295, 1, 70, 8, 2563, 1, 4294967295, 4294967295, 1, 70, 8, 2564, 1, 4294967295, 4294967295, 3, 70, 8, 2565, 2, 2016, 4294967295, 8, 70, 8, 2567, 1, 4294967295, 4294967295, 1, 70, 32, 2568, 1, 4294967295, 4294967295, 1, 70, 8, 2569, 1, 4294967295, 4294967295, 1, 70, 32, 2570, 1, 4294967295, 4294967295, 1, 70, 32, 2571, 1, 4294967295, 4294967295, 5, 70, 8, 2572, 1, 2022, 4294967295, 8, 70, 8, 2573, 1, 4294967295, 4294967295, 10, 70, 8, 2574, 2, 4294967295, 4294967295, 12, 70, 8, 2576, 1, 4294967295, 2025, 9, 70, 8, 2577, 1, 4294967295, 4294967295, 1, 70, 8, 2578, 1, 4294967295, 4294967295, 3, 70, 8, 2579, 2, 2028, 4294967295, 8, 70, 8, 2581, 1, 4294967295, 4294967295, 1, 71, 32, 2582, 1, 4294967295, 4294967295, 1, 71, 32, 2583, 1, 4294967295, 4294967295, 5, 71, 8, 2584, 1, 2032, 4294967295, 8, 71, 8, 2585, 1, 4294967295, 4294967295, 10, 71, 8, 2586, 2, 4294967295, 4294967295, 12, 71, 8, 2588, 1, 4294967295, 2035, 9, 71, 8, 2589, 1, 4294967295, 4294967295, 1, 71, 32, 2590, 1, 4294967295, 4294967295, 1, 71, 8, 2591, 1, 4294967295, 4294967295, 1, 71, 32, 2592, 1, 4294967295, 4294967295, 1, 71, 32, 2593, 1, 4294967295, 4294967295, 5, 71, 8, 2594, 1, 2041, 4294967295, 8, 71, 8, 2595, 1, 4294967295, 4294967295, 10, 71, 8, 2596, 2, 4294967295, 4294967295, 12, 71, 8, 2598, 1, 4294967295, 2044, 9, 71, 8, 2599, 1, 4294967295, 4294967295, 1, 71, 8, 2600, 1, 4294967295, 4294967295, 1, 71, 32, 2601, 1, 4294967295, 4294967295, 3, 71, 8, 2602, 2, 2048, 4294967295, 8, 71, 8, 2604, 1, 4294967295, 4294967295, 1, 72, 32, 2605, 1, 4294967295, 4294967295, 1, 72, 32, 2606, 1, 4294967295, 4294967295, 5, 72, 8, 2607, 1, 2052, 4294967295, 8, 72, 8, 2608, 1, 4294967295, 4294967295, 10, 72, 8, 2609, 2, 4294967295, 4294967295, 12, 72, 8, 2611, 1, 4294967295, 2055, 9, 72, 8, 2612, 1, 4294967295, 4294967295, 1, 72, 8, 2613, 1, 4294967295, 4294967295, 3, 72, 8, 2614, 2, 2058, 4294967295, 8, 72, 8, 2616, 1, 4294967295, 4294967295, 1, 72, 32, 2617, 1, 4294967295, 4294967295, 5, 72, 8, 2618, 1, 2061, 4294967295, 8, 72, 8, 2619, 1, 4294967295, 4294967295, 10, 72, 8, 2620, 2, 4294967295, 4294967295, 12, 72, 8, 2622, 1, 4294967295, 2064, 9, 72, 8, 2623, 1, 4294967295, 4294967295, 1, 72, 32, 2624, 1, 4294967295, 4294967295, 1, 72, 32, 2625, 1, 4294967295, 4294967295, 5, 72, 8, 2626, 1, 2068, 4294967295, 8, 72, 8, 2627, 1, 4294967295, 4294967295, 10, 72, 8, 2628, 2, 4294967295, 4294967295, 12, 72, 8, 2630, 1, 4294967295, 2071, 9, 72, 8, 2631, 1, 4294967295, 4294967295, 1, 72, 32, 2632, 1, 4294967295, 4294967295, 1, 72, 8, 2633, 1, 4294967295, 4294967295, 1, 72, 32, 2634, 1, 4294967295, 4294967295, 1, 72, 8, 2635, 1, 4294967295, 4294967295, 1, 73, 8, 2636, 1, 4294967295, 4294967295, 1, 73, 32, 2637, 1, 4294967295, 4294967295, 1, 73, 8, 2638, 1, 4294967295, 4294967295, 1, 73, 8, 2639, 1, 4294967295, 4294967295, 1, 73, 8, 2640, 1, 4294967295, 4294967295, 1, 73, 8, 2641, 1, 4294967295, 4294967295, 3, 73, 8, 2642, 2, 2083, 4294967295, 8, 73, 8, 2644, 1, 4294967295, 4294967295, 1, 73, 32, 2645, 1, 4294967295, 4294967295, 5, 73, 8, 2646, 1, 2086, 4294967295, 8, 73, 8, 2647, 1, 4294967295, 4294967295, 10, 73, 8, 2648, 2, 4294967295, 4294967295, 12, 73, 8, 2650, 1, 4294967295, 2089, 9, 73, 8, 2651, 1, 4294967295, 4294967295, 1, 73, 8, 2652, 1, 4294967295, 4294967295, 1, 73, 8, 2653, 1, 4294967295, 4294967295, 1, 74, 32, 2654, 1, 4294967295, 4294967295, 1, 74, 32, 2655, 1, 4294967295, 4294967295, 5, 74, 8, 2656, 1, 2095, 4294967295, 8, 74, 8, 2657, 1, 4294967295, 4294967295, 10, 74, 8, 2658, 2, 4294967295, 4294967295, 12, 74, 8, 2660, 1, 4294967295, 2098, 9, 74, 8, 2661, 1, 4294967295, 4294967295, 1, 75, 32, 2662, 1, 4294967295, 4294967295, 4, 75, 8, 2663, 1, 2101, 4294967295, 8, 75, 8, 2664, 1, 4294967295, 4294967295, 11, 75, 8, 2665, 2, 4294967295, 4294967295, 12, 75, 8, 2667, 1, 4294967295, 2102, 1, 76, 8, 2668, 1, 4294967295, 4294967295, 1, 76, 8, 2669, 1, 4294967295, 4294967295, 1, 77, 8, 2670, 1, 4294967295, 4294967295, 1, 77, 32, 2671, 1, 4294967295, 4294967295, 5, 77, 8, 2672, 1, 2109, 4294967295, 8, 77, 8, 2673, 1, 4294967295, 4294967295, 10, 77, 8, 2674, 2, 4294967295, 4294967295, 12, 77, 8, 2676, 1, 4294967295, 2112, 9, 77, 8, 2677, 1, 4294967295, 4294967295, 1, 77, 32, 2678, 1, 4294967295, 4294967295, 1, 77, 32, 2679, 1, 4294967295, 4294967295, 5, 77, 8, 2680, 1, 2116, 4294967295, 8, 77, 8, 2681, 1, 4294967295, 4294967295, 10, 77, 8, 2682, 2, 4294967295, 4294967295, 12, 77, 8, 2684, 1, 4294967295, 2119, 9, 77, 8, 2685, 1, 4294967295, 4294967295, 1, 77, 8, 2686, 1, 4294967295, 4294967295, 5, 77, 8, 2687, 1, 2122, 4294967295, 8, 77, 8, 2688, 1, 4294967295, 4294967295, 10, 77, 8, 2689, 2, 4294967295, 4294967295, 12, 77, 8, 2691, 1, 4294967295, 2125, 9, 77, 8, 2692, 1, 4294967295, 4294967295, 1, 78, 8, 2693, 1, 4294967295, 4294967295, 1, 78, 32, 2694, 1, 4294967295, 4294967295, 5, 78, 8, 2695, 1, 2129, 4294967295, 8, 78, 8, 2696, 1, 4294967295, 4294967295, 10, 78, 8, 2697, 2, 4294967295, 4294967295, 12, 78, 8, 2699, 1, 4294967295, 2132, 9, 78, 8, 2700, 1, 4294967295, 4294967295, 1, 78, 32, 2701, 1, 4294967295, 4294967295, 1, 78, 32, 2702, 1, 4294967295, 4294967295, 5, 78, 8, 2703, 1, 2136, 4294967295, 8, 78, 8, 2704, 1, 4294967295, 4294967295, 10, 78, 8, 2705, 2, 4294967295, 4294967295, 12, 78, 8, 2707, 1, 4294967295, 2139, 9, 78, 8, 2708, 1, 4294967295, 4294967295, 1, 78, 8, 2709, 1, 4294967295, 4294967295, 5, 78, 8, 2710, 1, 2142, 4294967295, 8, 78, 8, 2711, 1, 4294967295, 4294967295, 10, 78, 8, 2712, 2, 4294967295, 4294967295, 12, 78, 8, 2714, 1, 4294967295, 2145, 9, 78, 8, 2715, 1, 4294967295, 4294967295, 1, 79, 8, 2716, 1, 4294967295, 4294967295, 1, 79, 8, 2717, 1, 4294967295, 4294967295, 1, 79, 32, 2718, 1, 4294967295, 4294967295, 5, 79, 8, 2719, 1, 2150, 4294967295, 8, 79, 8, 2720, 1, 4294967295, 4294967295, 10, 79, 8, 2721, 2, 4294967295, 4294967295, 12, 79, 8, 2723, 1, 4294967295, 2153, 9, 79, 8, 2724, 1, 4294967295, 4294967295, 1, 79, 8, 2725, 1, 4294967295, 4294967295, 1, 79, 8, 2726, 1, 4294967295, 4294967295, 5, 79, 8, 2727, 1, 2157, 4294967295, 8, 79, 8, 2728, 1, 4294967295, 4294967295, 10, 79, 8, 2729, 2, 4294967295, 4294967295, 12, 79, 8, 2731, 1, 4294967295, 2160, 9, 79, 8, 2732, 1, 4294967295, 4294967295, 1, 80, 8, 2733, 1, 4294967295, 4294967295, 1, 80, 8, 2734, 1, 4294967295, 4294967295, 1, 80, 32, 2735, 1, 4294967295, 4294967295, 5, 80, 8, 2736, 1, 2165, 4294967295, 8, 80, 8, 2737, 1, 4294967295, 4294967295, 10, 80, 8, 2738, 2, 4294967295, 4294967295, 12, 80, 8, 2740, 1, 4294967295, 2168, 9, 80, 8, 2741, 1, 4294967295, 4294967295, 1, 80, 8, 2742, 1, 4294967295, 4294967295, 1, 80, 8, 2743, 1, 4294967295, 4294967295, 5, 80, 8, 2744, 1, 2172, 4294967295, 8, 80, 8, 2745, 1, 4294967295, 4294967295, 10, 80, 8, 2746, 2, 4294967295, 4294967295, 12, 80, 8, 2748, 1, 4294967295, 2175, 9, 80, 8, 2749, 1, 4294967295, 4294967295, 1, 81, 8, 2750, 1, 4294967295, 4294967295, 1, 81, 8, 2751, 1, 4294967295, 4294967295, 5, 81, 8, 2752, 1, 2179, 4294967295, 8, 81, 8, 2753, 1, 4294967295, 4294967295, 10, 81, 8, 2754, 2, 4294967295, 4294967295, 12, 81, 8, 2756, 1, 4294967295, 2182, 9, 81, 8, 2757, 1, 4294967295, 4294967295, 1, 82, 8, 2758, 1, 4294967295, 4294967295, 1, 82, 8, 2759, 1, 4294967295, 4294967295, 1, 82, 32, 2760, 1, 4294967295, 4294967295, 5, 82, 8, 2761, 1, 2187, 4294967295, 8, 82, 8, 2762, 1, 4294967295, 4294967295, 10, 82, 8, 2763, 2, 4294967295, 4294967295, 12, 82, 8, 2765, 1, 4294967295, 2190, 9, 82, 8, 2766, 1, 4294967295, 4294967295, 1, 82, 8, 2767, 1, 4294967295, 4294967295, 1, 82, 8, 2768, 1, 4294967295, 4294967295, 1, 82, 8, 2769, 1, 4294967295, 4294967295, 1, 82, 32, 2770, 1, 4294967295, 4294967295, 5, 82, 8, 2771, 1, 2196, 4294967295, 8, 82, 8, 2772, 1, 4294967295, 4294967295, 10, 82, 8, 2773, 2, 4294967295, 4294967295, 12, 82, 8, 2775, 1, 4294967295, 2199, 9, 82, 8, 2776, 1, 4294967295, 4294967295, 1, 82, 8, 2777, 1, 4294967295, 4294967295, 1, 82, 8, 2778, 1, 4294967295, 4294967295, 5, 82, 8, 2779, 2, 2203, 4294967295, 8, 82, 8, 2781, 1, 4294967295, 4294967295, 10, 82, 8, 2782, 2, 4294967295, 4294967295, 12, 82, 8, 2784, 1, 4294967295, 2206, 9, 82, 8, 2785, 1, 4294967295, 4294967295, 1, 83, 8, 2786, 1, 4294967295, 4294967295, 1, 83, 32, 2787, 1, 4294967295, 4294967295, 5, 83, 8, 2788, 1, 2210, 4294967295, 8, 83, 8, 2789, 1, 4294967295, 4294967295, 10, 83, 8, 2790, 2, 4294967295, 4294967295, 12, 83, 8, 2792, 1, 4294967295, 2213, 9, 83, 8, 2793, 1, 4294967295, 4294967295, 1, 83, 8, 2794, 1, 4294967295, 4294967295, 1, 83, 32, 2795, 1, 4294967295, 4294967295, 5, 83, 8, 2796, 1, 2217, 4294967295, 8, 83, 8, 2797, 1, 4294967295, 4294967295, 10, 83, 8, 2798, 2, 4294967295, 4294967295, 12, 83, 8, 2800, 1, 4294967295, 2220, 9, 83, 8, 2801, 1, 4294967295, 4294967295, 1, 83, 8, 2802, 1, 4294967295, 4294967295, 1, 83, 8, 2803, 1, 4294967295, 4294967295, 5, 83, 8, 2804, 1, 2224, 4294967295, 8, 83, 8, 2805, 1, 4294967295, 4294967295, 10, 83, 8, 2806, 2, 4294967295, 4294967295, 12, 83, 8, 2808, 1, 4294967295, 2227, 9, 83, 8, 2809, 1, 4294967295, 4294967295, 1, 84, 32, 2810, 1, 4294967295, 4294967295, 1, 84, 32, 2811, 1, 4294967295, 4294967295, 1, 84, 8, 2812, 1, 4294967295, 4294967295, 1, 85, 8, 2813, 1, 4294967295, 4294967295, 1, 85, 8, 2814, 1, 4294967295, 4294967295, 1, 85, 32, 2815, 1, 4294967295, 4294967295, 5, 85, 8, 2816, 1, 2235, 4294967295, 8, 85, 8, 2817, 1, 4294967295, 4294967295, 10, 85, 8, 2818, 2, 4294967295, 4294967295, 12, 85, 8, 2820, 1, 4294967295, 2238, 9, 85, 8, 2821, 1, 4294967295, 4294967295, 1, 85, 8, 2822, 1, 4294967295, 4294967295, 1, 85, 8, 2823, 1, 4294967295, 4294967295, 5, 85, 8, 2824, 1, 2242, 4294967295, 8, 85, 8, 2825, 1, 4294967295, 4294967295, 10, 85, 8, 2826, 2, 4294967295, 4294967295, 12, 85, 8, 2828, 1, 4294967295, 2245, 9, 85, 8, 2829, 1, 4294967295, 4294967295, 1, 86, 8, 2830, 1, 4294967295, 4294967295, 1, 86, 32, 2831, 1, 4294967295, 4294967295, 1, 86, 32, 2832, 1, 4294967295, 4294967295, 5, 86, 8, 2833, 1, 2250, 4294967295, 8, 86, 8, 2834, 1, 4294967295, 4294967295, 10, 86, 8, 2835, 2, 4294967295, 4294967295, 12, 86, 8, 2837, 1, 4294967295, 2253, 9, 86, 8, 2838, 1, 4294967295, 4294967295, 1, 86, 8, 2839, 1, 4294967295, 4294967295, 5, 86, 8, 2840, 1, 2256, 4294967295, 8, 86, 8, 2841, 1, 4294967295, 4294967295, 10, 86, 8, 2842, 2, 4294967295, 4294967295, 12, 86, 8, 2844, 1, 4294967295, 2259, 9, 86, 8, 2845, 1, 4294967295, 4294967295, 1, 87, 8, 2846, 1, 4294967295, 4294967295, 1, 87, 8, 2847, 1, 4294967295, 4294967295, 1, 87, 32, 2848, 1, 4294967295, 4294967295, 5, 87, 8, 2849, 1, 2264, 4294967295, 8, 87, 8, 2850, 1, 4294967295, 4294967295, 10, 87, 8, 2851, 2, 4294967295, 4294967295, 12, 87, 8, 2853, 1, 4294967295, 2267, 9, 87, 8, 2854, 1, 4294967295, 4294967295, 1, 87, 8, 2855, 1, 4294967295, 4294967295, 1, 87, 8, 2856, 1, 4294967295, 4294967295, 5, 87, 8, 2857, 1, 2271, 4294967295, 8, 87, 8, 2858, 1, 4294967295, 4294967295, 10, 87, 8, 2859, 2, 4294967295, 4294967295, 12, 87, 8, 2861, 1, 4294967295, 2274, 9, 87, 8, 2862, 1, 4294967295, 4294967295, 1, 88, 8, 2863, 1, 4294967295, 4294967295, 1, 88, 8, 2864, 1, 4294967295, 4294967295, 1, 88, 32, 2865, 1, 4294967295, 4294967295, 5, 88, 8, 2866, 1, 2279, 4294967295, 8, 88, 8, 2867, 1, 4294967295, 4294967295, 10, 88, 8, 2868, 2, 4294967295, 4294967295, 12, 88, 8, 2870, 1, 4294967295, 2282, 9, 88, 8, 2871, 1, 4294967295, 4294967295, 1, 88, 8, 2872, 1, 4294967295, 4294967295, 1, 88, 8, 2873, 1, 4294967295, 4294967295, 5, 88, 8, 2874, 1, 2286, 4294967295, 8, 88, 8, 2875, 1, 4294967295, 4294967295, 10, 88, 8, 2876, 2, 4294967295, 4294967295, 12, 88, 8, 2878, 1, 4294967295, 2289, 9, 88, 8, 2879, 1, 4294967295, 4294967295, 1, 89, 8, 2880, 1, 4294967295, 4294967295, 1, 89, 32, 2881, 1, 4294967295, 4294967295, 5, 89, 8, 2882, 1, 2293, 4294967295, 8, 89, 8, 2883, 1, 4294967295, 4294967295, 10, 89, 8, 2884, 2, 4294967295, 4294967295, 12, 89, 8, 2886, 1, 4294967295, 2296, 9, 89, 8, 2887, 1, 4294967295, 4294967295, 1, 89, 8, 2888, 1, 4294967295, 4294967295, 1, 89, 32, 2889, 1, 4294967295, 4294967295, 5, 89, 8, 2890, 1, 2300, 4294967295, 8, 89, 8, 2891, 1, 4294967295, 4294967295, 10, 89, 8, 2892, 2, 4294967295, 4294967295, 12, 89, 8, 2894, 1, 4294967295, 2303, 9, 89, 8, 2895, 1, 4294967295, 4294967295, 1, 89, 8, 2896, 1, 4294967295, 4294967295, 1, 89, 8, 2897, 1, 4294967295, 4294967295, 5, 89, 8, 2898, 1, 2307, 4294967295, 8, 89, 8, 2899, 1, 4294967295, 4294967295, 10, 89, 8, 2900, 2, 4294967295, 4294967295, 12, 89, 8, 2902, 1, 4294967295, 2310, 9, 89, 8, 2903, 1, 4294967295, 4294967295, 1, 90, 8, 2904, 1, 4294967295, 4294967295, 5, 90, 8, 2905, 1, 2313, 4294967295, 8, 90, 8, 2906, 1, 4294967295, 4294967295, 10, 90, 8, 2907, 2, 4294967295, 4294967295, 12, 90, 8, 2909, 1, 4294967295, 2316, 9, 90, 8, 2910, 1, 4294967295, 4294967295, 1, 90, 8, 2911, 1, 4294967295, 4294967295, 1, 90, 8, 2912, 1, 4294967295, 4294967295, 1, 91, 8, 2913, 1, 4294967295, 4294967295, 1, 91, 8, 2914, 1, 4294967295, 4294967295, 1, 91, 8, 2915, 1, 4294967295, 4294967295, 1, 91, 32, 2916, 1, 4294967295, 4294967295, 5, 91, 8, 2917, 1, 2324, 4294967295, 8, 91, 8, 2918, 1, 4294967295, 4294967295, 10, 91, 8, 2919, 2, 4294967295, 4294967295, 12, 91, 8, 2921, 1, 4294967295, 2327, 9, 91, 8, 2922, 1, 4294967295, 4294967295, 3, 91, 8, 2923, 3, 2329, 4294967295, 8, 91, 8, 2926, 1, 4294967295, 4294967295, 1, 92, 8, 2927, 1, 4294967295, 4294967295, 1, 92, 8, 2928, 1, 4294967295, 4294967295, 5, 92, 8, 2929, 1, 2333, 4294967295, 8, 92, 8, 2930, 1, 4294967295, 4294967295, 10, 92, 8, 2931, 2, 4294967295, 4294967295, 12, 92, 8, 2933, 1, 4294967295, 2336, 9, 92, 8, 2934, 1, 4294967295, 4294967295, 1, 93, 8, 2935, 1, 4294967295, 4294967295, 1, 93, 8, 2936, 1, 4294967295, 4294967295, 1, 93, 8, 2937, 1, 4294967295, 4294967295, 1, 93, 8, 2938, 1, 4294967295, 4294967295, 1, 93, 8, 2939, 1, 4294967295, 4294967295, 3, 93, 8, 2940, 5, 2343, 4294967295, 8, 93, 8, 2945, 1, 4294967295, 4294967295, 1, 94, 8, 2946, 1, 4294967295, 4294967295, 1, 94, 8, 2947, 1, 4294967295, 4294967295, 1, 94, 8, 2948, 1, 4294967295, 4294967295, 1, 94, 8, 2949, 1, 4294967295, 4294967295, 1, 94, 8, 2950, 1, 4294967295, 4294967295, 3, 94, 8, 2951, 3, 2350, 4294967295, 8, 94, 8, 2954, 1, 4294967295, 4294967295, 1, 95, 32, 2955, 1, 4294967295, 4294967295, 1, 95, 32, 2956, 1, 4294967295, 4294967295, 5, 95, 8, 2957, 1, 2354, 4294967295, 8, 95, 8, 2958, 1, 4294967295, 4294967295, 10, 95, 8, 2959, 2, 4294967295, 4294967295, 12, 95, 8, 2961, 1, 4294967295, 2357, 9, 95, 8, 2962, 1, 4294967295, 4294967295, 1, 95, 8, 2963, 1, 4294967295, 4294967295, 1, 95, 32, 2964, 1, 4294967295, 4294967295, 5, 95, 8, 2965, 1, 2361, 4294967295, 8, 95, 8, 2966, 1, 4294967295, 4294967295, 10, 95, 8, 2967, 2, 4294967295, 4294967295, 12, 95, 8, 2969, 1, 4294967295, 2364, 9, 95, 8, 2970, 1, 4294967295, 4294967295, 1, 95, 32, 2971, 1, 4294967295, 4294967295, 1, 95, 8, 2972, 1, 4294967295, 4294967295, 1, 96, 8, 2973, 1, 4294967295, 4294967295, 1, 96, 8, 2974, 1, 4294967295, 4294967295, 3, 96, 8, 2975, 2, 2370, 4294967295, 8, 96, 8, 2977, 1, 4294967295, 4294967295, 1, 97, 32, 2978, 1, 4294967295, 4294967295, 1, 97, 32, 2979, 1, 4294967295, 4294967295, 5, 97, 8, 2980, 1, 2374, 4294967295, 8, 97, 8, 2981, 1, 4294967295, 4294967295, 10, 97, 8, 2982, 2, 4294967295, 4294967295, 12, 97, 8, 2984, 1, 4294967295, 2377, 9, 97, 8, 2985, 1, 4294967295, 4294967295, 1, 97, 8, 2986, 1, 4294967295, 4294967295, 1, 97, 32, 2987, 1, 4294967295, 4294967295, 5, 97, 8, 2988, 1, 2381, 4294967295, 8, 97, 8, 2989, 1, 4294967295, 4294967295, 10, 97, 8, 2990, 2, 4294967295, 4294967295, 12, 97, 8, 2992, 1, 4294967295, 2384, 9, 97, 8, 2993, 1, 4294967295, 4294967295, 1, 97, 32, 2994, 1, 4294967295, 4294967295, 1, 97, 8, 2995, 1, 4294967295, 4294967295, 1, 98, 8, 2996, 1, 4294967295, 4294967295, 1, 98, 8, 2997, 1, 4294967295, 4294967295, 1, 98, 8, 2998, 1, 4294967295, 4294967295, 3, 98, 8, 2999, 3, 2391, 4294967295, 8, 98, 8, 3002, 1, 4294967295, 4294967295, 1, 99, 32, 3003, 1, 4294967295, 4294967295, 1, 99, 32, 3004, 1, 4294967295, 4294967295, 5, 99, 8, 3005, 1, 2395, 4294967295, 8, 99, 8, 3006, 1, 4294967295, 4294967295, 10, 99, 8, 3007, 2, 4294967295, 4294967295, 12, 99, 8, 3009, 1, 4294967295, 2398, 9, 99, 8, 3010, 1, 4294967295, 4294967295, 1, 99, 8, 3011, 1, 4294967295, 4294967295, 1, 99, 32, 3012, 1, 4294967295, 4294967295, 5, 99, 8, 3013, 1, 2402, 4294967295, 8, 99, 8, 3014, 1, 4294967295, 4294967295, 10, 99, 8, 3015, 2, 4294967295, 4294967295, 12, 99, 8, 3017, 1, 4294967295, 2405, 9, 99, 8, 3018, 1, 4294967295, 4294967295, 1, 99, 32, 3019, 1, 4294967295, 4294967295, 1, 99, 32, 3020, 1, 4294967295, 4294967295, 5, 99, 8, 3021, 1, 2409, 4294967295, 8, 99, 8, 3022, 1, 4294967295, 4294967295, 10, 99, 8, 3023, 2, 4294967295, 4294967295, 12, 99, 8, 3025, 1, 4294967295, 2412, 9, 99, 8, 3026, 1, 4294967295, 4294967295, 1, 99, 8, 3027, 1, 4294967295, 4294967295, 5, 99, 8, 3028, 1, 2415, 4294967295, 8, 99, 8, 3029, 1, 4294967295, 4294967295, 10, 99, 8, 3030, 2, 4294967295, 4294967295, 12, 99, 8, 3032, 1, 4294967295, 2418, 9, 99, 8, 3033, 1, 4294967295, 4294967295, 1, 99, 32, 3034, 1, 4294967295, 4294967295, 5, 99, 8, 3035, 1, 2421, 4294967295, 8, 99, 8, 3036, 1, 4294967295, 4294967295, 10, 99, 8, 3037, 2, 4294967295, 4294967295, 12, 99, 8, 3039, 1, 4294967295, 2424, 9, 99, 8, 3040, 1, 4294967295, 4294967295, 1, 99, 32, 3041, 1, 4294967295, 4294967295, 3, 99, 8, 3042, 2, 2427, 4294967295, 8, 99, 8, 3044, 1, 4294967295, 4294967295, 1, 99, 32, 3045, 1, 4294967295, 4294967295, 5, 99, 8, 3046, 1, 2430, 4294967295, 8, 99, 8, 3047, 1, 4294967295, 4294967295, 10, 99, 8, 3048, 2, 4294967295, 4294967295, 12, 99, 8, 3050, 1, 4294967295, 2433, 9, 99, 8, 3051, 1, 4294967295, 4294967295, 1, 99, 32, 3052, 1, 4294967295, 4294967295, 1, 99, 8, 3053, 1, 4294967295, 4294967295, 1, 100, 8, 3054, 1, 4294967295, 4294967295, 1, 100, 32, 3055, 1, 4294967295, 4294967295, 5, 100, 8, 3056, 1, 2439, 4294967295, 8, 100, 8, 3057, 1, 4294967295, 4294967295, 10, 100, 8, 3058, 2, 4294967295, 4294967295, 12, 100, 8, 3060, 1, 4294967295, 2442, 9, 100, 8, 3061, 1, 4294967295, 4294967295, 1, 100, 8, 3062, 1, 4294967295, 4294967295, 1, 100, 8, 3063, 1, 4294967295, 4294967295, 1, 100, 32, 3064, 1, 4294967295, 4294967295, 3, 100, 8, 3065, 3, 2447, 4294967295, 8, 100, 8, 3068, 1, 4294967295, 4294967295, 1, 101, 8, 3069, 1, 4294967295, 4294967295, 3, 101, 8, 3070, 2, 2450, 4294967295, 8, 101, 8, 3072, 1, 4294967295, 4294967295, 1, 101, 8, 3073, 1, 4294967295, 4294967295, 3, 101, 8, 3074, 2, 2453, 4294967295, 8, 101, 8, 3076, 1, 4294967295, 4294967295, 1, 101, 8, 3077, 1, 4294967295, 4294967295, 1, 101, 8, 3078, 1, 4294967295, 4294967295, 3, 101, 8, 3079, 2, 2457, 4294967295, 8, 101, 8, 3081, 1, 4294967295, 4294967295, 1, 102, 8, 3082, 1, 4294967295, 4294967295, 5, 102, 8, 3083, 1, 2460, 4294967295, 8, 102, 8, 3084, 1, 4294967295, 4294967295, 10, 102, 8, 3085, 2, 4294967295, 4294967295, 12, 102, 8, 3087, 1, 4294967295, 2463, 9, 102, 8, 3088, 1, 4294967295, 4294967295, 1, 102, 8, 3089, 1, 4294967295, 4294967295, 3, 102, 8, 3090, 2, 2466, 4294967295, 8, 102, 8, 3092, 1, 4294967295, 4294967295, 1, 102, 32, 3093, 1, 4294967295, 4294967295, 5, 102, 8, 3094, 1, 2469, 4294967295, 8, 102, 8, 3095, 1, 4294967295, 4294967295, 10, 102, 8, 3096, 2, 4294967295, 4294967295, 12, 102, 8, 3098, 1, 4294967295, 2472, 9, 102, 8, 3099, 1, 4294967295, 4294967295, 1, 102, 8, 3100, 1, 4294967295, 4294967295, 1, 102, 8, 3101, 1, 4294967295, 4294967295, 1, 103, 32, 3102, 1, 4294967295, 4294967295, 1, 103, 32, 3103, 1, 4294967295, 4294967295, 5, 103, 8, 3104, 1, 2478, 4294967295, 8, 103, 8, 3105, 1, 4294967295, 4294967295, 10, 103, 8, 3106, 2, 4294967295, 4294967295, 12, 103, 8, 3108, 1, 4294967295, 2481, 9, 103, 8, 3109, 1, 4294967295, 4294967295, 1, 103, 8, 3110, 1, 4294967295, 4294967295, 1, 103, 32, 3111, 1, 4294967295, 4294967295, 5, 103, 8, 3112, 1, 2485, 4294967295, 8, 103, 8, 3113, 1, 4294967295, 4294967295, 10, 103, 8, 3114, 2, 4294967295, 4294967295, 12, 103, 8, 3116, 1, 4294967295, 2488, 9, 103, 8, 3117, 1, 4294967295, 4294967295, 1, 103, 32, 3118, 1, 4294967295, 4294967295, 1, 103, 32, 3119, 1, 4294967295, 4294967295, 5, 103, 8, 3120, 1, 2492, 4294967295, 8, 103, 8, 3121, 1, 4294967295, 4294967295, 10, 103, 8, 3122, 2, 4294967295, 4294967295, 12, 103, 8, 3124, 1, 4294967295, 2495, 9, 103, 8, 3125, 1, 4294967295, 4294967295, 1, 103, 8, 3126, 1, 4294967295, 4294967295, 5, 103, 8, 3127, 1, 2498, 4294967295, 8, 103, 8, 3128, 1, 4294967295, 4294967295, 10, 103, 8, 3129, 2, 4294967295, 4294967295, 12, 103, 8, 3131, 1, 4294967295, 2501, 9, 103, 8, 3132, 1, 4294967295, 4294967295, 1, 103, 32, 3133, 1, 4294967295, 4294967295, 5, 103, 8, 3134, 1, 2504, 4294967295, 8, 103, 8, 3135, 1, 4294967295, 4294967295, 10, 103, 8, 3136, 2, 4294967295, 4294967295, 12, 103, 8, 3138, 1, 4294967295, 2507, 9, 103, 8, 3139, 1, 4294967295, 4294967295, 1, 103, 32, 3140, 1, 4294967295, 4294967295, 3, 103, 8, 3141, 2, 2510, 4294967295, 8, 103, 8, 3143, 1, 4294967295, 4294967295, 1, 103, 32, 3144, 1, 4294967295, 4294967295, 5, 103, 8, 3145, 1, 2513, 4294967295, 8, 103, 8, 3146, 1, 4294967295, 4294967295, 10, 103, 8, 3147, 2, 4294967295, 4294967295, 12, 103, 8, 3149, 1, 4294967295, 2516, 9, 103, 8, 3150, 1, 4294967295, 4294967295, 1, 103, 32, 3151, 1, 4294967295, 4294967295, 1, 103, 8, 3152, 1, 4294967295, 4294967295, 1, 104, 32, 3153, 1, 4294967295, 4294967295, 1, 104, 32, 3154, 1, 4294967295, 4294967295, 5, 104, 8, 3155, 1, 2522, 4294967295, 8, 104, 8, 3156, 1, 4294967295, 4294967295, 10, 104, 8, 3157, 2, 4294967295, 4294967295, 12, 104, 8, 3159, 1, 4294967295, 2525, 9, 104, 8, 3160, 1, 4294967295, 4294967295, 1, 104, 8, 3161, 1, 4294967295, 4294967295, 1, 104, 32, 3162, 1, 4294967295, 4294967295, 5, 104, 8, 3163, 1, 2529, 4294967295, 8, 104, 8, 3164, 1, 4294967295, 4294967295, 10, 104, 8, 3165, 2, 4294967295, 4294967295, 12, 104, 8, 3167, 1, 4294967295, 2532, 9, 104, 8, 3168, 1, 4294967295, 4294967295, 1, 104, 32, 3169, 1, 4294967295, 4294967295, 1, 104, 32, 3170, 1, 4294967295, 4294967295, 5, 104, 8, 3171, 1, 2536, 4294967295, 8, 104, 8, 3172, 1, 4294967295, 4294967295, 10, 104, 8, 3173, 2, 4294967295, 4294967295, 12, 104, 8, 3175, 1, 4294967295, 2539, 9, 104, 8, 3176, 1, 4294967295, 4294967295, 1, 104, 8, 3177, 1, 4294967295, 4294967295, 5, 104, 8, 3178, 1, 2542, 4294967295, 8, 104, 8, 3179, 1, 4294967295, 4294967295, 10, 104, 8, 3180, 2, 4294967295, 4294967295, 12, 104, 8, 3182, 1, 4294967295, 2545, 9, 104, 8, 3183, 1, 4294967295, 4294967295, 1, 104, 32, 3184, 1, 4294967295, 4294967295, 5, 104, 8, 3185, 1, 2548, 4294967295, 8, 104, 8, 3186, 1, 4294967295, 4294967295, 10, 104, 8, 3187, 2, 4294967295, 4294967295, 12, 104, 8, 3189, 1, 4294967295, 2551, 9, 104, 8, 3190, 1, 4294967295, 4294967295, 1, 104, 32, 3191, 1, 4294967295, 4294967295, 3, 104, 8, 3192, 2, 2554, 4294967295, 8, 104, 8, 3194, 1, 4294967295, 4294967295, 1, 104, 32, 3195, 1, 4294967295, 4294967295, 5, 104, 8, 3196, 1, 2557, 4294967295, 8, 104, 8, 3197, 1, 4294967295, 4294967295, 10, 104, 8, 3198, 2, 4294967295, 4294967295, 12, 104, 8, 3200, 1, 4294967295, 2560, 9, 104, 8, 3201, 1, 4294967295, 4294967295, 3, 104, 8, 3202, 2, 2562, 4294967295, 8, 104, 8, 3204, 1, 4294967295, 4294967295, 1, 104, 32, 3205, 1, 4294967295, 4294967295, 1, 104, 8, 3206, 1, 4294967295, 4294967295, 1, 105, 8, 3207, 1, 4294967295, 4294967295, 3, 105, 8, 3208, 2, 2567, 4294967295, 8, 105, 8, 3210, 1, 4294967295, 4294967295, 1, 105, 32, 3211, 1, 4294967295, 4294967295, 5, 105, 8, 3212, 1, 2570, 4294967295, 8, 105, 8, 3213, 1, 4294967295, 4294967295, 10, 105, 8, 3214, 2, 4294967295, 4294967295, 12, 105, 8, 3216, 1, 4294967295, 2573, 9, 105, 8, 3217, 1, 4294967295, 4294967295, 1, 105, 8, 3218, 1, 4294967295, 4294967295, 1, 105, 32, 3219, 1, 4294967295, 4294967295, 5, 105, 8, 3220, 1, 2577, 4294967295, 8, 105, 8, 3221, 1, 4294967295, 4294967295, 10, 105, 8, 3222, 2, 4294967295, 4294967295, 12, 105, 8, 3224, 1, 4294967295, 2580, 9, 105, 8, 3225, 1, 4294967295, 4294967295, 1, 105, 32, 3226, 1, 4294967295, 4294967295, 1, 105, 32, 3227, 1, 4294967295, 4294967295, 5, 105, 8, 3228, 1, 2584, 4294967295, 8, 105, 8, 3229, 1, 4294967295, 4294967295, 10, 105, 8, 3230, 2, 4294967295, 4294967295, 12, 105, 8, 3232, 1, 4294967295, 2587, 9, 105, 8, 3233, 1, 4294967295, 4294967295, 3, 105, 8, 3234, 2, 2589, 4294967295, 8, 105, 8, 3236, 1, 4294967295, 4294967295, 1, 105, 32, 3237, 1, 4294967295, 4294967295, 3, 105, 8, 3238, 2, 2592, 4294967295, 8, 105, 8, 3240, 1, 4294967295, 4294967295, 1, 105, 32, 3241, 1, 4294967295, 4294967295, 5, 105, 8, 3242, 1, 2595, 4294967295, 8, 105, 8, 3243, 1, 4294967295, 4294967295, 10, 105, 8, 3244, 2, 4294967295, 4294967295, 12, 105, 8, 3246, 1, 4294967295, 2598, 9, 105, 8, 3247, 1, 4294967295, 4294967295, 1, 105, 8, 3248, 1, 4294967295, 4294967295, 1, 105, 8, 3249, 1, 4294967295, 4294967295, 1, 106, 8, 3250, 1, 4294967295, 4294967295, 1, 106, 8, 3251, 1, 4294967295, 4294967295, 1, 106, 8, 3252, 1, 4294967295, 4294967295, 1, 106, 8, 3253, 1, 4294967295, 4294967295, 1, 106, 8, 3254, 1, 4294967295, 4294967295, 1, 106, 8, 3255, 1, 4294967295, 4294967295, 1, 106, 8, 3256, 1, 4294967295, 4294967295, 1, 106, 8, 3257, 1, 4294967295, 4294967295, 1, 106, 8, 3258, 1, 4294967295, 4294967295, 1, 106, 8, 3259, 1, 4294967295, 4294967295, 1, 106, 8, 3260, 1, 4294967295, 4294967295, 1, 106, 8, 3261, 1, 4294967295, 4294967295, 1, 106, 8, 3262, 1, 4294967295, 4294967295, 1, 106, 8, 3263, 1, 4294967295, 4294967295, 3, 106, 8, 3264, 14, 2616, 4294967295, 8, 106, 8, 3278, 1, 4294967295, 4294967295, 1, 107, 32, 3279, 1, 4294967295, 4294967295, 1, 107, 32, 3280, 1, 4294967295, 4294967295, 5, 107, 8, 3281, 1, 2620, 4294967295, 8, 107, 8, 3282, 1, 4294967295, 4294967295, 10, 107, 8, 3283, 2, 4294967295, 4294967295, 12, 107, 8, 3285, 1, 4294967295, 2623, 9, 107, 8, 3286, 1, 4294967295, 4294967295, 1, 107, 8, 3287, 1, 4294967295, 4294967295, 1, 107, 32, 3288, 1, 4294967295, 4294967295, 5, 107, 8, 3289, 1, 2627, 4294967295, 8, 107, 8, 3290, 1, 4294967295, 4294967295, 10, 107, 8, 3291, 2, 4294967295, 4294967295, 12, 107, 8, 3293, 1, 4294967295, 2630, 9, 107, 8, 3294, 1, 4294967295, 4294967295, 1, 107, 32, 3295, 1, 4294967295, 4294967295, 1, 107, 8, 3296, 1, 4294967295, 4294967295, 1, 108, 32, 3297, 1, 4294967295, 4294967295, 1, 108, 32, 3298, 1, 4294967295, 4294967295, 5, 108, 8, 3299, 1, 2636, 4294967295, 8, 108, 8, 3300, 1, 4294967295, 4294967295, 10, 108, 8, 3301, 2, 4294967295, 4294967295, 12, 108, 8, 3303, 1, 4294967295, 2639, 9, 108, 8, 3304, 1, 4294967295, 4294967295, 1, 108, 8, 3305, 1, 4294967295, 4294967295, 1, 108, 32, 3306, 1, 4294967295, 4294967295, 5, 108, 8, 3307, 1, 2643, 4294967295, 8, 108, 8, 3308, 1, 4294967295, 4294967295, 10, 108, 8, 3309, 2, 4294967295, 4294967295, 12, 108, 8, 3311, 1, 4294967295, 2646, 9, 108, 8, 3312, 1, 4294967295, 4294967295, 1, 108, 32, 3313, 1, 4294967295, 4294967295, 1, 108, 32, 3314, 1, 4294967295, 4294967295, 5, 108, 8, 3315, 1, 2650, 4294967295, 8, 108, 8, 3316, 1, 4294967295, 4294967295, 10, 108, 8, 3317, 2, 4294967295, 4294967295, 12, 108, 8, 3319, 1, 4294967295, 2653, 9, 108, 8, 3320, 1, 4294967295, 4294967295, 1, 108, 8, 3321, 1, 4294967295, 4294967295, 5, 108, 8, 3322, 1, 2656, 4294967295, 8, 108, 8, 3323, 1, 4294967295, 4294967295, 10, 108, 8, 3324, 2, 4294967295, 4294967295, 12, 108, 8, 3326, 1, 4294967295, 2659, 9, 108, 8, 3327, 1, 4294967295, 4294967295, 1, 108, 32, 3328, 1, 4294967295, 4294967295, 5, 108, 8, 3329, 1, 2662, 4294967295, 8, 108, 8, 3330, 1, 4294967295, 4294967295, 10, 108, 8, 3331, 2, 4294967295, 4294967295, 12, 108, 8, 3333, 1, 4294967295, 2665, 9, 108, 8, 3334, 1, 4294967295, 4294967295, 1, 108, 32, 3335, 1, 4294967295, 4294967295, 3, 108, 8, 3336, 2, 2668, 4294967295, 8, 108, 8, 3338, 1, 4294967295, 4294967295, 1, 108, 32, 3339, 1, 4294967295, 4294967295, 5, 108, 8, 3340, 1, 2671, 4294967295, 8, 108, 8, 3341, 1, 4294967295, 4294967295, 10, 108, 8, 3342, 2, 4294967295, 4294967295, 12, 108, 8, 3344, 1, 4294967295, 2674, 9, 108, 8, 3345, 1, 4294967295, 4294967295, 3, 108, 8, 3346, 2, 2676, 4294967295, 8, 108, 8, 3348, 1, 4294967295, 4294967295, 1, 108, 32, 3349, 1, 4294967295, 4294967295, 1, 108, 8, 3350, 1, 4294967295, 4294967295, 1, 109, 32, 3351, 1, 4294967295, 4294967295, 1, 109, 8, 3352, 1, 4294967295, 4294967295, 1, 110, 8, 3353, 1, 4294967295, 4294967295, 1, 110, 8, 3354, 1, 4294967295, 4294967295, 3, 110, 8, 3355, 2, 2684, 4294967295, 8, 110, 8, 3357, 1, 4294967295, 4294967295, 1, 111, 32, 3358, 1, 4294967295, 4294967295, 1, 111, 8, 3359, 1, 4294967295, 4294967295, 1, 111, 8, 3360, 1, 4294967295, 4294967295, 5, 111, 8, 3361, 2, 2689, 4294967295, 8, 111, 8, 3363, 1, 4294967295, 4294967295, 10, 111, 8, 3364, 2, 4294967295, 4294967295, 12, 111, 8, 3366, 1, 4294967295, 2692, 9, 111, 8, 3367, 1, 4294967295, 4294967295, 1, 111, 32, 3368, 1, 4294967295, 4294967295, 1, 111, 8, 3369, 1, 4294967295, 4294967295, 1, 112, 32, 3370, 1, 4294967295, 4294967295, 1, 112, 8, 3371, 1, 4294967295, 4294967295, 1, 112, 8, 3372, 1, 4294967295, 4294967295, 1, 112, 32, 3373, 1, 4294967295, 4294967295, 5, 112, 8, 3374, 3, 2700, 4294967295, 8, 112, 8, 3377, 1, 4294967295, 4294967295, 10, 112, 8, 3378, 2, 4294967295, 4294967295, 12, 112, 8, 3380, 1, 4294967295, 2703, 9, 112, 8, 3381, 1, 4294967295, 4294967295, 1, 112, 32, 3382, 1, 4294967295, 4294967295, 1, 112, 8, 3383, 1, 4294967295, 4294967295, 1, 113, 32, 3384, 1, 4294967295, 4294967295, 1, 113, 8, 3385, 1, 4294967295, 4294967295, 1, 114, 32, 3386, 1, 4294967295, 4294967295, 1, 114, 32, 3387, 1, 4294967295, 4294967295, 5, 114, 8, 3388, 1, 2711, 4294967295, 8, 114, 8, 3389, 1, 4294967295, 4294967295, 10, 114, 8, 3390, 2, 4294967295, 4294967295, 12, 114, 8, 3392, 1, 4294967295, 2714, 9, 114, 8, 3393, 1, 4294967295, 4294967295, 1, 114, 8, 3394, 1, 4294967295, 4294967295, 1, 114, 32, 3395, 1, 4294967295, 4294967295, 5, 114, 8, 3396, 1, 2718, 4294967295, 8, 114, 8, 3397, 1, 4294967295, 4294967295, 10, 114, 8, 3398, 2, 4294967295, 4294967295, 12, 114, 8, 3400, 1, 4294967295, 2721, 9, 114, 8, 3401, 1, 4294967295, 4294967295, 1, 114, 32, 3402, 1, 4294967295, 4294967295, 1, 114, 8, 3403, 1, 4294967295, 4294967295, 1, 115, 32, 3404, 1, 4294967295, 4294967295, 1, 115, 8, 3405, 1, 4294967295, 4294967295, 1, 116, 32, 3406, 1, 4294967295, 4294967295, 1, 116, 32, 3407, 1, 4294967295, 4294967295, 5, 116, 8, 3408, 1, 2729, 4294967295, 8, 116, 8, 3409, 1, 4294967295, 4294967295, 10, 116, 8, 3410, 2, 4294967295, 4294967295, 12, 116, 8, 3412, 1, 4294967295, 2732, 9, 116, 8, 3413, 1, 4294967295, 4294967295, 1, 116, 8, 3414, 1, 4294967295, 4294967295, 1, 116, 32, 3415, 1, 4294967295, 4294967295, 5, 116, 8, 3416, 1, 2736, 4294967295, 8, 116, 8, 3417, 1, 4294967295, 4294967295, 10, 116, 8, 3418, 2, 4294967295, 4294967295, 12, 116, 8, 3420, 1, 4294967295, 2739, 9, 116, 8, 3421, 1, 4294967295, 4294967295, 1, 116, 32, 3422, 1, 4294967295, 4294967295, 1, 116, 8, 3423, 1, 4294967295, 4294967295, 1, 117, 32, 3424, 1, 4294967295, 4294967295, 1, 117, 32, 3425, 1, 4294967295, 4294967295, 5, 117, 8, 3426, 1, 2745, 4294967295, 8, 117, 8, 3427, 1, 4294967295, 4294967295, 10, 117, 8, 3428, 2, 4294967295, 4294967295, 12, 117, 8, 3430, 1, 4294967295, 2748, 9, 117, 8, 3431, 1, 4294967295, 4294967295, 1, 117, 8, 3432, 1, 4294967295, 4294967295, 3, 117, 8, 3433, 2, 2751, 4294967295, 8, 117, 8, 3435, 1, 4294967295, 4294967295, 1, 117, 32, 3436, 1, 4294967295, 4294967295, 5, 117, 8, 3437, 1, 2754, 4294967295, 8, 117, 8, 3438, 1, 4294967295, 4294967295, 10, 117, 8, 3439, 2, 4294967295, 4294967295, 12, 117, 8, 3441, 1, 4294967295, 2757, 9, 117, 8, 3442, 1, 4294967295, 4294967295, 1, 117, 32, 3443, 1, 4294967295, 4294967295, 1, 117, 32, 3444, 1, 4294967295, 4294967295, 5, 117, 8, 3445, 1, 2761, 4294967295, 8, 117, 8, 3446, 1, 4294967295, 4294967295, 10, 117, 8, 3447, 2, 4294967295, 4294967295, 12, 117, 8, 3449, 1, 4294967295, 2764, 9, 117, 8, 3450, 1, 4294967295, 4294967295, 3, 117, 8, 3451, 2, 2766, 4294967295, 8, 117, 8, 3453, 1, 4294967295, 4294967295, 1, 117, 8, 3454, 1, 4294967295, 4294967295, 1, 117, 32, 3455, 1, 4294967295, 4294967295, 5, 117, 8, 3456, 1, 2770, 4294967295, 8, 117, 8, 3457, 1, 4294967295, 4294967295, 10, 117, 8, 3458, 2, 4294967295, 4294967295, 12, 117, 8, 3460, 1, 4294967295, 2773, 9, 117, 8, 3461, 1, 4294967295, 4294967295, 1, 117, 32, 3462, 1, 4294967295, 4294967295, 1, 117, 8, 3463, 1, 4294967295, 4294967295, 1, 118, 8, 3464, 1, 4294967295, 4294967295, 1, 118, 32, 3465, 1, 4294967295, 4294967295, 5, 118, 8, 3466, 1, 2779, 4294967295, 8, 118, 8, 3467, 1, 4294967295, 4294967295, 10, 118, 8, 3468, 2, 4294967295, 4294967295, 12, 118, 8, 3470, 1, 4294967295, 2782, 9, 118, 8, 3471, 1, 4294967295, 4294967295, 1, 118, 32, 3472, 1, 4294967295, 4294967295, 1, 118, 32, 3473, 1, 4294967295, 4294967295, 5, 118, 8, 3474, 1, 2786, 4294967295, 8, 118, 8, 3475, 1, 4294967295, 4294967295, 10, 118, 8, 3476, 2, 4294967295, 4294967295, 12, 118, 8, 3478, 1, 4294967295, 2789, 9, 118, 8, 3479, 1, 4294967295, 4294967295, 1, 118, 8, 3480, 1, 4294967295, 4294967295, 5, 118, 8, 3481, 1, 2792, 4294967295, 8, 118, 8, 3482, 1, 4294967295, 4294967295, 10, 118, 8, 3483, 2, 4294967295, 4294967295, 12, 118, 8, 3485, 1, 4294967295, 2795, 9, 118, 8, 3486, 1, 4294967295, 4294967295, 1, 118, 32, 3487, 1, 4294967295, 4294967295, 5, 118, 8, 3488, 1, 2798, 4294967295, 8, 118, 8, 3489, 1, 4294967295, 4294967295, 10, 118, 8, 3490, 2, 4294967295, 4294967295, 12, 118, 8, 3492, 1, 4294967295, 2801, 9, 118, 8, 3493, 1, 4294967295, 4294967295, 1, 118, 32, 3494, 1, 4294967295, 4294967295, 3, 118, 8, 3495, 2, 2804, 4294967295, 8, 118, 8, 3497, 1, 4294967295, 4294967295, 1, 119, 8, 3498, 1, 4294967295, 4294967295, 1, 119, 8, 3499, 1, 4294967295, 4294967295, 1, 119, 32, 3500, 1, 4294967295, 4294967295, 5, 119, 8, 3501, 1, 2809, 4294967295, 8, 119, 8, 3502, 1, 4294967295, 4294967295, 10, 119, 8, 3503, 2, 4294967295, 4294967295, 12, 119, 8, 3505, 1, 4294967295, 2812, 9, 119, 8, 3506, 1, 4294967295, 4294967295, 1, 119, 32, 3507, 1, 4294967295, 4294967295, 1, 119, 32, 3508, 1, 4294967295, 4294967295, 5, 119, 8, 3509, 1, 2816, 4294967295, 8, 119, 8, 3510, 1, 4294967295, 4294967295, 10, 119, 8, 3511, 2, 4294967295, 4294967295, 12, 119, 8, 3513, 1, 4294967295, 2819, 9, 119, 8, 3514, 1, 4294967295, 4294967295, 1, 119, 8, 3515, 1, 4294967295, 4294967295, 3, 119, 8, 3516, 2, 2822, 4294967295, 8, 119, 8, 3518, 1, 4294967295, 4294967295, 3, 119, 8, 3519, 2, 2824, 4294967295, 8, 119, 8, 3521, 1, 4294967295, 4294967295, 1, 120, 32, 3522, 1, 4294967295, 4294967295, 3, 120, 8, 3523, 2, 2827, 4294967295, 8, 120, 8, 3525, 1, 4294967295, 4294967295, 1, 120, 32, 3526, 1, 4294967295, 4294967295, 5, 120, 8, 3527, 1, 2830, 4294967295, 8, 120, 8, 3528, 1, 4294967295, 4294967295, 10, 120, 8, 3529, 2, 4294967295, 4294967295, 12, 120, 8, 3531, 1, 4294967295, 2833, 9, 120, 8, 3532, 1, 4294967295, 4294967295, 1, 120, 32, 3533, 1, 4294967295, 4294967295, 1, 120, 32, 3534, 1, 4294967295, 4294967295, 5, 120, 8, 3535, 1, 2837, 4294967295, 8, 120, 8, 3536, 1, 4294967295, 4294967295, 10, 120, 8, 3537, 2, 4294967295, 4294967295, 12, 120, 8, 3539, 1, 4294967295, 2840, 9, 120, 8, 3540, 1, 4294967295, 4294967295, 1, 120, 8, 3541, 1, 4294967295, 4294967295, 1, 120, 32, 3542, 1, 4294967295, 4294967295, 5, 120, 8, 3543, 1, 2844, 4294967295, 8, 120, 8, 3544, 1, 4294967295, 4294967295, 10, 120, 8, 3545, 2, 4294967295, 4294967295, 12, 120, 8, 3547, 1, 4294967295, 2847, 9, 120, 8, 3548, 1, 4294967295, 4294967295, 1, 120, 32, 3549, 1, 4294967295, 4294967295, 1, 120, 8, 3550, 1, 4294967295, 4294967295, 3, 120, 8, 3551, 2, 2851, 4294967295, 8, 120, 8, 3553, 1, 4294967295, 4294967295, 1, 120, 32, 3554, 1, 4294967295, 4294967295, 5, 120, 8, 3555, 1, 2854, 4294967295, 8, 120, 8, 3556, 1, 4294967295, 4294967295, 10, 120, 8, 3557, 2, 4294967295, 4294967295, 12, 120, 8, 3559, 1, 4294967295, 2857, 9, 120, 8, 3560, 1, 4294967295, 4294967295, 1, 120, 8, 3561, 1, 4294967295, 4294967295, 1, 120, 32, 3562, 1, 4294967295, 4294967295, 5, 120, 8, 3563, 1, 2861, 4294967295, 8, 120, 8, 3564, 1, 4294967295, 4294967295, 10, 120, 8, 3565, 2, 4294967295, 4294967295, 12, 120, 8, 3567, 1, 4294967295, 2864, 9, 120, 8, 3568, 1, 4294967295, 4294967295, 1, 120, 32, 3569, 1, 4294967295, 4294967295, 1, 120, 32, 3570, 1, 4294967295, 4294967295, 5, 120, 8, 3571, 1, 2868, 4294967295, 8, 120, 8, 3572, 1, 4294967295, 4294967295, 10, 120, 8, 3573, 2, 4294967295, 4294967295, 12, 120, 8, 3575, 1, 4294967295, 2871, 9, 120, 8, 3576, 1, 4294967295, 4294967295, 1, 120, 8, 3577, 1, 4294967295, 4294967295, 3, 120, 8, 3578, 2, 2874, 4294967295, 8, 120, 8, 3580, 1, 4294967295, 4294967295, 1, 120, 32, 3581, 1, 4294967295, 4294967295, 5, 120, 8, 3582, 1, 2877, 4294967295, 8, 120, 8, 3583, 1, 4294967295, 4294967295, 10, 120, 8, 3584, 2, 4294967295, 4294967295, 12, 120, 8, 3586, 1, 4294967295, 2880, 9, 120, 8, 3587, 1, 4294967295, 4294967295, 1, 120, 8, 3588, 1, 4294967295, 4294967295, 3, 120, 8, 3589, 2, 2883, 4294967295, 8, 120, 8, 3591, 1, 4294967295, 4294967295, 1, 120, 32, 3592, 1, 4294967295, 4294967295, 5, 120, 8, 3593, 1, 2886, 4294967295, 8, 120, 8, 3594, 1, 4294967295, 4294967295, 10, 120, 8, 3595, 2, 4294967295, 4294967295, 12, 120, 8, 3597, 1, 4294967295, 2889, 9, 120, 8, 3598, 1, 4294967295, 4294967295, 1, 120, 8, 3599, 1, 4294967295, 4294967295, 3, 120, 8, 3600, 2, 2892, 4294967295, 8, 120, 8, 3602, 1, 4294967295, 4294967295, 1, 121, 8, 3603, 1, 4294967295, 4294967295, 1, 121, 8, 3604, 1, 4294967295, 4294967295, 3, 121, 8, 3605, 2, 2896, 4294967295, 8, 121, 8, 3607, 1, 4294967295, 4294967295, 1, 122, 32, 3608, 1, 4294967295, 4294967295, 3, 122, 8, 3609, 2, 2899, 4294967295, 8, 122, 8, 3611, 1, 4294967295, 4294967295, 1, 122, 32, 3612, 1, 4294967295, 4294967295, 5, 122, 8, 3613, 1, 2902, 4294967295, 8, 122, 8, 3614, 1, 4294967295, 4294967295, 10, 122, 8, 3615, 2, 4294967295, 4294967295, 12, 122, 8, 3617, 1, 4294967295, 2905, 9, 122, 8, 3618, 1, 4294967295, 4294967295, 1, 122, 32, 3619, 1, 4294967295, 4294967295, 1, 122, 32, 3620, 1, 4294967295, 4294967295, 5, 122, 8, 3621, 1, 2909, 4294967295, 8, 122, 8, 3622, 1, 4294967295, 4294967295, 10, 122, 8, 3623, 2, 4294967295, 4294967295, 12, 122, 8, 3625, 1, 4294967295, 2912, 9, 122, 8, 3626, 1, 4294967295, 4294967295, 1, 122, 32, 3627, 1, 4294967295, 4294967295, 1, 122, 32, 3628, 1, 4294967295, 4294967295, 5, 122, 8, 3629, 1, 2916, 4294967295, 8, 122, 8, 3630, 1, 4294967295, 4294967295, 10, 122, 8, 3631, 2, 4294967295, 4294967295, 12, 122, 8, 3633, 1, 4294967295, 2919, 9, 122, 8, 3634, 1, 4294967295, 4294967295, 1, 122, 8, 3635, 1, 4294967295, 4294967295, 1, 122, 32, 3636, 1, 4294967295, 4294967295, 5, 122, 8, 3637, 1, 2923, 4294967295, 8, 122, 8, 3638, 1, 4294967295, 4294967295, 10, 122, 8, 3639, 2, 4294967295, 4294967295, 12, 122, 8, 3641, 1, 4294967295, 2926, 9, 122, 8, 3642, 1, 4294967295, 4294967295, 3, 122, 8, 3643, 2, 2928, 4294967295, 8, 122, 8, 3645, 1, 4294967295, 4294967295, 1, 122, 32, 3646, 1, 4294967295, 4294967295, 5, 122, 8, 3647, 1, 2931, 4294967295, 8, 122, 8, 3648, 1, 4294967295, 4294967295, 10, 122, 8, 3649, 2, 4294967295, 4294967295, 12, 122, 8, 3651, 1, 4294967295, 2934, 9, 122, 8, 3652, 1, 4294967295, 4294967295, 1, 122, 8, 3653, 1, 4294967295, 4294967295, 3, 122, 8, 3654, 2, 2937, 4294967295, 8, 122, 8, 3656, 1, 4294967295, 4294967295, 1, 123, 32, 3657, 1, 4294967295, 4294967295, 1, 123, 8, 3658, 1, 4294967295, 4294967295, 1, 124, 32, 3659, 1, 4294967295, 4294967295, 1, 124, 32, 3660, 1, 4294967295, 4294967295, 1, 124, 32, 3661, 1, 4294967295, 4294967295, 5, 124, 8, 3662, 1, 2944, 4294967295, 8, 124, 8, 3663, 1, 4294967295, 4294967295, 10, 124, 8, 3664, 2, 4294967295, 4294967295, 12, 124, 8, 3666, 1, 4294967295, 2947, 9, 124, 8, 3667, 1, 4294967295, 4294967295, 1, 124, 8, 3668, 1, 4294967295, 4294967295, 1, 124, 32, 3669, 1, 4294967295, 4294967295, 5, 124, 8, 3670, 1, 2951, 4294967295, 8, 124, 8, 3671, 1, 4294967295, 4294967295, 10, 124, 8, 3672, 2, 4294967295, 4294967295, 12, 124, 8, 3674, 1, 4294967295, 2954, 9, 124, 8, 3675, 1, 4294967295, 4294967295, 1, 124, 32, 3676, 1, 4294967295, 4294967295, 1, 124, 8, 3677, 1, 4294967295, 4294967295, 3, 124, 8, 3678, 2, 2958, 4294967295, 8, 124, 8, 3680, 1, 4294967295, 4294967295, 1, 124, 32, 3681, 1, 4294967295, 4294967295, 1, 124, 8, 3682, 1, 4294967295, 4294967295, 3, 124, 8, 3683, 2, 2962, 4294967295, 8, 124, 8, 3685, 1, 4294967295, 4294967295, 1, 124, 32, 3686, 1, 4294967295, 4294967295, 3, 124, 8, 3687, 2, 2965, 4294967295, 8, 124, 8, 3689, 1, 4294967295, 4294967295, 1, 125, 32, 3690, 1, 4294967295, 4294967295, 1, 125, 32, 3691, 1, 4294967295, 4294967295, 5, 125, 8, 3692, 1, 2969, 4294967295, 8, 125, 8, 3693, 1, 4294967295, 4294967295, 10, 125, 8, 3694, 2, 4294967295, 4294967295, 12, 125, 8, 3696, 1, 4294967295, 2972, 9, 125, 8, 3697, 1, 4294967295, 4294967295, 1, 125, 32, 3698, 1, 4294967295, 4294967295, 1, 125, 32, 3699, 1, 4294967295, 4294967295, 5, 125, 8, 3700, 1, 2976, 4294967295, 8, 125, 8, 3701, 1, 4294967295, 4294967295, 10, 125, 8, 3702, 2, 4294967295, 4294967295, 12, 125, 8, 3704, 1, 4294967295, 2979, 9, 125, 8, 3705, 1, 4294967295, 4294967295, 1, 125, 8, 3706, 1, 4294967295, 4294967295, 1, 125, 32, 3707, 1, 4294967295, 4294967295, 5, 125, 8, 3708, 1, 2983, 4294967295, 8, 125, 8, 3709, 1, 4294967295, 4294967295, 10, 125, 8, 3710, 2, 4294967295, 4294967295, 12, 125, 8, 3712, 1, 4294967295, 2986, 9, 125, 8, 3713, 1, 4294967295, 4294967295, 1, 125, 32, 3714, 1, 4294967295, 4294967295, 1, 125, 32, 3715, 1, 4294967295, 4294967295, 5, 125, 8, 3716, 1, 2990, 4294967295, 8, 125, 8, 3717, 1, 4294967295, 4294967295, 10, 125, 8, 3718, 2, 4294967295, 4294967295, 12, 125, 8, 3720, 1, 4294967295, 2993, 9, 125, 8, 3721, 1, 4294967295, 4294967295, 1, 125, 8, 3722, 1, 4294967295, 4294967295, 1, 125, 8, 3723, 1, 4294967295, 4294967295, 3, 125, 8, 3724, 2, 2997, 4294967295, 8, 125, 8, 3726, 1, 4294967295, 4294967295, 1, 125, 32, 3727, 1, 4294967295, 4294967295, 5, 125, 8, 3728, 1, 3000, 4294967295, 8, 125, 8, 3729, 1, 4294967295, 4294967295, 10, 125, 8, 3730, 2, 4294967295, 4294967295, 12, 125, 8, 3732, 1, 4294967295, 3003, 9, 125, 8, 3733, 1, 4294967295, 4294967295, 1, 125, 32, 3734, 1, 4294967295, 4294967295, 3, 125, 8, 3735, 2, 3006, 4294967295, 8, 125, 8, 3737, 1, 4294967295, 4294967295, 1, 125, 32, 3738, 1, 4294967295, 4294967295, 5, 125, 8, 3739, 1, 3009, 4294967295, 8, 125, 8, 3740, 1, 4294967295, 4294967295, 10, 125, 8, 3741, 2, 4294967295, 4294967295, 12, 125, 8, 3743, 1, 4294967295, 3012, 9, 125, 8, 3744, 1, 4294967295, 4294967295, 1, 125, 32, 3745, 1, 4294967295, 4294967295, 1, 125, 32, 3746, 1, 4294967295, 4294967295, 5, 125, 8, 3747, 1, 3016, 4294967295, 8, 125, 8, 3748, 1, 4294967295, 4294967295, 10, 125, 8, 3749, 2, 4294967295, 4294967295, 12, 125, 8, 3751, 1, 4294967295, 3019, 9, 125, 8, 3752, 1, 4294967295, 4294967295, 1, 125, 8, 3753, 1, 4294967295, 4294967295, 1, 125, 32, 3754, 1, 4294967295, 4294967295, 3, 125, 8, 3755, 2, 3023, 4294967295, 8, 125, 8, 3757, 1, 4294967295, 4294967295, 1, 125, 32, 3758, 1, 4294967295, 4294967295, 3, 125, 8, 3759, 3, 3026, 4294967295, 8, 125, 8, 3762, 1, 4294967295, 4294967295, 1, 126, 32, 3763, 1, 4294967295, 4294967295, 1, 126, 8, 3764, 1, 4294967295, 4294967295, 5, 126, 8, 3765, 1, 3030, 4294967295, 8, 126, 8, 3766, 1, 4294967295, 4294967295, 10, 126, 8, 3767, 2, 4294967295, 4294967295, 12, 126, 8, 3769, 1, 4294967295, 3033, 9, 126, 8, 3770, 1, 4294967295, 4294967295, 1, 126, 32, 3771, 1, 4294967295, 4294967295, 5, 126, 8, 3772, 1, 3036, 4294967295, 8, 126, 8, 3773, 1, 4294967295, 4294967295, 10, 126, 8, 3774, 2, 4294967295, 4294967295, 12, 126, 8, 3776, 1, 4294967295, 3039, 9, 126, 8, 3777, 1, 4294967295, 4294967295, 1, 126, 32, 3778, 1, 4294967295, 4294967295, 1, 126, 32, 3779, 1, 4294967295, 4294967295, 5, 126, 8, 3780, 1, 3043, 4294967295, 8, 126, 8, 3781, 1, 4294967295, 4294967295, 10, 126, 8, 3782, 2, 4294967295, 4294967295, 12, 126, 8, 3784, 1, 4294967295, 3046, 9, 126, 8, 3785, 1, 4294967295, 4294967295, 1, 126, 8, 3786, 1, 4294967295, 4294967295, 1, 126, 32, 3787, 1, 4294967295, 4294967295, 5, 126, 8, 3788, 1, 3050, 4294967295, 8, 126, 8, 3789, 1, 4294967295, 4294967295, 10, 126, 8, 3790, 2, 4294967295, 4294967295, 12, 126, 8, 3792, 1, 4294967295, 3053, 9, 126, 8, 3793, 1, 4294967295, 4294967295, 1, 126, 32, 3794, 1, 4294967295, 4294967295, 1, 126, 32, 3795, 1, 4294967295, 4294967295, 5, 126, 8, 3796, 1, 3057, 4294967295, 8, 126, 8, 3797, 1, 4294967295, 4294967295, 10, 126, 8, 3798, 2, 4294967295, 4294967295, 12, 126, 8, 3800, 1, 4294967295, 3060, 9, 126, 8, 3801, 1, 4294967295, 4294967295, 3, 126, 8, 3802, 2, 3062, 4294967295, 8, 126, 8, 3804, 1, 4294967295, 4294967295, 1, 126, 8, 3805, 1, 4294967295, 4294967295, 1, 126, 32, 3806, 1, 4294967295, 4294967295, 1, 126, 8, 3807, 1, 4294967295, 4294967295, 1, 127, 32, 3808, 1, 4294967295, 4294967295, 1, 127, 32, 3809, 1, 4294967295, 4294967295, 5, 127, 8, 3810, 1, 3069, 4294967295, 8, 127, 8, 3811, 1, 4294967295, 4294967295, 10, 127, 8, 3812, 2, 4294967295, 4294967295, 12, 127, 8, 3814, 1, 4294967295, 3072, 9, 127, 8, 3815, 1, 4294967295, 4294967295, 1, 127, 8, 3816, 1, 4294967295, 4294967295, 3, 127, 8, 3817, 2, 3075, 4294967295, 8, 127, 8, 3819, 1, 4294967295, 4294967295, 1, 127, 32, 3820, 1, 4294967295, 4294967295, 5, 127, 8, 3821, 1, 3078, 4294967295, 8, 127, 8, 3822, 1, 4294967295, 4294967295, 10, 127, 8, 3823, 2, 4294967295, 4294967295, 12, 127, 8, 3825, 1, 4294967295, 3081, 9, 127, 8, 3826, 1, 4294967295, 4294967295, 1, 127, 32, 3827, 1, 4294967295, 4294967295, 1, 127, 32, 3828, 1, 4294967295, 4294967295, 5, 127, 8, 3829, 1, 3085, 4294967295, 8, 127, 8, 3830, 1, 4294967295, 4294967295, 10, 127, 8, 3831, 2, 4294967295, 4294967295, 12, 127, 8, 3833, 1, 4294967295, 3088, 9, 127, 8, 3834, 1, 4294967295, 4294967295, 1, 127, 8, 3835, 1, 4294967295, 4294967295, 1, 127, 32, 3836, 1, 4294967295, 4294967295, 5, 127, 8, 3837, 1, 3092, 4294967295, 8, 127, 8, 3838, 1, 4294967295, 4294967295, 10, 127, 8, 3839, 2, 4294967295, 4294967295, 12, 127, 8, 3841, 1, 4294967295, 3095, 9, 127, 8, 3842, 1, 4294967295, 4294967295, 5, 127, 8, 3843, 1, 3097, 4294967295, 8, 127, 8, 3844, 1, 4294967295, 4294967295, 10, 127, 8, 3845, 2, 4294967295, 4294967295, 12, 127, 8, 3847, 1, 4294967295, 3100, 9, 127, 8, 3848, 1, 4294967295, 4294967295, 1, 127, 32, 3849, 1, 4294967295, 4294967295, 5, 127, 8, 3850, 1, 3103, 4294967295, 8, 127, 8, 3851, 1, 4294967295, 4294967295, 10, 127, 8, 3852, 2, 4294967295, 4294967295, 12, 127, 8, 3854, 1, 4294967295, 3106, 9, 127, 8, 3855, 1, 4294967295, 4294967295, 1, 127, 32, 3856, 1, 4294967295, 4294967295, 1, 127, 8, 3857, 1, 4294967295, 4294967295, 1, 128, 8, 3858, 1, 4294967295, 4294967295, 1, 128, 32, 3859, 1, 4294967295, 4294967295, 5, 128, 8, 3860, 1, 3112, 4294967295, 8, 128, 8, 3861, 1, 4294967295, 4294967295, 10, 128, 8, 3862, 2, 4294967295, 4294967295, 12, 128, 8, 3864, 1, 4294967295, 3115, 9, 128, 8, 3865, 1, 4294967295, 4294967295, 1, 128, 32, 3866, 1, 4294967295, 4294967295, 1, 128, 32, 3867, 1, 4294967295, 4294967295, 5, 128, 8, 3868, 1, 3119, 4294967295, 8, 128, 8, 3869, 1, 4294967295, 4294967295, 10, 128, 8, 3870, 2, 4294967295, 4294967295, 12, 128, 8, 3872, 1, 4294967295, 3122, 9, 128, 8, 3873, 1, 4294967295, 4294967295, 1, 128, 8, 3874, 1, 4294967295, 4294967295, 5, 128, 8, 3875, 1, 3125, 4294967295, 8, 128, 8, 3876, 1, 4294967295, 4294967295, 10, 128, 8, 3877, 2, 4294967295, 4294967295, 12, 128, 8, 3879, 1, 4294967295, 3128, 9, 128, 8, 3880, 1, 4294967295, 4294967295, 1, 128, 32, 3881, 1, 4294967295, 4294967295, 5, 128, 8, 3882, 1, 3131, 4294967295, 8, 128, 8, 3883, 1, 4294967295, 4294967295, 10, 128, 8, 3884, 2, 4294967295, 4294967295, 12, 128, 8, 3886, 1, 4294967295, 3134, 9, 128, 8, 3887, 1, 4294967295, 4294967295, 1, 128, 32, 3888, 1, 4294967295, 4294967295, 3, 128, 8, 3889, 2, 3137, 4294967295, 8, 128, 8, 3891, 1, 4294967295, 4294967295, 1, 128, 32, 3892, 1, 4294967295, 4294967295, 5, 128, 8, 3893, 1, 3140, 4294967295, 8, 128, 8, 3894, 1, 4294967295, 4294967295, 10, 128, 8, 3895, 2, 4294967295, 4294967295, 12, 128, 8, 3897, 1, 4294967295, 3143, 9, 128, 8, 3898, 1, 4294967295, 4294967295, 1, 128, 32, 3899, 1, 4294967295, 4294967295, 1, 128, 32, 3900, 1, 4294967295, 4294967295, 5, 128, 8, 3901, 1, 3147, 4294967295, 8, 128, 8, 3902, 1, 4294967295, 4294967295, 10, 128, 8, 3903, 2, 4294967295, 4294967295, 12, 128, 8, 3905, 1, 4294967295, 3150, 9, 128, 8, 3906, 1, 4294967295, 4294967295, 1, 128, 8, 3907, 1, 4294967295, 4294967295, 1, 128, 8, 3908, 1, 4294967295, 4294967295, 3, 128, 8, 3909, 2, 3154, 4294967295, 8, 128, 8, 3911, 1, 4294967295, 4294967295, 1, 128, 32, 3912, 1, 4294967295, 4294967295, 1, 128, 32, 3913, 1, 4294967295, 4294967295, 5, 128, 8, 3914, 1, 3158, 4294967295, 8, 128, 8, 3915, 1, 4294967295, 4294967295, 10, 128, 8, 3916, 2, 4294967295, 4294967295, 12, 128, 8, 3918, 1, 4294967295, 3161, 9, 128, 8, 3919, 1, 4294967295, 4294967295, 1, 128, 32, 3920, 1, 4294967295, 4294967295, 1, 128, 32, 3921, 1, 4294967295, 4294967295, 5, 128, 8, 3922, 1, 3165, 4294967295, 8, 128, 8, 3923, 1, 4294967295, 4294967295, 10, 128, 8, 3924, 2, 4294967295, 4294967295, 12, 128, 8, 3926, 1, 4294967295, 3168, 9, 128, 8, 3927, 1, 4294967295, 4294967295, 1, 128, 8, 3928, 1, 4294967295, 4294967295, 1, 128, 8, 3929, 1, 4294967295, 4294967295, 3, 128, 8, 3930, 2, 3172, 4294967295, 8, 128, 8, 3932, 1, 4294967295, 4294967295, 3, 128, 8, 3933, 2, 3174, 4294967295, 8, 128, 8, 3935, 1, 4294967295, 4294967295, 1, 129, 8, 3936, 1, 4294967295, 4294967295, 1, 129, 8, 3937, 1, 4294967295, 4294967295, 1, 129, 8, 3938, 1, 4294967295, 4294967295, 3, 129, 8, 3939, 3, 3179, 4294967295, 8, 129, 8, 3942, 1, 4294967295, 4294967295, 1, 130, 8, 3943, 1, 4294967295, 4294967295, 1, 130, 32, 3944, 1, 4294967295, 4294967295, 5, 130, 8, 3945, 1, 3183, 4294967295, 8, 130, 8, 3946, 1, 4294967295, 4294967295, 10, 130, 8, 3947, 2, 4294967295, 4294967295, 12, 130, 8, 3949, 1, 4294967295, 3186, 9, 130, 8, 3950, 1, 4294967295, 4294967295, 1, 130, 8, 3951, 1, 4294967295, 4294967295, 1, 130, 8, 3952, 1, 4294967295, 4294967295, 1, 131, 8, 3953, 1, 4294967295, 4294967295, 1, 131, 32, 3954, 1, 4294967295, 4294967295, 5, 131, 8, 3955, 1, 3192, 4294967295, 8, 131, 8, 3956, 1, 4294967295, 4294967295, 10, 131, 8, 3957, 2, 4294967295, 4294967295, 12, 131, 8, 3959, 1, 4294967295, 3195, 9, 131, 8, 3960, 1, 4294967295, 4294967295, 1, 131, 8, 3961, 1, 4294967295, 4294967295, 1, 131, 8, 3962, 1, 4294967295, 4294967295, 1, 132, 32, 3963, 1, 4294967295, 4294967295, 1, 132, 32, 3964, 1, 4294967295, 4294967295, 5, 132, 8, 3965, 1, 3201, 4294967295, 8, 132, 8, 3966, 1, 4294967295, 4294967295, 10, 132, 8, 3967, 2, 4294967295, 4294967295, 12, 132, 8, 3969, 1, 4294967295, 3204, 9, 132, 8, 3970, 1, 4294967295, 4294967295, 1, 132, 8, 3971, 1, 4294967295, 4294967295, 1, 132, 32, 3972, 1, 4294967295, 4294967295, 5, 132, 8, 3973, 1, 3208, 4294967295, 8, 132, 8, 3974, 1, 4294967295, 4294967295, 10, 132, 8, 3975, 2, 4294967295, 4294967295, 12, 132, 8, 3977, 1, 4294967295, 3211, 9, 132, 8, 3978, 1, 4294967295, 4294967295, 1, 132, 8, 3979, 1, 4294967295, 4294967295, 4, 132, 8, 3980, 1, 3214, 4294967295, 8, 132, 8, 3981, 1, 4294967295, 4294967295, 11, 132, 8, 3982, 2, 4294967295, 4294967295, 12, 132, 8, 3984, 1, 4294967295, 3215, 1, 132, 32, 3985, 1, 4294967295, 4294967295, 5, 132, 8, 3986, 1, 3219, 4294967295, 8, 132, 8, 3987, 1, 4294967295, 4294967295, 10, 132, 8, 3988, 2, 4294967295, 4294967295, 12, 132, 8, 3990, 1, 4294967295, 3222, 9, 132, 8, 3991, 1, 4294967295, 4294967295, 1, 132, 8, 3992, 1, 4294967295, 4294967295, 3, 132, 8, 3993, 2, 3225, 4294967295, 8, 132, 8, 3995, 1, 4294967295, 4294967295, 1, 132, 32, 3996, 1, 4294967295, 4294967295, 5, 132, 8, 3997, 1, 3228, 4294967295, 8, 132, 8, 3998, 1, 4294967295, 4294967295, 10, 132, 8, 3999, 2, 4294967295, 4294967295, 12, 132, 8, 4001, 1, 4294967295, 3231, 9, 132, 8, 4002, 1, 4294967295, 4294967295, 1, 132, 8, 4003, 1, 4294967295, 4294967295, 3, 132, 8, 4004, 2, 3234, 4294967295, 8, 132, 8, 4006, 1, 4294967295, 4294967295, 1, 133, 32, 4007, 1, 4294967295, 4294967295, 1, 133, 32, 4008, 1, 4294967295, 4294967295, 5, 133, 8, 4009, 1, 3238, 4294967295, 8, 133, 8, 4010, 1, 4294967295, 4294967295, 10, 133, 8, 4011, 2, 4294967295, 4294967295, 12, 133, 8, 4013, 1, 4294967295, 3241, 9, 133, 8, 4014, 1, 4294967295, 4294967295, 1, 133, 32, 4015, 1, 4294967295, 4294967295, 1, 133, 8, 4016, 1, 4294967295, 4294967295, 5, 133, 8, 4017, 1, 3245, 4294967295, 8, 133, 8, 4018, 1, 4294967295, 4294967295, 10, 133, 8, 4019, 2, 4294967295, 4294967295, 12, 133, 8, 4021, 1, 4294967295, 3248, 9, 133, 8, 4022, 1, 4294967295, 4294967295, 1, 133, 8, 4023, 1, 4294967295, 4294967295, 1, 133, 32, 4024, 1, 4294967295, 4294967295, 1, 133, 8, 4025, 1, 4294967295, 4294967295, 1, 133, 32, 4026, 1, 4294967295, 4294967295, 5, 133, 8, 4027, 1, 3254, 4294967295, 8, 133, 8, 4028, 1, 4294967295, 4294967295, 10, 133, 8, 4029, 2, 4294967295, 4294967295, 12, 133, 8, 4031, 1, 4294967295, 3257, 9, 133, 8, 4032, 1, 4294967295, 4294967295, 1, 133, 32, 4033, 1, 4294967295, 4294967295, 3, 133, 8, 4034, 2, 3260, 4294967295, 8, 133, 8, 4036, 1, 4294967295, 4294967295, 1, 133, 32, 4037, 1, 4294967295, 4294967295, 1, 133, 32, 4038, 1, 4294967295, 4294967295, 5, 133, 8, 4039, 1, 3264, 4294967295, 8, 133, 8, 4040, 1, 4294967295, 4294967295, 10, 133, 8, 4041, 2, 4294967295, 4294967295, 12, 133, 8, 4043, 1, 4294967295, 3267, 9, 133, 8, 4044, 1, 4294967295, 4294967295, 1, 133, 8, 4045, 1, 4294967295, 4294967295, 1, 133, 8, 4046, 1, 4294967295, 4294967295, 1, 134, 32, 4047, 1, 4294967295, 4294967295, 1, 134, 32, 4048, 1, 4294967295, 4294967295, 5, 134, 8, 4049, 1, 3273, 4294967295, 8, 134, 8, 4050, 1, 4294967295, 4294967295, 10, 134, 8, 4051, 2, 4294967295, 4294967295, 12, 134, 8, 4053, 1, 4294967295, 3276, 9, 134, 8, 4054, 1, 4294967295, 4294967295, 1, 134, 8, 4055, 1, 4294967295, 4294967295, 1, 134, 8, 4056, 1, 4294967295, 4294967295, 1, 135, 32, 4057, 1, 4294967295, 4294967295, 1, 135, 32, 4058, 1, 4294967295, 4294967295, 5, 135, 8, 4059, 1, 3282, 4294967295, 8, 135, 8, 4060, 1, 4294967295, 4294967295, 10, 135, 8, 4061, 2, 4294967295, 4294967295, 12, 135, 8, 4063, 1, 4294967295, 3285, 9, 135, 8, 4064, 1, 4294967295, 4294967295, 1, 135, 8, 4065, 1, 4294967295, 4294967295, 1, 135, 32, 4066, 1, 4294967295, 4294967295, 1, 135, 8, 4067, 1, 4294967295, 4294967295, 3, 135, 8, 4068, 2, 3290, 4294967295, 8, 135, 8, 4070, 1, 4294967295, 4294967295, 1, 135, 32, 4071, 1, 4294967295, 4294967295, 1, 135, 32, 4072, 1, 4294967295, 4294967295, 1, 135, 32, 4073, 1, 4294967295, 4294967295, 1, 135, 32, 4074, 1, 4294967295, 4294967295, 3, 135, 8, 4075, 6, 3296, 4294967295, 8, 135, 8, 4081, 1, 4294967295, 4294967295, 1, 136, 8, 4082, 1, 4294967295, 4294967295, 3, 136, 8, 4083, 2, 3299, 4294967295, 8, 136, 8, 4085, 1, 4294967295, 4294967295, 1, 136, 32, 4086, 1, 4294967295, 4294967295, 1, 136, 32, 4087, 1, 4294967295, 4294967295, 5, 136, 8, 4088, 1, 3303, 4294967295, 8, 136, 8, 4089, 1, 4294967295, 4294967295, 10, 136, 8, 4090, 2, 4294967295, 4294967295, 12, 136, 8, 4092, 1, 4294967295, 3306, 9, 136, 8, 4093, 1, 4294967295, 4294967295, 1, 136, 8, 4094, 1, 4294967295, 4294967295, 1, 136, 32, 4095, 1, 4294967295, 4294967295, 3, 136, 8, 4096, 2, 3310, 4294967295, 8, 136, 8, 4098, 1, 4294967295, 4294967295, 1, 137, 32, 4099, 1, 4294967295, 4294967295, 1, 137, 8, 4100, 1, 4294967295, 4294967295, 1, 138, 32, 4101, 1, 4294967295, 4294967295, 1, 138, 8, 4102, 1, 4294967295, 4294967295, 1, 139, 32, 4103, 1, 4294967295, 4294967295, 1, 139, 8, 4104, 1, 4294967295, 4294967295, 1, 140, 32, 4105, 1, 4294967295, 4294967295, 1, 140, 8, 4106, 1, 4294967295, 4294967295, 1, 141, 32, 4107, 1, 4294967295, 4294967295, 1, 141, 8, 4108, 1, 4294967295, 4294967295, 1, 142, 32, 4109, 1, 4294967295, 4294967295, 1, 142, 8, 4110, 1, 4294967295, 4294967295, 1, 143, 32, 4111, 1, 4294967295, 4294967295, 1, 143, 8, 4112, 1, 4294967295, 4294967295, 1, 144, 32, 4113, 1, 4294967295, 4294967295, 1, 144, 8, 4114, 1, 4294967295, 4294967295, 1, 145, 32, 4115, 1, 4294967295, 4294967295, 1, 145, 32, 4116, 1, 4294967295, 4294967295, 1, 145, 32, 4117, 1, 4294967295, 4294967295, 1, 145, 32, 4118, 1, 4294967295, 4294967295, 1, 145, 8, 4119, 1, 4294967295, 4294967295, 3, 145, 8, 4120, 5, 3333, 4294967295, 8, 145, 8, 4125, 1, 4294967295, 4294967295, 1, 146, 32, 4126, 1, 4294967295, 4294967295, 1, 146, 32, 4127, 1, 4294967295, 4294967295, 1, 146, 32, 4128, 1, 4294967295, 4294967295, 1, 146, 8, 4129, 1, 4294967295, 4294967295, 3, 146, 8, 4130, 3, 3339, 4294967295, 8, 146, 8, 4133, 1, 4294967295, 4294967295, 1, 147, 32, 4134, 1, 4294967295, 4294967295, 1, 147, 8, 4135, 1, 4294967295, 4294967295, 1, 148, 32, 4136, 1, 4294967295, 4294967295, 5, 148, 8, 4137, 1, 3344, 4294967295, 8, 148, 8, 4138, 1, 4294967295, 4294967295, 10, 148, 8, 4139, 2, 4294967295, 4294967295, 12, 148, 8, 4141, 1, 4294967295, 3347, 9, 148, 8, 4142, 1, 4294967295, 4294967295, 1, 148, 32, 4143, 1, 4294967295, 4294967295, 1, 148, 32, 4144, 1, 4294967295, 4294967295, 5, 148, 8, 4145, 1, 3351, 4294967295, 8, 148, 8, 4146, 1, 4294967295, 4294967295, 10, 148, 8, 4147, 2, 4294967295, 4294967295, 12, 148, 8, 4149, 1, 4294967295, 3354, 9, 148, 8, 4150, 1, 4294967295, 4294967295, 1, 148, 8, 4151, 1, 4294967295, 4294967295, 1, 148, 32, 4152, 1, 4294967295, 4294967295, 3, 148, 8, 4153, 3, 3358, 4294967295, 8, 148, 8, 4156, 1, 4294967295, 4294967295, 1, 149, 32, 4157, 1, 4294967295, 4294967295, 1, 149, 32, 4158, 1, 4294967295, 4294967295, 1, 149, 8, 4159, 1, 4294967295, 4294967295, 1, 150, 8, 4160, 1, 4294967295, 4294967295, 1, 150, 8, 4161, 1, 4294967295, 4294967295, 4, 150, 8, 4162, 2, 3365, 4294967295, 8, 150, 8, 4164, 1, 4294967295, 4294967295, 11, 150, 8, 4165, 2, 4294967295, 4294967295, 12, 150, 8, 4167, 1, 4294967295, 3366, 1, 151, 8, 4168, 1, 4294967295, 4294967295, 1, 151, 8, 4169, 1, 4294967295, 4294967295, 4, 151, 8, 4170, 2, 3371, 4294967295, 8, 151, 8, 4172, 1, 4294967295, 4294967295, 11, 151, 8, 4173, 2, 4294967295, 4294967295, 12, 151, 8, 4175, 1, 4294967295, 3372, 1, 152, 8, 4176, 1, 4294967295, 4294967295, 1, 152, 8, 4177, 1, 4294967295, 4294967295, 1, 152, 8, 4178, 1, 4294967295, 4294967295, 1, 152, 8, 4179, 1, 4294967295, 4294967295, 1, 152, 8, 4180, 1, 4294967295, 4294967295, 1, 152, 8, 4181, 1, 4294967295, 4294967295, 1, 152, 8, 4182, 1, 4294967295, 4294967295, 1, 152, 8, 4183, 1, 4294967295, 4294967295, 3, 152, 8, 4184, 8, 3383, 4294967295, 8, 152, 8, 4192, 1, 4294967295, 4294967295, 1, 152, 32, 4193, 1, 4294967295, 4294967295, 5, 152, 8, 4194, 1, 3386, 4294967295, 8, 152, 8, 4195, 1, 4294967295, 4294967295, 10, 152, 8, 4196, 2, 4294967295, 4294967295, 12, 152, 8, 4198, 1, 4294967295, 3389, 9, 152, 8, 4199, 1, 4294967295, 4294967295, 1, 153, 8, 4200, 1, 4294967295, 4294967295, 4, 153, 8, 4201, 1, 3392, 4294967295, 8, 153, 8, 4202, 1, 4294967295, 4294967295, 11, 153, 8, 4203, 2, 4294967295, 4294967295, 12, 153, 8, 4205, 1, 4294967295, 3393, 1, 154, 8, 4206, 1, 4294967295, 4294967295, 1, 154, 32, 4207, 1, 4294967295, 4294967295, 1, 154, 32, 4208, 1, 4294967295, 4294967295, 5, 154, 8, 4209, 1, 3399, 4294967295, 8, 154, 8, 4210, 1, 4294967295, 4294967295, 10, 154, 8, 4211, 2, 4294967295, 4294967295, 12, 154, 8, 4213, 1, 4294967295, 3402, 9, 154, 8, 4214, 1, 4294967295, 4294967295, 3, 154, 8, 4215, 2, 3404, 4294967295, 8, 154, 8, 4217, 1, 4294967295, 4294967295, 1, 155, 32, 4218, 1, 4294967295, 4294967295, 1, 155, 8, 4219, 1, 4294967295, 4294967295, 1, 156, 32, 4220, 1, 4294967295, 4294967295, 1, 156, 8, 4221, 1, 4294967295, 4294967295, 1, 157, 32, 4222, 1, 4294967295, 4294967295, 1, 157, 8, 4223, 1, 4294967295, 4294967295, 1, 158, 32, 4224, 1, 4294967295, 4294967295, 1, 158, 8, 4225, 1, 4294967295, 4294967295, 1, 159, 8, 4226, 1, 4294967295, 4294967295, 4, 159, 8, 4227, 1, 3415, 4294967295, 8, 159, 8, 4228, 1, 4294967295, 4294967295, 11, 159, 8, 4229, 2, 4294967295, 4294967295, 12, 159, 8, 4231, 1, 4294967295, 3416, 1, 160, 8, 4232, 1, 4294967295, 4294967295, 1, 160, 32, 4233, 1, 4294967295, 4294967295, 5, 160, 8, 4234, 1, 3421, 4294967295, 8, 160, 8, 4235, 1, 4294967295, 4294967295, 10, 160, 8, 4236, 2, 4294967295, 4294967295, 12, 160, 8, 4238, 1, 4294967295, 3424, 9, 160, 8, 4239, 1, 4294967295, 4294967295, 1, 160, 8, 4240, 1, 4294967295, 4294967295, 1, 160, 32, 4241, 1, 4294967295, 4294967295, 5, 160, 8, 4242, 1, 3428, 4294967295, 8, 160, 8, 4243, 1, 4294967295, 4294967295, 10, 160, 8, 4244, 2, 4294967295, 4294967295, 12, 160, 8, 4246, 1, 4294967295, 3431, 9, 160, 8, 4247, 1, 4294967295, 4294967295, 1, 160, 8, 4248, 1, 4294967295, 4294967295, 3, 160, 8, 4249, 3, 3434, 4294967295, 8, 160, 8, 4252, 1, 4294967295, 4294967295, 1, 161, 32, 4253, 1, 4294967295, 4294967295, 1, 161, 8, 4254, 1, 4294967295, 4294967295, 1, 162, 32, 4255, 1, 4294967295, 4294967295, 1, 162, 8, 4256, 1, 4294967295, 4294967295, 1, 163, 32, 4257, 1, 4294967295, 4294967295, 1, 163, 8, 4258, 1, 4294967295, 4294967295, 1, 164, 32, 4259, 1, 4294967295, 4294967295, 1, 164, 8, 4260, 1, 4294967295, 4294967295, 1, 165, 32, 4261, 1, 4294967295, 4294967295, 1, 165, 8, 4262, 1, 4294967295, 4294967295, 1, 166, 32, 4263, 1, 4294967295, 4294967295, 1, 166, 8, 4264, 1, 4294967295, 4294967295, 1, 167, 8, 4265, 1, 4294967295, 4294967295, 1, 167, 8, 4266, 1, 4294967295, 4294967295, 3, 167, 8, 4267, 2, 3450, 4294967295, 8, 167, 8, 4269, 1, 4294967295, 4294967295, 1, 167, 32, 4270, 1, 4294967295, 4294967295, 5, 167, 8, 4271, 1, 3453, 4294967295, 8, 167, 8, 4272, 1, 4294967295, 4294967295, 10, 167, 8, 4273, 2, 4294967295, 4294967295, 12, 167, 8, 4275, 1, 4294967295, 3456, 9, 167, 8, 4276, 1, 4294967295, 4294967295, 1, 168, 8, 4277, 1, 4294967295, 4294967295, 1, 168, 32, 4278, 1, 4294967295, 4294967295, 5, 168, 8, 4279, 1, 3460, 4294967295, 8, 168, 8, 4280, 1, 4294967295, 4294967295, 10, 168, 8, 4281, 2, 4294967295, 4294967295, 12, 168, 8, 4283, 1, 4294967295, 3463, 9, 168, 8, 4284, 1, 4294967295, 4294967295, 1, 168, 32, 4285, 1, 4294967295, 4294967295, 1, 168, 32, 4286, 1, 4294967295, 4294967295, 3, 168, 8, 4287, 3, 3467, 4294967295, 8, 168, 8, 4290, 1, 4294967295, 4294967295, 1, 168, 8, 4291, 1, 4294967295, 4294967295, 1, 168, 8, 4292, 1, 4294967295, 4294967295, 1, 169, 8, 4293, 1, 4294967295, 4294967295, 1, 169, 32, 4294, 1, 4294967295, 4294967295, 5, 169, 8, 4295, 1, 3473, 4294967295, 8, 169, 8, 4296, 1, 4294967295, 4294967295, 10, 169, 8, 4297, 2, 4294967295, 4294967295, 12, 169, 8, 4299, 1, 4294967295, 3476, 9, 169, 8, 4300, 1, 4294967295, 4294967295, 1, 169, 32, 4301, 1, 4294967295, 4294967295, 1, 169, 32, 4302, 1, 4294967295, 4294967295, 3, 169, 8, 4303, 3, 3480, 4294967295, 8, 169, 8, 4306, 1, 4294967295, 4294967295, 1, 169, 32, 4307, 1, 4294967295, 4294967295, 1, 169, 8, 4308, 1, 4294967295, 4294967295, 4, 169, 8, 4309, 1, 3484, 4294967295, 8, 169, 8, 4310, 1, 4294967295, 4294967295, 11, 169, 8, 4311, 2, 4294967295, 4294967295, 12, 169, 8, 4313, 1, 4294967295, 3485, 1, 169, 32, 4314, 1, 4294967295, 4294967295, 1, 169, 8, 4315, 1, 4294967295, 4294967295, 1, 170, 32, 4316, 1, 4294967295, 4294967295, 1, 170, 32, 4317, 1, 4294967295, 4294967295, 1, 170, 32, 4318, 1, 4294967295, 4294967295, 5, 170, 8, 4319, 1, 3493, 4294967295, 8, 170, 8, 4320, 1, 4294967295, 4294967295, 10, 170, 8, 4321, 2, 4294967295, 4294967295, 12, 170, 8, 4323, 1, 4294967295, 3496, 9, 170, 8, 4324, 1, 4294967295, 4294967295, 1, 170, 32, 4325, 1, 4294967295, 4294967295, 1, 170, 8, 4326, 1, 4294967295, 4294967295, 1, 171, 8, 4327, 1, 4294967295, 4294967295, 1, 171, 8, 4328, 1, 4294967295, 4294967295, 3, 171, 8, 4329, 2, 3502, 4294967295, 8, 171, 8, 4331, 1, 4294967295, 4294967295, 1, 172, 32, 4332, 1, 4294967295, 4294967295, 1, 172, 8, 4333, 1, 4294967295, 4294967295, 1, 173, 8, 4334, 1, 4294967295, 4294967295, 1, 173, 32, 4335, 1, 4294967295, 4294967295, 5, 173, 8, 4336, 1, 3508, 4294967295, 8, 173, 8, 4337, 1, 4294967295, 4294967295, 10, 173, 8, 4338, 2, 4294967295, 4294967295, 12, 173, 8, 4340, 1, 4294967295, 3511, 9, 173, 8, 4341, 1, 4294967295, 4294967295, 1, 173, 32, 4342, 1, 4294967295, 4294967295, 1, 173, 8, 4343, 1, 4294967295, 4294967295, 5, 173, 8, 4344, 1, 3515, 4294967295, 8, 173, 8, 4345, 1, 4294967295, 4294967295, 10, 173, 8, 4346, 2, 4294967295, 4294967295, 12, 173, 8, 4348, 1, 4294967295, 3518, 9, 173, 8, 4349, 1, 4294967295, 4294967295, 1, 173, 0, 4350, 0, 4294967295, 4294967295, 1, 349, 0, 0, 0, 1, 374, 0, 0, 0, 1, 400, 0, 0, 0, 1, 350, 0, 0, 0, 1, 375, 0, 0, 0, 1, 406, 0, 0, 0, 1, 359, 0, 0, 0, 1, 384, 0, 0, 0, 1, 443, 0, 0, 0, 1, 364, 0, 0, 0, 1, 389, 0, 0, 0, 1, 448, 0, 0, 0, 1, 368, 0, 0, 0, 1, 395, 0, 0, 0, 1, 451, 0, 0, 0, 1, 447, 0, 0, 0, 1, 461, 0, 0, 0, 1, 457, 0, 0, 0, 1, 464, 0, 0, 0, 1, 367, 0, 0, 0, 1, 469, 0, 0, 0, 1, 509, 0, 0, 0, 1, 508, 0, 0, 0, 1, 466, 0, 0, 0, 1, 914, 0, 0, 0, 1, 1965, 0, 0, 0, 1, 511, 0, 0, 0, 1, 509, 0, 0, 0, 1, 602, 0, 0, 0, 1, 550, 0, 0, 0, 1, 606, 0, 0, 0, 1, 591, 0, 0, 0, 1, 977, 0, 0, 0, 1, 1567, 0, 0, 0, 1, 1703, 0, 0, 0, 1, 2937, 0, 0, 0, 1, 622, 0, 0, 0, 1, 605, 0, 0, 0, 1, 669, 0, 0, 0, 1, 646, 0, 0, 0, 1, 645, 0, 0, 0, 1, 705, 0, 0, 0, 1, 566, 0, 0, 0, 1, 968, 0, 0, 0, 1, 1558, 0, 0, 0, 1, 2924, 0, 0, 0, 1, 737, 0, 0, 0, 1, 761, 0, 0, 0, 1, 739, 0, 0, 0, 1, 738, 0, 0, 0, 1, 3502, 0, 0, 0, 1, 751, 0, 0, 0, 1, 722, 0, 0, 0, 1, 721, 0, 0, 0, 1, 764, 0, 0, 0, 1, 738, 0, 0, 0, 1, 781, 0, 0, 0, 1, 487, 0, 0, 0, 1, 541, 0, 0, 0, 1, 1056, 0, 0, 0, 1, 1218, 0, 0, 0, 1, 826, 0, 0, 0, 1, 805, 0, 0, 0, 1, 804, 0, 0, 0, 1, 851, 0, 0, 0, 1, 575, 0, 0, 0, 1, 1112, 0, 0, 0, 1, 1254, 0, 0, 0, 1, 2883, 0, 0, 0, 1, 881, 0, 0, 0, 1, 875, 0, 0, 0, 1, 874, 0, 0, 0, 1, 906, 0, 0, 0, 1, 617, 0, 0, 0, 1, 1638, 0, 0, 0, 1, 913, 0, 0, 0, 1, 902, 0, 0, 0, 1, 915, 0, 0, 0, 1, 914, 0, 0, 0, 1, 925, 0, 0, 0, 1, 914, 0, 0, 0, 1, 978, 0, 0, 0, 1, 1102, 0, 0, 0, 1, 1593, 0, 0, 0, 1, 1025, 0, 0, 0, 1, 1002, 0, 0, 0, 1, 1001, 0, 0, 0, 1, 1045, 0, 0, 0, 1, 509, 0, 0, 0, 1, 1131, 0, 0, 0, 1, 1121, 0, 0, 0, 1, 1372, 0, 0, 0, 1, 1430, 0, 0, 0, 1, 2892, 0, 0, 0, 1, 1136, 0, 0, 0, 1, 1186, 0, 0, 0, 1, 1185, 0, 0, 0, 1, 1245, 0, 0, 0, 1, 2016, 0, 0, 0, 1, 2824, 0, 0, 0, 1, 3051, 0, 0, 0, 1, 1162, 0, 0, 0, 1, 1245, 0, 0, 0, 1, 2016, 0, 0, 0, 1, 2821, 0, 0, 0, 1, 1207, 0, 0, 0, 1, 509, 0, 0, 0, 1, 1321, 0, 0, 0, 1, 1271, 0, 0, 0, 1, 1331, 0, 0, 0, 1, 1291, 0, 0, 0, 1, 1318, 0, 0, 0, 1, 1374, 0, 0, 0, 1, 1303, 0, 0, 0, 1, 1306, 0, 0, 0, 1, 1433, 0, 0, 0, 1, 2873, 0, 0, 0, 1, 1480, 0, 0, 0, 1, 1398, 0, 0, 0, 1, 1457, 0, 0, 0, 1, 1456, 0, 0, 0, 1, 1499, 0, 0, 0, 1, 1497, 0, 0, 0, 1, 1516, 0, 0, 0, 1, 1042, 0, 0, 0, 1, 1829, 0, 0, 0, 1, 1846, 0, 0, 0, 1, 1533, 0, 0, 0, 1, 509, 0, 0, 0, 1, 1569, 0, 0, 0, 1, 914, 0, 0, 0, 1, 1604, 0, 0, 0, 1, 1594, 0, 0, 0, 1, 1613, 0, 0, 0, 1, 591, 0, 0, 0, 1, 1647, 0, 0, 0, 1, 1622, 0, 0, 0, 1, 1683, 0, 0, 0, 1, 1664, 0, 0, 0, 1, 1663, 0, 0, 0, 1, 1705, 0, 0, 0, 1, 502, 0, 0, 0, 1, 703, 0, 0, 0, 1, 850, 0, 0, 0, 1, 899, 0, 0, 0, 1, 1103, 0, 0, 0, 1, 1161, 0, 0, 0, 1, 1363, 0, 0, 0, 1, 1422, 0, 0, 0, 1, 1515, 0, 0, 0, 1, 1531, 0, 0, 0, 1, 1771, 0, 0, 0, 1, 1818, 0, 0, 0, 1, 1829, 0, 0, 0, 1, 1846, 0, 0, 0, 1, 1880, 0, 0, 0, 1, 2201, 0, 0, 0, 1, 2305, 0, 0, 0, 1, 2822, 0, 0, 0, 1, 2845, 0, 0, 0, 1, 2874, 0, 0, 0, 1, 2952, 0, 0, 0, 1, 3197, 0, 0, 0, 1, 3259, 0, 0, 0, 1, 1716, 0, 0, 0, 1, 1713, 0, 0, 0, 1, 1721, 0, 0, 0, 1, 1892, 0, 0, 0, 1, 1720, 0, 0, 0, 1, 1713, 0, 0, 0, 1, 1892, 0, 0, 0, 1, 1733, 0, 0, 0, 1, 1730, 0, 0, 0, 1, 1735, 0, 0, 0, 1, 738, 0, 0, 0, 1, 743, 0, 0, 0, 1, 765, 0, 0, 0, 1, 1717, 0, 0, 0, 1, 1903, 0, 0, 0, 1, 1918, 0, 0, 0, 1, 1938, 0, 0, 0, 1, 3502, 0, 0, 0, 1, 1755, 0, 0, 0, 1, 1752, 0, 0, 0, 1, 1751, 0, 0, 0, 1, 1770, 0, 0, 0, 1, 2499, 0, 0, 0, 1, 2498, 0, 0, 0, 1, 1773, 0, 0, 0, 1, 1767, 0, 0, 0, 1, 1785, 0, 0, 0, 1, 1774, 0, 0, 0, 1, 1801, 0, 0, 0, 1, 738, 0, 0, 0, 1, 765, 0, 0, 0, 1, 1713, 0, 0, 0, 1, 1819, 0, 0, 0, 1, 1807, 0, 0, 0, 1, 1869, 0, 0, 0, 1, 1713, 0, 0, 0, 1, 1721, 0, 0, 0, 1, 1892, 0, 0, 0, 1, 1886, 0, 0, 0, 1, 1067, 0, 0, 0, 1, 1229, 0, 0, 0, 1, 1791, 0, 0, 0, 1, 3299, 0, 0, 0, 1, 1893, 0, 0, 0, 1, 1903, 0, 0, 0, 1, 1918, 0, 0, 0, 1, 1938, 0, 0, 0, 1, 1913, 0, 0, 0, 1, 1713, 0, 0, 0, 1, 1948, 0, 0, 0, 1, 1989, 0, 0, 0, 1, 2771, 0, 0, 0, 1, 1957, 0, 0, 0, 1, 391, 0, 0, 0, 1, 1945, 0, 0, 0, 1, 1942, 0, 0, 0, 1, 1977, 0, 0, 0, 1, 1966, 0, 0, 0, 1, 1956, 0, 0, 0, 1, 2329, 0, 0, 0, 1, 2466, 0, 0, 0, 1, 1976, 0, 0, 0, 1, 2028, 0, 0, 0, 1, 2048, 0, 0, 0, 1, 2058, 0, 0, 0, 1, 3026, 0, 0, 0, 1, 2997, 0, 0, 0, 1, 3023, 0, 0, 0, 1, 3153, 0, 0, 0, 1, 3171, 0, 0, 0, 1, 1978, 0, 0, 0, 1, 923, 0, 0, 0, 1, 1132, 0, 0, 0, 1, 1603, 0, 0, 0, 1, 1977, 0, 0, 0, 1, 3233, 0, 0, 0, 1, 3269, 0, 0, 0, 1, 3278, 0, 0, 0, 1, 1997, 0, 0, 0, 1, 1965, 0, 0, 0, 1, 1999, 0, 0, 0, 1, 1998, 0, 0, 0, 1, 2029, 0, 0, 0, 1, 1998, 0, 0, 0, 1, 2049, 0, 0, 0, 1, 1998, 0, 0, 0, 1, 2082, 0, 0, 0, 1, 1965, 0, 0, 0, 1, 2092, 0, 0, 0, 1, 392, 0, 0, 0, 1, 442, 0, 0, 0, 1, 460, 0, 0, 0, 1, 1300, 0, 0, 0, 1, 1315, 0, 0, 0, 1, 3154, 0, 0, 0, 1, 3172, 0, 0, 0, 1, 2100, 0, 0, 0, 1, 467, 0, 0, 0, 1, 903, 0, 0, 0, 1, 1941, 0, 0, 0, 1, 1952, 0, 0, 0, 1, 2104, 0, 0, 0, 1, 704, 0, 0, 0, 1, 780, 0, 0, 0, 1, 1043, 0, 0, 0, 1, 1132, 0, 0, 0, 1, 1271, 0, 0, 0, 1, 1329, 0, 0, 0, 1, 1498, 0, 0, 0, 1, 1965, 0, 0, 0, 1, 2019, 0, 0, 0, 1, 2038, 0, 0, 0, 1, 2074, 0, 0, 0, 1, 2091, 0, 0, 0, 1, 2416, 0, 0, 0, 1, 2415, 0, 0, 0, 1, 2600, 0, 0, 0, 1, 2628, 0, 0, 0, 1, 2657, 0, 0, 0, 1, 2656, 0, 0, 0, 1, 2719, 0, 0, 0, 1, 2737, 0, 0, 0, 1, 2984, 0, 0, 0, 1, 3064, 0, 0, 0, 1, 3179, 0, 0, 0, 1, 3188, 0, 0, 0, 1, 3296, 0, 0, 0, 1, 3290, 0, 0, 0, 1, 2106, 0, 0, 0, 1, 2105, 0, 0, 0, 1, 2126, 0, 0, 0, 1, 2123, 0, 0, 0, 1, 2122, 0, 0, 0, 1, 2146, 0, 0, 0, 1, 2143, 0, 0, 0, 1, 2142, 0, 0, 0, 1, 2161, 0, 0, 0, 1, 2158, 0, 0, 0, 1, 2155, 0, 0, 0, 1, 2176, 0, 0, 0, 1, 2173, 0, 0, 0, 1, 2170, 0, 0, 0, 1, 2183, 0, 0, 0, 1, 2180, 0, 0, 0, 1, 2207, 0, 0, 0, 1, 2204, 0, 0, 0, 1, 2192, 0, 0, 0, 1, 2228, 0, 0, 0, 1, 2218, 0, 0, 0, 1, 2231, 0, 0, 0, 1, 2225, 0, 0, 0, 1, 2222, 0, 0, 0, 1, 2246, 0, 0, 0, 1, 2243, 0, 0, 0, 1, 2240, 0, 0, 0, 1, 2260, 0, 0, 0, 1, 2257, 0, 0, 0, 1, 2256, 0, 0, 0, 1, 2275, 0, 0, 0, 1, 2272, 0, 0, 0, 1, 2269, 0, 0, 0, 1, 2290, 0, 0, 0, 1, 2287, 0, 0, 0, 1, 2284, 0, 0, 0, 1, 2314, 0, 0, 0, 1, 2308, 0, 0, 0, 1, 2370, 0, 0, 0, 1, 2328, 0, 0, 0, 1, 2313, 0, 0, 0, 1, 2330, 0, 0, 0, 1, 2318, 0, 0, 0, 1, 2345, 0, 0, 0, 1, 2342, 0, 0, 0, 1, 2333, 0, 0, 0, 1, 2349, 0, 0, 0, 1, 2077, 0, 0, 0, 1, 2362, 0, 0, 0, 1, 2351, 0, 0, 0, 1, 2350, 0, 0, 0, 1, 2369, 0, 0, 0, 1, 2080, 0, 0, 0, 1, 2382, 0, 0, 0, 1, 2371, 0, 0, 0, 1, 2370, 0, 0, 0, 1, 2390, 0, 0, 0, 1, 2346, 0, 0, 0, 1, 2392, 0, 0, 0, 1, 2343, 0, 0, 0, 1, 2391, 0, 0, 0, 1, 2436, 0, 0, 0, 1, 2343, 0, 0, 0, 1, 2391, 0, 0, 0, 1, 2449, 0, 0, 0, 1, 2179, 0, 0, 0, 1, 2343, 0, 0, 0, 1, 2461, 0, 0, 0, 1, 2457, 0, 0, 0, 1, 2475, 0, 0, 0, 1, 1764, 0, 0, 0, 1, 2343, 0, 0, 0, 1, 2391, 0, 0, 0, 1, 2450, 0, 0, 0, 1, 2519, 0, 0, 0, 1, 747, 0, 0, 0, 1, 1612, 0, 0, 0, 1, 1694, 0, 0, 0, 1, 2453, 0, 0, 0, 1, 2457, 0, 0, 0, 1, 2566, 0, 0, 0, 1, 2543, 0, 0, 0, 1, 2542, 0, 0, 0, 1, 2615, 0, 0, 0, 1, 2334, 0, 0, 0, 1, 2617, 0, 0, 0, 1, 2447, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2633, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2679, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2683, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2685, 0, 0, 0, 1, 2684, 0, 0, 0, 1, 2695, 0, 0, 0, 1, 2684, 0, 0, 0, 1, 2706, 0, 0, 0, 1, 2689, 0, 0, 0, 1, 2708, 0, 0, 0, 1, 2689, 0, 0, 0, 1, 2724, 0, 0, 0, 1, 2700, 0, 0, 0, 1, 2726, 0, 0, 0, 1, 2700, 0, 0, 0, 1, 2742, 0, 0, 0, 1, 2474, 0, 0, 0, 1, 2896, 0, 0, 0, 1, 2776, 0, 0, 0, 1, 2751, 0, 0, 0, 1, 2823, 0, 0, 0, 1, 2793, 0, 0, 0, 1, 2792, 0, 0, 0, 1, 2826, 0, 0, 0, 1, 2896, 0, 0, 0, 1, 2895, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2898, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2938, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2964, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2966, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 3027, 0, 0, 0, 1, 3075, 0, 0, 0, 1, 3066, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 3173, 0, 0, 0, 1, 3093, 0, 0, 0, 1, 3178, 0, 0, 0, 1, 3126, 0, 0, 0, 1, 3125, 0, 0, 0, 1, 3180, 0, 0, 0, 1, 3179, 0, 0, 0, 1, 3189, 0, 0, 0, 1, 3179, 0, 0, 0, 1, 3198, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 3235, 0, 0, 0, 1, 3214, 0, 0, 0, 1, 3270, 0, 0, 0, 1, 3225, 0, 0, 0, 1, 3234, 0, 0, 0, 1, 3295, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 3298, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 3311, 0, 0, 0, 1, 2081, 0, 0, 0, 1, 3313, 0, 0, 0, 1, 2151, 0, 0, 0, 1, 3315, 0, 0, 0, 1, 2166, 0, 0, 0, 1, 3317, 0, 0, 0, 1, 2188, 0, 0, 0, 1, 3184, 0, 0, 0, 1, 3319, 0, 0, 0, 1, 2197, 0, 0, 0, 1, 3193, 0, 0, 0, 1, 3321, 0, 0, 0, 1, 2265, 0, 0, 0, 1, 3323, 0, 0, 0, 1, 2280, 0, 0, 0, 1, 3325, 0, 0, 0, 1, 2301, 0, 0, 0, 1, 3332, 0, 0, 0, 1, 2325, 0, 0, 0, 1, 3338, 0, 0, 0, 1, 2343, 0, 0, 0, 1, 3340, 0, 0, 0, 1, 3333, 0, 0, 0, 1, 3339, 0, 0, 0, 1, 3357, 0, 0, 0, 1, 2440, 0, 0, 0, 1, 3359, 0, 0, 0, 1, 3358, 0, 0, 0, 1, 3364, 0, 0, 0, 1, 470, 0, 0, 0, 1, 512, 0, 0, 0, 1, 594, 0, 0, 0, 1, 670, 0, 0, 0, 1, 926, 0, 0, 0, 1, 1046, 0, 0, 0, 1, 1208, 0, 0, 0, 1, 1332, 0, 0, 0, 1, 1375, 0, 0, 0, 1, 1534, 0, 0, 0, 1, 1570, 0, 0, 0, 1, 1680, 0, 0, 0, 1, 3370, 0, 0, 0, 1, 1026, 0, 0, 0, 1, 1481, 0, 0, 0, 1, 3382, 0, 0, 0, 1, 3365, 0, 0, 0, 1, 3391, 0, 0, 0, 1, 1706, 0, 0, 0, 1, 1887, 0, 0, 0, 1, 1914, 0, 0, 0, 1, 1934, 0, 0, 0, 1, 3403, 0, 0, 0, 1, 3392, 0, 0, 0, 1, 3405, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3407, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3409, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3411, 0, 0, 0, 1, 1781, 0, 0, 0, 1, 3429, 0, 0, 0, 1, 3414, 0, 0, 0, 1, 827, 0, 0, 0, 1, 3433, 0, 0, 0, 1, 3415, 0, 0, 0, 1, 3435, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3437, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3439, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3441, 0, 0, 0, 1, 3371, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3443, 0, 0, 0, 1, 3422, 0, 0, 0, 1, 3445, 0, 0, 0, 1, 3383, 0, 0, 0, 1, 3449, 0, 0, 0, 1, 750, 0, 0, 0, 1, 880, 0, 0, 0, 1, 1135, 0, 0, 0, 1, 1786, 0, 0, 0, 1, 1956, 0, 0, 0, 1, 2009, 0, 0, 0, 1, 2329, 0, 0, 0, 1, 2460, 0, 0, 0, 1, 2567, 0, 0, 0, 1, 3030, 0, 0, 0, 1, 3245, 0, 0, 0, 1, 3365, 0, 0, 0, 1, 3371, 0, 0, 0, 1, 3404, 0, 0, 0, 1, 3434, 0, 0, 0, 1, 3466, 0, 0, 0, 1, 3450, 0, 0, 0, 1, 3479, 0, 0, 0, 1, 3450, 0, 0, 0, 1, 3489, 0, 0, 0, 1, 3461, 0, 0, 0, 1, 3474, 0, 0, 0, 1, 3501, 0, 0, 0, 1, 424, 0, 0, 0, 1, 431, 0, 0, 0, 1, 3469, 0, 0, 0, 1, 3484, 0, 0, 0, 1, 3503, 0, 0, 0, 1, 463, 0, 0, 0, 1, 486, 0, 0, 0, 1, 540, 0, 0, 0, 1, 681, 0, 0, 0, 1, 849, 0, 0, 0, 1, 888, 0, 0, 0, 1, 952, 0, 0, 0, 1, 1084, 0, 0, 0, 1, 1160, 0, 0, 0, 1, 1503, 0, 0, 0, 1, 1520, 0, 0, 0, 1, 1557, 0, 0, 0, 1, 1693, 0, 0, 0, 1, 1763, 0, 0, 0, 1, 1967, 0, 0, 0, 1, 2236, 0, 0, 0, 1, 2350, 0, 0, 0, 1, 2447, 0, 0, 0, 1, 2578, 0, 0, 0, 1, 2616, 0, 0, 0, 1, 2962, 0, 0, 0, 1, 3250, 0, 0, 0, 1, 3310, 0, 0, 0, 1, 3516, 0, 0, 0, 1, 3515, 0, 0, 0, 1, 3505, 0, 0, 0, 1, 441, 0, 0, 0, 1, 456, 0, 0, 0, 3, 4, 2, 350, 0, 1, 348, 0, 0, 0, 1, 350, 0, 0, 0, 1, 354, 0, 0, 0, 5, 353, 5, 0, 0, 1, 351, 0, 0, 0, 1, 356, 0, 0, 0, 1, 352, 0, 0, 0, 1, 355, 0, 0, 0, 1, 360, 0, 0, 0, 1, 354, 0, 0, 0, 3, 6, 3, 359, 0, 1, 357, 0, 0, 0, 1, 362, 0, 0, 0, 1, 358, 0, 0, 0, 1, 361, 0, 0, 0, 1, 363, 0, 0, 0, 1, 360, 0, 0, 0, 3, 8, 4, 364, 0, 3, 10, 5, 368, 0, 3, 16, 8, 367, 0, 1, 365, 0, 0, 0, 1, 370, 0, 0, 0, 1, 366, 0, 0, 0, 1, 369, 0, 0, 0, 1, 371, 0, 0, 0, 1, 368, 0, 0, 0, 5, 372, 4294967295, 0, 0, 1, 1, 0, 0, 0, 3, 4, 2, 375, 0, 1, 373, 0, 0, 0, 1, 375, 0, 0, 0, 1, 379, 0, 0, 0, 5, 378, 5, 0, 0, 1, 376, 0, 0, 0, 1, 381, 0, 0, 0, 1, 377, 0, 0, 0, 1, 380, 0, 0, 0, 1, 385, 0, 0, 0, 1, 379, 0, 0, 0, 3, 6, 3, 384, 0, 1, 382, 0, 0, 0, 1, 387, 0, 0, 0, 1, 383, 0, 0, 0, 1, 386, 0, 0, 0, 1, 388, 0, 0, 0, 1, 385, 0, 0, 0, 3, 8, 4, 389, 0, 3, 10, 5, 395, 0, 3, 130, 65, 391, 0, 3, 148, 74, 392, 0, 1, 394, 0, 0, 0, 1, 390, 0, 0, 0, 1, 397, 0, 0, 0, 1, 393, 0, 0, 0, 1, 396, 0, 0, 0, 1, 398, 0, 0, 0, 1, 395, 0, 0, 0, 5, 399, 4294967295, 0, 0, 1, 3, 0, 0, 0, 5, 402, 1, 0, 0, 5, 403, 5, 0, 0, 1, 401, 0, 0, 0, 1, 404, 0, 0, 0, 1, 402, 0, 0, 0, 1, 405, 0, 0, 0, 1, 5, 0, 0, 0, 7, 407, 0, 0, 0, 5, 411, 63, 0, 0, 5, 410, 5, 0, 0, 1, 408, 0, 0, 0, 1, 413, 0, 0, 0, 1, 409, 0, 0, 0, 1, 412, 0, 0, 0, 1, 414, 0, 0, 0, 1, 411, 0, 0, 0, 5, 418, 26, 0, 0, 5, 417, 5, 0, 0, 1, 415, 0, 0, 0, 1, 420, 0, 0, 0, 1, 416, 0, 0, 0, 1, 419, 0, 0, 0, 1, 430, 0, 0, 0, 1, 418, 0, 0, 0, 5, 423, 11, 0, 0, 3, 342, 171, 424, 0, 1, 422, 0, 0, 0, 1, 425, 0, 0, 0, 1, 423, 0, 0, 0, 1, 426, 0, 0, 0, 1, 427, 0, 0, 0, 5, 428, 12, 0, 0, 1, 431, 0, 0, 0, 3, 342, 171, 431, 0, 1, 421, 0, 0, 0, 1, 429, 0, 0, 0, 1, 435, 0, 0, 0, 5, 434, 5, 0, 0, 1, 432, 0, 0, 0, 1, 437, 0, 0, 0, 1, 433, 0, 0, 0, 1, 436, 0, 0, 0, 1, 7, 0, 0, 0, 1, 435, 0, 0, 0, 5, 439, 72, 0, 0, 3, 346, 173, 441, 0, 259, 148, 74, 442, 0, 1, 440, 0, 0, 0, 1, 442, 0, 0, 0, 1, 444, 0, 0, 0, 1, 438, 0, 0, 0, 1, 444, 0, 0, 0, 1, 9, 0, 0, 0, 3, 12, 6, 447, 0, 1, 445, 0, 0, 0, 1, 450, 0, 0, 0, 1, 446, 0, 0, 0, 1, 449, 0, 0, 0, 1, 11, 0, 0, 0, 1, 448, 0, 0, 0, 5, 452, 73, 0, 0, 3, 346, 173, 456, 0, 5, 454, 7, 0, 0, 5, 457, 15, 0, 0, 3, 14, 7, 457, 0, 1, 453, 0, 0, 0, 1, 455, 0, 0, 0, 1, 457, 0, 0, 0, 1, 459, 0, 0, 0, 259, 148, 74, 460, 0, 1, 458, 0, 0, 0, 1, 460, 0, 0, 0, 1, 13, 0, 0, 0, 5, 462, 102, 0, 0, 259, 344, 172, 463, 0, 1, 15, 0, 0, 0, 3, 20, 10, 466, 0, 259, 150, 75, 467, 0, 1, 465, 0, 0, 0, 1, 467, 0, 0, 0, 1, 17, 0, 0, 0, 3, 300, 150, 470, 0, 1, 468, 0, 0, 0, 1, 470, 0, 0, 0, 1, 471, 0, 0, 0, 5, 475, 80, 0, 0, 5, 474, 5, 0, 0, 1, 472, 0, 0, 0, 1, 477, 0, 0, 0, 1, 473, 0, 0, 0, 1, 476, 0, 0, 0, 1, 478, 0, 0, 0, 1, 475, 0, 0, 0, 3, 344, 172, 486, 0, 5, 481, 5, 0, 0, 1, 479, 0, 0, 0, 1, 484, 0, 0, 0, 1, 480, 0, 0, 0, 1, 483, 0, 0, 0, 1, 485, 0, 0, 0, 1, 482, 0, 0, 0, 3, 42, 21, 487, 0, 1, 482, 0, 0, 0, 1, 487, 0, 0, 0, 1, 491, 0, 0, 0, 5, 490, 5, 0, 0, 1, 488, 0, 0, 0, 1, 493, 0, 0, 0, 1, 489, 0, 0, 0, 1, 492, 0, 0, 0, 1, 494, 0, 0, 0, 1, 491, 0, 0, 0, 5, 498, 28, 0, 0, 5, 497, 5, 0, 0, 1, 495, 0, 0, 0, 1, 500, 0, 0, 0, 1, 496, 0, 0, 0, 1, 499, 0, 0, 0, 1, 501, 0, 0, 0, 1, 498, 0, 0, 0, 259, 98, 49, 502, 0, 1, 19, 0, 0, 0, 259, 22, 11, 509, 0, 259, 86, 43, 509, 0, 259, 62, 31, 509, 0, 259, 70, 35, 509, 0, 259, 18, 9, 509, 0, 1, 503, 0, 0, 0, 1, 504, 0, 0, 0, 1, 505, 0, 0, 0, 1, 506, 0, 0, 0, 1, 507, 0, 0, 0, 1, 21, 0, 0, 0, 3, 300, 150, 512, 0, 1, 510, 0, 0, 0, 1, 512, 0, 0, 0, 1, 524, 0, 0, 0, 5, 525, 74, 0, 0, 5, 518, 76, 0, 0, 5, 517, 5, 0, 0, 1, 515, 0, 0, 0, 1, 520, 0, 0, 0, 1, 516, 0, 0, 0, 1, 519, 0, 0, 0, 1, 522, 0, 0, 0, 1, 518, 0, 0, 0, 1, 514, 0, 0, 0, 1, 522, 0, 0, 0, 1, 523, 0, 0, 0, 5, 525, 75, 0, 0, 1, 513, 0, 0, 0, 1, 521, 0, 0, 0, 1, 529, 0, 0, 0, 5, 528, 5, 0, 0, 1, 526, 0, 0, 0, 1, 531, 0, 0, 0, 1, 527, 0, 0, 0, 1, 530, 0, 0, 0, 1, 532, 0, 0, 0, 1, 529, 0, 0, 0, 3, 344, 172, 540, 0, 5, 535, 5, 0, 0, 1, 533, 0, 0, 0, 1, 538, 0, 0, 0, 1, 534, 0, 0, 0, 1, 537, 0, 0, 0, 1, 539, 0, 0, 0, 1, 536, 0, 0, 0, 3, 42, 21, 541, 0, 1, 536, 0, 0, 0, 1, 541, 0, 0, 0, 1, 549, 0, 0, 0, 5, 544, 5, 0, 0, 1, 542, 0, 0, 0, 1, 547, 0, 0, 0, 1, 543, 0, 0, 0, 1, 546, 0, 0, 0, 1, 548, 0, 0, 0, 1, 545, 0, 0, 0, 3, 24, 12, 550, 0, 1, 545, 0, 0, 0, 1, 550, 0, 0, 0, 1, 565, 0, 0, 0, 5, 553, 5, 0, 0, 1, 551, 0, 0, 0, 1, 556, 0, 0, 0, 1, 552, 0, 0, 0, 1, 555, 0, 0, 0, 1, 557, 0, 0, 0, 1, 554, 0, 0, 0, 5, 561, 26, 0, 0, 5, 560, 5, 0, 0, 1, 558, 0, 0, 0, 1, 563, 0, 0, 0, 1, 559, 0, 0, 0, 1, 562, 0, 0, 0, 1, 564, 0, 0, 0, 1, 561, 0, 0, 0, 3, 32, 16, 566, 0, 1, 554, 0, 0, 0, 1, 566, 0, 0, 0, 1, 574, 0, 0, 0, 5, 569, 5, 0, 0, 1, 567, 0, 0, 0, 1, 572, 0, 0, 0, 1, 568, 0, 0, 0, 1, 571, 0, 0, 0, 1, 573, 0, 0, 0, 1, 570, 0, 0, 0, 3, 46, 23, 575, 0, 1, 570, 0, 0, 0, 1, 575, 0, 0, 0, 1, 590, 0, 0, 0, 5, 578, 5, 0, 0, 1, 576, 0, 0, 0, 1, 581, 0, 0, 0, 1, 577, 0, 0, 0, 1, 580, 0, 0, 0, 1, 582, 0, 0, 0, 1, 579, 0, 0, 0, 259, 26, 13, 591, 0, 5, 585, 5, 0, 0, 1, 583, 0, 0, 0, 1, 588, 0, 0, 0, 1, 584, 0, 0, 0, 1, 587, 0, 0, 0, 1, 589, 0, 0, 0, 1, 586, 0, 0, 0, 259, 92, 46, 591, 0, 1, 579, 0, 0, 0, 1, 586, 0, 0, 0, 1, 591, 0, 0, 0, 1, 23, 0, 0, 0, 3, 300, 150, 594, 0, 1, 592, 0, 0, 0, 1, 594, 0, 0, 0, 1, 595, 0, 0, 0, 5, 599, 81, 0, 0, 5, 598, 5, 0, 0, 1, 596, 0, 0, 0, 1, 601, 0, 0, 0, 1, 597, 0, 0, 0, 1, 600, 0, 0, 0, 1, 603, 0, 0, 0, 1, 599, 0, 0, 0, 1, 593, 0, 0, 0, 1, 603, 0, 0, 0, 1, 604, 0, 0, 0, 259, 28, 14, 605, 0, 1, 25, 0, 0, 0, 5, 610, 13, 0, 0, 5, 609, 5, 0, 0, 1, 607, 0, 0, 0, 1, 612, 0, 0, 0, 1, 608, 0, 0, 0, 1, 611, 0, 0, 0, 1, 613, 0, 0, 0, 1, 610, 0, 0, 0, 3, 50, 25, 617, 0, 5, 616, 5, 0, 0, 1, 614, 0, 0, 0, 1, 619, 0, 0, 0, 1, 615, 0, 0, 0, 1, 618, 0, 0, 0, 1, 620, 0, 0, 0, 1, 617, 0, 0, 0, 5, 621, 14, 0, 0, 1, 27, 0, 0, 0, 5, 626, 9, 0, 0, 5, 625, 5, 0, 0, 1, 623, 0, 0, 0, 1, 628, 0, 0, 0, 1, 624, 0, 0, 0, 1, 627, 0, 0, 0, 1, 658, 0, 0, 0, 1, 626, 0, 0, 0, 3, 30, 15, 646, 0, 5, 632, 5, 0, 0, 1, 630, 0, 0, 0, 1, 635, 0, 0, 0, 1, 631, 0, 0, 0, 1, 634, 0, 0, 0, 1, 636, 0, 0, 0, 1, 633, 0, 0, 0, 5, 640, 8, 0, 0, 5, 639, 5, 0, 0, 1, 637, 0, 0, 0, 1, 642, 0, 0, 0, 1, 638, 0, 0, 0, 1, 641, 0, 0, 0, 1, 643, 0, 0, 0, 1, 640, 0, 0, 0, 3, 30, 15, 645, 0, 1, 633, 0, 0, 0, 1, 648, 0, 0, 0, 1, 644, 0, 0, 0, 1, 647, 0, 0, 0, 1, 656, 0, 0, 0, 1, 646, 0, 0, 0, 5, 651, 5, 0, 0, 1, 649, 0, 0, 0, 1, 654, 0, 0, 0, 1, 650, 0, 0, 0, 1, 653, 0, 0, 0, 1, 655, 0, 0, 0, 1, 652, 0, 0, 0, 5, 657, 8, 0, 0, 1, 652, 0, 0, 0, 1, 657, 0, 0, 0, 1, 659, 0, 0, 0, 1, 629, 0, 0, 0, 1, 659, 0, 0, 0, 1, 663, 0, 0, 0, 5, 662, 5, 0, 0, 1, 660, 0, 0, 0, 1, 665, 0, 0, 0, 1, 661, 0, 0, 0, 1, 664, 0, 0, 0, 1, 666, 0, 0, 0, 1, 663, 0, 0, 0, 5, 667, 10, 0, 0, 1, 29, 0, 0, 0, 3, 300, 150, 670, 0, 1, 668, 0, 0, 0, 1, 670, 0, 0, 0, 1, 672, 0, 0, 0, 7, 673, 1, 0, 0, 1, 671, 0, 0, 0, 1, 673, 0, 0, 0, 1, 677, 0, 0, 0, 5, 676, 5, 0, 0, 1, 674, 0, 0, 0, 1, 679, 0, 0, 0, 1, 675, 0, 0, 0, 1, 678, 0, 0, 0, 1, 680, 0, 0, 0, 1, 677, 0, 0, 0, 3, 344, 172, 681, 0, 5, 685, 26, 0, 0, 5, 684, 5, 0, 0, 1, 682, 0, 0, 0, 1, 687, 0, 0, 0, 1, 683, 0, 0, 0, 1, 686, 0, 0, 0, 1, 688, 0, 0, 0, 1, 685, 0, 0, 0, 3, 98, 49, 703, 0, 5, 691, 5, 0, 0, 1, 689, 0, 0, 0, 1, 694, 0, 0, 0, 1, 690, 0, 0, 0, 1, 693, 0, 0, 0, 1, 695, 0, 0, 0, 1, 692, 0, 0, 0, 5, 699, 28, 0, 0, 5, 698, 5, 0, 0, 1, 696, 0, 0, 0, 1, 701, 0, 0, 0, 1, 697, 0, 0, 0, 1, 700, 0, 0, 0, 1, 702, 0, 0, 0, 1, 699, 0, 0, 0, 259, 152, 76, 704, 0, 1, 692, 0, 0, 0, 1, 704, 0, 0, 0, 1, 31, 0, 0, 0, 3, 38, 19, 722, 0, 5, 708, 5, 0, 0, 1, 706, 0, 0, 0, 1, 711, 0, 0, 0, 1, 707, 0, 0, 0, 1, 710, 0, 0, 0, 1, 712, 0, 0, 0, 1, 709, 0, 0, 0, 5, 716, 8, 0, 0, 5, 715, 5, 0, 0, 1, 713, 0, 0, 0, 1, 718, 0, 0, 0, 1, 714, 0, 0, 0, 1, 717, 0, 0, 0, 1, 719, 0, 0, 0, 1, 716, 0, 0, 0, 3, 38, 19, 721, 0, 1, 709, 0, 0, 0, 1, 724, 0, 0, 0, 1, 720, 0, 0, 0, 1, 723, 0, 0, 0, 1, 33, 0, 0, 0, 1, 722, 0, 0, 0, 259, 36, 18, 738, 0, 259, 40, 20, 738, 0, 259, 106, 53, 738, 0, 259, 116, 58, 738, 0, 5, 733, 124, 0, 0, 5, 732, 5, 0, 0, 1, 730, 0, 0, 0, 1, 735, 0, 0, 0, 1, 731, 0, 0, 0, 1, 734, 0, 0, 0, 1, 736, 0, 0, 0, 1, 733, 0, 0, 0, 259, 116, 58, 738, 0, 1, 725, 0, 0, 0, 1, 726, 0, 0, 0, 1, 727, 0, 0, 0, 1, 728, 0, 0, 0, 1, 729, 0, 0, 0, 1, 35, 0, 0, 0, 3, 106, 53, 743, 0, 5, 742, 5, 0, 0, 1, 740, 0, 0, 0, 1, 745, 0, 0, 0, 1, 741, 0, 0, 0, 1, 744, 0, 0, 0, 1, 746, 0, 0, 0, 1, 743, 0, 0, 0, 259, 208, 104, 747, 0, 1, 37, 0, 0, 0, 3, 334, 167, 750, 0, 1, 748, 0, 0, 0, 1, 753, 0, 0, 0, 1, 749, 0, 0, 0, 1, 752, 0, 0, 0, 1, 757, 0, 0, 0, 1, 751, 0, 0, 0, 5, 756, 5, 0, 0, 1, 754, 0, 0, 0, 1, 759, 0, 0, 0, 1, 755, 0, 0, 0, 1, 758, 0, 0, 0, 1, 760, 0, 0, 0, 1, 757, 0, 0, 0, 259, 34, 17, 761, 0, 1, 39, 0, 0, 0, 3, 106, 53, 765, 0, 3, 116, 58, 765, 0, 1, 762, 0, 0, 0, 1, 763, 0, 0, 0, 1, 769, 0, 0, 0, 5, 768, 5, 0, 0, 1, 766, 0, 0, 0, 1, 771, 0, 0, 0, 1, 767, 0, 0, 0, 1, 770, 0, 0, 0, 1, 772, 0, 0, 0, 1, 769, 0, 0, 0, 5, 776, 82, 0, 0, 5, 775, 5, 0, 0, 1, 773, 0, 0, 0, 1, 778, 0, 0, 0, 1, 774, 0, 0, 0, 1, 777, 0, 0, 0, 1, 779, 0, 0, 0, 1, 776, 0, 0, 0, 259, 152, 76, 780, 0, 1, 41, 0, 0, 0, 5, 785, 47, 0, 0, 5, 784, 5, 0, 0, 1, 782, 0, 0, 0, 1, 787, 0, 0, 0, 1, 783, 0, 0, 0, 1, 786, 0, 0, 0, 1, 788, 0, 0, 0, 1, 785, 0, 0, 0, 3, 44, 22, 805, 0, 5, 791, 5, 0, 0, 1, 789, 0, 0, 0, 1, 794, 0, 0, 0, 1, 790, 0, 0, 0, 1, 793, 0, 0, 0, 1, 795, 0, 0, 0, 1, 792, 0, 0, 0, 5, 799, 8, 0, 0, 5, 798, 5, 0, 0, 1, 796, 0, 0, 0, 1, 801, 0, 0, 0, 1, 797, 0, 0, 0, 1, 800, 0, 0, 0, 1, 802, 0, 0, 0, 1, 799, 0, 0, 0, 3, 44, 22, 804, 0, 1, 792, 0, 0, 0, 1, 807, 0, 0, 0, 1, 803, 0, 0, 0, 1, 806, 0, 0, 0, 1, 815, 0, 0, 0, 1, 805, 0, 0, 0, 5, 810, 5, 0, 0, 1, 808, 0, 0, 0, 1, 813, 0, 0, 0, 1, 809, 0, 0, 0, 1, 812, 0, 0, 0, 1, 814, 0, 0, 0, 1, 811, 0, 0, 0, 5, 816, 8, 0, 0, 1, 811, 0, 0, 0, 1, 816, 0, 0, 0, 1, 820, 0, 0, 0, 5, 819, 5, 0, 0, 1, 817, 0, 0, 0, 1, 822, 0, 0, 0, 1, 818, 0, 0, 0, 1, 821, 0, 0, 0, 1, 823, 0, 0, 0, 1, 820, 0, 0, 0, 5, 824, 48, 0, 0, 1, 43, 0, 0, 0, 3, 318, 159, 827, 0, 1, 825, 0, 0, 0, 1, 827, 0, 0, 0, 1, 831, 0, 0, 0, 5, 830, 5, 0, 0, 1, 828, 0, 0, 0, 1, 833, 0, 0, 0, 1, 829, 0, 0, 0, 1, 832, 0, 0, 0, 1, 834, 0, 0, 0, 1, 831, 0, 0, 0, 3, 344, 172, 849, 0, 5, 837, 5, 0, 0, 1, 835, 0, 0, 0, 1, 840, 0, 0, 0, 1, 836, 0, 0, 0, 1, 839, 0, 0, 0, 1, 841, 0, 0, 0, 1, 838, 0, 0, 0, 5, 845, 26, 0, 0, 5, 844, 5, 0, 0, 1, 842, 0, 0, 0, 1, 847, 0, 0, 0, 1, 843, 0, 0, 0, 1, 846, 0, 0, 0, 1, 848, 0, 0, 0, 1, 845, 0, 0, 0, 259, 98, 49, 850, 0, 1, 838, 0, 0, 0, 1, 850, 0, 0, 0, 1, 45, 0, 0, 0, 5, 855, 88, 0, 0, 5, 854, 5, 0, 0, 1, 852, 0, 0, 0, 1, 857, 0, 0, 0, 1, 853, 0, 0, 0, 1, 856, 0, 0, 0, 1, 858, 0, 0, 0, 1, 855, 0, 0, 0, 3, 48, 24, 875, 0, 5, 861, 5, 0, 0, 1, 859, 0, 0, 0, 1, 864, 0, 0, 0, 1, 860, 0, 0, 0, 1, 863, 0, 0, 0, 1, 865, 0, 0, 0, 1, 862, 0, 0, 0, 5, 869, 8, 0, 0, 5, 868, 5, 0, 0, 1, 866, 0, 0, 0, 1, 871, 0, 0, 0, 1, 867, 0, 0, 0, 1, 870, 0, 0, 0, 1, 872, 0, 0, 0, 1, 869, 0, 0, 0, 3, 48, 24, 874, 0, 1, 862, 0, 0, 0, 1, 877, 0, 0, 0, 1, 873, 0, 0, 0, 1, 876, 0, 0, 0, 1, 47, 0, 0, 0, 1, 875, 0, 0, 0, 3, 334, 167, 880, 0, 1, 878, 0, 0, 0, 1, 883, 0, 0, 0, 1, 879, 0, 0, 0, 1, 882, 0, 0, 0, 1, 884, 0, 0, 0, 1, 881, 0, 0, 0, 3, 344, 172, 888, 0, 5, 887, 5, 0, 0, 1, 885, 0, 0, 0, 1, 890, 0, 0, 0, 1, 886, 0, 0, 0, 1, 889, 0, 0, 0, 1, 891, 0, 0, 0, 1, 888, 0, 0, 0, 5, 895, 26, 0, 0, 5, 894, 5, 0, 0, 1, 892, 0, 0, 0, 1, 897, 0, 0, 0, 1, 893, 0, 0, 0, 1, 896, 0, 0, 0, 1, 898, 0, 0, 0, 1, 895, 0, 0, 0, 259, 98, 49, 899, 0, 1, 49, 0, 0, 0, 3, 52, 26, 902, 0, 3, 150, 75, 903, 0, 1, 901, 0, 0, 0, 1, 903, 0, 0, 0, 1, 905, 0, 0, 0, 1, 900, 0, 0, 0, 1, 908, 0, 0, 0, 1, 904, 0, 0, 0, 1, 907, 0, 0, 0, 1, 51, 0, 0, 0, 1, 906, 0, 0, 0, 259, 20, 10, 914, 0, 259, 56, 28, 914, 0, 259, 54, 27, 914, 0, 259, 88, 44, 914, 0, 1, 909, 0, 0, 0, 1, 910, 0, 0, 0, 1, 911, 0, 0, 0, 1, 912, 0, 0, 0, 1, 53, 0, 0, 0, 5, 919, 84, 0, 0, 5, 918, 5, 0, 0, 1, 916, 0, 0, 0, 1, 921, 0, 0, 0, 1, 917, 0, 0, 0, 1, 920, 0, 0, 0, 1, 922, 0, 0, 0, 1, 919, 0, 0, 0, 259, 136, 68, 923, 0, 1, 55, 0, 0, 0, 3, 300, 150, 926, 0, 1, 924, 0, 0, 0, 1, 926, 0, 0, 0, 1, 927, 0, 0, 0, 5, 931, 83, 0, 0, 5, 930, 5, 0, 0, 1, 928, 0, 0, 0, 1, 933, 0, 0, 0, 1, 929, 0, 0, 0, 1, 932, 0, 0, 0, 1, 935, 0, 0, 0, 1, 931, 0, 0, 0, 5, 936, 116, 0, 0, 1, 934, 0, 0, 0, 1, 936, 0, 0, 0, 1, 940, 0, 0, 0, 5, 939, 5, 0, 0, 1, 937, 0, 0, 0, 1, 942, 0, 0, 0, 1, 938, 0, 0, 0, 1, 941, 0, 0, 0, 1, 943, 0, 0, 0, 1, 940, 0, 0, 0, 5, 951, 77, 0, 0, 5, 946, 5, 0, 0, 1, 944, 0, 0, 0, 1, 949, 0, 0, 0, 1, 945, 0, 0, 0, 1, 948, 0, 0, 0, 1, 950, 0, 0, 0, 1, 947, 0, 0, 0, 3, 344, 172, 952, 0, 1, 947, 0, 0, 0, 1, 952, 0, 0, 0, 1, 967, 0, 0, 0, 5, 955, 5, 0, 0, 1, 953, 0, 0, 0, 1, 958, 0, 0, 0, 1, 954, 0, 0, 0, 1, 957, 0, 0, 0, 1, 959, 0, 0, 0, 1, 956, 0, 0, 0, 5, 963, 26, 0, 0, 5, 962, 5, 0, 0, 1, 960, 0, 0, 0, 1, 965, 0, 0, 0, 1, 961, 0, 0, 0, 1, 964, 0, 0, 0, 1, 966, 0, 0, 0, 1, 963, 0, 0, 0, 3, 32, 16, 968, 0, 1, 956, 0, 0, 0, 1, 968, 0, 0, 0, 1, 976, 0, 0, 0, 5, 971, 5, 0, 0, 1, 969, 0, 0, 0, 1, 974, 0, 0, 0, 1, 970, 0, 0, 0, 1, 973, 0, 0, 0, 1, 975, 0, 0, 0, 1, 972, 0, 0, 0, 259, 26, 13, 977, 0, 1, 972, 0, 0, 0, 1, 977, 0, 0, 0, 1, 57, 0, 0, 0, 5, 982, 9, 0, 0, 5, 981, 5, 0, 0, 1, 979, 0, 0, 0, 1, 984, 0, 0, 0, 1, 980, 0, 0, 0, 1, 983, 0, 0, 0, 1, 1014, 0, 0, 0, 1, 982, 0, 0, 0, 3, 60, 30, 1002, 0, 5, 988, 5, 0, 0, 1, 986, 0, 0, 0, 1, 991, 0, 0, 0, 1, 987, 0, 0, 0, 1, 990, 0, 0, 0, 1, 992, 0, 0, 0, 1, 989, 0, 0, 0, 5, 996, 8, 0, 0, 5, 995, 5, 0, 0, 1, 993, 0, 0, 0, 1, 998, 0, 0, 0, 1, 994, 0, 0, 0, 1, 997, 0, 0, 0, 1, 999, 0, 0, 0, 1, 996, 0, 0, 0, 3, 60, 30, 1001, 0, 1, 989, 0, 0, 0, 1, 1004, 0, 0, 0, 1, 1000, 0, 0, 0, 1, 1003, 0, 0, 0, 1, 1012, 0, 0, 0, 1, 1002, 0, 0, 0, 5, 1007, 5, 0, 0, 1, 1005, 0, 0, 0, 1, 1010, 0, 0, 0, 1, 1006, 0, 0, 0, 1, 1009, 0, 0, 0, 1, 1011, 0, 0, 0, 1, 1008, 0, 0, 0, 5, 1013, 8, 0, 0, 1, 1008, 0, 0, 0, 1, 1013, 0, 0, 0, 1, 1015, 0, 0, 0, 1, 985, 0, 0, 0, 1, 1015, 0, 0, 0, 1, 1019, 0, 0, 0, 5, 1018, 5, 0, 0, 1, 1016, 0, 0, 0, 1, 1021, 0, 0, 0, 1, 1017, 0, 0, 0, 1, 1020, 0, 0, 0, 1, 1022, 0, 0, 0, 1, 1019, 0, 0, 0, 5, 1023, 10, 0, 0, 1, 59, 0, 0, 0, 3, 302, 151, 1026, 0, 1, 1024, 0, 0, 0, 1, 1026, 0, 0, 0, 1, 1027, 0, 0, 0, 3, 84, 42, 1042, 0, 5, 1030, 5, 0, 0, 1, 1028, 0, 0, 0, 1, 1033, 0, 0, 0, 1, 1029, 0, 0, 0, 1, 1032, 0, 0, 0, 1, 1034, 0, 0, 0, 1, 1031, 0, 0, 0, 5, 1038, 28, 0, 0, 5, 1037, 5, 0, 0, 1, 1035, 0, 0, 0, 1, 1040, 0, 0, 0, 1, 1036, 0, 0, 0, 1, 1039, 0, 0, 0, 1, 1041, 0, 0, 0, 1, 1038, 0, 0, 0, 259, 152, 76, 1043, 0, 1, 1031, 0, 0, 0, 1, 1043, 0, 0, 0, 1, 61, 0, 0, 0, 3, 300, 150, 1046, 0, 1, 1044, 0, 0, 0, 1, 1046, 0, 0, 0, 1, 1047, 0, 0, 0, 5, 1055, 76, 0, 0, 5, 1050, 5, 0, 0, 1, 1048, 0, 0, 0, 1, 1053, 0, 0, 0, 1, 1049, 0, 0, 0, 1, 1052, 0, 0, 0, 1, 1054, 0, 0, 0, 1, 1051, 0, 0, 0, 3, 42, 21, 1056, 0, 1, 1051, 0, 0, 0, 1, 1056, 0, 0, 0, 1, 1072, 0, 0, 0, 5, 1059, 5, 0, 0, 1, 1057, 0, 0, 0, 1, 1062, 0, 0, 0, 1, 1058, 0, 0, 0, 1, 1061, 0, 0, 0, 1, 1063, 0, 0, 0, 1, 1060, 0, 0, 0, 3, 122, 61, 1067, 0, 5, 1066, 5, 0, 0, 1, 1064, 0, 0, 0, 1, 1069, 0, 0, 0, 1, 1065, 0, 0, 0, 1, 1068, 0, 0, 0, 1, 1070, 0, 0, 0, 1, 1067, 0, 0, 0, 5, 1071, 7, 0, 0, 1, 1073, 0, 0, 0, 1, 1060, 0, 0, 0, 1, 1073, 0, 0, 0, 1, 1077, 0, 0, 0, 5, 1076, 5, 0, 0, 1, 1074, 0, 0, 0, 1, 1079, 0, 0, 0, 1, 1075, 0, 0, 0, 1, 1078, 0, 0, 0, 1, 1080, 0, 0, 0, 1, 1077, 0, 0, 0, 3, 344, 172, 1084, 0, 5, 1083, 5, 0, 0, 1, 1081, 0, 0, 0, 1, 1086, 0, 0, 0, 1, 1082, 0, 0, 0, 1, 1085, 0, 0, 0, 1, 1087, 0, 0, 0, 1, 1084, 0, 0, 0, 3, 58, 29, 1102, 0, 5, 1090, 5, 0, 0, 1, 1088, 0, 0, 0, 1, 1093, 0, 0, 0, 1, 1089, 0, 0, 0, 1, 1092, 0, 0, 0, 1, 1094, 0, 0, 0, 1, 1091, 0, 0, 0, 5, 1098, 26, 0, 0, 5, 1097, 5, 0, 0, 1, 1095, 0, 0, 0, 1, 1100, 0, 0, 0, 1, 1096, 0, 0, 0, 1, 1099, 0, 0, 0, 1, 1101, 0, 0, 0, 1, 1098, 0, 0, 0, 3, 98, 49, 1103, 0, 1, 1091, 0, 0, 0, 1, 1103, 0, 0, 0, 1, 1111, 0, 0, 0, 5, 1106, 5, 0, 0, 1, 1104, 0, 0, 0, 1, 1109, 0, 0, 0, 1, 1105, 0, 0, 0, 1, 1108, 0, 0, 0, 1, 1110, 0, 0, 0, 1, 1107, 0, 0, 0, 3, 46, 23, 1112, 0, 1, 1107, 0, 0, 0, 1, 1112, 0, 0, 0, 1, 1120, 0, 0, 0, 5, 1115, 5, 0, 0, 1, 1113, 0, 0, 0, 1, 1118, 0, 0, 0, 1, 1114, 0, 0, 0, 1, 1117, 0, 0, 0, 1, 1119, 0, 0, 0, 1, 1116, 0, 0, 0, 259, 64, 32, 1121, 0, 1, 1116, 0, 0, 0, 1, 1121, 0, 0, 0, 1, 63, 0, 0, 0, 259, 136, 68, 1132, 0, 5, 1127, 28, 0, 0, 5, 1126, 5, 0, 0, 1, 1124, 0, 0, 0, 1, 1129, 0, 0, 0, 1, 1125, 0, 0, 0, 1, 1128, 0, 0, 0, 1, 1130, 0, 0, 0, 1, 1127, 0, 0, 0, 259, 152, 76, 1132, 0, 1, 1122, 0, 0, 0, 1, 1123, 0, 0, 0, 1, 65, 0, 0, 0, 3, 334, 167, 1135, 0, 1, 1133, 0, 0, 0, 1, 1138, 0, 0, 0, 1, 1134, 0, 0, 0, 1, 1137, 0, 0, 0, 1, 1142, 0, 0, 0, 1, 1136, 0, 0, 0, 5, 1141, 5, 0, 0, 1, 1139, 0, 0, 0, 1, 1144, 0, 0, 0, 1, 1140, 0, 0, 0, 1, 1143, 0, 0, 0, 1, 1145, 0, 0, 0, 1, 1142, 0, 0, 0, 3, 344, 172, 1160, 0, 5, 1148, 5, 0, 0, 1, 1146, 0, 0, 0, 1, 1151, 0, 0, 0, 1, 1147, 0, 0, 0, 1, 1150, 0, 0, 0, 1, 1152, 0, 0, 0, 1, 1149, 0, 0, 0, 5, 1156, 26, 0, 0, 5, 1155, 5, 0, 0, 1, 1153, 0, 0, 0, 1, 1158, 0, 0, 0, 1, 1154, 0, 0, 0, 1, 1157, 0, 0, 0, 1, 1159, 0, 0, 0, 1, 1156, 0, 0, 0, 259, 98, 49, 1161, 0, 1, 1149, 0, 0, 0, 1, 1161, 0, 0, 0, 1, 67, 0, 0, 0, 5, 1166, 9, 0, 0, 5, 1165, 5, 0, 0, 1, 1163, 0, 0, 0, 1, 1168, 0, 0, 0, 1, 1164, 0, 0, 0, 1, 1167, 0, 0, 0, 1, 1169, 0, 0, 0, 1, 1166, 0, 0, 0, 3, 66, 33, 1186, 0, 5, 1172, 5, 0, 0, 1, 1170, 0, 0, 0, 1, 1175, 0, 0, 0, 1, 1171, 0, 0, 0, 1, 1174, 0, 0, 0, 1, 1176, 0, 0, 0, 1, 1173, 0, 0, 0, 5, 1180, 8, 0, 0, 5, 1179, 5, 0, 0, 1, 1177, 0, 0, 0, 1, 1182, 0, 0, 0, 1, 1178, 0, 0, 0, 1, 1181, 0, 0, 0, 1, 1183, 0, 0, 0, 1, 1180, 0, 0, 0, 3, 66, 33, 1185, 0, 1, 1173, 0, 0, 0, 1, 1188, 0, 0, 0, 1, 1184, 0, 0, 0, 1, 1187, 0, 0, 0, 1, 1196, 0, 0, 0, 1, 1186, 0, 0, 0, 5, 1191, 5, 0, 0, 1, 1189, 0, 0, 0, 1, 1194, 0, 0, 0, 1, 1190, 0, 0, 0, 1, 1193, 0, 0, 0, 1, 1195, 0, 0, 0, 1, 1192, 0, 0, 0, 5, 1197, 8, 0, 0, 1, 1192, 0, 0, 0, 1, 1197, 0, 0, 0, 1, 1201, 0, 0, 0, 5, 1200, 5, 0, 0, 1, 1198, 0, 0, 0, 1, 1203, 0, 0, 0, 1, 1199, 0, 0, 0, 1, 1202, 0, 0, 0, 1, 1204, 0, 0, 0, 1, 1201, 0, 0, 0, 5, 1205, 10, 0, 0, 1, 69, 0, 0, 0, 3, 300, 150, 1208, 0, 1, 1206, 0, 0, 0, 1, 1208, 0, 0, 0, 1, 1209, 0, 0, 0, 7, 1217, 1, 0, 0, 5, 1212, 5, 0, 0, 1, 1210, 0, 0, 0, 1, 1215, 0, 0, 0, 1, 1211, 0, 0, 0, 1, 1214, 0, 0, 0, 1, 1216, 0, 0, 0, 1, 1213, 0, 0, 0, 3, 42, 21, 1218, 0, 1, 1213, 0, 0, 0, 1, 1218, 0, 0, 0, 1, 1234, 0, 0, 0, 5, 1221, 5, 0, 0, 1, 1219, 0, 0, 0, 1, 1224, 0, 0, 0, 1, 1220, 0, 0, 0, 1, 1223, 0, 0, 0, 1, 1225, 0, 0, 0, 1, 1222, 0, 0, 0, 3, 122, 61, 1229, 0, 5, 1228, 5, 0, 0, 1, 1226, 0, 0, 0, 1, 1231, 0, 0, 0, 1, 1227, 0, 0, 0, 1, 1230, 0, 0, 0, 1, 1232, 0, 0, 0, 1, 1229, 0, 0, 0, 5, 1233, 7, 0, 0, 1, 1235, 0, 0, 0, 1, 1222, 0, 0, 0, 1, 1235, 0, 0, 0, 1, 1239, 0, 0, 0, 5, 1238, 5, 0, 0, 1, 1236, 0, 0, 0, 1, 1241, 0, 0, 0, 1, 1237, 0, 0, 0, 1, 1240, 0, 0, 0, 1, 1244, 0, 0, 0, 1, 1239, 0, 0, 0, 3, 68, 34, 1245, 0, 3, 66, 33, 1245, 0, 1, 1242, 0, 0, 0, 1, 1243, 0, 0, 0, 1, 1253, 0, 0, 0, 5, 1248, 5, 0, 0, 1, 1246, 0, 0, 0, 1, 1251, 0, 0, 0, 1, 1247, 0, 0, 0, 1, 1250, 0, 0, 0, 1, 1252, 0, 0, 0, 1, 1249, 0, 0, 0, 3, 46, 23, 1254, 0, 1, 1249, 0, 0, 0, 1, 1254, 0, 0, 0, 1, 1272, 0, 0, 0, 5, 1257, 5, 0, 0, 1, 1255, 0, 0, 0, 1, 1260, 0, 0, 0, 1, 1256, 0, 0, 0, 1, 1259, 0, 0, 0, 1, 1270, 0, 0, 0, 1, 1258, 0, 0, 0, 5, 1265, 28, 0, 0, 5, 1264, 5, 0, 0, 1, 1262, 0, 0, 0, 1, 1267, 0, 0, 0, 1, 1263, 0, 0, 0, 1, 1266, 0, 0, 0, 1, 1268, 0, 0, 0, 1, 1265, 0, 0, 0, 3, 152, 76, 1271, 0, 3, 72, 36, 1271, 0, 1, 1261, 0, 0, 0, 1, 1269, 0, 0, 0, 1, 1273, 0, 0, 0, 1, 1258, 0, 0, 0, 1, 1273, 0, 0, 0, 1, 1281, 0, 0, 0, 5, 1276, 5, 0, 0, 1, 1274, 0, 0, 0, 1, 1279, 0, 0, 0, 1, 1275, 0, 0, 0, 1, 1278, 0, 0, 0, 1, 1280, 0, 0, 0, 1, 1277, 0, 0, 0, 5, 1282, 27, 0, 0, 1, 1277, 0, 0, 0, 1, 1282, 0, 0, 0, 1, 1286, 0, 0, 0, 5, 1285, 5, 0, 0, 1, 1283, 0, 0, 0, 1, 1288, 0, 0, 0, 1, 1284, 0, 0, 0, 1, 1287, 0, 0, 0, 1, 1319, 0, 0, 0, 1, 1286, 0, 0, 0, 3, 74, 37, 1291, 0, 1, 1289, 0, 0, 0, 1, 1291, 0, 0, 0, 1, 1302, 0, 0, 0, 5, 1294, 5, 0, 0, 1, 1292, 0, 0, 0, 1, 1297, 0, 0, 0, 1, 1293, 0, 0, 0, 1, 1296, 0, 0, 0, 1, 1299, 0, 0, 0, 1, 1295, 0, 0, 0, 3, 148, 74, 1300, 0, 1, 1298, 0, 0, 0, 1, 1300, 0, 0, 0, 1, 1301, 0, 0, 0, 259, 76, 38, 1303, 0, 1, 1295, 0, 0, 0, 1, 1303, 0, 0, 0, 1, 1320, 0, 0, 0, 3, 76, 38, 1306, 0, 1, 1304, 0, 0, 0, 1, 1306, 0, 0, 0, 1, 1317, 0, 0, 0, 5, 1309, 5, 0, 0, 1, 1307, 0, 0, 0, 1, 1312, 0, 0, 0, 1, 1308, 0, 0, 0, 1, 1311, 0, 0, 0, 1, 1314, 0, 0, 0, 1, 1310, 0, 0, 0, 3, 148, 74, 1315, 0, 1, 1313, 0, 0, 0, 1, 1315, 0, 0, 0, 1, 1316, 0, 0, 0, 259, 74, 37, 1318, 0, 1, 1310, 0, 0, 0, 1, 1318, 0, 0, 0, 1, 1320, 0, 0, 0, 1, 1290, 0, 0, 0, 1, 1305, 0, 0, 0, 1, 71, 0, 0, 0, 5, 1325, 82, 0, 0, 5, 1324, 5, 0, 0, 1, 1322, 0, 0, 0, 1, 1327, 0, 0, 0, 1, 1323, 0, 0, 0, 1, 1326, 0, 0, 0, 1, 1328, 0, 0, 0, 1, 1325, 0, 0, 0, 259, 152, 76, 1329, 0, 1, 73, 0, 0, 0, 3, 300, 150, 1332, 0, 1, 1330, 0, 0, 0, 1, 1332, 0, 0, 0, 1, 1333, 0, 0, 0, 5, 1371, 66, 0, 0, 5, 1336, 5, 0, 0, 1, 1334, 0, 0, 0, 1, 1339, 0, 0, 0, 1, 1335, 0, 0, 0, 1, 1338, 0, 0, 0, 1, 1340, 0, 0, 0, 1, 1337, 0, 0, 0, 5, 1344, 9, 0, 0, 5, 1343, 5, 0, 0, 1, 1341, 0, 0, 0, 1, 1346, 0, 0, 0, 1, 1342, 0, 0, 0, 1, 1345, 0, 0, 0, 1, 1347, 0, 0, 0, 1, 1344, 0, 0, 0, 5, 1362, 10, 0, 0, 5, 1350, 5, 0, 0, 1, 1348, 0, 0, 0, 1, 1353, 0, 0, 0, 1, 1349, 0, 0, 0, 1, 1352, 0, 0, 0, 1, 1354, 0, 0, 0, 1, 1351, 0, 0, 0, 5, 1358, 26, 0, 0, 5, 1357, 5, 0, 0, 1, 1355, 0, 0, 0, 1, 1360, 0, 0, 0, 1, 1356, 0, 0, 0, 1, 1359, 0, 0, 0, 1, 1361, 0, 0, 0, 1, 1358, 0, 0, 0, 3, 98, 49, 1363, 0, 1, 1351, 0, 0, 0, 1, 1363, 0, 0, 0, 1, 1367, 0, 0, 0, 5, 1366, 5, 0, 0, 1, 1364, 0, 0, 0, 1, 1369, 0, 0, 0, 1, 1365, 0, 0, 0, 1, 1368, 0, 0, 0, 1, 1370, 0, 0, 0, 1, 1367, 0, 0, 0, 259, 64, 32, 1372, 0, 1, 1337, 0, 0, 0, 1, 1372, 0, 0, 0, 1, 75, 0, 0, 0, 3, 300, 150, 1375, 0, 1, 1373, 0, 0, 0, 1, 1375, 0, 0, 0, 1, 1376, 0, 0, 0, 5, 1431, 67, 0, 0, 5, 1379, 5, 0, 0, 1, 1377, 0, 0, 0, 1, 1382, 0, 0, 0, 1, 1378, 0, 0, 0, 1, 1381, 0, 0, 0, 1, 1383, 0, 0, 0, 1, 1380, 0, 0, 0, 5, 1387, 9, 0, 0, 5, 1386, 5, 0, 0, 1, 1384, 0, 0, 0, 1, 1389, 0, 0, 0, 1, 1385, 0, 0, 0, 1, 1388, 0, 0, 0, 1, 1390, 0, 0, 0, 1, 1387, 0, 0, 0, 3, 80, 40, 1398, 0, 5, 1393, 5, 0, 0, 1, 1391, 0, 0, 0, 1, 1396, 0, 0, 0, 1, 1392, 0, 0, 0, 1, 1395, 0, 0, 0, 1, 1397, 0, 0, 0, 1, 1394, 0, 0, 0, 5, 1399, 8, 0, 0, 1, 1394, 0, 0, 0, 1, 1399, 0, 0, 0, 1, 1403, 0, 0, 0, 5, 1402, 5, 0, 0, 1, 1400, 0, 0, 0, 1, 1405, 0, 0, 0, 1, 1401, 0, 0, 0, 1, 1404, 0, 0, 0, 1, 1406, 0, 0, 0, 1, 1403, 0, 0, 0, 5, 1421, 10, 0, 0, 5, 1409, 5, 0, 0, 1, 1407, 0, 0, 0, 1, 1412, 0, 0, 0, 1, 1408, 0, 0, 0, 1, 1411, 0, 0, 0, 1, 1413, 0, 0, 0, 1, 1410, 0, 0, 0, 5, 1417, 26, 0, 0, 5, 1416, 5, 0, 0, 1, 1414, 0, 0, 0, 1, 1419, 0, 0, 0, 1, 1415, 0, 0, 0, 1, 1418, 0, 0, 0, 1, 1420, 0, 0, 0, 1, 1417, 0, 0, 0, 3, 98, 49, 1422, 0, 1, 1410, 0, 0, 0, 1, 1422, 0, 0, 0, 1, 1426, 0, 0, 0, 5, 1425, 5, 0, 0, 1, 1423, 0, 0, 0, 1, 1428, 0, 0, 0, 1, 1424, 0, 0, 0, 1, 1427, 0, 0, 0, 1, 1429, 0, 0, 0, 1, 1426, 0, 0, 0, 259, 64, 32, 1430, 0, 1, 1432, 0, 0, 0, 1, 1380, 0, 0, 0, 1, 1432, 0, 0, 0, 1, 77, 0, 0, 0, 5, 1437, 9, 0, 0, 5, 1436, 5, 0, 0, 1, 1434, 0, 0, 0, 1, 1439, 0, 0, 0, 1, 1435, 0, 0, 0, 1, 1438, 0, 0, 0, 1, 1469, 0, 0, 0, 1, 1437, 0, 0, 0, 3, 80, 40, 1457, 0, 5, 1443, 5, 0, 0, 1, 1441, 0, 0, 0, 1, 1446, 0, 0, 0, 1, 1442, 0, 0, 0, 1, 1445, 0, 0, 0, 1, 1447, 0, 0, 0, 1, 1444, 0, 0, 0, 5, 1451, 8, 0, 0, 5, 1450, 5, 0, 0, 1, 1448, 0, 0, 0, 1, 1453, 0, 0, 0, 1, 1449, 0, 0, 0, 1, 1452, 0, 0, 0, 1, 1454, 0, 0, 0, 1, 1451, 0, 0, 0, 3, 80, 40, 1456, 0, 1, 1444, 0, 0, 0, 1, 1459, 0, 0, 0, 1, 1455, 0, 0, 0, 1, 1458, 0, 0, 0, 1, 1467, 0, 0, 0, 1, 1457, 0, 0, 0, 5, 1462, 5, 0, 0, 1, 1460, 0, 0, 0, 1, 1465, 0, 0, 0, 1, 1461, 0, 0, 0, 1, 1464, 0, 0, 0, 1, 1466, 0, 0, 0, 1, 1463, 0, 0, 0, 5, 1468, 8, 0, 0, 1, 1463, 0, 0, 0, 1, 1468, 0, 0, 0, 1, 1470, 0, 0, 0, 1, 1440, 0, 0, 0, 1, 1470, 0, 0, 0, 1, 1474, 0, 0, 0, 5, 1473, 5, 0, 0, 1, 1471, 0, 0, 0, 1, 1476, 0, 0, 0, 1, 1472, 0, 0, 0, 1, 1475, 0, 0, 0, 1, 1477, 0, 0, 0, 1, 1474, 0, 0, 0, 5, 1478, 10, 0, 0, 1, 79, 0, 0, 0, 3, 302, 151, 1481, 0, 1, 1479, 0, 0, 0, 1, 1481, 0, 0, 0, 1, 1482, 0, 0, 0, 3, 82, 41, 1497, 0, 5, 1485, 5, 0, 0, 1, 1483, 0, 0, 0, 1, 1488, 0, 0, 0, 1, 1484, 0, 0, 0, 1, 1487, 0, 0, 0, 1, 1489, 0, 0, 0, 1, 1486, 0, 0, 0, 5, 1493, 28, 0, 0, 5, 1492, 5, 0, 0, 1, 1490, 0, 0, 0, 1, 1495, 0, 0, 0, 1, 1491, 0, 0, 0, 1, 1494, 0, 0, 0, 1, 1496, 0, 0, 0, 1, 1493, 0, 0, 0, 259, 152, 76, 1498, 0, 1, 1486, 0, 0, 0, 1, 1498, 0, 0, 0, 1, 81, 0, 0, 0, 3, 344, 172, 1503, 0, 5, 1502, 5, 0, 0, 1, 1500, 0, 0, 0, 1, 1505, 0, 0, 0, 1, 1501, 0, 0, 0, 1, 1504, 0, 0, 0, 1, 1514, 0, 0, 0, 1, 1503, 0, 0, 0, 5, 1510, 26, 0, 0, 5, 1509, 5, 0, 0, 1, 1507, 0, 0, 0, 1, 1512, 0, 0, 0, 1, 1508, 0, 0, 0, 1, 1511, 0, 0, 0, 1, 1513, 0, 0, 0, 1, 1510, 0, 0, 0, 259, 98, 49, 1515, 0, 1, 1506, 0, 0, 0, 1, 1515, 0, 0, 0, 1, 83, 0, 0, 0, 3, 344, 172, 1520, 0, 5, 1519, 5, 0, 0, 1, 1517, 0, 0, 0, 1, 1522, 0, 0, 0, 1, 1518, 0, 0, 0, 1, 1521, 0, 0, 0, 1, 1523, 0, 0, 0, 1, 1520, 0, 0, 0, 5, 1527, 26, 0, 0, 5, 1526, 5, 0, 0, 1, 1524, 0, 0, 0, 1, 1529, 0, 0, 0, 1, 1525, 0, 0, 0, 1, 1528, 0, 0, 0, 1, 1530, 0, 0, 0, 1, 1527, 0, 0, 0, 259, 98, 49, 1531, 0, 1, 85, 0, 0, 0, 3, 300, 150, 1534, 0, 1, 1532, 0, 0, 0, 1, 1534, 0, 0, 0, 1, 1535, 0, 0, 0, 5, 1539, 77, 0, 0, 5, 1538, 5, 0, 0, 1, 1536, 0, 0, 0, 1, 1541, 0, 0, 0, 1, 1537, 0, 0, 0, 1, 1540, 0, 0, 0, 1, 1542, 0, 0, 0, 1, 1539, 0, 0, 0, 3, 344, 172, 1557, 0, 5, 1545, 5, 0, 0, 1, 1543, 0, 0, 0, 1, 1548, 0, 0, 0, 1, 1544, 0, 0, 0, 1, 1547, 0, 0, 0, 1, 1549, 0, 0, 0, 1, 1546, 0, 0, 0, 5, 1553, 26, 0, 0, 5, 1552, 5, 0, 0, 1, 1550, 0, 0, 0, 1, 1555, 0, 0, 0, 1, 1551, 0, 0, 0, 1, 1554, 0, 0, 0, 1, 1556, 0, 0, 0, 1, 1553, 0, 0, 0, 3, 32, 16, 1558, 0, 1, 1546, 0, 0, 0, 1, 1558, 0, 0, 0, 1, 1566, 0, 0, 0, 5, 1561, 5, 0, 0, 1, 1559, 0, 0, 0, 1, 1564, 0, 0, 0, 1, 1560, 0, 0, 0, 1, 1563, 0, 0, 0, 1, 1565, 0, 0, 0, 1, 1562, 0, 0, 0, 259, 26, 13, 1567, 0, 1, 1562, 0, 0, 0, 1, 1567, 0, 0, 0, 1, 87, 0, 0, 0, 3, 300, 150, 1570, 0, 1, 1568, 0, 0, 0, 1, 1570, 0, 0, 0, 1, 1571, 0, 0, 0, 5, 1575, 81, 0, 0, 5, 1574, 5, 0, 0, 1, 1572, 0, 0, 0, 1, 1577, 0, 0, 0, 1, 1573, 0, 0, 0, 1, 1576, 0, 0, 0, 1, 1578, 0, 0, 0, 1, 1575, 0, 0, 0, 3, 58, 29, 1593, 0, 5, 1581, 5, 0, 0, 1, 1579, 0, 0, 0, 1, 1584, 0, 0, 0, 1, 1580, 0, 0, 0, 1, 1583, 0, 0, 0, 1, 1585, 0, 0, 0, 1, 1582, 0, 0, 0, 5, 1589, 26, 0, 0, 5, 1588, 5, 0, 0, 1, 1586, 0, 0, 0, 1, 1591, 0, 0, 0, 1, 1587, 0, 0, 0, 1, 1590, 0, 0, 0, 1, 1592, 0, 0, 0, 1, 1589, 0, 0, 0, 3, 90, 45, 1594, 0, 1, 1582, 0, 0, 0, 1, 1594, 0, 0, 0, 1, 1598, 0, 0, 0, 5, 1597, 5, 0, 0, 1, 1595, 0, 0, 0, 1, 1600, 0, 0, 0, 1, 1596, 0, 0, 0, 1, 1599, 0, 0, 0, 1, 1602, 0, 0, 0, 1, 1598, 0, 0, 0, 259, 136, 68, 1603, 0, 1, 1601, 0, 0, 0, 1, 1603, 0, 0, 0, 1, 89, 0, 0, 0, 7, 1608, 2, 0, 0, 5, 1607, 5, 0, 0, 1, 1605, 0, 0, 0, 1, 1610, 0, 0, 0, 1, 1606, 0, 0, 0, 1, 1609, 0, 0, 0, 1, 1611, 0, 0, 0, 1, 1608, 0, 0, 0, 259, 208, 104, 1612, 0, 1, 91, 0, 0, 0, 5, 1617, 13, 0, 0, 5, 1616, 5, 0, 0, 1, 1614, 0, 0, 0, 1, 1619, 0, 0, 0, 1, 1615, 0, 0, 0, 1, 1618, 0, 0, 0, 1, 1621, 0, 0, 0, 1, 1617, 0, 0, 0, 3, 94, 47, 1622, 0, 1, 1620, 0, 0, 0, 1, 1622, 0, 0, 0, 1, 1637, 0, 0, 0, 5, 1625, 5, 0, 0, 1, 1623, 0, 0, 0, 1, 1628, 0, 0, 0, 1, 1624, 0, 0, 0, 1, 1627, 0, 0, 0, 1, 1629, 0, 0, 0, 1, 1626, 0, 0, 0, 5, 1633, 27, 0, 0, 5, 1632, 5, 0, 0, 1, 1630, 0, 0, 0, 1, 1635, 0, 0, 0, 1, 1631, 0, 0, 0, 1, 1634, 0, 0, 0, 1, 1636, 0, 0, 0, 1, 1633, 0, 0, 0, 3, 50, 25, 1638, 0, 1, 1626, 0, 0, 0, 1, 1638, 0, 0, 0, 1, 1642, 0, 0, 0, 5, 1641, 5, 0, 0, 1, 1639, 0, 0, 0, 1, 1644, 0, 0, 0, 1, 1640, 0, 0, 0, 1, 1643, 0, 0, 0, 1, 1645, 0, 0, 0, 1, 1642, 0, 0, 0, 5, 1646, 14, 0, 0, 1, 93, 0, 0, 0, 3, 96, 48, 1664, 0, 5, 1650, 5, 0, 0, 1, 1648, 0, 0, 0, 1, 1653, 0, 0, 0, 1, 1649, 0, 0, 0, 1, 1652, 0, 0, 0, 1, 1654, 0, 0, 0, 1, 1651, 0, 0, 0, 5, 1658, 8, 0, 0, 5, 1657, 5, 0, 0, 1, 1655, 0, 0, 0, 1, 1660, 0, 0, 0, 1, 1656, 0, 0, 0, 1, 1659, 0, 0, 0, 1, 1661, 0, 0, 0, 1, 1658, 0, 0, 0, 3, 96, 48, 1663, 0, 1, 1651, 0, 0, 0, 1, 1666, 0, 0, 0, 1, 1662, 0, 0, 0, 1, 1665, 0, 0, 0, 1, 1670, 0, 0, 0, 1, 1664, 0, 0, 0, 5, 1669, 5, 0, 0, 1, 1667, 0, 0, 0, 1, 1672, 0, 0, 0, 1, 1668, 0, 0, 0, 1, 1671, 0, 0, 0, 1, 1674, 0, 0, 0, 1, 1670, 0, 0, 0, 5, 1675, 8, 0, 0, 1, 1673, 0, 0, 0, 1, 1675, 0, 0, 0, 1, 95, 0, 0, 0, 3, 300, 150, 1680, 0, 5, 1679, 5, 0, 0, 1, 1677, 0, 0, 0, 1, 1682, 0, 0, 0, 1, 1678, 0, 0, 0, 1, 1681, 0, 0, 0, 1, 1684, 0, 0, 0, 1, 1680, 0, 0, 0, 1, 1676, 0, 0, 0, 1, 1684, 0, 0, 0, 1, 1685, 0, 0, 0, 3, 344, 172, 1693, 0, 5, 1688, 5, 0, 0, 1, 1686, 0, 0, 0, 1, 1691, 0, 0, 0, 1, 1687, 0, 0, 0, 1, 1690, 0, 0, 0, 1, 1692, 0, 0, 0, 1, 1689, 0, 0, 0, 3, 208, 104, 1694, 0, 1, 1689, 0, 0, 0, 1, 1694, 0, 0, 0, 1, 1702, 0, 0, 0, 5, 1697, 5, 0, 0, 1, 1695, 0, 0, 0, 1, 1700, 0, 0, 0, 1, 1696, 0, 0, 0, 1, 1699, 0, 0, 0, 1, 1701, 0, 0, 0, 1, 1698, 0, 0, 0, 259, 26, 13, 1703, 0, 1, 1698, 0, 0, 0, 1, 1703, 0, 0, 0, 1, 97, 0, 0, 0, 3, 306, 153, 1706, 0, 1, 1704, 0, 0, 0, 1, 1706, 0, 0, 0, 1, 1712, 0, 0, 0, 259, 116, 58, 1713, 0, 259, 120, 60, 1713, 0, 259, 102, 51, 1713, 0, 259, 100, 50, 1713, 0, 259, 126, 63, 1713, 0, 1, 1707, 0, 0, 0, 1, 1708, 0, 0, 0, 1, 1709, 0, 0, 0, 1, 1710, 0, 0, 0, 1, 1711, 0, 0, 0, 1, 99, 0, 0, 0, 259, 106, 53, 1717, 0, 5, 1717, 108, 0, 0, 1, 1714, 0, 0, 0, 1, 1715, 0, 0, 0, 1, 101, 0, 0, 0, 3, 100, 50, 1721, 0, 3, 120, 60, 1721, 0, 1, 1718, 0, 0, 0, 1, 1719, 0, 0, 0, 1, 1725, 0, 0, 0, 5, 1724, 5, 0, 0, 1, 1722, 0, 0, 0, 1, 1727, 0, 0, 0, 1, 1723, 0, 0, 0, 1, 1726, 0, 0, 0, 1, 1729, 0, 0, 0, 1, 1725, 0, 0, 0, 3, 104, 52, 1730, 0, 1, 1728, 0, 0, 0, 1, 1731, 0, 0, 0, 1, 1729, 0, 0, 0, 1, 1732, 0, 0, 0, 1, 103, 0, 0, 0, 7, 1734, 3, 0, 0, 1, 105, 0, 0, 0, 3, 108, 54, 1752, 0, 5, 1738, 5, 0, 0, 1, 1736, 0, 0, 0, 1, 1741, 0, 0, 0, 1, 1737, 0, 0, 0, 1, 1740, 0, 0, 0, 1, 1742, 0, 0, 0, 1, 1739, 0, 0, 0, 5, 1746, 7, 0, 0, 5, 1745, 5, 0, 0, 1, 1743, 0, 0, 0, 1, 1748, 0, 0, 0, 1, 1744, 0, 0, 0, 1, 1747, 0, 0, 0, 1, 1749, 0, 0, 0, 1, 1746, 0, 0, 0, 3, 108, 54, 1751, 0, 1, 1739, 0, 0, 0, 1, 1754, 0, 0, 0, 1, 1750, 0, 0, 0, 1, 1753, 0, 0, 0, 1, 107, 0, 0, 0, 1, 1752, 0, 0, 0, 3, 344, 172, 1763, 0, 5, 1758, 5, 0, 0, 1, 1756, 0, 0, 0, 1, 1761, 0, 0, 0, 1, 1757, 0, 0, 0, 1, 1760, 0, 0, 0, 1, 1762, 0, 0, 0, 1, 1759, 0, 0, 0, 259, 206, 103, 1764, 0, 1, 1759, 0, 0, 0, 1, 1764, 0, 0, 0, 1, 109, 0, 0, 0, 3, 112, 56, 1767, 0, 1, 1765, 0, 0, 0, 1, 1767, 0, 0, 0, 1, 1768, 0, 0, 0, 259, 98, 49, 1771, 0, 5, 1771, 15, 0, 0, 1, 1766, 0, 0, 0, 1, 1769, 0, 0, 0, 1, 111, 0, 0, 0, 3, 114, 57, 1774, 0, 1, 1772, 0, 0, 0, 1, 1775, 0, 0, 0, 1, 1773, 0, 0, 0, 1, 1776, 0, 0, 0, 1, 113, 0, 0, 0, 3, 316, 158, 1781, 0, 5, 1780, 5, 0, 0, 1, 1778, 0, 0, 0, 1, 1783, 0, 0, 0, 1, 1779, 0, 0, 0, 1, 1782, 0, 0, 0, 1, 1786, 0, 0, 0, 1, 1781, 0, 0, 0, 259, 334, 167, 1786, 0, 1, 1777, 0, 0, 0, 1, 1784, 0, 0, 0, 1, 115, 0, 0, 0, 3, 122, 61, 1791, 0, 5, 1790, 5, 0, 0, 1, 1788, 0, 0, 0, 1, 1793, 0, 0, 0, 1, 1789, 0, 0, 0, 1, 1792, 0, 0, 0, 1, 1794, 0, 0, 0, 1, 1791, 0, 0, 0, 5, 1798, 7, 0, 0, 5, 1797, 5, 0, 0, 1, 1795, 0, 0, 0, 1, 1800, 0, 0, 0, 1, 1796, 0, 0, 0, 1, 1799, 0, 0, 0, 1, 1802, 0, 0, 0, 1, 1798, 0, 0, 0, 1, 1787, 0, 0, 0, 1, 1802, 0, 0, 0, 1, 1803, 0, 0, 0, 3, 118, 59, 1807, 0, 5, 1806, 5, 0, 0, 1, 1804, 0, 0, 0, 1, 1809, 0, 0, 0, 1, 1805, 0, 0, 0, 1, 1808, 0, 0, 0, 1, 1810, 0, 0, 0, 1, 1807, 0, 0, 0, 5, 1814, 34, 0, 0, 5, 1813, 5, 0, 0, 1, 1811, 0, 0, 0, 1, 1816, 0, 0, 0, 1, 1812, 0, 0, 0, 1, 1815, 0, 0, 0, 1, 1817, 0, 0, 0, 1, 1814, 0, 0, 0, 259, 98, 49, 1818, 0, 1, 117, 0, 0, 0, 5, 1823, 9, 0, 0, 5, 1822, 5, 0, 0, 1, 1820, 0, 0, 0, 1, 1825, 0, 0, 0, 1, 1821, 0, 0, 0, 1, 1824, 0, 0, 0, 1, 1828, 0, 0, 0, 1, 1823, 0, 0, 0, 3, 84, 42, 1829, 0, 3, 98, 49, 1829, 0, 1, 1826, 0, 0, 0, 1, 1827, 0, 0, 0, 1, 1829, 0, 0, 0, 1, 1849, 0, 0, 0, 5, 1832, 5, 0, 0, 1, 1830, 0, 0, 0, 1, 1835, 0, 0, 0, 1, 1831, 0, 0, 0, 1, 1834, 0, 0, 0, 1, 1836, 0, 0, 0, 1, 1833, 0, 0, 0, 5, 1840, 8, 0, 0, 5, 1839, 5, 0, 0, 1, 1837, 0, 0, 0, 1, 1842, 0, 0, 0, 1, 1838, 0, 0, 0, 1, 1841, 0, 0, 0, 1, 1845, 0, 0, 0, 1, 1840, 0, 0, 0, 3, 84, 42, 1846, 0, 3, 98, 49, 1846, 0, 1, 1843, 0, 0, 0, 1, 1844, 0, 0, 0, 1, 1848, 0, 0, 0, 1, 1833, 0, 0, 0, 1, 1851, 0, 0, 0, 1, 1847, 0, 0, 0, 1, 1850, 0, 0, 0, 1, 1859, 0, 0, 0, 1, 1849, 0, 0, 0, 5, 1854, 5, 0, 0, 1, 1852, 0, 0, 0, 1, 1857, 0, 0, 0, 1, 1853, 0, 0, 0, 1, 1856, 0, 0, 0, 1, 1858, 0, 0, 0, 1, 1855, 0, 0, 0, 5, 1860, 8, 0, 0, 1, 1855, 0, 0, 0, 1, 1860, 0, 0, 0, 1, 1864, 0, 0, 0, 5, 1863, 5, 0, 0, 1, 1861, 0, 0, 0, 1, 1866, 0, 0, 0, 1, 1862, 0, 0, 0, 1, 1865, 0, 0, 0, 1, 1867, 0, 0, 0, 1, 1864, 0, 0, 0, 5, 1868, 10, 0, 0, 1, 119, 0, 0, 0, 5, 1873, 9, 0, 0, 5, 1872, 5, 0, 0, 1, 1870, 0, 0, 0, 1, 1875, 0, 0, 0, 1, 1871, 0, 0, 0, 1, 1874, 0, 0, 0, 1, 1876, 0, 0, 0, 1, 1873, 0, 0, 0, 3, 98, 49, 1880, 0, 5, 1879, 5, 0, 0, 1, 1877, 0, 0, 0, 1, 1882, 0, 0, 0, 1, 1878, 0, 0, 0, 1, 1881, 0, 0, 0, 1, 1883, 0, 0, 0, 1, 1880, 0, 0, 0, 5, 1884, 10, 0, 0, 1, 121, 0, 0, 0, 3, 306, 153, 1887, 0, 1, 1885, 0, 0, 0, 1, 1887, 0, 0, 0, 1, 1891, 0, 0, 0, 259, 120, 60, 1892, 0, 259, 102, 51, 1892, 0, 259, 100, 50, 1892, 0, 1, 1888, 0, 0, 0, 1, 1889, 0, 0, 0, 1, 1890, 0, 0, 0, 1, 123, 0, 0, 0, 5, 1897, 9, 0, 0, 5, 1896, 5, 0, 0, 1, 1894, 0, 0, 0, 1, 1899, 0, 0, 0, 1, 1895, 0, 0, 0, 1, 1898, 0, 0, 0, 1, 1902, 0, 0, 0, 1, 1897, 0, 0, 0, 3, 106, 53, 1903, 0, 3, 124, 62, 1903, 0, 1, 1900, 0, 0, 0, 1, 1901, 0, 0, 0, 1, 1907, 0, 0, 0, 5, 1906, 5, 0, 0, 1, 1904, 0, 0, 0, 1, 1909, 0, 0, 0, 1, 1905, 0, 0, 0, 1, 1908, 0, 0, 0, 1, 1910, 0, 0, 0, 1, 1907, 0, 0, 0, 5, 1911, 10, 0, 0, 1, 125, 0, 0, 0, 3, 306, 153, 1914, 0, 1, 1912, 0, 0, 0, 1, 1914, 0, 0, 0, 1, 1917, 0, 0, 0, 3, 106, 53, 1918, 0, 3, 124, 62, 1918, 0, 1, 1915, 0, 0, 0, 1, 1916, 0, 0, 0, 1, 1922, 0, 0, 0, 5, 1921, 5, 0, 0, 1, 1919, 0, 0, 0, 1, 1924, 0, 0, 0, 1, 1920, 0, 0, 0, 1, 1923, 0, 0, 0, 1, 1925, 0, 0, 0, 1, 1922, 0, 0, 0, 5, 1929, 57, 0, 0, 5, 1928, 5, 0, 0, 1, 1926, 0, 0, 0, 1, 1931, 0, 0, 0, 1, 1927, 0, 0, 0, 1, 1930, 0, 0, 0, 1, 1933, 0, 0, 0, 1, 1929, 0, 0, 0, 3, 306, 153, 1934, 0, 1, 1932, 0, 0, 0, 1, 1934, 0, 0, 0, 1, 1937, 0, 0, 0, 259, 106, 53, 1938, 0, 259, 124, 62, 1938, 0, 1, 1935, 0, 0, 0, 1, 1936, 0, 0, 0, 1, 127, 0, 0, 0, 3, 130, 65, 1945, 0, 3, 150, 75, 1941, 0, 3, 130, 65, 1942, 0, 1, 1944, 0, 0, 0, 1, 1940, 0, 0, 0, 1, 1947, 0, 0, 0, 1, 1943, 0, 0, 0, 1, 1946, 0, 0, 0, 1, 1949, 0, 0, 0, 1, 1945, 0, 0, 0, 1, 1939, 0, 0, 0, 1, 1949, 0, 0, 0, 1, 1951, 0, 0, 0, 259, 150, 75, 1952, 0, 1, 1950, 0, 0, 0, 1, 1952, 0, 0, 0, 1, 129, 0, 0, 0, 3, 132, 66, 1956, 0, 3, 334, 167, 1956, 0, 1, 1953, 0, 0, 0, 1, 1954, 0, 0, 0, 1, 1959, 0, 0, 0, 1, 1955, 0, 0, 0, 1, 1958, 0, 0, 0, 1, 1964, 0, 0, 0, 1, 1957, 0, 0, 0, 259, 20, 10, 1965, 0, 259, 146, 73, 1965, 0, 259, 138, 69, 1965, 0, 259, 152, 76, 1965, 0, 1, 1960, 0, 0, 0, 1, 1961, 0, 0, 0, 1, 1962, 0, 0, 0, 1, 1963, 0, 0, 0, 1, 131, 0, 0, 0, 3, 344, 172, 1967, 0, 7, 1971, 4, 0, 0, 5, 1970, 5, 0, 0, 1, 1968, 0, 0, 0, 1, 1973, 0, 0, 0, 1, 1969, 0, 0, 0, 1, 1972, 0, 0, 0, 1, 133, 0, 0, 0, 1, 1971, 0, 0, 0, 259, 136, 68, 1977, 0, 259, 130, 65, 1977, 0, 1, 1974, 0, 0, 0, 1, 1975, 0, 0, 0, 1, 135, 0, 0, 0, 5, 1982, 13, 0, 0, 5, 1981, 5, 0, 0, 1, 1979, 0, 0, 0, 1, 1984, 0, 0, 0, 1, 1980, 0, 0, 0, 1, 1983, 0, 0, 0, 1, 1985, 0, 0, 0, 1, 1982, 0, 0, 0, 3, 128, 64, 1989, 0, 5, 1988, 5, 0, 0, 1, 1986, 0, 0, 0, 1, 1991, 0, 0, 0, 1, 1987, 0, 0, 0, 1, 1990, 0, 0, 0, 1, 1992, 0, 0, 0, 1, 1989, 0, 0, 0, 5, 1993, 14, 0, 0, 1, 137, 0, 0, 0, 259, 140, 70, 1998, 0, 259, 142, 71, 1998, 0, 259, 144, 72, 1998, 0, 1, 1994, 0, 0, 0, 1, 1995, 0, 0, 0, 1, 1996, 0, 0, 0, 1, 139, 0, 0, 0, 5, 2003, 95, 0, 0, 5, 2002, 5, 0, 0, 1, 2000, 0, 0, 0, 1, 2005, 0, 0, 0, 1, 2001, 0, 0, 0, 1, 2004, 0, 0, 0, 1, 2006, 0, 0, 0, 1, 2003, 0, 0, 0, 5, 2010, 9, 0, 0, 3, 334, 167, 2009, 0, 1, 2007, 0, 0, 0, 1, 2012, 0, 0, 0, 1, 2008, 0, 0, 0, 1, 2011, 0, 0, 0, 1, 2015, 0, 0, 0, 1, 2010, 0, 0, 0, 3, 66, 33, 2016, 0, 3, 68, 34, 2016, 0, 1, 2013, 0, 0, 0, 1, 2014, 0, 0, 0, 1, 2017, 0, 0, 0, 5, 2018, 104, 0, 0, 3, 152, 76, 2019, 0, 5, 2023, 10, 0, 0, 5, 2022, 5, 0, 0, 1, 2020, 0, 0, 0, 1, 2025, 0, 0, 0, 1, 2021, 0, 0, 0, 1, 2024, 0, 0, 0, 1, 2027, 0, 0, 0, 1, 2023, 0, 0, 0, 259, 134, 67, 2028, 0, 1, 2026, 0, 0, 0, 1, 2028, 0, 0, 0, 1, 141, 0, 0, 0, 5, 2033, 97, 0, 0, 5, 2032, 5, 0, 0, 1, 2030, 0, 0, 0, 1, 2035, 0, 0, 0, 1, 2031, 0, 0, 0, 1, 2034, 0, 0, 0, 1, 2036, 0, 0, 0, 1, 2033, 0, 0, 0, 5, 2037, 9, 0, 0, 3, 152, 76, 2038, 0, 5, 2042, 10, 0, 0, 5, 2041, 5, 0, 0, 1, 2039, 0, 0, 0, 1, 2044, 0, 0, 0, 1, 2040, 0, 0, 0, 1, 2043, 0, 0, 0, 1, 2047, 0, 0, 0, 1, 2042, 0, 0, 0, 259, 134, 67, 2048, 0, 5, 2048, 27, 0, 0, 1, 2045, 0, 0, 0, 1, 2046, 0, 0, 0, 1, 143, 0, 0, 0, 5, 2053, 96, 0, 0, 5, 2052, 5, 0, 0, 1, 2050, 0, 0, 0, 1, 2055, 0, 0, 0, 1, 2051, 0, 0, 0, 1, 2054, 0, 0, 0, 1, 2057, 0, 0, 0, 1, 2053, 0, 0, 0, 3, 134, 67, 2058, 0, 1, 2056, 0, 0, 0, 1, 2058, 0, 0, 0, 1, 2062, 0, 0, 0, 5, 2061, 5, 0, 0, 1, 2059, 0, 0, 0, 1, 2064, 0, 0, 0, 1, 2060, 0, 0, 0, 1, 2063, 0, 0, 0, 1, 2065, 0, 0, 0, 1, 2062, 0, 0, 0, 5, 2069, 97, 0, 0, 5, 2068, 5, 0, 0, 1, 2066, 0, 0, 0, 1, 2071, 0, 0, 0, 1, 2067, 0, 0, 0, 1, 2070, 0, 0, 0, 1, 2072, 0, 0, 0, 1, 2069, 0, 0, 0, 5, 2073, 9, 0, 0, 3, 152, 76, 2074, 0, 5, 2075, 10, 0, 0, 1, 145, 0, 0, 0, 3, 188, 94, 2077, 0, 5, 2078, 28, 0, 0, 1, 2083, 0, 0, 0, 3, 192, 96, 2080, 0, 3, 274, 137, 2081, 0, 1, 2083, 0, 0, 0, 1, 2076, 0, 0, 0, 1, 2079, 0, 0, 0, 1, 2087, 0, 0, 0, 5, 2086, 5, 0, 0, 1, 2084, 0, 0, 0, 1, 2089, 0, 0, 0, 1, 2085, 0, 0, 0, 1, 2088, 0, 0, 0, 1, 2090, 0, 0, 0, 1, 2087, 0, 0, 0, 259, 152, 76, 2091, 0, 1, 147, 0, 0, 0, 7, 2096, 5, 0, 0, 5, 2095, 5, 0, 0, 1, 2093, 0, 0, 0, 1, 2098, 0, 0, 0, 1, 2094, 0, 0, 0, 1, 2097, 0, 0, 0, 1, 149, 0, 0, 0, 1, 2096, 0, 0, 0, 7, 2101, 5, 0, 0, 1, 2099, 0, 0, 0, 1, 2102, 0, 0, 0, 1, 2100, 0, 0, 0, 1, 2103, 0, 0, 0, 1, 151, 0, 0, 0, 259, 154, 77, 2105, 0, 1, 153, 0, 0, 0, 3, 156, 78, 2123, 0, 5, 2109, 5, 0, 0, 1, 2107, 0, 0, 0, 1, 2112, 0, 0, 0, 1, 2108, 0, 0, 0, 1, 2111, 0, 0, 0, 1, 2113, 0, 0, 0, 1, 2110, 0, 0, 0, 5, 2117, 23, 0, 0, 5, 2116, 5, 0, 0, 1, 2114, 0, 0, 0, 1, 2119, 0, 0, 0, 1, 2115, 0, 0, 0, 1, 2118, 0, 0, 0, 1, 2120, 0, 0, 0, 1, 2117, 0, 0, 0, 3, 156, 78, 2122, 0, 1, 2110, 0, 0, 0, 1, 2125, 0, 0, 0, 1, 2121, 0, 0, 0, 1, 2124, 0, 0, 0, 1, 155, 0, 0, 0, 1, 2123, 0, 0, 0, 3, 158, 79, 2143, 0, 5, 2129, 5, 0, 0, 1, 2127, 0, 0, 0, 1, 2132, 0, 0, 0, 1, 2128, 0, 0, 0, 1, 2131, 0, 0, 0, 1, 2133, 0, 0, 0, 1, 2130, 0, 0, 0, 5, 2137, 22, 0, 0, 5, 2136, 5, 0, 0, 1, 2134, 0, 0, 0, 1, 2139, 0, 0, 0, 1, 2135, 0, 0, 0, 1, 2138, 0, 0, 0, 1, 2140, 0, 0, 0, 1, 2137, 0, 0, 0, 3, 158, 79, 2142, 0, 1, 2130, 0, 0, 0, 1, 2145, 0, 0, 0, 1, 2141, 0, 0, 0, 1, 2144, 0, 0, 0, 1, 157, 0, 0, 0, 1, 2143, 0, 0, 0, 3, 160, 80, 2158, 0, 3, 276, 138, 2151, 0, 5, 2150, 5, 0, 0, 1, 2148, 0, 0, 0, 1, 2153, 0, 0, 0, 1, 2149, 0, 0, 0, 1, 2152, 0, 0, 0, 1, 2154, 0, 0, 0, 1, 2151, 0, 0, 0, 3, 160, 80, 2155, 0, 1, 2157, 0, 0, 0, 1, 2147, 0, 0, 0, 1, 2160, 0, 0, 0, 1, 2156, 0, 0, 0, 1, 2159, 0, 0, 0, 1, 159, 0, 0, 0, 1, 2158, 0, 0, 0, 3, 162, 81, 2173, 0, 3, 278, 139, 2166, 0, 5, 2165, 5, 0, 0, 1, 2163, 0, 0, 0, 1, 2168, 0, 0, 0, 1, 2164, 0, 0, 0, 1, 2167, 0, 0, 0, 1, 2169, 0, 0, 0, 1, 2166, 0, 0, 0, 3, 162, 81, 2170, 0, 1, 2172, 0, 0, 0, 1, 2162, 0, 0, 0, 1, 2175, 0, 0, 0, 1, 2171, 0, 0, 0, 1, 2174, 0, 0, 0, 1, 161, 0, 0, 0, 1, 2173, 0, 0, 0, 3, 164, 82, 2180, 0, 3, 202, 101, 2179, 0, 1, 2177, 0, 0, 0, 1, 2182, 0, 0, 0, 1, 2178, 0, 0, 0, 1, 2181, 0, 0, 0, 1, 163, 0, 0, 0, 1, 2180, 0, 0, 0, 3, 166, 83, 2204, 0, 3, 280, 140, 2188, 0, 5, 2187, 5, 0, 0, 1, 2185, 0, 0, 0, 1, 2190, 0, 0, 0, 1, 2186, 0, 0, 0, 1, 2189, 0, 0, 0, 1, 2191, 0, 0, 0, 1, 2188, 0, 0, 0, 3, 166, 83, 2192, 0, 1, 2203, 0, 0, 0, 3, 282, 141, 2197, 0, 5, 2196, 5, 0, 0, 1, 2194, 0, 0, 0, 1, 2199, 0, 0, 0, 1, 2195, 0, 0, 0, 1, 2198, 0, 0, 0, 1, 2200, 0, 0, 0, 1, 2197, 0, 0, 0, 3, 98, 49, 2201, 0, 1, 2203, 0, 0, 0, 1, 2184, 0, 0, 0, 1, 2193, 0, 0, 0, 1, 2206, 0, 0, 0, 1, 2202, 0, 0, 0, 1, 2205, 0, 0, 0, 1, 165, 0, 0, 0, 1, 2204, 0, 0, 0, 3, 170, 85, 2225, 0, 5, 2210, 5, 0, 0, 1, 2208, 0, 0, 0, 1, 2213, 0, 0, 0, 1, 2209, 0, 0, 0, 1, 2212, 0, 0, 0, 1, 2214, 0, 0, 0, 1, 2211, 0, 0, 0, 3, 168, 84, 2218, 0, 5, 2217, 5, 0, 0, 1, 2215, 0, 0, 0, 1, 2220, 0, 0, 0, 1, 2216, 0, 0, 0, 1, 2219, 0, 0, 0, 1, 2221, 0, 0, 0, 1, 2218, 0, 0, 0, 3, 170, 85, 2222, 0, 1, 2224, 0, 0, 0, 1, 2211, 0, 0, 0, 1, 2227, 0, 0, 0, 1, 2223, 0, 0, 0, 1, 2226, 0, 0, 0, 1, 167, 0, 0, 0, 1, 2225, 0, 0, 0, 5, 2229, 46, 0, 0, 5, 2230, 26, 0, 0, 1, 169, 0, 0, 0, 3, 172, 86, 2243, 0, 3, 344, 172, 2236, 0, 5, 2235, 5, 0, 0, 1, 2233, 0, 0, 0, 1, 2238, 0, 0, 0, 1, 2234, 0, 0, 0, 1, 2237, 0, 0, 0, 1, 2239, 0, 0, 0, 1, 2236, 0, 0, 0, 3, 172, 86, 2240, 0, 1, 2242, 0, 0, 0, 1, 2232, 0, 0, 0, 1, 2245, 0, 0, 0, 1, 2241, 0, 0, 0, 1, 2244, 0, 0, 0, 1, 171, 0, 0, 0, 1, 2243, 0, 0, 0, 3, 174, 87, 2257, 0, 7, 2251, 6, 0, 0, 5, 2250, 5, 0, 0, 1, 2248, 0, 0, 0, 1, 2253, 0, 0, 0, 1, 2249, 0, 0, 0, 1, 2252, 0, 0, 0, 1, 2254, 0, 0, 0, 1, 2251, 0, 0, 0, 3, 174, 87, 2256, 0, 1, 2247, 0, 0, 0, 1, 2259, 0, 0, 0, 1, 2255, 0, 0, 0, 1, 2258, 0, 0, 0, 1, 173, 0, 0, 0, 1, 2257, 0, 0, 0, 3, 176, 88, 2272, 0, 3, 284, 142, 2265, 0, 5, 2264, 5, 0, 0, 1, 2262, 0, 0, 0, 1, 2267, 0, 0, 0, 1, 2263, 0, 0, 0, 1, 2266, 0, 0, 0, 1, 2268, 0, 0, 0, 1, 2265, 0, 0, 0, 3, 176, 88, 2269, 0, 1, 2271, 0, 0, 0, 1, 2261, 0, 0, 0, 1, 2274, 0, 0, 0, 1, 2270, 0, 0, 0, 1, 2273, 0, 0, 0, 1, 175, 0, 0, 0, 1, 2272, 0, 0, 0, 3, 178, 89, 2287, 0, 3, 286, 143, 2280, 0, 5, 2279, 5, 0, 0, 1, 2277, 0, 0, 0, 1, 2282, 0, 0, 0, 1, 2278, 0, 0, 0, 1, 2281, 0, 0, 0, 1, 2283, 0, 0, 0, 1, 2280, 0, 0, 0, 3, 178, 89, 2284, 0, 1, 2286, 0, 0, 0, 1, 2276, 0, 0, 0, 1, 2289, 0, 0, 0, 1, 2285, 0, 0, 0, 1, 2288, 0, 0, 0, 1, 177, 0, 0, 0, 1, 2287, 0, 0, 0, 3, 180, 90, 2308, 0, 5, 2293, 5, 0, 0, 1, 2291, 0, 0, 0, 1, 2296, 0, 0, 0, 1, 2292, 0, 0, 0, 1, 2295, 0, 0, 0, 1, 2297, 0, 0, 0, 1, 2294, 0, 0, 0, 3, 288, 144, 2301, 0, 5, 2300, 5, 0, 0, 1, 2298, 0, 0, 0, 1, 2303, 0, 0, 0, 1, 2299, 0, 0, 0, 1, 2302, 0, 0, 0, 1, 2304, 0, 0, 0, 1, 2301, 0, 0, 0, 3, 98, 49, 2305, 0, 1, 2307, 0, 0, 0, 1, 2294, 0, 0, 0, 1, 2310, 0, 0, 0, 1, 2306, 0, 0, 0, 1, 2309, 0, 0, 0, 1, 179, 0, 0, 0, 1, 2308, 0, 0, 0, 3, 182, 91, 2313, 0, 1, 2311, 0, 0, 0, 1, 2316, 0, 0, 0, 1, 2312, 0, 0, 0, 1, 2315, 0, 0, 0, 1, 2317, 0, 0, 0, 1, 2314, 0, 0, 0, 259, 184, 92, 2318, 0, 1, 181, 0, 0, 0, 259, 334, 167, 2329, 0, 259, 132, 66, 2329, 0, 3, 290, 145, 2325, 0, 5, 2324, 5, 0, 0, 1, 2322, 0, 0, 0, 1, 2327, 0, 0, 0, 1, 2323, 0, 0, 0, 1, 2326, 0, 0, 0, 1, 2329, 0, 0, 0, 1, 2325, 0, 0, 0, 1, 2319, 0, 0, 0, 1, 2320, 0, 0, 0, 1, 2321, 0, 0, 0, 1, 183, 0, 0, 0, 3, 212, 106, 2334, 0, 3, 186, 93, 2333, 0, 1, 2331, 0, 0, 0, 1, 2336, 0, 0, 0, 1, 2332, 0, 0, 0, 1, 2335, 0, 0, 0, 1, 185, 0, 0, 0, 1, 2334, 0, 0, 0, 259, 292, 146, 2343, 0, 259, 206, 103, 2343, 0, 259, 202, 101, 2343, 0, 259, 198, 99, 2343, 0, 259, 200, 100, 2343, 0, 1, 2337, 0, 0, 0, 1, 2338, 0, 0, 0, 1, 2339, 0, 0, 0, 1, 2340, 0, 0, 0, 1, 2341, 0, 0, 0, 1, 187, 0, 0, 0, 3, 184, 92, 2345, 0, 259, 196, 98, 2346, 0, 1, 2350, 0, 0, 0, 259, 344, 172, 2350, 0, 259, 190, 95, 2350, 0, 1, 2344, 0, 0, 0, 1, 2347, 0, 0, 0, 1, 2348, 0, 0, 0, 1, 189, 0, 0, 0, 5, 2355, 9, 0, 0, 5, 2354, 5, 0, 0, 1, 2352, 0, 0, 0, 1, 2357, 0, 0, 0, 1, 2353, 0, 0, 0, 1, 2356, 0, 0, 0, 1, 2358, 0, 0, 0, 1, 2355, 0, 0, 0, 3, 188, 94, 2362, 0, 5, 2361, 5, 0, 0, 1, 2359, 0, 0, 0, 1, 2364, 0, 0, 0, 1, 2360, 0, 0, 0, 1, 2363, 0, 0, 0, 1, 2365, 0, 0, 0, 1, 2362, 0, 0, 0, 5, 2366, 10, 0, 0, 1, 191, 0, 0, 0, 259, 180, 90, 2370, 0, 259, 194, 97, 2370, 0, 1, 2367, 0, 0, 0, 1, 2368, 0, 0, 0, 1, 193, 0, 0, 0, 5, 2375, 9, 0, 0, 5, 2374, 5, 0, 0, 1, 2372, 0, 0, 0, 1, 2377, 0, 0, 0, 1, 2373, 0, 0, 0, 1, 2376, 0, 0, 0, 1, 2378, 0, 0, 0, 1, 2375, 0, 0, 0, 3, 192, 96, 2382, 0, 5, 2381, 5, 0, 0, 1, 2379, 0, 0, 0, 1, 2384, 0, 0, 0, 1, 2380, 0, 0, 0, 1, 2383, 0, 0, 0, 1, 2385, 0, 0, 0, 1, 2382, 0, 0, 0, 5, 2386, 10, 0, 0, 1, 195, 0, 0, 0, 259, 206, 103, 2391, 0, 259, 198, 99, 2391, 0, 259, 200, 100, 2391, 0, 1, 2387, 0, 0, 0, 1, 2388, 0, 0, 0, 1, 2389, 0, 0, 0, 1, 197, 0, 0, 0, 5, 2396, 11, 0, 0, 5, 2395, 5, 0, 0, 1, 2393, 0, 0, 0, 1, 2398, 0, 0, 0, 1, 2394, 0, 0, 0, 1, 2397, 0, 0, 0, 1, 2399, 0, 0, 0, 1, 2396, 0, 0, 0, 3, 152, 76, 2416, 0, 5, 2402, 5, 0, 0, 1, 2400, 0, 0, 0, 1, 2405, 0, 0, 0, 1, 2401, 0, 0, 0, 1, 2404, 0, 0, 0, 1, 2406, 0, 0, 0, 1, 2403, 0, 0, 0, 5, 2410, 8, 0, 0, 5, 2409, 5, 0, 0, 1, 2407, 0, 0, 0, 1, 2412, 0, 0, 0, 1, 2408, 0, 0, 0, 1, 2411, 0, 0, 0, 1, 2413, 0, 0, 0, 1, 2410, 0, 0, 0, 3, 152, 76, 2415, 0, 1, 2403, 0, 0, 0, 1, 2418, 0, 0, 0, 1, 2414, 0, 0, 0, 1, 2417, 0, 0, 0, 1, 2426, 0, 0, 0, 1, 2416, 0, 0, 0, 5, 2421, 5, 0, 0, 1, 2419, 0, 0, 0, 1, 2424, 0, 0, 0, 1, 2420, 0, 0, 0, 1, 2423, 0, 0, 0, 1, 2425, 0, 0, 0, 1, 2422, 0, 0, 0, 5, 2427, 8, 0, 0, 1, 2422, 0, 0, 0, 1, 2427, 0, 0, 0, 1, 2431, 0, 0, 0, 5, 2430, 5, 0, 0, 1, 2428, 0, 0, 0, 1, 2433, 0, 0, 0, 1, 2429, 0, 0, 0, 1, 2432, 0, 0, 0, 1, 2434, 0, 0, 0, 1, 2431, 0, 0, 0, 5, 2435, 12, 0, 0, 1, 199, 0, 0, 0, 3, 296, 148, 2440, 0, 5, 2439, 5, 0, 0, 1, 2437, 0, 0, 0, 1, 2442, 0, 0, 0, 1, 2438, 0, 0, 0, 1, 2441, 0, 0, 0, 1, 2446, 0, 0, 0, 1, 2440, 0, 0, 0, 259, 344, 172, 2447, 0, 259, 214, 107, 2447, 0, 5, 2447, 74, 0, 0, 1, 2443, 0, 0, 0, 1, 2444, 0, 0, 0, 1, 2445, 0, 0, 0, 1, 201, 0, 0, 0, 3, 206, 103, 2450, 0, 1, 2448, 0, 0, 0, 1, 2450, 0, 0, 0, 1, 2456, 0, 0, 0, 3, 208, 104, 2453, 0, 1, 2451, 0, 0, 0, 1, 2453, 0, 0, 0, 1, 2454, 0, 0, 0, 259, 204, 102, 2457, 0, 259, 208, 104, 2457, 0, 1, 2452, 0, 0, 0, 1, 2455, 0, 0, 0, 1, 203, 0, 0, 0, 3, 334, 167, 2460, 0, 1, 2458, 0, 0, 0, 1, 2463, 0, 0, 0, 1, 2459, 0, 0, 0, 1, 2462, 0, 0, 0, 1, 2465, 0, 0, 0, 1, 2461, 0, 0, 0, 3, 132, 66, 2466, 0, 1, 2464, 0, 0, 0, 1, 2466, 0, 0, 0, 1, 2470, 0, 0, 0, 5, 2469, 5, 0, 0, 1, 2467, 0, 0, 0, 1, 2472, 0, 0, 0, 1, 2468, 0, 0, 0, 1, 2471, 0, 0, 0, 1, 2473, 0, 0, 0, 1, 2470, 0, 0, 0, 259, 234, 117, 2474, 0, 1, 205, 0, 0, 0, 5, 2479, 47, 0, 0, 5, 2478, 5, 0, 0, 1, 2476, 0, 0, 0, 1, 2481, 0, 0, 0, 1, 2477, 0, 0, 0, 1, 2480, 0, 0, 0, 1, 2482, 0, 0, 0, 1, 2479, 0, 0, 0, 3, 110, 55, 2499, 0, 5, 2485, 5, 0, 0, 1, 2483, 0, 0, 0, 1, 2488, 0, 0, 0, 1, 2484, 0, 0, 0, 1, 2487, 0, 0, 0, 1, 2489, 0, 0, 0, 1, 2486, 0, 0, 0, 5, 2493, 8, 0, 0, 5, 2492, 5, 0, 0, 1, 2490, 0, 0, 0, 1, 2495, 0, 0, 0, 1, 2491, 0, 0, 0, 1, 2494, 0, 0, 0, 1, 2496, 0, 0, 0, 1, 2493, 0, 0, 0, 3, 110, 55, 2498, 0, 1, 2486, 0, 0, 0, 1, 2501, 0, 0, 0, 1, 2497, 0, 0, 0, 1, 2500, 0, 0, 0, 1, 2509, 0, 0, 0, 1, 2499, 0, 0, 0, 5, 2504, 5, 0, 0, 1, 2502, 0, 0, 0, 1, 2507, 0, 0, 0, 1, 2503, 0, 0, 0, 1, 2506, 0, 0, 0, 1, 2508, 0, 0, 0, 1, 2505, 0, 0, 0, 5, 2510, 8, 0, 0, 1, 2505, 0, 0, 0, 1, 2510, 0, 0, 0, 1, 2514, 0, 0, 0, 5, 2513, 5, 0, 0, 1, 2511, 0, 0, 0, 1, 2516, 0, 0, 0, 1, 2512, 0, 0, 0, 1, 2515, 0, 0, 0, 1, 2517, 0, 0, 0, 1, 2514, 0, 0, 0, 5, 2518, 48, 0, 0, 1, 207, 0, 0, 0, 5, 2523, 9, 0, 0, 5, 2522, 5, 0, 0, 1, 2520, 0, 0, 0, 1, 2525, 0, 0, 0, 1, 2521, 0, 0, 0, 1, 2524, 0, 0, 0, 1, 2561, 0, 0, 0, 1, 2523, 0, 0, 0, 3, 210, 105, 2543, 0, 5, 2529, 5, 0, 0, 1, 2527, 0, 0, 0, 1, 2532, 0, 0, 0, 1, 2528, 0, 0, 0, 1, 2531, 0, 0, 0, 1, 2533, 0, 0, 0, 1, 2530, 0, 0, 0, 5, 2537, 8, 0, 0, 5, 2536, 5, 0, 0, 1, 2534, 0, 0, 0, 1, 2539, 0, 0, 0, 1, 2535, 0, 0, 0, 1, 2538, 0, 0, 0, 1, 2540, 0, 0, 0, 1, 2537, 0, 0, 0, 3, 210, 105, 2542, 0, 1, 2530, 0, 0, 0, 1, 2545, 0, 0, 0, 1, 2541, 0, 0, 0, 1, 2544, 0, 0, 0, 1, 2553, 0, 0, 0, 1, 2543, 0, 0, 0, 5, 2548, 5, 0, 0, 1, 2546, 0, 0, 0, 1, 2551, 0, 0, 0, 1, 2547, 0, 0, 0, 1, 2550, 0, 0, 0, 1, 2552, 0, 0, 0, 1, 2549, 0, 0, 0, 5, 2554, 8, 0, 0, 1, 2549, 0, 0, 0, 1, 2554, 0, 0, 0, 1, 2558, 0, 0, 0, 5, 2557, 5, 0, 0, 1, 2555, 0, 0, 0, 1, 2560, 0, 0, 0, 1, 2556, 0, 0, 0, 1, 2559, 0, 0, 0, 1, 2562, 0, 0, 0, 1, 2558, 0, 0, 0, 1, 2526, 0, 0, 0, 1, 2562, 0, 0, 0, 1, 2563, 0, 0, 0, 5, 2564, 10, 0, 0, 1, 209, 0, 0, 0, 3, 334, 167, 2567, 0, 1, 2565, 0, 0, 0, 1, 2567, 0, 0, 0, 1, 2571, 0, 0, 0, 5, 2570, 5, 0, 0, 1, 2568, 0, 0, 0, 1, 2573, 0, 0, 0, 1, 2569, 0, 0, 0, 1, 2572, 0, 0, 0, 1, 2588, 0, 0, 0, 1, 2571, 0, 0, 0, 3, 344, 172, 2578, 0, 5, 2577, 5, 0, 0, 1, 2575, 0, 0, 0, 1, 2580, 0, 0, 0, 1, 2576, 0, 0, 0, 1, 2579, 0, 0, 0, 1, 2581, 0, 0, 0, 1, 2578, 0, 0, 0, 5, 2585, 28, 0, 0, 5, 2584, 5, 0, 0, 1, 2582, 0, 0, 0, 1, 2587, 0, 0, 0, 1, 2583, 0, 0, 0, 1, 2586, 0, 0, 0, 1, 2589, 0, 0, 0, 1, 2585, 0, 0, 0, 1, 2574, 0, 0, 0, 1, 2589, 0, 0, 0, 1, 2591, 0, 0, 0, 5, 2592, 15, 0, 0, 1, 2590, 0, 0, 0, 1, 2592, 0, 0, 0, 1, 2596, 0, 0, 0, 5, 2595, 5, 0, 0, 1, 2593, 0, 0, 0, 1, 2598, 0, 0, 0, 1, 2594, 0, 0, 0, 1, 2597, 0, 0, 0, 1, 2599, 0, 0, 0, 1, 2596, 0, 0, 0, 259, 152, 76, 2600, 0, 1, 211, 0, 0, 0, 259, 214, 107, 2616, 0, 259, 344, 172, 2616, 0, 259, 218, 109, 2616, 0, 259, 220, 110, 2616, 0, 259, 272, 136, 2616, 0, 259, 242, 121, 2616, 0, 259, 244, 122, 2616, 0, 259, 216, 108, 2616, 0, 259, 246, 123, 2616, 0, 259, 248, 124, 2616, 0, 259, 250, 125, 2616, 0, 259, 254, 127, 2616, 0, 259, 264, 132, 2616, 0, 259, 270, 135, 2616, 0, 1, 2601, 0, 0, 0, 1, 2602, 0, 0, 0, 1, 2603, 0, 0, 0, 1, 2604, 0, 0, 0, 1, 2605, 0, 0, 0, 1, 2606, 0, 0, 0, 1, 2607, 0, 0, 0, 1, 2608, 0, 0, 0, 1, 2609, 0, 0, 0, 1, 2610, 0, 0, 0, 1, 2611, 0, 0, 0, 1, 2612, 0, 0, 0, 1, 2613, 0, 0, 0, 1, 2614, 0, 0, 0, 1, 213, 0, 0, 0, 5, 2621, 9, 0, 0, 5, 2620, 5, 0, 0, 1, 2618, 0, 0, 0, 1, 2623, 0, 0, 0, 1, 2619, 0, 0, 0, 1, 2622, 0, 0, 0, 1, 2624, 0, 0, 0, 1, 2621, 0, 0, 0, 3, 152, 76, 2628, 0, 5, 2627, 5, 0, 0, 1, 2625, 0, 0, 0, 1, 2630, 0, 0, 0, 1, 2626, 0, 0, 0, 1, 2629, 0, 0, 0, 1, 2631, 0, 0, 0, 1, 2628, 0, 0, 0, 5, 2632, 10, 0, 0, 1, 215, 0, 0, 0, 5, 2637, 11, 0, 0, 5, 2636, 5, 0, 0, 1, 2634, 0, 0, 0, 1, 2639, 0, 0, 0, 1, 2635, 0, 0, 0, 1, 2638, 0, 0, 0, 1, 2675, 0, 0, 0, 1, 2637, 0, 0, 0, 3, 152, 76, 2657, 0, 5, 2643, 5, 0, 0, 1, 2641, 0, 0, 0, 1, 2646, 0, 0, 0, 1, 2642, 0, 0, 0, 1, 2645, 0, 0, 0, 1, 2647, 0, 0, 0, 1, 2644, 0, 0, 0, 5, 2651, 8, 0, 0, 5, 2650, 5, 0, 0, 1, 2648, 0, 0, 0, 1, 2653, 0, 0, 0, 1, 2649, 0, 0, 0, 1, 2652, 0, 0, 0, 1, 2654, 0, 0, 0, 1, 2651, 0, 0, 0, 3, 152, 76, 2656, 0, 1, 2644, 0, 0, 0, 1, 2659, 0, 0, 0, 1, 2655, 0, 0, 0, 1, 2658, 0, 0, 0, 1, 2667, 0, 0, 0, 1, 2657, 0, 0, 0, 5, 2662, 5, 0, 0, 1, 2660, 0, 0, 0, 1, 2665, 0, 0, 0, 1, 2661, 0, 0, 0, 1, 2664, 0, 0, 0, 1, 2666, 0, 0, 0, 1, 2663, 0, 0, 0, 5, 2668, 8, 0, 0, 1, 2663, 0, 0, 0, 1, 2668, 0, 0, 0, 1, 2672, 0, 0, 0, 5, 2671, 5, 0, 0, 1, 2669, 0, 0, 0, 1, 2674, 0, 0, 0, 1, 2670, 0, 0, 0, 1, 2673, 0, 0, 0, 1, 2676, 0, 0, 0, 1, 2672, 0, 0, 0, 1, 2640, 0, 0, 0, 1, 2676, 0, 0, 0, 1, 2677, 0, 0, 0, 5, 2678, 12, 0, 0, 1, 217, 0, 0, 0, 7, 2680, 7, 0, 0, 1, 219, 0, 0, 0, 259, 222, 111, 2684, 0, 259, 224, 112, 2684, 0, 1, 2681, 0, 0, 0, 1, 2682, 0, 0, 0, 1, 221, 0, 0, 0, 5, 2690, 151, 0, 0, 3, 226, 113, 2689, 0, 3, 228, 114, 2689, 0, 1, 2686, 0, 0, 0, 1, 2687, 0, 0, 0, 1, 2692, 0, 0, 0, 1, 2688, 0, 0, 0, 1, 2691, 0, 0, 0, 1, 2693, 0, 0, 0, 1, 2690, 0, 0, 0, 5, 2694, 160, 0, 0, 1, 223, 0, 0, 0, 5, 2701, 152, 0, 0, 3, 230, 115, 2700, 0, 3, 232, 116, 2700, 0, 5, 2700, 166, 0, 0, 1, 2696, 0, 0, 0, 1, 2697, 0, 0, 0, 1, 2698, 0, 0, 0, 1, 2703, 0, 0, 0, 1, 2699, 0, 0, 0, 1, 2702, 0, 0, 0, 1, 2704, 0, 0, 0, 1, 2701, 0, 0, 0, 5, 2705, 165, 0, 0, 1, 225, 0, 0, 0, 7, 2707, 8, 0, 0, 1, 227, 0, 0, 0, 5, 2712, 164, 0, 0, 5, 2711, 5, 0, 0, 1, 2709, 0, 0, 0, 1, 2714, 0, 0, 0, 1, 2710, 0, 0, 0, 1, 2713, 0, 0, 0, 1, 2715, 0, 0, 0, 1, 2712, 0, 0, 0, 3, 152, 76, 2719, 0, 5, 2718, 5, 0, 0, 1, 2716, 0, 0, 0, 1, 2721, 0, 0, 0, 1, 2717, 0, 0, 0, 1, 2720, 0, 0, 0, 1, 2722, 0, 0, 0, 1, 2719, 0, 0, 0, 5, 2723, 14, 0, 0, 1, 229, 0, 0, 0, 7, 2725, 9, 0, 0, 1, 231, 0, 0, 0, 5, 2730, 169, 0, 0, 5, 2729, 5, 0, 0, 1, 2727, 0, 0, 0, 1, 2732, 0, 0, 0, 1, 2728, 0, 0, 0, 1, 2731, 0, 0, 0, 1, 2733, 0, 0, 0, 1, 2730, 0, 0, 0, 3, 152, 76, 2737, 0, 5, 2736, 5, 0, 0, 1, 2734, 0, 0, 0, 1, 2739, 0, 0, 0, 1, 2735, 0, 0, 0, 1, 2738, 0, 0, 0, 1, 2740, 0, 0, 0, 1, 2737, 0, 0, 0, 5, 2741, 14, 0, 0, 1, 233, 0, 0, 0, 5, 2746, 13, 0, 0, 5, 2745, 5, 0, 0, 1, 2743, 0, 0, 0, 1, 2748, 0, 0, 0, 1, 2744, 0, 0, 0, 1, 2747, 0, 0, 0, 1, 2765, 0, 0, 0, 1, 2746, 0, 0, 0, 3, 236, 118, 2751, 0, 1, 2749, 0, 0, 0, 1, 2751, 0, 0, 0, 1, 2755, 0, 0, 0, 5, 2754, 5, 0, 0, 1, 2752, 0, 0, 0, 1, 2757, 0, 0, 0, 1, 2753, 0, 0, 0, 1, 2756, 0, 0, 0, 1, 2758, 0, 0, 0, 1, 2755, 0, 0, 0, 5, 2762, 34, 0, 0, 5, 2761, 5, 0, 0, 1, 2759, 0, 0, 0, 1, 2764, 0, 0, 0, 1, 2760, 0, 0, 0, 1, 2763, 0, 0, 0, 1, 2766, 0, 0, 0, 1, 2762, 0, 0, 0, 1, 2750, 0, 0, 0, 1, 2766, 0, 0, 0, 1, 2767, 0, 0, 0, 3, 128, 64, 2771, 0, 5, 2770, 5, 0, 0, 1, 2768, 0, 0, 0, 1, 2773, 0, 0, 0, 1, 2769, 0, 0, 0, 1, 2772, 0, 0, 0, 1, 2774, 0, 0, 0, 1, 2771, 0, 0, 0, 5, 2775, 14, 0, 0, 1, 235, 0, 0, 0, 3, 238, 119, 2793, 0, 5, 2779, 5, 0, 0, 1, 2777, 0, 0, 0, 1, 2782, 0, 0, 0, 1, 2778, 0, 0, 0, 1, 2781, 0, 0, 0, 1, 2783, 0, 0, 0, 1, 2780, 0, 0, 0, 5, 2787, 8, 0, 0, 5, 2786, 5, 0, 0, 1, 2784, 0, 0, 0, 1, 2789, 0, 0, 0, 1, 2785, 0, 0, 0, 1, 2788, 0, 0, 0, 1, 2790, 0, 0, 0, 1, 2787, 0, 0, 0, 3, 238, 119, 2792, 0, 1, 2780, 0, 0, 0, 1, 2795, 0, 0, 0, 1, 2791, 0, 0, 0, 1, 2794, 0, 0, 0, 1, 2803, 0, 0, 0, 1, 2793, 0, 0, 0, 5, 2798, 5, 0, 0, 1, 2796, 0, 0, 0, 1, 2801, 0, 0, 0, 1, 2797, 0, 0, 0, 1, 2800, 0, 0, 0, 1, 2802, 0, 0, 0, 1, 2799, 0, 0, 0, 5, 2804, 8, 0, 0, 1, 2799, 0, 0, 0, 1, 2804, 0, 0, 0, 1, 237, 0, 0, 0, 259, 66, 33, 2824, 0, 3, 68, 34, 2821, 0, 5, 2809, 5, 0, 0, 1, 2807, 0, 0, 0, 1, 2812, 0, 0, 0, 1, 2808, 0, 0, 0, 1, 2811, 0, 0, 0, 1, 2813, 0, 0, 0, 1, 2810, 0, 0, 0, 5, 2817, 26, 0, 0, 5, 2816, 5, 0, 0, 1, 2814, 0, 0, 0, 1, 2819, 0, 0, 0, 1, 2815, 0, 0, 0, 1, 2818, 0, 0, 0, 1, 2820, 0, 0, 0, 1, 2817, 0, 0, 0, 259, 98, 49, 2822, 0, 1, 2810, 0, 0, 0, 1, 2822, 0, 0, 0, 1, 2824, 0, 0, 0, 1, 2805, 0, 0, 0, 1, 2806, 0, 0, 0, 1, 239, 0, 0, 0, 5, 2827, 124, 0, 0, 1, 2825, 0, 0, 0, 1, 2827, 0, 0, 0, 1, 2831, 0, 0, 0, 5, 2830, 5, 0, 0, 1, 2828, 0, 0, 0, 1, 2833, 0, 0, 0, 1, 2829, 0, 0, 0, 1, 2832, 0, 0, 0, 1, 2834, 0, 0, 0, 1, 2831, 0, 0, 0, 5, 2850, 76, 0, 0, 5, 2837, 5, 0, 0, 1, 2835, 0, 0, 0, 1, 2840, 0, 0, 0, 1, 2836, 0, 0, 0, 1, 2839, 0, 0, 0, 1, 2841, 0, 0, 0, 1, 2838, 0, 0, 0, 3, 98, 49, 2845, 0, 5, 2844, 5, 0, 0, 1, 2842, 0, 0, 0, 1, 2847, 0, 0, 0, 1, 2843, 0, 0, 0, 1, 2846, 0, 0, 0, 1, 2848, 0, 0, 0, 1, 2845, 0, 0, 0, 5, 2849, 7, 0, 0, 1, 2851, 0, 0, 0, 1, 2838, 0, 0, 0, 1, 2851, 0, 0, 0, 1, 2855, 0, 0, 0, 5, 2854, 5, 0, 0, 1, 2852, 0, 0, 0, 1, 2857, 0, 0, 0, 1, 2853, 0, 0, 0, 1, 2856, 0, 0, 0, 1, 2858, 0, 0, 0, 1, 2855, 0, 0, 0, 3, 78, 39, 2873, 0, 5, 2861, 5, 0, 0, 1, 2859, 0, 0, 0, 1, 2864, 0, 0, 0, 1, 2860, 0, 0, 0, 1, 2863, 0, 0, 0, 1, 2865, 0, 0, 0, 1, 2862, 0, 0, 0, 5, 2869, 26, 0, 0, 5, 2868, 5, 0, 0, 1, 2866, 0, 0, 0, 1, 2871, 0, 0, 0, 1, 2867, 0, 0, 0, 1, 2870, 0, 0, 0, 1, 2872, 0, 0, 0, 1, 2869, 0, 0, 0, 3, 98, 49, 2874, 0, 1, 2862, 0, 0, 0, 1, 2874, 0, 0, 0, 1, 2882, 0, 0, 0, 5, 2877, 5, 0, 0, 1, 2875, 0, 0, 0, 1, 2880, 0, 0, 0, 1, 2876, 0, 0, 0, 1, 2879, 0, 0, 0, 1, 2881, 0, 0, 0, 1, 2878, 0, 0, 0, 3, 46, 23, 2883, 0, 1, 2878, 0, 0, 0, 1, 2883, 0, 0, 0, 1, 2891, 0, 0, 0, 5, 2886, 5, 0, 0, 1, 2884, 0, 0, 0, 1, 2889, 0, 0, 0, 1, 2885, 0, 0, 0, 1, 2888, 0, 0, 0, 1, 2890, 0, 0, 0, 1, 2887, 0, 0, 0, 259, 64, 32, 2892, 0, 1, 2887, 0, 0, 0, 1, 2892, 0, 0, 0, 1, 241, 0, 0, 0, 259, 234, 117, 2896, 0, 259, 240, 120, 2896, 0, 1, 2893, 0, 0, 0, 1, 2894, 0, 0, 0, 1, 243, 0, 0, 0, 5, 2899, 116, 0, 0, 1, 2897, 0, 0, 0, 1, 2899, 0, 0, 0, 1, 2903, 0, 0, 0, 5, 2902, 5, 0, 0, 1, 2900, 0, 0, 0, 1, 2905, 0, 0, 0, 1, 2901, 0, 0, 0, 1, 2904, 0, 0, 0, 1, 2906, 0, 0, 0, 1, 2903, 0, 0, 0, 5, 2927, 77, 0, 0, 5, 2909, 5, 0, 0, 1, 2907, 0, 0, 0, 1, 2912, 0, 0, 0, 1, 2908, 0, 0, 0, 1, 2911, 0, 0, 0, 1, 2913, 0, 0, 0, 1, 2910, 0, 0, 0, 5, 2917, 26, 0, 0, 5, 2916, 5, 0, 0, 1, 2914, 0, 0, 0, 1, 2919, 0, 0, 0, 1, 2915, 0, 0, 0, 1, 2918, 0, 0, 0, 1, 2920, 0, 0, 0, 1, 2917, 0, 0, 0, 3, 32, 16, 2924, 0, 5, 2923, 5, 0, 0, 1, 2921, 0, 0, 0, 1, 2926, 0, 0, 0, 1, 2922, 0, 0, 0, 1, 2925, 0, 0, 0, 1, 2928, 0, 0, 0, 1, 2924, 0, 0, 0, 1, 2910, 0, 0, 0, 1, 2928, 0, 0, 0, 1, 2936, 0, 0, 0, 5, 2931, 5, 0, 0, 1, 2929, 0, 0, 0, 1, 2934, 0, 0, 0, 1, 2930, 0, 0, 0, 1, 2933, 0, 0, 0, 1, 2935, 0, 0, 0, 1, 2932, 0, 0, 0, 259, 26, 13, 2937, 0, 1, 2932, 0, 0, 0, 1, 2937, 0, 0, 0, 1, 245, 0, 0, 0, 7, 2939, 10, 0, 0, 1, 247, 0, 0, 0, 5, 2957, 86, 0, 0, 5, 2945, 47, 0, 0, 5, 2944, 5, 0, 0, 1, 2942, 0, 0, 0, 1, 2947, 0, 0, 0, 1, 2943, 0, 0, 0, 1, 2946, 0, 0, 0, 1, 2948, 0, 0, 0, 1, 2945, 0, 0, 0, 3, 98, 49, 2952, 0, 5, 2951, 5, 0, 0, 1, 2949, 0, 0, 0, 1, 2954, 0, 0, 0, 1, 2950, 0, 0, 0, 1, 2953, 0, 0, 0, 1, 2955, 0, 0, 0, 1, 2952, 0, 0, 0, 5, 2956, 48, 0, 0, 1, 2958, 0, 0, 0, 1, 2941, 0, 0, 0, 1, 2958, 0, 0, 0, 1, 2961, 0, 0, 0, 5, 2960, 41, 0, 0, 259, 344, 172, 2962, 0, 1, 2959, 0, 0, 0, 1, 2962, 0, 0, 0, 1, 2965, 0, 0, 0, 5, 2965, 62, 0, 0, 1, 2940, 0, 0, 0, 1, 2963, 0, 0, 0, 1, 249, 0, 0, 0, 5, 2970, 89, 0, 0, 5, 2969, 5, 0, 0, 1, 2967, 0, 0, 0, 1, 2972, 0, 0, 0, 1, 2968, 0, 0, 0, 1, 2971, 0, 0, 0, 1, 2973, 0, 0, 0, 1, 2970, 0, 0, 0, 5, 2977, 9, 0, 0, 5, 2976, 5, 0, 0, 1, 2974, 0, 0, 0, 1, 2979, 0, 0, 0, 1, 2975, 0, 0, 0, 1, 2978, 0, 0, 0, 1, 2980, 0, 0, 0, 1, 2977, 0, 0, 0, 3, 152, 76, 2984, 0, 5, 2983, 5, 0, 0, 1, 2981, 0, 0, 0, 1, 2986, 0, 0, 0, 1, 2982, 0, 0, 0, 1, 2985, 0, 0, 0, 1, 2987, 0, 0, 0, 1, 2984, 0, 0, 0, 5, 2991, 10, 0, 0, 5, 2990, 5, 0, 0, 1, 2988, 0, 0, 0, 1, 2993, 0, 0, 0, 1, 2989, 0, 0, 0, 1, 2992, 0, 0, 0, 1, 3025, 0, 0, 0, 1, 2991, 0, 0, 0, 259, 134, 67, 3026, 0, 3, 134, 67, 2997, 0, 1, 2995, 0, 0, 0, 1, 2997, 0, 0, 0, 1, 3001, 0, 0, 0, 5, 3000, 5, 0, 0, 1, 2998, 0, 0, 0, 1, 3003, 0, 0, 0, 1, 2999, 0, 0, 0, 1, 3002, 0, 0, 0, 1, 3005, 0, 0, 0, 1, 3001, 0, 0, 0, 5, 3006, 27, 0, 0, 1, 3004, 0, 0, 0, 1, 3006, 0, 0, 0, 1, 3010, 0, 0, 0, 5, 3009, 5, 0, 0, 1, 3007, 0, 0, 0, 1, 3012, 0, 0, 0, 1, 3008, 0, 0, 0, 1, 3011, 0, 0, 0, 1, 3013, 0, 0, 0, 1, 3010, 0, 0, 0, 5, 3017, 90, 0, 0, 5, 3016, 5, 0, 0, 1, 3014, 0, 0, 0, 1, 3019, 0, 0, 0, 1, 3015, 0, 0, 0, 1, 3018, 0, 0, 0, 1, 3022, 0, 0, 0, 1, 3017, 0, 0, 0, 259, 134, 67, 3023, 0, 5, 3023, 27, 0, 0, 1, 3020, 0, 0, 0, 1, 3021, 0, 0, 0, 1, 3026, 0, 0, 0, 5, 3026, 27, 0, 0, 1, 2994, 0, 0, 0, 1, 2996, 0, 0, 0, 1, 3024, 0, 0, 0, 1, 251, 0, 0, 0, 5, 3061, 9, 0, 0, 3, 334, 167, 3030, 0, 1, 3028, 0, 0, 0, 1, 3033, 0, 0, 0, 1, 3029, 0, 0, 0, 1, 3032, 0, 0, 0, 1, 3037, 0, 0, 0, 1, 3031, 0, 0, 0, 5, 3036, 5, 0, 0, 1, 3034, 0, 0, 0, 1, 3039, 0, 0, 0, 1, 3035, 0, 0, 0, 1, 3038, 0, 0, 0, 1, 3040, 0, 0, 0, 1, 3037, 0, 0, 0, 5, 3044, 78, 0, 0, 5, 3043, 5, 0, 0, 1, 3041, 0, 0, 0, 1, 3046, 0, 0, 0, 1, 3042, 0, 0, 0, 1, 3045, 0, 0, 0, 1, 3047, 0, 0, 0, 1, 3044, 0, 0, 0, 3, 66, 33, 3051, 0, 5, 3050, 5, 0, 0, 1, 3048, 0, 0, 0, 1, 3053, 0, 0, 0, 1, 3049, 0, 0, 0, 1, 3052, 0, 0, 0, 1, 3054, 0, 0, 0, 1, 3051, 0, 0, 0, 5, 3058, 28, 0, 0, 5, 3057, 5, 0, 0, 1, 3055, 0, 0, 0, 1, 3060, 0, 0, 0, 1, 3056, 0, 0, 0, 1, 3059, 0, 0, 0, 1, 3062, 0, 0, 0, 1, 3058, 0, 0, 0, 1, 3031, 0, 0, 0, 1, 3062, 0, 0, 0, 1, 3063, 0, 0, 0, 3, 152, 76, 3064, 0, 5, 3065, 10, 0, 0, 1, 253, 0, 0, 0, 5, 3070, 91, 0, 0, 5, 3069, 5, 0, 0, 1, 3067, 0, 0, 0, 1, 3072, 0, 0, 0, 1, 3068, 0, 0, 0, 1, 3071, 0, 0, 0, 1, 3074, 0, 0, 0, 1, 3070, 0, 0, 0, 3, 252, 126, 3075, 0, 1, 3073, 0, 0, 0, 1, 3075, 0, 0, 0, 1, 3079, 0, 0, 0, 5, 3078, 5, 0, 0, 1, 3076, 0, 0, 0, 1, 3081, 0, 0, 0, 1, 3077, 0, 0, 0, 1, 3080, 0, 0, 0, 1, 3082, 0, 0, 0, 1, 3079, 0, 0, 0, 5, 3086, 13, 0, 0, 5, 3085, 5, 0, 0, 1, 3083, 0, 0, 0, 1, 3088, 0, 0, 0, 1, 3084, 0, 0, 0, 1, 3087, 0, 0, 0, 1, 3098, 0, 0, 0, 1, 3086, 0, 0, 0, 3, 256, 128, 3093, 0, 5, 3092, 5, 0, 0, 1, 3090, 0, 0, 0, 1, 3095, 0, 0, 0, 1, 3091, 0, 0, 0, 1, 3094, 0, 0, 0, 1, 3097, 0, 0, 0, 1, 3093, 0, 0, 0, 1, 3089, 0, 0, 0, 1, 3100, 0, 0, 0, 1, 3096, 0, 0, 0, 1, 3099, 0, 0, 0, 1, 3104, 0, 0, 0, 1, 3098, 0, 0, 0, 5, 3103, 5, 0, 0, 1, 3101, 0, 0, 0, 1, 3106, 0, 0, 0, 1, 3102, 0, 0, 0, 1, 3105, 0, 0, 0, 1, 3107, 0, 0, 0, 1, 3104, 0, 0, 0, 5, 3108, 14, 0, 0, 1, 255, 0, 0, 0, 3, 258, 129, 3126, 0, 5, 3112, 5, 0, 0, 1, 3110, 0, 0, 0, 1, 3115, 0, 0, 0, 1, 3111, 0, 0, 0, 1, 3114, 0, 0, 0, 1, 3116, 0, 0, 0, 1, 3113, 0, 0, 0, 5, 3120, 8, 0, 0, 5, 3119, 5, 0, 0, 1, 3117, 0, 0, 0, 1, 3122, 0, 0, 0, 1, 3118, 0, 0, 0, 1, 3121, 0, 0, 0, 1, 3123, 0, 0, 0, 1, 3120, 0, 0, 0, 3, 258, 129, 3125, 0, 1, 3113, 0, 0, 0, 1, 3128, 0, 0, 0, 1, 3124, 0, 0, 0, 1, 3127, 0, 0, 0, 1, 3136, 0, 0, 0, 1, 3126, 0, 0, 0, 5, 3131, 5, 0, 0, 1, 3129, 0, 0, 0, 1, 3134, 0, 0, 0, 1, 3130, 0, 0, 0, 1, 3133, 0, 0, 0, 1, 3135, 0, 0, 0, 1, 3132, 0, 0, 0, 5, 3137, 8, 0, 0, 1, 3132, 0, 0, 0, 1, 3137, 0, 0, 0, 1, 3141, 0, 0, 0, 5, 3140, 5, 0, 0, 1, 3138, 0, 0, 0, 1, 3143, 0, 0, 0, 1, 3139, 0, 0, 0, 1, 3142, 0, 0, 0, 1, 3144, 0, 0, 0, 1, 3141, 0, 0, 0, 5, 3148, 34, 0, 0, 5, 3147, 5, 0, 0, 1, 3145, 0, 0, 0, 1, 3150, 0, 0, 0, 1, 3146, 0, 0, 0, 1, 3149, 0, 0, 0, 1, 3151, 0, 0, 0, 1, 3148, 0, 0, 0, 3, 134, 67, 3153, 0, 259, 148, 74, 3154, 0, 1, 3152, 0, 0, 0, 1, 3154, 0, 0, 0, 1, 3174, 0, 0, 0, 5, 3159, 90, 0, 0, 5, 3158, 5, 0, 0, 1, 3156, 0, 0, 0, 1, 3161, 0, 0, 0, 1, 3157, 0, 0, 0, 1, 3160, 0, 0, 0, 1, 3162, 0, 0, 0, 1, 3159, 0, 0, 0, 5, 3166, 34, 0, 0, 5, 3165, 5, 0, 0, 1, 3163, 0, 0, 0, 1, 3168, 0, 0, 0, 1, 3164, 0, 0, 0, 1, 3167, 0, 0, 0, 1, 3169, 0, 0, 0, 1, 3166, 0, 0, 0, 3, 134, 67, 3171, 0, 259, 148, 74, 3172, 0, 1, 3170, 0, 0, 0, 1, 3172, 0, 0, 0, 1, 3174, 0, 0, 0, 1, 3109, 0, 0, 0, 1, 3155, 0, 0, 0, 1, 257, 0, 0, 0, 259, 152, 76, 3179, 0, 259, 260, 130, 3179, 0, 259, 262, 131, 3179, 0, 1, 3175, 0, 0, 0, 1, 3176, 0, 0, 0, 1, 3177, 0, 0, 0, 1, 259, 0, 0, 0, 3, 280, 140, 3184, 0, 5, 3183, 5, 0, 0, 1, 3181, 0, 0, 0, 1, 3186, 0, 0, 0, 1, 3182, 0, 0, 0, 1, 3185, 0, 0, 0, 1, 3187, 0, 0, 0, 1, 3184, 0, 0, 0, 259, 152, 76, 3188, 0, 1, 261, 0, 0, 0, 3, 282, 141, 3193, 0, 5, 3192, 5, 0, 0, 1, 3190, 0, 0, 0, 1, 3195, 0, 0, 0, 1, 3191, 0, 0, 0, 1, 3194, 0, 0, 0, 1, 3196, 0, 0, 0, 1, 3193, 0, 0, 0, 259, 98, 49, 3197, 0, 1, 263, 0, 0, 0, 5, 3202, 92, 0, 0, 5, 3201, 5, 0, 0, 1, 3199, 0, 0, 0, 1, 3204, 0, 0, 0, 1, 3200, 0, 0, 0, 1, 3203, 0, 0, 0, 1, 3205, 0, 0, 0, 1, 3202, 0, 0, 0, 3, 136, 68, 3233, 0, 5, 3208, 5, 0, 0, 1, 3206, 0, 0, 0, 1, 3211, 0, 0, 0, 1, 3207, 0, 0, 0, 1, 3210, 0, 0, 0, 1, 3212, 0, 0, 0, 1, 3209, 0, 0, 0, 3, 266, 133, 3214, 0, 1, 3209, 0, 0, 0, 1, 3215, 0, 0, 0, 1, 3213, 0, 0, 0, 1, 3216, 0, 0, 0, 1, 3224, 0, 0, 0, 5, 3219, 5, 0, 0, 1, 3217, 0, 0, 0, 1, 3222, 0, 0, 0, 1, 3218, 0, 0, 0, 1, 3221, 0, 0, 0, 1, 3223, 0, 0, 0, 1, 3220, 0, 0, 0, 259, 268, 134, 3225, 0, 1, 3220, 0, 0, 0, 1, 3225, 0, 0, 0, 1, 3234, 0, 0, 0, 5, 3228, 5, 0, 0, 1, 3226, 0, 0, 0, 1, 3231, 0, 0, 0, 1, 3227, 0, 0, 0, 1, 3230, 0, 0, 0, 1, 3232, 0, 0, 0, 1, 3229, 0, 0, 0, 259, 268, 134, 3234, 0, 1, 3213, 0, 0, 0, 1, 3229, 0, 0, 0, 1, 265, 0, 0, 0, 5, 3239, 93, 0, 0, 5, 3238, 5, 0, 0, 1, 3236, 0, 0, 0, 1, 3241, 0, 0, 0, 1, 3237, 0, 0, 0, 1, 3240, 0, 0, 0, 1, 3242, 0, 0, 0, 1, 3239, 0, 0, 0, 5, 3246, 9, 0, 0, 3, 334, 167, 3245, 0, 1, 3243, 0, 0, 0, 1, 3248, 0, 0, 0, 1, 3244, 0, 0, 0, 1, 3247, 0, 0, 0, 1, 3249, 0, 0, 0, 1, 3246, 0, 0, 0, 3, 344, 172, 3250, 0, 5, 3251, 26, 0, 0, 3, 98, 49, 3259, 0, 5, 3254, 5, 0, 0, 1, 3252, 0, 0, 0, 1, 3257, 0, 0, 0, 1, 3253, 0, 0, 0, 1, 3256, 0, 0, 0, 1, 3258, 0, 0, 0, 1, 3255, 0, 0, 0, 5, 3260, 8, 0, 0, 1, 3255, 0, 0, 0, 1, 3260, 0, 0, 0, 1, 3261, 0, 0, 0, 5, 3265, 10, 0, 0, 5, 3264, 5, 0, 0, 1, 3262, 0, 0, 0, 1, 3267, 0, 0, 0, 1, 3263, 0, 0, 0, 1, 3266, 0, 0, 0, 1, 3268, 0, 0, 0, 1, 3265, 0, 0, 0, 259, 136, 68, 3269, 0, 1, 267, 0, 0, 0, 5, 3274, 94, 0, 0, 5, 3273, 5, 0, 0, 1, 3271, 0, 0, 0, 1, 3276, 0, 0, 0, 1, 3272, 0, 0, 0, 1, 3275, 0, 0, 0, 1, 3277, 0, 0, 0, 1, 3274, 0, 0, 0, 259, 136, 68, 3278, 0, 1, 269, 0, 0, 0, 5, 3283, 98, 0, 0, 5, 3282, 5, 0, 0, 1, 3280, 0, 0, 0, 1, 3285, 0, 0, 0, 1, 3281, 0, 0, 0, 1, 3284, 0, 0, 0, 1, 3286, 0, 0, 0, 1, 3283, 0, 0, 0, 259, 152, 76, 3296, 0, 7, 3289, 11, 0, 0, 259, 152, 76, 3290, 0, 1, 3288, 0, 0, 0, 1, 3290, 0, 0, 0, 1, 3296, 0, 0, 0, 5, 3296, 100, 0, 0, 5, 3296, 59, 0, 0, 5, 3296, 101, 0, 0, 5, 3296, 60, 0, 0, 1, 3279, 0, 0, 0, 1, 3287, 0, 0, 0, 1, 3291, 0, 0, 0, 1, 3292, 0, 0, 0, 1, 3293, 0, 0, 0, 1, 3294, 0, 0, 0, 1, 271, 0, 0, 0, 3, 122, 61, 3299, 0, 1, 3297, 0, 0, 0, 1, 3299, 0, 0, 0, 1, 3300, 0, 0, 0, 5, 3304, 38, 0, 0, 5, 3303, 5, 0, 0, 1, 3301, 0, 0, 0, 1, 3306, 0, 0, 0, 1, 3302, 0, 0, 0, 1, 3305, 0, 0, 0, 1, 3309, 0, 0, 0, 1, 3304, 0, 0, 0, 259, 344, 172, 3310, 0, 5, 3310, 74, 0, 0, 1, 3307, 0, 0, 0, 1, 3308, 0, 0, 0, 1, 273, 0, 0, 0, 7, 3312, 12, 0, 0, 1, 275, 0, 0, 0, 7, 3314, 13, 0, 0, 1, 277, 0, 0, 0, 7, 3316, 14, 0, 0, 1, 279, 0, 0, 0, 7, 3318, 15, 0, 0, 1, 281, 0, 0, 0, 7, 3320, 16, 0, 0, 1, 283, 0, 0, 0, 7, 3322, 17, 0, 0, 1, 285, 0, 0, 0, 7, 3324, 18, 0, 0, 1, 287, 0, 0, 0, 7, 3326, 19, 0, 0, 1, 289, 0, 0, 0, 5, 3333, 20, 0, 0, 5, 3333, 21, 0, 0, 5, 3333, 19, 0, 0, 5, 3333, 18, 0, 0, 259, 294, 147, 3333, 0, 1, 3327, 0, 0, 0, 1, 3328, 0, 0, 0, 1, 3329, 0, 0, 0, 1, 3330, 0, 0, 0, 1, 3331, 0, 0, 0, 1, 291, 0, 0, 0, 5, 3339, 20, 0, 0, 5, 3339, 21, 0, 0, 5, 3337, 25, 0, 0, 259, 294, 147, 3339, 0, 1, 3334, 0, 0, 0, 1, 3335, 0, 0, 0, 1, 3336, 0, 0, 0, 1, 293, 0, 0, 0, 7, 3341, 20, 0, 0, 1, 295, 0, 0, 0, 5, 3344, 5, 0, 0, 1, 3342, 0, 0, 0, 1, 3347, 0, 0, 0, 1, 3343, 0, 0, 0, 1, 3346, 0, 0, 0, 1, 3348, 0, 0, 0, 1, 3345, 0, 0, 0, 5, 3358, 7, 0, 0, 5, 3351, 5, 0, 0, 1, 3349, 0, 0, 0, 1, 3354, 0, 0, 0, 1, 3350, 0, 0, 0, 1, 3353, 0, 0, 0, 1, 3355, 0, 0, 0, 1, 3352, 0, 0, 0, 259, 298, 149, 3358, 0, 5, 3358, 38, 0, 0, 1, 3345, 0, 0, 0, 1, 3352, 0, 0, 0, 1, 3356, 0, 0, 0, 1, 297, 0, 0, 0, 5, 3360, 46, 0, 0, 5, 3361, 7, 0, 0, 1, 299, 0, 0, 0, 3, 334, 167, 3365, 0, 3, 304, 152, 3365, 0, 1, 3362, 0, 0, 0, 1, 3363, 0, 0, 0, 1, 3366, 0, 0, 0, 1, 3364, 0, 0, 0, 1, 3367, 0, 0, 0, 1, 301, 0, 0, 0, 3, 334, 167, 3371, 0, 3, 328, 164, 3371, 0, 1, 3368, 0, 0, 0, 1, 3369, 0, 0, 0, 1, 3372, 0, 0, 0, 1, 3370, 0, 0, 0, 1, 3373, 0, 0, 0, 1, 303, 0, 0, 0, 3, 310, 155, 3383, 0, 3, 312, 156, 3383, 0, 3, 314, 157, 3383, 0, 3, 322, 161, 3383, 0, 3, 324, 162, 3383, 0, 3, 326, 163, 3383, 0, 3, 328, 164, 3383, 0, 3, 332, 166, 3383, 0, 1, 3374, 0, 0, 0, 1, 3375, 0, 0, 0, 1, 3376, 0, 0, 0, 1, 3377, 0, 0, 0, 1, 3378, 0, 0, 0, 1, 3379, 0, 0, 0, 1, 3380, 0, 0, 0, 1, 3381, 0, 0, 0, 1, 3387, 0, 0, 0, 5, 3386, 5, 0, 0, 1, 3384, 0, 0, 0, 1, 3389, 0, 0, 0, 1, 3385, 0, 0, 0, 1, 3388, 0, 0, 0, 1, 305, 0, 0, 0, 1, 3387, 0, 0, 0, 3, 308, 154, 3392, 0, 1, 3390, 0, 0, 0, 1, 3393, 0, 0, 0, 1, 3391, 0, 0, 0, 1, 3394, 0, 0, 0, 1, 307, 0, 0, 0, 259, 334, 167, 3404, 0, 5, 3400, 124, 0, 0, 5, 3399, 5, 0, 0, 1, 3397, 0, 0, 0, 1, 3402, 0, 0, 0, 1, 3398, 0, 0, 0, 1, 3401, 0, 0, 0, 1, 3404, 0, 0, 0, 1, 3400, 0, 0, 0, 1, 3395, 0, 0, 0, 1, 3396, 0, 0, 0, 1, 309, 0, 0, 0, 7, 3406, 21, 0, 0, 1, 311, 0, 0, 0, 7, 3408, 22, 0, 0, 1, 313, 0, 0, 0, 7, 3410, 23, 0, 0, 1, 315, 0, 0, 0, 7, 3412, 24, 0, 0, 1, 317, 0, 0, 0, 3, 320, 160, 3415, 0, 1, 3413, 0, 0, 0, 1, 3416, 0, 0, 0, 1, 3414, 0, 0, 0, 1, 3417, 0, 0, 0, 1, 319, 0, 0, 0, 3, 330, 165, 3422, 0, 5, 3421, 5, 0, 0, 1, 3419, 0, 0, 0, 1, 3424, 0, 0, 0, 1, 3420, 0, 0, 0, 1, 3423, 0, 0, 0, 1, 3434, 0, 0, 0, 1, 3422, 0, 0, 0, 3, 316, 158, 3429, 0, 5, 3428, 5, 0, 0, 1, 3426, 0, 0, 0, 1, 3431, 0, 0, 0, 1, 3427, 0, 0, 0, 1, 3430, 0, 0, 0, 1, 3434, 0, 0, 0, 1, 3429, 0, 0, 0, 259, 334, 167, 3434, 0, 1, 3418, 0, 0, 0, 1, 3425, 0, 0, 0, 1, 3432, 0, 0, 0, 1, 321, 0, 0, 0, 7, 3436, 25, 0, 0, 1, 323, 0, 0, 0, 5, 3438, 129, 0, 0, 1, 325, 0, 0, 0, 7, 3440, 26, 0, 0, 1, 327, 0, 0, 0, 7, 3442, 27, 0, 0, 1, 329, 0, 0, 0, 5, 3444, 134, 0, 0, 1, 331, 0, 0, 0, 7, 3446, 28, 0, 0, 1, 333, 0, 0, 0, 3, 336, 168, 3450, 0, 3, 338, 169, 3450, 0, 1, 3447, 0, 0, 0, 1, 3448, 0, 0, 0, 1, 3454, 0, 0, 0, 5, 3453, 5, 0, 0, 1, 3451, 0, 0, 0, 1, 3456, 0, 0, 0, 1, 3452, 0, 0, 0, 1, 3455, 0, 0, 0, 1, 335, 0, 0, 0, 1, 3454, 0, 0, 0, 3, 340, 170, 3461, 0, 5, 3460, 5, 0, 0, 1, 3458, 0, 0, 0, 1, 3463, 0, 0, 0, 1, 3459, 0, 0, 0, 1, 3462, 0, 0, 0, 1, 3467, 0, 0, 0, 1, 3461, 0, 0, 0, 5, 3467, 41, 0, 0, 5, 3467, 43, 0, 0, 1, 3457, 0, 0, 0, 1, 3464, 0, 0, 0, 1, 3465, 0, 0, 0, 1, 3468, 0, 0, 0, 259, 342, 171, 3469, 0, 1, 337, 0, 0, 0, 3, 340, 170, 3474, 0, 5, 3473, 5, 0, 0, 1, 3471, 0, 0, 0, 1, 3476, 0, 0, 0, 1, 3472, 0, 0, 0, 1, 3475, 0, 0, 0, 1, 3480, 0, 0, 0, 1, 3474, 0, 0, 0, 5, 3480, 41, 0, 0, 5, 3480, 43, 0, 0, 1, 3470, 0, 0, 0, 1, 3477, 0, 0, 0, 1, 3478, 0, 0, 0, 1, 3481, 0, 0, 0, 5, 3483, 11, 0, 0, 3, 342, 171, 3484, 0, 1, 3482, 0, 0, 0, 1, 3485, 0, 0, 0, 1, 3483, 0, 0, 0, 1, 3486, 0, 0, 0, 1, 3487, 0, 0, 0, 5, 3488, 12, 0, 0, 1, 339, 0, 0, 0, 7, 3490, 0, 0, 0, 7, 3494, 29, 0, 0, 5, 3493, 5, 0, 0, 1, 3491, 0, 0, 0, 1, 3496, 0, 0, 0, 1, 3492, 0, 0, 0, 1, 3495, 0, 0, 0, 1, 3497, 0, 0, 0, 1, 3494, 0, 0, 0, 5, 3498, 26, 0, 0, 1, 341, 0, 0, 0, 259, 36, 18, 3502, 0, 259, 106, 53, 3502, 0, 1, 3499, 0, 0, 0, 1, 3500, 0, 0, 0, 1, 343, 0, 0, 0, 7, 3504, 30, 0, 0, 1, 345, 0, 0, 0, 3, 344, 172, 3516, 0, 5, 3508, 5, 0, 0, 1, 3506, 0, 0, 0, 1, 3511, 0, 0, 0, 1, 3507, 0, 0, 0, 1, 3510, 0, 0, 0, 1, 3512, 0, 0, 0, 1, 3509, 0, 0, 0, 5, 3513, 7, 0, 0, 3, 344, 172, 3515, 0, 1, 3509, 0, 0, 0, 1, 3518, 0, 0, 0, 1, 3514, 0, 0, 0, 1, 3517, 0, 0, 0, 1, 347, 0, 0, 0, 1, 3516, 0, 0, 0, 0, 2, 1, 0, 2, 2, 1, 1, 2, 2, 3, 1, 1, 4, 2, 4, 1, 1, 6, 2, 5, 1, 1, 8, 2, 6, 2, 1, 10, 2, 8, 1, 1, 12, 2, 9, 2, 0, 14, 0, 11, 1, 0, 14, 0, 12, 1, 0, 14, 0, 13, 2, 1, 14, 2, 15, 2, 1, 16, 2, 17, 1, 1, 18, 2, 18, 2, 1, 20, 2, 20, 1, 1, 22, 2, 21, 2, 1, 24, 2, 23, 2, 1, 26, 2, 25, 1, 1, 28, 2, 26, 1, 1, 30, 2, 27, 2, 1, 32, 2, 29, 1, 1, 34, 2, 30, 1, 1, 36, 2, 31, 2, 0, 38, 0, 33, 1, 1, 38, 2, 34, 2, 1, 40, 2, 36, 1, 1, 42, 2, 37, 1, 0, 44, 0, 38, 1, 0, 44, 0, 39, 1, 0, 44, 0, 40, 1, 1, 44, 2, 41, 7, 2, 46, 3, 41, 41, 43, 43, 78, 79, 85, 86, 45, 46, 41, 42, 5, 5, 27, 27, 36, 37, 137, 137, 140, 147, 161, 163, 166, 168, 61, 61, 85, 85, 58, 58, 99, 99, 29, 33, 51, 52, 54, 55, 47, 50, 104, 104, 106, 106, 103, 103, 105, 105, 18, 19, 15, 17, 53, 53, 102, 102, 24, 25, 113, 118, 125, 125, 130, 130, 109, 112, 104, 104, 107, 107, 119, 124, 126, 128, 131, 133, 135, 136, 64, 71, 63, 71, 73, 73, 81, 84, 88, 88, 93, 94, 107, 136, 148, 148, 0, 2560, 0, 0, 0, 0, 49152, 0, 0, 0, 6291456, 0, 0, 24576, 0, 0, 0, 1536, 0, 0, 134217760, 0, 0, 0, 0, 48, 0, 0, 0, 536870912, 2097152, 0, 0, 67108864, 0, 8, 3758096384, 3, 0, 0, 0, 14155776, 0, 0, 0, 491520, 0, 0, 0, 0, 0, 1280, 0, 0, 0, 640, 786432, 0, 0, 0, 229376, 0, 0, 0, 0, 2097152, 0, 64, 50331648, 0, 0, 0, 0, 0, 0, 8257536, 0, 0, 0, 122880, 0, 0, 0, 2304, 0, 0, 0, 528482304, 0, 0, 255, 0, 0, 2147483648, 1629356799, 4294965248, 1049087, 0, 349, 354, 360, 368, 374, 379, 385, 395, 404, 411, 418, 425, 430, 435, 441, 443, 448, 456, 459, 466, 469, 475, 482, 486, 491, 498, 508, 511, 518, 521, 524, 529, 536, 540, 545, 549, 554, 561, 565, 570, 574, 579, 586, 590, 593, 599, 602, 610, 617, 626, 633, 640, 646, 652, 656, 658, 663, 669, 672, 677, 685, 692, 699, 703, 709, 716, 722, 733, 737, 743, 751, 757, 764, 769, 776, 785, 792, 799, 805, 811, 815, 820, 826, 831, 838, 845, 849, 855, 862, 869, 875, 881, 888, 895, 902, 906, 913, 919, 925, 931, 935, 940, 947, 951, 956, 963, 967, 972, 976, 982, 989, 996, 1002, 1008, 1012, 1014, 1019, 1025, 1031, 1038, 1042, 1045, 1051, 1055, 1060, 1067, 1072, 1077, 1084, 1091, 1098, 1102, 1107, 1111, 1116, 1120, 1127, 1131, 1136, 1142, 1149, 1156, 1160, 1166, 1173, 1180, 1186, 1192, 1196, 1201, 1207, 1213, 1217, 1222, 1229, 1234, 1239, 1244, 1249, 1253, 1258, 1265, 1270, 1272, 1277, 1281, 1286, 1290, 1295, 1299, 1302, 1305, 1310, 1314, 1317, 1319, 1325, 1331, 1337, 1344, 1351, 1358, 1362, 1367, 1371, 1374, 1380, 1387, 1394, 1398, 1403, 1410, 1417, 1421, 1426, 1431, 1437, 1444, 1451, 1457, 1463, 1467, 1469, 1474, 1480, 1486, 1493, 1497, 1503, 1510, 1514, 1520, 1527, 1533, 1539, 1546, 1553, 1557, 1562, 1566, 1569, 1575, 1582, 1589, 1593, 1598, 1602, 1608, 1617, 1621, 1626, 1633, 1637, 1642, 1651, 1658, 1664, 1670, 1674, 1680, 1683, 1689, 1693, 1698, 1702, 1705, 1712, 1716, 1720, 1725, 1731, 1739, 1746, 1752, 1759, 1763, 1766, 1770, 1775, 1781, 1785, 1791, 1798, 1801, 1807, 1814, 1823, 1828, 1833, 1840, 1845, 1849, 1855, 1859, 1864, 1873, 1880, 1886, 1891, 1897, 1902, 1907, 1913, 1917, 1922, 1929, 1933, 1937, 1945, 1948, 1951, 1955, 1957, 1964, 1971, 1976, 1982, 1989, 1997, 2003, 2010, 2015, 2023, 2027, 2033, 2042, 2047, 2053, 2057, 2062, 2069, 2082, 2087, 2096, 2102, 2110, 2117, 2123, 2130, 2137, 2143, 2151, 2158, 2166, 2173, 2180, 2188, 2197, 2202, 2204, 2211, 2218, 2225, 2236, 2243, 2251, 2257, 2265, 2272, 2280, 2287, 2294, 2301, 2308, 2314, 2325, 2328, 2334, 2342, 2349, 2355, 2362, 2369, 2375, 2382, 2390, 2396, 2403, 2410, 2416, 2422, 2426, 2431, 2440, 2446, 2449, 2452, 2456, 2461, 2465, 2470, 2479, 2486, 2493, 2499, 2505, 2509, 2514, 2523, 2530, 2537, 2543, 2549, 2553, 2558, 2561, 2566, 2571, 2578, 2585, 2588, 2591, 2596, 2615, 2621, 2628, 2637, 2644, 2651, 2657, 2663, 2667, 2672, 2675, 2683, 2688, 2690, 2699, 2701, 2712, 2719, 2730, 2737, 2746, 2750, 2755, 2762, 2765, 2771, 2780, 2787, 2793, 2799, 2803, 2810, 2817, 2821, 2823, 2826, 2831, 2838, 2845, 2850, 2855, 2862, 2869, 2873, 2878, 2882, 2887, 2891, 2895, 2898, 2903, 2910, 2917, 2924, 2927, 2932, 2936, 2945, 2952, 2957, 2961, 2964, 2970, 2977, 2984, 2991, 2996, 3001, 3005, 3010, 3017, 3022, 3025, 3031, 3037, 3044, 3051, 3058, 3061, 3070, 3074, 3079, 3086, 3093, 3098, 3104, 3113, 3120, 3126, 3132, 3136, 3141, 3148, 3153, 3159, 3166, 3171, 3173, 3178, 3184, 3193, 3202, 3209, 3215, 3220, 3224, 3229, 3233, 3239, 3246, 3255, 3259, 3265, 3274, 3283, 3289, 3295, 3298, 3304, 3309, 3332, 3338, 3345, 3352, 3357, 3364, 3366, 3370, 3372, 3382, 3387, 3393, 3400, 3403, 3416, 3422, 3429, 3433, 3449, 3454, 3461, 3466, 3474, 3479, 3485, 3494, 3501, 3509, 3516, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347]; -static ATN_CELL: OnceLock = OnceLock::new(); - -/// Validates and caches the packed grammar ATN for all parser instances. -fn atn() -> &'static ParserAtn { - ATN_CELL.get_or_init(|| { - ParserAtn::from_static(PARSER_ATN_DATA) - .unwrap_or_else(|error| panic!("generated parser ATN is incompatible with this runtime: {error}")) - }) -} - -/// Borrows the validated packed parser ATN embedded in this module. -pub fn parser_atn() -> &'static ParserAtn { - atn() -} - -antlr4_runtime::__antlr4_rust_parser_entry_points! { - parser: KotlinParser, - output: KotlinParserParseOutput, - validated_tree: KotlinValidatedTree, - validation_error: KotlinValidationError, - validate_tree: validate_tree_structure, -} - -/// Generated parser. Each grammar rule is exposed as a public method. -/// -/// Pick an entry-rule method that matches the grammar's intended -/// top-level construct for the input being parsed. The generator can -/// infer entry candidates from call paths that reach explicit `EOF` -/// matches, from parser rules that no other rule calls, and from -/// configured entry rules. It cannot infer the semantic choice -/// between multiple candidates. -/// -/// Likely parser entry-rule methods: -/// - `kotlin_file()` -/// - `script()` -/// -/// All parser rule methods: -/// - `kotlin_file()` -/// - `script()` -/// - `shebang_line()` -/// - `file_annotation()` -/// - `package_header()` -/// - `import_list()` -/// - `import_header()` -/// - `import_alias()` -/// - `top_level_object()` -/// - `type_alias()` -/// - `declaration()` -/// - `class_declaration()` -/// - `primary_constructor()` -/// - `class_body()` -/// - `class_parameters()` -/// - `class_parameter()` -/// - `delegation_specifiers()` -/// - `delegation_specifier()` -/// - `constructor_invocation()` -/// - `annotated_delegation_specifier()` -/// - `explicit_delegation()` -/// - `type_parameters()` -/// - `type_parameter()` -/// - `type_constraints()` -/// - `type_constraint()` -/// - `class_member_declarations()` -/// - `class_member_declaration()` -/// - `anonymous_initializer()` -/// - `companion_object()` -/// - `function_value_parameters()` -/// - `function_value_parameter()` -/// - `function_declaration()` -/// - `function_body()` -/// - `variable_declaration()` -/// - `multi_variable_declaration()` -/// - `property_declaration()` -/// - `property_delegate()` -/// - `getter()` -/// - `setter()` -/// - `parameters_with_optional_type()` -/// - `function_value_parameter_with_optional_type()` -/// - `parameter_with_optional_type()` -/// - `parameter()` -/// - `object_declaration()` -/// - `secondary_constructor()` -/// - `constructor_delegation_call()` -/// - `enum_class_body()` -/// - `enum_entries()` -/// - `enum_entry()` -/// - `r#type()` -/// - `type_reference()` -/// - `nullable_type()` -/// - `quest()` -/// - `user_type()` -/// - `simple_user_type()` -/// - `type_projection()` -/// - `type_projection_modifiers()` -/// - `type_projection_modifier()` -/// - `function_type()` -/// - `function_type_parameters()` -/// - `parenthesized_type()` -/// - `receiver_type()` -/// - `parenthesized_user_type()` -/// - `definitely_non_nullable_type()` -/// - `statements()` -/// - `statement()` -/// - `label()` -/// - `control_structure_body()` -/// - `block()` -/// - `loop_statement()` -/// - `for_statement()` -/// - `while_statement()` -/// - `do_while_statement()` -/// - `assignment()` -/// - `semi()` -/// - `semis()` -/// - `expression()` -/// - `disjunction()` -/// - `conjunction()` -/// - `equality()` -/// - `comparison()` -/// - `generic_call_like_comparison()` -/// - `infix_operation()` -/// - `elvis_expression()` -/// - `elvis()` -/// - `infix_function_call()` -/// - `range_expression()` -/// - `additive_expression()` -/// - `multiplicative_expression()` -/// - `as_expression()` -/// - `prefix_unary_expression()` -/// - `unary_prefix()` -/// - `postfix_unary_expression()` -/// - `postfix_unary_suffix()` -/// - `directly_assignable_expression()` -/// - `parenthesized_directly_assignable_expression()` -/// - `assignable_expression()` -/// - `parenthesized_assignable_expression()` -/// - `assignable_suffix()` -/// - `indexing_suffix()` -/// - `navigation_suffix()` -/// - `call_suffix()` -/// - `annotated_lambda()` -/// - `type_arguments()` -/// - `value_arguments()` -/// - `value_argument()` -/// - `primary_expression()` -/// - `parenthesized_expression()` -/// - `collection_literal()` -/// - `literal_constant()` -/// - `string_literal()` -/// - `line_string_literal()` -/// - `multi_line_string_literal()` -/// - `line_string_content()` -/// - `line_string_expression()` -/// - `multi_line_string_content()` -/// - `multi_line_string_expression()` -/// - `lambda_literal()` -/// - `lambda_parameters()` -/// - `lambda_parameter()` -/// - `anonymous_function()` -/// - `function_literal()` -/// - `object_literal()` -/// - `this_expression()` -/// - `super_expression()` -/// - `if_expression()` -/// - `when_subject()` -/// - `when_expression()` -/// - `when_entry()` -/// - `when_condition()` -/// - `range_test()` -/// - `type_test()` -/// - `try_expression()` -/// - `catch_block()` -/// - `finally_block()` -/// - `jump_expression()` -/// - `callable_reference()` -/// - `assignment_and_operator()` -/// - `equality_operator()` -/// - `comparison_operator()` -/// - `in_operator()` -/// - `is_operator()` -/// - `additive_operator()` -/// - `multiplicative_operator()` -/// - `as_operator()` -/// - `prefix_unary_operator()` -/// - `postfix_unary_operator()` -/// - `excl()` -/// - `member_access_operator()` -/// - `safe_nav()` -/// - `modifiers()` -/// - `parameter_modifiers()` -/// - `modifier()` -/// - `type_modifiers()` -/// - `type_modifier()` -/// - `class_modifier()` -/// - `member_modifier()` -/// - `visibility_modifier()` -/// - `variance_modifier()` -/// - `type_parameter_modifiers()` -/// - `type_parameter_modifier()` -/// - `function_modifier()` -/// - `property_modifier()` -/// - `inheritance_modifier()` -/// - `parameter_modifier()` -/// - `reification_modifier()` -/// - `platform_modifier()` -/// - `annotation()` -/// - `single_annotation()` -/// - `multi_annotation()` -/// - `annotation_use_site_target()` -/// - `unescaped_annotation()` -/// - `simple_identifier()` -/// - `identifier()` -#[derive(Debug)] -pub struct KotlinParser -where - L: TokenSource, - H: antlr4_runtime::SemanticHooks, -{ - base: BaseParser, - simulator: Option>, - generated_only: bool, - adaptive_atn: antlr4_runtime::generated::AdaptiveAtnRetryState<0>, -} - -impl KotlinParser -where - L: TokenSource, -{ - pub fn new(input: CommonTokenStream) -> Self { - Self::with_hooks(input, antlr4_runtime::NoSemanticHooks) - } -} - -impl KotlinParser -where - L: TokenSource, - H: antlr4_runtime::SemanticHooks, -{ - pub fn with_hooks(input: CommonTokenStream, hooks: H) -> Self { - let grammar_metadata = metadata(); - let data = grammar_metadata.recognizer_data(); - let mut base = BaseParser::with_semantic_hooks(input, data, hooks); - base.set_unknown_predicate_policy(antlr4_runtime::UnknownSemanticPolicy::Error); - Self { - base, - simulator: None, - generated_only: std::env::var_os("ANTLR4_RUST_GENERATED_ONLY").is_some(), - adaptive_atn: antlr4_runtime::generated::AdaptiveAtnRetryState::new(), - } - } - - const __GENERATED_RULE_BODIES: [Option>; 174] = [ - Some(Self::parse_generated_rule_0), - Some(Self::parse_generated_rule_1), - Some(Self::parse_generated_rule_2), - Some(Self::parse_generated_rule_3), - Some(Self::parse_generated_rule_4), - Some(Self::parse_generated_rule_5), - Some(Self::parse_generated_rule_6), - Some(Self::parse_generated_rule_7), - Some(Self::parse_generated_rule_8), - Some(Self::parse_generated_rule_9), - Some(Self::parse_generated_rule_10), - Some(Self::parse_generated_rule_11), - Some(Self::parse_generated_rule_12), - Some(Self::parse_generated_rule_13), - Some(Self::parse_generated_rule_14), - Some(Self::parse_generated_rule_15), - Some(Self::parse_generated_rule_16), - Some(Self::parse_generated_rule_17), - Some(Self::parse_generated_rule_18), - Some(Self::parse_generated_rule_19), - Some(Self::parse_generated_rule_20), - Some(Self::parse_generated_rule_21), - Some(Self::parse_generated_rule_22), - Some(Self::parse_generated_rule_23), - Some(Self::parse_generated_rule_24), - Some(Self::parse_generated_rule_25), - Some(Self::parse_generated_rule_26), - Some(Self::parse_generated_rule_27), - Some(Self::parse_generated_rule_28), - Some(Self::parse_generated_rule_29), - Some(Self::parse_generated_rule_30), - Some(Self::parse_generated_rule_31), - Some(Self::parse_generated_rule_32), - Some(Self::parse_generated_rule_33), - Some(Self::parse_generated_rule_34), - Some(Self::parse_generated_rule_35), - Some(Self::parse_generated_rule_36), - Some(Self::parse_generated_rule_37), - Some(Self::parse_generated_rule_38), - Some(Self::parse_generated_rule_39), - Some(Self::parse_generated_rule_40), - Some(Self::parse_generated_rule_41), - Some(Self::parse_generated_rule_42), - Some(Self::parse_generated_rule_43), - Some(Self::parse_generated_rule_44), - Some(Self::parse_generated_rule_45), - Some(Self::parse_generated_rule_46), - Some(Self::parse_generated_rule_47), - Some(Self::parse_generated_rule_48), - Some(Self::parse_generated_rule_49), - Some(Self::parse_generated_rule_50), - Some(Self::parse_generated_rule_51), - Some(Self::parse_generated_rule_52), - Some(Self::parse_generated_rule_53), - Some(Self::parse_generated_rule_54), - Some(Self::parse_generated_rule_55), - Some(Self::parse_generated_rule_56), - Some(Self::parse_generated_rule_57), - Some(Self::parse_generated_rule_58), - Some(Self::parse_generated_rule_59), - Some(Self::parse_generated_rule_60), - Some(Self::parse_generated_rule_61), - Some(Self::parse_generated_rule_62), - Some(Self::parse_generated_rule_63), - Some(Self::parse_generated_rule_64), - Some(Self::parse_generated_rule_65), - Some(Self::parse_generated_rule_66), - Some(Self::parse_generated_rule_67), - Some(Self::parse_generated_rule_68), - Some(Self::parse_generated_rule_69), - Some(Self::parse_generated_rule_70), - Some(Self::parse_generated_rule_71), - Some(Self::parse_generated_rule_72), - Some(Self::parse_generated_rule_73), - Some(Self::parse_generated_rule_74), - Some(Self::parse_generated_rule_75), - Some(Self::parse_generated_rule_76), - Some(Self::parse_generated_rule_77), - Some(Self::parse_generated_rule_78), - Some(Self::parse_generated_rule_79), - Some(Self::parse_generated_rule_80), - Some(Self::parse_generated_rule_81), - Some(Self::parse_generated_rule_82), - Some(Self::parse_generated_rule_83), - Some(Self::parse_generated_rule_84), - Some(Self::parse_generated_rule_85), - Some(Self::parse_generated_rule_86), - Some(Self::parse_generated_rule_87), - Some(Self::parse_generated_rule_88), - Some(Self::parse_generated_rule_89), - Some(Self::parse_generated_rule_90), - Some(Self::parse_generated_rule_91), - Some(Self::parse_generated_rule_92), - Some(Self::parse_generated_rule_93), - Some(Self::parse_generated_rule_94), - Some(Self::parse_generated_rule_95), - Some(Self::parse_generated_rule_96), - Some(Self::parse_generated_rule_97), - Some(Self::parse_generated_rule_98), - Some(Self::parse_generated_rule_99), - Some(Self::parse_generated_rule_100), - Some(Self::parse_generated_rule_101), - Some(Self::parse_generated_rule_102), - Some(Self::parse_generated_rule_103), - Some(Self::parse_generated_rule_104), - Some(Self::parse_generated_rule_105), - Some(Self::parse_generated_rule_106), - Some(Self::parse_generated_rule_107), - Some(Self::parse_generated_rule_108), - Some(Self::parse_generated_rule_109), - Some(Self::parse_generated_rule_110), - Some(Self::parse_generated_rule_111), - Some(Self::parse_generated_rule_112), - Some(Self::parse_generated_rule_113), - Some(Self::parse_generated_rule_114), - Some(Self::parse_generated_rule_115), - Some(Self::parse_generated_rule_116), - Some(Self::parse_generated_rule_117), - Some(Self::parse_generated_rule_118), - Some(Self::parse_generated_rule_119), - Some(Self::parse_generated_rule_120), - Some(Self::parse_generated_rule_121), - Some(Self::parse_generated_rule_122), - Some(Self::parse_generated_rule_123), - Some(Self::parse_generated_rule_124), - Some(Self::parse_generated_rule_125), - Some(Self::parse_generated_rule_126), - Some(Self::parse_generated_rule_127), - Some(Self::parse_generated_rule_128), - Some(Self::parse_generated_rule_129), - Some(Self::parse_generated_rule_130), - Some(Self::parse_generated_rule_131), - Some(Self::parse_generated_rule_132), - Some(Self::parse_generated_rule_133), - Some(Self::parse_generated_rule_134), - Some(Self::parse_generated_rule_135), - Some(Self::parse_generated_rule_136), - Some(Self::parse_generated_rule_137), - Some(Self::parse_generated_rule_138), - Some(Self::parse_generated_rule_139), - Some(Self::parse_generated_rule_140), - Some(Self::parse_generated_rule_141), - Some(Self::parse_generated_rule_142), - Some(Self::parse_generated_rule_143), - Some(Self::parse_generated_rule_144), - Some(Self::parse_generated_rule_145), - Some(Self::parse_generated_rule_146), - Some(Self::parse_generated_rule_147), - Some(Self::parse_generated_rule_148), - Some(Self::parse_generated_rule_149), - Some(Self::parse_generated_rule_150), - Some(Self::parse_generated_rule_151), - Some(Self::parse_generated_rule_152), - Some(Self::parse_generated_rule_153), - Some(Self::parse_generated_rule_154), - Some(Self::parse_generated_rule_155), - Some(Self::parse_generated_rule_156), - Some(Self::parse_generated_rule_157), - Some(Self::parse_generated_rule_158), - Some(Self::parse_generated_rule_159), - Some(Self::parse_generated_rule_160), - Some(Self::parse_generated_rule_161), - Some(Self::parse_generated_rule_162), - Some(Self::parse_generated_rule_163), - Some(Self::parse_generated_rule_164), - Some(Self::parse_generated_rule_165), - Some(Self::parse_generated_rule_166), - Some(Self::parse_generated_rule_167), - Some(Self::parse_generated_rule_168), - Some(Self::parse_generated_rule_169), - Some(Self::parse_generated_rule_170), - Some(Self::parse_generated_rule_171), - Some(Self::parse_generated_rule_172), - Some(Self::parse_generated_rule_173), - ]; - - #[allow(dead_code)] - #[inline(always)] - fn dispatch_generated_rule(&mut self, rule_index: usize, precedence: i32, allow_fallback: bool) -> Result { - let body = Self::__GENERATED_RULE_BODIES.get(rule_index).copied().flatten().expect("generated rule dispatch target"); - antlr4_runtime::generated::dispatch_generated_rule(self, rule_index, precedence, allow_fallback, body) - } - - #[allow(dead_code)] - fn parse_generated_rule(&mut self, rule_index: usize, precedence: i32, allow_fallback: bool) -> Option> { - let _body = Self::__GENERATED_RULE_BODIES.get(rule_index).copied().flatten()?; - match rule_index { - 11 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(11, precedence, allow_fallback)), - 11 => None, - 12 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(12, precedence, allow_fallback)), - 12 => None, - 14 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(14, precedence, allow_fallback)), - 14 => None, - 15 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(15, precedence, allow_fallback)), - 15 => None, - 16 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(16, precedence, allow_fallback)), - 16 => None, - 17 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(17, precedence, allow_fallback)), - 17 => None, - 19 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(19, precedence, allow_fallback)), - 19 => None, - 20 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(20, precedence, allow_fallback)), - 20 => None, - 28 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(28, precedence, allow_fallback)), - 28 => None, - 29 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(29, precedence, allow_fallback)), - 29 => None, - 30 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(30, precedence, allow_fallback)), - 30 => None, - 31 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(31, precedence, allow_fallback)), - 31 => None, - 35 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(35, precedence, allow_fallback)), - 35 => None, - 38 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(38, precedence, allow_fallback)), - 38 => None, - 39 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(39, precedence, allow_fallback)), - 39 => None, - 40 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(40, precedence, allow_fallback)), - 40 => None, - 43 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(43, precedence, allow_fallback)), - 43 => None, - 44 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(44, precedence, allow_fallback)), - 44 => None, - 46 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(46, precedence, allow_fallback)), - 46 => None, - 47 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(47, precedence, allow_fallback)), - 47 => None, - 48 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(48, precedence, allow_fallback)), - 48 => None, - 70 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(70, precedence, allow_fallback)), - 70 => None, - 71 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(71, precedence, allow_fallback)), - 71 => None, - 72 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(72, precedence, allow_fallback)), - 72 => None, - 76 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(76, precedence, allow_fallback)), - 76 => None, - 77 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(77, precedence, allow_fallback)), - 77 => None, - 78 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(78, precedence, allow_fallback)), - 78 => None, - 79 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(79, precedence, allow_fallback)), - 79 => None, - 80 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(80, precedence, allow_fallback)), - 80 => None, - 81 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(81, precedence, allow_fallback)), - 81 => None, - 82 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(82, precedence, allow_fallback)), - 82 => None, - 83 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(83, precedence, allow_fallback)), - 83 => None, - 85 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(85, precedence, allow_fallback)), - 85 => None, - 86 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(86, precedence, allow_fallback)), - 86 => None, - 87 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(87, precedence, allow_fallback)), - 87 => None, - 88 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(88, precedence, allow_fallback)), - 88 => None, - 89 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(89, precedence, allow_fallback)), - 89 => None, - 90 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(90, precedence, allow_fallback)), - 90 => None, - 92 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(92, precedence, allow_fallback)), - 92 => None, - 99 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(99, precedence, allow_fallback)), - 99 => None, - 101 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(101, precedence, allow_fallback)), - 101 => None, - 104 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(104, precedence, allow_fallback)), - 104 => None, - 105 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(105, precedence, allow_fallback)), - 105 => None, - 106 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(106, precedence, allow_fallback)), - 106 => None, - 107 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(107, precedence, allow_fallback)), - 107 => None, - 108 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(108, precedence, allow_fallback)), - 108 => None, - 114 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(114, precedence, allow_fallback)), - 114 => None, - 116 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(116, precedence, allow_fallback)), - 116 => None, - 120 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(120, precedence, allow_fallback)), - 120 => None, - 122 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(122, precedence, allow_fallback)), - 122 => None, - 125 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(125, precedence, allow_fallback)), - 125 => None, - 126 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(126, precedence, allow_fallback)), - 126 => None, - 127 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(127, precedence, allow_fallback)), - 127 => None, - 135 if self.generated_only() || self.base.has_rule_depth_cap() || self.base.has_parse_listeners() => Some(self.dispatch_generated_rule(135, precedence, allow_fallback)), - 135 => None, - _ => Some(self.dispatch_generated_rule(rule_index, precedence, allow_fallback)), - } - } - - #[allow(dead_code)] - fn parse_generated_rule_0(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 0isize, 0, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 349, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 5 | 41 | 43 | 72..=80 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 349, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 348isize, self.dispatch_generated_rule(2, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_354 = false; - loop { - self.base.sync_into(atn(), 354, &mut __ctx, __loop_iter_354, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 41 | 43 | 72..=80 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 354, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_354 = true; - self.base.match_token_into(5, 353, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_360 = false; - loop { - self.base.sync_into(atn(), 360, &mut __ctx, __loop_iter_360, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 360) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(2, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(2, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 360, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_360 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 357isize, self.dispatch_generated_rule(3, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 363isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 364isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_368 = false; - loop { - self.base.sync_into(atn(), 368, &mut __ctx, __loop_iter_368, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 74..=80 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 368, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_368 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 365isize, self.dispatch_generated_rule(8, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(-1, 372, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_1(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 2isize, 1, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 374, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 1 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 374, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 373isize, self.dispatch_generated_rule(2, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_379 = false; - loop { - self.base.sync_into(atn(), 379, &mut __ctx, __loop_iter_379, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 379) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(5, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(5, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 379, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_379 = true; - self.base.match_token_into(5, 378, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_385 = false; - loop { - self.base.sync_into(atn(), 385, &mut __ctx, __loop_iter_385, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 385) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(6, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(6, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 385, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_385 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 382isize, self.dispatch_generated_rule(3, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 388isize, self.dispatch_generated_rule(4, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 389isize, self.dispatch_generated_rule(5, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_395 = false; - loop { - self.base.sync_into(atn(), 395, &mut __ctx, __loop_iter_395, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 395, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_395 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 390isize, self.dispatch_generated_rule(65, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 391isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(-1, 399, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_2(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 4isize, 2, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(1, 402, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(5, 403, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_404 = true; - loop { - self.base.sync_into(atn(), 404, &mut __ctx, __loop_iter_404, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 404) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(8, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(8, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 404, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_404 = true; - self.base.match_token_into(5, 403, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_3(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 6isize, 3, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(41, 41), (43, 43)], 407, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(63, 411, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_411 = false; - loop { - self.base.sync_into(atn(), 411, &mut __ctx, __loop_iter_411, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 411, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_411 = true; - self.base.match_token_into(5, 410, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 418, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_418 = false; - loop { - self.base.sync_into(atn(), 418, &mut __ctx, __loop_iter_418, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 418, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_418 = true; - self.base.match_token_into(5, 417, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 11 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 430, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 11 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 430, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(11, 423, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 422isize, self.dispatch_generated_rule(171, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_425 = true; - loop { - self.base.sync_into(atn(), 425, &mut __ctx, __loop_iter_425, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 425, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_425 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 422isize, self.dispatch_generated_rule(171, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(12, 428, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 429isize, self.dispatch_generated_rule(171, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_435 = false; - loop { - self.base.sync_into(atn(), 435, &mut __ctx, __loop_iter_435, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 435) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(13, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(13, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 435, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_435 = true; - self.base.match_token_into(5, 434, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_4(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 8isize, 4, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 443, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 72 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 443, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(72, 439, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 439isize, self.dispatch_generated_rule(173, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 441, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 441) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(14, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(14, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 441, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 440isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_5(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 10isize, 5, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_448 = false; - loop { - self.base.sync_into(atn(), 448, &mut __ctx, __loop_iter_448, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 448) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(16, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(16, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 448, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_448 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 445isize, self.dispatch_generated_rule(6, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_6(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 12isize, 6, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(73, 452, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 452isize, self.dispatch_generated_rule(173, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 456, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 7 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 102 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 27 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 456, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(7, 454, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(15, 457, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 455isize, self.dispatch_generated_rule(7, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 459, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 459) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(18, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(18, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 459, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 458isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_7(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 14isize, 7, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(102, 462, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 462isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_8(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 16isize, 8, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 464isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 466, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - -1 | 41 | 43 | 74..=80 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 466, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 465isize, self.dispatch_generated_rule(75, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_9(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 18isize, 9, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 469, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 469, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 468isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(80, 475, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_475 = false; - loop { - self.base.sync_into(atn(), 475, &mut __ctx, __loop_iter_475, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 475, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_475 = true; - self.base.match_token_into(5, 474, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 478isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 486, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 486) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(23, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(23, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 486, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_482 = false; - loop { - self.base.sync_into(atn(), 482, &mut __ctx, __loop_iter_482, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 482, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_482 = true; - self.base.match_token_into(5, 481, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 485isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_491 = false; - loop { - self.base.sync_into(atn(), 491, &mut __ctx, __loop_iter_491, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 491, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_491 = true; - self.base.match_token_into(5, 490, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(28, 498, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_498 = false; - loop { - self.base.sync_into(atn(), 498, &mut __ctx, __loop_iter_498, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 498, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_498 = true; - self.base.match_token_into(5, 497, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 501isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_10(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 20isize, 10, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 74..=75 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78..=79 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 80 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 508, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 508) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(26, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(26, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 508, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 503isize, self.parse_rule_precedence_from_generated(11, 0), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 504isize, self.parse_rule_precedence_from_generated(43, 0), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 505isize, self.parse_rule_precedence_from_generated(31, 0), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 506isize, self.parse_rule_precedence_from_generated(35, 0), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 507isize, self.dispatch_generated_rule(9, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_11(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 22isize, 11, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 511, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74..=76 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 511, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 510isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 74 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75..=76 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 524, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 74 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75..=76 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 524, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(74, 525, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.sync_into(atn(), 521, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 76 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 521, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(76, 518, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_518 = false; - loop { - self.base.sync_into(atn(), 518, &mut __ctx, __loop_iter_518, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 75 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 518, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_518 = true; - self.base.match_token_into(5, 517, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(75, 525, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_529 = false; - loop { - self.base.sync_into(atn(), 529, &mut __ctx, __loop_iter_529, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 529, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_529 = true; - self.base.match_token_into(5, 528, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 532isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 540, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 540) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(33, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(33, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 540, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_536 = false; - loop { - self.base.sync_into(atn(), 536, &mut __ctx, __loop_iter_536, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 536, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_536 = true; - self.base.match_token_into(5, 535, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 539isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 549, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 549) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(35, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(35, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 549, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_545 = false; - loop { - self.base.sync_into(atn(), 545, &mut __ctx, __loop_iter_545, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 81 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 545, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_545 = true; - self.base.match_token_into(5, 544, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 548isize, self.parse_rule_precedence_from_generated(12, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 565, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 565) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(38, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(38, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 565, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_554 = false; - loop { - self.base.sync_into(atn(), 554, &mut __ctx, __loop_iter_554, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 554, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_554 = true; - self.base.match_token_into(5, 553, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 561, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_561 = false; - loop { - self.base.sync_into(atn(), 561, &mut __ctx, __loop_iter_561, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 561) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(37, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(37, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 561, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_561 = true; - self.base.match_token_into(5, 560, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 564isize, self.parse_rule_precedence_from_generated(16, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 574, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 574) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(40, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(40, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 574, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_570 = false; - loop { - self.base.sync_into(atn(), 570, &mut __ctx, __loop_iter_570, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 88 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 570, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_570 = true; - self.base.match_token_into(5, 569, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 573isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 590, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 590) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(43, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(43, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 590, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_579 = false; - loop { - self.base.sync_into(atn(), 579, &mut __ctx, __loop_iter_579, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 579, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_579 = true; - self.base.match_token_into(5, 578, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 582isize, self.dispatch_generated_rule(13, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - let mut __loop_iter_586 = false; - loop { - self.base.sync_into(atn(), 586, &mut __ctx, __loop_iter_586, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 586, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_586 = true; - self.base.match_token_into(5, 585, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 589isize, self.parse_rule_precedence_from_generated(46, 0), __ctx); - } - 3 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_12(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 24isize, 12, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 602, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 81 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 602, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 593, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 593, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 592isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(81, 599, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_599 = false; - loop { - self.base.sync_into(atn(), 599, &mut __ctx, __loop_iter_599, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 599, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_599 = true; - self.base.match_token_into(5, 598, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 604isize, self.parse_rule_precedence_from_generated(14, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_13(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 26isize, 13, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(13, 610, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_610 = false; - loop { - self.base.sync_into(atn(), 610, &mut __ctx, __loop_iter_610, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 610) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(47, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(47, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 610, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_610 = true; - self.base.match_token_into(5, 609, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 613isize, self.dispatch_generated_rule(25, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_617 = false; - loop { - self.base.sync_into(atn(), 617, &mut __ctx, __loop_iter_617, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 617, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_617 = true; - self.base.match_token_into(5, 616, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(14, 621, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_14(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 28isize, 14, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 626, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_626 = false; - loop { - self.base.sync_into(atn(), 626, &mut __ctx, __loop_iter_626, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 626) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(49, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(49, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 626, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_626 = true; - self.base.match_token_into(5, 625, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 658, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 658) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(55, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(55, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 658, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 629isize, self.parse_rule_precedence_from_generated(15, 0), __ctx); - let mut __loop_iter_646 = false; - loop { - self.base.sync_into(atn(), 646, &mut __ctx, __loop_iter_646, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 646) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(52, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(52, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 646, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_646 = true; - let mut __loop_iter_633 = false; - loop { - self.base.sync_into(atn(), 633, &mut __ctx, __loop_iter_633, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 633, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_633 = true; - self.base.match_token_into(5, 632, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 640, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_640 = false; - loop { - self.base.sync_into(atn(), 640, &mut __ctx, __loop_iter_640, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 640) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(51, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(51, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 640, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_640 = true; - self.base.match_token_into(5, 639, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 643isize, self.parse_rule_precedence_from_generated(15, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 656, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 656) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(54, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(54, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 656, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_652 = false; - loop { - self.base.sync_into(atn(), 652, &mut __ctx, __loop_iter_652, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 652, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_652 = true; - self.base.match_token_into(5, 651, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 657, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_663 = false; - loop { - self.base.sync_into(atn(), 663, &mut __ctx, __loop_iter_663, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 663, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_663 = true; - self.base.match_token_into(5, 662, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 667, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_15(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 30isize, 15, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 669, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 669) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(57, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(57, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 669, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 668isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 672, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 78..=79 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 672, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_set_into(&[(78, 79)], 673, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_677 = false; - loop { - self.base.sync_into(atn(), 677, &mut __ctx, __loop_iter_677, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 677, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_677 = true; - self.base.match_token_into(5, 676, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 680isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(26, 685, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_685 = false; - loop { - self.base.sync_into(atn(), 685, &mut __ctx, __loop_iter_685, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 685, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_685 = true; - self.base.match_token_into(5, 684, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 688isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 703, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 703) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(63, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(63, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 703, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_692 = false; - loop { - self.base.sync_into(atn(), 692, &mut __ctx, __loop_iter_692, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 692, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_692 = true; - self.base.match_token_into(5, 691, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(28, 699, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_699 = false; - loop { - self.base.sync_into(atn(), 699, &mut __ctx, __loop_iter_699, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 699) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(62, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(62, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 699, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_699 = true; - self.base.match_token_into(5, 698, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 702isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_16(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 32isize, 16, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 705isize, self.parse_rule_precedence_from_generated(19, 0), __ctx); - let mut __loop_iter_722 = false; - loop { - self.base.sync_into(atn(), 722, &mut __ctx, __loop_iter_722, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 722) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(66, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(66, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 722, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_722 = true; - let mut __loop_iter_709 = false; - loop { - self.base.sync_into(atn(), 709, &mut __ctx, __loop_iter_709, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 709, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_709 = true; - self.base.match_token_into(5, 708, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 716, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_716 = false; - loop { - self.base.sync_into(atn(), 716, &mut __ctx, __loop_iter_716, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 716) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(65, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(65, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 716, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_716 = true; - self.base.match_token_into(5, 715, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 719isize, self.parse_rule_precedence_from_generated(19, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_17(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 34isize, 17, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 737, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 737) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(68, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(68, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 737, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 725isize, self.dispatch_generated_rule(18, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 726isize, self.parse_rule_precedence_from_generated(20, 0), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 727isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 728isize, self.dispatch_generated_rule(58, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - self.base.match_token_into(124, 733, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_733 = false; - loop { - self.base.sync_into(atn(), 733, &mut __ctx, __loop_iter_733, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 733, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_733 = true; - self.base.match_token_into(5, 732, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 736isize, self.dispatch_generated_rule(58, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_18(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 36isize, 18, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 739isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_743 = false; - loop { - self.base.sync_into(atn(), 743, &mut __ctx, __loop_iter_743, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 743, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_743 = true; - self.base.match_token_into(5, 742, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 746isize, self.parse_rule_precedence_from_generated(104, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_19(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 38isize, 19, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_751 = false; - loop { - self.base.sync_into(atn(), 751, &mut __ctx, __loop_iter_751, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 751) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(70, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(70, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 751, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_751 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 748isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_757 = false; - loop { - self.base.sync_into(atn(), 757, &mut __ctx, __loop_iter_757, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 757, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_757 = true; - self.base.match_token_into(5, 756, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 760isize, self.parse_rule_precedence_from_generated(17, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_20(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 40isize, 20, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 | 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 764, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 764) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(72, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(72, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 764, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 762isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 763isize, self.dispatch_generated_rule(58, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_769 = false; - loop { - self.base.sync_into(atn(), 769, &mut __ctx, __loop_iter_769, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 769, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_769 = true; - self.base.match_token_into(5, 768, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(82, 776, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_776 = false; - loop { - self.base.sync_into(atn(), 776, &mut __ctx, __loop_iter_776, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 776) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(74, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(74, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 776, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_776 = true; - self.base.match_token_into(5, 775, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 779isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_21(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 42isize, 21, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(47, 785, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_785 = false; - loop { - self.base.sync_into(atn(), 785, &mut __ctx, __loop_iter_785, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 785) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(75, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(75, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 785, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_785 = true; - self.base.match_token_into(5, 784, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 788isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_805 = false; - loop { - self.base.sync_into(atn(), 805, &mut __ctx, __loop_iter_805, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 805) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(78, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(78, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 805, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_805 = true; - let mut __loop_iter_792 = false; - loop { - self.base.sync_into(atn(), 792, &mut __ctx, __loop_iter_792, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 792, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_792 = true; - self.base.match_token_into(5, 791, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 799, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_799 = false; - loop { - self.base.sync_into(atn(), 799, &mut __ctx, __loop_iter_799, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 799) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(77, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(77, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 799, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_799 = true; - self.base.match_token_into(5, 798, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 802isize, self.dispatch_generated_rule(22, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 815, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 815) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(80, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(80, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 815, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_811 = false; - loop { - self.base.sync_into(atn(), 811, &mut __ctx, __loop_iter_811, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 811, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_811 = true; - self.base.match_token_into(5, 810, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 816, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_820 = false; - loop { - self.base.sync_into(atn(), 820, &mut __ctx, __loop_iter_820, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 48 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 820, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_820 = true; - self.base.match_token_into(5, 819, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(48, 824, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_22(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 44isize, 22, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 826, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 826) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(82, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(82, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 826, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 825isize, self.dispatch_generated_rule(159, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_831 = false; - loop { - self.base.sync_into(atn(), 831, &mut __ctx, __loop_iter_831, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 831, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_831 = true; - self.base.match_token_into(5, 830, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 834isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 849, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 849) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(86, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(86, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 849, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_838 = false; - loop { - self.base.sync_into(atn(), 838, &mut __ctx, __loop_iter_838, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 838, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_838 = true; - self.base.match_token_into(5, 837, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 845, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_845 = false; - loop { - self.base.sync_into(atn(), 845, &mut __ctx, __loop_iter_845, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 845, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_845 = true; - self.base.match_token_into(5, 844, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 848isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_23(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 46isize, 23, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(88, 855, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_855 = false; - loop { - self.base.sync_into(atn(), 855, &mut __ctx, __loop_iter_855, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 855, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_855 = true; - self.base.match_token_into(5, 854, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 858isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_875 = false; - loop { - self.base.sync_into(atn(), 875, &mut __ctx, __loop_iter_875, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 875) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(90, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(90, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 875, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_875 = true; - let mut __loop_iter_862 = false; - loop { - self.base.sync_into(atn(), 862, &mut __ctx, __loop_iter_862, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 862, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_862 = true; - self.base.match_token_into(5, 861, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 869, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_869 = false; - loop { - self.base.sync_into(atn(), 869, &mut __ctx, __loop_iter_869, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 869, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_869 = true; - self.base.match_token_into(5, 868, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 872isize, self.dispatch_generated_rule(24, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_24(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 48isize, 24, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_881 = false; - loop { - self.base.sync_into(atn(), 881, &mut __ctx, __loop_iter_881, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 881, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_881 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 878isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 884isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_888 = false; - loop { - self.base.sync_into(atn(), 888, &mut __ctx, __loop_iter_888, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 888, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_888 = true; - self.base.match_token_into(5, 887, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 895, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_895 = false; - loop { - self.base.sync_into(atn(), 895, &mut __ctx, __loop_iter_895, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 895, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_895 = true; - self.base.match_token_into(5, 894, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 898isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_25(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 50isize, 25, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_906 = false; - loop { - self.base.sync_into(atn(), 906, &mut __ctx, __loop_iter_906, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 74..=81 | 83..=84 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 906, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_906 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 900isize, self.dispatch_generated_rule(26, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 902, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 902) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(94, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(94, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 902, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 901isize, self.dispatch_generated_rule(75, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_26(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 52isize, 26, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 74..=80 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 83 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 84 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 913, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 913) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(96, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(96, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 913, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 909isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 910isize, self.parse_rule_precedence_from_generated(28, 0), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 911isize, self.dispatch_generated_rule(27, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 912isize, self.parse_rule_precedence_from_generated(44, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_27(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 54isize, 27, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(84, 919, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_919 = false; - loop { - self.base.sync_into(atn(), 919, &mut __ctx, __loop_iter_919, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 919, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_919 = true; - self.base.match_token_into(5, 918, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 922isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_28(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 56isize, 28, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 925, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 83 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 925, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 924isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(83, 931, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_931 = false; - loop { - self.base.sync_into(atn(), 931, &mut __ctx, __loop_iter_931, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 931) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(99, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(99, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 931, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_931 = true; - self.base.match_token_into(5, 930, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 935, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 935, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(116, 936, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_940 = false; - loop { - self.base.sync_into(atn(), 940, &mut __ctx, __loop_iter_940, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 940, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_940 = true; - self.base.match_token_into(5, 939, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(77, 951, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 951, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 951) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(103, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(103, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 951, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_947 = false; - loop { - self.base.sync_into(atn(), 947, &mut __ctx, __loop_iter_947, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 947, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_947 = true; - self.base.match_token_into(5, 946, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 950isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 967, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 967) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(106, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(106, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 967, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_956 = false; - loop { - self.base.sync_into(atn(), 956, &mut __ctx, __loop_iter_956, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 956, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_956 = true; - self.base.match_token_into(5, 955, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 963, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_963 = false; - loop { - self.base.sync_into(atn(), 963, &mut __ctx, __loop_iter_963, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 963) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(105, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(105, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 963, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_963 = true; - self.base.match_token_into(5, 962, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 966isize, self.parse_rule_precedence_from_generated(16, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 976, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 976) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(108, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(108, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 976, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_972 = false; - loop { - self.base.sync_into(atn(), 972, &mut __ctx, __loop_iter_972, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 972, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_972 = true; - self.base.match_token_into(5, 971, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 975isize, self.dispatch_generated_rule(13, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_29(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 58isize, 29, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 982, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_982 = false; - loop { - self.base.sync_into(atn(), 982, &mut __ctx, __loop_iter_982, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 982) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(109, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(109, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 982, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_982 = true; - self.base.match_token_into(5, 981, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1014, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1014, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 985isize, self.parse_rule_precedence_from_generated(30, 0), __ctx); - let mut __loop_iter_1002 = false; - loop { - self.base.sync_into(atn(), 1002, &mut __ctx, __loop_iter_1002, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1002) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(112, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(112, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1002, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1002 = true; - let mut __loop_iter_989 = false; - loop { - self.base.sync_into(atn(), 989, &mut __ctx, __loop_iter_989, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 989, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_989 = true; - self.base.match_token_into(5, 988, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 996, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_996 = false; - loop { - self.base.sync_into(atn(), 996, &mut __ctx, __loop_iter_996, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 996, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_996 = true; - self.base.match_token_into(5, 995, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 999isize, self.parse_rule_precedence_from_generated(30, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1012, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1012) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(114, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(114, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1012, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1008 = false; - loop { - self.base.sync_into(atn(), 1008, &mut __ctx, __loop_iter_1008, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1008, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1008 = true; - self.base.match_token_into(5, 1007, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1013, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1019 = false; - loop { - self.base.sync_into(atn(), 1019, &mut __ctx, __loop_iter_1019, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1019, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1019 = true; - self.base.match_token_into(5, 1018, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1023, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_30(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 60isize, 30, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1025, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1025) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(117, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(117, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1025, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1024isize, self.dispatch_generated_rule(151, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1027isize, self.dispatch_generated_rule(42, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1042, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1042) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(120, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(120, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1042, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1031 = false; - loop { - self.base.sync_into(atn(), 1031, &mut __ctx, __loop_iter_1031, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1031, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1031 = true; - self.base.match_token_into(5, 1030, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(28, 1038, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1038 = false; - loop { - self.base.sync_into(atn(), 1038, &mut __ctx, __loop_iter_1038, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1038) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(119, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(119, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1038, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1038 = true; - self.base.match_token_into(5, 1037, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1041isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_31(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 62isize, 31, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1045, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 76 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1045, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1044isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(76, 1055, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1055, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1055) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(123, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(123, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1055, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1051 = false; - loop { - self.base.sync_into(atn(), 1051, &mut __ctx, __loop_iter_1051, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1051, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1051 = true; - self.base.match_token_into(5, 1050, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1054isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1072, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1072) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(126, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(126, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1072, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1060 = false; - loop { - self.base.sync_into(atn(), 1060, &mut __ctx, __loop_iter_1060, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1060, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1060 = true; - self.base.match_token_into(5, 1059, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1063isize, self.dispatch_generated_rule(61, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1067 = false; - loop { - self.base.sync_into(atn(), 1067, &mut __ctx, __loop_iter_1067, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1067, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1067 = true; - self.base.match_token_into(5, 1066, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(7, 1071, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1077 = false; - loop { - self.base.sync_into(atn(), 1077, &mut __ctx, __loop_iter_1077, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1077, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1077 = true; - self.base.match_token_into(5, 1076, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1080isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1084 = false; - loop { - self.base.sync_into(atn(), 1084, &mut __ctx, __loop_iter_1084, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1084, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1084 = true; - self.base.match_token_into(5, 1083, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1087isize, self.parse_rule_precedence_from_generated(29, 0), __ctx); - self.base.sync_into(atn(), 1102, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1102) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(131, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(131, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1102, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1091 = false; - loop { - self.base.sync_into(atn(), 1091, &mut __ctx, __loop_iter_1091, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1091, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1091 = true; - self.base.match_token_into(5, 1090, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 1098, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1098 = false; - loop { - self.base.sync_into(atn(), 1098, &mut __ctx, __loop_iter_1098, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1098, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1098 = true; - self.base.match_token_into(5, 1097, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1101isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1111, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1111) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(133, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(133, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1111, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1107 = false; - loop { - self.base.sync_into(atn(), 1107, &mut __ctx, __loop_iter_1107, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 88 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1107, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1107 = true; - self.base.match_token_into(5, 1106, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1110isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1120, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1120) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(135, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(135, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1120, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1116 = false; - loop { - self.base.sync_into(atn(), 1116, &mut __ctx, __loop_iter_1116, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1116, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1116 = true; - self.base.match_token_into(5, 1115, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1119isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_32(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 64isize, 32, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1131, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 13 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1131, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1122isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(28, 1127, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1127 = false; - loop { - self.base.sync_into(atn(), 1127, &mut __ctx, __loop_iter_1127, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1127) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(136, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(136, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1127, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1127 = true; - self.base.match_token_into(5, 1126, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1130isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_33(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 66isize, 33, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1136 = false; - loop { - self.base.sync_into(atn(), 1136, &mut __ctx, __loop_iter_1136, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1136, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1136 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1133isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1142 = false; - loop { - self.base.sync_into(atn(), 1142, &mut __ctx, __loop_iter_1142, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1142, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1142 = true; - self.base.match_token_into(5, 1141, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1145isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1160, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1160) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(142, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(142, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1160, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1149 = false; - loop { - self.base.sync_into(atn(), 1149, &mut __ctx, __loop_iter_1149, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1149, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1149 = true; - self.base.match_token_into(5, 1148, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 1156, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1156 = false; - loop { - self.base.sync_into(atn(), 1156, &mut __ctx, __loop_iter_1156, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1156, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1156 = true; - self.base.match_token_into(5, 1155, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1159isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_34(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 68isize, 34, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 1166, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1166 = false; - loop { - self.base.sync_into(atn(), 1166, &mut __ctx, __loop_iter_1166, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1166) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(143, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(143, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1166, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1166 = true; - self.base.match_token_into(5, 1165, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1169isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1186 = false; - loop { - self.base.sync_into(atn(), 1186, &mut __ctx, __loop_iter_1186, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1186) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(146, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(146, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1186, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1186 = true; - let mut __loop_iter_1173 = false; - loop { - self.base.sync_into(atn(), 1173, &mut __ctx, __loop_iter_1173, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1173, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1173 = true; - self.base.match_token_into(5, 1172, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1180, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1180 = false; - loop { - self.base.sync_into(atn(), 1180, &mut __ctx, __loop_iter_1180, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1180) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(145, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(145, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1180, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1180 = true; - self.base.match_token_into(5, 1179, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1183isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1196, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1196) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(148, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(148, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1196, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1192 = false; - loop { - self.base.sync_into(atn(), 1192, &mut __ctx, __loop_iter_1192, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1192, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1192 = true; - self.base.match_token_into(5, 1191, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1197, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1201 = false; - loop { - self.base.sync_into(atn(), 1201, &mut __ctx, __loop_iter_1201, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1201, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1201 = true; - self.base.match_token_into(5, 1200, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1205, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_35(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 70isize, 35, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1207, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78..=79 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1207, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1206isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_set_into(&[(78, 79)], 1217, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1217, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1217) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(152, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(152, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1217, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1213 = false; - loop { - self.base.sync_into(atn(), 1213, &mut __ctx, __loop_iter_1213, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1213, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1213 = true; - self.base.match_token_into(5, 1212, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1216isize, self.dispatch_generated_rule(21, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1234, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1234) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(155, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(155, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1234, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1222 = false; - loop { - self.base.sync_into(atn(), 1222, &mut __ctx, __loop_iter_1222, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1222, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1222 = true; - self.base.match_token_into(5, 1221, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1225isize, self.dispatch_generated_rule(61, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1229 = false; - loop { - self.base.sync_into(atn(), 1229, &mut __ctx, __loop_iter_1229, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1229, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1229 = true; - self.base.match_token_into(5, 1228, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(7, 1233, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1239 = false; - loop { - self.base.sync_into(atn(), 1239, &mut __ctx, __loop_iter_1239, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1239) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(156, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(156, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1239, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1239 = true; - self.base.match_token_into(5, 1238, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1244, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1244, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1242isize, self.dispatch_generated_rule(34, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1243isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1253, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1253) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(159, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(159, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1253, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1249 = false; - loop { - self.base.sync_into(atn(), 1249, &mut __ctx, __loop_iter_1249, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 88 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1249, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1249 = true; - self.base.match_token_into(5, 1248, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1252isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1272, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1272) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(163, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(163, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1272, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1258 = false; - loop { - self.base.sync_into(atn(), 1258, &mut __ctx, __loop_iter_1258, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 | 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1258, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1258 = true; - self.base.match_token_into(5, 1257, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 28 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1270, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 28 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 82 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1270, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(28, 1265, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1265 = false; - loop { - self.base.sync_into(atn(), 1265, &mut __ctx, __loop_iter_1265, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1265) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(161, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(161, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1265, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1265 = true; - self.base.match_token_into(5, 1264, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1268isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1269isize, self.dispatch_generated_rule(36, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1281, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1281) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(165, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(165, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1281, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1277 = false; - loop { - self.base.sync_into(atn(), 1277, &mut __ctx, __loop_iter_1277, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1277, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1277 = true; - self.base.match_token_into(5, 1276, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(27, 1282, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1286 = false; - loop { - self.base.sync_into(atn(), 1286, &mut __ctx, __loop_iter_1286, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1286) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(166, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(166, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1286, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1286 = true; - self.base.match_token_into(5, 1285, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1319, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1319) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(175, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(175, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1319, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 1290, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1290) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(167, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(167, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1290, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1289isize, self.dispatch_generated_rule(37, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1302, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1302) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(170, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(170, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1302, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1295 = false; - loop { - self.base.sync_into(atn(), 1295, &mut __ctx, __loop_iter_1295, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1295) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(168, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(168, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1295, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1295 = true; - self.base.match_token_into(5, 1294, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1299, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 67 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1299, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1298isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1301isize, self.parse_rule_precedence_from_generated(38, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - self.base.sync_into(atn(), 1305, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1305) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(171, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(171, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1305, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1304isize, self.parse_rule_precedence_from_generated(38, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1317, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1317) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(174, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(174, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1317, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1310 = false; - loop { - self.base.sync_into(atn(), 1310, &mut __ctx, __loop_iter_1310, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1310) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(172, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(172, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1310, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1310 = true; - self.base.match_token_into(5, 1309, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1314, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 66 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1314, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1313isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1316isize, self.dispatch_generated_rule(37, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_36(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 72isize, 36, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(82, 1325, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1325 = false; - loop { - self.base.sync_into(atn(), 1325, &mut __ctx, __loop_iter_1325, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1325) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(176, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(176, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1325, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1325 = true; - self.base.match_token_into(5, 1324, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1328isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_37(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 74isize, 37, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1331, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 66 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1331, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1330isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(66, 1371, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1371, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1371) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(184, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(184, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1371, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1337 = false; - loop { - self.base.sync_into(atn(), 1337, &mut __ctx, __loop_iter_1337, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1337, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1337 = true; - self.base.match_token_into(5, 1336, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(9, 1344, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1344 = false; - loop { - self.base.sync_into(atn(), 1344, &mut __ctx, __loop_iter_1344, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1344, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1344 = true; - self.base.match_token_into(5, 1343, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1362, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1362, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1362) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(182, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(182, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1362, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1351 = false; - loop { - self.base.sync_into(atn(), 1351, &mut __ctx, __loop_iter_1351, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1351, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1351 = true; - self.base.match_token_into(5, 1350, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 1358, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1358 = false; - loop { - self.base.sync_into(atn(), 1358, &mut __ctx, __loop_iter_1358, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1358, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1358 = true; - self.base.match_token_into(5, 1357, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1361isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1367 = false; - loop { - self.base.sync_into(atn(), 1367, &mut __ctx, __loop_iter_1367, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1367, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1367 = true; - self.base.match_token_into(5, 1366, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1370isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_38(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 76isize, 38, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1374, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 67 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1374, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1373isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(67, 1431, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1431, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1431) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(195, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(195, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1431, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1380 = false; - loop { - self.base.sync_into(atn(), 1380, &mut __ctx, __loop_iter_1380, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1380, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1380 = true; - self.base.match_token_into(5, 1379, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(9, 1387, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1387 = false; - loop { - self.base.sync_into(atn(), 1387, &mut __ctx, __loop_iter_1387, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1387, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1387 = true; - self.base.match_token_into(5, 1386, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1390isize, self.parse_rule_precedence_from_generated(40, 0), __ctx); - self.base.sync_into(atn(), 1398, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1398) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(189, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(189, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1398, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1394 = false; - loop { - self.base.sync_into(atn(), 1394, &mut __ctx, __loop_iter_1394, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1394, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1394 = true; - self.base.match_token_into(5, 1393, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1399, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1403 = false; - loop { - self.base.sync_into(atn(), 1403, &mut __ctx, __loop_iter_1403, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1403, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1403 = true; - self.base.match_token_into(5, 1402, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1421, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 1421, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1421) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(193, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(193, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1421, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1410 = false; - loop { - self.base.sync_into(atn(), 1410, &mut __ctx, __loop_iter_1410, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1410, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1410 = true; - self.base.match_token_into(5, 1409, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 1417, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1417 = false; - loop { - self.base.sync_into(atn(), 1417, &mut __ctx, __loop_iter_1417, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1417, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1417 = true; - self.base.match_token_into(5, 1416, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1420isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1426 = false; - loop { - self.base.sync_into(atn(), 1426, &mut __ctx, __loop_iter_1426, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1426, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1426 = true; - self.base.match_token_into(5, 1425, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1429isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_39(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 78isize, 39, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 1437, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1437 = false; - loop { - self.base.sync_into(atn(), 1437, &mut __ctx, __loop_iter_1437, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1437) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(196, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(196, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1437, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1437 = true; - self.base.match_token_into(5, 1436, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1469, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1469, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1440isize, self.parse_rule_precedence_from_generated(40, 0), __ctx); - let mut __loop_iter_1457 = false; - loop { - self.base.sync_into(atn(), 1457, &mut __ctx, __loop_iter_1457, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1457) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(199, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(199, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1457, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1457 = true; - let mut __loop_iter_1444 = false; - loop { - self.base.sync_into(atn(), 1444, &mut __ctx, __loop_iter_1444, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1444, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1444 = true; - self.base.match_token_into(5, 1443, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1451, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1451 = false; - loop { - self.base.sync_into(atn(), 1451, &mut __ctx, __loop_iter_1451, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1451, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1451 = true; - self.base.match_token_into(5, 1450, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1454isize, self.parse_rule_precedence_from_generated(40, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1467, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1467) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(201, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(201, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1467, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1463 = false; - loop { - self.base.sync_into(atn(), 1463, &mut __ctx, __loop_iter_1463, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1463, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1463 = true; - self.base.match_token_into(5, 1462, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1468, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1474 = false; - loop { - self.base.sync_into(atn(), 1474, &mut __ctx, __loop_iter_1474, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1474, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1474 = true; - self.base.match_token_into(5, 1473, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1478, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_40(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 80isize, 40, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1480, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1480) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(204, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(204, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1480, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1479isize, self.dispatch_generated_rule(151, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1482isize, self.dispatch_generated_rule(41, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1497, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1497) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(207, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(207, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1497, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1486 = false; - loop { - self.base.sync_into(atn(), 1486, &mut __ctx, __loop_iter_1486, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1486, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1486 = true; - self.base.match_token_into(5, 1485, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(28, 1493, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1493 = false; - loop { - self.base.sync_into(atn(), 1493, &mut __ctx, __loop_iter_1493, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1493) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(206, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(206, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1493, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1493 = true; - self.base.match_token_into(5, 1492, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1496isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_41(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 82isize, 41, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1499isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1503 = false; - loop { - self.base.sync_into(atn(), 1503, &mut __ctx, __loop_iter_1503, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1503) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(208, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(208, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1503, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1503 = true; - self.base.match_token_into(5, 1502, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1514, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 26 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 8 | 10 | 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1514, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(26, 1510, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1510 = false; - loop { - self.base.sync_into(atn(), 1510, &mut __ctx, __loop_iter_1510, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1510, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1510 = true; - self.base.match_token_into(5, 1509, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1513isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_42(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 84isize, 42, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1516isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1520 = false; - loop { - self.base.sync_into(atn(), 1520, &mut __ctx, __loop_iter_1520, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1520, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1520 = true; - self.base.match_token_into(5, 1519, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 1527, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1527 = false; - loop { - self.base.sync_into(atn(), 1527, &mut __ctx, __loop_iter_1527, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1527, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1527 = true; - self.base.match_token_into(5, 1526, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1530isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_43(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 86isize, 43, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1533, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1533, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1532isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(77, 1539, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1539 = false; - loop { - self.base.sync_into(atn(), 1539, &mut __ctx, __loop_iter_1539, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1539, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1539 = true; - self.base.match_token_into(5, 1538, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1542isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1557, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1557) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(217, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(217, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1557, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1546 = false; - loop { - self.base.sync_into(atn(), 1546, &mut __ctx, __loop_iter_1546, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1546, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1546 = true; - self.base.match_token_into(5, 1545, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 1553, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1553 = false; - loop { - self.base.sync_into(atn(), 1553, &mut __ctx, __loop_iter_1553, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1553) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(216, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(216, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1553, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1553 = true; - self.base.match_token_into(5, 1552, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1556isize, self.parse_rule_precedence_from_generated(16, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1566, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1566) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(219, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(219, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1566, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1562 = false; - loop { - self.base.sync_into(atn(), 1562, &mut __ctx, __loop_iter_1562, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1562, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1562 = true; - self.base.match_token_into(5, 1561, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1565isize, self.dispatch_generated_rule(13, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_44(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 88isize, 44, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1569, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 81 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1569, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1568isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(81, 1575, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1575 = false; - loop { - self.base.sync_into(atn(), 1575, &mut __ctx, __loop_iter_1575, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1575, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1575 = true; - self.base.match_token_into(5, 1574, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1578isize, self.parse_rule_precedence_from_generated(29, 0), __ctx); - self.base.sync_into(atn(), 1593, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1593) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(224, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(224, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1593, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1582 = false; - loop { - self.base.sync_into(atn(), 1582, &mut __ctx, __loop_iter_1582, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1582, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1582 = true; - self.base.match_token_into(5, 1581, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 1589, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1589 = false; - loop { - self.base.sync_into(atn(), 1589, &mut __ctx, __loop_iter_1589, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 85..=86 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1589, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1589 = true; - self.base.match_token_into(5, 1588, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1592isize, self.dispatch_generated_rule(45, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1598 = false; - loop { - self.base.sync_into(atn(), 1598, &mut __ctx, __loop_iter_1598, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1598) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(225, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(225, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1598, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1598 = true; - self.base.match_token_into(5, 1597, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1602, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 14 | 27 | 41 | 43 | 74..=81 | 83..=84 | 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1602, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1601isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_45(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 90isize, 45, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(85, 86)], 1608, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1608 = false; - loop { - self.base.sync_into(atn(), 1608, &mut __ctx, __loop_iter_1608, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1608, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1608 = true; - self.base.match_token_into(5, 1607, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1611isize, self.parse_rule_precedence_from_generated(104, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_46(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 92isize, 46, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(13, 1617, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1617 = false; - loop { - self.base.sync_into(atn(), 1617, &mut __ctx, __loop_iter_1617, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1617) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(228, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(228, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1617, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1617 = true; - self.base.match_token_into(5, 1616, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1621, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 14 | 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1621, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1620isize, self.parse_rule_precedence_from_generated(47, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1637, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1637) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(232, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(232, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1637, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1626 = false; - loop { - self.base.sync_into(atn(), 1626, &mut __ctx, __loop_iter_1626, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1626, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1626 = true; - self.base.match_token_into(5, 1625, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(27, 1633, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1633 = false; - loop { - self.base.sync_into(atn(), 1633, &mut __ctx, __loop_iter_1633, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1633) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(231, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(231, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1633, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1633 = true; - self.base.match_token_into(5, 1632, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1636isize, self.dispatch_generated_rule(25, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1642 = false; - loop { - self.base.sync_into(atn(), 1642, &mut __ctx, __loop_iter_1642, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1642, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1642 = true; - self.base.match_token_into(5, 1641, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(14, 1646, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_47(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 94isize, 47, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1647isize, self.parse_rule_precedence_from_generated(48, 0), __ctx); - let mut __loop_iter_1664 = false; - loop { - self.base.sync_into(atn(), 1664, &mut __ctx, __loop_iter_1664, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1664) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(236, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(236, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1664, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1664 = true; - let mut __loop_iter_1651 = false; - loop { - self.base.sync_into(atn(), 1651, &mut __ctx, __loop_iter_1651, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1651, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1651 = true; - self.base.match_token_into(5, 1650, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1658, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1658 = false; - loop { - self.base.sync_into(atn(), 1658, &mut __ctx, __loop_iter_1658, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1658, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1658 = true; - self.base.match_token_into(5, 1657, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1661isize, self.parse_rule_precedence_from_generated(48, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_1670 = false; - loop { - self.base.sync_into(atn(), 1670, &mut __ctx, __loop_iter_1670, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1670) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(237, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(237, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1670, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1670 = true; - self.base.match_token_into(5, 1669, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1674, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 8 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 14 | 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1674, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(8, 1675, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_48(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 96isize, 48, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1683, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1683) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(240, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(240, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1683, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1676isize, self.dispatch_generated_rule(150, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1680 = false; - loop { - self.base.sync_into(atn(), 1680, &mut __ctx, __loop_iter_1680, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1680, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1680 = true; - self.base.match_token_into(5, 1679, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1685isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1693, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1693) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(242, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(242, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1693, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1689 = false; - loop { - self.base.sync_into(atn(), 1689, &mut __ctx, __loop_iter_1689, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1689, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1689 = true; - self.base.match_token_into(5, 1688, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1692isize, self.parse_rule_precedence_from_generated(104, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1702, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1702) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(244, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(244, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1702, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1698 = false; - loop { - self.base.sync_into(atn(), 1698, &mut __ctx, __loop_iter_1698, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1698, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1698 = true; - self.base.match_token_into(5, 1697, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1701isize, self.dispatch_generated_rule(13, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_49(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 98isize, 49, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1705, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1705) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(245, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(245, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1705, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1704isize, self.dispatch_generated_rule(153, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1712, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1712) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(246, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(246, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1712, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1707isize, self.dispatch_generated_rule(58, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1708isize, self.dispatch_generated_rule(60, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1709isize, self.dispatch_generated_rule(51, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1710isize, self.dispatch_generated_rule(50, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1711isize, self.dispatch_generated_rule(63, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_50(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 100isize, 50, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107 | 109..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1716, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1716) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(247, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(247, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1716, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1714isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(108, 1717, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_51(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 102isize, 51, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1720, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1720, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1718isize, self.dispatch_generated_rule(50, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1719isize, self.dispatch_generated_rule(60, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1725 = false; - loop { - self.base.sync_into(atn(), 1725, &mut __ctx, __loop_iter_1725, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 45..=46 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1725, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1725 = true; - self.base.match_token_into(5, 1724, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1728isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1731 = true; - loop { - self.base.sync_into(atn(), 1731, &mut __ctx, __loop_iter_1731, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1731) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(250, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(250, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1731, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1731 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1728isize, self.dispatch_generated_rule(52, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_52(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 104isize, 52, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(45, 46)], 1734, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_53(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 106isize, 53, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1735isize, self.dispatch_generated_rule(54, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1752 = false; - loop { - self.base.sync_into(atn(), 1752, &mut __ctx, __loop_iter_1752, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1752) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(253, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(253, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1752, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1752 = true; - let mut __loop_iter_1739 = false; - loop { - self.base.sync_into(atn(), 1739, &mut __ctx, __loop_iter_1739, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1739, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1739 = true; - self.base.match_token_into(5, 1738, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(7, 1746, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1746 = false; - loop { - self.base.sync_into(atn(), 1746, &mut __ctx, __loop_iter_1746, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1746, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1746 = true; - self.base.match_token_into(5, 1745, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1749isize, self.dispatch_generated_rule(54, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_54(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 108isize, 54, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1755isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 1763, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1763) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(255, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(255, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1763, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1759 = false; - loop { - self.base.sync_into(atn(), 1759, &mut __ctx, __loop_iter_1759, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 47 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1759, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1759 = true; - self.base.match_token_into(5, 1758, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1762isize, self.dispatch_generated_rule(103, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_55(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 110isize, 55, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 104 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 15 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1770, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 104 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 15 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1770, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 1766, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1766) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(256, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(256, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1766, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1765isize, self.dispatch_generated_rule(56, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1768isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(15, 1771, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_56(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 112isize, 56, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1772isize, self.dispatch_generated_rule(57, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1775 = true; - loop { - self.base.sync_into(atn(), 1775, &mut __ctx, __loop_iter_1775, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1775) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(258, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(258, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1775, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1775 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1772isize, self.dispatch_generated_rule(57, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_57(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 114isize, 57, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 104 | 107 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1785, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 104 | 107 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1785, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1777isize, self.dispatch_generated_rule(158, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1781 = false; - loop { - self.base.sync_into(atn(), 1781, &mut __ctx, __loop_iter_1781, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 104 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 1781, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1781 = true; - self.base.match_token_into(5, 1780, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1784isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_58(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 116isize, 58, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1801, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1801) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(263, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(263, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1801, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1787isize, self.dispatch_generated_rule(61, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1791 = false; - loop { - self.base.sync_into(atn(), 1791, &mut __ctx, __loop_iter_1791, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1791, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1791 = true; - self.base.match_token_into(5, 1790, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(7, 1798, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1798 = false; - loop { - self.base.sync_into(atn(), 1798, &mut __ctx, __loop_iter_1798, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1798, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1798 = true; - self.base.match_token_into(5, 1797, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1803isize, self.dispatch_generated_rule(59, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1807 = false; - loop { - self.base.sync_into(atn(), 1807, &mut __ctx, __loop_iter_1807, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 34 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1807, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1807 = true; - self.base.match_token_into(5, 1806, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(34, 1814, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1814 = false; - loop { - self.base.sync_into(atn(), 1814, &mut __ctx, __loop_iter_1814, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1814, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1814 = true; - self.base.match_token_into(5, 1813, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1817isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_59(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 118isize, 59, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 1823, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1823 = false; - loop { - self.base.sync_into(atn(), 1823, &mut __ctx, __loop_iter_1823, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1823) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(266, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(266, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1823, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1823 = true; - self.base.match_token_into(5, 1822, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1828, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1828) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(267, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(267, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1828, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1826isize, self.dispatch_generated_rule(42, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1827isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1849 = false; - loop { - self.base.sync_into(atn(), 1849, &mut __ctx, __loop_iter_1849, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1849) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(271, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(271, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1849, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1849 = true; - let mut __loop_iter_1833 = false; - loop { - self.base.sync_into(atn(), 1833, &mut __ctx, __loop_iter_1833, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1833, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1833 = true; - self.base.match_token_into(5, 1832, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1840, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1840 = false; - loop { - self.base.sync_into(atn(), 1840, &mut __ctx, __loop_iter_1840, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1840, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1840 = true; - self.base.match_token_into(5, 1839, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 | 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1845, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1845) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(270, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(270, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1845, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1843isize, self.dispatch_generated_rule(42, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1844isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1859, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1859) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(273, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(273, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1859, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_1855 = false; - loop { - self.base.sync_into(atn(), 1855, &mut __ctx, __loop_iter_1855, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1855, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1855 = true; - self.base.match_token_into(5, 1854, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 1860, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1864 = false; - loop { - self.base.sync_into(atn(), 1864, &mut __ctx, __loop_iter_1864, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1864, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1864 = true; - self.base.match_token_into(5, 1863, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1868, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_60(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 120isize, 60, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 1873, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1873 = false; - loop { - self.base.sync_into(atn(), 1873, &mut __ctx, __loop_iter_1873, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1873, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1873 = true; - self.base.match_token_into(5, 1872, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1876isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1880 = false; - loop { - self.base.sync_into(atn(), 1880, &mut __ctx, __loop_iter_1880, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1880, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1880 = true; - self.base.match_token_into(5, 1879, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1884, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_61(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 122isize, 61, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1886, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1886) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(277, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(277, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1886, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1885isize, self.dispatch_generated_rule(153, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1891, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1891) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(278, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(278, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1891, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1888isize, self.dispatch_generated_rule(60, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1889isize, self.dispatch_generated_rule(51, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1890isize, self.dispatch_generated_rule(50, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_62(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 124isize, 62, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 1897, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1897 = false; - loop { - self.base.sync_into(atn(), 1897, &mut __ctx, __loop_iter_1897, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1897, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1897 = true; - self.base.match_token_into(5, 1896, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1902, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1902, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1900isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1901isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1907 = false; - loop { - self.base.sync_into(atn(), 1907, &mut __ctx, __loop_iter_1907, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1907, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1907 = true; - self.base.match_token_into(5, 1906, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 1911, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_63(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 126isize, 63, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1913, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1913) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(282, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(282, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1913, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1912isize, self.dispatch_generated_rule(153, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1917, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1917, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1915isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1916isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_1922 = false; - loop { - self.base.sync_into(atn(), 1922, &mut __ctx, __loop_iter_1922, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 57 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1922, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1922 = true; - self.base.match_token_into(5, 1921, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(57, 1929, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1929 = false; - loop { - self.base.sync_into(atn(), 1929, &mut __ctx, __loop_iter_1929, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1929, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1929 = true; - self.base.match_token_into(5, 1928, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 1933, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1933) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(286, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(286, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1933, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1932isize, self.dispatch_generated_rule(153, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1937, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1937, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1935isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1936isize, self.dispatch_generated_rule(62, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_64(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 128isize, 64, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 1948, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1948) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(289, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(289, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1948, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1939isize, self.dispatch_generated_rule(65, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1945 = false; - loop { - self.base.sync_into(atn(), 1945, &mut __ctx, __loop_iter_1945, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1945) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(288, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(288, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1945, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1945 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1940isize, self.dispatch_generated_rule(75, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1941isize, self.dispatch_generated_rule(65, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 1951, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1951) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(290, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(290, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1951, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1950isize, self.dispatch_generated_rule(75, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_65(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 130isize, 65, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_1957 = false; - loop { - self.base.sync_into(atn(), 1957, &mut __ctx, __loop_iter_1957, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1957) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(292, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(292, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1957, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1957 = true; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1955, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1955, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1953isize, self.dispatch_generated_rule(66, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1954isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 74..=75 | 78..=80 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 95..=97 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1964, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1964) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(293, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(293, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1964, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1960isize, self.dispatch_generated_rule(10, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1961isize, self.dispatch_generated_rule(73, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1962isize, self.dispatch_generated_rule(69, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1963isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_66(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 132isize, 66, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1966isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_set_into(&[(41, 42)], 1971, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1971 = false; - loop { - self.base.sync_into(atn(), 1971, &mut __ctx, __loop_iter_1971, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1971) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(294, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(294, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1971, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1971 = true; - self.base.match_token_into(5, 1970, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_67(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 134isize, 67, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1976, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1976) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(295, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(295, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1976, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1974isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1975isize, self.dispatch_generated_rule(65, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_68(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 136isize, 68, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(13, 1982, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_1982 = false; - loop { - self.base.sync_into(atn(), 1982, &mut __ctx, __loop_iter_1982, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 1982) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(296, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(296, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1982, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1982 = true; - self.base.match_token_into(5, 1981, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1985isize, self.dispatch_generated_rule(64, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_1989 = false; - loop { - self.base.sync_into(atn(), 1989, &mut __ctx, __loop_iter_1989, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 1989, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_1989 = true; - self.base.match_token_into(5, 1988, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(14, 1993, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_69(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 138isize, 69, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 95 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 97 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 96 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 1997, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 95 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 97 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 96 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 1997, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1994isize, self.parse_rule_precedence_from_generated(70, 0), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1995isize, self.parse_rule_precedence_from_generated(71, 0), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 1996isize, self.parse_rule_precedence_from_generated(72, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_70(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 140isize, 70, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(95, 2003, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2003 = false; - loop { - self.base.sync_into(atn(), 2003, &mut __ctx, __loop_iter_2003, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2003, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2003 = true; - self.base.match_token_into(5, 2002, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(9, 2010, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2010 = false; - loop { - self.base.sync_into(atn(), 2010, &mut __ctx, __loop_iter_2010, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2010) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(300, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(300, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2010, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2010 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2007isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2015, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 5 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2015, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2013isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2014isize, self.dispatch_generated_rule(34, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(104, 2018, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2018isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - self.base.match_token_into(10, 2023, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2023 = false; - loop { - self.base.sync_into(atn(), 2023, &mut __ctx, __loop_iter_2023, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2023) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(302, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(302, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2023, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2023 = true; - self.base.match_token_into(5, 2022, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2027, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2027) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(303, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(303, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2027, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2026isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_71(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 142isize, 71, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(97, 2033, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2033 = false; - loop { - self.base.sync_into(atn(), 2033, &mut __ctx, __loop_iter_2033, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2033, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2033 = true; - self.base.match_token_into(5, 2032, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(9, 2037, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2037isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - self.base.match_token_into(10, 2042, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2042 = false; - loop { - self.base.sync_into(atn(), 2042, &mut __ctx, __loop_iter_2042, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2042) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(305, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(305, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2042, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2042 = true; - self.base.match_token_into(5, 2041, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2047, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2047, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2045isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(27, 2048, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_72(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 144isize, 72, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(96, 2053, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2053 = false; - loop { - self.base.sync_into(atn(), 2053, &mut __ctx, __loop_iter_2053, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2053) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(307, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(307, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2053, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2053 = true; - self.base.match_token_into(5, 2052, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2057, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2057) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(308, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(308, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2057, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2056isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2062 = false; - loop { - self.base.sync_into(atn(), 2062, &mut __ctx, __loop_iter_2062, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 97 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2062, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2062 = true; - self.base.match_token_into(5, 2061, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(97, 2069, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2069 = false; - loop { - self.base.sync_into(atn(), 2069, &mut __ctx, __loop_iter_2069, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2069, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2069 = true; - self.base.match_token_into(5, 2068, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(9, 2073, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2073isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - self.base.match_token_into(10, 2075, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_73(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 146isize, 73, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 18..=21 | 24..=25 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2082, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2082) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(311, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(311, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2082, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2076isize, self.dispatch_generated_rule(94, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(28, 2078, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2079isize, self.dispatch_generated_rule(96, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2080isize, self.dispatch_generated_rule(137, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2087 = false; - loop { - self.base.sync_into(atn(), 2087, &mut __ctx, __loop_iter_2087, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2087) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(312, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(312, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2087, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2087 = true; - self.base.match_token_into(5, 2086, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2090isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_74(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 148isize, 74, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(5, 5), (27, 27)], 2096, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2096 = false; - loop { - self.base.sync_into(atn(), 2096, &mut __ctx, __loop_iter_2096, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2096) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(313, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(313, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2096, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2096 = true; - self.base.match_token_into(5, 2095, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_75(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 150isize, 75, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(5, 5), (27, 27)], 2101, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2102 = true; - loop { - self.base.sync_into(atn(), 2102, &mut __ctx, __loop_iter_2102, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2102) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(314, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(314, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2102, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2102 = true; - self.base.match_set_into(&[(5, 5), (27, 27)], 2101, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_76(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 152isize, 76, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2104isize, self.parse_rule_precedence_from_generated(77, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_77(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 154isize, 77, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2106isize, self.parse_rule_precedence_from_generated(78, 0), __ctx); - let mut __loop_iter_2123 = false; - loop { - self.base.sync_into(atn(), 2123, &mut __ctx, __loop_iter_2123, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2123) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(317, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(317, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2123, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2123 = true; - let mut __loop_iter_2110 = false; - loop { - self.base.sync_into(atn(), 2110, &mut __ctx, __loop_iter_2110, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 23 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2110, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2110 = true; - self.base.match_token_into(5, 2109, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(23, 2117, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2117 = false; - loop { - self.base.sync_into(atn(), 2117, &mut __ctx, __loop_iter_2117, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2117) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(316, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(316, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2117, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2117 = true; - self.base.match_token_into(5, 2116, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2120isize, self.parse_rule_precedence_from_generated(78, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_78(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 156isize, 78, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2126isize, self.parse_rule_precedence_from_generated(79, 0), __ctx); - let mut __loop_iter_2143 = false; - loop { - self.base.sync_into(atn(), 2143, &mut __ctx, __loop_iter_2143, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2143) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(320, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(320, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2143, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2143 = true; - let mut __loop_iter_2130 = false; - loop { - self.base.sync_into(atn(), 2130, &mut __ctx, __loop_iter_2130, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 22 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2130, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2130 = true; - self.base.match_token_into(5, 2129, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(22, 2137, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2137 = false; - loop { - self.base.sync_into(atn(), 2137, &mut __ctx, __loop_iter_2137, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2137) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(319, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(319, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2137, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2137 = true; - self.base.match_token_into(5, 2136, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2140isize, self.parse_rule_precedence_from_generated(79, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_79(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 158isize, 79, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2146isize, self.parse_rule_precedence_from_generated(80, 0), __ctx); - let mut __loop_iter_2158 = false; - loop { - self.base.sync_into(atn(), 2158, &mut __ctx, __loop_iter_2158, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2158) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(322, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(322, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2158, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2158 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2147isize, self.dispatch_generated_rule(138, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2151 = false; - loop { - self.base.sync_into(atn(), 2151, &mut __ctx, __loop_iter_2151, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2151) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(321, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(321, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2151, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2151 = true; - self.base.match_token_into(5, 2150, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2154isize, self.parse_rule_precedence_from_generated(80, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_80(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 160isize, 80, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2161isize, self.parse_rule_precedence_from_generated(81, 0), __ctx); - let mut __loop_iter_2173 = false; - loop { - self.base.sync_into(atn(), 2173, &mut __ctx, __loop_iter_2173, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2173) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(324, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(324, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2173, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2173 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2162isize, self.dispatch_generated_rule(139, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2166 = false; - loop { - self.base.sync_into(atn(), 2166, &mut __ctx, __loop_iter_2166, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2166) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(323, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(323, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2166, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2166 = true; - self.base.match_token_into(5, 2165, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2169isize, self.parse_rule_precedence_from_generated(81, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_81(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 162isize, 81, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2176isize, self.parse_rule_precedence_from_generated(82, 0), __ctx); - let mut __loop_iter_2180 = false; - loop { - self.base.sync_into(atn(), 2180, &mut __ctx, __loop_iter_2180, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2180) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(325, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(325, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2180, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2180 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2177isize, self.parse_rule_precedence_from_generated(101, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_82(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 164isize, 82, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2183isize, self.parse_rule_precedence_from_generated(83, 0), __ctx); - let mut __loop_iter_2204 = false; - loop { - self.base.sync_into(atn(), 2204, &mut __ctx, __loop_iter_2204, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2204) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(329, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(329, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2204, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2204 = true; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 104 | 106 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 103 | 105 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2202, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 104 | 106 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 103 | 105 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2202, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2184isize, self.dispatch_generated_rule(140, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2188 = false; - loop { - self.base.sync_into(atn(), 2188, &mut __ctx, __loop_iter_2188, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2188) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(326, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(326, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2188, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2188 = true; - self.base.match_token_into(5, 2187, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2191isize, self.parse_rule_precedence_from_generated(83, 0), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2193isize, self.dispatch_generated_rule(141, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2197 = false; - loop { - self.base.sync_into(atn(), 2197, &mut __ctx, __loop_iter_2197, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2197, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2197 = true; - self.base.match_token_into(5, 2196, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2200isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_83(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 166isize, 83, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2207isize, self.parse_rule_precedence_from_generated(85, 0), __ctx); - let mut __loop_iter_2225 = false; - loop { - self.base.sync_into(atn(), 2225, &mut __ctx, __loop_iter_2225, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2225) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(332, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(332, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2225, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2225 = true; - let mut __loop_iter_2211 = false; - loop { - self.base.sync_into(atn(), 2211, &mut __ctx, __loop_iter_2211, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 46 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2211, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2211 = true; - self.base.match_token_into(5, 2210, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2214isize, self.dispatch_generated_rule(84, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2218 = false; - loop { - self.base.sync_into(atn(), 2218, &mut __ctx, __loop_iter_2218, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2218) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(331, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(331, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2218, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2218 = true; - self.base.match_token_into(5, 2217, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2221isize, self.parse_rule_precedence_from_generated(85, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_84(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 168isize, 84, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(46, 2229, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(26, 2230, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_85(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 170isize, 85, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2231isize, self.parse_rule_precedence_from_generated(86, 0), __ctx); - let mut __loop_iter_2243 = false; - loop { - self.base.sync_into(atn(), 2243, &mut __ctx, __loop_iter_2243, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2243) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(334, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(334, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2243, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2243 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2232isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2236 = false; - loop { - self.base.sync_into(atn(), 2236, &mut __ctx, __loop_iter_2236, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2236) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(333, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(333, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2236, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2236 = true; - self.base.match_token_into(5, 2235, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2239isize, self.parse_rule_precedence_from_generated(86, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_86(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 172isize, 86, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2246isize, self.parse_rule_precedence_from_generated(87, 0), __ctx); - let mut __loop_iter_2257 = false; - loop { - self.base.sync_into(atn(), 2257, &mut __ctx, __loop_iter_2257, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2257) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(336, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(336, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2257, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2257 = true; - self.base.match_set_into(&[(36, 37)], 2251, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2251 = false; - loop { - self.base.sync_into(atn(), 2251, &mut __ctx, __loop_iter_2251, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2251) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(335, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(335, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2251, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2251 = true; - self.base.match_token_into(5, 2250, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2254isize, self.parse_rule_precedence_from_generated(87, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_87(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 174isize, 87, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2260isize, self.parse_rule_precedence_from_generated(88, 0), __ctx); - let mut __loop_iter_2272 = false; - loop { - self.base.sync_into(atn(), 2272, &mut __ctx, __loop_iter_2272, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2272) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(338, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(338, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2272, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2272 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2261isize, self.dispatch_generated_rule(142, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2265 = false; - loop { - self.base.sync_into(atn(), 2265, &mut __ctx, __loop_iter_2265, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2265) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(337, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(337, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2265, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2265 = true; - self.base.match_token_into(5, 2264, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2268isize, self.parse_rule_precedence_from_generated(88, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_88(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 176isize, 88, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2275isize, self.parse_rule_precedence_from_generated(89, 0), __ctx); - let mut __loop_iter_2287 = false; - loop { - self.base.sync_into(atn(), 2287, &mut __ctx, __loop_iter_2287, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2287) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(340, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(340, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2287, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2287 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2276isize, self.dispatch_generated_rule(143, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2280 = false; - loop { - self.base.sync_into(atn(), 2280, &mut __ctx, __loop_iter_2280, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2280) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(339, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(339, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2280, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2280 = true; - self.base.match_token_into(5, 2279, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2283isize, self.parse_rule_precedence_from_generated(89, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_89(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 178isize, 89, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2290isize, self.parse_rule_precedence_from_generated(90, 0), __ctx); - let mut __loop_iter_2308 = false; - loop { - self.base.sync_into(atn(), 2308, &mut __ctx, __loop_iter_2308, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2308) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(343, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(343, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2308, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2308 = true; - let mut __loop_iter_2294 = false; - loop { - self.base.sync_into(atn(), 2294, &mut __ctx, __loop_iter_2294, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 53 | 102 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2294, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2294 = true; - self.base.match_token_into(5, 2293, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2297isize, self.dispatch_generated_rule(144, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2301 = false; - loop { - self.base.sync_into(atn(), 2301, &mut __ctx, __loop_iter_2301, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2301, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2301 = true; - self.base.match_token_into(5, 2300, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2304isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_90(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 180isize, 90, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2314 = false; - loop { - self.base.sync_into(atn(), 2314, &mut __ctx, __loop_iter_2314, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2314) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(344, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(344, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2314, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2314 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2311isize, self.dispatch_generated_rule(91, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2317isize, self.parse_rule_precedence_from_generated(92, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_91(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 182isize, 91, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18..=21 | 24..=25 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2328, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18..=21 | 24..=25 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2328, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2319isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2320isize, self.dispatch_generated_rule(66, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2321isize, self.dispatch_generated_rule(145, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2325 = false; - loop { - self.base.sync_into(atn(), 2325, &mut __ctx, __loop_iter_2325, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2325) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(345, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(345, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2325, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2325 = true; - self.base.match_token_into(5, 2324, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_92(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 184isize, 92, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2330isize, self.parse_rule_precedence_from_generated(106, 0), __ctx); - let mut __loop_iter_2334 = false; - loop { - self.base.sync_into(atn(), 2334, &mut __ctx, __loop_iter_2334, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2334) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(347, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(347, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2334, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2334 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2331isize, self.dispatch_generated_rule(93, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_93(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 186isize, 93, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 20..=21 | 25 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 13 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 | 38 | 46 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2342, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2342) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(348, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(348, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2342, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2337isize, self.dispatch_generated_rule(146, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2338isize, self.dispatch_generated_rule(103, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2339isize, self.parse_rule_precedence_from_generated(101, 0), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2340isize, self.parse_rule_precedence_from_generated(99, 0), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2341isize, self.dispatch_generated_rule(100, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_94(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 188isize, 94, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 11 | 13 | 38 | 41 | 43 | 58..=62 | 76..=77 | 85..=86 | 89 | 91..=92 | 98..=101 | 137 | 140..=147 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2349, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2349) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(349, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(349, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2349, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2344isize, self.parse_rule_precedence_from_generated(92, 0), __ctx); - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2345isize, self.dispatch_generated_rule(98, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2347isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2348isize, self.dispatch_generated_rule(95, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_95(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 190isize, 95, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 2355, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2355 = false; - loop { - self.base.sync_into(atn(), 2355, &mut __ctx, __loop_iter_2355, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2355) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(350, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(350, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2355, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2355 = true; - self.base.match_token_into(5, 2354, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2358isize, self.dispatch_generated_rule(94, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2362 = false; - loop { - self.base.sync_into(atn(), 2362, &mut __ctx, __loop_iter_2362, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2362, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2362 = true; - self.base.match_token_into(5, 2361, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 2366, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_96(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 192isize, 96, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2369, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2369) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(352, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(352, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2369, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2367isize, self.parse_rule_precedence_from_generated(90, 0), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2368isize, self.dispatch_generated_rule(97, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_97(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 194isize, 97, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 2375, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2375 = false; - loop { - self.base.sync_into(atn(), 2375, &mut __ctx, __loop_iter_2375, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2375) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(353, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(353, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2375, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2375 = true; - self.base.match_token_into(5, 2374, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2378isize, self.dispatch_generated_rule(96, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2382 = false; - loop { - self.base.sync_into(atn(), 2382, &mut __ctx, __loop_iter_2382, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2382, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2382 = true; - self.base.match_token_into(5, 2381, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 2386, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_98(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 196isize, 98, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 47 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 7 | 38 | 46 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2390, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 47 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 7 | 38 | 46 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2390, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2387isize, self.dispatch_generated_rule(103, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2388isize, self.parse_rule_precedence_from_generated(99, 0), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2389isize, self.dispatch_generated_rule(100, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_99(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 198isize, 99, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(11, 2396, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2396 = false; - loop { - self.base.sync_into(atn(), 2396, &mut __ctx, __loop_iter_2396, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2396) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(356, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(356, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2396, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2396 = true; - self.base.match_token_into(5, 2395, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2399isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - let mut __loop_iter_2416 = false; - loop { - self.base.sync_into(atn(), 2416, &mut __ctx, __loop_iter_2416, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2416) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(359, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(359, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2416, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2416 = true; - let mut __loop_iter_2403 = false; - loop { - self.base.sync_into(atn(), 2403, &mut __ctx, __loop_iter_2403, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2403, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2403 = true; - self.base.match_token_into(5, 2402, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2410, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2410 = false; - loop { - self.base.sync_into(atn(), 2410, &mut __ctx, __loop_iter_2410, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2410) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(358, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(358, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2410, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2410 = true; - self.base.match_token_into(5, 2409, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2413isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2426, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2426) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(361, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(361, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2426, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2422 = false; - loop { - self.base.sync_into(atn(), 2422, &mut __ctx, __loop_iter_2422, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2422, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2422 = true; - self.base.match_token_into(5, 2421, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2427, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2431 = false; - loop { - self.base.sync_into(atn(), 2431, &mut __ctx, __loop_iter_2431, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2431, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2431 = true; - self.base.match_token_into(5, 2430, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(12, 2435, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_100(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 200isize, 100, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2436isize, self.dispatch_generated_rule(148, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2440 = false; - loop { - self.base.sync_into(atn(), 2440, &mut __ctx, __loop_iter_2440, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 63..=71 | 73..=74 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2440, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2440 = true; - self.base.match_token_into(5, 2439, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2446, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2446, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2443isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2444isize, self.parse_rule_precedence_from_generated(107, 0), __ctx); - } - 3 => { - self.base.match_token_into(74, 2447, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_101(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 202isize, 101, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2449, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 47 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 9 | 13 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2449, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2448isize, self.dispatch_generated_rule(103, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 13 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2456, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2456) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(367, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(367, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2456, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 2452, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 13 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2452, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2451isize, self.parse_rule_precedence_from_generated(104, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2454isize, self.dispatch_generated_rule(102, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2455isize, self.parse_rule_precedence_from_generated(104, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_102(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 204isize, 102, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __loop_iter_2461 = false; - loop { - self.base.sync_into(atn(), 2461, &mut __ctx, __loop_iter_2461, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 13 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2461, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2461 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2458isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2465, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2465, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2464isize, self.dispatch_generated_rule(66, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2470 = false; - loop { - self.base.sync_into(atn(), 2470, &mut __ctx, __loop_iter_2470, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2470, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2470 = true; - self.base.match_token_into(5, 2469, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2473isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_103(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 206isize, 103, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(47, 2479, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2479 = false; - loop { - self.base.sync_into(atn(), 2479, &mut __ctx, __loop_iter_2479, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 15 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 104 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2479, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2479 = true; - self.base.match_token_into(5, 2478, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2482isize, self.dispatch_generated_rule(55, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2499 = false; - loop { - self.base.sync_into(atn(), 2499, &mut __ctx, __loop_iter_2499, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2499) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(374, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(374, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2499, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2499 = true; - let mut __loop_iter_2486 = false; - loop { - self.base.sync_into(atn(), 2486, &mut __ctx, __loop_iter_2486, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2486, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2486 = true; - self.base.match_token_into(5, 2485, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2493, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2493 = false; - loop { - self.base.sync_into(atn(), 2493, &mut __ctx, __loop_iter_2493, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 15 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 104 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2493, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2493 = true; - self.base.match_token_into(5, 2492, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2496isize, self.dispatch_generated_rule(55, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2509, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2509) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(376, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(376, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2509, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2505 = false; - loop { - self.base.sync_into(atn(), 2505, &mut __ctx, __loop_iter_2505, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2505, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2505 = true; - self.base.match_token_into(5, 2504, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2510, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2514 = false; - loop { - self.base.sync_into(atn(), 2514, &mut __ctx, __loop_iter_2514, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 48 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2514, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2514 = true; - self.base.match_token_into(5, 2513, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(48, 2518, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_104(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 208isize, 104, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 2523, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2523 = false; - loop { - self.base.sync_into(atn(), 2523, &mut __ctx, __loop_iter_2523, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2523) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(378, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(378, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2523, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2523 = true; - self.base.match_token_into(5, 2522, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2561, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 13 | 15 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2561, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2526isize, self.parse_rule_precedence_from_generated(105, 0), __ctx); - let mut __loop_iter_2543 = false; - loop { - self.base.sync_into(atn(), 2543, &mut __ctx, __loop_iter_2543, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2543) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(381, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(381, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2543, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2543 = true; - let mut __loop_iter_2530 = false; - loop { - self.base.sync_into(atn(), 2530, &mut __ctx, __loop_iter_2530, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2530, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2530 = true; - self.base.match_token_into(5, 2529, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2537, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2537 = false; - loop { - self.base.sync_into(atn(), 2537, &mut __ctx, __loop_iter_2537, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2537) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(380, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(380, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2537, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2537 = true; - self.base.match_token_into(5, 2536, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2540isize, self.parse_rule_precedence_from_generated(105, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2553, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2553) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(383, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(383, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2553, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2549 = false; - loop { - self.base.sync_into(atn(), 2549, &mut __ctx, __loop_iter_2549, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2549, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2549 = true; - self.base.match_token_into(5, 2548, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2554, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2558 = false; - loop { - self.base.sync_into(atn(), 2558, &mut __ctx, __loop_iter_2558, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2558, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2558 = true; - self.base.match_token_into(5, 2557, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(10, 2564, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_105(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 210isize, 105, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2566, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2566) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(386, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(386, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2566, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2565isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2571 = false; - loop { - self.base.sync_into(atn(), 2571, &mut __ctx, __loop_iter_2571, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2571) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(387, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(387, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2571, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2571 = true; - self.base.match_token_into(5, 2570, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2588, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2588) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(390, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(390, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2588, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2574isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2578 = false; - loop { - self.base.sync_into(atn(), 2578, &mut __ctx, __loop_iter_2578, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2578, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2578 = true; - self.base.match_token_into(5, 2577, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(28, 2585, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2585 = false; - loop { - self.base.sync_into(atn(), 2585, &mut __ctx, __loop_iter_2585, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2585) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(389, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(389, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2585, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2585 = true; - self.base.match_token_into(5, 2584, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2591, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 15 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2591, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(15, 2592, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2596 = false; - loop { - self.base.sync_into(atn(), 2596, &mut __ctx, __loop_iter_2596, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2596) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(392, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(392, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2596, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2596 = true; - self.base.match_token_into(5, 2595, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2599isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_106(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 212isize, 106, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 137 | 140..=147 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 38 | 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 76 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 61 | 85 => antlr4_runtime::ParserAtnPrediction { alt: 9, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 | 86 => antlr4_runtime::ParserAtnPrediction { alt: 10, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 89 => antlr4_runtime::ParserAtnPrediction { alt: 11, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 91 => antlr4_runtime::ParserAtnPrediction { alt: 12, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 92 => antlr4_runtime::ParserAtnPrediction { alt: 13, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 58..=60 | 98..=101 => antlr4_runtime::ParserAtnPrediction { alt: 14, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2615, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2615) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(393, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(393, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2615, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2601isize, self.parse_rule_precedence_from_generated(107, 0), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2602isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2603isize, self.dispatch_generated_rule(109, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2604isize, self.dispatch_generated_rule(110, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2605isize, self.dispatch_generated_rule(136, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2606isize, self.dispatch_generated_rule(121, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2607isize, self.parse_rule_precedence_from_generated(122, 0), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2608isize, self.parse_rule_precedence_from_generated(108, 0), __ctx); - } - 9 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2609isize, self.dispatch_generated_rule(123, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 10 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2610isize, self.dispatch_generated_rule(124, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 11 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2611isize, self.parse_rule_precedence_from_generated(125, 0), __ctx); - } - 12 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2612isize, self.parse_rule_precedence_from_generated(127, 0), __ctx); - } - 13 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2613isize, self.dispatch_generated_rule(132, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 14 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2614isize, self.parse_rule_precedence_from_generated(135, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_107(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 214isize, 107, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 2621, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2621 = false; - loop { - self.base.sync_into(atn(), 2621, &mut __ctx, __loop_iter_2621, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2621) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(394, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(394, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2621, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2621 = true; - self.base.match_token_into(5, 2620, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2624isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - let mut __loop_iter_2628 = false; - loop { - self.base.sync_into(atn(), 2628, &mut __ctx, __loop_iter_2628, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2628, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2628 = true; - self.base.match_token_into(5, 2627, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 2632, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_108(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 216isize, 108, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(11, 2637, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2637 = false; - loop { - self.base.sync_into(atn(), 2637, &mut __ctx, __loop_iter_2637, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2637) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(396, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(396, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2637, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2637 = true; - self.base.match_token_into(5, 2636, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2675, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2675, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2640isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - let mut __loop_iter_2657 = false; - loop { - self.base.sync_into(atn(), 2657, &mut __ctx, __loop_iter_2657, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2657) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(399, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(399, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2657, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2657 = true; - let mut __loop_iter_2644 = false; - loop { - self.base.sync_into(atn(), 2644, &mut __ctx, __loop_iter_2644, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2644, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2644 = true; - self.base.match_token_into(5, 2643, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2651, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2651 = false; - loop { - self.base.sync_into(atn(), 2651, &mut __ctx, __loop_iter_2651, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2651) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(398, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(398, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2651, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2651 = true; - self.base.match_token_into(5, 2650, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2654isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2667, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2667) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(401, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(401, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2667, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2663 = false; - loop { - self.base.sync_into(atn(), 2663, &mut __ctx, __loop_iter_2663, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2663, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2663 = true; - self.base.match_token_into(5, 2662, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2668, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2672 = false; - loop { - self.base.sync_into(atn(), 2672, &mut __ctx, __loop_iter_2672, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2672, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2672 = true; - self.base.match_token_into(5, 2671, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(12, 2678, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_109(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 218isize, 109, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(137, 137), (140, 147)], 2680, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_110(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 220isize, 110, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 151 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 152 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2683, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 151 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 152 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2683, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2681isize, self.dispatch_generated_rule(111, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2682isize, self.dispatch_generated_rule(112, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_111(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 222isize, 111, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(151, 2690, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2690 = false; - loop { - self.base.sync_into(atn(), 2690, &mut __ctx, __loop_iter_2690, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 161..=164 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 160 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2690, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2690 = true; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 161..=163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 164 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2688, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 161..=163 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 164 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2688, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2686isize, self.dispatch_generated_rule(113, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2687isize, self.parse_rule_precedence_from_generated(114, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(160, 2694, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_112(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 224isize, 112, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(152, 2701, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2701 = false; - loop { - self.base.sync_into(atn(), 2701, &mut __ctx, __loop_iter_2701, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 166..=169 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 165 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2701, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2701 = true; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 167..=168 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 169 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2699, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2699) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(407, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(407, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2699, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2696isize, self.dispatch_generated_rule(115, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2697isize, self.parse_rule_precedence_from_generated(116, 0), __ctx); - } - 3 => { - self.base.match_token_into(166, 2700, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(165, 2705, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_113(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 226isize, 113, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(161, 163)], 2707, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_114(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 228isize, 114, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(164, 2712, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2712 = false; - loop { - self.base.sync_into(atn(), 2712, &mut __ctx, __loop_iter_2712, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2712) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(409, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(409, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2712, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2712 = true; - self.base.match_token_into(5, 2711, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2715isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - let mut __loop_iter_2719 = false; - loop { - self.base.sync_into(atn(), 2719, &mut __ctx, __loop_iter_2719, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2719, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2719 = true; - self.base.match_token_into(5, 2718, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(14, 2723, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_115(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 230isize, 115, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(166, 168)], 2725, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_116(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 232isize, 116, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(169, 2730, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2730 = false; - loop { - self.base.sync_into(atn(), 2730, &mut __ctx, __loop_iter_2730, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2730) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(411, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(411, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2730, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2730 = true; - self.base.match_token_into(5, 2729, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2733isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - let mut __loop_iter_2737 = false; - loop { - self.base.sync_into(atn(), 2737, &mut __ctx, __loop_iter_2737, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2737, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2737 = true; - self.base.match_token_into(5, 2736, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(14, 2741, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_117(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 234isize, 117, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(13, 2746, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2746 = false; - loop { - self.base.sync_into(atn(), 2746, &mut __ctx, __loop_iter_2746, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2746) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(413, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(413, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2746, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2746 = true; - self.base.match_token_into(5, 2745, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2765, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2765) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(417, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(417, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2765, &__prediction); - match __prediction.alt { - 1 => { - self.base.sync_into(atn(), 2750, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2750) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(414, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(414, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2750, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2749isize, self.dispatch_generated_rule(118, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2755 = false; - loop { - self.base.sync_into(atn(), 2755, &mut __ctx, __loop_iter_2755, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 34 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2755, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2755 = true; - self.base.match_token_into(5, 2754, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(34, 2762, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2762 = false; - loop { - self.base.sync_into(atn(), 2762, &mut __ctx, __loop_iter_2762, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2762) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(416, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(416, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2762, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2762 = true; - self.base.match_token_into(5, 2761, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2767isize, self.dispatch_generated_rule(64, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2771 = false; - loop { - self.base.sync_into(atn(), 2771, &mut __ctx, __loop_iter_2771, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2771, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2771 = true; - self.base.match_token_into(5, 2770, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(14, 2775, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_118(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 236isize, 118, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2776isize, self.dispatch_generated_rule(119, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2793 = false; - loop { - self.base.sync_into(atn(), 2793, &mut __ctx, __loop_iter_2793, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2793) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(421, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(421, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2793, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2793 = true; - let mut __loop_iter_2780 = false; - loop { - self.base.sync_into(atn(), 2780, &mut __ctx, __loop_iter_2780, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2780, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2780 = true; - self.base.match_token_into(5, 2779, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2787, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2787 = false; - loop { - self.base.sync_into(atn(), 2787, &mut __ctx, __loop_iter_2787, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2787) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(420, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(420, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2787, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2787 = true; - self.base.match_token_into(5, 2786, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2790isize, self.dispatch_generated_rule(119, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 2803, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2803) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(423, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(423, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2803, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2799 = false; - loop { - self.base.sync_into(atn(), 2799, &mut __ctx, __loop_iter_2799, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2799, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2799 = true; - self.base.match_token_into(5, 2798, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 2804, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_119(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 238isize, 119, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2823, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 5 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2823, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2805isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2806isize, self.dispatch_generated_rule(34, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 2821, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2821) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(426, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(426, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2821, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2810 = false; - loop { - self.base.sync_into(atn(), 2810, &mut __ctx, __loop_iter_2810, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2810, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2810 = true; - self.base.match_token_into(5, 2809, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 2817, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2817 = false; - loop { - self.base.sync_into(atn(), 2817, &mut __ctx, __loop_iter_2817, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2817, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2817 = true; - self.base.match_token_into(5, 2816, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2820isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_120(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 240isize, 120, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2826, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 124 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 76 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2826, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(124, 2827, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2831 = false; - loop { - self.base.sync_into(atn(), 2831, &mut __ctx, __loop_iter_2831, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 76 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2831, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2831 = true; - self.base.match_token_into(5, 2830, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(76, 2850, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2850, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2850) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(432, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(432, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2850, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2838 = false; - loop { - self.base.sync_into(atn(), 2838, &mut __ctx, __loop_iter_2838, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2838, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2838 = true; - self.base.match_token_into(5, 2837, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2841isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2845 = false; - loop { - self.base.sync_into(atn(), 2845, &mut __ctx, __loop_iter_2845, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2845, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2845 = true; - self.base.match_token_into(5, 2844, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(7, 2849, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2855 = false; - loop { - self.base.sync_into(atn(), 2855, &mut __ctx, __loop_iter_2855, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2855, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2855 = true; - self.base.match_token_into(5, 2854, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2858isize, self.parse_rule_precedence_from_generated(39, 0), __ctx); - self.base.sync_into(atn(), 2873, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2873) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(436, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(436, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2873, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2862 = false; - loop { - self.base.sync_into(atn(), 2862, &mut __ctx, __loop_iter_2862, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2862, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2862 = true; - self.base.match_token_into(5, 2861, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 2869, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2869 = false; - loop { - self.base.sync_into(atn(), 2869, &mut __ctx, __loop_iter_2869, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2869, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2869 = true; - self.base.match_token_into(5, 2868, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2872isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2882, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2882) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(438, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(438, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2882, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2878 = false; - loop { - self.base.sync_into(atn(), 2878, &mut __ctx, __loop_iter_2878, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 88 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2878, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2878 = true; - self.base.match_token_into(5, 2877, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2881isize, self.dispatch_generated_rule(23, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2891, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2891) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(440, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(440, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2891, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2887 = false; - loop { - self.base.sync_into(atn(), 2887, &mut __ctx, __loop_iter_2887, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 | 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2887, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2887 = true; - self.base.match_token_into(5, 2886, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2890isize, self.dispatch_generated_rule(32, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_121(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 242isize, 121, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 13 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 76 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2895, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 13 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 76 | 124 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2895, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2893isize, self.dispatch_generated_rule(117, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2894isize, self.parse_rule_precedence_from_generated(120, 0), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_122(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 244isize, 122, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 2898, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 116 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2898, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(116, 2899, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_2903 = false; - loop { - self.base.sync_into(atn(), 2903, &mut __ctx, __loop_iter_2903, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 77 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2903, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2903 = true; - self.base.match_token_into(5, 2902, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(77, 2927, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2927, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2927) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(447, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(447, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2927, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2910 = false; - loop { - self.base.sync_into(atn(), 2910, &mut __ctx, __loop_iter_2910, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2910, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2910 = true; - self.base.match_token_into(5, 2909, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 2917, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2917 = false; - loop { - self.base.sync_into(atn(), 2917, &mut __ctx, __loop_iter_2917, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2917) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(445, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(445, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2917, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2917 = true; - self.base.match_token_into(5, 2916, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2920isize, self.parse_rule_precedence_from_generated(16, 0), __ctx); - let mut __loop_iter_2924 = false; - loop { - self.base.sync_into(atn(), 2924, &mut __ctx, __loop_iter_2924, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2924) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(446, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(446, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2924, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2924 = true; - self.base.match_token_into(5, 2923, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2936, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2936) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(449, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(449, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2936, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_2932 = false; - loop { - self.base.sync_into(atn(), 2932, &mut __ctx, __loop_iter_2932, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2932, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2932 = true; - self.base.match_token_into(5, 2931, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2935isize, self.dispatch_generated_rule(13, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_123(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 246isize, 123, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(61, 61), (85, 85)], 2939, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_124(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 248isize, 124, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 2964, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 86 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 62 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2964, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(86, 2957, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 2957, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2957) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(452, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(452, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2957, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(47, 2945, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2945 = false; - loop { - self.base.sync_into(atn(), 2945, &mut __ctx, __loop_iter_2945, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2945, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2945 = true; - self.base.match_token_into(5, 2944, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2948isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_2952 = false; - loop { - self.base.sync_into(atn(), 2952, &mut __ctx, __loop_iter_2952, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 48 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2952, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2952 = true; - self.base.match_token_into(5, 2951, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(48, 2956, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.sync_into(atn(), 2961, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2961) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(453, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(453, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2961, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(41, 2960, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2960isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - self.base.match_token_into(62, 2965, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_125(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 250isize, 125, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(89, 2970, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2970 = false; - loop { - self.base.sync_into(atn(), 2970, &mut __ctx, __loop_iter_2970, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2970, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2970 = true; - self.base.match_token_into(5, 2969, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(9, 2977, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2977 = false; - loop { - self.base.sync_into(atn(), 2977, &mut __ctx, __loop_iter_2977, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2977) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(456, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(456, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2977, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2977 = true; - self.base.match_token_into(5, 2976, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2980isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - let mut __loop_iter_2984 = false; - loop { - self.base.sync_into(atn(), 2984, &mut __ctx, __loop_iter_2984, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 2984, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2984 = true; - self.base.match_token_into(5, 2983, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(10, 2991, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_2991 = false; - loop { - self.base.sync_into(atn(), 2991, &mut __ctx, __loop_iter_2991, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2991) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(458, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(458, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2991, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_2991 = true; - self.base.match_token_into(5, 2990, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 90 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3025, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3025) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(465, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(465, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3025, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2994isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.sync_into(atn(), 2996, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 2996) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(459, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(459, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 2996, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 2995isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3001 = false; - loop { - self.base.sync_into(atn(), 3001, &mut __ctx, __loop_iter_3001, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3001) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(460, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(460, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3001, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3001 = true; - self.base.match_token_into(5, 3000, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 3005, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 27 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 90 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3005, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(27, 3006, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3010 = false; - loop { - self.base.sync_into(atn(), 3010, &mut __ctx, __loop_iter_3010, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3010, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3010 = true; - self.base.match_token_into(5, 3009, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(90, 3017, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3017 = false; - loop { - self.base.sync_into(atn(), 3017, &mut __ctx, __loop_iter_3017, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3017) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(463, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(463, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3017, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3017 = true; - self.base.match_token_into(5, 3016, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3022, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73..=86 | 88..=89 | 91..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 27 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3022, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3020isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(27, 3023, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 3 => { - self.base.match_token_into(27, 3026, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_126(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 252isize, 126, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(9, 3061, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 3061, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3061) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(471, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(471, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3061, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_3031 = false; - loop { - self.base.sync_into(atn(), 3031, &mut __ctx, __loop_iter_3031, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 78 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3031, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3031 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3028isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_3037 = false; - loop { - self.base.sync_into(atn(), 3037, &mut __ctx, __loop_iter_3037, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 78 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3037, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3037 = true; - self.base.match_token_into(5, 3036, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(78, 3044, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3044 = false; - loop { - self.base.sync_into(atn(), 3044, &mut __ctx, __loop_iter_3044, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3044) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(468, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(468, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3044, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3044 = true; - self.base.match_token_into(5, 3043, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3047isize, self.dispatch_generated_rule(33, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3051 = false; - loop { - self.base.sync_into(atn(), 3051, &mut __ctx, __loop_iter_3051, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 28 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3051, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3051 = true; - self.base.match_token_into(5, 3050, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(28, 3058, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3058 = false; - loop { - self.base.sync_into(atn(), 3058, &mut __ctx, __loop_iter_3058, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3058) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(470, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(470, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3058, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3058 = true; - self.base.match_token_into(5, 3057, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3063isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - self.base.match_token_into(10, 3065, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_127(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 254isize, 127, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(91, 3070, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3070 = false; - loop { - self.base.sync_into(atn(), 3070, &mut __ctx, __loop_iter_3070, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3070) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(472, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(472, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3070, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3070 = true; - self.base.match_token_into(5, 3069, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 3074, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 5 | 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3074, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3073isize, self.parse_rule_precedence_from_generated(126, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3079 = false; - loop { - self.base.sync_into(atn(), 3079, &mut __ctx, __loop_iter_3079, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3079, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3079 = true; - self.base.match_token_into(5, 3078, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(13, 3086, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3086 = false; - loop { - self.base.sync_into(atn(), 3086, &mut __ctx, __loop_iter_3086, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3086) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(475, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(475, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3086, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3086 = true; - self.base.match_token_into(5, 3085, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_3098 = false; - loop { - self.base.sync_into(atn(), 3098, &mut __ctx, __loop_iter_3098, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3098) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(477, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(477, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3098, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3098 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3089isize, self.dispatch_generated_rule(128, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3093 = false; - loop { - self.base.sync_into(atn(), 3093, &mut __ctx, __loop_iter_3093, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3093) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(476, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(476, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3093, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3093 = true; - self.base.match_token_into(5, 3092, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __loop_iter_3104 = false; - loop { - self.base.sync_into(atn(), 3104, &mut __ctx, __loop_iter_3104, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 14 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3104, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3104 = true; - self.base.match_token_into(5, 3103, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(14, 3108, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_128(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 256isize, 128, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 103..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3173, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 103..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 90 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3173, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3109isize, self.dispatch_generated_rule(129, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3126 = false; - loop { - self.base.sync_into(atn(), 3126, &mut __ctx, __loop_iter_3126, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3126) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(481, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(481, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3126, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3126 = true; - let mut __loop_iter_3113 = false; - loop { - self.base.sync_into(atn(), 3113, &mut __ctx, __loop_iter_3113, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3113, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3113 = true; - self.base.match_token_into(5, 3112, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 3120, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3120 = false; - loop { - self.base.sync_into(atn(), 3120, &mut __ctx, __loop_iter_3120, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3120) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(480, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(480, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3120, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3120 = true; - self.base.match_token_into(5, 3119, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3123isize, self.dispatch_generated_rule(129, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 3136, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3136) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(483, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(483, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3136, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_3132 = false; - loop { - self.base.sync_into(atn(), 3132, &mut __ctx, __loop_iter_3132, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3132, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3132 = true; - self.base.match_token_into(5, 3131, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 3137, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3141 = false; - loop { - self.base.sync_into(atn(), 3141, &mut __ctx, __loop_iter_3141, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 34 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3141, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3141 = true; - self.base.match_token_into(5, 3140, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(34, 3148, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3148 = false; - loop { - self.base.sync_into(atn(), 3148, &mut __ctx, __loop_iter_3148, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3148) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(485, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(485, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3148, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3148 = true; - self.base.match_token_into(5, 3147, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3151isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 3153, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3153) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(486, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(486, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3153, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3152isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - self.base.match_token_into(90, 3159, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3159 = false; - loop { - self.base.sync_into(atn(), 3159, &mut __ctx, __loop_iter_3159, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 34 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3159, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3159 = true; - self.base.match_token_into(5, 3158, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(34, 3166, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3166 = false; - loop { - self.base.sync_into(atn(), 3166, &mut __ctx, __loop_iter_3166, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3166) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(488, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(488, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3166, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3166 = true; - self.base.match_token_into(5, 3165, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3169isize, self.dispatch_generated_rule(67, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 3171, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3171) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(489, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(489, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3171, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3170isize, self.dispatch_generated_rule(74, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_129(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 258isize, 129, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 104 | 106 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 103 | 105 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3178, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 5 | 9 | 11 | 13 | 18..=21 | 24..=25 | 38 | 41 | 43 | 58..=71 | 73 | 76..=77 | 81..=86 | 88..=89 | 91..=94 | 98..=101 | 107..=137 | 140..=148 | 151..=152 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 104 | 106 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 103 | 105 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3178, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3175isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3176isize, self.dispatch_generated_rule(130, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3177isize, self.dispatch_generated_rule(131, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_130(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 260isize, 130, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3180isize, self.dispatch_generated_rule(140, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3184 = false; - loop { - self.base.sync_into(atn(), 3184, &mut __ctx, __loop_iter_3184, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3184) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(492, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(492, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3184, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3184 = true; - self.base.match_token_into(5, 3183, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3187isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_131(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 262isize, 131, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3189isize, self.dispatch_generated_rule(141, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3193 = false; - loop { - self.base.sync_into(atn(), 3193, &mut __ctx, __loop_iter_3193, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3193, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3193 = true; - self.base.match_token_into(5, 3192, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3196isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_132(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 264isize, 132, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(92, 3202, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3202 = false; - loop { - self.base.sync_into(atn(), 3202, &mut __ctx, __loop_iter_3202, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3202, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3202 = true; - self.base.match_token_into(5, 3201, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3205isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 93 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3233, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3233) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(500, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(500, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3233, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_3209 = false; - loop { - self.base.sync_into(atn(), 3209, &mut __ctx, __loop_iter_3209, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 93 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3209, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3209 = true; - self.base.match_token_into(5, 3208, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3212isize, self.dispatch_generated_rule(133, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3215 = true; - loop { - self.base.sync_into(atn(), 3215, &mut __ctx, __loop_iter_3215, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3215) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(496, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(496, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3215, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3215 = true; - let mut __loop_iter_3209 = false; - loop { - self.base.sync_into(atn(), 3209, &mut __ctx, __loop_iter_3209, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 93 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3209, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3209 = true; - self.base.match_token_into(5, 3208, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3212isize, self.dispatch_generated_rule(133, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.sync_into(atn(), 3224, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3224) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(498, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(498, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3224, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_3220 = false; - loop { - self.base.sync_into(atn(), 3220, &mut __ctx, __loop_iter_3220, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3220, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3220 = true; - self.base.match_token_into(5, 3219, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3223isize, self.dispatch_generated_rule(134, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - let mut __loop_iter_3229 = false; - loop { - self.base.sync_into(atn(), 3229, &mut __ctx, __loop_iter_3229, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 94 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3229, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3229 = true; - self.base.match_token_into(5, 3228, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3232isize, self.dispatch_generated_rule(134, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_133(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 266isize, 133, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(93, 3239, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3239 = false; - loop { - self.base.sync_into(atn(), 3239, &mut __ctx, __loop_iter_3239, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3239, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3239 = true; - self.base.match_token_into(5, 3238, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(9, 3246, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3246 = false; - loop { - self.base.sync_into(atn(), 3246, &mut __ctx, __loop_iter_3246, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3246, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3246 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3243isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3249isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.match_token_into(26, 3251, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3251isize, self.dispatch_generated_rule(49, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - self.base.sync_into(atn(), 3259, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 | 8 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 10 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3259, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_3255 = false; - loop { - self.base.sync_into(atn(), 3255, &mut __ctx, __loop_iter_3255, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 8 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3255, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3255 = true; - self.base.match_token_into(5, 3254, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(8, 3260, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(10, 3265, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3265 = false; - loop { - self.base.sync_into(atn(), 3265, &mut __ctx, __loop_iter_3265, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3265, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3265 = true; - self.base.match_token_into(5, 3264, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3268isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_134(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 268isize, 134, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(94, 3274, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3274 = false; - loop { - self.base.sync_into(atn(), 3274, &mut __ctx, __loop_iter_3274, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 13 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3274, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3274 = true; - self.base.match_token_into(5, 3273, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3277isize, self.dispatch_generated_rule(68, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_135(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 270isize, 135, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 98 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 58 | 99 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 100 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 59 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 101 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 60 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3295, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 98 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 58 | 99 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 100 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 59 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 101 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 60 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3295, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(98, 3283, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3283 = false; - loop { - self.base.sync_into(atn(), 3283, &mut __ctx, __loop_iter_3283, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3283) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(507, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(507, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3283, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3283 = true; - self.base.match_token_into(5, 3282, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3286isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - self.base.match_set_into(&[(58, 58), (99, 99)], 3289, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.sync_into(atn(), 3289, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3289) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(508, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(508, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3289, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3288isize, self.parse_rule_precedence_from_generated(76, 0), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 3 => { - self.base.match_token_into(100, 3296, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(59, 3296, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - self.base.match_token_into(101, 3296, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 6 => { - self.base.match_token_into(60, 3296, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_136(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 272isize, 136, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 3298, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 38 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3298, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3297isize, self.dispatch_generated_rule(61, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(38, 3304, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3304 = false; - loop { - self.base.sync_into(atn(), 3304, &mut __ctx, __loop_iter_3304, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73..=74 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3304, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3304 = true; - self.base.match_token_into(5, 3303, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3309, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 74 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3309, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3307isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(74, 3310, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_137(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 274isize, 137, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(29, 33)], 3312, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_138(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 276isize, 138, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(51, 52), (54, 55)], 3314, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_139(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 278isize, 139, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(47, 50)], 3316, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_140(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 280isize, 140, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(104, 104), (106, 106)], 3318, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_141(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 282isize, 141, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(103, 103), (105, 105)], 3320, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_142(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 284isize, 142, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(18, 19)], 3322, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_143(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 286isize, 143, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(15, 17)], 3324, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_144(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 288isize, 144, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(53, 53), (102, 102)], 3326, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_145(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 290isize, 145, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 20 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 21 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 24..=25 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3332, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 20 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 21 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 19 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 18 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 24..=25 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3332, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(20, 3333, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(21, 3333, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(19, 3333, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 4 => { - self.base.match_token_into(18, 3333, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3331isize, self.dispatch_generated_rule(147, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_146(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 292isize, 146, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 20 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 21 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 25 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3338, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 20 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 21 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 25 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3338, &__prediction); - match __prediction.alt { - 1 => { - self.base.match_token_into(20, 3339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - self.base.match_token_into(21, 3339, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(25, 3337, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3337isize, self.dispatch_generated_rule(147, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_147(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 294isize, 147, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(24, 25)], 3341, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_148(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 296isize, 148, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 7 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 46 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 38 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3357, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3357) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(517, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(517, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3357, &__prediction); - match __prediction.alt { - 1 => { - let mut __loop_iter_3345 = false; - loop { - self.base.sync_into(atn(), 3345, &mut __ctx, __loop_iter_3345, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3345, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3345 = true; - self.base.match_token_into(5, 3344, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(7, 3358, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - let mut __loop_iter_3352 = false; - loop { - self.base.sync_into(atn(), 3352, &mut __ctx, __loop_iter_3352, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 46 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3352, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3352 = true; - self.base.match_token_into(5, 3351, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3355isize, self.dispatch_generated_rule(149, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - self.base.match_token_into(38, 3358, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_149(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 298isize, 149, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(46, 3360, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_token_into(7, 3361, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_150(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 300isize, 150, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3364, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3364, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3362isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3363isize, self.dispatch_generated_rule(152, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3366 = true; - loop { - self.base.sync_into(atn(), 3366, &mut __ctx, __loop_iter_3366, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3366) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(519, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(519, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3366, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3366 = true; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3364, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109..=133 | 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3364, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3362isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3363isize, self.dispatch_generated_rule(152, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_151(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 302isize, 151, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131..=133 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3370, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131..=133 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3370, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3368isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3369isize, self.dispatch_generated_rule(164, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3372 = true; - loop { - self.base.sync_into(atn(), 3372, &mut __ctx, __loop_iter_3372, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3372) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(521, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(521, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3372, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3372 = true; - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131..=133 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3370, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131..=133 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3370, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3368isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3369isize, self.dispatch_generated_rule(164, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_152(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 304isize, 152, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 113..=118 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 | 130 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109..=112 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 119..=124 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 129 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 126..=128 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131..=133 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3382, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 113..=118 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 125 | 130 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 109..=112 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 119..=124 => antlr4_runtime::ParserAtnPrediction { alt: 4, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 129 => antlr4_runtime::ParserAtnPrediction { alt: 5, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 126..=128 => antlr4_runtime::ParserAtnPrediction { alt: 6, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 131..=133 => antlr4_runtime::ParserAtnPrediction { alt: 7, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 135..=136 => antlr4_runtime::ParserAtnPrediction { alt: 8, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3382, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3374isize, self.dispatch_generated_rule(155, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3375isize, self.dispatch_generated_rule(156, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3376isize, self.dispatch_generated_rule(157, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 4 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3377isize, self.dispatch_generated_rule(161, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 5 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3378isize, self.dispatch_generated_rule(162, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 6 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3379isize, self.dispatch_generated_rule(163, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 7 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3380isize, self.dispatch_generated_rule(164, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 8 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3381isize, self.dispatch_generated_rule(166, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3387 = false; - loop { - self.base.sync_into(atn(), 3387, &mut __ctx, __loop_iter_3387, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3387) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(523, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(523, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3387, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3387 = true; - self.base.match_token_into(5, 3386, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_153(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 306isize, 153, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3390isize, self.dispatch_generated_rule(154, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3393 = true; - loop { - self.base.sync_into(atn(), 3393, &mut __ctx, __loop_iter_3393, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3393) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(524, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(524, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3393, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3393 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3390isize, self.dispatch_generated_rule(154, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_154(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 308isize, 154, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3403, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 124 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3403, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3395isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - self.base.match_token_into(124, 3400, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3400 = false; - loop { - self.base.sync_into(atn(), 3400, &mut __ctx, __loop_iter_3400, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 9 | 41 | 43 | 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - }; - self.base.record_generated_prediction_diagnostic(atn(), 3400, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3400 = true; - self.base.match_token_into(5, 3399, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_155(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 310isize, 155, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(113, 118)], 3406, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_156(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 312isize, 156, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(125, 125), (130, 130)], 3408, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_157(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 314isize, 157, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(109, 112)], 3410, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_158(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 316isize, 158, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(104, 104), (107, 107)], 3412, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_159(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 318isize, 159, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3413isize, self.dispatch_generated_rule(160, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3416 = true; - loop { - self.base.sync_into(atn(), 3416, &mut __ctx, __loop_iter_3416, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3416) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(527, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(527, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3416, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3416 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3413isize, self.dispatch_generated_rule(160, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_160(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 320isize, 160, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - let mut __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 134 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 104 | 107 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => { - self.base.sync_into(atn(), 3433, &mut __ctx, false, &mut __sync_error)?; - __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - match self.base.la(1) { - 134 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 104 | 107 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 41 | 43 => antlr4_runtime::ParserAtnPrediction { alt: 3, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3433, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3418isize, self.dispatch_generated_rule(165, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3422 = false; - loop { - self.base.sync_into(atn(), 3422, &mut __ctx, __loop_iter_3422, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3422) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(528, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(528, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3422, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3422 = true; - self.base.match_token_into(5, 3421, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3425isize, self.dispatch_generated_rule(158, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3429 = false; - loop { - self.base.sync_into(atn(), 3429, &mut __ctx, __loop_iter_3429, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3429) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(529, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(529, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3429, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3429 = true; - self.base.match_token_into(5, 3428, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 3 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3432isize, self.dispatch_generated_rule(167, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_161(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 322isize, 161, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(119, 124)], 3436, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_162(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 324isize, 162, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(129, 3438, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_163(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 326isize, 163, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(126, 128)], 3440, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_164(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 328isize, 164, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(131, 133)], 3442, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_165(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 330isize, 165, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_into(134, 3444, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_166(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 332isize, 166, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(135, 136)], 3446, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_167(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 334isize, 167, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 3449, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3449) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(531, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(531, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3449, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3447isize, self.dispatch_generated_rule(168, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3448isize, self.dispatch_generated_rule(169, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - let mut __loop_iter_3454 = false; - loop { - self.base.sync_into(atn(), 3454, &mut __ctx, __loop_iter_3454, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3454) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(532, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(532, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3454, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3454 = true; - self.base.match_token_into(5, 3453, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_168(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 336isize, 168, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 3466, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3466) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(534, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(534, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3466, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3457isize, self.dispatch_generated_rule(170, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3461 = false; - loop { - self.base.sync_into(atn(), 3461, &mut __ctx, __loop_iter_3461, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3461, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3461 = true; - self.base.match_token_into(5, 3460, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - self.base.match_token_into(41, 3467, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(43, 3467, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3468isize, self.dispatch_generated_rule(171, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_169(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 338isize, 169, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 3479, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3479) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(536, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(536, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3479, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3470isize, self.dispatch_generated_rule(170, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3474 = false; - loop { - self.base.sync_into(atn(), 3474, &mut __ctx, __loop_iter_3474, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 11 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3474, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3474 = true; - self.base.match_token_into(5, 3473, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - 2 => { - self.base.match_token_into(41, 3480, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 3 => { - self.base.match_token_into(43, 3480, atn(), &mut __ctx, &mut __consumed_eof)?; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - self.base.match_token_into(11, 3483, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3482isize, self.dispatch_generated_rule(171, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3485 = true; - loop { - self.base.sync_into(atn(), 3485, &mut __ctx, __loop_iter_3485, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 63..=71 | 73 | 81..=84 | 88 | 93..=94 | 107..=136 | 148 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 12 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3485, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3485 = true; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3482isize, self.dispatch_generated_rule(171, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(12, 3488, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_170(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 340isize, 170, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_set_into(&[(41, 41), (43, 43)], 3490, atn(), &mut __ctx, &mut __consumed_eof)?; - self.base.match_set_into(&[(64, 71)], 3494, atn(), &mut __ctx, &mut __consumed_eof)?; - let mut __loop_iter_3494 = false; - loop { - self.base.sync_into(atn(), 3494, &mut __ctx, __loop_iter_3494, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 26 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3494, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3494 = true; - self.base.match_token_into(5, 3493, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(26, 3498, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_171(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 342isize, 171, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.sync_into(atn(), 3501, &mut __ctx, false, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3501) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(539, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(539, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3501, &__prediction); - match __prediction.alt { - 1 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3499isize, self.dispatch_generated_rule(18, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3500isize, self.dispatch_generated_rule(53, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_172(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 344isize, 172, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - self.base.match_token_set_into(atn().token_set(30).expect("generated parser token-set index"), 3504, atn(), &mut __ctx, &mut __consumed_eof)?; - } - success {} - recovery {} - } - } - - #[allow(dead_code)] - fn parse_generated_rule_173(&mut self, __precedence: i32, allow_fallback: bool) -> Result { - let _ = __precedence; - antlr4_runtime::__antlr4_rust_generated_rule! { - ordinary self, 346isize, 173, allow_fallback, atn(), GeneratedRuleError::Fatal; - retry [adaptive]; - bind (__ctx, __rule_start, __consumed_eof, __sync_error); - setup {} - body { - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3505isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - let mut __loop_iter_3516 = false; - loop { - self.base.sync_into(atn(), 3516, &mut __ctx, __loop_iter_3516, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = if let Some(__prediction) = self.base.ll1_decision_prediction(atn(), 3516) { - __prediction - } else { - let __prediction = { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - __simulator.adaptive_predict_stream_info_sll_probe(541, 0, self.base.input()) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - }; - if __prediction.requires_full_context && self.base.prediction_mode() != antlr4_runtime::PredictionMode::Sll { - let __simulator = self.simulator.get_or_insert_with(|| antlr4_runtime::ParserAtnSimulator::new_shared(atn())); - let __prediction_context = __simulator.intern_prediction_context(self.base.rule_context_version(), self.base.prediction_context_return_states(atn())); - __simulator.set_exact_ambig_detection(self.base.prediction_mode() == antlr4_runtime::PredictionMode::LlExactAmbigDetection); - __simulator.adaptive_predict_stream_info_with_context(541, 0, self.base.input(), __prediction_context) - .map_err(|__error| match __error { - antlr4_runtime::ParserAtnSimulatorError::NoViableAlt { index, .. } => self.base.no_viable_alternative_error_at(__decision_start, index), - _ => self.base.no_viable_alternative_error(__decision_start), - })? - } else { - __prediction - } - }; - self.base.record_generated_prediction_diagnostic(atn(), 3516, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3516 = true; - let mut __loop_iter_3509 = false; - loop { - self.base.sync_into(atn(), 3509, &mut __ctx, __loop_iter_3509, &mut __sync_error)?; - let __decision_start = antlr4_runtime::IntStream::index(self.base.input()); - let __prediction = match self.base.la(1) { - 5 => antlr4_runtime::ParserAtnPrediction { alt: 1, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - 7 => antlr4_runtime::ParserAtnPrediction { alt: 2, requires_full_context: false, has_semantic_context: false, diagnostic: None }, - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - }; - self.base.record_generated_prediction_diagnostic(atn(), 3509, &__prediction); - match __prediction.alt { - 1 => { - __loop_iter_3509 = true; - self.base.match_token_into(5, 3508, atn(), &mut __ctx, &mut __consumed_eof)?; - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - self.base.match_token_into(7, 3513, atn(), &mut __ctx, &mut __consumed_eof)?; - antlr4_runtime::__antlr4_rust_invoke_subrule!(self, 3513isize, self.dispatch_generated_rule(172, 0, false).map_err(GeneratedRuleError::into_error), __ctx); - } - 2 => { - break; - } - _ => return Err(self.base.no_viable_alternative_error(__decision_start)), - } - } - } - success {} - recovery {} - } - } - - - - pub fn kotlin_file(&mut self) -> Result { - self.parse_rule(0) - } - pub fn script(&mut self) -> Result { - self.parse_rule(1) - } - pub fn shebang_line(&mut self) -> Result { - self.parse_rule(2) - } - pub fn file_annotation(&mut self) -> Result { - self.parse_rule(3) - } - pub fn package_header(&mut self) -> Result { - self.parse_rule(4) - } - pub fn import_list(&mut self) -> Result { - self.parse_rule(5) - } - pub fn import_header(&mut self) -> Result { - self.parse_rule(6) - } - pub fn import_alias(&mut self) -> Result { - self.parse_rule(7) - } - pub fn top_level_object(&mut self) -> Result { - self.parse_rule(8) - } - pub fn type_alias(&mut self) -> Result { - self.parse_rule(9) - } - pub fn declaration(&mut self) -> Result { - self.parse_rule(10) - } - pub fn class_declaration(&mut self) -> Result { - self.parse_rule(11) - } - pub fn primary_constructor(&mut self) -> Result { - self.parse_rule(12) - } - pub fn class_body(&mut self) -> Result { - self.parse_rule(13) - } - pub fn class_parameters(&mut self) -> Result { - self.parse_rule(14) - } - pub fn class_parameter(&mut self) -> Result { - self.parse_rule(15) - } - pub fn delegation_specifiers(&mut self) -> Result { - self.parse_rule(16) - } - pub fn delegation_specifier(&mut self) -> Result { - self.parse_rule(17) - } - pub fn constructor_invocation(&mut self) -> Result { - self.parse_rule(18) - } - pub fn annotated_delegation_specifier(&mut self) -> Result { - self.parse_rule(19) - } - pub fn explicit_delegation(&mut self) -> Result { - self.parse_rule(20) - } - pub fn type_parameters(&mut self) -> Result { - self.parse_rule(21) - } - pub fn type_parameter(&mut self) -> Result { - self.parse_rule(22) - } - pub fn type_constraints(&mut self) -> Result { - self.parse_rule(23) - } - pub fn type_constraint(&mut self) -> Result { - self.parse_rule(24) - } - pub fn class_member_declarations(&mut self) -> Result { - self.parse_rule(25) - } - pub fn class_member_declaration(&mut self) -> Result { - self.parse_rule(26) - } - pub fn anonymous_initializer(&mut self) -> Result { - self.parse_rule(27) - } - pub fn companion_object(&mut self) -> Result { - self.parse_rule(28) - } - pub fn function_value_parameters(&mut self) -> Result { - self.parse_rule(29) - } - pub fn function_value_parameter(&mut self) -> Result { - self.parse_rule(30) - } - pub fn function_declaration(&mut self) -> Result { - self.parse_rule(31) - } - pub fn function_body(&mut self) -> Result { - self.parse_rule(32) - } - pub fn variable_declaration(&mut self) -> Result { - self.parse_rule(33) - } - pub fn multi_variable_declaration(&mut self) -> Result { - self.parse_rule(34) - } - pub fn property_declaration(&mut self) -> Result { - self.parse_rule(35) - } - pub fn property_delegate(&mut self) -> Result { - self.parse_rule(36) - } - pub fn getter(&mut self) -> Result { - self.parse_rule(37) - } - pub fn setter(&mut self) -> Result { - self.parse_rule(38) - } - pub fn parameters_with_optional_type(&mut self) -> Result { - self.parse_rule(39) - } - pub fn function_value_parameter_with_optional_type(&mut self) -> Result { - self.parse_rule(40) - } - pub fn parameter_with_optional_type(&mut self) -> Result { - self.parse_rule(41) - } - pub fn parameter(&mut self) -> Result { - self.parse_rule(42) - } - pub fn object_declaration(&mut self) -> Result { - self.parse_rule(43) - } - pub fn secondary_constructor(&mut self) -> Result { - self.parse_rule(44) - } - pub fn constructor_delegation_call(&mut self) -> Result { - self.parse_rule(45) - } - pub fn enum_class_body(&mut self) -> Result { - self.parse_rule(46) - } - pub fn enum_entries(&mut self) -> Result { - self.parse_rule(47) - } - pub fn enum_entry(&mut self) -> Result { - self.parse_rule(48) - } - pub fn r#type(&mut self) -> Result { - self.parse_rule(49) - } - pub fn type_reference(&mut self) -> Result { - self.parse_rule(50) - } - pub fn nullable_type(&mut self) -> Result { - self.parse_rule(51) - } - pub fn quest(&mut self) -> Result { - self.parse_rule(52) - } - pub fn user_type(&mut self) -> Result { - self.parse_rule(53) - } - pub fn simple_user_type(&mut self) -> Result { - self.parse_rule(54) - } - pub fn type_projection(&mut self) -> Result { - self.parse_rule(55) - } - pub fn type_projection_modifiers(&mut self) -> Result { - self.parse_rule(56) - } - pub fn type_projection_modifier(&mut self) -> Result { - self.parse_rule(57) - } - pub fn function_type(&mut self) -> Result { - self.parse_rule(58) - } - pub fn function_type_parameters(&mut self) -> Result { - self.parse_rule(59) - } - pub fn parenthesized_type(&mut self) -> Result { - self.parse_rule(60) - } - pub fn receiver_type(&mut self) -> Result { - self.parse_rule(61) - } - pub fn parenthesized_user_type(&mut self) -> Result { - self.parse_rule(62) - } - pub fn definitely_non_nullable_type(&mut self) -> Result { - self.parse_rule(63) - } - pub fn statements(&mut self) -> Result { - self.parse_rule(64) - } - pub fn statement(&mut self) -> Result { - self.parse_rule(65) - } - pub fn label(&mut self) -> Result { - self.parse_rule(66) - } - pub fn control_structure_body(&mut self) -> Result { - self.parse_rule(67) - } - pub fn block(&mut self) -> Result { - self.parse_rule(68) - } - pub fn loop_statement(&mut self) -> Result { - self.parse_rule(69) - } - pub fn for_statement(&mut self) -> Result { - self.parse_rule(70) - } - pub fn while_statement(&mut self) -> Result { - self.parse_rule(71) - } - pub fn do_while_statement(&mut self) -> Result { - self.parse_rule(72) - } - pub fn assignment(&mut self) -> Result { - self.parse_rule(73) - } - pub fn semi(&mut self) -> Result { - self.parse_rule(74) - } - pub fn semis(&mut self) -> Result { - self.parse_rule(75) - } - pub fn expression(&mut self) -> Result { - self.parse_rule(76) - } - pub fn disjunction(&mut self) -> Result { - self.parse_rule(77) - } - pub fn conjunction(&mut self) -> Result { - self.parse_rule(78) - } - pub fn equality(&mut self) -> Result { - self.parse_rule(79) - } - pub fn comparison(&mut self) -> Result { - self.parse_rule(80) - } - pub fn generic_call_like_comparison(&mut self) -> Result { - self.parse_rule(81) - } - pub fn infix_operation(&mut self) -> Result { - self.parse_rule(82) - } - pub fn elvis_expression(&mut self) -> Result { - self.parse_rule(83) - } - pub fn elvis(&mut self) -> Result { - self.parse_rule(84) - } - pub fn infix_function_call(&mut self) -> Result { - self.parse_rule(85) - } - pub fn range_expression(&mut self) -> Result { - self.parse_rule(86) - } - pub fn additive_expression(&mut self) -> Result { - self.parse_rule(87) - } - pub fn multiplicative_expression(&mut self) -> Result { - self.parse_rule(88) - } - pub fn as_expression(&mut self) -> Result { - self.parse_rule(89) - } - pub fn prefix_unary_expression(&mut self) -> Result { - self.parse_rule(90) - } - pub fn unary_prefix(&mut self) -> Result { - self.parse_rule(91) - } - pub fn postfix_unary_expression(&mut self) -> Result { - self.parse_rule(92) - } - pub fn postfix_unary_suffix(&mut self) -> Result { - self.parse_rule(93) - } - pub fn directly_assignable_expression(&mut self) -> Result { - self.parse_rule(94) - } - pub fn parenthesized_directly_assignable_expression(&mut self) -> Result { - self.parse_rule(95) - } - pub fn assignable_expression(&mut self) -> Result { - self.parse_rule(96) - } - pub fn parenthesized_assignable_expression(&mut self) -> Result { - self.parse_rule(97) - } - pub fn assignable_suffix(&mut self) -> Result { - self.parse_rule(98) - } - pub fn indexing_suffix(&mut self) -> Result { - self.parse_rule(99) - } - pub fn navigation_suffix(&mut self) -> Result { - self.parse_rule(100) - } - pub fn call_suffix(&mut self) -> Result { - self.parse_rule(101) - } - pub fn annotated_lambda(&mut self) -> Result { - self.parse_rule(102) - } - pub fn type_arguments(&mut self) -> Result { - self.parse_rule(103) - } - pub fn value_arguments(&mut self) -> Result { - self.parse_rule(104) - } - pub fn value_argument(&mut self) -> Result { - self.parse_rule(105) - } - pub fn primary_expression(&mut self) -> Result { - self.parse_rule(106) - } - pub fn parenthesized_expression(&mut self) -> Result { - self.parse_rule(107) - } - pub fn collection_literal(&mut self) -> Result { - self.parse_rule(108) - } - pub fn literal_constant(&mut self) -> Result { - self.parse_rule(109) - } - pub fn string_literal(&mut self) -> Result { - self.parse_rule(110) - } - pub fn line_string_literal(&mut self) -> Result { - self.parse_rule(111) - } - pub fn multi_line_string_literal(&mut self) -> Result { - self.parse_rule(112) - } - pub fn line_string_content(&mut self) -> Result { - self.parse_rule(113) - } - pub fn line_string_expression(&mut self) -> Result { - self.parse_rule(114) - } - pub fn multi_line_string_content(&mut self) -> Result { - self.parse_rule(115) - } - pub fn multi_line_string_expression(&mut self) -> Result { - self.parse_rule(116) - } - pub fn lambda_literal(&mut self) -> Result { - self.parse_rule(117) - } - pub fn lambda_parameters(&mut self) -> Result { - self.parse_rule(118) - } - pub fn lambda_parameter(&mut self) -> Result { - self.parse_rule(119) - } - pub fn anonymous_function(&mut self) -> Result { - self.parse_rule(120) - } - pub fn function_literal(&mut self) -> Result { - self.parse_rule(121) - } - pub fn object_literal(&mut self) -> Result { - self.parse_rule(122) - } - pub fn this_expression(&mut self) -> Result { - self.parse_rule(123) - } - pub fn super_expression(&mut self) -> Result { - self.parse_rule(124) - } - pub fn if_expression(&mut self) -> Result { - self.parse_rule(125) - } - pub fn when_subject(&mut self) -> Result { - self.parse_rule(126) - } - pub fn when_expression(&mut self) -> Result { - self.parse_rule(127) - } - pub fn when_entry(&mut self) -> Result { - self.parse_rule(128) - } - pub fn when_condition(&mut self) -> Result { - self.parse_rule(129) - } - pub fn range_test(&mut self) -> Result { - self.parse_rule(130) - } - pub fn type_test(&mut self) -> Result { - self.parse_rule(131) - } - pub fn try_expression(&mut self) -> Result { - self.parse_rule(132) - } - pub fn catch_block(&mut self) -> Result { - self.parse_rule(133) - } - pub fn finally_block(&mut self) -> Result { - self.parse_rule(134) - } - pub fn jump_expression(&mut self) -> Result { - self.parse_rule(135) - } - pub fn callable_reference(&mut self) -> Result { - self.parse_rule(136) - } - pub fn assignment_and_operator(&mut self) -> Result { - self.parse_rule(137) - } - pub fn equality_operator(&mut self) -> Result { - self.parse_rule(138) - } - pub fn comparison_operator(&mut self) -> Result { - self.parse_rule(139) - } - pub fn in_operator(&mut self) -> Result { - self.parse_rule(140) - } - pub fn is_operator(&mut self) -> Result { - self.parse_rule(141) - } - pub fn additive_operator(&mut self) -> Result { - self.parse_rule(142) - } - pub fn multiplicative_operator(&mut self) -> Result { - self.parse_rule(143) - } - pub fn as_operator(&mut self) -> Result { - self.parse_rule(144) - } - pub fn prefix_unary_operator(&mut self) -> Result { - self.parse_rule(145) - } - pub fn postfix_unary_operator(&mut self) -> Result { - self.parse_rule(146) - } - pub fn excl(&mut self) -> Result { - self.parse_rule(147) - } - pub fn member_access_operator(&mut self) -> Result { - self.parse_rule(148) - } - pub fn safe_nav(&mut self) -> Result { - self.parse_rule(149) - } - pub fn modifiers(&mut self) -> Result { - self.parse_rule(150) - } - pub fn parameter_modifiers(&mut self) -> Result { - self.parse_rule(151) - } - pub fn modifier(&mut self) -> Result { - self.parse_rule(152) - } - pub fn type_modifiers(&mut self) -> Result { - self.parse_rule(153) - } - pub fn type_modifier(&mut self) -> Result { - self.parse_rule(154) - } - pub fn class_modifier(&mut self) -> Result { - self.parse_rule(155) - } - pub fn member_modifier(&mut self) -> Result { - self.parse_rule(156) - } - pub fn visibility_modifier(&mut self) -> Result { - self.parse_rule(157) - } - pub fn variance_modifier(&mut self) -> Result { - self.parse_rule(158) - } - pub fn type_parameter_modifiers(&mut self) -> Result { - self.parse_rule(159) - } - pub fn type_parameter_modifier(&mut self) -> Result { - self.parse_rule(160) - } - pub fn function_modifier(&mut self) -> Result { - self.parse_rule(161) - } - pub fn property_modifier(&mut self) -> Result { - self.parse_rule(162) - } - pub fn inheritance_modifier(&mut self) -> Result { - self.parse_rule(163) - } - pub fn parameter_modifier(&mut self) -> Result { - self.parse_rule(164) - } - pub fn reification_modifier(&mut self) -> Result { - self.parse_rule(165) - } - pub fn platform_modifier(&mut self) -> Result { - self.parse_rule(166) - } - pub fn annotation(&mut self) -> Result { - self.parse_rule(167) - } - pub fn single_annotation(&mut self) -> Result { - self.parse_rule(168) - } - pub fn multi_annotation(&mut self) -> Result { - self.parse_rule(169) - } - pub fn annotation_use_site_target(&mut self) -> Result { - self.parse_rule(170) - } - pub fn unescaped_annotation(&mut self) -> Result { - self.parse_rule(171) - } - pub fn simple_identifier(&mut self) -> Result { - self.parse_rule(172) - } - pub fn identifier(&mut self) -> Result { - self.parse_rule(173) - } - - - fn run_action(&mut self, _action: antlr4_runtime::ParserAction, _tree: antlr4_runtime::ParseTree) {} - -} - -antlr4_runtime::__antlr4_rust_parser_driver! { - type: KotlinParser, - fields: { - base: base, - simulator: simulator, - }, - atn: atn, - adaptive_direct: false, - fallback(parser, rule_index, precedence) { - parser.base.parse_atn_rule_with_runtime_options_and_precedence(atn(), rule_index, precedence, antlr4_runtime::ParserRuntimeOptions { action_indices: &[], track_alt_numbers: false, track_context_alt_numbers: false, predicates: &[], semantics: Some(parser_semantics()), rule_args: &[], member_actions: &[], return_actions: &[], unknown_predicate_policy: antlr4_runtime::UnknownSemanticPolicy::Error , ..antlr4_runtime::ParserRuntimeOptions::default() }) - } -} - - - -antlr4_runtime::__antlr4_rust_parser_facade! { - type: KotlinParser, - fields: { - base: base, - simulator: simulator, - generated_only: generated_only, - }, - metadata: metadata, - parser_atn: parser_atn, - reset(parser) { - parser.adaptive_atn.reset(); - } -} -} - -#[allow(warnings, missing_docs, clippy::all, clippy::pedantic, clippy::nursery)] -pub use self::__antlr4_rust_generated::*; diff --git a/crates/mehen-kotlin-parser/src/generated/semantics.json b/crates/mehen-kotlin-parser/src/generated/semantics.json deleted file mode 100644 index 0b6b7e5b..00000000 --- a/crates/mehen-kotlin-parser/src/generated/semantics.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "version": 2, - "policy": "error", - "note": "unknown coordinates currently default to assume-true; a future minor release changes the default to error", - "options": [ - { - "name": "tokenVocab", - "value": "KotlinLexer", - "line": 7, - "column": 10, - "disposition": "metadata" - } - ], - "grammars": [ - { - "kind": "lexer", - "name": "KotlinLexer", - "coordinates": [] - }, - { - "kind": "parser", - "name": "KotlinParser", - "coordinates": [] - } - ] -} diff --git a/crates/mehen-kotlin-parser/src/lib.rs b/crates/mehen-kotlin-parser/src/lib.rs deleted file mode 100644 index aa4a55bf..00000000 --- a/crates/mehen-kotlin-parser/src/lib.rs +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-kotlin-parser` — ANTLR-generated Kotlin lexer and parser. -//! -//! This crate holds **only** the machine-generated Kotlin lexer/parser -//! produced from the official Kotlin specification ANTLR grammar -//! (`Kotlin/kotlin-spec`, vendored in `grammar/`) running on the -//! [`antlr4_runtime`] Rust runtime. It carries no mehen-specific logic and -//! no dependency on `mehen-core`, so it can be consumed on its own — e.g. -//! `mehen-kotlin-parser = { git = "https://github.com/ophi-dev/mehen", tag = "…" }` -//! — the same way this repo consumes the ruff/oxc/sqruff parser crates. -//! -//! (Linked to the repository, not docs.rs: the analyzer crates are -//! `publish = false`, so they have no docs.rs page to link to.) -//! -//! The [`mehen-kotlin`](https://github.com/ophi-dev/mehen/tree/main/crates/mehen-kotlin) analyzer crate depends -//! on this one and walks the resulting [`antlr4_runtime::ParseTree`] to -//! compute metrics. -//! -//! ## Regenerating — never hand-edit -//! -//! The modules are produced by `cargo xtask antlr generate kotlin` from the -//! vendored grammar and checked in verbatim (see `src/generated/README.md` -//! and `grammar/PROVENANCE.md`). `cargo xtask antlr check-generated` guards -//! against drift in CI. -//! -//! ## Quickstart -//! -//! ```no_run -//! use mehen_kotlin_parser::kotlin_parser::{self, KotlinParser}; -//! use mehen_kotlin_parser::kotlin_lexer::KotlinLexer; -//! // `number_of_syntax_errors` is a `Parser`-trait method, so the trait -//! // must be in scope to call it. -//! use antlr4_runtime::Parser; -//! -//! # fn main() -> Result<(), antlr4_runtime::AntlrError> { -//! // One-call setup: build lexer + token stream + parser and run an entry -//! // rule. `parse_with_parser` keeps the parser so you can read diagnostics. -//! let out = kotlin_parser::parse_with_parser( -//! "fun main() {}\n", -//! KotlinLexer::new, -//! KotlinParser::kotlin_file, -//! )?; -//! let errors = out.parser.number_of_syntax_errors(); -//! let parsed = out.parser.into_parsed_file(out.result); -//! let _ = (errors, parsed.tree()); -//! # Ok(()) -//! # } -//! ``` - -#![forbid(unsafe_code)] - -/// Re-export of the ANTLR v4 Rust runtime the generated modules were built -/// against, so downstream crates can name the runtime types (`ParseTree`, -/// `Node`, `TokenView`, …) without pinning the runtime version themselves. -pub use antlr4_runtime; - -/// ANTLR-generated Kotlin lexer. -/// -/// Regenerate with `cargo xtask antlr generate kotlin` — never hand-edit. -#[path = "generated/kotlin_lexer.rs"] -pub mod kotlin_lexer; - -/// ANTLR-generated Kotlin parser. -/// -/// Regenerate with `cargo xtask antlr generate kotlin` — never hand-edit. -#[path = "generated/kotlin_parser.rs"] -pub mod kotlin_parser; diff --git a/crates/mehen-kotlin/Cargo.toml b/crates/mehen-kotlin/Cargo.toml deleted file mode 100644 index b1551414..00000000 --- a/crates/mehen-kotlin/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "mehen-kotlin" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — Kotlin language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -# The generated Kotlin lexer/parser now live in the standalone, publishable -# `mehen-kotlin-parser` crate (produced by `cargo xtask antlr generate -# kotlin`). This analyzer depends on it for the grammar and reaches the ANTLR -# runtime through its `antlr4_runtime` re-export. -mehen-kotlin-parser = { workspace = true } -# `mehen-antlr` owns the runtime version pin and the shared span/comment/ -# diagnostic helpers; the walker reaches the runtime types (`Node`, -# `RuleNodeView`, `TokenView`, …) through its `runtime` re-export. -mehen-antlr = { workspace = true } -smol_str = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-kotlin/src/lib.rs b/crates/mehen-kotlin/src/lib.rs deleted file mode 100644 index b91eae18..00000000 --- a/crates/mehen-kotlin/src/lib.rs +++ /dev/null @@ -1,382 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-kotlin` — Kotlin language analyzer. -//! -//! Kotlin is parsed by a parser generated from the **official Kotlin -//! specification ANTLR grammar** (`Kotlin/kotlin-spec`, vendored in -//! `grammar/`) running on the ANTLR Rust runtime via [`mehen_antlr`]. This -//! replaces the earlier tree-sitter-kotlin backend; the ANTLR grammar is a -//! richer, semantically-named CST (`whenEntry`, `elvisExpression`, -//! `catchBlock`, `jumpExpression` with explicit `THROW`/`RETURN`/`CONTINUE`/ -//! `BREAK` alternatives, `safeNav`, …) that lets the metric walker ask -//! direct structural questions instead of inferring them from anonymous -//! punctuation and parent/sibling shape. -//! -//! The generated lexer/parser modules live in [`generated`]; they are -//! produced by `cargo xtask antlr generate kotlin` and checked in verbatim -//! (see `src/generated/README.md`). They are not hand-edited and are -//! self-contained generated modules with their own lint and formatting -//! attributes. -//! -//! Metric coverage follows the same SonarKotlin-aligned definitions the -//! tree-sitter walker targeted (see [`walker`] for the per-metric table). -//! Where the richer grammar makes a metric *more* correct than the -//! tree-sitter approximation, the change is intentional and called out in -//! the walker's docs. - -#![forbid(unsafe_code)] - -mod walker; - -use mehen_antlr::DiagnosticCollector; -use mehen_antlr::runtime::{ParsedFile, Parser}; -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, LineIndex, - ParseDiagnostic, Result, SourceFile, SourceSpan, byte_offset_clamped, -}; - -use mehen_kotlin_parser::kotlin_lexer::KotlinLexer; -use mehen_kotlin_parser::kotlin_parser::{self, KotlinParser}; - -pub struct KotlinAnalyzer; - -/// A recovered parse: the flat-arena [`ParsedFile`] owns the token store and -/// CST storage, and the walker borrows [`Node`](mehen_antlr::runtime::Node) -/// views from it. `loc_tokens` is precomputed from the (eagerly buffered, -/// hidden-channel-inclusive) token store. -struct ParsedKotlin { - parsed: ParsedFile, - syntax_errors: usize, - lexer_diagnostics: Vec, - loc_tokens: Vec, -} - -impl KotlinAnalyzer { - pub fn new() -> Self { - Self - } - - /// Parse `source` and return the tree with the fewest recovered errors - /// from the two top-level entry rules. The preferred rule (per the file - /// extension) is tried first; the other is tried only if the preferred - /// one recovered any errors, so clean input parses exactly once. Ties go - /// to the preferred rule. Returns `None` only if both entry-rule calls - /// hard-fail (return `Err` rather than a recovered tree). - fn parse_best( - &self, - source: &str, - prefers_script: bool, - line_index: &LineIndex, - ) -> Option { - let preferred = self.parse_entry(source, prefers_script, line_index); - // A clean (zero-error) preferred parse wins outright — no second parse. - if preferred - .as_ref() - .is_some_and(|parsed| parsed.syntax_errors == 0) - { - return preferred; - } - let alternate = self.parse_entry(source, !prefers_script, line_index); - match (preferred, alternate) { - // Keep whichever recovered fewer errors; ties favor the preferred. - (Some(preferred), Some(alternate)) => { - Some(if alternate.syntax_errors < preferred.syntax_errors { - alternate - } else { - preferred - }) - } - (Some(preferred), None) => Some(preferred), - (None, Some(alternate)) => Some(alternate), - (None, None) => None, - } - } - - /// Parse with one entry rule (`script` when `script_rule` is true, else - /// `kotlinFile`) and return the recovered [`ParsedFile`], syntax-error - /// count, and LOC token list, or `None` if the rule call hard-failed. - /// - /// Setup goes through the generated [`kotlin_parser::parse_with_parser`] - /// driver (runtime 0.33): its lexer closure swaps the runtime's default - /// console listener for a structured diagnostic collector, its entry - /// closure removes the parser console listener before running the rule, - /// and the returned output keeps the parser so the recovered tree can be - /// folded into a [`ParsedFile`] that owns the token store and CST. - fn parse_entry( - &self, - source: &str, - script_rule: bool, - line_index: &LineIndex, - ) -> Option { - let entry = if script_rule { - KotlinParser::script - } else { - KotlinParser::kotlin_file - }; - let lexer_diagnostics = DiagnosticCollector::default(); - let out = kotlin_parser::parse_with_parser( - source, - |input| { - let mut lexer = KotlinLexer::new(input); - lexer.remove_error_listeners(); - lexer.add_error_listener(lexer_diagnostics.clone()); - lexer - }, - |parser| { - parser.remove_error_listeners(); - entry(parser) - }, - ) - .ok()?; - let syntax_errors = out.parser.number_of_syntax_errors(); - let lexer_diagnostics = - lexer_diagnostics.diagnostics("kotlin.syntax_error", 16, line_index); - - // `into_parsed_file` consumes the parser and moves the eagerly-buffered - // token store into the `ParsedFile`; the LOC token list is then read - // straight from that store (all channels, so hidden-channel comments - // are present — no `fill()` step needed). - let parsed = out.parser.into_parsed_file(out.result); - let loc_tokens = collect_loc_tokens(&parsed, line_index); - Some(ParsedKotlin { - parsed, - syntax_errors, - lexer_diagnostics, - loc_tokens, - }) - } -} - -impl Default for KotlinAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for KotlinAnalyzer { - fn language(&self) -> Language { - Language::Kotlin - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::Antlr - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - let line_index = LineIndex::new(&source.text); - - // Kotlin has two top-level entry rules: `kotlinFile` (a compilation - // unit — declarations after the import section) and `script` (allows - // top-level statements, for `.kts`). Picking the wrong one recovers - // the input as a cascade of syntax errors. - // - // The file extension is the *preferred* rule, but it isn't decisive: - // embedded/misnamed sources don't always match their extension. Parse - // with the preferred rule first and, only if the parser records syntax - // errors, try the other and keep whichever tree has fewer errors. - // Clean inputs parse exactly once. - let prefers_script = source - .path - .extension() - .is_some_and(|ext| ext.eq_ignore_ascii_case("kts")); - - let parsed = match self.parse_best(&source.text, prefers_script, &line_index) { - Some(parsed) => parsed, - None => { - // Both entry rules hard-failed (the rule call itself returned - // Err, not a recovered tree) — we cannot produce any tree. - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: line_index.line_count(), - }; - return Ok(LanguageAnalysis { - language: Language::Kotlin, - backend: AnalysisBackend::Antlr, - diagnostics: vec![ParseDiagnostic::fatal( - "kotlin.parse_error", - "kotlin ANTLR parse failed for both entry rules".to_string(), - )], - root: mehen_antlr::empty_space(span), - contributions: Vec::new(), - }); - } - }; - - // The `ParsedFile` owns the token store and CST; `tree()` is the root - // `Node` borrowing view the walker traverses. - let tree = parsed.parsed.tree(); - let mut evidence = mehen_metrics::MetricEvidence::new("kotlin", config.emit_contributions); - let root = walker::walk( - tree, - &line_index, - source.text.len(), - &parsed.loc_tokens, - &mut evidence, - ); - - // Recovered ANTLR error nodes are surfaced as `error` (not - // `warning`) so the diagnostic contract (plan §9.3) treats the - // analysis as incomplete: `mehen metrics` exits 1 and `mehen diff` - // records the file under `analysis_errors`. - let mut diagnostics = parsed.lexer_diagnostics; - let remaining = 16usize.saturating_sub(diagnostics.len()); - diagnostics.extend(mehen_antlr::collect_errors( - tree, - "kotlin.syntax_error", - remaining, - &line_index, - )); - - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::Kotlin, - backend: AnalysisBackend::Antlr, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} - -/// Classify the parsed file's token store into the source-ordered LOC token -/// list that drives the LOC family. Comments (`LineComment` / -/// `DelimitedComment`, plus the string-mode `Inside_Comment`) are comments; -/// whitespace and newlines (default- and string-mode) are skipped; every -/// other token is code. Comments are absent from the parse tree (hidden -/// channel), so LOC comes from this full token pass — the token store is -/// eagerly buffered through EOF, so every token (all channels) is present. -fn collect_loc_tokens(parsed: &ParsedFile, line_index: &LineIndex) -> Vec { - use mehen_kotlin_parser::kotlin_lexer::{ - AS_SAFE, AT_BOTH_WS, AT_POST_WS, AT_PRE_WS, DELIMITED_COMMENT, EXCL_WS, INSIDE_COMMENT, - INSIDE_NL, INSIDE_WS, LINE_COMMENT, NL, NOT_IN, NOT_IS, QUEST_WS, WS, - }; - - mehen_antlr::loc_tokens( - // Since the 0.15 runtime `&TokenStore` is `IntoIterator` (issue #123), - // so the eagerly-buffered store feeds the LOC sweep directly — no - // hand-rolled index loop. - parsed.tokens(), - &[LINE_COMMENT, DELIMITED_COMMENT, INSIDE_COMMENT], - &[WS, NL, INSIDE_WS, INSIDE_NL], - // Operator tokens whose lexer rules embed the `Hidden` fragment, so a - // comment glued to them lives inside the token text (e.g. `!is/* c */`). - &[ - EXCL_WS, NOT_IS, NOT_IN, QUEST_WS, AS_SAFE, AT_POST_WS, AT_PRE_WS, AT_BOTH_WS, - ], - line_index, - ) -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, Language, SourceFile, SpaceKind}; - - fn analyze(source: &str, path: &str) -> LanguageAnalysis { - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new(path.into(), Language::Kotlin, source.to_string()); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() - } - - #[test] - fn empty_file_yields_root_unit() { - let a = analyze("", "test.kt"); - assert_eq!(a.root.kind, SpaceKind::Unit); - assert!(a.root.spaces.is_empty()); - } - - #[test] - fn fun_creates_function_space() { - let a = analyze("fun foo(): Int { return 1 }\n", "test.kt"); - assert!(a.root.spaces.iter().any(|s| s.kind == SpaceKind::Function)); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("foo")); - } - - #[test] - fn class_creates_class_space_with_method() { - let a = analyze("class C { fun m() {} }\n", "test.kt"); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("C")); - assert_eq!(a.root.spaces[0].spaces.len(), 1); - } - - #[test] - fn interface_creates_interface_space() { - let a = analyze("interface I { fun m() }\n", "test.kt"); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Interface); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("I")); - } - - /// Top-level statements (script content) parse cleanly because the - /// analyzer picks the entry rule (`script` vs `kotlinFile`) that recovers - /// the fewest errors. The `.kts` extension *prefers* `script`, but the - /// heuristic also recovers the same content in a misnamed `.kt` file — - /// the extension is a preference, not a hard constraint. - #[test] - fn script_content_parses_cleanly_via_best_entry_rule() { - // Pure top-level statements: clean under the `script` rule. - let src = "println(\"hi\")\ngreet()\n"; - - let script = analyze(src, "build.gradle.kts"); - assert!( - script.diagnostics.is_empty(), - "`.kts` top-level statements should parse cleanly, got {}", - script.diagnostics.len() - ); - - // The same content in a `.kt` file: `kotlinFile` would reject the - // statements, so the heuristic falls back to `script` and lands the - // same clean parse. - let file = analyze(src, "Main.kt"); - assert!( - file.diagnostics.is_empty(), - "`.kt` with statement content should fall back to `script`, got {}", - file.diagnostics.len() - ); - } - - /// A real compilation unit (declarations, no top-level statements) still - /// parses cleanly as a `.kt` file via the preferred `kotlinFile` rule. - #[test] - fn kt_compilation_unit_parses_cleanly() { - let src = "package demo\n\nclass C {\n fun m(): Int = 1\n}\n"; - let a = analyze(src, "Main.kt"); - assert!( - a.diagnostics.is_empty(), - "compilation unit should parse cleanly, got {}", - a.diagnostics.len() - ); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); - } - - /// Regression: string-template interpolation (`"… ${expr} …"`) must parse - /// cleanly. The Kotlin lexer pushes `DEFAULT_MODE` on `${` and relies on - /// `}` popping back to string mode; the vendored grammar's `RCURL` rule - /// is patched to `-> popMode` (the upstream Java action was a no-op in - /// the Rust target), so the text after the interpolation is no longer - /// mis-tokenized as Kotlin code. - #[test] - fn string_template_interpolation_parses_cleanly() { - for src in [ - "fun f(x: Int) { val s = \"v=${x} y\" }\n", - "fun f(b: Boolean) { val s = \"a ${ if (b) 1 else 2 } z\" }\n", - "fun f(x: Int) {\n val s = \"v=${x}\"\n val y = x + 1\n}\n", - ] { - let a = analyze(src, "Main.kt"); - assert!( - a.diagnostics.is_empty(), - "string template should parse with no recovered errors, got {} for {src:?}", - a.diagnostics.len() - ); - } - } -} diff --git a/crates/mehen-kotlin/src/walker.rs b/crates/mehen-kotlin/src/walker.rs deleted file mode 100644 index 20c7317e..00000000 --- a/crates/mehen-kotlin/src/walker.rs +++ /dev/null @@ -1,1575 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ANTLR-based Kotlin metric walker. -//! -//! Drives a recursive descent over the ANTLR `ParseTree` (entry rule -//! `kotlinFile`) and produces a populated [`MetricSpace`]. The structure -//! follows the per-language `Visitor` pattern used by `mehen-rust` and -//! `mehen-ruby`: one [`State`] per space, finalize-and-merge on close, with -//! a parent-less ANTLR tree handled by threading context **top-down** -//! (ANTLR rule contexts expose children but no parent pointer). -//! -//! ## Metric coverage (SonarKotlin-aligned) -//! -//! - **Cyclomatic**: `ifExpression`, every loop (`forStatement`, -//! `whileStatement`, `doWhileStatement`), every `whenEntry`, and each -//! short-circuit `&&` (`CONJ`) / `||` (`DISJ`) operator token. `catch` -//! is intentionally excluded (matches SonarKotlin's -//! `CyclomaticComplexityVisitor`). -//! - **Cognitive**: nesting on `ifExpression` (skipping the inner `if` of -//! an `else if`), loops, `whenExpression`, `catchBlock`; flat `+1` on -//! every `else` and on label-qualified `break@`/`continue@`; per-operator -//! boolean-sequence collapse on `&&`/`||`; statement-shape resets. -//! - **ABC**: assignments via `assignment` and `propertyDeclaration` with -//! an initializer; branches via every `callSuffix` (a call); conditions -//! via `ifExpression`/`whenEntry`/`catchBlock`/loops/comparison & -//! equality operators / `&&`/`||`/`?:`/`?.`/`!!`. -//! - **NExit**: `jumpExpression` whose lead token is `RETURN`/`RETURN_AT` -//! or `THROW`. -//! - **NArgs**: `functionValueParameter` count under a function's -//! `functionValueParameters`; `lambdaParameter` count under a lambda's -//! `lambdaParameters`. -//! - **NOM**: every `functionDeclaration`, `anonymousFunction`, -//! `secondaryConstructor`, `getter`, `setter` is a function space (NOM -//! `record_function`); every `lambdaLiteral` is a function-shaped space -//! counted as a closure. -//! - **LOC**: PLOC from per-space code-line observations during the AST -//! walk (NL excluded), LLOC from statement-shaped rules, CLOC from a -//! source-ordered pass over the hidden-channel comment tokens routed to -//! the deepest enclosing space via `SpaceRangeTracker` after the walk. -//! - **Halstead**: per-token operator/operand classification — keyword and -//! punctuation tokens are operators; identifiers, literals, `this`, -//! `super`, `field` are operands (deduped by text). -//! - **NPA / NPM / WMC**: class-vs-interface routing via the -//! `classDeclaration`'s leading `CLASS`/`INTERFACE` token. NPA counts -//! `propertyDeclaration` directly under a `classMemberDeclaration` plus -//! primary-constructor `classParameter`s carrying `val`/`var`. NPM counts -//! `functionDeclaration`/`secondaryConstructor`/`getter`/`setter` -//! directly under a class body, public unless an explicit visibility -//! modifier says otherwise. - -use mehen_antlr::runtime::token::Token; -use mehen_antlr::runtime::{FromRuleNode, Node, RuleNodeView, TerminalNodeView}; -use mehen_antlr::{LocToken, LocTokenKind, ctx_span, span_from_tokens}; -use mehen_core::{LineIndex, MetricSpace, SpaceKind}; -use mehen_metrics::{ - ContainerKind, HalsteadOperand, HalsteadOperator, MetricEvidence, MetricTreeBuilder, - SpaceRangeTracker, State, apply_state_to, finalize_state, merge_child_into_parent, -}; -use smol_str::SmolStr; - -use mehen_kotlin_parser::kotlin_parser as kp; - -/// Drive the walk over the parsed `kotlinFile` tree and return the unit -/// `MetricSpace`. `loc_tokens` is the source-ordered code/comment token list -/// recovered from the full (hidden-channel-inclusive) token stream; LOC is -/// computed from it in a single ordered pass *after* the tree walk has -/// opened and closed every space, so comments and code interleave correctly -/// and per-space `loc.ploc`/`loc.cloc` reflect each scope's body. -pub(crate) fn walk( - tree: Node<'_>, - line_index: &LineIndex, - source_len: usize, - loc_tokens: &[LocToken], - evidence: &mut MetricEvidence, -) -> MetricSpace { - let unit_span = match tree.as_rule() { - Some(rule) => ctx_span(rule, line_index, source_len), - None => mehen_core::SourceSpan::empty(), - }; - - let mut unit_state = State::new(); - unit_state - .loc - .set_span(0, line_index.line_count().saturating_sub(1), true); - - let mut walker = Walker { - line_index, - source_len, - tree: MetricTreeBuilder::new(unit_span), - stack: vec![unit_state], - kinds: vec![SpaceKind::Unit], - suppress_parent_wmc: vec![false], - cognitive: CognitiveContext::default(), - loc_routing: SpaceRangeTracker::new(), - evidence, - }; - - if let Some(rule) = tree.as_rule() { - for child in rule.children() { - walker.visit(child, ChildHint::default()); - } - } - - let mut unit_state = walker.stack.pop().expect("walker stack underflow"); - - // CLOC pass: route each comment to the deepest enclosing space (or the - // unit) in source order. Comments are hidden-channel — absent from the - // parse tree — so they can't be observed during the AST walk. Running - // this *after* the walk (which seeded each space's `ploc_lines` via - // `record_close`) means a comment sharing a line with code is correctly - // classified as a code-comment, and each space gets its own `loc.cloc`. - // PLOC code lines are already recorded per-space during the AST walk, so - // only comments are routed here (mirrors `mehen-python`). - for t in loc_tokens { - if t.kind == LocTokenKind::Comment { - walker.loc_routing.observe_comment( - t.start_byte, - t.end_byte, - &mut unit_state.loc, - t.start_row, - t.end_row, - ); - } - } - - finalize_state(&mut unit_state); - - // Order matters (mirrors `mehen-rust`'s token-routed finish): - // 1. assemble the tree, - // 2. `finalize_into_tree` — roll each space's token-routed LOC up the - // parent chain (merging into `unit_loc`) and overlay the per-space - // LOC keys onto the tree, - // 3. write the unit keys from the now-merged `unit_loc`. - // Doing `apply_state_to` for the unit *last* is what gives the unit its - // rolled-up PLOC/CLOC — otherwise the unit reads 0 because every code - // token routed into a child space. - let mut root = walker.tree.finish(); - // Halstead is recorded during the AST walk (Pattern A), so the tracker - // carries no Halstead events — the overlay only rewrites the LOC keys. - let mut unit_halstead = std::mem::take(&mut unit_state.halstead); - let mut unit_loc = std::mem::take(&mut unit_state.loc); - walker - .loc_routing - .finalize_into_tree(&mut root, &mut unit_halstead, &mut unit_loc); - unit_state.halstead = unit_halstead; - unit_state.loc = unit_loc; - apply_state_to(unit_state, &mut root.metrics); - root -} - -/// Per-frame cognitive context — the legacy `(nesting, depth, lambda)` -/// triple. `nesting + depth + lambda` is the effective nesting level when a -/// nesting-increasing construct is observed. -#[derive(Clone, Copy, Debug, Default)] -struct CognitiveContext { - nesting: u32, - depth: u32, - lambda: u32, -} - -/// Context threaded *down* into a child during the walk, replacing the -/// upward `node.parent()` queries the tree-sitter walker used (ANTLR -/// contexts have no parent pointer). -#[derive(Clone, Copy, Debug, Default)] -struct ChildHint { - /// This rule is being visited as the `else`-branch body of an - /// enclosing `ifExpression`. An `ifExpression` reached through this - /// hint is an `else if` and must not add cognitive nesting. - is_else_branch: bool, - /// This node is a direct member position of the enclosing class body - /// (a `classMemberDeclaration`'s child), so NPA/NPM should consider it. - in_class_member: bool, - /// When this node is (within) a class-body `propertyDeclaration`, the - /// property's resolved visibility, so a `getter`/`setter` with no - /// explicit modifier of its own inherits it for NPM. `None` outside a - /// class-body property. - property_visibility: Option, - /// This terminal is the token of a `simpleIdentifier` rule. Kotlin - /// soft keywords (`value`, `field`, `data`, …) lex as dedicated token - /// types but are identifiers in this position, so they are Halstead - /// *operands* regardless of token type. - in_simple_identifier: bool, - /// We are inside an anonymous class body that opens no metric space of - /// its own — an `enumEntry`'s body (`A { … }`) or an `objectLiteral` - /// (`object { … }`). Their `classMemberDeclaration`s must NOT seed - /// `in_class_member`, and their functions must NOT roll into the - /// enclosing class's WMC — those members belong to the anonymous - /// subclass, not the lexically-enclosing class. Cleared once a *real* - /// nested class-like declaration opens its own space. - in_anon_body: bool, -} - -/// The enclosing class-body property's container + default visibility, -/// threaded down to its accessors for NPM. -#[derive(Clone, Copy, Debug)] -struct AccessorOwner { - container: ContainerKind, - property_is_public: bool, -} - -struct Walker<'a> { - line_index: &'a LineIndex, - source_len: usize, - tree: MetricTreeBuilder, - stack: Vec, - kinds: Vec, - /// Parallel to `stack`/`kinds`: whether the closing space must NOT - /// contribute to its parent's WMC. Set for functions opened inside an - /// enum entry's anonymous body — that body opens no space of its own, so - /// the function closes with the *enum* as parent, but it belongs to the - /// entry's anonymous subclass, not the enum. - suppress_parent_wmc: Vec, - cognitive: CognitiveContext, - /// Records each opened space's byte range so the post-walk LOC token - /// pass can route code/comment lines to the deepest enclosing scope. - loc_routing: SpaceRangeTracker, - /// Contribution-evidence sink (plan §5.4). Record methods are no-ops - /// when disabled, so classify hooks call them unconditionally via the - /// `record_rule_evidence` / `record_token_evidence` helpers. - evidence: &'a mut MetricEvidence, -} - -impl Walker<'_> { - fn current(&mut self) -> &mut State { - self.stack.last_mut().expect("walker stack empty") - } - - /// Record contribution evidence for a rule context. The span is only - /// computed when the sink is enabled, so classify hooks can call this - /// unconditionally next to each stat increment. - #[inline] - fn record_rule_evidence(&mut self, ctx: RuleNodeView<'_>, record: F) - where - F: FnOnce(&mut MetricEvidence, mehen_core::SourceSpan), - { - if self.evidence.is_enabled() { - let span = ctx_span(ctx, self.line_index, self.source_len); - record(self.evidence, span); - } - } - - /// As [`Self::record_rule_evidence`] but for a single terminal token — - /// the span covers just the token, so operator evidence points at the - /// `&&` / `else` keyword itself. - #[inline] - fn record_token_evidence(&mut self, term: TerminalNodeView<'_>, record: F) - where - F: FnOnce(&mut MetricEvidence, mehen_core::SourceSpan), - { - if self.evidence.is_enabled() { - let sym = term.symbol(); - let span = span_from_tokens(&sym, &sym, self.line_index, self.source_len); - record(self.evidence, span); - } - } - - fn visit(&mut self, node: Node<'_>, hint: ChildHint) { - if let Some(rule) = node.as_rule() { - self.visit_rule(rule, hint); - } else if let Some(term) = node.as_terminal() { - self.visit_terminal(term, hint); - } - // Error leaves carry no metric contribution; they are surfaced as - // diagnostics by `mehen_antlr::collect_errors` in the analyzer. - } - - fn visit_terminal(&mut self, term: TerminalNodeView<'_>, hint: ChildHint) { - let tt = term.symbol().token_type(); - - // Cyclomatic: each short-circuit boolean operator token. - if matches!(tt, kp::CONJ | kp::DISJ) { - self.current().cyclomatic.record_decision(); - let op = if tt == kp::CONJ { "&&" } else { "||" }; - self.record_token_evidence(term, |e, s| e.decision(s, op)); - } - - // Cognitive: `else` adds a flat +1 (covers `else if`); the boolean - // operators feed the sequence collapser. The prefix `!` never feeds - // the collapser — a negated operand's logical subtree is instead - // isolated at the rule level in `visit_rule` (see the - // `is_logical_negation` boundary there). The `EXCL_*` tokens are - // shared with the postfix `!!` not-null assertion, which must not - // affect a boolean run at all. Evidence amounts are the structural - // delta actually applied — a same-operator repeat records nothing. - match tt { - kp::ELSE => { - self.current().cognitive.increment_by_one(); - self.record_token_evidence(term, |e, s| e.cognitive(s, 1, "else")); - } - kp::CONJ | kp::DISJ => { - let op = if tt == kp::CONJ { "&&" } else { "||" }; - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean(op); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_token_evidence(term, |e, s| e.cognitive(s, delta, op)); - } - _ => {} - } - - // ABC conditions: comparison / equality / boolean / elvis / safe-nav - // / not-null operators. - if is_abc_condition_token(tt) { - self.current().abc.record_condition(); - let detail = condition_token_spelling(tt); - self.record_token_evidence(term, |e, s| e.abc_condition(s, detail)); - } - - // Halstead operator/operand token classification. A token reached - // via `simpleIdentifier` is always an operand (covers Kotlin soft - // keywords used as identifiers, e.g. `value`/`field`/`data`). - let class = if hint.in_simple_identifier { - HalsteadClass::Operand - } else { - halstead_class(tt) - }; - match class { - HalsteadClass::Operator => { - let label = kp_token_name(tt); - self.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(label), - text: None, - }); - } - HalsteadClass::Operand => { - let text = term.symbol().text_or_empty(); - self.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(SmolStr::new(text)), - }); - } - HalsteadClass::Skip => {} - } - - // PLOC: a code token's start row is a code line, recorded into the - // current space during the AST walk so per-space PLOC and its - // min/max bounds are correct at close time. `NL` is excluded — - // Kotlin newlines are grammar-significant (statement separators) so - // they appear as visible tree tokens, but a blank/structural newline - // is not code. Comments are *not* handled here either — they're - // hidden-channel (absent from the tree) and are routed in source - // order after the walk (see `walk`), which lets a comment sharing a - // line with code classify as a code-comment. - // - // `SHEBANG_LINE` (`#!/usr/bin/env kotlin` on an executable `.kts`) is - // a *visible* terminal but is an interpreter directive, not Kotlin - // code. Route it as a comment (CLOC) — matching how the Python - // backend treats `#!`-lines — rather than PLOC: it must not be code, - // and leaving it out of PLOC alone would silently reclassify its row - // as a phantom blank line (`blank = sloc - ploc - only_comment`). - if tt == kp::SHEBANG_LINE { - let row = (term.symbol().line() as u32).saturating_sub(1); - self.current().loc.observe_comment(row, row); - } else if tt >= 0 && tt != kp::NL { - // Only the annotation tokens that fold *leading* trivia into their - // text (`AT_PRE_WS: (Hidden|NL) '@'`, `AT_BOTH_WS`) need the row - // advanced past that trivia — for them `line()` points at the - // trivia's (possibly blank/comment-only) line, not the real `@`. - // For any other token the text IS the lexeme, so the heuristic - // would be wrong: a raw multiline-string content token whose text - // happens to start with `\n// …` or `\n/* … */` is literal string - // content, not folded trivia, and must keep its real start row. - let base = (term.symbol().line() as u32).saturating_sub(1); - let row = if folds_leading_trivia(tt) { - base.saturating_add(leading_newlines(term.symbol().text_or_empty())) - } else { - base - }; - self.current().loc.observe_code_line(row); - } - } - - fn visit_rule(&mut self, ctx: RuleNodeView<'_>, hint: ChildHint) { - let ri = ctx.rule_index(); - - // Snapshot the cognitive context of the *enclosing* construct - // before anything in this subtree mutates it. This must happen - // before `maybe_open_space`, which calls `enter_function_cognitive` - // (resetting nesting/lambda and bumping depth) for function/lambda - // spaces — otherwise the restore below would reinstate the reset - // inner-function context instead of the caller's, and sibling code - // after a nested function/lambda would lose its enclosing nesting. - let saved_cognitive = self.cognitive; - - // NPA / NPM: classify direct members of the *enclosing* class - // before we open any space for this node (so the kinds stack still - // has the class on top). `in_class_member` is threaded through the - // transparent wrapper rules (`classMemberDeclaration`, - // `declaration`) so it reaches the actual member declaration. - if hint.in_class_member && is_class_member_rule(ri) { - self.classify_class_member(ctx, ri); - } - - // Does this rule open a metric space? - let opened = self.maybe_open_space(ctx, ri, hint); - - // Per-rule classification (cyclomatic / cognitive / ABC / exit / LOC). - self.classify_rule(ctx, ri, hint); - - // A call argument (`g(a && b)`) is an independent boolean context: its - // inner short-circuit run must not collapse with a same-kind operator - // outside the call, and vice-versa. Save the enclosing run's `last_op`, - // start the argument fresh, then restore it so the *outer* run - // continues across the call as if it were a single operand. This makes - // `g(a && b) + g(c && d)` count +2 (two independent runs) while keeping - // `a && g(x) && b` at +1 (one outer run, the call argument isolated). - // - // A logical negation (`!expr`) is the same kind of boundary: in - // SonarSource's tree flattening a negated operand is a leaf of the - // enclosing run — flattening stops there — so a logical subtree under - // `!` is its own run. Isolating it makes `a && !(b && c) && d` count - // +2 (outer run + inner run) while a scalar `!b` stays invisible - // (nothing inside to run, and the restored `last_op` lets the outer - // run continue): `a && !b && c` remains +1 (issue #217, PR #235). - let saved_bool = if ri == kp::RULE_VALUE_ARGUMENT || is_logical_negation(ctx, ri) { - let prev = self.current().cognitive.boolean_seq.last_op.take(); - Some(prev) - } else { - None - }; - - // Recurse into children, computing each child's hint. - self.visit_children(ctx, ri, hint); - - if let Some(prev) = saved_bool { - self.current().cognitive.boolean_seq.last_op = prev; - } - - if opened { - self.close_space(); - } - self.cognitive = saved_cognitive; - } - - /// Walk the children of `ctx`, deriving each child's [`ChildHint`] from - /// this rule's identity, the inbound hint, and the child's position. - fn visit_children(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) { - // `NodeChildren` is a cheap `Clone` slice-iterator, so it is re-walked - // (below, and once here for the `else` scan) without allocating — the - // hot path avoids collecting children into a `Vec` for every node. - - // For `ifExpression`, the `else`-branch body is the - // `controlStructureBody` that appears after the `ELSE` token. Tag - // it so an `ifExpression` reached through it (without an - // intervening `block`) is recognized as `else if`. - let else_body_idx = if ri == kp::RULE_IF_EXPRESSION { - else_branch_index(ctx.children()) - } else { - None - }; - // `is_else_branch` flows down through the transparent - // statement/expression wrapper chain (`controlStructureBody` → - // `statement` → expression ladder → `primaryExpression`) until it - // reaches the inner `ifExpression`. A `block` (braces) stops the - // flow: `else { if … }` is a genuinely nested `if`, not an - // `else if`. - let propagate_else = hint.is_else_branch && is_else_transparent(ri); - - // A class/interface/object body member position originates at - // `classMemberDeclaration`. `in_class_member` then flows through the - // transparent `declaration` wrapper down to the real member rule - // (`functionDeclaration`, `propertyDeclaration`, …). Any other rule - // (a method body, an expression) clears it so nested local - // declarations are not counted as class members. - // Track whether we're inside an anonymous class body that opens no - // space of its own — an `enumEntry` body or an `objectLiteral` - // (`object { … }`). Their direct members must not be attributed to - // the lexically-enclosing class. Set on entering those rules and - // CLEARED once a *real* class-like declaration opens its own space — - // that nested class owns its members normally (e.g. - // `A { class Inner { fun m() {} } }`: `m` belongs to `Inner`). - let in_anon_body = if opens_class_like(ri) { - false - } else { - hint.in_anon_body || ri == kp::RULE_ENUM_ENTRY || ri == kp::RULE_OBJECT_LITERAL - }; - - // A class/interface/object/enum body member position originates at - // `classMemberDeclaration` (the enum's *own* methods reach it via - // `enumClassBody → classMemberDeclarations`). `in_class_member` then - // flows through the transparent `declaration` wrapper to the real - // member rule. A `classMemberDeclaration` reached *inside* an - // anonymous body (enum entry / object literal) is suppressed — those - // members belong to the anonymous subclass, which opens no space here. - let propagate_member = match ri { - kp::RULE_CLASS_MEMBER_DECLARATION => !in_anon_body, - kp::RULE_DECLARATION => hint.in_class_member, - _ => false, - }; - - // When recursing into a class-body `propertyDeclaration`, resolve - // its container + visibility once and thread it to the accessors - // (`getter`/`setter`) for NPM. The enclosing space kind is the - // class-like that owns the property. - let property_owner = if in_anon_body { - // Inside an anonymous body (object literal / enum entry) the - // accessors belong to that anonymous subclass — which opens no - // space — so they must NOT inherit an enclosing property's owner. - // Otherwise a class property initialized to an `object { … }` - // whose member has a getter/setter (suppressed from - // `in_class_member`, so the inner property never re-resolves the - // owner) would record that accessor on the lexically-enclosing - // class, undoing the anonymous-body suppression for accessors. - None - } else if ri == kp::RULE_PROPERTY_DECLARATION && hint.in_class_member { - match self.kinds.last().cloned().unwrap_or(SpaceKind::Unit) { - SpaceKind::Class | SpaceKind::Impl => Some(AccessorOwner { - container: ContainerKind::Class, - property_is_public: member_is_public(ctx), - }), - SpaceKind::Interface | SpaceKind::Trait => Some(AccessorOwner { - container: ContainerKind::Interface, - property_is_public: member_is_public(ctx), - }), - _ => None, - } - } else { - // Propagate an already-resolved owner through transparent - // wrappers inside the property (none in practice — accessors - // are direct children — but keep it explicit). - hint.property_visibility - }; - - // Tokens directly under `simpleIdentifier` are identifiers (incl. - // soft keywords used as names) → Halstead operands. - let in_simple_identifier = ri == kp::RULE_SIMPLE_IDENTIFIER; - - for (idx, child) in ctx.children().enumerate() { - let mut child_hint = ChildHint::default(); - if Some(idx) == else_body_idx || propagate_else { - child_hint.is_else_branch = true; - } - child_hint.in_class_member = propagate_member; - child_hint.property_visibility = property_owner; - child_hint.in_simple_identifier = in_simple_identifier; - child_hint.in_anon_body = in_anon_body; - self.visit(child, child_hint); - } - } - - /// Open a metric space for space-introducing rules. Returns whether a - /// space was pushed. - fn maybe_open_space(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) -> bool { - match ri { - kp::RULE_GETTER | kp::RULE_SETTER => { - let detail = if ri == kp::RULE_GETTER { - "getter" - } else { - "setter" - }; - // A property accessor is a method of the enclosing class - // (NPM): its visibility is its own explicit modifier, else - // the owning property's visibility. Record it before - // opening the function space so the class state is still on - // top of the stack. - if let Some(owner) = hint.property_visibility { - let public = - visibility_from_modifiers_of(ctx).unwrap_or(owner.property_is_public); - self.current().npm.record_method(owner.container, public); - if public { - self.record_rule_evidence(ctx, |e, s| e.public_method(s, detail)); - } - } - let name = rule_name(ctx); - let mut state = self.new_space_state(ctx); - state.nom.record_function(); - let argc = count_function_args(ctx); - state.nargs.record_function_args(argc); - if self.evidence.is_enabled() { - let span = self.space_span(ctx); - self.evidence.function(span, detail); - self.evidence.function_args(span, argc, detail); - } - self.push_space(SpaceKind::Function, name, ctx, state, hint.in_anon_body); - self.enter_function_cognitive(); - true - } - kp::RULE_FUNCTION_DECLARATION - | kp::RULE_ANONYMOUS_FUNCTION - | kp::RULE_SECONDARY_CONSTRUCTOR => { - let detail = match ri { - kp::RULE_FUNCTION_DECLARATION => "function_declaration", - kp::RULE_ANONYMOUS_FUNCTION => "anonymous_function", - _ => "secondary_constructor", - }; - let name = rule_name(ctx); - let mut state = self.new_space_state(ctx); - state.nom.record_function(); - let argc = count_function_args(ctx); - state.nargs.record_function_args(argc); - if self.evidence.is_enabled() { - let span = self.space_span(ctx); - self.evidence.function(span, detail); - self.evidence.function_args(span, argc, detail); - } - self.push_space(SpaceKind::Function, name, ctx, state, hint.in_anon_body); - self.enter_function_cognitive(); - true - } - kp::RULE_LAMBDA_LITERAL => { - let mut state = self.new_space_state(ctx); - state.nom.record_closure(); - let argc = count_lambda_args(ctx); - state.nargs.record_closure_args(argc); - if self.evidence.is_enabled() { - let span = self.space_span(ctx); - self.evidence.closure(span, "lambda_literal"); - self.evidence.closure_args(span, argc, "lambda_literal"); - } - self.push_space(SpaceKind::Function, None, ctx, state, hint.in_anon_body); - self.enter_function_cognitive(); - true - } - kp::RULE_CLASS_DECLARATION => { - let name = rule_name(ctx); - // A `classDeclaration` leads with either `CLASS` or `INTERFACE`; - // the typed context exposes `interface_token()` (Option). - let is_interface = kp::ClassDeclarationContext::from_rule_node(ctx) - .and_then(|class| class.interface_token()) - .is_some(); - let kind = if is_interface { - SpaceKind::Interface - } else { - SpaceKind::Class - }; - let mut state = self.new_space_state(ctx); - state.npa.record_class_like(); - state.npm.record_class_like(); - if !is_interface { - state.wmc.record_class_like(); - } - // Primary-constructor properties (`class C(val x: Int)`) are - // class attributes. They live under - // `primaryConstructor → classParameters → classParameter`, - // not in the class body, so count them here against the - // freshly-opened class state. - let container = if is_interface { - ContainerKind::Interface - } else { - ContainerKind::Class - }; - record_constructor_properties( - ctx, - container, - &mut state, - self.evidence, - self.line_index, - self.source_len, - ); - // A class-like space owns its own WMC, so it never suppresses - // a parent contribution (and it has already cleared the - // enum-entry suppression for its own body). - self.push_space(kind, name, ctx, state, false); - true - } - kp::RULE_OBJECT_DECLARATION | kp::RULE_COMPANION_OBJECT => { - let name = rule_name(ctx); - let mut state = self.new_space_state(ctx); - state.npa.record_class_like(); - state.npm.record_class_like(); - state.wmc.record_class_like(); - self.push_space(SpaceKind::Class, name, ctx, state, false); - true - } - _ => false, - } - } - - /// A space's source span, with leading trivia trimmed. A declaration's - /// start token can be an `AT_PRE_WS`/`AT_BOTH_WS` annotation token whose - /// text folds in the preceding newline(s)/comment (`"\n@"`, `"/* c */@"`). - /// Left untrimmed this pulls the span's `start_line` onto a blank/comment - /// line (inflating `sloc`/`blank`) *and* leaves `start_byte` inside the - /// folded comment — and since `push_space` routes comments by the span's - /// byte range, a leading block comment would be attributed to this space's - /// CLOC. Advance both `start_byte` and `start_line` past the folded - /// trivia so the span begins at the real declaration character. - fn space_span(&self, ctx: RuleNodeView<'_>) -> mehen_core::SourceSpan { - let mut span = ctx_span(ctx, self.line_index, self.source_len); - if let Some(start) = ctx.start() - && folds_leading_trivia(start.token_type()) - { - let (_, trivia_bytes) = leading_trivia(start.text_or_empty()); - if trivia_bytes > 0 { - let trimmed = span - .start_byte - .saturating_add(trivia_bytes as u32) - .min(span.end_byte); - span.start_byte = trimmed; - // Derive the line from the trimmed byte via the authoritative - // byte->line index (handles the same-line `/* c */@` case that - // a newline count alone would miss). - span.start_line = self.line_index.line_at(trimmed).min(span.end_line); - } - } - span - } - - fn new_space_state(&self, ctx: RuleNodeView<'_>) -> State { - let mut state = State::new(); - let span = self.space_span(ctx); - state.loc.set_span( - span.start_line.saturating_sub(1), - span.end_line.saturating_sub(1), - false, - ); - state - } - - fn push_space( - &mut self, - kind: SpaceKind, - name: Option, - ctx: RuleNodeView<'_>, - state: State, - suppress_parent_wmc: bool, - ) { - let span = self.space_span(ctx); - let space_id = self.tree.open(kind.clone(), span, name); - // Record this space's byte range so the post-walk LOC token pass - // routes code/comment lines into it. - self.loc_routing - .record_open(space_id, span.start_byte, span.end_byte); - self.stack.push(state); - self.kinds.push(kind); - self.suppress_parent_wmc.push(suppress_parent_wmc); - } - - /// Cognitive function-entry: reset nesting / lambda, bump depth when - /// nested inside another function. - fn enter_function_cognitive(&mut self) { - let nested_inside_function = self - .kinds - .iter() - .rev() - .skip(1) - .any(|k| matches!(k, SpaceKind::Function)); - self.cognitive.nesting = 0; - self.cognitive.lambda = 0; - if nested_inside_function { - self.cognitive.depth = self.cognitive.depth.saturating_add(1); - } - } - - fn close_space(&mut self) { - let closed_kind = self.kinds.pop().expect("kinds underflow"); - let suppress_wmc = self.suppress_parent_wmc.pop().unwrap_or(false); - let mut state = self.stack.pop().expect("stack underflow"); - if matches!(closed_kind, SpaceKind::Function) { - state.wmc.set_cyclomatic(state.cyclomatic.cyclomatic + 1); - } - finalize_state(&mut state); - // Stash this space's AST-side LOC + cyclomatic snapshot so the LOC - // token pass can seed its `ploc_lines` (for correct comment-after- - // code classification) and recompute MI from the token-routed LOC. - if let Some(space_id) = self.tree.current_id() { - self.loc_routing - .record_close(space_id, &state.loc, &state.cyclomatic); - } - apply_state_to(state.clone(), self.tree.metrics_mut()); - if let Some(parent) = self.stack.last_mut() { - let parent_kind = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - merge_child_into_parent(parent, &state); - // Roll a closing function's cyclomatic into the parent's WMC — - // unless it's a function from an enum entry's anonymous body, - // which belongs to that subclass (no space of its own) and must - // not inflate the enclosing enum's WMC. - if matches!(closed_kind, SpaceKind::Function) && !suppress_wmc { - let container = container_kind(parent_kind); - state.wmc.finalize_method_into(container, &mut parent.wmc); - } - } - self.tree.close(); - } - - /// Per-rule cyclomatic / cognitive / ABC / exit / LOC classification. - fn classify_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) { - // Cyclomatic decisions: if / loops / when-entry. The match yields - // the evidence detail so the decision set and its reason codes - // cannot drift apart. - let decision_detail = match ri { - kp::RULE_IF_EXPRESSION => Some("if_expression"), - kp::RULE_FOR_STATEMENT => Some("for_statement"), - kp::RULE_WHILE_STATEMENT => Some("while_statement"), - kp::RULE_DO_WHILE_STATEMENT => Some("do_while_statement"), - kp::RULE_WHEN_ENTRY => Some("when_entry"), - _ => None, - }; - if let Some(detail) = decision_detail { - self.current().cyclomatic.record_decision(); - self.record_rule_evidence(ctx, |e, s| e.decision(s, detail)); - } - - self.classify_cognitive(ctx, ri, hint); - self.classify_abc_rule(ctx, ri); - self.classify_exit(ctx, ri); - self.classify_loc_rule(ctx, ri); - self.classify_empty_string_operand(ctx, ri); - } - - /// Record a Halstead operand for an *empty* string literal (`""` / - /// `""""""`). A non-empty literal records its operand(s) via the content - /// tokens (`LINE_STR_TEXT`, escapes, refs), but an empty literal emits - /// only delimiter tokens (all skipped), so without this it would - /// contribute no operand at all — undercounting Halstead/MI for the very - /// common empty-string default. An empty literal has only terminal - /// children (the delimiters); a non-empty one has at least one content / - /// template-expression *rule* child, so "no rule children" detects empty - /// without firing on `"$x"` / `"${…}"` (which carry rule children). - fn classify_empty_string_operand(&mut self, ctx: RuleNodeView<'_>, ri: usize) { - if !matches!( - ri, - kp::RULE_LINE_STRING_LITERAL | kp::RULE_MULTI_LINE_STRING_LITERAL - ) { - return; - } - let has_content = ctx.children().any(|c| c.as_rule().is_some()); - if !has_content { - self.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(SmolStr::new("\"\"")), - }); - } - } - - fn classify_cognitive(&mut self, ctx: RuleNodeView<'_>, ri: usize, hint: ChildHint) { - match ri { - // `else if` (an ifExpression reached as an else-branch body) - // does not add nesting — only the flat `else` +1 (emitted when - // the ELSE terminal is visited) applies. - kp::RULE_IF_EXPRESSION if hint.is_else_branch => {} - kp::RULE_IF_EXPRESSION - | kp::RULE_FOR_STATEMENT - | kp::RULE_WHILE_STATEMENT - | kp::RULE_DO_WHILE_STATEMENT - | kp::RULE_WHEN_EXPRESSION - | kp::RULE_CATCH_BLOCK => { - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - let detail = match ri { - kp::RULE_IF_EXPRESSION => "if_expression", - kp::RULE_FOR_STATEMENT => "for_statement", - kp::RULE_WHILE_STATEMENT => "while_statement", - kp::RULE_DO_WHILE_STATEMENT => "do_while_statement", - kp::RULE_WHEN_EXPRESSION => "when_expression", - _ => "catch_block", - }; - self.record_rule_evidence(ctx, |e, s| { - e.cognitive(s, effective.saturating_add(1), detail); - }); - } - // Label-qualified break/continue add +1 (goto-like). - kp::RULE_JUMP_EXPRESSION => { - if let Some(jump) = kp::JumpExpressionContext::from_rule_node(ctx) - && (jump.break_at_token().is_some() || jump.continue_at_token().is_some()) - { - self.current().cognitive.increment_by_one(); - self.record_rule_evidence(ctx, |e, s| e.cognitive(s, 1, "jump_expression")); - } - self.current().cognitive.boolean_seq.reset(); - } - // Statement-shape boolean resets. Each `statement` starts a - // fresh boolean sequence so operators never collapse across - // statement boundaries — e.g. `foo(a && b); bar(c && d)` is +2, - // not +1. `statement` is the general boundary; `assignment` and - // `propertyDeclaration` are kept for the property-initializer - // and assignment forms that are not wrapped in a `statement` - // (class-body property declarations, `for`/`while` bodies). - kp::RULE_STATEMENT | kp::RULE_ASSIGNMENT | kp::RULE_PROPERTY_DECLARATION => { - self.current().cognitive.boolean_seq.reset(); - } - // NOTE: the prefix `!` deliberately adds nothing here. - // - // Both SonarJava (`CognitiveComplexityVisitor.flattenLogicalExpression`) - // and SonarKotlin (`CognitiveComplexity.flattenOperators`) flatten only - // the `&&`/`||` operators, treating a negated operand as a plain operand - // where flattening *stops* — the `!` itself is invisible to the run, so - // `a && !b && c` is a single `&&` run and costs exactly what - // `a && b && c` costs. But because flattening stops at the negated - // operand, a logical subtree beneath it (`!(b && c)`) is its own run. - // That boundary is enforced in `visit_rule`, which isolates the - // `boolean_seq` around a logical-negation operand exactly like a call - // argument (see `is_logical_negation`). - // - // This previously matched `RULE_PREFIX_UNARY_OPERATOR` (logical `!`) - // and called `boolean_seq.not_operator("!")`, which broke the run and - // scored 2 where every other analyzer — and SonarKotlin itself — - // scores 1 on identical logic. Fixed in issue #217. With no - // `not_operator` caller left in this walker, the postfix `!!` - // not-null assertion (`postfixUnaryOperator`, sharing the same - // `EXCL_*` tokens) cannot break a run either, which is what - // `kotlin_not_null_assertion_does_not_break_boolean_sequence` asserts. - _ => {} - } - } - - fn classify_abc_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize) { - match ri { - kp::RULE_ASSIGNMENT => { - self.current().abc.record_assignment(); - self.record_rule_evidence(ctx, |e, s| e.abc_assignment(s, "assignment")); - } - // A `propertyDeclaration` with an initializer (`= expr`) is an - // assignment; `val`/`var` without `=` is not. - kp::RULE_PROPERTY_DECLARATION - if kp::PropertyDeclarationContext::from_rule_node(ctx) - .and_then(|p| p.assignment_token()) - .is_some() => - { - self.current().abc.record_assignment(); - self.record_rule_evidence(ctx, |e, s| { - e.abc_assignment(s, "property_declaration"); - }); - } - // A call: the `callSuffix` rule wraps the argument list of a - // postfix call. - kp::RULE_CALL_SUFFIX => { - self.current().abc.record_branch(); - self.record_rule_evidence(ctx, |e, s| e.abc_branch(s, "call_suffix")); - } - // Multi-token operators modeled as rules: elvis (`?:`), - // safe-nav (`?.`), and the `!!` not-null assertion. - kp::RULE_ELVIS => { - self.current().abc.record_condition(); - self.record_rule_evidence(ctx, |e, s| e.abc_condition(s, "?:")); - } - kp::RULE_SAFE_NAV => { - self.current().abc.record_condition(); - self.record_rule_evidence(ctx, |e, s| e.abc_condition(s, "?.")); - } - kp::RULE_POSTFIX_UNARY_OPERATOR - if kp::PostfixUnaryOperatorContext::from_rule_node(ctx) - .and_then(|op| op.excl_no_ws_token()) - .is_some() => - { - self.current().abc.record_condition(); - self.record_rule_evidence(ctx, |e, s| e.abc_condition(s, "!!")); - } - kp::RULE_IF_EXPRESSION - | kp::RULE_WHEN_ENTRY - | kp::RULE_CATCH_BLOCK - | kp::RULE_FOR_STATEMENT - | kp::RULE_WHILE_STATEMENT - | kp::RULE_DO_WHILE_STATEMENT => { - self.current().abc.record_condition(); - let detail = match ri { - kp::RULE_IF_EXPRESSION => "if_expression", - kp::RULE_WHEN_ENTRY => "when_entry", - kp::RULE_CATCH_BLOCK => "catch_block", - kp::RULE_FOR_STATEMENT => "for_statement", - kp::RULE_WHILE_STATEMENT => "while_statement", - _ => "do_while_statement", - }; - self.record_rule_evidence(ctx, |e, s| e.abc_condition(s, detail)); - } - _ => {} - } - } - - fn classify_exit(&mut self, ctx: RuleNodeView<'_>, ri: usize) { - if ri == kp::RULE_JUMP_EXPRESSION { - // NExit counts a bare `return` or `throw` — these exit the - // enclosing function. A labeled `return@label` (`RETURN_AT`) - // returns from a lambda, not the function, so it is excluded - // (matches SonarKotlin); `break`/`continue` are excluded too. - if let Some(jump) = kp::JumpExpressionContext::from_rule_node(ctx) { - let detail = if jump.return_token().is_some() { - Some("return") - } else if jump.throw_token().is_some() { - Some("throw") - } else { - None - }; - if let Some(detail) = detail { - self.current().nexit.record_exit(); - self.record_rule_evidence(ctx, |e, s| e.exit(s, detail)); - } - } - } - } - - fn classify_loc_rule(&mut self, ctx: RuleNodeView<'_>, ri: usize) { - // LLOC: statement / declaration-shaped rules. - if matches!( - ri, - kp::RULE_FUNCTION_DECLARATION - | kp::RULE_CLASS_DECLARATION - | kp::RULE_OBJECT_DECLARATION - | kp::RULE_COMPANION_OBJECT - | kp::RULE_SECONDARY_CONSTRUCTOR - | kp::RULE_PROPERTY_DECLARATION - | kp::RULE_GETTER - | kp::RULE_SETTER - | kp::RULE_ASSIGNMENT - | kp::RULE_FOR_STATEMENT - | kp::RULE_WHILE_STATEMENT - | kp::RULE_DO_WHILE_STATEMENT - | kp::RULE_IF_EXPRESSION - | kp::RULE_WHEN_EXPRESSION - | kp::RULE_TRY_EXPRESSION - | kp::RULE_JUMP_EXPRESSION - ) { - self.current().loc.observe_lloc(); - } - - // A statement-position *plain* expression (e.g. a call statement - // `foo(bar())` or a bare `a + b`) is one LLOC. `declaration` / - // `assignment` / `loopStatement` payloads are counted via their own - // rules above. Control-flow expressions used as statements - // (`if`/`when`/`try`/`return`/`throw`/…) are *also* already counted - // by the rule arm above — counting them here too would double-count, - // so skip a `statement → expression` whose expression bottoms out in - // one of those forms. - if ri == kp::RULE_STATEMENT - && let Some(expr) = ctx.child_rule(kp::RULE_EXPRESSION) - && !expression_is_already_lloc(expr) - { - self.current().loc.observe_lloc(); - } - } - - /// NPA / NPM classification for a direct member of an enclosing class - /// body. `ctx` is the member declaration rule itself (the - /// `in_class_member` hint already flowed through the transparent - /// wrapper rules), and `ri` is its rule index. - fn classify_class_member(&mut self, ctx: RuleNodeView<'_>, ri: usize) { - let container = match self.kinds.last().cloned().unwrap_or(SpaceKind::Unit) { - SpaceKind::Class | SpaceKind::Impl => ContainerKind::Class, - SpaceKind::Interface | SpaceKind::Trait => ContainerKind::Interface, - _ => return, - }; - let public = member_is_public(ctx); - match ri { - kp::RULE_PROPERTY_DECLARATION => { - self.current().npa.record_attribute(container, public); - if public { - self.record_rule_evidence(ctx, |e, s| { - e.public_attribute(s, "property_declaration"); - }); - } - } - kp::RULE_FUNCTION_DECLARATION | kp::RULE_SECONDARY_CONSTRUCTOR => { - self.current().npm.record_method(container, public); - if public { - let detail = if ri == kp::RULE_FUNCTION_DECLARATION { - "function_declaration" - } else { - "secondary_constructor" - }; - self.record_rule_evidence(ctx, |e, s| e.public_method(s, detail)); - } - } - _ => {} - } - } -} - -// -------------------------------------------------------------------- -// Free helpers (top-down tree inspection — no parent pointers). -// -------------------------------------------------------------------- - -/// Is this node a `prefixUnaryExpression` carrying a logical-not prefix -/// (`!expr`)? Matched at the rule level — `prefixUnaryOperator` is the -/// logical `!`, whereas the postfix `!!` not-null assertion is -/// `postfixUnaryOperator` and shares the same `EXCL_*` tokens but is not a -/// negation. Used by [`Walker::visit_rule`] to isolate the negated operand's -/// boolean-sequence context (see the comment there). -fn is_logical_negation(ctx: RuleNodeView<'_>, ri: usize) -> bool { - ri == kp::RULE_PREFIX_UNARY_EXPRESSION - && kp::PrefixUnaryExpressionContext::from_rule_node(ctx).is_some_and(|expr| { - expr.unary_prefix_children().any(|prefix| { - prefix - .prefix_unary_operator() - .and_then(|op| op.excl()) - .is_some() - }) - }) -} - -/// Index of the `else`-branch `controlStructureBody` child of an -/// `ifExpression`, if present. The else body is the `controlStructureBody` -/// that appears *after* the `ELSE` terminal among the children. Takes the -/// child iterator directly so no `Vec` is allocated. -fn else_branch_index<'a>(children: impl Iterator>) -> Option { - let mut seen_else = false; - for (idx, child) in children.enumerate() { - if let Some(t) = child.as_terminal() { - if t.symbol().token_type() == kp::ELSE { - seen_else = true; - } - } else if let Some(rule) = child.as_rule() - && seen_else - && rule.rule_index() == kp::RULE_CONTROL_STRUCTURE_BODY - { - return Some(idx); - } - } - None -} - -/// The declared name of a class/function/object: its first -/// `simpleIdentifier` child's covered text. -fn rule_name(ctx: RuleNodeView<'_>) -> Option { - for child in ctx.children() { - if let Some(rule) = child.as_rule() - && matches!( - rule.rule_index(), - kp::RULE_SIMPLE_IDENTIFIER | kp::RULE_IDENTIFIER - ) - { - let t = rule.text(); - if !t.is_empty() { - return Some(t); - } - } - } - None -} - -/// Count the declared parameters of a function-like space. Handles every -/// parameter-list shape the grammar attaches to a function space: -/// -/// - `functionDeclaration` / `secondaryConstructor`: `functionValueParameters` -/// holding `functionValueParameter`s. -/// - `anonymousFunction`: `parametersWithOptionalType` holding -/// `functionValueParameterWithOptionalType`s. -/// - `setter`: a single `functionValueParameterWithOptionalType` as a direct -/// child (e.g. `set(value)`), with no enclosing parameter-list rule. -fn count_function_args(ctx: RuleNodeView<'_>) -> u32 { - let mut total = 0; - for child in ctx.children() { - if let Some(c) = child.as_rule() { - match c.rule_index() { - kp::RULE_FUNCTION_VALUE_PARAMETERS => { - total += c.child_rules(kp::RULE_FUNCTION_VALUE_PARAMETER).count() as u32; - } - kp::RULE_PARAMETERS_WITH_OPTIONAL_TYPE => { - total += c - .child_rules(kp::RULE_FUNCTION_VALUE_PARAMETER_WITH_OPTIONAL_TYPE) - .count() as u32; - } - // A setter's lone parameter sits directly under `setter`. - kp::RULE_FUNCTION_VALUE_PARAMETER_WITH_OPTIONAL_TYPE => total += 1, - _ => {} - } - } - } - total -} - -/// Count `lambdaParameter`s under a lambda literal's `lambdaParameters`. -/// -/// Reads the generated typed context (0.15 runtime): a `lambdaLiteral` has an -/// optional `lambdaParameters` child, which holds the repeated -/// `lambdaParameter`s. -fn count_lambda_args(ctx: RuleNodeView<'_>) -> u32 { - kp::LambdaLiteralContext::from_rule_node(ctx) - .and_then(|lambda| lambda.lambda_parameters()) - .map(|params| params.lambda_parameter_children().count() as u32) - .unwrap_or(0) -} - -/// Whether a member declaration is public — default unless a -/// `visibilityModifier` (`private`/`protected`/`internal`) overrides. -fn member_is_public(ctx: RuleNodeView<'_>) -> bool { - visibility_from_modifiers_of(ctx).unwrap_or(true) -} - -/// Explicit visibility declared *on this node itself* (via its own -/// `modifiers` child), or `None` if it has no visibility modifier. Used for -/// property accessors, whose own modifier overrides the property's. -fn visibility_from_modifiers_of(ctx: RuleNodeView<'_>) -> Option { - for child in ctx.children() { - if let Some(c) = child.as_rule() - && c.rule_index() == kp::RULE_MODIFIERS - { - return visibility_from_modifiers(c); - } - } - None -} - -/// Resolve an explicit visibility from a `modifiers` rule: `Some(false)` -/// for private/protected/internal, `Some(true)` for public, `None` if no -/// visibility modifier is present. -fn visibility_from_modifiers(modifiers: RuleNodeView<'_>) -> Option { - for child in modifiers.children() { - if let Some(modifier) = child.as_rule() { - if modifier.rule_index() != kp::RULE_MODIFIER { - continue; - } - // A `modifier` wraps a `visibilityModifier` rule whose token is - // the visibility keyword. - for inner in modifier.children() { - if let Some(vis) = inner.as_rule() - && vis.rule_index() == kp::RULE_VISIBILITY_MODIFIER - { - if vis.has_token(kp::PUBLIC) { - return Some(true); - } - if vis.has_token(kp::PRIVATE) - || vis.has_token(kp::PROTECTED) - || vis.has_token(kp::INTERNAL) - { - return Some(false); - } - } - } - } - } - None -} - -/// Record primary-constructor properties as class attributes (NPA). -/// -/// Walks `classDeclaration → primaryConstructor → classParameters → -/// classParameter` and counts each parameter that carries a `val`/`var` -/// keyword (a plain parameter without `val`/`var` is not a property). Each -/// counted parameter's visibility comes from its own modifiers (default -/// public). -fn record_constructor_properties( - class_ctx: RuleNodeView<'_>, - container: ContainerKind, - state: &mut State, - evidence: &mut MetricEvidence, - line_index: &LineIndex, - source_len: usize, -) { - // Navigate the typed chain (0.15 runtime): a class declaration's optional - // `primaryConstructor` holds a required `classParameters`, which holds the - // repeated `classParameter`s. - let Some(params) = kp::ClassDeclarationContext::from_rule_node(class_ctx) - .and_then(|class| class.primary_constructor()) - .and_then(|primary| primary.class_parameters().ok()) - else { - return; - }; - for param in params.class_parameter_children() { - // Only `val`/`var` parameters are properties (a plain parameter is - // not); the typed context exposes both keyword accessors of the - // `(VAL | VAR)?` group. - if param.val_token().is_none() && param.var_token().is_none() { - continue; - } - // `member_is_public` scans `modifiers` generically across several - // context types, so it stays on the underlying node. - let public = member_is_public(param.rule_node()); - state.npa.record_attribute(container, public); - if public && evidence.is_enabled() { - let span = ctx_span(param.rule_node(), line_index, source_len); - evidence.public_attribute(span, "class_parameter"); - } - } -} - -/// Whether a `statement`'s `expression` child bottoms out in a control-flow -/// expression that the rule-level LLOC arm already counts -/// (`if`/`when`/`try`/`jump`). Used to avoid double-counting those forms -/// when they appear as bare expression statements. -/// -/// Descends the single-child precedence-ladder wrappers (the same chain -/// `else if` detection walks); an operator splits the ladder into multiple -/// children, which means the expression is a compound (binary/call) form — -/// a plain statement that should be counted, so we stop and return false. -fn expression_is_already_lloc(expr: RuleNodeView<'_>) -> bool { - let mut current = expr; - loop { - match current.rule_index() { - kp::RULE_IF_EXPRESSION - | kp::RULE_WHEN_EXPRESSION - | kp::RULE_TRY_EXPRESSION - | kp::RULE_JUMP_EXPRESSION => return true, - _ => {} - } - // Follow the chain only while this rule is a transparent - // single-child wrapper leading toward a primary expression. - let mut rules = current.children().filter_map(|c| c.as_rule()); - match (rules.next(), rules.next()) { - (Some(only), None) if is_expression_ladder(current.rule_index()) => current = only, - _ => return false, - } - } -} - -/// Rules in the expression precedence ladder that the LLOC double-count -/// guard descends through (mirrors [`is_else_transparent`] minus the -/// statement/control-structure wrappers — here we start from `expression`). -fn is_expression_ladder(ri: usize) -> bool { - matches!( - ri, - kp::RULE_EXPRESSION - | kp::RULE_DISJUNCTION - | kp::RULE_CONJUNCTION - | kp::RULE_EQUALITY - | kp::RULE_COMPARISON - | kp::RULE_GENERIC_CALL_LIKE_COMPARISON - | kp::RULE_INFIX_OPERATION - | kp::RULE_ELVIS_EXPRESSION - | kp::RULE_INFIX_FUNCTION_CALL - | kp::RULE_RANGE_EXPRESSION - | kp::RULE_ADDITIVE_EXPRESSION - | kp::RULE_MULTIPLICATIVE_EXPRESSION - | kp::RULE_AS_EXPRESSION - | kp::RULE_PREFIX_UNARY_EXPRESSION - | kp::RULE_POSTFIX_UNARY_EXPRESSION - | kp::RULE_PRIMARY_EXPRESSION - // `(if (a) … else …)` wraps the control-flow expression in - // `parenthesizedExpression: LPAREN expression RPAREN`. The parens - // are terminals (filtered out), leaving a single rule child, so - // the descent continues into the inner expression — otherwise a - // parenthesized bare `if`/`when`/`try`/`jump` statement is - // double-counted as LLOC (once by its own rule arm, once by the - // `statement → expression` arm). - | kp::RULE_PARENTHESIZED_EXPRESSION - ) -} - -fn container_kind(parent_kind: SpaceKind) -> ContainerKind { - match parent_kind { - SpaceKind::Class | SpaceKind::Impl => ContainerKind::Class, - SpaceKind::Interface | SpaceKind::Trait => ContainerKind::Interface, - _ => ContainerKind::Other, - } -} - -// -------------------------------------------------------------------- -// ABC / Halstead token classification. -// -------------------------------------------------------------------- - -/// Comparison / equality / boolean operator tokens that count as an ABC -/// "condition". Multi-token operators (`?:`, `?.`, `!!`) are handled as -/// rules in [`Walker::classify_abc_rule`], not here. -fn is_abc_condition_token(tt: i32) -> bool { - matches!( - tt, - kp::EQEQ - | kp::EXCL_EQ - | kp::EQEQEQ - | kp::EXCL_EQEQ - | kp::LANGLE - | kp::RANGLE - | kp::LE - | kp::GE - | kp::CONJ - | kp::DISJ - ) -} - -/// Source spelling of an ABC-condition operator token, used as the -/// evidence reason detail (`kotlin.abc.condition.==`). Kept in sync with -/// [`is_abc_condition_token`]. -fn condition_token_spelling(tt: i32) -> &'static str { - match tt { - kp::EQEQ => "==", - kp::EXCL_EQ => "!=", - kp::EQEQEQ => "===", - kp::EXCL_EQEQ => "!==", - kp::LANGLE => "<", - kp::RANGLE => ">", - kp::LE => "<=", - kp::GE => ">=", - kp::CONJ => "&&", - kp::DISJ => "||", - _ => "condition", - } -} - -/// Rules the `is_else_branch` hint is allowed to flow through on its way -/// from an `ifExpression`'s else `controlStructureBody` down to a directly- -/// nested `ifExpression` (the `else if` case). This is exactly the -/// statement → expression precedence-ladder chain the kotlin-spec grammar -/// inserts between a control-structure body and a bare expression. -/// -/// `block` is intentionally absent: `else { if … }` introduces a real -/// nesting level and must not be flattened to an `else if`. -fn is_else_transparent(ri: usize) -> bool { - matches!( - ri, - kp::RULE_CONTROL_STRUCTURE_BODY - | kp::RULE_STATEMENT - | kp::RULE_EXPRESSION - | kp::RULE_DISJUNCTION - | kp::RULE_CONJUNCTION - | kp::RULE_EQUALITY - | kp::RULE_COMPARISON - | kp::RULE_GENERIC_CALL_LIKE_COMPARISON - | kp::RULE_INFIX_OPERATION - | kp::RULE_ELVIS_EXPRESSION - | kp::RULE_INFIX_FUNCTION_CALL - | kp::RULE_RANGE_EXPRESSION - | kp::RULE_ADDITIVE_EXPRESSION - | kp::RULE_MULTIPLICATIVE_EXPRESSION - | kp::RULE_AS_EXPRESSION - | kp::RULE_PREFIX_UNARY_EXPRESSION - | kp::RULE_POSTFIX_UNARY_EXPRESSION - | kp::RULE_PRIMARY_EXPRESSION - ) -} - -/// Rules that are direct class members (NPA/NPM candidates) once the -/// `in_class_member` hint has flowed down through the transparent wrapper -/// rules. -fn is_class_member_rule(ri: usize) -> bool { - matches!( - ri, - kp::RULE_PROPERTY_DECLARATION - | kp::RULE_FUNCTION_DECLARATION - | kp::RULE_SECONDARY_CONSTRUCTOR - ) -} - -/// Measure the leading *trivia* prefix of `text` — whitespace **and** -/// comments — up to the first real code byte, returning -/// `(embedded_newline_count, prefix_byte_len)`. -/// -/// Some tokens fold preceding trivia into their text (`AT_PRE_WS`/ -/// `AT_BOTH_WS` = e.g. `"\n@"`, `"/* c\n */@"`, or same-line `"/* docs */@"`), -/// so the token's reported line/start point at the trivia rather than the -/// real code character. Callers use the newline count to advance a PLOC row -/// and the byte length to advance a span's start offset past the folded -/// trivia. Since the token text is the verbatim source substring, the -/// prefix's byte length within `text` equals its byte length in the source. -fn leading_trivia(text: &str) -> (u32, usize) { - let bytes = text.as_bytes(); - let mut i = 0; - let mut count = 0u32; - while i < bytes.len() { - match bytes[i] { - b'\n' => { - count += 1; - i += 1; - } - b' ' | b'\t' | b'\r' => i += 1, - // Leading block comment: skip it, counting embedded newlines. - b'/' if bytes.get(i + 1) == Some(&b'*') => { - i += 2; - while i + 1 < bytes.len() && !(bytes[i] == b'*' && bytes[i + 1] == b'/') { - if bytes[i] == b'\n' { - count += 1; - } - i += 1; - } - i += 2; // consume `*/` - } - // Leading line comment: skip to end of line (the newline after it - // is counted on the next loop iteration). - b'/' if bytes.get(i + 1) == Some(&b'/') => { - while i < bytes.len() && bytes[i] != b'\n' { - i += 1; - } - } - _ => break, - } - } - (count, i.min(bytes.len())) -} - -/// Count the newlines in the leading trivia prefix of `text` (see -/// [`leading_trivia`]). Used to advance a token's PLOC row past trivia folded -/// into the token, so the code line is where the real character is. -fn leading_newlines(text: &str) -> u32 { - leading_trivia(text).0 -} - -/// Whether a token type folds *leading* trivia (whitespace/newlines/comments) -/// into its text. Only the annotation `@` tokens whose lexer rule begins with -/// `(Hidden | NL)` do — `AT_PRE_WS` and `AT_BOTH_WS`. Other trivia-bearing -/// tokens fold *trailing* trivia (the lexeme comes first), so their leading -/// prefix is never trivia. Crucially this must exclude string-content tokens: -/// a raw multiline string whose first line is `// …` or `/* … */` is literal -/// content, not folded trivia, and the leading-trivia heuristic must not -/// touch it. -fn folds_leading_trivia(tt: i32) -> bool { - matches!(tt, kp::AT_PRE_WS | kp::AT_BOTH_WS) -} - -/// Rules that open a class-like metric space (see `maybe_open_space`). Used -/// to clear the `in_anon_body` suppression once a real nested class/object -/// owns the following body — its members belong to that class, not the enum. -fn opens_class_like(ri: usize) -> bool { - matches!( - ri, - kp::RULE_CLASS_DECLARATION | kp::RULE_OBJECT_DECLARATION | kp::RULE_COMPANION_OBJECT - ) -} - -enum HalsteadClass { - Operator, - Operand, - Skip, -} - -/// Classify a token type as a Halstead operator, operand, or skipped. -/// -/// Keywords and punctuation are operators; identifiers, literals, `this`, -/// `super`, and `field` are operands. Whitespace/newline, EOF, comments, -/// and string-delimiter tokens are skipped. -fn halstead_class(tt: i32) -> HalsteadClass { - // Operands: identifiers, literals, this/super/field, string text. - if matches!( - tt, - kp::IDENTIFIER - | kp::INTEGER_LITERAL - | kp::HEX_LITERAL - | kp::BIN_LITERAL - | kp::REAL_LITERAL - | kp::FLOAT_LITERAL - | kp::DOUBLE_LITERAL - | kp::LONG_LITERAL - | kp::UNSIGNED_LITERAL - | kp::CHARACTER_LITERAL - | kp::BOOLEAN_LITERAL - | kp::NULL_LITERAL - | kp::THIS - | kp::SUPER - // Labeled receivers (`this@Outer`, `super@Outer`) lex as single - // `THIS_AT`/`SUPER_AT` tokens — they name the same receiver value - // as bare `this`/`super`, so they are operands, not operators. - | kp::THIS_AT - | kp::SUPER_AT - | kp::FIELD - // String *content* tokens are operands (the literal's value), - // matching plain text: line/multiline text, escaped chars - // (`\n`), and the literal `"` runs inside a raw string. - | kp::LINE_STR_TEXT - | kp::MULTI_LINE_STR_TEXT - | kp::LINE_STR_ESCAPED_CHAR - | kp::MULTI_LINE_STRING_QUOTE - // Simple string-template references (`"$x"`) lex as a single - // `…_STR_REF` token holding the interpolated identifier — it's - // the operand, matching the `"${x}"` expression form. - | kp::LINE_STR_REF - | kp::MULTI_LINE_STR_REF - ) { - return HalsteadClass::Operand; - } - - // Skip structural / trivia tokens, including the string delimiters for - // both ordinary (`"`) and raw/triple-quoted (`"""`) strings so raw - // strings don't record extra Halstead operators vs. ordinary literals. - // - // `NL` is skipped because Kotlin emits a newline token between nearly - // every construct — it is pervasive structural whitespace, not an - // operator the programmer wrote. An *explicit* `;` statement separator is - // different: it is a typed punctuator, peer to `,`/`.`/`:`/`(`, all of - // which count as operators — so the semicolon falls through to the - // operator default below rather than being skipped here. - if matches!( - tt, - kp::NL - | kp::QUOTE_OPEN - | kp::QUOTE_CLOSE - | kp::TRIPLE_QUOTE_OPEN - | kp::TRIPLE_QUOTE_CLOSE - // A `.kts` shebang (`#!/usr/bin/env kotlin`) is an interpreter - // directive, not a Kotlin operator/operand — skip it. - | kp::SHEBANG_LINE - ) || tt < 0 - { - return HalsteadClass::Skip; - } - - // Everything else (keywords, punctuation including the explicit `;`, - // operators) is an operator. - HalsteadClass::Operator -} - -/// A stable string label for an operator token, used as its Halstead -/// operator key. The numeric token type is stable for a given generated -/// grammar, so we render it as a compact label. -fn kp_token_name(tt: i32) -> String { - format!("t{tt}") -} diff --git a/crates/mehen-kotlin/tests/abc.rs b/crates/mehen-kotlin/tests/abc.rs deleted file mode 100644 index 8391f12f..00000000 --- a/crates/mehen-kotlin/tests/abc.rs +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_abc_basic() { - let a = analyze( - "fun f(a: Int, b: Int): Int { - val c = a + b // +1 A (val with initializer) - log(c) // +1 B - if (c > 0) { // +1 C (if) + +1 C (>) - return c - } - return 0 - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 1.0, - "branches": 1.0, - "conditions": 2.0, - "magnitude": 2.449489742783178, - "assignments_average": 0.5, - "branches_average": 0.5, - "conditions_average": 1.0, - "assignments_min": 0.0, - "assignments_max": 1.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 2.0 - }"### - ); -} diff --git a/crates/mehen-kotlin/tests/cognitive.rs b/crates/mehen-kotlin/tests/cognitive.rs deleted file mode 100644 index 650886b3..00000000 --- a/crates/mehen-kotlin/tests/cognitive.rs +++ /dev/null @@ -1,375 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity tests for the tree-sitter-kotlin walker. -//! -//! Ports the legacy `kotlin_*` cognitive tests from -//! `crates/mehen-engine/src/legacy/metrics/cognitive.rs` byte-identical. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_nested_if_increments_nesting() { - let a = analyze( - "fun f(a: Boolean, b: Boolean) { - if (a) { // +1 - if (b) { // +2 (nesting = 1) - println(\"hi\") - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn kotlin_try_catch_nesting() { - // SonarKotlin's `CognitiveComplexity` increments and bumps nesting on - // `KtCatchClause`, not on the enclosing `try`. An `if` inside the - // catch block therefore sees nesting=1 at the +1 structural cost. - let a = analyze( - "fun f() { - try { - if (a) { // +1 (try itself contributes 0) - println(\"a\") - } - } catch (e: Exception) { // +1 catch - if (b) { // +2 (nesting = 1 from catch) - println(\"b\") - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn kotlin_labeled_break_and_continue() { - // Label-qualified `break@label` / `continue@label` flip the linear - // flow and earn +1 each per the Sonar whitepaper. Unlabelled forms - // don't. - let a = analyze( - "fun f() { - outer@ for (i in 0..10) { // +1 for - for (j in 0..10) { // +2 (nesting=1) - if (i == j) { // +3 (nesting=2) - continue@outer // +1 labelled continue - } - if (j > 5) { // +3 (nesting=2) - break@outer // +1 labelled break - } - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 11.0, - "average": 11.0, - "min": 0.0, - "max": 11.0 - }"### - ); -} - -#[test] -fn kotlin_else_if_counts_as_one() { - // `else if` in Kotlin parses as an `if_expression` whose parent is - // another `if_expression`. It should NOT increase nesting; only the - // `else` keyword adds +1, matching other C-style languages. - let a = analyze( - "fun f(a: Int) { - if (a > 0) { // +1 - println(\"pos\") - } else if (a < 0) { // +1 - println(\"neg\") - } else { // +1 - println(\"zero\") - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn kotlin_nested_if_in_then_branch_is_not_else_if() { - // Regression: an unbraced nested `if` in the *then* branch of an - // outer `if` parses as `if_expression > control_structure_body > - // if_expression`. The grammar also uses `control_structure_body` - // for the `else` branch, so `is_else_if` must specifically check - // that the body it lives in is the outer if's `alternative`, not - // its `consequence`. Otherwise this nested-if is misclassified as - // `else if` and cognitive complexity undercounts by 2 (no +1 - // structural cost and no +1 nesting). - let a = analyze( - "fun f(a: Boolean, b: Boolean) { - if (a) // +1 - if (b) // +2 (nesting = 1) - println(\"hi\") - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn kotlin_nested_if_inside_else_if_chain_counts() { - // Mixed shape: a nested `if` inside both the then-branch of the - // outer `if` AND the body of an `else if`. The outer `if` counts - // +1, the nested `if` in the then-branch counts +2 (nesting=1), - // the `else if` counts +1 (flattened, no nesting), and its nested - // `if` counts +2 (nesting=1) for a total of 6. This locks in that - // the fix only flattens the else-branch, not the then-branch. - let a = analyze( - "fun f(a: Int, b: Int) { - if (a > 0) { // +1 - if (b > 0) { // +2 (nesting = 1) - println(\"x\") - } - } else if (a < 0) { // +1 (flattened else-if) - if (b > 0) { // +2 (nesting = 1) - println(\"y\") - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 6.0, - "average": 6.0, - "min": 0.0, - "max": 6.0 - }"### - ); -} - -#[test] -fn kotlin_nesting_preserved_after_nested_lambda() { - // Regression: a lambda resets the cognitive context on entry. Sibling - // code after the lambda (the second `if`) must still see the enclosing - // `if`'s nesting. If the outer context isn't snapshotted *before* the - // lambda's function-entry reset, the inner `if` under-counts (sum 2). - let a = analyze( - "fun f(a: Boolean, xs: List) { - if (a) { // +1 - xs.forEach { println(it) } // lambda resets context - if (a) { // +2 (nesting = 1, preserved) - println(\"x\") - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!( - cog.sum, 3.0, - "inner if must retain outer nesting after lambda" - ); -} - -#[test] -fn kotlin_negation_does_not_break_boolean_sequence() { - // A prefix `!` negation does NOT break a same-operator boolean run. Both - // SonarJava (`CognitiveComplexityVisitor.flattenLogicalExpression`) and - // SonarKotlin (`CognitiveComplexity.flattenOperators`) flatten only the - // `&&`/`||` operators and treat a negated operand as a plain operand where - // flattening stops — the `!` is invisible to the run. So `a && !b && c` - // is a single `&&` run → +1, exactly like `a && b && c` (issue #217). - let a = analyze( - "fun g(a: Boolean, b: Boolean, c: Boolean): Boolean { - return a && !b && c - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 1.0, "negation must not break the run"); -} - -/// Regression (PR #235 review): a *logical subtree* under a negation is an -/// independent boolean context, like a call argument. In SonarSource's tree -/// flattening a negated operand is a leaf of the enclosing run — flattening -/// stops there — so the inner run is scored separately, not collapsed into -/// the outer one. `a && !(b && c) && d` is one outer `&&` run (+1) plus one -/// inner `&&` run (+1) → 2. Making `!` a complete no-op would feed all three -/// `&&` into the same `last_op` state and undercount this as 1. -#[test] -fn kotlin_negated_logical_subtree_is_a_separate_boolean_run() { - let a = analyze( - "fun g(a: Boolean, b: Boolean, c: Boolean, d: Boolean): Boolean { - return a && !(b && c) && d - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 2.0, "inner run under `!` is a separate run"); - - // Leading form: `!(a && b) && c` — the negated subtree's `&&` and the - // outer `&&` are two runs → 2. - let a = analyze( - "fun g(a: Boolean, b: Boolean, c: Boolean): Boolean { - return !(a && b) && c - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 2.0, "leading negated subtree is its own run"); - - // Same-kind operator on both sides of the boundary, `||` flavour: - // `a || !(b || c) || d` → outer `||` run + inner `||` run = 2. - let a = analyze( - "fun g(a: Boolean, b: Boolean, c: Boolean, d: Boolean): Boolean { - return a || !(b || c) || d - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 2.0, "negated `||` subtree is its own run"); - - // Mixed kinds still count each alternation: `a && !(b || c) && d` is an - // outer `&&` run (+1) plus an inner `||` run (+1) → 2, and the isolation - // must not double-count the outer run's continuation after the operand. - let a = analyze( - "fun g(a: Boolean, b: Boolean, c: Boolean, d: Boolean): Boolean { - return a && !(b || c) && d - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!( - cog.sum, 2.0, - "outer run continues across the negated operand" - ); - - // A *scalar* negation stays invisible: parenthesized single operand has - // no inner run, so `a && !(b) && c` is one run → 1, same as `a && !b && c`. - let a = analyze( - "fun g(a: Boolean, b: Boolean, c: Boolean): Boolean { - return a && !(b) && c - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 1.0, "scalar negation still does not break the run"); -} - -#[test] -fn kotlin_boolean_sequence_resets_between_call_statements() { - // Two standalone calls each carrying `&&`. The boolean sequence must - // reset at the statement boundary, so the second `&&` adds +1 instead - // of collapsing with the first → +2, not +1. - let a = analyze( - "fun h(a: Boolean, b: Boolean, c: Boolean, d: Boolean) { - foo(a && b) - bar(c && d) - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 2.0); -} - -/// Regression: the postfix `!!` not-null assertion shares the `EXCL_*` -/// tokens with the prefix `!` logical-not; neither breaks a boolean run. -/// `a && b!! && c` collapses both `&&` into one run → +1, same as -/// `a && !b && c` (see `kotlin_negation_does_not_break_boolean_sequence`). -#[test] -fn kotlin_not_null_assertion_does_not_break_boolean_sequence() { - let a = analyze( - "fun h(a: Boolean, b: Boolean?, c: Boolean): Boolean { - return a && b!! && c - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 1.0); -} - -/// Regression: two independent call-argument expressions in a *single* -/// statement, each with the same boolean operator (`g(a && b) + g(c && d)`), -/// are separate boolean runs — the second `&&` must not collapse with the -/// first. A call argument is an independent boolean context: its `last_op` is -/// saved/reset on entry and restored on exit, so the two `&&` count +2. -#[test] -fn kotlin_boolean_sequence_resets_between_call_args_in_one_statement() { - let a = analyze( - "fun h(a: Boolean, b: Boolean, c: Boolean, d: Boolean): Int { - return g(a && b) + g(c && d) - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 2.0, "two independent call-arg `&&` runs are +2"); -} - -/// Regression: a call used as an *operand* of a surrounding boolean run must -/// NOT break that run. `a && g(x) && b` is one outer `&&` sequence with the -/// call isolated as a single operand → +1. (The save/restore of the call -/// argument's boolean state must leave the *outer* `last_op` intact, so this -/// must not regress to +2 — which a flat per-call reset would cause.) -#[test] -fn kotlin_call_operand_does_not_break_enclosing_boolean_sequence() { - let with_empty_call = analyze( - "fun h(a: Boolean, b: Boolean): Boolean { - return a && g() && b - }", - ); - let with_arg_call = analyze( - "fun h(a: Boolean, b: Boolean, x: Int): Boolean { - return a && g(x) && b - }", - ); - assert_eq!( - mehen_report::metrics_json::cognitive(&with_empty_call.root.metrics).sum, - 1.0, - "a call with no args must not break the outer `&&` run" - ); - assert_eq!( - mehen_report::metrics_json::cognitive(&with_arg_call.root.metrics).sum, - 1.0, - "a call with an argument must not break the outer `&&` run" - ); -} diff --git a/crates/mehen-kotlin/tests/contributions.rs b/crates/mehen-kotlin/tests/contributions.rs deleted file mode 100644 index e01b7a0b..00000000 --- a/crates/mehen-kotlin/tests/contributions.rs +++ /dev/null @@ -1,199 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the Kotlin analyzer (plan §5.4). - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - KotlinAnalyzer::new() - .analyze( - &SourceFile::new("S.kt".into(), Language::Kotlin, source.to_string()), - config, - ) - .expect("Kotlin analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -class Classifier(val bias: Int) { - fun classify(a: Int, b: Int): Int { - if (a > 0 && b > 0) { - return 1 - } else { - return -1 - } - } - - fun tally(items: List): Int { - var total = 0 - for (item in items) { - total += item - } - val doubled = items.map { it * 2 } - return when { - total > 10 -> total - else -> doubled.size - } - } -} -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ("npa", "npa"), - ("npm", "npm"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn reasons_are_kotlin_namespaced_with_grammar_names() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "kotlin.cyclomatic.if_expression", - "kotlin.cyclomatic.for_statement", - "kotlin.cyclomatic.when_entry", - "kotlin.cyclomatic.&&", - "kotlin.cognitive.if_expression", - "kotlin.cognitive.for_statement", - "kotlin.cognitive.when_expression", - "kotlin.cognitive.else", - "kotlin.nexit.return", - "kotlin.abc.assignment.property_declaration", - "kotlin.abc.assignment.assignment", - "kotlin.abc.branch.call_suffix", - "kotlin.abc.condition.if_expression", - "kotlin.abc.condition.>", - "kotlin.nom.function.function_declaration", - "kotlin.nom.closure.lambda_literal", - "kotlin.nargs.function.function_declaration", - "kotlin.npa.class_parameter", - "kotlin.npm.function_declaration", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("kotlin."))); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn boolean_run_transitions_record_only_moved_deltas() { - let source = "\ -fun f(a: Boolean, b: Boolean, c: Boolean): Int { - if (a && b && c) { - return 1 - } - return 0 -} -"; - let analysis = analyze(source, &AnalysisConfig::production()); - let boolean: Vec = analysis - .contributions - .iter() - .filter(|item| item.reason.as_str() == "kotlin.cognitive.&&") - .map(|item| item.amount) - .collect(); - assert_eq!(boolean, vec![1.0]); - assert_eq!(metric(&analysis, "cognitive.sum"), 2.0); // if + boolean run -} - -#[test] -fn private_members_record_no_public_evidence() { - let source = "\ -class Vault(private val secret: Int, val open: Int) { - private fun hidden() {} - fun visible() {} -} -"; - let analysis = analyze(source, &AnalysisConfig::production()); - assert_eq!(evidence_sum(&analysis, "npa"), metric(&analysis, "npa")); - assert_eq!(evidence_sum(&analysis, "npm"), metric(&analysis, "npm")); - assert_eq!(evidence_sum(&analysis, "npa"), 1.0); - assert_eq!(evidence_sum(&analysis, "npm"), 1.0); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc", - "npa", - "npm", - "wmc", - ] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-kotlin/tests/cyclomatic.rs b/crates/mehen-kotlin/tests/cyclomatic.rs deleted file mode 100644 index 7c13a362..00000000 --- a/crates/mehen-kotlin/tests/cyclomatic.rs +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity tests for the tree-sitter-kotlin walker. -//! -//! Every legacy `check_metrics::` cyclomatic test from -//! `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs` is ported -//! here byte-identical so the parity contract (plan §12.3.1) is -//! visibly maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_simple_function() { - let a = analyze( - "fun f(a: Int, b: Int): Int { // +2 (+1 unit space, +1 fun) - if (a > b) { // +1 - return a - } - return b - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn kotlin_when_branches_count() { - // `when` itself doesn't add; each branch (`when_entry`) does. - let a = analyze( - "fun grade(score: Int): String { // +2 (+1 unit, +1 fun) - return when { // +0 - score >= 90 -> \"A\" // +1 - score >= 80 -> \"B\" // +1 - score >= 70 -> \"C\" // +1 - else -> \"F\" // +1 (else is its own when_entry) - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - }"### - ); -} - -#[test] -fn kotlin_try_catch_counts_catch_not_try() { - // Aligns with SonarKotlin's `CyclomaticComplexityVisitor`: `try` - // itself is NOT a decision point, and `catch` is NOT either — - // SonarKotlin counts `catch` only in cognitive complexity, not - // cyclomatic. Reference: - // sonar-kotlin-metrics/.../CyclomaticComplexityVisitor.kt - let a = analyze( - "fun f() { // +2 (+1 unit, +1 fun) - try { - risky() - } catch (e: Exception) { - // catch does not add cyclomatic complexity per SonarKotlin - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0 - }"### - ); -} - -#[test] -fn kotlin_logical_operators() { - let a = analyze( - "fun check(a: Boolean, b: Boolean, c: Boolean): Boolean { // +2 - if (a && b || c) { // +3 (+1 if, +1 &&, +1 ||) - return true - } - return false - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - }"### - ); -} diff --git a/crates/mehen-kotlin/tests/exit.rs b/crates/mehen-kotlin/tests/exit.rs deleted file mode 100644 index 7e3c02e1..00000000 --- a/crates/mehen-kotlin/tests/exit.rs +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NExit tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_return_and_throw_count_as_exits() { - let a = analyze( - "fun f(a: Int): Int { - if (a < 0) { - throw IllegalArgumentException(\"bad\") - } - return a - }", - ); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn kotlin_labeled_lambda_return_does_not_count_as_function_exit() { - let a = analyze( - "fun f(xs: List) { - xs.forEach { x -> - if (x < 0) return@forEach - } - }", - ); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} diff --git a/crates/mehen-kotlin/tests/halstead.rs b/crates/mehen-kotlin/tests/halstead.rs deleted file mode 100644 index 176d529a..00000000 --- a/crates/mehen-kotlin/tests/halstead.rs +++ /dev/null @@ -1,234 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Halstead tests for the ANTLR Kotlin walker. -//! -//! The ANTLR backend tokenizes Kotlin more completely than the former -//! tree-sitter walker: every lexical token is classified, so closing -//! delimiters (`)`, `}`) count as distinct Halstead operators alongside -//! their opening forms. Operand counts are unchanged. These snapshots -//! reflect the richer (and more classically Halstead-complete) operator -//! vocabulary — an intentional improvement over the tree-sitter numbers, -//! per the ANTLR migration's "improve where the grammar allows" policy. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Regression: `get`/`set` accessor keywords must be Halstead operators -/// and `field` must be an operand. The ANTLR walker classifies a token -/// reached via the `simpleIdentifier` rule as an operand, so Kotlin soft -/// keywords used as names (`value`, `field`) count as operands while the -/// `get`/`set` accessor keywords (reached via the `getter`/`setter` rules) -/// stay operators. -/// -/// Operands (distinct by text): `C`, `x`, `Int`, `0`, `field`, `value` = 6. -/// Operators (distinct token types): `class`, `{`, `}`, `var`, `:`, `=`, -/// `get`, `(`, `)`, `set` = 10. (The ANTLR lexer counts both opening and -/// closing delimiters, unlike the former tree-sitter walker.) -#[test] -fn kotlin_accessor_tokens_contribute_to_halstead() { - let a = analyze( - "class C { - var x: Int = 0 - get() = field - set(value) { field = value } - }", - ); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - assert_eq!(h.n1, 10.0, "distinct operators"); - assert_eq!(h.big_n1, 16.0); - assert_eq!(h.n2, 6.0, "distinct operands (C/x/Int/0/field/value)"); - assert_eq!(h.big_n2, 8.0); -} - -#[test] -fn kotlin_operators_and_operands() { - let a = analyze( - "fun add(a: Int, b: Int): Int { - return a + b - }", - ); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - // Only core counts are locked in; derived measures shift with the - // vocabulary in ways that aren't meaningful to assert. - insta::assert_json_snapshot!( - h, - { - ".estimated_program_length" => "[masked]", - ".purity_ratio" => "[masked]", - ".volume" => "[masked]", - ".difficulty" => "[masked]", - ".level" => "[masked]", - ".effort" => "[masked]", - ".time" => "[masked]", - ".bugs" => "[masked]" - }, - @r###" - { - "n1": 9.0, - "N1": 11.0, - "n2": 4.0, - "N2": 8.0, - "length": 19.0, - "estimated_program_length": "[masked]", - "purity_ratio": "[masked]", - "vocabulary": 13.0, - "volume": "[masked]", - "difficulty": "[masked]", - "level": "[masked]", - "effort": "[masked]", - "time": "[masked]", - "bugs": "[masked]" - }"### - ); -} - -/// Regression: raw/triple-quoted string delimiters (`"""`) are skipped in -/// Halstead just like ordinary `"` delimiters, so a raw string records the -/// same operator counts as an equivalent ordinary string (no inflation). -#[test] -fn kotlin_raw_string_delimiters_excluded_from_halstead() { - let raw = analyze("fun f() = \"\"\"hello\"\"\"\n"); - let ord = analyze("fun f() = \"hello\"\n"); - let rh = mehen_report::metrics_json::halstead(&raw.root.metrics); - let oh = mehen_report::metrics_json::halstead(&ord.root.metrics); - assert_eq!( - (rh.n1, rh.big_n1), - (oh.n1, oh.big_n1), - "raw-string delimiters must not add Halstead operators vs. ordinary strings" - ); -} - -/// Regression: a simple string-template reference (`"$x"`) lexes as a single -/// `LINE_STR_REF` token holding the interpolated identifier, which must be a -/// Halstead operand (like the `x` in the `"${x}"` form) rather than falling -/// through to the operator default. -#[test] -fn kotlin_simple_string_template_ref_is_operand() { - // `fun f(x: Int) = "$x"`. Operands (distinct text): `f`, `x`, `Int`, and - // the `$x` ref token (text `$x`) = 4. The point is that the ref counts as - // an *operand* — before the fix it fell through to the operator default, - // so it would have inflated n1 and been absent from n2. - let with_ref = analyze("fun f(x: Int) = \"$x\"\n"); - let h = mehen_report::metrics_json::halstead(&with_ref.root.metrics); - assert_eq!(h.n2, 4.0, "the `$x` ref must be counted as an operand"); - // Sanity: an ordinary string literal of the same shape has the same - // operator count — the ref didn't leak into operators. - let plain = analyze("fun f(x: Int) = \"hi\"\n"); - let ph = mehen_report::metrics_json::halstead(&plain.root.metrics); - assert_eq!(h.n1, ph.n1, "the ref must not be classified as an operator"); -} - -/// Regression: string *content* tokens — escaped chars (`\n` → -/// `LINE_STR_ESCAPED_CHAR`) and the literal `"` runs in raw strings -/// (`MULTI_LINE_STRING_QUOTE`) — are Halstead operands (the literal's value), -/// not operators. An escape must not inflate the operator count vs. an -/// equivalent plain string. -#[test] -fn kotlin_string_escape_content_is_operand_not_operator() { - let esc = analyze("fun f() = \"a\\nb\"\n"); - let plain = analyze("fun f() = \"ab\"\n"); - let eh = mehen_report::metrics_json::halstead(&esc.root.metrics); - let ph = mehen_report::metrics_json::halstead(&plain.root.metrics); - assert_eq!( - eh.n1, ph.n1, - "the \\n escape must be an operand, not an extra operator" - ); -} - -/// Analyze as a `.kts` script so the shebang is parsed via the `script` -/// entry rule. -fn analyze_kts(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kts".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Regression: a `.kts` shebang (`#!/usr/bin/env kotlin`) is an interpreter -/// directive, not a Kotlin operator/operand. It must not contribute to the -/// Halstead vocabulary — a script with a shebang has the same operator and -/// operand counts as the same script without one. -#[test] -fn kotlin_shebang_excluded_from_halstead() { - let with_shebang = analyze_kts("#!/usr/bin/env kotlin\nval x = 1\nprintln(x)\n"); - let without = analyze_kts("val x = 1\nprintln(x)\n"); - let wh = mehen_report::metrics_json::halstead(&with_shebang.root.metrics); - let oh = mehen_report::metrics_json::halstead(&without.root.metrics); - assert_eq!( - (wh.n1, wh.big_n1, wh.n2, wh.big_n2), - (oh.n1, oh.big_n1, oh.n2, oh.big_n2), - "the shebang must not change any Halstead count" - ); -} - -/// Regression: an empty string literal (`""` / `""""""`) emits only -/// delimiter tokens (all skipped) and no content token, so it would record -/// no Halstead operand at all — undercounting Halstead/MI for the common -/// empty-string default. An empty literal must count as one operand, like a -/// non-empty literal of the same shape. -#[test] -fn kotlin_empty_string_literal_is_operand() { - let empty = analyze("fun f() = \"\"\n"); - let nonempty = analyze("fun f() = \"x\"\n"); - let raw_empty = analyze("fun f() = \"\"\"\"\"\"\n"); - let eh = mehen_report::metrics_json::halstead(&empty.root.metrics); - let nh = mehen_report::metrics_json::halstead(&nonempty.root.metrics); - let rh = mehen_report::metrics_json::halstead(&raw_empty.root.metrics); - // `f` + the literal = 2 operands, total 2, same as a non-empty literal. - assert_eq!((eh.n2, eh.big_n2), (2.0, 2.0), "empty `\"\"` is an operand"); - assert_eq!((eh.n2, eh.big_n2), (nh.n2, nh.big_n2)); - assert_eq!( - (rh.n2, rh.big_n2), - (2.0, 2.0), - "empty raw `\"\"\"\"\"\"` is an operand" - ); -} - -/// Regression: a labeled receiver (`this@Outer` / `super@Outer`) lexes as a -/// single `THIS_AT`/`SUPER_AT` token. It names the same receiver value as -/// bare `this`/`super`, so it must be a Halstead operand — not fall through -/// to the operator default (which both inflates n1 and drops the receiver -/// from the operand set). -#[test] -fn kotlin_labeled_receiver_is_operand() { - let labeled = - analyze("class Outer {\n inner class Inner {\n fun f() = this@Outer\n }\n}\n"); - let bare = analyze("class Outer {\n inner class Inner {\n fun f() = this\n }\n}\n"); - let lh = mehen_report::metrics_json::halstead(&labeled.root.metrics); - let bh = mehen_report::metrics_json::halstead(&bare.root.metrics); - // `this@Outer` must classify exactly like bare `this`. - assert_eq!( - (lh.n1, lh.big_n1, lh.n2, lh.big_n2), - (bh.n1, bh.big_n1, bh.n2, bh.big_n2), - "this@Outer must classify like bare this (operand, not operator)" - ); -} - -/// Regression: an *explicit* `;` statement separator (`val a = 1; val b = 2`) -/// is a typed punctuator, peer to `,`/`.`/`:`/`(` — it must count as a -/// Halstead operator. (Only `NL`, which Kotlin emits pervasively as -/// structural whitespace, is skipped.) An explicit semicolon therefore adds -/// exactly one distinct operator vs. the newline-separated form. -#[test] -fn kotlin_explicit_semicolon_is_operator() { - let semi = analyze("fun f() { val a = 1; val b = 2 }\n"); - let newline = analyze("fun f() { val a = 1\n val b = 2 }\n"); - let sh = mehen_report::metrics_json::halstead(&semi.root.metrics); - let nh = mehen_report::metrics_json::halstead(&newline.root.metrics); - assert_eq!( - sh.n1, - nh.n1 + 1.0, - "the explicit `;` must add one distinct operator" - ); - assert_eq!(sh.big_n1, nh.big_n1 + 1.0, "and one operator occurrence"); -} diff --git a/crates/mehen-kotlin/tests/loc.rs b/crates/mehen-kotlin/tests/loc.rs deleted file mode 100644 index 322a200d..00000000 --- a/crates/mehen-kotlin/tests/loc.rs +++ /dev/null @@ -1,327 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - // Match the legacy `check_metrics` test harness: trim whitespace, - // append a single trailing newline. The line-count helpers in - // `LineIndex` count `\n` boundaries so the trailing newline pushes - // SLOC up by one row, matching the legacy snapshots. - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_simple_loc() { - let a = analyze( - "// header - fun greet(name: String) { - println(\"hi, \" + name) - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!(loc); -} - -#[test] -fn kotlin_nested_calls_do_not_add_extra_lloc() { - let a = analyze( - "fun f() { - val x = foo(bar()) - foo(bar()) - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - loc, - @r###" - { - "sloc": 4.0, - "ploc": 4.0, - "lloc": 3.0, - "cloc": 0.0, - "blank": 0.0, - "sloc_average": 2.0, - "ploc_average": 2.0, - "lloc_average": 1.5, - "cloc_average": 0.0, - "blank_average": 0.0, - "sloc_min": 4.0, - "sloc_max": 4.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 4.0, - "ploc_max": 4.0, - "lloc_min": 3.0, - "lloc_max": 3.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} - -#[test] -fn kotlin_counts_companion_and_accessors_as_lloc() { - let a = analyze( - "class C { - companion object { - fun make() = C() - } - - var x: Int = 0 - get() = field - set(value) { field = value } - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!(loc.lloc, 7.0); -} - -/// Regression: a control-flow expression used as a statement (`if`, -/// `return`, …) is counted as LLOC by its own rule arm. The -/// `statement → expression` arm must NOT count it again, or every bare -/// `if`/`when`/`try`/`return`/`throw` statement records two LLOC. -#[test] -fn kotlin_control_flow_statements_count_lloc_once() { - let a = analyze( - "fun f(a: Int): Int { - if (a > 0) { foo() } - bar() - return a - }", - ); - // f (1) + if (1) + foo() (1) + bar() (1) + return (1) = 5. - // (Pre-fix: the `if` and `return` would each count twice → 7.) - assert_eq!(mehen_report::metrics_json::loc(&a.root.metrics).lloc, 5.0); -} - -/// Regression: a *parenthesized* bare control-flow expression -/// (`(if (a) foo() else bar())`) must not be double-counted as LLOC. The -/// `statement → expression` dedup guard descends the precedence ladder to -/// find an already-counted `if`/`when`/`try`/`jump`; it must also descend -/// through `parenthesizedExpression` (a single-rule-child wrapper), or the -/// parenthesized form counts once by the inner `if` arm and again by the -/// statement arm. -#[test] -fn kotlin_parenthesized_control_flow_counts_lloc_once() { - let paren = analyze("fun f(a: Boolean) {\n (if (a) foo() else bar())\n}\n"); - let plain = analyze("fun f(a: Boolean) {\n if (a) foo() else bar()\n}\n"); - assert_eq!( - mehen_report::metrics_json::loc(&paren.root.metrics).lloc, - mehen_report::metrics_json::loc(&plain.root.metrics).lloc, - "parenthesizing a bare `if` statement must not add an LLOC" - ); -} - -/// Regression: a multiline block comment that starts after code on the same -/// line (`val x = /* … */ 1`) is classified as a code-comment, not -/// comment-only — comments are now routed in source order after the AST walk -/// (which seeds each space's known code lines), so the "comment shares a line -/// with code" check sees the code. The file totals stay correct. -#[test] -fn kotlin_inline_block_comment_after_code() { - let a = analyze( - "fun f(): Int { - val x = /* trailing */ 1 - return x - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - // The inline block comment shares the `val x = … 1` line, so it is a - // code-comment: cloc counts it but it adds no comment-only/blank line. - assert_eq!(loc.cloc, 1.0); - assert_eq!(loc.blank, 0.0); -} - -/// Regression: Kotlin folds optional trivia into certain operator tokens -/// (`NOT_IS: '!is' (Hidden|NL)`), so a comment glued to the operator -/// (`x !is/* note */ Int`) lives inside the operator token's text rather than -/// a standalone comment token. The LOC pass scans these trivia-bearing -/// operators for embedded comments so CLOC isn't undercounted. -#[test] -fn kotlin_comment_embedded_in_operator_token_counts_as_cloc() { - let a = analyze( - "fun f(x: Any): Boolean { - return x !is/* note */ Int - }", - ); - assert_eq!(mehen_report::metrics_json::loc(&a.root.metrics).cloc, 1.0); -} - -/// Regression: `AT_PRE_WS`/`AT_BOTH_WS` annotation tokens fold the *leading* -/// newline into the token text (`"\n@"`), so `line()` points at the blank -/// line before the annotation. The PLOC observation advances past leading -/// newlines, so a blank line before an annotated declaration is not counted -/// as code. -#[test] -fn kotlin_blank_line_before_annotation_is_not_ploc() { - // 4 source lines: `fun a()`, blank, `@Deprecated`, `fun b()`. - let a = analyze("fun a() {}\n\n@Deprecated\nfun b() {}\n"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!(loc.ploc, 3.0, "the blank line must not count as code"); - assert_eq!(loc.blank, 1.0); -} - -/// Regression: a multiline block comment folded into the leading trivia of -/// an `AT_PRE_WS` annotation token must not mark its comment-only lines as -/// code. The PLOC trivia-skip advances past a leading block comment (and its -/// embedded newlines), so the comment lines count as CLOC, not PLOC. -#[test] -fn kotlin_block_comment_before_annotation_is_not_ploc() { - // 5 source lines: `fun a()`, `/* c1`, ` c2 */`, `@Deprecated`, `fun b()`. - let a = analyze("fun a() {}\n/* c1\n c2 */\n@Deprecated\nfun b() {}\n"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.ploc, 3.0, - "the 2 block-comment lines must not count as code" - ); - assert_eq!(loc.cloc, 2.0); -} - -/// Regression: a multi-line block comment whose *closing* row carries code -/// (`/* c\n*/ val x = 1`) must classify that closing row as a code-comment, -/// not comment-only. Otherwise the code-bearing row is double-counted as -/// comment-only and masks a genuine blank line elsewhere -/// (`blank = sloc - ploc - only_comment_lines`). -#[test] -fn kotlin_block_comment_closing_on_code_line_preserves_blank() { - // 6 lines: `fun f()`, `val a = 1`, BLANK, `/* c`, `*/ val b = 2`, `}`. - let a = analyze("fun f() {\n val a = 1\n\n /* c\n*/ val b = 2\n}\n"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!(loc.blank, 1.0, "the genuine blank line must still count"); - // ploc: `fun f`, `val a`, `*/ val b`, `}` = 4 (the comment-only `/* c` is not code). - assert_eq!(loc.ploc, 4.0); -} - -/// Regression: an annotated declaration after a blank line has its `@` token -/// lexed as `AT_PRE_WS`, whose folded leading newline would otherwise pull -/// the space's span start onto the blank line — inflating the space's `sloc` -/// and `blank`. The span start is trimmed past leading trivia. -#[test] -fn kotlin_annotated_space_span_excludes_leading_blank() { - // `fun a()`, blank, `@Deprecated`, `fun b() { println(1) }` (lines 4–6). - let a = analyze("fun a() {}\n\n@Deprecated\nfun b() {\n println(1)\n}\n"); - let b = a - .root - .spaces - .iter() - .find(|s| s.name.as_deref() == Some("b")) - .expect("function b space"); - // b spans `@Deprecated`(3) .. `}`(6) = 4 SLOC, no blank inside. - assert_eq!( - b.span.start_line, 3, - "span must start at @Deprecated, not the blank line" - ); - let loc = mehen_report::metrics_json::loc(&b.metrics); - assert_eq!(loc.sloc, 4.0); - assert_eq!(loc.blank, 0.0); -} - -/// Regression: a block comment folded into an annotation token's leading -/// trivia (`/* doc */\n@Anno fun b()`) must not be routed into the annotated -/// space's CLOC. Trimming only the span's `start_line` left `start_byte` -/// inside the folded comment, and `push_space` routes comments by byte range, -/// so the comment was attributed to `b`. The span's `start_byte` is now -/// trimmed past the trivia, so the comment counts only at file level. -#[test] -fn kotlin_block_comment_folded_into_annotation_not_routed_to_space() { - // `fun a()`, blank, `/* doc */`, `@Deprecated`, `fun b() { println(1) }`. - let a = analyze("fun a() {}\n\n/* doc */\n@Deprecated\nfun b() {\n println(1)\n}\n"); - let b = a - .root - .spaces - .iter() - .find(|s| s.name.as_deref() == Some("b")) - .expect("function b space"); - // The span starts at `@Deprecated` (line 4), past the leading comment. - assert_eq!(b.span.start_line, 4, "span must start at @Deprecated"); - let b_loc = mehen_report::metrics_json::loc(&b.metrics); - assert_eq!(b_loc.cloc, 0.0, "leading comment must not be b's CLOC"); - // The comment is still counted once, at file level. - assert_eq!(mehen_report::metrics_json::loc(&a.root.metrics).cloc, 1.0); -} - -/// Regression: the same fold on a *single line* (`/* docs */@Anno fun b()`) -/// has zero embedded newlines, so a newline-count-only trim would miss it — -/// but the comment bytes are still inside the span. The byte-based trim -/// advances `start_byte` past the comment, keeping it out of `b`'s CLOC. -#[test] -fn kotlin_same_line_comment_before_annotation_not_routed_to_space() { - // `fun a()`, blank, `/* docs */@Deprecated fun b() { println(1) }`. - let a = analyze("fun a() {}\n\n/* docs */@Deprecated fun b() {\n println(1)\n}\n"); - let b = a - .root - .spaces - .iter() - .find(|s| s.name.as_deref() == Some("b")) - .expect("function b space"); - assert_eq!( - mehen_report::metrics_json::loc(&b.metrics).cloc, - 0.0, - "same-line leading comment must not be b's CLOC" - ); - assert_eq!(mehen_report::metrics_json::loc(&a.root.metrics).cloc, 1.0); -} - -/// Analyze as a `.kts` script (the shebang is only valid in scripts, which -/// use the `script` entry rule). -fn analyze_kts(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kts".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Regression: `SHEBANG_LINE` (`#!/usr/bin/env kotlin`) is a *visible* tree -/// terminal on executable `.kts` scripts, but it is an interpreter directive, -/// not Kotlin code. It must not count as PLOC, and (since it occupies a -/// physical row) must be routed to CLOC rather than silently becoming a -/// phantom blank line. -#[test] -fn kotlin_shebang_line_is_cloc_not_ploc_or_blank() { - let a = analyze_kts("#!/usr/bin/env kotlin\nval x = 1\nprintln(x)\n"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!(loc.ploc, 2.0, "shebang must not count as code"); - assert_eq!(loc.cloc, 1.0, "shebang is comment-like trivia"); - assert_eq!(loc.blank, 0.0, "shebang must not become a phantom blank"); - // The same script without the shebang has the same code/blank profile. - let b = analyze_kts("val x = 1\nprintln(x)\n"); - let lb = mehen_report::metrics_json::loc(&b.root.metrics); - assert_eq!(loc.ploc, lb.ploc); - assert_eq!(loc.blank, lb.blank); -} - -/// Regression: the folded-leading-trivia PLOC adjustment (which advances a -/// token's code row past trivia folded into `AT_PRE_WS`/`AT_BOTH_WS` -/// annotation tokens) must apply ONLY to those annotation tokens. A raw -/// triple-quoted string whose first content line looks like a comment -/// (`// …` or `/* … */`) is literal string content, not folded trivia — its -/// LOC must be identical to a raw string whose first line is plain text. -#[test] -fn kotlin_raw_string_content_looking_like_comment_is_code() { - let comment_like = - analyze("fun f(): String {\n return \"\"\"\n// looks like comment\nreal\n\"\"\"\n}\n"); - let block_like = - analyze("fun f(): String {\n return \"\"\"\n/* block */\nreal\n\"\"\"\n}\n"); - let plain = analyze("fun f(): String {\n return \"\"\"\nplain text here\nreal\n\"\"\"\n}\n"); - let cl = mehen_report::metrics_json::loc(&comment_like.root.metrics); - let bl = mehen_report::metrics_json::loc(&block_like.root.metrics); - let pl = mehen_report::metrics_json::loc(&plain.root.metrics); - // The string content must never be classified as a comment. - assert_eq!(cl.cloc, 0.0, "`// …` inside a raw string is not a comment"); - assert_eq!( - bl.cloc, 0.0, - "`/* … */` inside a raw string is not a comment" - ); - // And the comment-looking forms must match the plain-text baseline. - assert_eq!((cl.ploc, cl.blank), (pl.ploc, pl.blank)); - assert_eq!((bl.ploc, bl.blank), (pl.ploc, pl.blank)); -} diff --git a/crates/mehen-kotlin/tests/nargs.rs b/crates/mehen-kotlin/tests/nargs.rs deleted file mode 100644 index 180bf51f..00000000 --- a/crates/mehen-kotlin/tests/nargs.rs +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NArgs tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_counts_function_constructor_and_lambda_parameters() { - let a = analyze( - "class C { - constructor(a: Int, b: Int) - } - - fun f(a: Int, b: String = \"x\", vararg xs: Int) {} - - fun g(items: List) { - items.map { item -> item + 1 } - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - assert_eq!(nargs.total_functions, 6.0); - assert_eq!(nargs.total_closures, 1.0); - assert_eq!(nargs.functions_max, 3.0); - assert_eq!(nargs.closures_max, 1.0); -} - -/// Regression: a setter's lone parameter sits directly under `setter` -/// (`set(value)`), and an anonymous function's parameters live under -/// `parametersWithOptionalType`, not `functionValueParameters`. Both must -/// be counted — they previously reported `nargs=0`. -#[test] -fn kotlin_counts_setter_and_anonymous_function_parameters() { - let a = analyze( - "class C { - var x: Int = 0 - set(value) { field = value } - } - - val h = fun(a: Int, b: Int): Int { return a + b }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - // setter `value` (1) + anonymous function `a, b` (2). - assert_eq!(nargs.total_functions, 3.0); - assert_eq!(nargs.functions_max, 2.0); -} diff --git a/crates/mehen-kotlin/tests/nom.rs b/crates/mehen-kotlin/tests/nom.rs deleted file mode 100644 index 0545cc77..00000000 --- a/crates/mehen-kotlin/tests/nom.rs +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NOM tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_init_block_is_not_counted_as_function() { - let a = analyze( - "class C { - init { - println(\"ready\") - } - }", - ); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - insta::assert_json_snapshot!( - nom, - @r###" - { - "functions": 0.0, - "closures": 0.0, - "functions_average": 0.0, - "closures_average": 0.0, - "total": 0.0, - "average": 0.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} diff --git a/crates/mehen-kotlin/tests/npa.rs b/crates/mehen-kotlin/tests/npa.rs deleted file mode 100644 index 84a0e28d..00000000 --- a/crates/mehen-kotlin/tests/npa.rs +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPA tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_npa_counts_class_properties() { - let a = analyze( - "class C { - val a: Int = 1 - private val b: Int = 2 - protected val c: Int = 3 - internal val d: Int = 4 - }", - ); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - // public: a. non-public: b, c, d. - insta::assert_json_snapshot!( - npa, - @r###" - { - "classes": 1.0, - "interfaces": 0.0, - "class_attributes": 4.0, - "interface_attributes": 0.0, - "classes_average": 0.25, - "interfaces_average": null, - "total": 1.0, - "total_attributes": 4.0, - "average": 0.25 - }"### - ); -} - -#[test] -fn kotlin_npa_counts_constructor_properties() { - // Constructor parameters with `val`/`var` are class attributes. - // Plain parameters (no val/var) are NOT attributes. - let a = analyze( - "class C(val a: Int, private var b: String, internal val c: Long, d: Double) { - protected val e: Int = 0 - }", - ); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!( - npa, - @r###" - { - "classes": 1.0, - "interfaces": 0.0, - "class_attributes": 4.0, - "interface_attributes": 0.0, - "classes_average": 0.25, - "interfaces_average": null, - "total": 1.0, - "total_attributes": 4.0, - "average": 0.25 - }"### - ); -} - -#[test] -fn kotlin_npa_routes_interface_properties_to_interface_counters() { - // Same class-vs-interface routing concern as NPM: tree-sitter-kotlin - // uses `class_declaration` for both classes and interfaces, so the - // container must be decided by the declaration's leading keyword. - let a = analyze( - "interface Foo { - val a: Int - val b: Int - } - - class Bar { - val c: Int = 1 - private val d: Int = 2 - }", - ); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!( - npa, - @r###" - { - "classes": 1.0, - "interfaces": 2.0, - "class_attributes": 2.0, - "interface_attributes": 2.0, - "classes_average": 0.5, - "interfaces_average": 1.0, - "total": 3.0, - "total_attributes": 4.0, - "average": 0.75 - }"### - ); -} diff --git a/crates/mehen-kotlin/tests/npm.rs b/crates/mehen-kotlin/tests/npm.rs deleted file mode 100644 index 0f1d19bc..00000000 --- a/crates/mehen-kotlin/tests/npm.rs +++ /dev/null @@ -1,259 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPM tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_npm_counts_visibility_modifiers() { - let a = analyze( - "class C { - fun a() {} - public fun b() {} - private fun c() {} - protected fun d() {} - internal fun e() {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - // public: a, b. non-public: c, d, e. - insta::assert_json_snapshot!( - npm, - @r#" - { - "classes": 2.0, - "interfaces": 0.0, - "class_methods": 5.0, - "interface_methods": 0.0, - "classes_average": 0.4, - "interfaces_average": null, - "total": 2.0, - "total_methods": 5.0, - "average": 0.4 - } - "# - ); -} - -#[test] -fn kotlin_npm_routes_interface_methods_to_interface_counters() { - // tree-sitter-kotlin parses `class` and `interface` into the same - // `class_declaration` node; only the leading keyword child - // distinguishes them. Interface methods must land in the - // interface_methods / interfaces counters, not class_methods / - // classes. - let a = analyze( - "interface Foo { - fun a() - fun b(): Int - } - - class Bar { - fun c() {} - fun d() {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!( - npm, - @r#" - { - "classes": 2.0, - "interfaces": 2.0, - "class_methods": 2.0, - "interface_methods": 2.0, - "classes_average": 1.0, - "interfaces_average": 1.0, - "total": 4.0, - "total_methods": 4.0, - "average": 1.0 - } - "# - ); -} - -#[test] -fn kotlin_npm_counts_secondary_constructors() { - let a = analyze( - "class C { - constructor() - private constructor(x: Int) - internal constructor(y: String) - fun visible() {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - // public: default-visible constructor and visible(). - // non-public: private/internal secondary constructors. - insta::assert_json_snapshot!( - npm, - @r#" - { - "classes": 2.0, - "interfaces": 0.0, - "class_methods": 4.0, - "interface_methods": 0.0, - "classes_average": 0.5, - "interfaces_average": null, - "total": 2.0, - "total_methods": 4.0, - "average": 0.5 - } - "# - ); -} - -#[test] -fn kotlin_npm_counts_property_accessors() { - let a = analyze( - "class C { - var x: Int = 0 - get() = field - private set(value) { field = value } - - private var hidden: Int = 0 - get() = field - set(value) { field = value } - } - - interface I { - val y: Int - get() = 1 - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - // class C -> public getter + private setter, plus two private - // accessors inheriting from private property visibility. - // interface I -> public getter. - insta::assert_json_snapshot!( - npm, - @r#" - { - "classes": 1.0, - "interfaces": 1.0, - "class_methods": 4.0, - "interface_methods": 1.0, - "classes_average": 0.25, - "interfaces_average": 1.0, - "total": 2.0, - "total_methods": 5.0, - "average": 0.4 - } - "# - ); -} - -/// Regression: a method in an enum constant's anonymous body -/// (`A { fun local() {} }`) belongs to that anonymous subclass, not the -/// enum — no space is opened for the entry, so it must not be counted as a -/// method of the enclosing enum. Only the enum's own `shared` counts. -#[test] -fn kotlin_npm_excludes_enum_entry_body_members() { - let a = analyze( - "enum class E { - A { - fun local() {} - }; - - fun shared() {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - assert_eq!( - npm.class_methods, 1.0, - "only the enum's own `shared` counts" - ); - assert_eq!(npm.total_methods, 1.0); -} - -/// Regression: a *real* nested class inside an enum-entry body must still -/// own its members. The `in_enum_entry` suppression (which keeps the entry's -/// own direct members off the enum) is cleared once a real class-like space -/// opens, so `class Inner { fun m() {} }` inside entry `A` counts `m` on -/// `Inner` — while the entry's direct `fun direct` does not count on the enum. -#[test] -fn kotlin_npm_counts_real_nested_class_inside_enum_entry() { - let a = analyze( - "enum class E { - A { - class Inner { fun m() {} } - fun direct() {} - }; - - fun shared() {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - // `Inner.m` (on the nested class) + `E.shared` (on the enum) = 2. - // `E.direct` (the entry's own method) is NOT attributed to the enum. - assert_eq!(npm.total_methods, 2.0); -} - -/// Regression: an object literal (`object { … }`) is an anonymous class -/// whose body opens no metric space, so its members must not be attributed -/// to the lexically-enclosing class. Only `C.outer` counts on `C`; the -/// object literal's `inner` does not. -#[test] -fn kotlin_npm_excludes_object_literal_body_members() { - let a = analyze( - "class C { - fun outer() {} - val o = object { - fun inner() {} - } - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - assert_eq!(npm.class_methods, 1.0, "only `C.outer` counts"); - assert_eq!(npm.total_methods, 1.0); -} - -/// Regression: a property accessor (`get`/`set`) inside an anonymous object -/// literal in a class property's initializer belongs to that anonymous -/// subclass, not the enclosing class. The accessor owner is threaded via -/// `property_visibility` (separate from the `in_class_member` gate that -/// suppresses ordinary members), so without clearing it inside an anonymous -/// body the inner getter was recorded on the enclosing class's NPM. -#[test] -fn kotlin_npm_excludes_object_literal_accessor() { - let a = analyze( - "class C { - val o = object { - val p: Int = 0 - get() = field - } - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - assert_eq!( - npm.class_methods, 0.0, - "the object-literal's getter must not count on C" - ); - assert_eq!(npm.total_methods, 0.0); -} - -/// Sanity counterpart to the above: a *real* class-body property accessor -/// must still be counted as a class method. (Guards against the -/// anonymous-body fix over-suppressing genuine accessors.) -#[test] -fn kotlin_npm_counts_real_class_body_accessor() { - let a = analyze( - "class C { - val p: Int = 0 - get() = field - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - assert_eq!(npm.class_methods, 1.0, "C's own getter counts"); - assert_eq!(npm.total_methods, 1.0); -} diff --git a/crates/mehen-kotlin/tests/snapshots/loc__kotlin_simple_loc.snap b/crates/mehen-kotlin/tests/snapshots/loc__kotlin_simple_loc.snap deleted file mode 100644 index 2ee60f71..00000000 --- a/crates/mehen-kotlin/tests/snapshots/loc__kotlin_simple_loc.snap +++ /dev/null @@ -1,27 +0,0 @@ ---- -source: crates/mehen-kotlin/tests/loc.rs -assertion_line: 27 -expression: loc ---- -{ - "sloc": 4.0, - "ploc": 3.0, - "lloc": 2.0, - "cloc": 1.0, - "blank": 0.0, - "sloc_average": 2.0, - "ploc_average": 1.5, - "lloc_average": 1.0, - "cloc_average": 0.5, - "blank_average": 0.0, - "sloc_min": 3.0, - "sloc_max": 3.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 3.0, - "ploc_max": 3.0, - "lloc_min": 2.0, - "lloc_max": 2.0, - "blank_min": 0.0, - "blank_max": 0.0 -} diff --git a/crates/mehen-kotlin/tests/wmc.rs b/crates/mehen-kotlin/tests/wmc.rs deleted file mode 100644 index 4cd31bbe..00000000 --- a/crates/mehen-kotlin/tests/wmc.rs +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! WMC tests for the tree-sitter-kotlin walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_kotlin::KotlinAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = KotlinAnalyzer::new(); - let file = SourceFile::new("foo.kt".into(), Language::Kotlin, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn kotlin_wmc_class_sums_method_cyclomatics() { - let a = analyze( - "class C { - fun a(x: Int): Int { - return if (x > 0) 1 else 0 - } - fun b(): Int { return 1 } - }", - ); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - // class C -> a cyc = 2 (if), b cyc = 1 -> 3 - insta::assert_json_snapshot!( - wmc, - @r###" - { - "classes": 3.0, - "interfaces": 0.0, - "total": 3.0 - }"### - ); -} - -/// Regression: a function inside an enum constant's anonymous body must not -/// roll into the enum's WMC. The entry body opens no space, so `local` -/// closes with the enum as parent — but it belongs to the entry's anonymous -/// subclass, so its cyclomatic is excluded from the enum's WMC. Only the -/// enum's own `shared` (cyclomatic 1) contributes. -#[test] -fn kotlin_wmc_excludes_enum_entry_body_functions() { - let a = analyze( - "enum class E { - A { - fun local(x: Int): Int { return if (x > 0) 1 else 2 } - }; - - fun shared() {} - }", - ); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - // Only `E.shared` (cyclomatic 1) — `A.local` (cyclomatic 2) is excluded. - assert_eq!(wmc.total, 1.0); -} diff --git a/crates/mehen-markdown/Cargo.toml b/crates/mehen-markdown/Cargo.toml deleted file mode 100644 index 5875d248..00000000 --- a/crates/mehen-markdown/Cargo.toml +++ /dev/null @@ -1,43 +0,0 @@ -[package] -name = "mehen-markdown" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — Markdown documentation metrics analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -# `regex`, `unicode-script`, and `unicode-segmentation` are pinned here -# (not in `[workspace.dependencies]`) because `mehen-markdown` is the -# only consumer — they back the prose-quality metric heuristics -# (sentence segmentation, script detection, identifier matching). -regex = "^1.7" -unicode-script = "^0.5" -unicode-segmentation = "^1.13" -serde = { workspace = true } -# `pulldown-cmark` is the Markdown parser backend. Default features are -# disabled because the analyzer consumes parser events and byte offsets -# directly; it never renders HTML. -pulldown-cmark = { version = "=0.13.4", default-features = false } - -[dev-dependencies] -# Tests rely on `mehen-engine`'s `init_markdown` to register the -# embedded-code fence dispatch (the legacy pre-1.0 metric analyzer -# for Rust/Python/etc., now living under -# `mehen_engine::legacy::*`). Phase-6+ replaces this with the -# rewrite-plan §4.7 `LanguageDispatcher` once per-language analyzers -# reach parity. -mehen-engine = { workspace = true } - -camino = { workspace = true } -insta = { workspace = true } -pretty_assertions = { workspace = true } -serde_json = { workspace = true } -tempfile = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-markdown/src/analyzer.rs b/crates/mehen-markdown/src/analyzer.rs deleted file mode 100644 index 62190bdd..00000000 --- a/crates/mehen-markdown/src/analyzer.rs +++ /dev/null @@ -1,457 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Top-level Markdown analysis entry point. -//! -//! Parses a Markdown source buffer with pulldown-cmark and produces a -//! [`MarkdownMetrics`] record covering: -//! -//! - §5 LOC family, -//! - §4 word count `W`, -//! - §3.4 section tree, -//! - §6 Effective Content Units, -//! - §7 Markdown Reading Path Complexity (weighted + raw), -//! - §8 Markdown Cognitive Complexity, -//! - §9 Markdown Halstead + §9.4 embedded-code adjustment, -//! - §10 Documentation Maintainability Index (full formula — all terms), -//! - §11 link classification + debt + scent + review burden, -//! - §12 visuals (images + diagrams), -//! - §13 tables, -//! - §14.1 per-code-fence burden (stored in `artifacts`), -//! - §14.3 per-math-block burden (stored in `artifacts`), -//! - §15 Repository Grounding Score, -//! - §16 Evidence Coverage Score, -//! - §17 Filler / Lazy Structure Risk + diagnostic labels, -//! - §18 Review Criticality Index, -//! - §19 artifact debt score, -//! - §20 Section Balance Score, -//! - §21 Good Scaffold Score, -//! - §§29–38 language-aware prose layer. -//! -//! The prose layer is kept strictly separate per §29.1 — it never modifies -//! any structural score. -//! -//! Pipeline order: Phase A (LOC, sections, words, ECU) → Phase B (MRPC, -//! MCC, Halstead) → Phase C (links, visuals, tables, artifacts, artifact -//! debt) → Phase D (section balance, grounding, filler, good scaffold, -//! DMI, RCI) → Phase E (prose). Phase C feeds real diagram node/edge -//! counts back into ECU so §6 does not stay at zero. - -use std::path::Path; - -use crate::artifact_debt::{DebtInputs, artifact_debt_score}; -use crate::code_burden::{CodeFence, analyze_code_fences}; -use crate::dmi::{DmiInputs, compute_dmi}; -use crate::ecu::{compute_ecu_inputs, effective_content_units}; -use crate::embedded_code::embedded_volume; -use crate::filler::analyze_filler; -use crate::good_scaffold::analyze_good_scaffold; -use crate::grounding::analyze_grounding; -use crate::halstead::compute_halstead; -use crate::links::analyze_links; -use crate::loc::{LineClasses, derive_ratios, physical_line_count}; -use crate::math_burden::{MathBlock, analyze_math_blocks}; -use crate::mcc::compute_mcc; -use crate::mrpc::compute_mrpc; -use crate::nearby::{BlockSpan, collect_blocks, has_prose_within}; -use crate::prose::analyze_prose; -use crate::rci::{RciInputs, compute_rci}; -use crate::section_balance::analyze_section_balance; -use crate::sections::collect_sections; -use crate::syntax_tree::{Node, parse_with_document}; -use crate::tables::{aggregate_tables, analyze_tables}; -use crate::types::{ - AiEra, ArtifactKind, ArtifactRecord, Complexity, DiagramRecord, Grounding, ImageRecord, - Maintainability, MarkdownMetrics, Review, Size, TableRecord, -}; -use crate::visuals::analyze_visuals; -use crate::words::count_words; - -/// Parses `source` as Markdown and returns a metric record covering Phase A, -/// Phase B, Phase C, and Phase E. `path` is recorded verbatim into the -/// output's `path` field; the caller controls whether it is absolute or -/// relative. -pub fn analyze_markdown(source: &str, path: &Path) -> MarkdownMetrics { - let mut evidence = mehen_core::ContributionCollector::new(false); - analyze_markdown_with_evidence(source, path, &mut evidence) -} - -/// As [`analyze_markdown`], additionally recording contribution evidence -/// (plan §5.4) into `evidence`: every MCC adjustment (element charges and -/// scaled scaffold credits) with the exact amounts applied. Crate-internal — -/// the registry-driven `LanguageAnalyzer::analyze` path uses this; -/// `analyze_markdown` keeps its original public signature for existing -/// fixtures and callers. -pub(crate) fn analyze_markdown_with_evidence( - source: &str, - path: &Path, - evidence: &mut mehen_core::ContributionCollector, -) -> MarkdownMetrics { - let (tree, document) = parse_with_document(source); - let root = tree.root(); - - // Phase A: LOC family, ratios, size, sections, ECU inputs. - let total_lines = physical_line_count(source); - let classes = LineClasses::build(&root, total_lines); - let loc = classes.loc_family(); - let loc_ratios = derive_ratios(&loc); - - let words = count_words(&root); - let sections = collect_sections(&root); - // §3.4: the derived section tree has one section per heading. No - // synthetic root is exported, so `sections.len()` is the heading count. - let heading_sections = sections.len() as u64; - let headings = heading_sections; - - let ecu_inputs = compute_ecu_inputs(&root, &classes); - let ecu = effective_content_units(&loc, words, &ecu_inputs); - - // Phase B: complexity surface (MRPC, MCC, Halstead). DMI is deferred - // until Phase D has computed its inputs. - let mrpc = compute_mrpc(&root, &document, source); - let mcc = compute_mcc(&root, &document, source, evidence); - let mut halstead = compute_halstead(&root, &document, source); - let emb = embedded_volume(&document); - halstead.embedded_volume = emb; - halstead.total_volume = halstead.volume + emb; - - // Phase C: block index for nearby-prose queries. - let blocks: Vec = collect_blocks(&root); - - // Phase C: links. - // TODO(link-check): the `resolved = None` external links become a CLI - // flag so `--link-check` probes external URLs. For now they stay - // unchecked to keep analysis offline and deterministic. - let (link_records, link_agg) = analyze_links(&document, path, §ions, &[]); - - // Phase C: visuals (images + diagrams). - let visual_analysis = analyze_visuals(&root, &document, source, path, words, &blocks); - - // Phase C: tables. Patch has_local_explanation afterwards via the - // nearby-block index. - let mut table_records = analyze_tables(&root, source); - for t in &mut table_records { - t.has_local_explanation = has_prose_within(&blocks, t.start_line, t.end_line, 2); - // Recompute scaffold now that the explanation flag is known. The - // per-table formula is a product of size_credit × has_header × - // has_local_explanation. - if !t.has_local_explanation { - t.scaffold = 0.0; - } - } - let tables_agg = aggregate_tables(&table_records); - - // Phase C: code fences (skipping diagram-tagged fences which are owned - // by visuals.rs). - let code_fences: Vec = analyze_code_fences(&document, &blocks); - - // Phase C: math blocks. - let math_blocks: Vec = analyze_math_blocks(&root, source, &blocks); - - // Diagram ECU contribution: feed diagram_nodes / diagram_edges now that - // we have real counts. This fixes up §6 ECU without changing existing - // code in `ecu.rs` (Phase A leaves zeros). - let mut ecu_inputs_final = ecu_inputs.clone(); - ecu_inputs_final.diagram_nodes = visual_analysis.diagrams.iter().map(|d| d.nodes).sum(); - ecu_inputs_final.diagram_edges = visual_analysis.diagrams.iter().map(|d| d.edges).sum(); - let ecu_final = if ecu_inputs_final.diagram_nodes > 0 || ecu_inputs_final.diagram_edges > 0 { - effective_content_units(&loc, words, &ecu_inputs_final) - } else { - ecu - }; - - // Phase C: unified artifact list — used by §19 and later by Phase D. - let html_records = collect_html_blocks(&root); - let artifacts = build_artifact_list( - &code_fences, - &table_records, - &visual_analysis.diagrams, - &visual_analysis.images, - &math_blocks, - &html_records, - &blocks, - ); - - // Phase C: artifact debt score. - let debt_inputs = DebtInputs { - artifacts: &artifacts, - links: &link_records, - loc: &loc, - raw_html_or_mdx_lines: ecu_inputs_final.raw_html_or_mdx_lines, - diagram_parse_errors: visual_analysis - .diagrams - .iter() - .filter(|d| d.parse_error) - .count() as u64, - }; - let artifact_debt = artifact_debt_score(&debt_inputs); - - // Phase D: section balance (§20). - let section_balance = analyze_section_balance(§ions, words); - - // Phase D: grounding (§15) + evidence coverage (§16). - let grounding = analyze_grounding( - &root, - source, - path, - words, - §ions, - &link_records, - &artifacts, - &table_records, - ); - - // Phase D: filler / lazy risk (§17). - let filler = analyze_filler( - &root, - source, - words, - §ions, - &artifacts, - &link_records, - &loc, - &grounding, - §ion_balance, - ); - - // Phase D: good scaffold (§21). - let good_scaffold = analyze_good_scaffold( - &artifacts, - &link_records, - &link_agg, - &visual_analysis.aggregate, - &tables_agg, - ); - - // Phase D: DMI now that every §10 term is populated. - let dmi = compute_dmi(DmiInputs { - mrpc: mrpc.weighted, - mcc: mcc.mcc, - total_volume: halstead.total_volume, - link_debt_score: link_agg.link_debt_score, - table_burden_score: tables_agg.table_burden_score, - artifact_debt_score: artifact_debt, - section_imbalance: 1.0 - section_balance.section_balance_score, - filler_lazy_risk: filler.filler_lazy_risk, - good_scaffold_score: good_scaffold.good_scaffold_score, - }); - - // Phase D: RCI (§18). `metric_delta_percent` + `changed_links_or_artifacts` - // default to 0 — those are `mehen diff` inputs (Phase F). - let rci = compute_rci(RciInputs { - mcc: mcc.mcc, - words, - mdh_volume_total: halstead.total_volume, - repository_grounding_score: grounding.repository_grounding_score, - evidence_coverage_score: grounding.evidence_coverage_score, - link_review_burden: link_agg.review_burden, - embedded_code_complexity: halstead.embedded_volume, - metric_delta_percent: 0.0, - changed_links_or_artifacts: 0, - }); - - // §§29–38 Prose layer. Kept strictly separate per §29.1 — it never - // modifies any structural score. - let prose = analyze_prose(&root, source.as_bytes()); - - MarkdownMetrics { - path: path.to_string_lossy().to_string(), - loc, - loc_ratios, - size: Size { - words, - effective_content_units: ecu_final, - sections: heading_sections, - headings, - }, - ecu_inputs: ecu_inputs_final, - sections, - complexity: Complexity { - reading_path_complexity: mrpc.weighted, - reading_path_complexity_raw: mrpc.raw, - cognitive_complexity: mcc.mcc, - halstead, - }, - links: link_agg, - link_records, - visuals: visual_analysis.aggregate, - tables: tables_agg, - maintainability: Maintainability { - documentation_maintainability_index: dmi, - section_balance_score: section_balance.section_balance_score, - good_scaffold_score: good_scaffold.good_scaffold_score, - artifact_debt_score: artifact_debt, - }, - grounding: Grounding { - repository_grounding_score: grounding.repository_grounding_score, - evidence_coverage_score: grounding.evidence_coverage_score, - }, - ai_era: AiEra { - filler_lazy_structure_risk: filler.filler_lazy_risk, - labels: filler.labels, - top_contributors: filler.top_contributors, - }, - review: Review { - review_criticality_index: rci.review_criticality_index, - }, - artifacts, - prose, - } -} - -#[derive(Debug, Clone)] -struct HtmlBlockRecord { - start_line: u64, - end_line: u64, -} - -fn collect_html_blocks(root: &Node<'_>) -> Vec { - let mut out: Vec = Vec::new(); - walk_html(root, &mut out); - out.sort_by_key(|a| a.start_line); - out -} - -fn walk_html(node: &Node<'_>, out: &mut Vec) { - use crate::kind::NodeKind::*; - let kind = node.kind(); - if matches!(kind, HtmlBlock) { - let start_line = (node.start_row() as u64) + 1; - let (end_row, end_col) = node.end_position(); - let mut end = end_row; - if end > node.start_row() && end_col == 0 { - end -= 1; - } - let end_line = (end as u64) + 1; - out.push(HtmlBlockRecord { - start_line, - end_line, - }); - return; - } - for child in node.children() { - walk_html(&child, out); - } -} - -#[allow(clippy::too_many_arguments)] -fn build_artifact_list( - code: &[CodeFence], - tables: &[TableRecord], - diagrams: &[DiagramRecord], - images: &[ImageRecord], - math: &[MathBlock], - html: &[HtmlBlockRecord], - blocks: &[BlockSpan], -) -> Vec { - let mut out: Vec = Vec::new(); - - for c in code { - let oversized = c.loc > 120; - out.push(ArtifactRecord { - id: 0, - kind: ArtifactKind::Code, - start_line: c.start_line, - end_line: c.end_line, - language_tag: c.language.clone(), - size: c.loc, - has_explanation: c.has_nearby_prose, - has_label: c.has_language_tag, - oversized, - burden: c.burden, - }); - } - - for t in tables { - let oversized = t.cells > 300; - out.push(ArtifactRecord { - id: 0, - kind: ArtifactKind::Table, - start_line: t.start_line, - end_line: t.end_line, - language_tag: None, - size: t.cells, - has_explanation: t.has_local_explanation, - has_label: t.has_header, - oversized, - burden: t.burden, - }); - } - - for d in diagrams { - let oversized = d.nodes > 80; - out.push(ArtifactRecord { - id: 0, - kind: ArtifactKind::Diagram, - start_line: d.start_line, - end_line: d.end_line, - language_tag: Some(d.language.clone()), - size: d.nodes, - has_explanation: d.has_title_or_caption, - has_label: d.has_title_or_caption, - oversized, - burden: d.complexity, - }); - } - - for img in images { - out.push(ArtifactRecord { - id: 0, - kind: ArtifactKind::Image, - start_line: img.line, - end_line: img.line, - language_tag: None, - size: 1, - has_explanation: img.has_nearby_reference, - has_label: img.has_alt_or_caption, - oversized: false, - burden: img.image_complexity, - }); - } - - for m in math { - let oversized = m.tokens > 50; - out.push(ArtifactRecord { - id: 0, - kind: ArtifactKind::Math, - start_line: m.start_line, - end_line: m.end_line, - language_tag: None, - size: m.tokens, - has_explanation: m.has_nearby_prose, - has_label: false, - oversized, - burden: m.burden, - }); - } - - for h in html { - let size = h.end_line.saturating_sub(h.start_line) + 1; - let has_explanation = has_prose_within(blocks, h.start_line, h.end_line, 2); - out.push(ArtifactRecord { - id: 0, - kind: ArtifactKind::Html, - start_line: h.start_line, - end_line: h.end_line, - language_tag: None, - size, - has_explanation, - has_label: false, - oversized: false, - burden: size as f64, - }); - } - - // Sort: start_line, then kind (lexicographic) for determinism, then - // assign sequential ids. - out.sort_by(|a, b| { - a.start_line - .cmp(&b.start_line) - .then((a.kind as u8).cmp(&(b.kind as u8))) - .then(a.end_line.cmp(&b.end_line)) - }); - for (i, rec) in out.iter_mut().enumerate() { - rec.id = i as u64; - } - out -} diff --git a/crates/mehen-markdown/src/artifact_debt.rs b/crates/mehen-markdown/src/artifact_debt.rs deleted file mode 100644 index 3927efc3..00000000 --- a/crates/mehen-markdown/src/artifact_debt.rs +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Artifact Debt Score per §19. -//! -//! ```text -//! ArtifactDebtScore = clamp01( -//! 0.25 * sat(unlabelled_code_fences / max(1, code_fences); 0.05, 0.50) -//! + 0.20 * sat(artifact_parse_errors / max(1, artifacts); 0.00, 0.20) -//! + 0.15 * sat(oversized_artifacts / max(1, artifacts); 0.05, 0.30) -//! + 0.15 * sat(unexplained_artifacts / max(1, artifacts); 0.10, 0.60) -//! + 0.15 * sat(raw_html_or_mdx_lines / max(1, DLOC); 0.05, 0.25) -//! + 0.10 * sat(external_artifact_links / max(1, artifacts); 0.10, 0.60) -//! ) -//! ``` - -use crate::mathops::{clamp01, sat}; -use crate::types::{ArtifactKind, ArtifactRecord, LinkClass, LinkRecord, LocFamily}; - -/// Inputs the score needs beyond what's embedded in `ArtifactRecord`. -pub(crate) struct DebtInputs<'a> { - pub(crate) artifacts: &'a [ArtifactRecord], - pub(crate) links: &'a [LinkRecord], - pub(crate) loc: &'a LocFamily, - pub(crate) raw_html_or_mdx_lines: u64, - pub(crate) diagram_parse_errors: u64, -} - -pub(crate) fn artifact_debt_score(inputs: &DebtInputs<'_>) -> f64 { - let artifacts = inputs.artifacts; - // §19 is a per-artifact metric. A prose-only document with no - // artifacts has zero artifact debt by definition — counting stray - // prose external links as "artifact debt" creates false positives - // on snippet-free markdown (Codex P1 on PR #84). The only §19 - // component that is not strictly artifact-bound is - // `raw_html_or_mdx_lines / DLOC`; we keep that contribution so - // raw-HTML-heavy prose still produces debt, but every per-artifact - // ratio resolves to 0 when `artifacts.is_empty()`. - if artifacts.is_empty() { - let raw_html_lines = inputs.raw_html_or_mdx_lines as f64; - let dloc = inputs.loc.dloc.max(1) as f64; - return clamp01(0.15 * sat(raw_html_lines / dloc, 0.05, 0.25)); - } - - let total_artifacts = artifacts.len() as f64; - - let code_fences = artifacts - .iter() - .filter(|a| a.kind == ArtifactKind::Code) - .count() as f64; - let unlabelled = artifacts - .iter() - .filter(|a| a.kind == ArtifactKind::Code && a.language_tag.is_none()) - .count() as f64; - - let oversized = artifacts.iter().filter(|a| a.oversized).count() as f64; - let unexplained = artifacts.iter().filter(|a| !a.has_explanation).count() as f64; - - // §19: artifact_parse_errors currently = diagram parse errors. If - // Phase B wires code-fence parser errors these would be added here. - let parse_errors = inputs.diagram_parse_errors as f64; - let raw_html_lines = inputs.raw_html_or_mdx_lines as f64; - let dloc = inputs.loc.dloc.max(1) as f64; - - // External artifact links = links pointed at from inside an artifact. - // As a conservative approximation we use the count of External / - // ExternalVendor / Scholarly / IssuePR link destinations document-wide. - // The proper "inside artifact" restriction needs per-link artifact - // attribution which is Phase D territory. - let external_artifact_links = inputs - .links - .iter() - .filter(|l| { - matches!( - l.class, - LinkClass::External - | LinkClass::ExternalVendor - | LinkClass::Scholarly - | LinkClass::IssuePr - ) - }) - .count() as f64; - - let score = 0.25 * sat(unlabelled / code_fences.max(1.0), 0.05, 0.50) - + 0.20 * sat(parse_errors / total_artifacts, 0.00, 0.20) - + 0.15 * sat(oversized / total_artifacts, 0.05, 0.30) - + 0.15 * sat(unexplained / total_artifacts, 0.10, 0.60) - + 0.15 * sat(raw_html_lines / dloc, 0.05, 0.25) - + 0.10 * sat(external_artifact_links / total_artifacts, 0.10, 0.60); - - clamp01(score) -} diff --git a/crates/mehen-markdown/src/code_burden.rs b/crates/mehen-markdown/src/code_burden.rs deleted file mode 100644 index 15bbeb85..00000000 --- a/crates/mehen-markdown/src/code_burden.rs +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Per-fence code burden per §14.1. -//! -//! For each fenced code block, we compute: -//! -//! ```text -//! CodeFenceBurden(c) = -//! 1.0 -//! + 0.08 * max(0, LOC_c - 12) -//! + 0.50 * sat(LOC_c; 40, 120) -//! + 0.40 * sat(line_length_p95_c; 100, 180) -//! + 1.50 * missing_language_tag -//! + 0.00 * parser_error_if_language_supported // Phase B wires this -//! + 0.20 * code_cognitive_c // Phase B wires this -//! + 0.05 * sqrt(code_halstead_volume_c) // Phase B wires this -//! ``` -//! -//! Phase C ships the shape-only terms (LOC, line length, missing tag). The -//! parser-error / cognitive / halstead terms stay zero until Phase B lands. - -use crate::document::{CodeBlock, MarkdownDocument, is_diagram_language}; -use crate::mathops::sat; -use crate::nearby::{BlockSpan, has_prose_within}; - -/// Per-fence summary used to populate ArtifactRecord rows and Phase D's -/// filler / grounding pipelines. -#[derive(Debug, Clone)] -pub(crate) struct CodeFence { - pub(crate) start_line: u64, - pub(crate) end_line: u64, - pub(crate) language: Option, - pub(crate) loc: u64, - pub(crate) has_language_tag: bool, - pub(crate) has_nearby_prose: bool, - pub(crate) burden: f64, -} - -/// Records every fenced code block and skips diagram -/// fences (they are owned by `visuals.rs`). Returns a deterministic list -/// sorted by start_line. -pub(crate) fn analyze_code_fences( - document: &MarkdownDocument, - blocks: &[BlockSpan], -) -> Vec { - let mut out = document - .code_blocks - .iter() - .filter_map(|block| build(block, blocks)) - .collect::>(); - // Sort for determinism. - out.sort_by_key(|a| a.start_line); - out -} - -fn build(block: &CodeBlock, blocks: &[BlockSpan]) -> Option { - if !block.is_fenced() { - return None; - } - - // Diagrams are handled in `visuals.rs`; skip them here so the burden - // score isn't counted twice. We still leave the record in the artifact - // list (see `analyzer.rs`), but filter at the §14.1 site. - if let Some(lang) = block.language.as_deref() - && is_diagram_language(lang) - { - return None; - } - - // Body LOC excludes fence delimiters because the document fact stores - // only the pulldown code-block text. - let (body_loc, line_len_p95) = code_body_stats(&block.content); - - let has_nearby_prose = has_prose_within(blocks, block.start_line, block.end_line, 2); - - let has_language_tag = block.language.is_some(); - let missing_language_tag = if has_language_tag { 0.0 } else { 1.0 }; - let burden = 1.0 - + 0.08 * (body_loc as f64 - 12.0).max(0.0) - + 0.50 * sat(body_loc as f64, 40.0, 120.0) - + 0.40 * sat(line_len_p95, 100.0, 180.0) - + 1.50 * missing_language_tag; - - Some(CodeFence { - start_line: block.start_line, - end_line: block.end_line, - language: block.language.clone(), - loc: body_loc, - has_language_tag, - has_nearby_prose, - burden, - }) -} - -fn code_body_stats(body: &str) -> (u64, f64) { - let mut line_lengths: Vec = Vec::new(); - for line in body.lines() { - line_lengths.push(line.chars().count()); - } - let loc = line_lengths.len() as u64; - if line_lengths.is_empty() { - return (loc, 0.0); - } - // p95 = length at index ceil(0.95 * N) - 1. - line_lengths.sort_unstable(); - let idx = ((0.95 * line_lengths.len() as f64).ceil() as usize) - .saturating_sub(1) - .min(line_lengths.len() - 1); - (loc, line_lengths[idx] as f64) -} - -#[cfg(test)] -mod tests { - use crate::document::parse_document; - - use super::analyze_code_fences; - - #[test] - fn fenced_code_burden_uses_pulldown_body_without_delimiters() { - let document = - parse_document("# T\n\nIntro.\n\n```Rust,no_run {#sample}\nfn main() {}\n```\n"); - - let fences = analyze_code_fences(&document, &[]); - - assert_eq!(fences.len(), 1); - assert_eq!(fences[0].start_line, 5); - assert_eq!(fences[0].end_line, 7); - assert_eq!(fences[0].language.as_deref(), Some("rust")); - assert_eq!(fences[0].loc, 1); - assert!(fences[0].has_language_tag); - } - - #[test] - fn diagram_fences_are_owned_by_visuals() { - let document = parse_document("```mermaid\ngraph TD\n A --> B\n```\n"); - - let fences = analyze_code_fences(&document, &[]); - - assert!(fences.is_empty()); - } -} diff --git a/crates/mehen-markdown/src/data/abbreviations_en.txt b/crates/mehen-markdown/src/data/abbreviations_en.txt deleted file mode 100644 index ec728cc5..00000000 --- a/crates/mehen-markdown/src/data/abbreviations_en.txt +++ /dev/null @@ -1,178 +0,0 @@ -# English abbreviations. Lines starting with `#` or blank are ignored. -# Each entry is matched case-sensitively against the token immediately -# preceding a period. When matched, the period does NOT open a sentence. -# Source: synthesized from write-good, proselint, and retext-smartypants lists. -Mr -Mrs -Ms -Dr -Prof -Sr -Jr -St -Mt -Mts -Rd -Ave -Blvd -Ln -Sq -Co -Corp -Inc -Ltd -Bros -Cie -Cia -Hon -Rev -Capt -Lt -Col -Gen -Maj -Sgt -Cpl -Pvt -Cmdr -Adm -Gov -Sen -Rep -Pres -Supt -Asst -U.S -U.K -U.N -N.Y -L.A -D.C -P.O -P.S -R.S.V.P -A.D -B.C -B.C.E -C.E -A.M -P.M -a.m -p.m -No -Nos -Vol -Vols -Ed -Eds -pp -p -Ch -ch -Sec -sec -Fig -fig -Figs -figs -Eq -Ver -ver -Rev -rev -vs -v -cf -e.g -E.g -i.e -I.e -etc -viz -approx -ca -c -et al -al -op -loc -ibid -q.v -n.b -N.B -ff -n -Fr -Pkwy -Pkg -Ste -Apt -Bldg -Dept -Univ -Assn -Soc -Inst -Jan -Feb -Mar -Apr -Jun -Jul -Aug -Sep -Sept -Oct -Nov -Dec -Mon -Tue -Tues -Wed -Thu -Thur -Thurs -Fri -Sat -Sun -oz -lb -lbs -ft -yd -yds -mi -km -cm -mm -ml -dl -kg -mg -hr -hrs -min -mins -sec -secs -mo -mos -yr -yrs -vol -vols -w -w.r.t -i.e -e.g -i.e -i.e., -e.g., -Ph.D -M.D -M.A -B.A -B.S -M.S -M.B.A -J.D diff --git a/crates/mehen-markdown/src/data/cliches.txt b/crates/mehen-markdown/src/data/cliches.txt deleted file mode 100644 index a82fa5f0..00000000 --- a/crates/mehen-markdown/src/data/cliches.txt +++ /dev/null @@ -1,555 +0,0 @@ -# Clichés — tired phrases to avoid. -# Source: words/no-cliches (https://github.com/words/no-cliches) — MIT. -# Bundled list is a representative subset; the full list is too long to bundle -# without bloating the binary. Covers the most common ~250 entries. -# Format: one lowercase phrase per line. -a chip off the old block -a cut above the rest -a dime a dozen -a drop in the bucket -a fate worse than death -a far cry -a grain of salt -a little bird told me -a no-brainer -a perfect storm -a piece of cake -a pretty penny -a shot in the arm -a shot in the dark -a stone's throw -above and beyond -absence makes the heart grow fonder -acid test -after all is said and done -against all odds -against the clock -ahead of the curve -ahead of the pack -all bark and no bite -all bets are off -all in a day's work -all in good time -all in the same boat -all intents and purposes -all is well that ends well -all roads lead to rome -all that glitters is not gold -all the bells and whistles -all walks of life -all's well that ends well -an axe to grind -apple of my eye -apples to apples -armchair quarterback -as easy as pie -as good as gold -as luck would have it -as right as rain -as the crow flies -at a loss for words -at the drop of a hat -at the end of the day -avoid like the plague -awesome -back against the wall -back to square one -back to the drawing board -bad apple -bad egg -baptism by fire -baptism of fire -barking up the wrong tree -basic necessities -be all and end all -be that as it may -beat a dead horse -beat around the bush -beauty is in the eye of the beholder -beg the question -beggars can't be choosers -behind the eight ball -believe me -believe you me -benefit of the doubt -best laid plans -better late than never -between a rock and a hard place -between you and me -beyond the pale -bide your time -big fish in a small pond -bird's-eye view -birds of a feather flock together -bite the bullet -bite the dust -bite the hand that feeds you -bitten by the bug -blessing in disguise -blood is thicker than water -blow off steam -blue in the face -boils down to -bolt from the blue -bone of contention -bone to pick -born and bred -born with a silver spoon -bottom of the barrel -bought the farm -brain-child -brain-dead -brand new -break a leg -break the ice -breath of fresh air -bright and early -bring home the bacon -bring to the table -broad strokes -build a better mousetrap -bull by the horns -bull in a china shop -bumpy ride -burn the candle at both ends -burn the midnight oil -burning question -burst at the seams -burst his bubble -business as usual -butter wouldn't melt -butterflies in my stomach -by hook or by crook -by leaps and bounds -by the book -by the same token -by the skin of one's teeth -can of worms -cannot be overstated -caught between a rock and a hard place -caught red-handed -champing at the bit -chomping at the bit -circle the wagons -clean as a whistle -clear as a bell -clear as crystal -clear as day -clear as mud -climb the ladder -close to the vest -coast is clear -cog in the machine -cold as ice -cold feet -cold shoulder -cold turkey -come full circle -come hell or high water -come out of the woodwork -come to a head -come to grips with -come what may -costs an arm and a leg -couch potato -count your blessings -countless hours -counting chickens -crack of dawn -crash and burn -cream of the crop -crocodile tears -cross that bridge when we come to it -crunch time -cry over spilled milk -crystal clear -curiosity killed the cat -cut and dried -cut from the same cloth -cut the mustard -cut to the chase -dark horse -dawn of a new day -day in and day out -dead as a doornail -dead in the water -dead to the world -deer in the headlights -devil is in the details -different strokes for different folks -don't count your chickens before they hatch -don't hold your breath -don't judge a book by its cover -dog and pony show -dog-eat-dog world -dot the i's and cross the t's -down and dirty -down and out -down in the dumps -down the drain -down the rabbit hole -down to the wire -drop in the bucket -dyed in the wool -each and every -early bird gets the worm -easier said than done -easy as pie -easy come easy go -egg on your face -eleventh hour -every cloud has a silver lining -every dog has its day -every fiber of my being -every nook and cranny -every step of the way -everything but the kitchen sink -exception that proves the rule -eye for an eye -face the music -fair and square -fall on deaf ears -falling through the cracks -famous last words -fancy free -far and wide -far be it from me -few and far between -field day -fight tooth and nail -final nail in the coffin -first and foremost -first come first served -fit as a fiddle -flash in the pan -flat as a pancake -flesh and blood -food for thought -fool's paradise -for all intents and purposes -for the long haul -for what it's worth -foregone conclusion -forest for the trees -free and clear -free as a bird -from time immemorial -full circle -full of beans -gain ground -game plan -get a grip -get a leg up -get the ball rolling -get the upper hand -give 110 percent -give and take -give it the old college try -give it your all -give up the ghost -go down the drain -go the distance -go the extra mile -go with the flow -going against the grain -golden opportunity -gone but not forgotten -good as gold -good clean fun -good things come to those who wait -grain of salt -grease the wheels -great minds think alike -green light -green with envy -grin and bear it -hand over fist -happy as a clam -hard and fast -hard as nails -hard nut to crack -hat in hand -have a nice day -have a ton of -head over heels -heart of gold -hit below the belt -hit the ground running -hit the nail on the head -hit the road -hold your horses -hook line and sinker -hot potato -if looks could kill -if the shoe fits -in a nutshell -in black and white -in no time flat -in spades -in the blink of an eye -in the end -in the nick of time -in the same boat -in this day and age -it is what it is -it never rains but it pours -it takes two to tango -it's a long story -it's a small world -it's all downhill from here -it's always darkest before the dawn -it's not brain surgery -it's not rocket science -ivory tower -jack of all trades -jockey for position -jog your memory -jump on the bandwagon -jump the gun -jump the shark -just for kicks -just the tip of the iceberg -keep it real -keep your chin up -keep your eyes peeled -keep your nose to the grindstone -kick the bucket -kill two birds with one stone -knee-jerk reaction -knock on wood -know the ropes -knuckle down -land of the living -last but not least -last straw -laugh out loud -lay down the law -lay of the land -leaps and bounds -leave no stone unturned -let the cat out of the bag -level playing field -life is short -lift a finger -light at the end of the tunnel -like a boss -like a broken record -lion's share -live and let live -living the dream -loaded for bear -long story short -loose cannon -lost cause -lost in the shuffle -low-hanging fruit -make a long story short -make ends meet -make it or break it -make no bones about it -make the grade -method to my madness -mind over matter -miss the boat -moment of truth -money doesn't grow on trees -more than meets the eye -move the goalposts -much ado about nothing -my bad -nail in the coffin -neat as a pin -neck of the woods -needle in a haystack -never in a million years -never say die -never say never -new kid on the block -new lease on life -nip it in the bud -no holds barred -no ifs, ands, or buts -no pain no gain -no stone left unturned -no stone unturned -no time like the present -none the wiser -nose to the grindstone -not by a long shot -not my cup of tea -not to put too fine a point on it -on cloud nine -on the face of it -on the fence -on the same page -once in a blue moon -one for the books -one in a million -open and shut case -open secret -opposite sex -out of left field -out of pocket -out of the blue -out of the box -out of the frying pan -over a barrel -over the hump -over the moon -overturn every stone -pain in the neck -par for the course -passing fad -passing fancy -pave the way -pedal to the metal -pie in the sky -piece of cake -play devil's advocate -play hardball -play it by ear -play second fiddle -play your cards right -plot thickens -point of no return -pot calling the kettle black -powers that be -prick up your ears -pros and cons -pull the wool over your eyes -pull your weight -push the envelope -put a cork in it -put the cart before the horse -put two and two together -put your best foot forward -put your foot down -quick as a wink -quick on the draw -raining cats and dogs -read between the lines -reality check -reap the rewards -rest on your laurels -ride out the storm -right as rain -ring a bell -road to hell -road to recovery -rock and a hard place -rock the boat -roll with the punches -rome wasn't built in a day -run circles around -running on empty -sanity check -save face -scared stiff -second nature -see eye to eye -see the light -seize the day -selling like hotcakes -set in stone -shape up or ship out -short and sweet -shot in the dark -silent as the grave -sink or swim -sixth sense -skate on thin ice -skin in the game -slippery slope -smooth sailing -snug as a bug in a rug -sour grapes -speak of the devil -speak volumes -spill the beans -spread like wildfire -square peg in a round hole -stand the test of time -start from scratch -state of the art -steal someone's thunder -stick in the mud -stiff upper lip -straight from the horse's mouth -stretched thin -string along -stubborn as a mule -sweet as pie -take it with a grain of salt -take the bull by the horns -take the high road -take the lead -take the plunge -tell it like it is -the ball is in your court -the bottom line -the early bird catches the worm -the elephant in the room -the end of an era -the last nail in the coffin -the path of least resistance -the pot calling the kettle black -the real deal -the time of my life -the tip of the iceberg -the whole nine yards -the whole shebang -the world is your oyster -think outside the box -thorn in my side -through thick and thin -throw caution to the wind -throw in the towel -throw under the bus -tie the knot -time flies -time is money -time is of the essence -time will tell -tip of the iceberg -to each his own -toe the line -too many cooks in the kitchen -tough as nails -tried and true -tried and tested -turn a blind eye -turn over a new leaf -twelve o'clock shadow -two sides of the same coin -under the weather -up in the air -up to par -up to speed -up to the task -uphill battle -walking on eggshells -waste not want not -water under the bridge -what goes around comes around -when all is said and done -when pigs fly -when the cat's away -when the chips are down -when the rubber hits the road -where there's smoke there's fire -whole nine yards -wild goose chase -win-win situation -with all due respect -with bated breath -with flying colors -with open arms -without a hitch -without further ado -without rhyme or reason -worth its weight in gold -you bet your bottom dollar -you can't have it both ways -you can't have your cake and eat it too -you can't judge a book by its cover -you can't win them all diff --git a/crates/mehen-markdown/src/data/hedges.txt b/crates/mehen-markdown/src/data/hedges.txt deleted file mode 100644 index 1c939073..00000000 --- a/crates/mehen-markdown/src/data/hedges.txt +++ /dev/null @@ -1,92 +0,0 @@ -# Hedge words — words that soften claims. -# Source: https://github.com/words/hedges (MIT). -# One lowercase entry per line. Multi-word hedges use spaces. -about -almost -apparent -apparently -appear -appeared -appears -approximately -around -basically -can -conceivably -could -couple -depending -depends -doubtful -effectively -especially -estimate -estimated -fairly -few -frequently -generally -guess -guessing -kind of -largely -likely -look like -looks like -maybe -might -more or less -most -mostly -much -nearly -occasionally -often -overall -perhaps -possible -possibly -practically -presumably -probable -probably -quite -rather -really -relatively -roughly -seem -seemed -seemingly -seems -seldom -several -should -significant -significantly -slightly -some -somebody -someone -something -sometimes -somewhat -somewhere -sort of -suggest -suggested -suggests -suppose -supposed -supposedly -supposing -surely -tend -tended -tendency -tending -tends -typical -typically -usually -would diff --git a/crates/mehen-markdown/src/data/inclusive_flags.txt b/crates/mehen-markdown/src/data/inclusive_flags.txt deleted file mode 100644 index 1ff7fa85..00000000 --- a/crates/mehen-markdown/src/data/inclusive_flags.txt +++ /dev/null @@ -1,71 +0,0 @@ -# Inclusive-language flags. Format: -# \t\t -# Categories: gendered, ableist, tech-exclusion, condescending. -# Source: alex / retext-equality (https://github.com/retextjs/retext-equality) — MIT, -# plus Inclusive Naming Initiative mappings (Apache-2.0) and Amazon inclusive-language list. -gendered mankind humanity, people -gendered manmade artificial, synthetic, machine-made -gendered manhole maintenance hole -gendered fireman firefighter -gendered policeman police officer -gendered policewoman police officer -gendered chairman chairperson, chair -gendered chairwoman chairperson, chair -gendered spokesman spokesperson -gendered spokeswoman spokesperson -gendered salesman salesperson -gendered saleswoman salesperson -gendered stewardess flight attendant -gendered waitress server -gendered housewife homemaker -gendered middleman intermediary, liaison -gendered manpower workforce, staffing, labor -gendered man-hour person-hour, work hour -gendered man-hours person-hours, work hours -gendered manning staffing -gendered freshman first-year student -gendered mother tongue native language, first language -gendered you guys all of you, everyone, team -gendered guys everyone, folks, team -ableist crazy unreasonable, surprising, intense -ableist insane unreasonable, surprising -ableist lame unimpressive, uninspired -ableist dumb unsophisticated, lacking -ableist stupid poor, unreasonable -ableist blind to unaware of, oblivious to -ableist tone deaf insensitive, unaware -ableist cripple disable, hinder -ableist crippling debilitating, severe -ableist handicapped disabled, has a disability -ableist spaz overreact -ableist psycho unreasonable, erratic -ableist schizo erratic -ableist bipolar variable, erratic -ableist OCD meticulous -tech-exclusion master primary, main, leader, controller -tech-exclusion slave replica, secondary, follower, responder -tech-exclusion whitelist allowlist, approved list -tech-exclusion blacklist denylist, blocklist -tech-exclusion whitelisted allowlisted -tech-exclusion blacklisted denylisted, blocked -tech-exclusion grandfathered legacy, exempt -tech-exclusion grandfather clause legacy exception -tech-exclusion sanity check spot check, check, validation -tech-exclusion sanity-check spot-check, check -tech-exclusion dummy value placeholder value, sample -tech-exclusion dummy placeholder, sample -tech-exclusion native feature built-in feature -tech-exclusion native app built-in app -tech-exclusion first-class citizen fully supported -tech-exclusion peanut gallery critic, critical audience -condescending obviously (remove or restate) -condescending clearly (remove) -condescending just (remove) -condescending simply (remove) -condescending easy (remove — describe steps instead) -condescending easily (remove) -condescending of course (remove) -condescending naturally (remove) -condescending trivial straightforward -condescending trivially (remove or restate) -condescending basic (remove or restate) diff --git a/crates/mehen-markdown/src/data/ja_redundant.txt b/crates/mehen-markdown/src/data/ja_redundant.txt deleted file mode 100644 index 97257320..00000000 --- a/crates/mehen-markdown/src/data/ja_redundant.txt +++ /dev/null @@ -1,47 +0,0 @@ -# Japanese redundant expressions (ja-no-redundant-expression). -# Source: textlint-rule-preset-ja-technical-writing (MIT). -# Each line is a substring match inside Japanese text. -することができる -することができます -することができない -することができません -することが可能 -することが可能です -することが可能である -することが可能になる -することが出来る -することが出来ます -することが出来ない -ことができる -ことができます -ことが可能 -ということ -というもの -というふうに -というような -という形で -という風に -のほう -のほうが -のほうへ -のほうから -行なう -行なった -行なって -行なわ -に関して -に関しての -に対して -について -においては -における -による -によって -に基づく -に基づいて -〜させていただく -させていただきます -させていただいて -なお、その上 -なお、また -ところで、さて diff --git a/crates/mehen-markdown/src/data/ja_weak_phrases.txt b/crates/mehen-markdown/src/data/ja_weak_phrases.txt deleted file mode 100644 index c246a6e4..00000000 --- a/crates/mehen-markdown/src/data/ja_weak_phrases.txt +++ /dev/null @@ -1,44 +0,0 @@ -# Japanese weak phrases (ja-no-weak-phrase). -# Source: textlint-rule-preset-ja-technical-writing (MIT). -# Each line is a substring match. Any occurrence inside a Japanese block -# counts as one weak-phrase hit. -かもしれない -かも知れない -かもしれません -かも知れません -と思います -と思う -と思われる -と考えられる -のような気がする -気がする -気がします -感じがする -感じがします -だと思います -と言える -言えるだろう -とも言える -と考えられます -らしいです -らしい -ようです -ようだ -かもしれず -でしょう -でしょうか -可能性がある -可能性があります -可能性を持つ -ではないか -かと思われる -おそらく -多分 -たぶん -たぶん〜だろう -ほぼ -ほとんど -ほとんどの -〜的な -〜的で -〜的に diff --git a/crates/mehen-markdown/src/data/jouyou_kanji.txt b/crates/mehen-markdown/src/data/jouyou_kanji.txt deleted file mode 100644 index e529fdbc..00000000 --- a/crates/mehen-markdown/src/data/jouyou_kanji.txt +++ /dev/null @@ -1,1838 +0,0 @@ -# Jōyō kanji list — Japan MEXT 2010 revision (2,136 entries). -# Public domain (Japanese government policy document). -# Format: one entry per line. `\t` where grade is: -# 1..6 = Kyōiku grade (elementary school year) -# 7 = Secondary Jōyō (junior high + high school) -# Non-listed kanji are treated as grade 8 (hyōgai). -# Source: https://www.mext.go.jp/a_menu/shotou/new-cs/youryou/syo/kokugo/001.htm -# This list is an unabridged Grade 1-6 (Kyōiku) sample plus representative -# secondary Jōyō. For a Tier-0 deterministic proxy of jouyou_grade_mean this -# is sufficient; the full 2,136-entry list can be substituted without code -# change. Every entry must be a single grapheme and a valid Unicode Han code -# point. -# --- Grade 1 (80 chars) --- -一 1 -右 1 -雨 1 -円 1 -王 1 -音 1 -下 1 -火 1 -花 1 -貝 1 -学 1 -気 1 -九 1 -休 1 -玉 1 -金 1 -空 1 -月 1 -犬 1 -見 1 -五 1 -口 1 -校 1 -左 1 -三 1 -山 1 -子 1 -四 1 -糸 1 -字 1 -耳 1 -七 1 -車 1 -手 1 -十 1 -出 1 -女 1 -小 1 -上 1 -森 1 -人 1 -水 1 -正 1 -生 1 -青 1 -夕 1 -石 1 -赤 1 -千 1 -川 1 -先 1 -早 1 -草 1 -足 1 -村 1 -大 1 -男 1 -竹 1 -中 1 -虫 1 -町 1 -天 1 -田 1 -土 1 -二 1 -日 1 -入 1 -年 1 -白 1 -八 1 -百 1 -文 1 -木 1 -本 1 -名 1 -目 1 -立 1 -力 1 -林 1 -六 1 -# --- Grade 2 (160 chars) --- -引 2 -羽 2 -雲 2 -園 2 -遠 2 -黄 2 -何 2 -夏 2 -家 2 -科 2 -歌 2 -画 2 -会 2 -回 2 -海 2 -絵 2 -外 2 -角 2 -楽 2 -活 2 -間 2 -丸 2 -岩 2 -顔 2 -汽 2 -記 2 -帰 2 -弓 2 -牛 2 -魚 2 -京 2 -強 2 -教 2 -近 2 -兄 2 -形 2 -計 2 -元 2 -言 2 -原 2 -戸 2 -古 2 -午 2 -後 2 -語 2 -工 2 -公 2 -広 2 -交 2 -光 2 -考 2 -行 2 -高 2 -合 2 -黒 2 -今 2 -才 2 -細 2 -作 2 -算 2 -止 2 -市 2 -矢 2 -姉 2 -思 2 -紙 2 -寺 2 -自 2 -時 2 -室 2 -社 2 -弱 2 -首 2 -秋 2 -週 2 -春 2 -書 2 -少 2 -場 2 -色 2 -食 2 -心 2 -新 2 -親 2 -図 2 -数 2 -西 2 -声 2 -星 2 -晴 2 -切 2 -雪 2 -船 2 -線 2 -前 2 -組 2 -走 2 -多 2 -太 2 -体 2 -台 2 -地 2 -池 2 -知 2 -茶 2 -昼 2 -長 2 -鳥 2 -朝 2 -直 2 -通 2 -弟 2 -店 2 -点 2 -電 2 -刀 2 -冬 2 -当 2 -東 2 -答 2 -頭 2 -同 2 -道 2 -読 2 -内 2 -南 2 -肉 2 -馬 2 -買 2 -売 2 -麦 2 -半 2 -番 2 -父 2 -風 2 -分 2 -聞 2 -米 2 -歩 2 -母 2 -方 2 -北 2 -妹 2 -毎 2 -万 2 -明 2 -鳴 2 -毛 2 -門 2 -夜 2 -野 2 -友 2 -用 2 -曜 2 -来 2 -里 2 -理 2 -話 2 -# --- Grade 3 (200 chars) --- -悪 3 -安 3 -暗 3 -医 3 -委 3 -意 3 -育 3 -員 3 -院 3 -飲 3 -運 3 -泳 3 -駅 3 -央 3 -横 3 -屋 3 -温 3 -化 3 -荷 3 -界 3 -開 3 -階 3 -寒 3 -感 3 -漢 3 -館 3 -岸 3 -起 3 -期 3 -客 3 -究 3 -急 3 -級 3 -宮 3 -球 3 -去 3 -橋 3 -業 3 -曲 3 -局 3 -銀 3 -区 3 -苦 3 -具 3 -君 3 -係 3 -軽 3 -血 3 -決 3 -研 3 -県 3 -庫 3 -湖 3 -向 3 -幸 3 -港 3 -号 3 -根 3 -祭 3 -皿 3 -仕 3 -死 3 -使 3 -始 3 -指 3 -歯 3 -詩 3 -次 3 -事 3 -持 3 -式 3 -実 3 -写 3 -者 3 -主 3 -守 3 -取 3 -酒 3 -受 3 -州 3 -拾 3 -終 3 -習 3 -集 3 -住 3 -重 3 -宿 3 -所 3 -暑 3 -助 3 -昭 3 -消 3 -商 3 -章 3 -勝 3 -乗 3 -植 3 -申 3 -身 3 -神 3 -真 3 -深 3 -進 3 -世 3 -整 3 -昔 3 -全 3 -相 3 -送 3 -想 3 -息 3 -速 3 -族 3 -他 3 -打 3 -対 3 -待 3 -代 3 -第 3 -題 3 -炭 3 -短 3 -談 3 -着 3 -注 3 -柱 3 -丁 3 -帳 3 -調 3 -追 3 -定 3 -庭 3 -笛 3 -鉄 3 -転 3 -都 3 -度 3 -投 3 -豆 3 -島 3 -湯 3 -登 3 -等 3 -動 3 -童 3 -農 3 -波 3 -配 3 -倍 3 -箱 3 -畑 3 -発 3 -反 3 -板 3 -皮 3 -悲 3 -美 3 -鼻 3 -筆 3 -氷 3 -表 3 -秒 3 -病 3 -品 3 -負 3 -部 3 -服 3 -福 3 -物 3 -平 3 -返 3 -勉 3 -放 3 -味 3 -命 3 -面 3 -問 3 -役 3 -薬 3 -由 3 -油 3 -有 3 -遊 3 -予 3 -羊 3 -洋 3 -葉 3 -陽 3 -様 3 -落 3 -流 3 -旅 3 -両 3 -緑 3 -礼 3 -列 3 -練 3 -路 3 -和 3 -# --- Grade 4 (202 chars) --- -愛 4 -案 4 -以 4 -衣 4 -位 4 -囲 4 -胃 4 -印 4 -英 4 -栄 4 -塩 4 -億 4 -加 4 -果 4 -貨 4 -課 4 -芽 4 -改 4 -械 4 -害 4 -街 4 -各 4 -覚 4 -完 4 -官 4 -管 4 -関 4 -観 4 -願 4 -希 4 -季 4 -紀 4 -喜 4 -旗 4 -器 4 -機 4 -議 4 -求 4 -泣 4 -救 4 -給 4 -挙 4 -漁 4 -共 4 -協 4 -鏡 4 -競 4 -極 4 -訓 4 -軍 4 -郡 4 -径 4 -型 4 -景 4 -芸 4 -欠 4 -結 4 -建 4 -健 4 -験 4 -固 4 -功 4 -好 4 -香 4 -候 4 -康 4 -佐 4 -差 4 -菜 4 -最 4 -材 4 -昨 4 -札 4 -刷 4 -殺 4 -察 4 -参 4 -産 4 -散 4 -残 4 -士 4 -氏 4 -史 4 -司 4 -試 4 -児 4 -治 4 -辞 4 -失 4 -借 4 -種 4 -周 4 -祝 4 -順 4 -初 4 -松 4 -笑 4 -唱 4 -焼 4 -象 4 -照 4 -賞 4 -臣 4 -信 4 -成 4 -省 4 -清 4 -静 4 -席 4 -積 4 -折 4 -節 4 -説 4 -浅 4 -戦 4 -選 4 -然 4 -争 4 -倉 4 -巣 4 -束 4 -側 4 -続 4 -卒 4 -孫 4 -帯 4 -隊 4 -達 4 -単 4 -置 4 -仲 4 -貯 4 -兆 4 -腸 4 -低 4 -底 4 -停 4 -的 4 -典 4 -伝 4 -徒 4 -努 4 -灯 4 -堂 4 -働 4 -特 4 -得 4 -毒 4 -熱 4 -念 4 -敗 4 -梅 4 -博 4 -飯 4 -必 4 -票 4 -標 4 -不 4 -夫 4 -付 4 -府 4 -副 4 -粉 4 -兵 4 -別 4 -辺 4 -変 4 -便 4 -包 4 -法 4 -望 4 -牧 4 -末 4 -満 4 -未 4 -脈 4 -民 4 -無 4 -約 4 -勇 4 -要 4 -養 4 -浴 4 -利 4 -陸 4 -良 4 -料 4 -量 4 -輪 4 -類 4 -令 4 -冷 4 -例 4 -歴 4 -連 4 -老 4 -労 4 -録 4 -# --- Grade 5 (193 chars) --- -圧 5 -移 5 -因 5 -永 5 -営 5 -衛 5 -易 5 -益 5 -液 5 -演 5 -応 5 -往 5 -桜 5 -恩 5 -可 5 -仮 5 -価 5 -河 5 -過 5 -賀 5 -快 5 -解 5 -格 5 -確 5 -額 5 -刊 5 -幹 5 -慣 5 -眼 5 -基 5 -寄 5 -規 5 -技 5 -義 5 -逆 5 -久 5 -旧 5 -居 5 -許 5 -境 5 -均 5 -禁 5 -句 5 -群 5 -経 5 -潔 5 -件 5 -券 5 -険 5 -検 5 -限 5 -現 5 -減 5 -故 5 -個 5 -護 5 -効 5 -厚 5 -耕 5 -鉱 5 -構 5 -興 5 -講 5 -混 5 -査 5 -再 5 -災 5 -妻 5 -採 5 -際 5 -在 5 -財 5 -罪 5 -雑 5 -酸 5 -賛 5 -支 5 -志 5 -枝 5 -師 5 -資 5 -飼 5 -示 5 -似 5 -識 5 -質 5 -舎 5 -謝 5 -授 5 -修 5 -述 5 -術 5 -準 5 -序 5 -招 5 -承 5 -証 5 -条 5 -状 5 -常 5 -情 5 -織 5 -職 5 -制 5 -性 5 -政 5 -勢 5 -精 5 -製 5 -税 5 -責 5 -績 5 -接 5 -設 5 -舌 5 -絶 5 -銭 5 -祖 5 -素 5 -総 5 -造 5 -像 5 -増 5 -則 5 -測 5 -属 5 -率 5 -損 5 -態 5 -貸 5 -退 5 -団 5 -断 5 -築 5 -張 5 -提 5 -程 5 -適 5 -敵 5 -統 5 -銅 5 -導 5 -徳 5 -独 5 -任 5 -燃 5 -能 5 -破 5 -犯 5 -判 5 -版 5 -比 5 -肥 5 -非 5 -備 5 -俵 5 -評 5 -貧 5 -布 5 -婦 5 -富 5 -武 5 -復 5 -複 5 -仏 5 -編 5 -弁 5 -保 5 -墓 5 -報 5 -豊 5 -防 5 -貿 5 -暴 5 -務 5 -夢 5 -迷 5 -綿 5 -輸 5 -余 5 -預 5 -容 5 -略 5 -留 5 -領 5 -歴 5 -# --- Grade 6 (191 chars) --- -異 6 -遺 6 -域 6 -宇 6 -映 6 -延 6 -沿 6 -我 6 -灰 6 -拡 6 -革 6 -閣 6 -割 6 -株 6 -干 6 -巻 6 -看 6 -簡 6 -危 6 -机 6 -揮 6 -貴 6 -疑 6 -吸 6 -供 6 -胸 6 -郷 6 -勤 6 -筋 6 -系 6 -敬 6 -警 6 -劇 6 -激 6 -穴 6 -絹 6 -権 6 -憲 6 -源 6 -厳 6 -己 6 -呼 6 -誤 6 -后 6 -孝 6 -皇 6 -紅 6 -降 6 -鋼 6 -刻 6 -穀 6 -骨 6 -困 6 -砂 6 -座 6 -済 6 -裁 6 -策 6 -冊 6 -蚕 6 -至 6 -私 6 -姿 6 -視 6 -詞 6 -誌 6 -磁 6 -射 6 -捨 6 -尺 6 -若 6 -樹 6 -収 6 -宗 6 -就 6 -衆 6 -従 6 -縦 6 -縮 6 -熟 6 -純 6 -処 6 -署 6 -諸 6 -除 6 -将 6 -傷 6 -障 6 -城 6 -蒸 6 -針 6 -仁 6 -垂 6 -推 6 -寸 6 -盛 6 -聖 6 -誠 6 -宣 6 -専 6 -泉 6 -洗 6 -染 6 -善 6 -奏 6 -窓 6 -創 6 -装 6 -層 6 -操 6 -蔵 6 -臓 6 -存 6 -尊 6 -宅 6 -担 6 -探 6 -誕 6 -段 6 -暖 6 -値 6 -宙 6 -忠 6 -著 6 -庁 6 -頂 6 -潮 6 -賃 6 -痛 6 -敵 6 -展 6 -討 6 -党 6 -糖 6 -届 6 -難 6 -乳 6 -認 6 -納 6 -脳 6 -派 6 -拝 6 -背 6 -肺 6 -俳 6 -班 6 -晩 6 -否 6 -批 6 -秘 6 -腹 6 -奮 6 -並 6 -陛 6 -閉 6 -片 6 -補 6 -暮 6 -宝 6 -訪 6 -亡 6 -忘 6 -棒 6 -枚 6 -幕 6 -密 6 -盟 6 -模 6 -訳 6 -郵 6 -優 6 -預 6 -幼 6 -欲 6 -翌 6 -乱 6 -卵 6 -覧 6 -裏 6 -律 6 -臨 6 -朗 6 -論 6 -# --- Secondary (Junior High + High School) Jōyō. Representative subset. --- -亜 7 -哀 7 -握 7 -扱 7 -依 7 -偉 7 -違 7 -維 7 -緯 7 -壱 7 -芋 7 -咽 7 -姻 7 -淫 7 -陰 7 -隠 7 -韻 7 -右 7 -宇 7 -虞 7 -浦 7 -運 7 -雲 7 -営 7 -影 7 -鋭 7 -越 7 -謁 7 -閲 7 -宴 7 -援 7 -煙 7 -猿 7 -遠 7 -鉛 7 -縁 7 -汚 7 -凹 7 -奥 7 -押 7 -欧 7 -殴 7 -翁 7 -沖 7 -憶 7 -臆 7 -虞 7 -乙 7 -卸 7 -恩 7 -穏 7 -下 7 -化 7 -佳 7 -架 7 -華 7 -菓 7 -靴 7 -寡 7 -箇 7 -稼 7 -蚊 7 -我 7 -牙 7 -瓦 7 -雅 7 -餓 7 -介 7 -皆 7 -塊 7 -壊 7 -怪 7 -悔 7 -懐 7 -戒 7 -拐 7 -晦 7 -械 7 -蓋 7 -慨 7 -概 7 -涯 7 -該 7 -骸 7 -垣 7 -柿 7 -核 7 -殻 7 -郭 7 -隔 7 -穫 7 -岳 7 -顎 7 -葛 7 -喝 7 -括 7 -渇 7 -褐 7 -轄 7 -且 7 -缶 7 -敢 7 -棺 7 -款 7 -歓 7 -環 7 -監 7 -緩 7 -罐 7 -艦 7 -還 7 -鑑 7 -含 7 -岩 7 -頑 7 -玩 7 -企 7 -伎 7 -祈 7 -軌 7 -既 7 -飢 7 -鬼 7 -幾 7 -棋 7 -棄 7 -棋 7 -毅 7 -騎 7 -虐 7 -脚 7 -及 7 -丘 7 -朽 7 -叫 7 -糾 7 -窮 7 -享 7 -峡 7 -恭 7 -狭 7 -恐 7 -挟 7 -矯 7 -驚 7 -仰 7 -凝 7 -暁 7 -菌 7 -琴 7 -僅 7 -緊 7 -錦 7 -吟 7 -駆 7 -具 7 -愚 7 -偶 7 -遇 7 -隅 7 -屈 7 -掘 7 -靴 7 -繰 7 -刑 7 -契 7 -恵 7 -啓 7 -掲 7 -渓 7 -蛍 7 -携 7 -継 7 -傾 7 -慶 7 -憩 7 -鶏 7 -撃 7 -傑 7 -肩 7 -倹 7 -兼 7 -剣 7 -圏 7 -堅 7 -嫌 7 -献 7 -遣 7 -賢 7 -謙 7 -繭 7 -顕 7 -懸 7 -幻 7 -玄 7 -孤 7 -弧 7 -枯 7 -雇 7 -誇 7 -鼓 7 -顧 7 -互 7 -呉 7 -娯 7 -悟 7 -碁 7 -御 7 -侯 7 -洪 7 -荒 7 -貢 7 -控 7 -慌 7 -硬 7 -溝 7 -綱 7 -酵 7 -稿 7 -衡 7 -購 7 -乞 7 -拷 7 -剛 7 -傲 7 -豪 7 -克 7 -酷 7 -獄 7 -込 7 -頃 7 -昆 7 -婚 7 -恨 7 -紺 7 -魂 7 -墾 7 -懇 7 -佐 7 -唆 7 -詐 7 -鎖 7 -債 7 -催 7 -載 7 -歳 7 -崎 7 -埼 7 -削 7 -索 7 -酢 7 -雌 7 -施 7 -肢 7 -諮 7 -侍 7 -慈 7 -餌 7 -軸 7 -執 7 -漆 7 -疾 7 -嫉 7 -湿 7 -嫉 7 -漆 7 -柴 7 -芝 7 -斜 7 -煮 7 -遮 7 -蛇 7 -邪 7 -酌 7 -寂 7 -朱 7 -狩 7 -殊 7 -珠 7 -趣 7 -儒 7 -寿 7 -獣 7 -瞬 7 -旬 7 -巡 7 -盾 7 -循 7 -遵 7 -庶 7 -緒 7 -叙 7 -徐 7 -償 7 -匠 7 -昇 7 -沼 7 -宵 7 -称 7 -症 7 -祥 7 -粧 7 -詔 7 -奨 7 -詳 7 -彰 7 -憧 7 -衝 7 -償 7 -礁 7 -鐘 7 -丈 7 -冗 7 -浄 7 -剰 7 -畳 7 -嬢 7 -錠 7 -譲 7 -嘱 7 -辱 7 -伸 7 -芯 7 -辛 7 -侵 7 -津 7 -娠 7 -紳 7 -診 7 -寝 7 -慎 7 -審 7 -甚 7 -尋 7 -尽 7 -迅 7 -陣 7 -酢 7 -須 7 -穂 7 -随 7 -髄 7 -据 7 -杉 7 -澄 7 -瀬 7 -畝 7 -是 7 -井 7 -斉 7 -征 7 -牲 7 -逝 7 -婿 7 -誓 7 -請 7 -隻 7 -惜 7 -斥 7 -析 7 -籍 7 -跡 7 -拙 7 -窃 7 -摂 7 -仙 7 -占 7 -扇 7 -栓 7 -旋 7 -践 7 -煎 7 -羨 7 -遷 7 -薦 7 -鮮 7 -繊 7 -禅 7 -漸 7 -膳 7 -繕 7 -狙 7 -阻 7 -租 7 -粗 7 -措 7 -疎 7 -礎 7 -双 7 -壮 7 -荘 7 -捜 7 -掃 7 -挿 7 -曹 7 -桑 7 -喪 7 -葬 7 -僧 7 -遭 7 -槽 7 -踪 7 -燥 7 -霜 7 -騒 7 -藻 7 -僧 7 -即 7 -促 7 -俗 7 -賊 7 -堕 7 -妥 7 -惰 7 -馱 7 -駄 7 -体 7 -耐 7 -怠 7 -胎 7 -堆 7 -袋 7 -逮 7 -替 7 -貸 7 -滞 7 -腿 7 -戴 7 -泰 7 -濯 7 -卓 7 -拓 7 -沢 7 -濯 7 -諾 7 -但 7 -棚 7 -誰 7 -丹 7 -旦 7 -担 7 -淡 7 -胆 7 -嘆 7 -端 7 -綻 7 -緞 7 -値 7 -恥 7 -痴 7 -稚 7 -致 7 -遅 7 -畜 7 -逐 7 -蓄 7 -秩 7 -窒 7 -嫡 7 -抽 7 -衷 7 -酎 7 -鋳 7 -駐 7 -著 7 -貯 7 -丁 7 -弔 7 -挑 7 -彫 7 -眺 7 -釣 7 -脹 7 -超 7 -跳 7 -徴 7 -嘲 7 -澄 7 -聴 7 -懲 7 -勅 7 -捗 7 -沈 7 -珍 7 -朕 7 -陳 7 -鎮 7 -津 7 -墜 7 -塚 7 -漬 7 -坪 7 -爪 7 -鶴 7 -泥 7 -摘 7 -滴 7 -溺 7 -迭 7 -哲 7 -徹 7 -撤 7 -塡 7 -添 7 -殿 7 -吐 7 -妬 7 -途 7 -奴 7 -怒 7 -到 7 -逃 7 -倒 7 -凍 7 -唐 7 -桃 7 -透 7 -悼 7 -盗 7 -陶 7 -塔 7 -搭 7 -棟 7 -痘 7 -筒 7 -稲 7 -踏 7 -謄 7 -騰 7 -闘 7 -洞 7 -胴 7 -瞳 7 -峠 7 -匿 7 -督 7 -篤 7 -凸 7 -突 7 -屯 7 -惇 7 -呑 7 -頓 7 -丼 7 -曇 7 -鈍 7 -縄 7 -軟 7 -尼 7 -弐 7 -匂 7 -虹 7 -妊 7 -忍 7 -寧 7 -猫 7 -粘 7 -悩 7 -濃 7 -把 7 -婆 7 -罵 7 -杯 7 -輩 7 -培 7 -媒 7 -賠 7 -陪 7 -伯 7 -拍 7 -泊 7 -舶 7 -薄 7 -漠 7 -縛 7 -爆 7 -麦 7 -肌 7 -鉢 7 -髪 7 -伐 7 -罰 7 -閥 7 -氾 7 -汎 7 -版 7 -班 7 -畔 7 -般 7 -販 7 -搬 7 -煩 7 -頒 7 -範 7 -繁 7 -藩 7 -盤 7 -蛮 7 -卑 7 -妃 7 -披 7 -疲 7 -被 7 -扉 7 -罷 7 -避 7 -尾 7 -微 7 -眉 7 -膝 7 -肘 7 -匹 7 -泌 7 -姫 7 -媛 7 -漂 7 -苗 7 -描 7 -錨 7 -浜 7 -苗 7 -頻 7 -敏 7 -瓶 7 -賓 7 -怖 7 -扶 7 -敷 7 -普 7 -腐 7 -譜 7 -膚 7 -赴 7 -附 7 -侮 7 -舞 7 -封 7 -伏 7 -幅 7 -覆 7 -払 7 -沸 7 -噴 7 -紛 7 -雰 7 -憤 7 -丙 7 -併 7 -柄 7 -塀 7 -幣 7 -弊 7 -偏 7 -遍 7 -哺 7 -抱 7 -峰 7 -砲 7 -崩 7 -胞 7 -倣 7 -飽 7 -褒 7 -縫 7 -芳 7 -褒 7 -俸 7 -剖 7 -紡 7 -傍 7 -貌 7 -膨 7 -謀 7 -僕 7 -墨 7 -撲 7 -朴 7 -没 7 -堀 7 -奔 7 -凡 7 -盆 7 -摩 7 -磨 7 -魔 7 -麻 7 -埋 7 -妹 7 -槙 7 -幕 7 -又 7 -抹 7 -繭 7 -慢 7 -漫 7 -魅 7 -岬 7 -妙 7 -眠 7 -矛 7 -霧 7 -娘 7 -銘 7 -滅 7 -免 7 -麺 7 -網 7 -猛 7 -盲 7 -耗 7 -妄 7 -網 7 -黙 7 -尤 7 -紋 7 -靄 7 -厄 7 -躍 7 -矢 7 -喩 7 -愉 7 -諭 7 -癒 7 -唯 7 -幽 7 -悠 7 -湧 7 -猶 7 -誘 7 -融 7 -憂 7 -誉 7 -与 7 -誉 7 -溶 7 -窯 7 -庸 7 -揚 7 -揺 7 -遥 7 -瑶 7 -謡 7 -抑 7 -沃 7 -翼 7 -羅 7 -裸 7 -頼 7 -雷 7 -酪 7 -絡 7 -欄 7 -濫 7 -藍 7 -蘭 7 -吏 7 -痢 7 -履 7 -璃 7 -離 7 -柳 7 -硫 7 -隆 7 -粒 7 -竜 7 -慮 7 -僚 7 -寮 7 -涼 7 -猟 7 -料 7 -僚 7 -療 7 -陵 7 -糧 7 -藍 7 -臨 7 -倫 7 -涙 7 -累 7 -塁 7 -戻 7 -鈴 7 -零 7 -霊 7 -隷 7 -麗 7 -齢 7 -暦 7 -劣 7 -烈 7 -裂 7 -廉 7 -恋 7 -憐 7 -漣 7 -錬 7 -炉 7 -賂 7 -露 7 -弄 7 -郎 7 -朗 7 -廊 7 -楼 7 -漏 7 -籠 7 -麓 7 -賄 7 -惑 7 -枠 7 -脇 7 -藁 7 -湾 7 -腕 7 diff --git a/crates/mehen-markdown/src/data/ngsl_1_2.txt b/crates/mehen-markdown/src/data/ngsl_1_2.txt deleted file mode 100644 index 7ecb4fb6..00000000 --- a/crates/mehen-markdown/src/data/ngsl_1_2.txt +++ /dev/null @@ -1,1573 +0,0 @@ -# New General Service List (NGSL 1.2) — Browne, Culligan, Phillips (2013). -# http://www.newgeneralservicelist.com/ -# License: CC BY-SA 4.0 (attribution required). Bundled with NOTICE in -# LICENSE-THIRD-PARTY. -# Format: one lowercase headword per line. Inflected forms are NOT listed; -# the Dale-Chall-style check strips suffixes (-s, -es, -ed, -ing, -ly) before -# lookup. The list below is the NGSL 1.2 lemma list (2800 entries). -the -be -and -of -a -in -to -have -it -i -that -for -you -he -with -on -do -say -this -they -at -but -we -his -from -not -by -she -or -as -what -go -their -can -who -get -if -would -her -all -my -make -about -know -will -as -up -one -time -there -year -so -think -when -which -them -some -me -people -take -out -into -just -see -him -your -come -could -now -than -like -other -how -then -its -our -two -more -these -want -way -look -first -also -new -because -day -use -no -man -find -here -thing -give -many -well -only -those -tell -very -even -back -any -good -woman -through -us -life -child -work -down -may -after -should -call -world -over -school -still -try -last -ask -need -too -feel -three -state -never -become -between -high -really -something -most -another -much -family -own -leave -put -old -while -mean -on -keep -student -why -let -great -same -big -group -begin -seem -country -help -talk -where -turn -problem -every -start -hand -might -american -show -part -against -place -such -again -few -case -most -week -company -system -each -right -program -hear -question -during -play -government -run -small -number -off -always -move -live -night -area -believe -hold -today -bring -happen -next -without -before -large -million -must -home -under -water -room -write -mother -lose -form -offer -power -though -company -room -read -although -until -actually -friend -age -pretty -push -include -history -idea -rather -add -allow -continue -close -hot -learn -probably -present -kind -around -report -stop -include -remember -person -dog -face -wait -throw -listen -sleep -wonder -laugh -quite -town -drink -worry -bottle -receive -carry -song -almost -guy -develop -join -possible -agree -care -hard -couple -decide -mom -smile -doctor -beautiful -bad -deal -lead -cover -arm -easy -open -success -education -build -space -foot -near -perhaps -north -wife -maybe -late -middle -young -step -sign -effort -couple -boy -heart -door -service -front -figure -relation -business -thought -decision -fact -major -within -century -process -truth -society -effect -especially -whose -meeting -sea -third -nothing -cause -war -rest -grow -certain -economic -simply -stay -less -indeed -interest -condition -mind -understand -probably -science -short -word -direct -early -force -important -research -recent -sure -especially -expect -matter -support -court -either -likely -subject -example -relationship -nation -international -ever -season -local -value -energy -fine -result -teacher -project -activity -particular -usually -season -music -fish -industry -population -meaning -teacher -ability -provide -office -speech -drive -discuss -economy -site -pay -available -able -note -simply -clear -base -size -perhaps -despite -general -site -past -among -generally -effect -wall -class -section -fast -act -low -drop -north -test -news -enough -hope -bring -east -west -south -culture -weapon -author -hour -minute -mile -wear -increase -describe -evidence -prepare -section -sense -central -spend -society -experience -street -market -behind -door -term -rise -source -sound -benefit -land -similar -notice -whole -technology -piece -type -design -attention -interest -cause -industry -force -account -charge -claim -church -economic -race -bank -region -station -account -fund -standard -wind -organization -camera -animal -vote -strategy -sort -role -skill -various -consider -likely -create -create -chance -range -growth -response -base -table -choice -kitchen -chair -cancer -employee -budget -religious -enter -blood -foundation -shoulder -whether -concern -activity -remove -style -gas -environment -professional -medical -surface -shake -beyond -tree -wood -vehicle -unit -scientist -position -industry -stage -environmental -tool -event -position -rate -argue -treatment -experience -training -performance -situation -source -authority -argument -analysis -traffic -manage -claim -structure -theory -commercial -religious -common -experience -structure -opportunity -image -hospital -relate -fire -institution -ready -bed -modern -bear -save -involve -collection -quickly -finally -yeah -stock -response -indeed -moment -argue -property -majority -knowledge -identify -trial -staff -nice -senior -board -campaign -range -debate -statement -firm -challenge -truly -cut -legal -protection -assume -lawyer -evidence -relationship -yet -commercial -commission -consumer -tend -factor -region -trade -patient -poor -owner -opinion -conservative -magazine -participant -environment -worker -hotel -cold -quality -mean -commercial -ground -artist -success -weight -beyond -wind -scene -instead -expect -fresh -focus -hair -heavy -wide -culture -instead -foreign -fight -maintain -concern -statement -conclude -technique -explain -agent -generation -suggest -attack -increase -occur -reveal -view -evening -reflect -purpose -lay -whole -deep -notice -traditional -reality -race -investigate -dollar -truth -survey -improve -statement -medicine -pattern -positive -reveal -reader -evaluate -ahead -respond -hang -reach -determine -imagine -professor -behavior -blame -spring -finish -analyze -significant -contain -despite -describe -measure -hispanic -determine -vision -officer -version -brain -quickly -enjoy -tiny -thus -yard -moon -resource -physical -stress -strong -direction -dark -draw -wave -soldier -sort -commercial -sea -particular -generation -wish -appeal -detail -ball -wife -military -hall -glass -disease -leader -wine -contain -radio -yeah -worker -bottle -window -trade -ride -thin -somebody -television -relate -complete -strong -apartment -suffer -trial -prepare -visit -spend -experience -protect -technology -coach -bar -glance -strategy -nine -claim -brother -twenty -commercial -sun -cake -painting -smile -yellow -reduce -fast -mirror -gain -debate -chemical -generation -trade -wonder -recover -sweet -dish -lunch -sixth -senior -moment -concentrate -yeah -dinner -exceed -dead -salt -expand -shot -hole -shine -bottle -officer -meal -glass -approach -kitchen -hunt -carry -pretty -daughter -concept -sister -rule -finger -bar -belong -sell -leg -appear -cook -wait -bad -mind -nothing -step -surface -dog -movement -trip -light -soil -husband -rate -strike -speech -price -choose -sign -ago -professional -concept -truth -language -throughout -exist -wait -throw -kid -tell -consider -discover -enjoy -win -learn -wall -understand -behind -eat -stone -fall -pay -explain -enjoy -ask -carry -become -allow -meet -follow -produce -pull -send -leave -lose -let -include -visit -cry -stand -find -hurt -bring -finish -reach -prove -answer -return -provide -protect -remain -cost -lead -remain -want -sit -open -travel -smile -fly -cross -dance -order -drive -close -cook -invite -share -collect -serve -sell -happen -change -guess -wait -pass -marry -forget -mean -drop -fix -choose -plan -introduce -prefer -kill -reply -arrive -bear -grow -end -lift -save -hit -burn -shine -ride -shake -sing -hear -promise -invite -contain -arrange -bother -test -bury -argue -breathe -concern -continue -claim -apply -belong -care -cheer -act -bend -repeat -affect -announce -pretend -behave -accept -achieve -organize -escape -celebrate -beat -attract -manage -avoid -admit -apologize -deliver -press -suit -measure -demand -increase -destroy -pick -injure -deserve -disappear -discover -express -enter -jump -replace -fall -rule -stretch -suck -complete -create -occupy -offer -prepare -provide -recognize -reply -rescue -serve -smoke -solve -teach -translate -touch -travel -weigh -welcome -arrange -attach -charge -consist -drop -identify -include -judge -lock -mark -melt -owe -own -prefer -prove -punish -quit -raise -reduce -remove -rent -repair -rest -review -risk -suggest -surround -train -train -warn -waste -watch -dig -earn -fasten -gather -hate -hug -joke -kiss -name -perform -recommend -reflect -relax -require -return -reveal -ring -seal -separate -settle -shake -shift -shine -shout -sort -split -spot -stick -stink -strike -struggle -supply -support -surprise -treat -turn -unlock -wake -advise -bet -bite -climb -collect -confess -crawl -crush -decorate -defeat -delay -display -drown -educate -elect -embarrass -entertain -examine -exchange -exclude -expand -explode -extend -fail -float -fold -forecast -govern -handle -hunt -injure -interrupt -invent -involve -march -marry -measure -move -paint -pop -present -prevent -print -promote -pronounce -protect -protest -rebuild -recognize -recover -reduce -regret -reject -release -rely -remember -remind -remove -repair -rescue -reserve -resist -return -ring -rub -search -serve -settle -shine -skip -slide -slip -solve -sort -squeeze -stare -startle -stay -steal -stop -stress -struck -succeed -suggest -surround -suspect -swallow -swim -translate -trap -trust -twist -warn -wave -weigh -whisper -witness -withdraw -wonder -worry -wrap -yell -add -afford -agree -answer -argue -arrive -ask -attack -avoid -bake -beat -beg -behave -believe -bend -bet -bite -blame -blend -block -boil -borrow -bounce -break -break -breathe -bring -build -buy -call -calm -camp -cancel -catch -challenge -change -check -chew -choose -chop -clean -climb -close -collect -comb -combine -come -complain -complete -concentrate -confuse -connect -contain -continue -control -cook -copy -correct -cost -count -cover -crawl -create -cross -cry -curl -cut -damage -dance -decide -decorate -deliver -demand -depend -describe -destroy -develop -die -dig -disappear -discover -discuss -dive -divide -do -draw -drink -drive -drop -dry -earn -eat -educate -employ -empty -encourage -enjoy -enter -escape -examine -excite -exercise -exist -expect -experience -explain -explode -explore -express -fail -fall -feed -feel -fight -fill -film -find -finish -fish -fit -fix -flow -fly -fold -follow -forget -forgive -freeze -fry -gather -get -give -glance -glow -go -grow -guess -hand -hang -happen -hate -have -hear -help -hide -hit -hold -hope -hug -hunt -hurry -hurt -imagine -improve -include -increase -inform -insist -interest -introduce -invent -invite -join -joke -jump -keep -kick -kill -kiss -kneel -knock -know -land -last -laugh -lay -lead -learn -leave -lend -let -lie -lift -light -like -listen -live -lock -look -lose -love -make -marry -matter -mean -measure -meet -mend -mention -mess -mind -miss -mix -move -name -need -nod -note -notice -obey -object -observe -obtain -offer -open -order -organize -owe -own -pack -paint -park -pass -pay -peel -pick -plant -play -point -post -pour -practice -pray -prefer -prepare -present -press -pretend -prevent -print -produce -promise -protect -prove -provide -pull -punish -push -put -quit -race -rain -raise -reach -read -realize -rebuild -receive -record -refer -reflect -refuse -regret -reject -relate -relax -release -rely -remain -remember -remind -remove -rent -repair -repeat -reply -report -require -reserve -rescue -respect -respond -rest -return -reveal -review -ride -ring -rise -risk -roast -rob -rock -roll -rule -run -save -say -search -see -seem -select -sell -send -separate -serve -set -sew -shake -share -shine -shiver -shoot -shout -show -shower -shut -sigh -sing -sit -skate -skip -sleep -slide -slip -smell -smile -smoke -snow -solve -sort -speak -spend -spill -spin -spread -stand -stare -start -stay -steal -step -stick -stop -store -strike -study -succeed -suck -suggest -suit -support -surprise -survive -swear -sweep -swim -take -talk -taste -teach -tear -tell -thank -think -throw -tidy -tie -touch -train -travel -treat -trust -try -turn -understand -use -visit -wait -wake -walk -want -warn -wash -waste -watch -wave -wear -weigh -whisper -win -wipe -wish -wonder -work -worry -wrap -write -yawn -yell diff --git a/crates/mehen-markdown/src/data/nltk_stopwords_en.txt b/crates/mehen-markdown/src/data/nltk_stopwords_en.txt deleted file mode 100644 index d0f5f665..00000000 --- a/crates/mehen-markdown/src/data/nltk_stopwords_en.txt +++ /dev/null @@ -1,184 +0,0 @@ -# NLTK English stopword list (nltk 3.8 / stopwords.english). -# Public domain — part of the Natural Language Toolkit corpus, -# distributed under the "Apache Software License" for the code and -# "public domain" for the list content (see nltk/corpus/stopwords). -# One lowercase token per line. -i -me -my -myself -we -our -ours -ourselves -you -you're -you've -you'll -you'd -your -yours -yourself -yourselves -he -him -his -himself -she -she's -her -hers -herself -it -it's -its -itself -they -them -their -theirs -themselves -what -which -who -whom -this -that -that'll -these -those -am -is -are -was -were -be -been -being -have -has -had -having -do -does -did -doing -a -an -the -and -but -if -or -because -as -until -while -of -at -by -for -with -about -against -between -into -through -during -before -after -above -below -to -from -up -down -in -out -on -off -over -under -again -further -then -once -here -there -when -where -why -how -all -any -both -each -few -more -most -other -some -such -no -nor -not -only -own -same -so -than -too -very -s -t -can -will -just -don -don't -should -should've -now -d -ll -m -o -re -ve -y -ain -aren -aren't -couldn -couldn't -didn -didn't -doesn -doesn't -hadn -hadn't -hasn -hasn't -haven -haven't -isn -isn't -ma -mightn -mightn't -mustn -mustn't -needn -needn't -shan -shan't -shouldn -shouldn't -wasn -wasn't -weren -weren't -won -won't -wouldn -wouldn't diff --git a/crates/mehen-markdown/src/data/nonwords.txt b/crates/mehen-markdown/src/data/nonwords.txt deleted file mode 100644 index 7d443f69..00000000 --- a/crates/mehen-markdown/src/data/nonwords.txt +++ /dev/null @@ -1,39 +0,0 @@ -# Non-words — words flagged as incorrect usage or malformations. -# Source: proselint / words/non-word-toxicity lists, adapted. -# Format: one lowercase entry per line. -alot -alright -agreeance -affordal -alot of -anyways -awhile -concretize -deplane -disorient -disorientate -doubleplus -everyday people -expresso -for all intensive purposes -gallent -humility -I could care less -irregardless -oftenest -orientate -preplan -preventative -re-raise -refudiate -reoccur -supposably -thusly -unthaw -withheld -anyway -anyways -funner -funnest -heighth -nimrod diff --git a/crates/mehen-markdown/src/data/passive_irregulars.txt b/crates/mehen-markdown/src/data/passive_irregulars.txt deleted file mode 100644 index d9388e33..00000000 --- a/crates/mehen-markdown/src/data/passive_irregulars.txt +++ /dev/null @@ -1,178 +0,0 @@ -# Irregular past participles used by the passive-voice detector. -# Source: write-good 1.0.8 (https://github.com/btford/write-good/blob/master/lib/passive.js) — MIT. -# One lowercase word per line. Lines starting with `#` or blank are ignored. -awoken -been -born -beat -become -begun -bent -beset -bet -bid -bidden -bound -bitten -bled -blown -broken -bred -brought -broadcast -built -burnt -burst -bought -cast -caught -chosen -clung -come -cost -crept -cut -dealt -dug -dived -done -drawn -dreamt -driven -drunk -eaten -fallen -fed -felt -fought -found -fit -fled -flung -flown -forbidden -forgotten -foregone -forgiven -forsaken -frozen -gotten -given -gone -ground -grown -hung -heard -hidden -hit -held -hurt -kept -knelt -knit -known -laid -led -leapt -learnt -left -lent -let -lain -lighted -lost -made -meant -met -misspelt -mistaken -mown -overcome -overdone -overtaken -overthrown -paid -pled -proven -put -quit -read -rid -ridden -rung -risen -run -sawn -said -seen -sought -sold -sent -set -sewn -shaken -shaven -shorn -shed -shone -shod -shot -shown -shrunk -shut -sung -sunk -sat -slept -slain -slid -slung -slit -smitten -sown -spoken -sped -spent -spilt -spun -spit -split -spread -sprung -stood -stolen -stuck -stung -stunk -stridden -struck -strung -striven -sworn -swept -swollen -swum -swung -taken -taught -torn -told -thought -thrived -thrown -thrust -trodden -understood -upheld -upset -woken -worn -woven -wed -wept -wound -won -withheld -withstood -wrung -written diff --git a/crates/mehen-markdown/src/data/weasels.txt b/crates/mehen-markdown/src/data/weasels.txt deleted file mode 100644 index 28e1aaba..00000000 --- a/crates/mehen-markdown/src/data/weasels.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Weasel words — vague intensifiers / quantifiers. -# Source: write-good (https://github.com/btford/write-good/blob/master/lib/weasel.js) — MIT. -# One lowercase entry per line. -are a number -clearly -completely -exceedingly -excellent -extremely -fairly -few -huge -interestingly -largely -many -mostly -obviously -quite -relatively -remarkably -several -significantly -substantially -surprisingly -tiny -various -vast -very -a number of -lots of -lots -a lot of -a bunch of -sort of -a bit -a lot -bunch diff --git a/crates/mehen-markdown/src/data/wordy_phrases.txt b/crates/mehen-markdown/src/data/wordy_phrases.txt deleted file mode 100644 index 944d0012..00000000 --- a/crates/mehen-markdown/src/data/wordy_phrases.txt +++ /dev/null @@ -1,313 +0,0 @@ -# Wordy phrases — verbose constructions with simpler alternatives. -# Source: retext-simplify (https://github.com/retextjs/retext-simplify) MIT, -# condensed to the phrase list; simpler alternative in comment (not used at runtime). -# Format: one lowercase phrase per line. -a number of -a small number of -a variety of -absolutely essential -absolutely necessary -accounted for by the fact that -accordingly -actual fact -adjacent to -advance planning -all of -all of a sudden -along the lines of -an appreciable amount of -an appreciable number of -an example of this is the fact that -an order of magnitude -any and all -are in agreement -are of the same opinion -as a consequence of -as a matter of fact -as a means of -as is the case -as of this date -as per -as regards -as the case may be -as to -as yet -ascertain -at a later date -at all times -at an earlier date -at first glance -at present -at the conclusion of -at the present time -at this moment in time -at this point in time -at this time -attach together -authored -based on the fact that -based on the premise that -because of the fact that -be an indication of -be benefited by -be cognizant of -be responsible for -be that as it may -beg to differ -being as -both of them -boyfriend -bring to a conclusion -buy up -by a factor of two -by means of -by the same token -by virtue of -by virtue of the fact that -by way of -called attention to the fact that -cease and desist -close proximity -commence -communicate -completely opposite -concerning the matter of -conduct an investigation -considered to be -consists of -continue on -costs the sum of -could possibly -currently -definitely decided -demonstrate -despite the fact that -did not succeed -due to the fact that -during the course of -during the time that -each and every one -each individual -effected -end result -endeavor -enter into a dialogue -equally as -established the fact that -estimated at about -eventuate -exhibit a tendency to -facilitate -factor -fatally killed -few in number -final outcome -finalize -first and foremost -first of all -for a short space of time -for the purpose of -for the reason that -from the point of view of -give rise to -given the fact that -have the ability to -has a requirement for -he is a man who -honest truth -if and when -if conditions are such that -impact -important essentials -in a hasty manner -in a position to -in a timely manner -in advance of -in an uncertain manner -in attendance -in close proximity -in conjunction with -in connection with -in excess of -in lieu of -in light of the fact that -in many cases -in my opinion -in order to -in regard to -in relation to -in respect to -in spite of the fact that -in terms of -in the absence of -in the amount of -in the course of -in the end -in the event that -in the final analysis -in the immediate vicinity of -in the majority of cases -in the nature of -in the near future -in the neighborhood of -in the process of -in the vicinity of -in view of -in view of the fact that -inasmuch as -inquire -is able to -is applicable to -is aware of the fact that -is in the process of -is of the opinion that -is required to -is undertaking to -it is -it is believed that -it is clear that -it is essential that -it is evident that -it is highly recommended -it is imperative that -it is incumbent upon -it is interesting that -it is necessary that -it is obvious that -it is often the case that -it is possible -it is possible that -it is recommended that -it is vital that -it is worth mentioning -last but not least -later on -like for example -liquidate -majority of -make adjustments to -make an application to -make inquiries about -many of the -may have been -modify -most likely -moreover -needless to say -not merely -notwithstanding the fact that -of an indefinite nature -of the opinion that -offer a suggestion -on a daily basis -on account of -on behalf of -on numerous occasions -on the basis of -on the grounds that -on the occasion of -on the part of -once in a great while -one of the -one of the reasons -outside of -owing to the fact that -owing to the fact -partake -past history -past memories -perhaps a few -personally i believe -pertaining to -plan ahead -plan in advance -plethora -point in time -possibility exists -pre-planned -pre-heat -presently -previous to -prior to -provide a response to -provided that -put the emphasis on -quite a few -quite unique -reach a conclusion -refer back -relating to -relative to -remuneration -render inoperative -residence -respecting -resultant effect -return back -said -serious crisis -serves the function of being -shall -should you wish -similar to -since there is no other -small in size -so as to -so consequently -still persists -strike action -subsequent to -sufficient number of -take into consideration -take action -take under consideration -terminate -that being said -the fact of the matter is -the fact that -the majority of -the reason being -the reason for -the reason is because -the reason that -the vast majority of -there are -there is -thereafter -therefore -this is -this point in time -through the use of -thus -to be perfectly honest -to my mind -to speak -together with -tomorrow -totality of -true facts -ultimately -under the provisions of -utilize -utilization -various different -very unique -vis-à-vis -vis-a-vis -want for -was a person who -was able to -was in the process of -we are of the opinion that -whether or not -while -whilst -with reference to -with regard to -with respect to -with the exception of -with the possible exception of -with the purpose of -with the result that -within the realm of possibility -yet to come diff --git a/crates/mehen-markdown/src/diagrams/mermaid.rs b/crates/mehen-markdown/src/diagrams/mermaid.rs deleted file mode 100644 index f965297a..00000000 --- a/crates/mehen-markdown/src/diagrams/mermaid.rs +++ /dev/null @@ -1,388 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Line-based Mermaid parser covering `graph`, `flowchart`, `stateDiagram`, -//! and `sequenceDiagram` shapes. This is intentionally narrow: §12.2 only -//! needs node/edge/connected-component/cycle counts, not semantic fidelity. -//! -//! Supported shapes (sufficient for §12.2): -//! -//! - `graph ` / `flowchart ` — ASCII DAGs. -//! - `stateDiagram-v2` — states and transitions. -//! - `sequenceDiagram` — participants and interactions. -//! - Basic `classDiagram`, `erDiagram`, `journey`, `gantt` are treated as -//! unknown subgraphs but still parse cleanly. - -use std::collections::BTreeSet; - -use super::DiagramSignal; - -pub fn parse(body: &str) -> DiagramSignal { - let mut nodes: BTreeSet = BTreeSet::new(); - let mut edges: Vec<(String, String)> = Vec::new(); - let mut has_title = false; - let mut saw_header = false; - let mut kind = DiagramKind::Unknown; - - for raw in body.lines() { - let line = strip_mermaid_comment(raw); - let trimmed = line.trim(); - if trimmed.is_empty() { - continue; - } - - // Title lines (`title My Diagram`) anywhere count as labels. - if trimmed.starts_with("title ") || trimmed.starts_with("title:") { - has_title = true; - continue; - } - if trimmed.starts_with("%%") { - continue; - } - - if !saw_header && let Some(k) = detect_header(trimmed) { - kind = k; - saw_header = true; - continue; - } - - match kind { - DiagramKind::Graph => parse_graph_line(trimmed, &mut nodes, &mut edges), - DiagramKind::State => parse_state_line(trimmed, &mut nodes, &mut edges), - DiagramKind::Sequence => parse_sequence_line(trimmed, &mut nodes, &mut edges), - DiagramKind::ClassOrEr => parse_class_line(trimmed, &mut nodes, &mut edges), - DiagramKind::Unknown => { - // Fallback: if there's a `-->` / `->` edge on the line, still - // pick it up so generic mermaid flavors don't silently zero. - parse_graph_line(trimmed, &mut nodes, &mut edges); - } - } - } - - // Cycles per §12.2: max(0, E - N + P) - let components = super::connected_components(&nodes, &edges); - let n = nodes.len() as i64; - let e = edges.len() as i64; - let p = components as i64; - let cycles_i = e - n + p; - let cycles = if cycles_i > 0 { cycles_i as u64 } else { 0 }; - - DiagramSignal { - nodes: nodes.len() as u64, - edges: edges.len() as u64, - components, - cycles, - parse_error: false, - has_title, - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum DiagramKind { - Graph, - State, - Sequence, - ClassOrEr, - Unknown, -} - -fn detect_header(s: &str) -> Option { - let first = s.split_whitespace().next().unwrap_or(""); - match first { - "graph" | "flowchart" => Some(DiagramKind::Graph), - "stateDiagram" | "stateDiagram-v2" => Some(DiagramKind::State), - "sequenceDiagram" => Some(DiagramKind::Sequence), - "classDiagram" | "erDiagram" => Some(DiagramKind::ClassOrEr), - _ => None, - } -} - -fn strip_mermaid_comment(line: &str) -> &str { - if let Some(idx) = line.find("%%") { - &line[..idx] - } else { - line - } -} - -fn parse_graph_line(line: &str, nodes: &mut BTreeSet, edges: &mut Vec<(String, String)>) { - // Split the line on any recognized mermaid edge terminator. We walk from - // left to right, extracting a node reference, then consuming the edge - // tokens (with optional `|label|` or `-- text --` body) that follow. - let mut rest = line.trim(); - let Some((first_id, after_first)) = extract_node_ref(rest) else { - return; - }; - rest = after_first.trim(); - let mut last = first_id; - nodes.insert(last.clone()); - - while let Some(remainder) = consume_edge(rest) { - let Some((next_id, after_next)) = extract_node_ref(remainder.trim_start()) else { - break; - }; - nodes.insert(next_id.clone()); - edges.push((last.clone(), next_id.clone())); - last = next_id; - rest = after_next.trim(); - } -} - -/// Consumes the edge tokens starting at `input` — including optional -/// `|label|` or `-- text --` annotations — and returns the remainder of -/// the string after the trailing arrow. Returns `None` if `input` does -/// not begin with an edge. -fn consume_edge(input: &str) -> Option<&str> { - let s = input.trim_start(); - if s.is_empty() { - return None; - } - let first = s.as_bytes()[0]; - if !matches!(first, b'-' | b'=' | b'<' | b'~' | b'.') { - return None; - } - // Scan through the edge prefix: any run of `-`, `=`, `<`, `>`, `.`, `~`. - // Then optionally skip `|…|` OR `identifier text -->` segment. - let mut idx = 0; - while idx < s.len() && matches!(s.as_bytes()[idx], b'-' | b'=' | b'<' | b'>' | b'.' | b'~') { - idx += 1; - } - let arrow_head = &s[..idx]; - let mut after = &s[idx..]; - // Must have seen at least one `>`-style termination OR a bare `--`/`==` - // edge on this pass. We accept any arrow-like shape that contains at - // least one `-` or `=` — the flexibility is deliberate because Phase C - // needs approximate counts, not exact mermaid validation. - if !arrow_head.contains('-') && !arrow_head.contains('=') { - return None; - } - // Optional `|label|`. - if after.starts_with('|') - && let Some(close) = after[1..].find('|') - { - after = &after[close + 2..]; - } - // Optional `-- text --` middle segment: if what follows is a word and - // then another arrow, consume through that arrow. - let bytes = after.as_bytes(); - if !bytes.is_empty() && !bytes[0].is_ascii_alphanumeric() { - return Some(after); - } - // Look for a trailing arrow later on the line. If there is one, treat - // the intervening characters as a label. - if let Some(next_arrow) = find_next_arrow(after) { - return Some(&after[next_arrow..]); - } - Some(after) -} - -fn find_next_arrow(s: &str) -> Option { - // Look for `-->`, `==>`, `->`, `-.->`, `--o`, etc. Return the byte index - // of the character AFTER the arrow. - for pat in ["-->|", "-->", "==>|", "==>", "-.->", "-->o", "--o", "->"] { - if let Some(idx) = s.find(pat) { - let end = idx + pat.len(); - // If the arrow was `-->|` we still need to skip the `label|`. - if pat.ends_with('|') - && let Some(close) = s[end..].find('|') - { - return Some(end + close + 1); - } - return Some(end); - } - } - None -} - -fn extract_node_ref(input: &str) -> Option<(String, &str)> { - let s = input.trim_start(); - if s.is_empty() { - return None; - } - let bytes = s.as_bytes(); - // Identifier starts with alnum / underscore. - if !bytes[0].is_ascii_alphanumeric() && bytes[0] != b'_' { - return None; - } - let mut end = 0; - while end < bytes.len() && (bytes[end].is_ascii_alphanumeric() || bytes[end] == b'_') { - end += 1; - } - let id = s[..end].to_string(); - // Skip an optional shape suffix `[label]`, `(label)`, `{label}`, `>label]`. - let mut rest = &s[end..]; - for (open, close) in [('[', ']'), ('(', ')'), ('{', '}')] { - if rest.starts_with(open) - && let Some(idx) = rest.find(close) - { - rest = &rest[idx + 1..]; - break; - } - } - Some((id, rest)) -} - -fn parse_state_line(line: &str, nodes: &mut BTreeSet, edges: &mut Vec<(String, String)>) { - // `A --> B`, `A --> B : event`, `[*] --> B`. - if let Some((lhs, rhs)) = line.split_once("-->") { - let l = clean_state_id(lhs); - let r = rhs.split(':').next().unwrap_or(""); - let r = clean_state_id(r); - if !l.is_empty() { - nodes.insert(l.clone()); - } - if !r.is_empty() { - nodes.insert(r.clone()); - } - if !l.is_empty() && !r.is_empty() { - edges.push((l, r)); - } - } else { - let id = clean_state_id(line); - if !id.is_empty() { - nodes.insert(id); - } - } -} - -fn clean_state_id(s: &str) -> String { - let s = s.trim(); - if s == "[*]" { - return "__START_OR_END__".to_string(); - } - s.chars() - .take_while(|c| c.is_ascii_alphanumeric() || *c == '_') - .collect() -} - -fn parse_sequence_line( - line: &str, - nodes: &mut BTreeSet, - edges: &mut Vec<(String, String)>, -) { - // `participant Alice` - if let Some(name) = line.strip_prefix("participant ") { - let id = sequence_actor(name); - if !id.is_empty() { - nodes.insert(id); - } - return; - } - if let Some(name) = line.strip_prefix("actor ") { - let id = sequence_actor(name); - if !id.is_empty() { - nodes.insert(id); - } - return; - } - // `A->>B: msg`, `A->B`, `A-->>B`, `A-)B`, etc. - const ARROWS: &[&str] = &["->>", "-->>", "-)", "-x", "--x", "--)", "->", "-->"]; - for arrow in ARROWS { - if let Some(idx) = line.find(arrow) { - let lhs = sequence_actor(&line[..idx]); - let rest = &line[idx + arrow.len()..]; - let rhs = sequence_actor(rest.split(':').next().unwrap_or("")); - if !lhs.is_empty() { - nodes.insert(lhs.clone()); - } - if !rhs.is_empty() { - nodes.insert(rhs.clone()); - } - if !lhs.is_empty() && !rhs.is_empty() { - edges.push((lhs, rhs)); - } - return; - } - } -} - -fn sequence_actor(s: &str) -> String { - s.trim() - .chars() - .take_while(|c| c.is_ascii_alphanumeric() || *c == '_') - .collect() -} - -fn parse_class_line(line: &str, nodes: &mut BTreeSet, edges: &mut Vec<(String, String)>) { - // `class Foo`, `Foo <|-- Bar`, `Foo : +method()`. - if let Some(name) = line.strip_prefix("class ") { - let id = class_ident(name); - if !id.is_empty() { - nodes.insert(id); - } - return; - } - const RELATIONS: &[&str] = &[ - "<|--", "--|>", "*--", "--*", "o--", "--o", "<--", "-->", "..|>", "<|..", "..", "--", - ]; - for rel in RELATIONS { - if let Some(idx) = line.find(rel) { - let lhs = class_ident(&line[..idx]); - let rhs = class_ident(&line[idx + rel.len()..]); - if !lhs.is_empty() { - nodes.insert(lhs.clone()); - } - if !rhs.is_empty() { - nodes.insert(rhs.clone()); - } - if !lhs.is_empty() && !rhs.is_empty() { - edges.push((lhs, rhs)); - } - return; - } - } - let id = class_ident(line); - if !id.is_empty() { - nodes.insert(id); - } -} - -fn class_ident(s: &str) -> String { - s.trim() - .chars() - .take_while(|c| c.is_ascii_alphanumeric() || *c == '_') - .collect() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn graph_td_two_nodes_two_edges_one_cycle() { - let src = "graph TD\n A --> B\n B --> A\n"; - let sig = parse(src); - assert_eq!(sig.nodes, 2); - assert_eq!(sig.edges, 2); - assert_eq!(sig.components, 1); - assert_eq!(sig.cycles, 1); - assert!(!sig.parse_error); - } - - #[test] - fn graph_td_linear() { - let src = "graph TD\n A --> B --> C\n"; - let sig = parse(src); - assert_eq!(sig.nodes, 3); - assert_eq!(sig.edges, 2); - assert_eq!(sig.components, 1); - assert_eq!(sig.cycles, 0); - } - - #[test] - fn sequence_participants_counted() { - let src = "sequenceDiagram\n participant Alice\n participant Bob\n Alice->>Bob: hi\n"; - let sig = parse(src); - assert_eq!(sig.nodes, 2); - assert_eq!(sig.edges, 1); - } - - #[test] - fn state_diagram_counts_transitions() { - let src = "stateDiagram-v2\n [*] --> Idle\n Idle --> Running\n Running --> Idle\n"; - let sig = parse(src); - // States: __START_OR_END__, Idle, Running = 3 nodes. - assert_eq!(sig.nodes, 3); - assert_eq!(sig.edges, 3); - } -} diff --git a/crates/mehen-markdown/src/diagrams/mod.rs b/crates/mehen-markdown/src/diagrams/mod.rs deleted file mode 100644 index aed5367a..00000000 --- a/crates/mehen-markdown/src/diagrams/mod.rs +++ /dev/null @@ -1,277 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Native diagram parsers used by §12.2 Diagram Complexity. -//! -//! Mermaid is parsed structurally (nodes, edges, connected components, -//! cycles). PlantUML, DOT, D2, and Vega-Lite fall back to a token-proxy -//! metric that counts identifier-looking lines as nodes — enough to size -//! the diagram for §12.2 without dragging in a full parser. - -pub mod mermaid; - -/// Parsed diagram signals consumed by §12.2 and the artifact-debt pipeline. -#[derive(Debug, Default, Clone)] -pub struct DiagramSignal { - pub nodes: u64, - pub edges: u64, - pub components: u64, - pub cycles: u64, - pub parse_error: bool, - pub has_title: bool, -} - -/// Parse `body` as `language`. Returns a best-effort [`DiagramSignal`]. -/// Unknown languages return `parse_error = true` with zeroed counts so the -/// per-diagram burden still gets the +2.0 parse-error term from §12.2. -pub fn parse_diagram(language: &str, body: &str) -> DiagramSignal { - let lang = language.to_lowercase(); - match lang.as_str() { - "mermaid" => mermaid::parse(body), - "plantuml" | "puml" => parse_plantuml(body), - "dot" | "graphviz" => parse_dot(body), - "d2" => parse_d2(body), - "vega-lite" | "vegalite" | "vl" | "vega" => parse_vega_like(body), - _ => DiagramSignal { - parse_error: true, - ..DiagramSignal::default() - }, - } -} - -/// PlantUML proxy: count identifiers on the LHS of `:`/`-->`/`->`/`<--`/`<-`. -/// Titles come from leading `title` / `@startuml title`. -fn parse_plantuml(body: &str) -> DiagramSignal { - let mut nodes: std::collections::BTreeSet = Default::default(); - let mut edges: u64 = 0; - let mut has_title = false; - - for raw in body.lines() { - let line = raw.trim(); - if line.is_empty() - || line.starts_with('\'') - || line.starts_with("/'") - || line.starts_with("@startuml") - || line.starts_with("@enduml") - || line.starts_with("skinparam") - { - if line.starts_with("@startuml ") || line.starts_with("title ") { - has_title = true; - } - continue; - } - if line.starts_with("title ") { - has_title = true; - continue; - } - for (lhs, rhs) in split_edge(line) { - if let Some(n) = ident(lhs) { - nodes.insert(n); - } - if let Some(n) = ident(rhs) { - nodes.insert(n); - } - edges += 1; - } - if !contains_edge(line) - && let Some(n) = ident(line) - { - nodes.insert(n); - } - } - - let components = connected_components(&nodes, &[]); - DiagramSignal { - nodes: nodes.len() as u64, - edges, - components, - cycles: 0, - parse_error: false, - has_title, - } -} - -/// DOT / Graphviz proxy. Same technique as plantuml but with `->` / `--`. -fn parse_dot(body: &str) -> DiagramSignal { - let mut nodes: std::collections::BTreeSet = Default::default(); - let mut edges: u64 = 0; - let mut has_title = false; - for raw in body.lines() { - let line = raw.trim().trim_end_matches(';'); - if line.is_empty() - || line.starts_with("//") - || line.starts_with('#') - || line.starts_with("digraph") - || line.starts_with("graph ") - || line == "}" - || line == "{" - { - if line.contains("label=") { - has_title = true; - } - continue; - } - for (lhs, rhs) in split_edge(line) { - if let Some(n) = ident(lhs) { - nodes.insert(n); - } - if let Some(n) = ident(rhs) { - nodes.insert(n); - } - edges += 1; - } - if !contains_edge(line) - && let Some(n) = ident(line) - { - nodes.insert(n); - } - } - let components = connected_components(&nodes, &[]); - DiagramSignal { - nodes: nodes.len() as u64, - edges, - components, - cycles: 0, - parse_error: false, - has_title, - } -} - -/// D2 proxy: `a -> b`, `a <-> b`, `a: label`. -fn parse_d2(body: &str) -> DiagramSignal { - let mut nodes: std::collections::BTreeSet = Default::default(); - let mut edges: u64 = 0; - let mut has_title = false; - for raw in body.lines() { - let line = raw.trim(); - if line.is_empty() || line.starts_with('#') { - continue; - } - if line.starts_with("title:") { - has_title = true; - continue; - } - for (lhs, rhs) in split_edge(line) { - if let Some(n) = ident(lhs) { - nodes.insert(n); - } - if let Some(n) = ident(rhs) { - nodes.insert(n); - } - edges += 1; - } - if !contains_edge(line) - && let Some((lhs, _)) = line.split_once(':') - && let Some(n) = ident(lhs) - { - nodes.insert(n); - } - } - let components = connected_components(&nodes, &[]); - DiagramSignal { - nodes: nodes.len() as u64, - edges, - components, - cycles: 0, - parse_error: false, - has_title, - } -} - -/// Vega-Lite proxy: count top-level `marks`, `encoding`, `data` objects as -/// nodes. This is far too crude to be semantically accurate but suffices as -/// a size-proxy for §12.2. -fn parse_vega_like(body: &str) -> DiagramSignal { - let mut nodes: u64 = 0; - let mut has_title = false; - for raw in body.lines() { - let line = raw.trim(); - if line.starts_with("\"title\"") { - has_title = true; - } - if line.ends_with('{') || line.ends_with('[') { - nodes += 1; - } - } - DiagramSignal { - nodes, - edges: 0, - components: if nodes == 0 { 0 } else { 1 }, - cycles: 0, - parse_error: false, - has_title, - } -} - -fn split_edge(line: &str) -> Vec<(&str, &str)> { - let seps = ["-->", "<--", "->", "<-", "==>", "<==", "---", "==="]; - for sep in seps { - if let Some(idx) = line.find(sep) { - let lhs = &line[..idx]; - let rhs = &line[idx + sep.len()..]; - return vec![(lhs.trim(), rhs.trim())]; - } - } - Vec::new() -} - -fn contains_edge(line: &str) -> bool { - ["-->", "<--", "->", "<-", "==>", "<==", "---", "==="] - .iter() - .any(|s| line.contains(s)) -} - -fn ident(s: &str) -> Option { - let trimmed = s.trim(); - if trimmed.is_empty() { - return None; - } - // Strip brackets, pipes, and trailing labels. - let stripped: String = trimmed - .chars() - .take_while(|c| c.is_ascii_alphanumeric() || *c == '_' || *c == '-') - .collect(); - if stripped.is_empty() { - None - } else { - Some(stripped) - } -} - -pub fn connected_components( - nodes: &std::collections::BTreeSet, - edges: &[(String, String)], -) -> u64 { - if nodes.is_empty() { - return 0; - } - let mut parent: std::collections::BTreeMap = - nodes.iter().map(|n| (n.clone(), n.clone())).collect(); - fn find(parent: &mut std::collections::BTreeMap, x: &str) -> String { - let p = parent.get(x).cloned().unwrap_or_else(|| x.to_string()); - if p == x { - p - } else { - let root = find(parent, &p); - parent.insert(x.to_string(), root.clone()); - root - } - } - for (a, b) in edges { - if !parent.contains_key(a) { - parent.insert(a.clone(), a.clone()); - } - if !parent.contains_key(b) { - parent.insert(b.clone(), b.clone()); - } - let ra = find(&mut parent, a); - let rb = find(&mut parent, b); - if ra != rb { - parent.insert(ra, rb); - } - } - let mut scratch = parent.clone(); - let roots: std::collections::BTreeSet = - parent.keys().map(|k| find(&mut scratch, k)).collect(); - roots.len() as u64 -} diff --git a/crates/mehen-markdown/src/dmi.rs b/crates/mehen-markdown/src/dmi.rs deleted file mode 100644 index 00f436dc..00000000 --- a/crates/mehen-markdown/src/dmi.rs +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Documentation Maintainability Index (DMI) per §10. -//! -//! After Phase D ships, every §10.1 term is wired: -//! -//! ```text -//! V_norm = sat(ln(1 + MDH_volume_total); 8, 15) -//! M_norm = sat(MCC; 15, 80) -//! R_norm = sat(MRPC; 8, 40) -//! L_norm = LinkDebtScore (Phase C) -//! T_norm = TableBurdenScore (Phase C) -//! A_norm = ArtifactDebtScore (Phase C) -//! S_norm = 1 - SectionBalanceScore (Phase D) -//! F_norm = FillerLazyRisk (Phase D) -//! G_norm = GoodScaffoldScore (Phase D) -//! ``` -//! -//! Final formula §10.2: -//! -//! ```text -//! DMI = clamp01( -//! 1 -//! - 0.18 * V_norm -//! - 0.18 * M_norm -//! - 0.10 * R_norm -//! - 0.16 * L_norm -//! - 0.10 * T_norm -//! - 0.10 * A_norm -//! - 0.10 * S_norm -//! - 0.12 * F_norm -//! + 0.10 * G_norm -//! ) * 100 -//! ``` - -/// Inputs to §10.2's formula. -#[derive(Debug, Clone, Copy, Default)] -pub(crate) struct DmiInputs { - /// Phase-B: MRPC weighted value (§7.3). - pub(crate) mrpc: f64, - /// Phase-B: MCC final value (§8.4). - pub(crate) mcc: f64, - /// Phase-B: Markdown Halstead total volume including §9.4 embedded term. - pub(crate) total_volume: f64, - /// Phase-C: `links.link_debt_score` (§11.2). - pub(crate) link_debt_score: f64, - /// Phase-C: `tables.table_burden_score` (§13.3). - pub(crate) table_burden_score: f64, - /// Phase-C: `maintainability.artifact_debt_score` (§19). - pub(crate) artifact_debt_score: f64, - /// Phase-D: `1 - maintainability.section_balance_score` (§20). - pub(crate) section_imbalance: f64, - /// Phase-D: `ai_era.filler_lazy_structure_risk` (§17). - pub(crate) filler_lazy_risk: f64, - /// Phase-D: `maintainability.good_scaffold_score` (§21). - pub(crate) good_scaffold_score: f64, -} - -/// Computes the DMI value on the `[0, 100]` scale. -pub(crate) fn compute_dmi(inputs: DmiInputs) -> f64 { - let v_norm = saturate(ln_1p(inputs.total_volume), 8.0, 15.0); - let m_norm = saturate(inputs.mcc, 15.0, 80.0); - let r_norm = saturate(inputs.mrpc, 8.0, 40.0); - - let l_norm = inputs.link_debt_score.clamp(0.0, 1.0); - let t_norm = inputs.table_burden_score.clamp(0.0, 1.0); - let a_norm = inputs.artifact_debt_score.clamp(0.0, 1.0); - let s_norm = inputs.section_imbalance.clamp(0.0, 1.0); - let f_norm = inputs.filler_lazy_risk.clamp(0.0, 1.0); - let g_norm = inputs.good_scaffold_score.clamp(0.0, 1.0); - - let raw = 1.0 - - 0.18 * v_norm - - 0.18 * m_norm - - 0.10 * r_norm - - 0.16 * l_norm - - 0.10 * t_norm - - 0.10 * a_norm - - 0.10 * s_norm - - 0.12 * f_norm - + 0.10 * g_norm; - raw.clamp(0.0, 1.0) * 100.0 -} - -fn saturate(x: f64, lo: f64, hi: f64) -> f64 { - if !x.is_finite() || hi <= lo { - return 0.0; - } - ((x - lo) / (hi - lo)).clamp(0.0, 1.0) -} - -fn ln_1p(x: f64) -> f64 { - if x <= 0.0 { - return 0.0; - } - x.ln_1p() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn zero_inputs_produce_perfect_dmi() { - let dmi = compute_dmi(DmiInputs::default()); - assert_eq!(dmi, 100.0); - } - - #[test] - fn extreme_inputs_clamp_to_zero() { - let dmi = compute_dmi(DmiInputs { - mrpc: 1000.0, - mcc: 1000.0, - total_volume: 1e18, - link_debt_score: 1.0, - table_burden_score: 1.0, - artifact_debt_score: 1.0, - section_imbalance: 1.0, - filler_lazy_risk: 1.0, - good_scaffold_score: 0.0, - }); - // Sum of negative coefficients: 0.18+0.18+0.10+0.16+0.10+0.10+0.10+0.12 = 1.04. - // 1.0 - 1.04 = -0.04 → clamped to 0. × 100 = 0. - assert_eq!(dmi, 0.0); - } - - #[test] - fn good_scaffold_offsets_moderate_penalties() { - let penalized = compute_dmi(DmiInputs { - mrpc: 8.0, - mcc: 15.0, - total_volume: 0.0, - link_debt_score: 0.5, - table_burden_score: 0.0, - artifact_debt_score: 0.0, - section_imbalance: 0.0, - filler_lazy_risk: 0.0, - good_scaffold_score: 0.0, - }); - let rewarded = compute_dmi(DmiInputs { - mrpc: 8.0, - mcc: 15.0, - total_volume: 0.0, - link_debt_score: 0.5, - table_burden_score: 0.0, - artifact_debt_score: 0.0, - section_imbalance: 0.0, - filler_lazy_risk: 0.0, - good_scaffold_score: 1.0, - }); - assert!(rewarded > penalized, "scaffold should offset"); - } - - #[test] - fn intermediate_values_behave_monotonically() { - let low = compute_dmi(DmiInputs { - mrpc: 5.0, - mcc: 5.0, - total_volume: 10.0, - ..DmiInputs::default() - }); - let high = compute_dmi(DmiInputs { - mrpc: 30.0, - mcc: 50.0, - total_volume: 10_000.0, - link_debt_score: 0.8, - table_burden_score: 0.5, - artifact_debt_score: 0.7, - section_imbalance: 0.4, - filler_lazy_risk: 0.5, - good_scaffold_score: 0.0, - }); - assert!(low > high, "low={low}, high={high}"); - } -} diff --git a/crates/mehen-markdown/src/document.rs b/crates/mehen-markdown/src/document.rs deleted file mode 100644 index 301ea48d..00000000 --- a/crates/mehen-markdown/src/document.rs +++ /dev/null @@ -1,1080 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Pulldown-cmark backed Markdown document facts. -//! -//! Metric passes that need Markdown semantics should consume this module -//! directly instead of reconstructing those semantics from structural node -//! walks. Cursor-style passes can still use the compact structural tree for -//! nested spans, while links, anchors, reference definitions, footnotes, and -//! code blocks stay native pulldown data here. - -use std::collections::HashMap; -use std::ops::Range; - -use pulldown_cmark::{ - BrokenLink, CodeBlockKind as PulldownCodeBlockKind, CowStr, Event, HeadingLevel, LinkType, - Options, Parser, Tag, TagEnd, -}; - -use crate::source_text::normalize_line_endings; - -#[derive(Debug)] -pub(crate) struct MarkdownDocument { - pub(crate) headings: Vec, - pub(crate) links: Vec, - pub(crate) reference_definitions: Vec, - pub(crate) footnote_references: Vec, - pub(crate) footnote_definitions: Vec, - pub(crate) code_blocks: Vec, - code_block_start_lines: HashMap, - link_spans: HashMap<(usize, usize), usize>, -} - -#[derive(Debug)] -pub(crate) struct Heading { - pub(crate) text: String, -} - -#[derive(Debug)] -pub(crate) struct LinkUse { - pub(crate) line: u64, - pub(crate) kind: LinkUseKind, - pub(crate) destination: String, - pub(crate) reference_label: Option, - pub(crate) text: String, - pub(crate) is_image: bool, - span: Range, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(crate) enum LinkUseKind { - Inline, - Reference, - ReferenceUnknown, - Collapsed, - CollapsedUnknown, - Shortcut, - ShortcutUnknown, - Autolink, - Email, - WikiLink, -} - -impl LinkUseKind { - pub(crate) fn is_reference_style(self) -> bool { - matches!( - self, - Self::Reference - | Self::ReferenceUnknown - | Self::Collapsed - | Self::CollapsedUnknown - | Self::Shortcut - | Self::ShortcutUnknown - ) - } -} - -#[derive(Clone, Debug)] -pub(crate) struct ReferenceDefinition { - pub(crate) line: u64, - pub(crate) label: String, - pub(crate) destination: String, - pub(crate) span: Range, - pub(crate) label_span: Range, - pub(crate) destination_span: Range, - pub(crate) title_span: Option>, -} - -#[derive(Debug)] -pub(crate) struct FootnoteReference { - pub(crate) line: u64, - pub(crate) label: String, -} - -#[derive(Debug)] -pub(crate) struct FootnoteDefinition { - pub(crate) label: String, -} - -#[derive(Debug)] -pub(crate) struct CodeBlock { - pub(crate) kind: CodeBlockKind, - pub(crate) start_line: u64, - pub(crate) end_line: u64, - pub(crate) language: Option, - pub(crate) content: String, -} - -impl CodeBlock { - pub(crate) fn is_fenced(&self) -> bool { - self.kind == CodeBlockKind::Fenced - } - - pub(crate) fn content_line_count(&self) -> usize { - self.content.lines().count() - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(crate) enum CodeBlockKind { - Fenced, - Indented, -} - -#[cfg(test)] -pub(crate) fn parse_document(source: &str) -> MarkdownDocument { - let reference_definitions = reference_definitions_from_source(source); - let mut builder = DocumentBuilder::new(source, reference_definitions); - let parser = Parser::new_with_broken_link_callback( - source, - markdown_options(), - Some(preserve_broken_reference_link), - ); - let offset_iter = parser.into_offset_iter(); - - for (event, range) in offset_iter { - builder.handle_event(event, range); - } - - builder.finish() -} - -pub(crate) fn markdown_options() -> Options { - Options::ENABLE_TABLES - | Options::ENABLE_FOOTNOTES - | Options::ENABLE_STRIKETHROUGH - | Options::ENABLE_TASKLISTS - | Options::ENABLE_YAML_STYLE_METADATA_BLOCKS - | Options::ENABLE_PLUSES_DELIMITED_METADATA_BLOCKS - | Options::ENABLE_MATH - | Options::ENABLE_GFM - | Options::ENABLE_WIKILINKS -} - -pub(crate) fn preserve_broken_reference_link<'a>( - _link: BrokenLink<'a>, -) -> Option<(CowStr<'a>, CowStr<'a>)> { - Some(("".into(), "".into())) -} - -pub(crate) fn line_starts(source: &str) -> Vec { - let mut out = vec![0]; - for (idx, byte) in source.bytes().enumerate() { - if byte == b'\n' { - out.push(idx + 1); - } - } - out -} - -pub(crate) fn row_at(line_starts: &[usize], source_len: usize, byte: usize) -> usize { - let byte = byte.min(source_len); - match line_starts.binary_search(&byte) { - Ok(row) => row, - Err(0) => 0, - Err(row) => row - 1, - } -} - -pub(crate) fn normalize_reference_label(label: &str) -> String { - label - .split_whitespace() - .collect::>() - .join(" ") - .to_lowercase() -} - -pub(crate) fn code_language(info: &str) -> Option { - let head = info - .split(|c: char| c.is_whitespace() || c == ',' || c == '{') - .next() - .unwrap_or("") - .trim(); - (!head.is_empty()).then(|| head.to_ascii_lowercase()) -} - -pub(crate) fn is_diagram_language(lang: &str) -> bool { - matches!( - lang, - "mermaid" - | "plantuml" - | "puml" - | "dot" - | "graphviz" - | "d2" - | "vega-lite" - | "vegalite" - | "vl" - | "vega" - ) -} - -pub(crate) fn reference_definitions_from_source(source: &str) -> Vec { - let line_starts = line_starts(source); - let source_blocks = SourceBlockSpans::collect(source); - let mut definitions = Vec::new(); - let mut cursor = 0; - - while cursor < source.len() { - let line = next_line_range(source, cursor); - let line_without_eol = trim_line_ending(source, line.clone()); - let Some(content_start) = definition_content_start(source, &line_without_eol) else { - cursor = line.end; - continue; - }; - - if source_blocks.suppresses_reference_definition(content_start) { - cursor = line.end; - continue; - } - - if let Some(definition) = - parse_reference_definition_at(source, line.start, content_start, &line_starts) - { - cursor = next_line_start_after(source, definition.span.end); - definitions.push(definition); - } else { - cursor = line.end; - } - } - - definitions -} - -#[derive(Default)] -struct SourceBlockSpans { - code_or_html: Vec>, - paragraphs: Vec>, -} - -impl SourceBlockSpans { - fn collect(source: &str) -> Self { - let mut spans = SourceBlockSpans::default(); - let mut paragraph: Option> = None; - let mut code_block: Option> = None; - let mut html_block: Option> = None; - - let parser = Parser::new_with_broken_link_callback( - source, - markdown_options(), - Some(preserve_broken_reference_link), - ); - - for (event, range) in parser.into_offset_iter() { - match event { - Event::Start(Tag::Paragraph) => paragraph = Some(range), - Event::End(TagEnd::Paragraph) => { - push_open_span(&mut spans.paragraphs, paragraph.take(), range) - } - Event::Start(Tag::CodeBlock(_)) => code_block = Some(range), - Event::End(TagEnd::CodeBlock) => { - push_open_span(&mut spans.code_or_html, code_block.take(), range) - } - Event::Start(Tag::HtmlBlock) => html_block = Some(range), - Event::End(TagEnd::HtmlBlock) => { - push_open_span(&mut spans.code_or_html, html_block.take(), range) - } - Event::Html(_) => { - if let Some(active) = html_block.as_mut() { - active.end = active.end.max(range.end); - } else { - spans.code_or_html.push(range); - } - } - Event::Text(_) - | Event::Code(_) - | Event::InlineMath(_) - | Event::DisplayMath(_) - | Event::InlineHtml(_) - | Event::FootnoteReference(_) - | Event::SoftBreak - | Event::HardBreak - | Event::Rule - | Event::TaskListMarker(_) => { - if let Some(active) = paragraph.as_mut() { - active.end = active.end.max(range.end); - } - if let Some(active) = code_block.as_mut() { - active.end = active.end.max(range.end); - } - if let Some(active) = html_block.as_mut() { - active.end = active.end.max(range.end); - } - } - Event::Start(_) | Event::End(_) => {} - } - } - - spans - } - - fn suppresses_reference_definition(&self, byte: usize) -> bool { - self.code_or_html - .iter() - .any(|span| contains_byte(span, byte)) - || self.paragraphs.iter().any(|span| contains_byte(span, byte)) - } -} - -fn push_open_span(target: &mut Vec>, open: Option>, end: Range) { - if let Some(mut span) = open { - span.end = span.end.max(end.end); - if span.start < span.end { - target.push(span); - } - } -} - -fn contains_byte(span: &Range, byte: usize) -> bool { - span.start <= byte && byte < span.end -} - -fn definition_content_start(source: &str, range: &Range) -> Option { - let bytes = source.as_bytes(); - let mut cursor = range.start; - cursor = skip_spaces_up_to(source, cursor, range.end, 3).0; - - loop { - if cursor >= range.end { - return Some(cursor); - } - - if bytes[cursor] == b'>' { - cursor += 1; - if cursor < range.end && matches!(bytes[cursor], b' ' | b'\t') { - cursor += 1; - } - cursor = skip_spaces_up_to(source, cursor, range.end, 3).0; - continue; - } - - if let Some(after_marker) = list_marker_content_start(source, cursor, range.end) { - cursor = skip_spaces_up_to(source, after_marker, range.end, 3).0; - continue; - } - - break; - } - - Some(cursor) -} - -fn list_marker_content_start(source: &str, cursor: usize, end: usize) -> Option { - let bytes = source.as_bytes(); - let marker_end = match bytes.get(cursor)? { - b'-' | b'+' | b'*' => cursor + 1, - byte if byte.is_ascii_digit() => { - let mut cursor = cursor; - let mut digits = 0; - while cursor < end && bytes[cursor].is_ascii_digit() && digits < 9 { - cursor += 1; - digits += 1; - } - if digits == 0 || !matches!(bytes.get(cursor), Some(b'.' | b')')) { - return None; - } - cursor + 1 - } - _ => return None, - }; - if !matches!(bytes.get(marker_end), Some(b' ' | b'\t')) { - return None; - } - Some(skip_spaces(source, marker_end)) -} - -fn skip_spaces_up_to(source: &str, mut cursor: usize, end: usize, limit: usize) -> (usize, usize) { - let bytes = source.as_bytes(); - let mut spaces = 0; - while cursor < end && bytes[cursor] == b' ' && spaces < limit { - cursor += 1; - spaces += 1; - } - (cursor, spaces) -} - -fn next_line_range(source: &str, start: usize) -> Range { - let tail = &source[start..]; - match tail.find('\n') { - Some(offset) => start..start + offset + 1, - None => start..source.len(), - } -} - -fn next_line_start_after(source: &str, byte: usize) -> usize { - if byte >= source.len() { - return source.len(); - } - source[byte..] - .find('\n') - .map(|offset| byte + offset + 1) - .unwrap_or(source.len()) -} - -fn trim_line_ending(source: &str, range: Range) -> Range { - let mut end = range.end; - if end > range.start && source.as_bytes()[end - 1] == b'\n' { - end -= 1; - } - if end > range.start && source.as_bytes()[end - 1] == b'\r' { - end -= 1; - } - range.start..end -} - -fn parse_reference_definition_at( - source: &str, - line_start: usize, - content_start: usize, - line_starts: &[usize], -) -> Option { - let bytes = source.as_bytes(); - let source_len = source.len(); - let mut cursor = content_start; - if bytes.get(cursor) != Some(&b'[') { - return None; - } - - let (label_span, label, after_label) = parse_link_label(source, cursor)?; - if label.starts_with('^') { - return None; - } - if bytes.get(after_label) != Some(&b':') { - return None; - } - cursor = after_label + 1; - cursor = skip_spaces_and_one_linebreak(source, cursor)?; - - let (destination_span, destination, after_destination) = - parse_link_destination(source, cursor)?; - cursor = after_destination; - let destination_end = cursor; - - let mut title_span = None; - let mut span_end = destination_end; - if let Some(after_space) = skip_optional_title_space(source, cursor) - && let Some((parsed_title_span, after_title)) = parse_link_title(source, after_space) - && only_blank_until_line_end(source, after_title) - { - title_span = Some(parsed_title_span); - span_end = after_title; - } else if !only_blank_until_line_end(source, cursor) { - return None; - } - - Some(ReferenceDefinition { - line: row_at(line_starts, source_len, line_start) as u64 + 1, - label: normalize_reference_label(&label), - destination, - span: line_start..span_end, - label_span, - destination_span, - title_span, - }) -} - -fn parse_link_label(source: &str, start: usize) -> Option<(Range, String, usize)> { - let bytes = source.as_bytes(); - if bytes.get(start) != Some(&b'[') { - return None; - } - let mut cursor = start + 1; - let content_start = cursor; - while cursor < source.len() { - match bytes[cursor] { - b'\\' if next_is_escapable_punctuation(bytes, cursor) => cursor += 2, - b'\\' => cursor += 1, - b'[' => return None, - b']' => { - let raw = &source[content_start..cursor]; - let label = unescape_markdown(raw); - if label.trim().is_empty() { - return None; - } - return Some((start..cursor + 1, label, cursor + 1)); - } - _ => cursor += 1, - } - } - None -} - -fn skip_spaces_and_one_linebreak(source: &str, mut cursor: usize) -> Option { - cursor = skip_spaces(source, cursor); - let bytes = source.as_bytes(); - let newline_len = match bytes.get(cursor) { - Some(b'\n') => 1, - Some(b'\r') if bytes.get(cursor + 1) == Some(&b'\n') => 2, - Some(b'\r') => 1, - _ => return Some(cursor), - }; - cursor += newline_len; - let next = skip_spaces(source, cursor); - if next.saturating_sub(cursor) > 3 { - None - } else { - Some(next) - } -} - -fn skip_optional_title_space(source: &str, cursor: usize) -> Option { - let after_spaces = skip_spaces(source, cursor); - if after_spaces > cursor { - return Some(after_spaces); - } - let bytes = source.as_bytes(); - let newline_len = match bytes.get(cursor) { - Some(b'\n') => 1, - Some(b'\r') if bytes.get(cursor + 1) == Some(&b'\n') => 2, - Some(b'\r') => 1, - _ => return None, - }; - let next_line = cursor + newline_len; - let after_line_spaces = skip_spaces(source, next_line); - (after_line_spaces.saturating_sub(next_line) <= 3).then_some(after_line_spaces) -} - -fn skip_spaces(source: &str, mut cursor: usize) -> usize { - while matches!(source.as_bytes().get(cursor), Some(b' ' | b'\t')) { - cursor += 1; - } - cursor -} - -fn parse_link_destination(source: &str, start: usize) -> Option<(Range, String, usize)> { - let bytes = source.as_bytes(); - if bytes.get(start) == Some(&b'<') { - let mut cursor = start + 1; - while cursor < source.len() { - match bytes[cursor] { - b'\\' if next_is_escapable_punctuation(bytes, cursor) => cursor += 2, - b'\\' => cursor += 1, - b'>' => { - let inner = start + 1..cursor; - let destination = unescape_markdown(&source[inner.clone()]); - return Some((inner, destination, cursor + 1)); - } - b'<' => return None, - b'\n' | b'\r' => return None, - _ => cursor += 1, - } - } - return None; - } - - let mut cursor = start; - let mut depth = 0usize; - while cursor < source.len() { - match bytes[cursor] { - b'\\' if next_is_escapable_punctuation(bytes, cursor) => cursor += 2, - b'\\' => cursor += 1, - b'(' => { - depth += 1; - cursor += 1; - } - b')' if depth > 0 => { - depth -= 1; - cursor += 1; - } - b')' => return None, - b' ' | b'\t' | b'\n' | b'\r' => break, - _ => cursor += 1, - } - } - - (cursor > start && depth == 0).then(|| { - let destination = unescape_markdown(&source[start..cursor]); - (start..cursor, destination, cursor) - }) -} - -fn parse_link_title(source: &str, start: usize) -> Option<(Range, usize)> { - let bytes = source.as_bytes(); - let (open, close) = match bytes.get(start)? { - b'\'' => (b'\'', b'\''), - b'"' => (b'"', b'"'), - b'(' => (b'(', b')'), - _ => return None, - }; - - let mut cursor = start + 1; - let content_start = cursor; - while cursor < source.len() { - match bytes[cursor] { - b'\\' if next_is_escapable_punctuation(bytes, cursor) => cursor += 2, - b'\\' => cursor += 1, - byte if byte == open && open == b'(' => return None, - byte if byte == close => { - let inner = content_start..cursor; - return Some((inner, cursor + 1)); - } - _ => cursor += 1, - } - } - None -} - -fn only_blank_until_line_end(source: &str, mut cursor: usize) -> bool { - let bytes = source.as_bytes(); - while let Some(byte) = bytes.get(cursor) { - match *byte { - b' ' | b'\t' => cursor += 1, - b'\r' | b'\n' => return true, - _ => return false, - } - } - true -} - -fn next_is_escapable_punctuation(bytes: &[u8], cursor: usize) -> bool { - bytes.get(cursor + 1).is_some_and(u8::is_ascii_punctuation) -} - -pub(crate) fn unescape_markdown(text: &str) -> String { - let mut out = String::with_capacity(text.len()); - let mut chars = text.chars().peekable(); - while let Some(ch) = chars.next() { - if ch == '\\' { - if let Some(next) = chars.next_if(char::is_ascii_punctuation) { - out.push(next); - } else { - out.push(ch); - } - } else { - out.push(ch); - } - } - out -} - -#[cfg(test)] -mod tests { - use super::*; - - fn definitions(source: &str) -> Vec { - reference_definitions_from_source(source) - } - - fn labels(source: &str) -> Vec { - definitions(source) - .into_iter() - .map(|definition| definition.label) - .collect() - } - - #[test] - fn reference_definition_cannot_interrupt_paragraph() { - assert!(definitions("Foo\n[bar]: /baz\n").is_empty()); - } - - #[test] - fn reference_definitions_inside_block_containers_are_recognized() { - let source = "> [quoted]: /quote\n\n- [listed]: /list\n"; - - assert_eq!(labels(source), vec!["quoted", "listed"]); - } - - #[test] - fn malformed_reference_definition_with_trailing_text_is_rejected() { - assert!(definitions("[foo]: /url oops\n").is_empty()); - } - - #[test] - fn html_blocks_suppress_reference_definition_scanning() { - let source = "\n"; - - assert!(definitions(source).is_empty()); - } - - #[test] - fn container_scoped_fenced_code_suppresses_reference_definitions() { - let source = "> ```\n> [fake]: /url\n> ```\n"; - - assert!(definitions(source).is_empty()); - } - - #[test] - fn reference_label_rejects_nested_brackets() { - assert!(definitions("[a[b]]: /url\n").is_empty()); - } - - #[test] - fn reference_definitions_preserve_non_escapable_backslashes() { - let source = "[foo\\q]: \n[bar\\]]: /ok\\q\n"; - let definitions = definitions(source); - - assert_eq!(definitions[0].label, "foo\\q"); - assert_eq!(definitions[0].destination, "https://example.com/a\\q"); - assert_eq!(definitions[1].label, "bar]"); - assert_eq!(definitions[1].destination, "/ok\\q"); - } - - #[test] - fn unescape_markdown_only_unescapes_commonmark_punctuation() { - assert_eq!( - unescape_markdown("foo\\] bar\\q baz\\\\"), - "foo] bar\\q baz\\" - ); - } - - #[test] - fn reference_definition_labels_preserve_first_duplicate() { - let document = parse_document("[foo]: /first\n[foo]: /second\n"); - let labels = document.reference_definition_labels(); - - assert_eq!(document.reference_definitions.len(), 2); - assert_eq!(labels["foo"].destination, "/first"); - } - - #[test] - fn angle_destination_rejects_unescaped_lt() { - assert!(definitions("[id]: \n").is_empty()); - } - - #[test] - fn raw_destination_rejects_unbalanced_parentheses() { - assert!(definitions("[id]: /docs(\n").is_empty()); - assert!(definitions("[id]: /docs)\n").is_empty()); - - let definitions = definitions("[balanced]: /docs(ok)\n[escaped]: /docs\\(ok\\)\n"); - assert_eq!( - definitions - .into_iter() - .map(|definition| (definition.label, definition.destination)) - .collect::>(), - vec![ - ("balanced".to_string(), "/docs(ok)".to_string()), - ("escaped".to_string(), "/docs(ok)".to_string()), - ] - ); - } -} - -pub(crate) struct DocumentBuilder<'a> { - source: &'a str, - line_starts: Vec, - headings: Vec, - links: Vec, - reference_definitions: Vec, - footnote_references: Vec, - footnote_definitions: Vec, - code_blocks: Vec, - heading_stack: Vec, - link_stack: Vec, - code_block_stack: Vec, -} - -impl<'a> DocumentBuilder<'a> { - pub(crate) fn new(source: &'a str, reference_definitions: Vec) -> Self { - Self { - source, - line_starts: line_starts(source), - headings: Vec::new(), - links: Vec::new(), - reference_definitions, - footnote_references: Vec::new(), - footnote_definitions: Vec::new(), - code_blocks: Vec::new(), - heading_stack: Vec::new(), - link_stack: Vec::new(), - code_block_stack: Vec::new(), - } - } - - pub(crate) fn finish(self) -> MarkdownDocument { - let code_block_start_lines = self - .code_blocks - .iter() - .enumerate() - .map(|(index, block)| (block.start_line, index)) - .collect(); - let link_spans = self - .links - .iter() - .enumerate() - .map(|(index, link)| ((link.span.start, link.span.end), index)) - .collect(); - MarkdownDocument { - headings: self.headings, - links: self.links, - reference_definitions: self.reference_definitions, - footnote_references: self.footnote_references, - footnote_definitions: self.footnote_definitions, - code_blocks: self.code_blocks, - code_block_start_lines, - link_spans, - } - } - - pub(crate) fn handle_event(&mut self, event: Event<'a>, range: Range) { - match event { - Event::Start(tag) => self.start_tag(tag, range), - Event::End(tag) => self.end_tag(tag), - Event::Text(text) => self.push_text_event(&text, range), - Event::Code(text) => self.push_text(&text), - Event::InlineMath(text) | Event::DisplayMath(text) => self.push_text(&text), - Event::FootnoteReference(label) => self.add_footnote_reference(&label, range), - Event::SoftBreak | Event::HardBreak => self.push_text(" "), - Event::Html(_) | Event::InlineHtml(_) | Event::Rule | Event::TaskListMarker(_) => {} - } - } - - fn start_tag(&mut self, tag: Tag<'a>, range: Range) { - match tag { - Tag::Heading { level, .. } => self.push_heading(level), - Tag::Link { - link_type, - dest_url, - id, - .. - } => self.push_link(link_type, &dest_url, &id, range, false), - Tag::Image { - link_type, - dest_url, - id, - .. - } => self.push_link(link_type, &dest_url, &id, range, true), - Tag::CodeBlock(kind) => self.push_code_block(kind, range), - Tag::FootnoteDefinition(label) => self.push_footnote_definition(&label), - Tag::Paragraph - | Tag::BlockQuote(_) - | Tag::HtmlBlock - | Tag::List(_) - | Tag::Item - | Tag::Table(_) - | Tag::TableHead - | Tag::TableRow - | Tag::TableCell - | Tag::Emphasis - | Tag::Strong - | Tag::Strikethrough - | Tag::MetadataBlock(_) - | Tag::DefinitionList - | Tag::DefinitionListTitle - | Tag::DefinitionListDefinition - | Tag::Superscript - | Tag::Subscript => {} - } - } - - fn end_tag(&mut self, tag: TagEnd) { - match tag { - TagEnd::Heading(_) => self.pop_heading(), - TagEnd::Link | TagEnd::Image => self.pop_link(), - TagEnd::CodeBlock => self.pop_code_block(), - TagEnd::Paragraph - | TagEnd::BlockQuote(_) - | TagEnd::HtmlBlock - | TagEnd::List(_) - | TagEnd::Item - | TagEnd::FootnoteDefinition - | TagEnd::Table - | TagEnd::TableHead - | TagEnd::TableRow - | TagEnd::TableCell - | TagEnd::Emphasis - | TagEnd::Strong - | TagEnd::Strikethrough - | TagEnd::MetadataBlock(_) - | TagEnd::DefinitionList - | TagEnd::DefinitionListTitle - | TagEnd::DefinitionListDefinition - | TagEnd::Superscript - | TagEnd::Subscript => {} - } - } - - fn push_heading(&mut self, _level: HeadingLevel) { - self.heading_stack.push(HeadingFrame { - text: String::new(), - }); - } - - fn pop_heading(&mut self) { - if let Some(frame) = self.heading_stack.pop() { - let text = frame.text.trim().to_string(); - if !text.is_empty() { - self.headings.push(Heading { text }); - } - } - } - - fn push_link( - &mut self, - link_type: LinkType, - destination: &str, - reference_id: &str, - range: Range, - is_image: bool, - ) { - self.link_stack.push(LinkFrame { - span: range.clone(), - line: self.line_for(range.start), - kind: link_type.into(), - destination: destination.to_string(), - reference_label: (!reference_id.is_empty()) - .then(|| normalize_reference_label(reference_id)), - text: String::new(), - is_image, - }); - } - - fn pop_link(&mut self) { - if let Some(frame) = self.link_stack.pop() { - self.links.push(LinkUse { - line: frame.line, - kind: frame.kind, - destination: frame.destination, - reference_label: frame.reference_label, - text: frame.text.trim().to_string(), - is_image: frame.is_image, - span: frame.span, - }); - } - } - - fn push_footnote_definition(&mut self, label: &str) { - self.footnote_definitions.push(FootnoteDefinition { - label: label.to_string(), - }); - } - - fn add_footnote_reference(&mut self, label: &str, range: Range) { - let label = label.to_string(); - self.footnote_references.push(FootnoteReference { - line: self.line_for(range.start), - label: label.clone(), - }); - self.push_text(&format!("[^{label}]")); - } - - fn push_code_block(&mut self, kind: PulldownCodeBlockKind<'a>, range: Range) { - let (kind, language) = match kind { - PulldownCodeBlockKind::Fenced(info) => (CodeBlockKind::Fenced, code_language(&info)), - PulldownCodeBlockKind::Indented => (CodeBlockKind::Indented, None), - }; - self.code_block_stack.push(CodeBlockFrame { - kind, - start_line: self.line_for(range.start), - end_line: self.end_line_for(range.clone()), - language, - content: String::new(), - }); - } - - fn pop_code_block(&mut self) { - if let Some(frame) = self.code_block_stack.pop() { - self.code_blocks.push(CodeBlock { - kind: frame.kind, - start_line: frame.start_line, - end_line: frame.end_line, - language: frame.language, - content: normalize_line_endings(&frame.content), - }); - } - } - - fn push_text_event(&mut self, text: &str, _range: Range) { - if let Some(code) = self.code_block_stack.last_mut() { - code.content.push_str(text); - return; - } - self.push_text(text); - } - - fn push_text(&mut self, text: &str) { - if let Some(heading) = self.heading_stack.last_mut() { - heading.text.push_str(text); - } - if let Some(link) = self.link_stack.last_mut() { - link.text.push_str(text); - } - } - - pub(crate) fn line_for(&self, byte: usize) -> u64 { - row_at(&self.line_starts, self.source.len(), byte) as u64 + 1 - } - - fn end_line_for(&self, range: Range) -> u64 { - let start_row = row_at(&self.line_starts, self.source.len(), range.start); - let mut end_row = row_at(&self.line_starts, self.source.len(), range.end); - let end_col = range - .end - .saturating_sub(*self.line_starts.get(end_row).unwrap_or(&range.end)); - if end_row > start_row && end_col == 0 { - end_row -= 1; - } - end_row as u64 + 1 - } -} - -#[derive(Debug)] -struct HeadingFrame { - text: String, -} - -#[derive(Debug)] -struct LinkFrame { - span: Range, - line: u64, - kind: LinkUseKind, - destination: String, - reference_label: Option, - text: String, - is_image: bool, -} - -#[derive(Debug)] -struct CodeBlockFrame { - kind: CodeBlockKind, - start_line: u64, - end_line: u64, - language: Option, - content: String, -} - -impl From for LinkUseKind { - fn from(value: LinkType) -> Self { - match value { - LinkType::Inline => Self::Inline, - LinkType::Reference => Self::Reference, - LinkType::ReferenceUnknown => Self::ReferenceUnknown, - LinkType::Collapsed => Self::Collapsed, - LinkType::CollapsedUnknown => Self::CollapsedUnknown, - LinkType::Shortcut => Self::Shortcut, - LinkType::ShortcutUnknown => Self::ShortcutUnknown, - LinkType::Autolink => Self::Autolink, - LinkType::Email => Self::Email, - LinkType::WikiLink { .. } => Self::WikiLink, - } - } -} - -impl MarkdownDocument { - pub(crate) fn code_block_by_start_row(&self, start_row: usize) -> Option<&CodeBlock> { - self.code_block_start_lines - .get(&(start_row as u64 + 1)) - .and_then(|index| self.code_blocks.get(*index)) - } - - pub(crate) fn link_destination_by_span( - &self, - start_byte: usize, - end_byte: usize, - ) -> Option<&str> { - let index = self.link_spans.get(&(start_byte, end_byte))?; - let destination = self.links.get(*index)?.destination.as_str(); - (!destination.is_empty()).then_some(destination) - } - - pub(crate) fn reference_definition_labels(&self) -> HashMap<&str, &ReferenceDefinition> { - let mut labels = HashMap::new(); - for definition in &self.reference_definitions { - labels - .entry(definition.label.as_str()) - .or_insert(definition); - } - labels - } -} diff --git a/crates/mehen-markdown/src/ecu.rs b/crates/mehen-markdown/src/ecu.rs deleted file mode 100644 index f45aae2f..00000000 --- a/crates/mehen-markdown/src/ecu.rs +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Effective Content Units per §6. -//! -//! ```text -//! ECU = W/240 -//! + 0.35 * CLOC -//! + 0.06 * table_cells -//! + 0.40 * diagram_nodes -//! + 0.25 * diagram_edges -//! + 0.12 * math_tokens -//! + 0.20 * raw_html_or_mdx_lines -//! ``` -//! -//! Phase A produces all terms except `diagram_nodes` and `diagram_edges`, -//! which remain `0` until Phase C implements Mermaid / PlantUML / DOT -//! extraction. `table_cells` = sum of `pipe_table_cell` children across -//! `pipe_table_row`. `math_tokens` = words-like tokens inside `math_block` / -//! `math_inline`. `raw_html_or_mdx_lines` = distinct physical lines whose -//! top-level owner is a raw HTML or MDX JSX block. - -use std::collections::HashSet; - -use crate::kind::NodeKind; -use crate::loc::LineClass; -use crate::loc::LineClasses; -use crate::syntax_tree::Node; -use crate::types::{EcuInputs, LocFamily}; - -/// Counts the ECU inputs that fall out of the AST. `classes` is used to -/// derive `raw_html_or_mdx_lines` without walking again. -pub(crate) fn compute_ecu_inputs(root: &Node<'_>, classes: &LineClasses) -> EcuInputs { - let mut table_cells: u64 = 0; - let mut math_tokens: u64 = 0; - let mut raw_html_lines: HashSet = HashSet::new(); - - walk( - root, - &mut table_cells, - &mut math_tokens, - &mut raw_html_lines, - ); - - // Also include any line classed as OtherArtifact that was covered by a - // raw HTML / MDX block — the class map already did the heavy lifting. - // We reuse the classes vector to enumerate lines and filter. - let mut raw_html_or_mdx_lines: u64 = 0; - let mut i = 0; - while let Some(class) = classes.class_at(i) { - if raw_html_lines.contains(&i) && class == LineClass::OtherArtifact { - raw_html_or_mdx_lines += 1; - } - i += 1; - } - - EcuInputs { - table_cells, - // TODO(Phase C): wire diagram extraction from fenced code blocks - // with `mermaid` / `plantuml` / `dot` / `d2` info strings. - diagram_nodes: 0, - diagram_edges: 0, - math_tokens, - raw_html_or_mdx_lines, - } -} - -fn walk( - node: &Node<'_>, - table_cells: &mut u64, - math_tokens: &mut u64, - raw_html_lines: &mut HashSet, -) { - use NodeKind::*; - - let kind = node.kind(); - - match kind { - // Count body-row cells per §6. The delimiter row is excluded because - // it is pure structure (---, :---:); the header row is included - // because its cells carry content. - PipeTableHeader | PipeTableRow => { - for child in node.children() { - if matches!(child.kind(), PipeTableCell) { - *table_cells += 1; - } - } - // Fall through to recurse for any nested content (e.g. inline - // code inside a cell does not itself matter for Phase A). - } - // Math: count word-like tokens inside math_block / math_inline. - MathBlock | MathInline => { - let mut tokens: u64 = 0; - count_math_tokens(node, &mut tokens); - *math_tokens += tokens; - // Do not recurse further — children are already counted. - return; - } - // Raw HTML / MDX lines. - HtmlBlock => { - let start = node.start_row(); - let (end_row, end_col) = node.end_position(); - let mut end = end_row; - if end > start && end_col == 0 { - end -= 1; - } - for row in start..=end { - raw_html_lines.insert(row); - } - return; - } - _ => {} - } - - for child in node.children() { - walk(&child, table_cells, math_tokens, raw_html_lines); - } -} - -fn count_math_tokens(node: &Node<'_>, total: &mut u64) { - let kind = node.kind(); - if matches!( - kind, - NodeKind::WordToken - | NodeKind::NumericToken - | NodeKind::IdentifierLikeToken - | NodeKind::PathLikeToken - ) { - *total += 1; - } - for child in node.children() { - count_math_tokens(&child, total); - } -} - -/// Final ECU value per §6. Coefficients are exact and deterministic. -pub(crate) fn effective_content_units(loc: &LocFamily, words: u64, inputs: &EcuInputs) -> f64 { - let words = words as f64 / 240.0; - let code = 0.35 * loc.cloc as f64; - let table = 0.06 * inputs.table_cells as f64; - let diagram_n = 0.40 * inputs.diagram_nodes as f64; - let diagram_e = 0.25 * inputs.diagram_edges as f64; - let math = 0.12 * inputs.math_tokens as f64; - let html = 0.20 * inputs.raw_html_or_mdx_lines as f64; - words + code + table + diagram_n + diagram_e + math + html -} diff --git a/crates/mehen-markdown/src/embedded_code.rs b/crates/mehen-markdown/src/embedded_code.rs deleted file mode 100644 index 480d85d3..00000000 --- a/crates/mehen-markdown/src/embedded_code.rs +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! §9.4 embedded-code adjustment. -//! -//! For every supported fenced code block — `rust`, `ts`/`tsx`, `py`, `go`, -//! `rb`, `c`, `kotlin`, `pwsh`/`powershell` — run the fence body through -//! the source-language analysis pipeline and accumulate: -//! -//! ```text -//! embedded_volume = Σ 0.20 * sqrt(volume_c) -//! + 0.50 * cognitive_c -//! + 0.10 * loc_c -//! ``` -//! -//! The dispatch is decoupled from this crate via [`set_embedded_dispatch`]: -//! the markdown crate doesn't depend on the per-language analyzers -//! directly. `mehen-engine` supplies a callback that maps a fence-language -//! code + body to numeric volume/cognitive/sloc. - -use std::sync::OnceLock; - -use crate::document::MarkdownDocument; - -/// Languages a fenced code block can declare. Mirrors the pre-1.0 -/// `LANG` enum, but kept local to this crate so we don't depend on -/// `mehen::langs` at compile time. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum FenceLanguage { - Rust, - Python, - Typescript, - Tsx, - Go, - Ruby, - Kotlin, - Java, - Powershell, - C, - CSharp, - Php, -} - -/// Metrics extracted from one fenced code block. Returned by the -/// dispatch callback registered through [`set_embedded_dispatch`]. -#[derive(Clone, Copy, Debug, Default)] -pub struct EmbeddedFenceMetrics { - pub volume: f64, - pub cognitive_sum: f64, - pub sloc: f64, -} - -type DispatchFn = fn(FenceLanguage, String) -> Option; - -static DISPATCH: OnceLock = OnceLock::new(); - -/// Register the embedded-code dispatch callback. -/// -/// Called by `mehen_engine::init_markdown` at startup so the Markdown -/// analyzer can drive the language registry for fence bodies. -pub fn set_embedded_dispatch(f: DispatchFn) { - let _ = DISPATCH.set(f); -} - -/// Public entry: analyze every fenced code block whose language maps to a -/// supported [`FenceLanguage`] and sum the §9.4 contributions. -pub(crate) fn embedded_volume(document: &MarkdownDocument) -> f64 { - let mut total = 0.0; - for block in document - .code_blocks - .iter() - .filter(|block| block.is_fenced()) - { - let lang = block.language.as_deref().and_then(map_fence_to_lang); - if let Some(lang) = lang { - let mut body = block.content.clone(); - if matches!(lang, FenceLanguage::Php) { - let leading = body.trim_start(); - if !leading.starts_with(" f64 { - let Some(dispatch) = DISPATCH.get() else { - return 0.0; - }; - let Some(m) = dispatch(lang, body) else { - return 0.0; - }; - let v = if m.volume.is_finite() && m.volume > 0.0 { - 0.20 * m.volume.sqrt() - } else { - 0.0 - }; - let c = if m.cognitive_sum.is_finite() { - 0.50 * m.cognitive_sum - } else { - 0.0 - }; - let l = if m.sloc.is_finite() { - 0.10 * m.sloc - } else { - 0.0 - }; - v + c + l -} - -fn map_fence_to_lang(info: &str) -> Option { - let head = info - .split([' ', '\t', ',']) - .next() - .unwrap_or("") - .to_ascii_lowercase(); - Some(match head.as_str() { - "rust" | "rs" => FenceLanguage::Rust, - "python" | "py" => FenceLanguage::Python, - "typescript" | "ts" => FenceLanguage::Typescript, - "tsx" | "jsx" => FenceLanguage::Tsx, - "javascript" | "js" => FenceLanguage::Typescript, - "go" => FenceLanguage::Go, - "ruby" | "rb" => FenceLanguage::Ruby, - "kotlin" | "kt" | "kts" => FenceLanguage::Kotlin, - "java" => FenceLanguage::Java, - "powershell" | "pwsh" | "ps1" => FenceLanguage::Powershell, - "c" => FenceLanguage::C, - // `cs` and `csharp` are the tags GitHub and dotnet docs use; `csx` marks - // a script fence, which Roslyn's `compilation_unit` accepts via - // `global_statement`. - "csharp" | "cs" | "c#" | "csx" => FenceLanguage::CSharp, - "php" => FenceLanguage::Php, - _ => return None, - }) -} diff --git a/crates/mehen-markdown/src/evidence.rs b/crates/mehen-markdown/src/evidence.rs deleted file mode 100644 index eae86549..00000000 --- a/crates/mehen-markdown/src/evidence.rs +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Evidence Coverage Score per §16. -//! -//! §16.2 Per-section formula: -//! -//! ```text -//! anchor_density_s = evidence_anchors_s / max(1, W_s / 250) -//! section_evidence_s = sat(anchor_density_s; 0.2, 1.5) -//! ``` -//! -//! §16.3 Aggregate: `0.5 * mean(section_evidence_s) + 0.5 * p25(section_evidence_s)`. -//! -//! The actual counting of per-section evidence anchors lives alongside the -//! §15 grounding pipeline in `grounding.rs`. This module re-exports the -//! values so the §23 schema can cleanly map `grounding.evidence_coverage_score` -//! and Phase-D consumers (filler, RCI) have a narrow dependency surface. -//! -//! §16.1 evidence anchors we count: -//! -//! - Resolved relative link. -//! - External link. -//! - Internal link to a non-trivial section (treated as `resolved Some(true)`). -//! - Labelled code fence. -//! - Table with header. -//! - Parseable diagram with caption. -//! - Image with alt/caption. -//! - Math block with nearby explanation. -//! - Issue/PR/Scholarly reference link. -//! - Path-like token resolved to repo (rolls into §15 counts). -//! -//! The implementation is in `grounding::compute_per_section_anchors` and -//! the aggregate is produced inline by `grounding::analyze_grounding`. -//! This module is intentionally empty: it exists to group the §16 design -//! notes alongside the source tree so future Phase-D consumers know -//! where the anchor-counting logic lives without adding a second cache -//! of the same values. diff --git a/crates/mehen-markdown/src/filler.rs b/crates/mehen-markdown/src/filler.rs deleted file mode 100644 index cbaf2453..00000000 --- a/crates/mehen-markdown/src/filler.rs +++ /dev/null @@ -1,538 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Filler / Lazy Structure Risk per §17. -//! -//! Each sub-score below matches the research-foundation formula exactly. -//! The aggregation (§17.9) is: -//! -//! ```text -//! FillerLazyRisk = clamp01( -//! 0.20 * UnanchoredProseMass -//! + 0.15 * LowArtifactDensity -//! + 0.20 * LowRepoGrounding -//! + 0.15 * LazySectioning -//! + 0.12 * RepetitionDensity -//! + 0.12 * SpecificityScarcity -//! + 0.04 * ReferenceHollowness -//! + 0.02 * PlaceholderDensity -//! ) -//! ``` -//! -//! §17.11 diagnostic labels are emitted whenever a contributing sub-score is -//! non-trivial. The top-3 contributors (sorted by score desc) are surfaced -//! as `(label, score)` pairs for the exported schema's -//! `ai_era.top_contributors`. -//! -//! Phase D never touches Phase A/B/C metrics — it reads from them only. - -use std::collections::BTreeSet; - -use crate::grounding::GroundingOutputs; -use crate::kind::NodeKind; -use crate::mathops::{clamp01, sat}; -use crate::section_balance::SectionBalance; -use crate::syntax_tree::Node; -use crate::tree_helpers::{ProseContext, is_non_prose_container, node_text, opens_prose_context}; -use crate::types::{ArtifactRecord, LinkClass, LinkRecord, LocFamily, Section}; - -/// Diagnostic labels from §17.11. -pub(crate) mod labels { - pub(super) const LARGE_UNANCHORED: &str = "large-unanchored-prose"; - pub(super) const LOW_REPO_GROUNDING: &str = "low-repository-grounding"; - pub(super) const LAZY_SECTIONING: &str = "lazy-sectioning"; - pub(super) const LOW_ARTIFACT_DENSITY: &str = "low-artifact-density"; - pub(super) const NEAR_DUP_PARAGRAPHS: &str = "near-duplicate-paragraphs"; - pub(super) const SPECIFICITY_SCARCITY: &str = "specificity-scarcity"; - pub(super) const HOLLOW_REFERENCES: &str = "hollow-references"; - pub(super) const PLACEHOLDER_HEAVY: &str = "placeholder-heavy"; -} - -/// Sub-scores + final FillerLazyRisk. -/// -/// Sub-score fields marked `#[allow(dead_code)]` are populated for §17's -/// diagnostic surface (Phase F / `mehen diff`) but not read by the -/// analyzer's return value directly. Keeping them on the result makes the -/// internal plumbing visible for audit. -#[derive(Debug, Default, Clone)] -pub(crate) struct FillerResult { - #[allow(dead_code)] - pub(crate) unanchored_prose_mass: f64, - #[allow(dead_code)] - pub(crate) low_artifact_density: f64, - #[allow(dead_code)] - pub(crate) low_repo_grounding: f64, - #[allow(dead_code)] - pub(crate) lazy_sectioning: f64, - #[allow(dead_code)] - pub(crate) repetition_density: f64, - #[allow(dead_code)] - pub(crate) specificity_scarcity: f64, - #[allow(dead_code)] - pub(crate) reference_hollowness: f64, - #[allow(dead_code)] - pub(crate) placeholder_density: f64, - pub(crate) filler_lazy_risk: f64, - pub(crate) labels: Vec, - pub(crate) top_contributors: Vec<(String, f64)>, - #[allow(dead_code)] - pub(crate) near_duplicate_paragraph_rate: f64, - #[allow(dead_code)] - pub(crate) repeated_heading_rate: f64, -} - -/// Main entry. Takes every Phase A/B/C output Phase D needs; never mutates -/// them. -#[allow(clippy::too_many_arguments)] -pub(crate) fn analyze_filler( - root: &Node<'_>, - source: &str, - words: u64, - sections: &[Section], - artifacts: &[ArtifactRecord], - links: &[LinkRecord], - loc: &LocFamily, - grounding: &GroundingOutputs, - section_balance: &SectionBalance, -) -> FillerResult { - // §17 assumes substantive prose. A document with 0 words has nothing - // to judge; returning a high filler risk would be a false positive on - // placeholder / stub files. Emit a zero risk with no labels in that - // case — every sub-score still computes zero individually because - // every denominator max()'s to `1`. - if words == 0 { - return FillerResult::default(); - } - - // §17.1 UnanchoredProseMass - let w = words.max(1) as f64; - let unanchored_words = words.saturating_sub(grounding.anchored_words); - let unanchored_prose_mass = sat(unanchored_words as f64 / w, 0.35, 0.85); - - // §17.2 LowArtifactDensity: A = total artifact count (per §4). - let a = artifacts.len() as f64; - let artifact_density = a / (w / 800.0).max(1.0); - let low_artifact_density = 1.0 - sat(artifact_density, 0.5, 2.0); - - // §17.3 LowRepoGrounding = 1 - RepositoryGroundingScore. - let low_repo_grounding = 1.0 - grounding.repository_grounding_score; - - // §17.4 LazySectioning. - let lazy_sectioning = compute_lazy_sectioning(words, sections, section_balance); - - // §17.5 RepetitionDensity. - let (near_duplicate_rate, repeated_heading_rate) = - compute_repetition_signals(root, source, sections); - let repetition_density = clamp01( - 0.75 * sat(near_duplicate_rate, 0.02, 0.20) + 0.25 * sat(repeated_heading_rate, 0.02, 0.15), - ); - - // §17.6 SpecificityScarcity. - let specific_tokens = grounding.tokens.identifier_like_tokens - + grounding.tokens.path_like_tokens - + grounding.tokens.numeric_tokens - + grounding.tokens.inline_code_tokens; - let specificity_density = specific_tokens as f64 / w; - let specificity_scarcity = 1.0 - sat(specificity_density, 0.03, 0.15); - - // §17.7 ReferenceHollowness. - let reference_hollowness = compute_reference_hollowness(links); - - // §17.8 PlaceholderDensity. - let placeholder_tokens = count_placeholder_tokens(root, source, links); - let placeholder_density = sat(placeholder_tokens as f64 / (w / 1000.0).max(1.0), 0.5, 4.0); - - let raw = 0.20 * unanchored_prose_mass - + 0.15 * low_artifact_density - + 0.20 * low_repo_grounding - + 0.15 * lazy_sectioning - + 0.12 * repetition_density - + 0.12 * specificity_scarcity - + 0.04 * reference_hollowness - + 0.02 * placeholder_density; - let filler_lazy_risk = clamp01(raw); - - // §17.11 diagnostic labels: emit when sub-score > 0.40 or any - // concrete signal hit (broken/duplicate paragraphs, placeholders). - let mut labels_set: BTreeSet = BTreeSet::new(); - if unanchored_prose_mass > 0.40 { - labels_set.insert(labels::LARGE_UNANCHORED.to_string()); - } - if low_repo_grounding > 0.40 { - labels_set.insert(labels::LOW_REPO_GROUNDING.to_string()); - } - if lazy_sectioning > 0.40 { - labels_set.insert(labels::LAZY_SECTIONING.to_string()); - } - if low_artifact_density > 0.40 { - labels_set.insert(labels::LOW_ARTIFACT_DENSITY.to_string()); - } - if near_duplicate_rate > 0.0 { - labels_set.insert(labels::NEAR_DUP_PARAGRAPHS.to_string()); - } - if specificity_scarcity > 0.40 { - labels_set.insert(labels::SPECIFICITY_SCARCITY.to_string()); - } - if reference_hollowness > 0.40 { - labels_set.insert(labels::HOLLOW_REFERENCES.to_string()); - } - if placeholder_tokens > 0 { - labels_set.insert(labels::PLACEHOLDER_HEAVY.to_string()); - } - let labels_vec: Vec = labels_set.into_iter().collect(); - - // Top-3 contributors by score desc, then label asc. - let contributors = [ - (labels::LARGE_UNANCHORED.to_string(), unanchored_prose_mass), - ( - labels::LOW_ARTIFACT_DENSITY.to_string(), - low_artifact_density, - ), - (labels::LOW_REPO_GROUNDING.to_string(), low_repo_grounding), - (labels::LAZY_SECTIONING.to_string(), lazy_sectioning), - (labels::NEAR_DUP_PARAGRAPHS.to_string(), repetition_density), - ( - labels::SPECIFICITY_SCARCITY.to_string(), - specificity_scarcity, - ), - (labels::HOLLOW_REFERENCES.to_string(), reference_hollowness), - (labels::PLACEHOLDER_HEAVY.to_string(), placeholder_density), - ]; - let mut sorted: Vec<(String, f64)> = contributors.to_vec(); - sorted.sort_by(|a, b| match b.1.partial_cmp(&a.1) { - Some(std::cmp::Ordering::Equal) | None => a.0.cmp(&b.0), - Some(o) => o, - }); - let top_contributors: Vec<(String, f64)> = sorted.into_iter().take(3).collect(); - - let _ = loc; // reserved for a future §17.x extension; kept in signature. - - FillerResult { - unanchored_prose_mass, - low_artifact_density, - low_repo_grounding, - lazy_sectioning, - repetition_density, - specificity_scarcity, - reference_hollowness, - placeholder_density, - filler_lazy_risk, - labels: labels_vec, - top_contributors, - near_duplicate_paragraph_rate: near_duplicate_rate, - repeated_heading_rate, - } -} - -fn compute_lazy_sectioning( - words: u64, - sections: &[Section], - section_balance: &SectionBalance, -) -> f64 { - let w = words as f64; - let h = sections.len() as f64; - let heading_density = h / (w / 700.0).max(1.0); - let shallow = if section_balance.shallow_large_doc { - 1.0 - } else { - 0.0 - }; - clamp01( - 0.35 * (1.0 - sat(heading_density, 0.6, 2.0)) - + 0.35 * sat(section_balance.long_section_rate, 0.10, 0.60) - + 0.30 * shallow, - ) -} - -/// §17.5 repetition signals. -/// -/// Paragraphs are collected in document order (sorted by `start_byte`) and -/// each is converted to a normalized 5-token shingle set using a -/// `BTreeSet` so iteration is deterministic. Pairs with Jaccard -/// similarity > 0.82 are counted; each paragraph is counted at most once so -/// the rate stays in `[0, 1]`. -/// -/// Repeated heading rate: duplicate normalized (lowercased, trimmed) heading -/// text occurrences / headings. -fn compute_repetition_signals(root: &Node<'_>, source: &str, sections: &[Section]) -> (f64, f64) { - let mut paragraphs = collect_paragraphs(root, source); - // Sort by start_byte so iteration order is deterministic even if the - // walker produces them in a different order. - paragraphs.sort_by_key(|p| p.start_byte); - - let shingles: Vec> = paragraphs - .iter() - .map(|p| paragraph_shingles(&p.text)) - .collect(); - - let n = paragraphs.len(); - let mut is_near_dup: Vec = vec![false; n]; - for i in 0..n { - if shingles[i].is_empty() { - continue; - } - for j in (i + 1)..n { - if shingles[j].is_empty() { - continue; - } - let sim = jaccard(&shingles[i], &shingles[j]); - if sim > 0.82 { - is_near_dup[i] = true; - is_near_dup[j] = true; - } - } - } - let near_dup_count = is_near_dup.iter().filter(|x| **x).count() as f64; - let near_duplicate_rate = if n == 0 { - 0.0 - } else { - near_dup_count / n as f64 - }; - - let repeated_heading_rate = compute_repeated_heading_rate(sections); - - (near_duplicate_rate, repeated_heading_rate) -} - -fn compute_repeated_heading_rate(sections: &[Section]) -> f64 { - let total = sections.len() as f64; - if total == 0.0 { - return 0.0; - } - // Phase A `heading_text` is often `None` — the grammar extracts only - // structural text. We fall back to the first source-line heading slug - // via `start_line`: the sections list is derived directly from the AST - // so sections with matching heading text share an identical - // `(heading_level, heading_text)` key. When `heading_text` is `None` - // we cannot measure repetition from this source, so this metric is - // effectively zero in Phase D until a Phase-E heading-text extractor - // lands. Until then: iterate all sections and count duplicate - // normalized heading_text values. - let mut seen: std::collections::BTreeMap = Default::default(); - let mut duplicates = 0u64; - for s in sections { - if let Some(text) = s.heading_text.as_ref() { - let key = normalize_heading(text); - let entry = seen.entry(key).or_insert(0); - *entry += 1; - if *entry > 1 { - duplicates += 1; - } - } - } - duplicates as f64 / total -} - -fn normalize_heading(s: &str) -> String { - s.trim().to_lowercase() -} - -#[derive(Debug, Clone)] -struct Paragraph { - text: String, - start_byte: usize, -} - -fn collect_paragraphs(root: &Node<'_>, source: &str) -> Vec { - let mut out: Vec = Vec::new(); - walk_paragraphs(root, source, &mut out); - out -} - -fn walk_paragraphs(node: &Node<'_>, source: &str, out: &mut Vec) { - let kind = node.kind(); - if matches!(kind, NodeKind::Paragraph) { - let start = node.start_byte(); - let end = node.end_byte(); - let raw = source.as_bytes().get(start..end).unwrap_or(&[]); - let text = String::from_utf8_lossy(raw).into_owned(); - out.push(Paragraph { - text, - start_byte: start, - }); - // Don't descend — nested paragraphs are rare and the top-level - // paragraph text is what we want for shingle matching. - return; - } - for child in node.children() { - walk_paragraphs(&child, source, out); - } -} - -/// Normalize to whitespace-separated ASCII-lowercase tokens, drop markdown -/// punctuation, then produce the set of 5-token shingles. Returns an empty -/// set when the paragraph has fewer than 5 tokens. -fn paragraph_shingles(text: &str) -> BTreeSet { - let tokens: Vec = text - .split_whitespace() - .map(|t| { - t.trim_matches(|c: char| !c.is_alphanumeric()) - .to_lowercase() - }) - .filter(|t| !t.is_empty()) - .collect(); - if tokens.len() < 5 { - return BTreeSet::new(); - } - let mut set: BTreeSet = BTreeSet::new(); - for window in tokens.windows(5) { - set.insert(window.join(" ")); - } - set -} - -fn jaccard(a: &BTreeSet, b: &BTreeSet) -> f64 { - if a.is_empty() && b.is_empty() { - return 0.0; - } - let inter = a.intersection(b).count() as f64; - let union = a.union(b).count() as f64; - if union == 0.0 { 0.0 } else { inter / union } -} - -/// §17.7 ReferenceHollowness: bibliography entries + footnote definitions + -/// external citations vs. the subset with verifiable URLs. Phase D has no -/// link-check, so "verifiable" here means: -/// -/// - External-family URLs with a valid host (classified as External / -/// ExternalVendor / Scholarly / IssuePr). -/// - Reference definitions with a non-empty destination matching a URL or -/// path pattern. -/// - Footnote definitions that have a matching reference (we can approximate -/// by treating footnote-definition links as verifiable). -fn compute_reference_hollowness(links: &[LinkRecord]) -> f64 { - let mut total_refs: u64 = 0; - let mut verifiable: u64 = 0; - for l in links { - match l.class { - LinkClass::ReferenceDefinition => { - total_refs += 1; - if !l.destination.trim().is_empty() && looks_reference(&l.destination) { - verifiable += 1; - } - } - LinkClass::Footnote => { - total_refs += 1; - // A footnote reference is "verifiable" if the destination - // resolves to a definition (already reflected in `resolved`). - if matches!(l.resolved, Some(true)) { - verifiable += 1; - } - } - LinkClass::External | LinkClass::ExternalVendor | LinkClass::Scholarly => { - total_refs += 1; - // External URLs are not link-checked in Phase D; count them - // as verifiable because the host/URL shape parses. - verifiable += 1; - } - _ => {} - } - } - if total_refs == 0 { - return 0.0; - } - 1.0 - (verifiable as f64 / total_refs as f64) -} - -fn looks_reference(s: &str) -> bool { - s.contains("://") || s.starts_with('/') || s.contains('.') || s.contains('#') -} - -/// §17.8 placeholder tokens: TODO / TBD / FIXME / XXX / lorem / placeholder, -/// plus empty links / empty images. -fn count_placeholder_tokens(root: &Node<'_>, source: &str, links: &[LinkRecord]) -> u64 { - let mut count = count_placeholder_words(root, source); - for l in links { - let dest = l.destination.trim(); - let dest_lower = dest.to_lowercase(); - if dest.is_empty() - || dest_lower == "tbd" - || dest_lower == "todo" - || dest_lower == "#" - || dest_lower == "placeholder" - { - count += 1; - } - } - count -} - -fn count_placeholder_words(root: &Node<'_>, source: &str) -> u64 { - let mut total = 0u64; - walk_placeholder_words(root, source, &mut total, false); - total -} - -fn walk_placeholder_words(node: &Node<'_>, source: &str, total: &mut u64, inside_prose: bool) { - use NodeKind::*; - let kind = node.kind(); - if is_non_prose_container(kind) { - return; - } - let next_inside = inside_prose || opens_prose_context(kind, ProseContext::PLACEHOLDER_TEXT); - - if next_inside - && matches!(kind, WordToken | IdentifierLikeToken) - && is_placeholder(node_text(node, source).trim()) - { - *total += 1; - } - - for child in node.children() { - walk_placeholder_words(&child, source, total, next_inside); - } -} - -fn is_placeholder(token: &str) -> bool { - if token.is_empty() { - return false; - } - let upper = token.to_ascii_uppercase(); - matches!( - upper.as_str(), - "TODO" | "TBD" | "FIXME" | "XXX" | "LOREM" | "PLACEHOLDER" - ) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn paragraph_shingles_produce_five_token_windows() { - let s = paragraph_shingles("one two three four five six"); - assert_eq!(s.len(), 2); - assert!(s.contains("one two three four five")); - assert!(s.contains("two three four five six")); - } - - #[test] - fn paragraph_shingles_under_five_tokens_is_empty() { - let s = paragraph_shingles("alpha beta gamma delta"); - assert!(s.is_empty()); - } - - #[test] - fn jaccard_of_identical_sets_is_one() { - let a: BTreeSet = ["x", "y", "z"].iter().map(|s| s.to_string()).collect(); - let b: BTreeSet = ["x", "y", "z"].iter().map(|s| s.to_string()).collect(); - assert_eq!(jaccard(&a, &b), 1.0); - } - - #[test] - fn jaccard_of_disjoint_sets_is_zero() { - let a: BTreeSet = ["x"].iter().map(|s| s.to_string()).collect(); - let b: BTreeSet = ["y"].iter().map(|s| s.to_string()).collect(); - assert_eq!(jaccard(&a, &b), 0.0); - } - - #[test] - fn placeholder_detection_is_case_insensitive() { - assert!(is_placeholder("TODO")); - assert!(is_placeholder("tbd")); - assert!(is_placeholder("FIXME")); - assert!(is_placeholder("lorem")); - assert!(!is_placeholder("todo_list")); - assert!(!is_placeholder("fixture")); - } -} diff --git a/crates/mehen-markdown/src/good_scaffold.rs b/crates/mehen-markdown/src/good_scaffold.rs deleted file mode 100644 index 8da04627..00000000 --- a/crates/mehen-markdown/src/good_scaffold.rs +++ /dev/null @@ -1,154 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Good Scaffold Score per §21. -//! -//! ```text -//! GoodScaffoldScore = clamp01( -//! 0.25 * VisualScaffoldScore -//! + 0.20 * TableScaffoldScore -//! + 0.20 * bounded_labelled_code_example_score -//! + 0.15 * InformationScentScore -//! + 0.10 * section_summary_score -//! + 0.10 * successful_internal_navigation_score -//! ) -//! ``` -//! -//! Phase D inputs: -//! -//! - `VisualScaffoldScore` → already populated by Phase C (`visuals`). -//! - `TableScaffoldScore` → already populated by Phase C (`tables`). -//! - `bounded_labelled_code_example_score` → computed here from -//! `ArtifactRecord` rows (labelled code fences of bounded size with -//! nearby explanation). -//! - `InformationScentScore` → already populated by Phase C (`links`). -//! - `section_summary_score` → stays at `0.0` in Phase D. This requires a -//! natural-language summariser which is out of scope; when/if a -//! Phase F summariser lands we'll wire it here without changing the -//! schema. -//! - `successful_internal_navigation_score` → resolved internal anchors / -//! total internal anchors. -//! -//! This score is only a modest offset to DMI. §21 explicitly states it -//! "should never erase objective defects like broken links or parse -//! failures". - -use crate::mathops::clamp01; -use crate::types::{ArtifactKind, ArtifactRecord, LinkClass, LinkRecord, Links, Tables, Visuals}; - -/// §21 output plus intermediate sub-scores so later Phase F / mehen diff -/// can surface them. -#[derive(Debug, Default, Clone)] -pub(crate) struct GoodScaffold { - pub(crate) good_scaffold_score: f64, - #[allow(dead_code)] - pub(crate) bounded_labelled_code_example_score: f64, - #[allow(dead_code)] - pub(crate) successful_internal_navigation_score: f64, - /// Reserved for a future natural-language summariser; always 0.0 for now. - #[allow(dead_code)] - pub(crate) section_summary_score: f64, -} - -/// Compute §21 from Phase A/B/C outputs. -pub(crate) fn analyze_good_scaffold( - artifacts: &[ArtifactRecord], - links_records: &[LinkRecord], - links_agg: &Links, - visuals: &Visuals, - tables: &Tables, -) -> GoodScaffold { - let bounded = bounded_labelled_code_example_score(artifacts); - let internal_nav = successful_internal_navigation_score(links_records); - let section_summary_score = 0.0; - - let raw = 0.25 * visuals.visual_scaffold_score - + 0.20 * tables.table_scaffold_score - + 0.20 * bounded - + 0.15 * links_agg.information_scent_score - + 0.10 * section_summary_score - + 0.10 * internal_nav; - - GoodScaffold { - good_scaffold_score: clamp01(raw), - bounded_labelled_code_example_score: bounded, - successful_internal_navigation_score: internal_nav, - section_summary_score, - } -} - -/// A labelled code fence is "bounded" when it has a language tag, is not -/// oversized (`oversized = false`), and has a nearby explanation. We measure -/// the fraction of code fences that satisfy all three properties. -fn bounded_labelled_code_example_score(artifacts: &[ArtifactRecord]) -> f64 { - let mut code_total: u64 = 0; - let mut bounded: u64 = 0; - for a in artifacts { - if a.kind != ArtifactKind::Code { - continue; - } - code_total += 1; - if a.has_label && !a.oversized && a.has_explanation { - bounded += 1; - } - } - if code_total == 0 { - return 0.0; - } - clamp01(bounded as f64 / code_total as f64) -} - -fn successful_internal_navigation_score(links: &[LinkRecord]) -> f64 { - let mut total_internal: u64 = 0; - let mut resolved: u64 = 0; - for l in links { - if l.class == LinkClass::Internal { - total_internal += 1; - if matches!(l.resolved, Some(true)) { - resolved += 1; - } - } - } - if total_internal == 0 { - 0.0 - } else { - resolved as f64 / total_internal as f64 - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn mk_code(lang: Option<&str>, oversized: bool, explained: bool) -> ArtifactRecord { - ArtifactRecord { - id: 0, - kind: ArtifactKind::Code, - start_line: 1, - end_line: 10, - language_tag: lang.map(String::from), - size: 10, - has_explanation: explained, - has_label: lang.is_some(), - oversized, - burden: 0.0, - } - } - - #[test] - fn bounded_score_is_fraction() { - let arts = vec![ - mk_code(Some("rust"), false, true), - mk_code(Some("py"), false, false), - mk_code(None, false, true), - ]; - let score = bounded_labelled_code_example_score(&arts); - assert!((score - (1.0 / 3.0)).abs() < 1e-9); - } - - #[test] - fn bounded_score_no_code_is_zero() { - let score = bounded_labelled_code_example_score(&[]); - assert_eq!(score, 0.0); - } -} diff --git a/crates/mehen-markdown/src/grounding.rs b/crates/mehen-markdown/src/grounding.rs deleted file mode 100644 index eb9c64ed..00000000 --- a/crates/mehen-markdown/src/grounding.rs +++ /dev/null @@ -1,582 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Repository Grounding Score (§15) and Evidence Coverage Score (§16). -//! -//! Grounding captures how strongly a Markdown document ties back to concrete -//! repository reality (files, commands, identifiers, versions, issues). -//! Evidence coverage asks whether every section carries at least some -//! evidence anchor. Both are Phase-D metrics and never modify Phase A/B/C/E -//! outputs — they only *read* from them. -//! -//! §15.2 formula: -//! -//! ```text -//! RepositoryGroundingScore = clamp01( -//! 0.25 * sat(repo_link_density; 0.5, 4.0) -//! + 0.25 * path_resolution_rate -//! + 0.20 * sat(code_example_density; 0.5, 3.0) -//! + 0.15 * sat(identifier_density; 0.02, 0.12) -//! + 0.15 * sat(version_fact_density; 0.01, 0.08) -//! ) -//! ``` -//! -//! §16.3 formula: `0.5 * mean(section_evidence) + 0.5 * p25(section_evidence)`. - -use std::path::Path; - -use crate::kind::NodeKind; -use crate::mathops::{clamp01, sat}; -use crate::syntax_tree::Node; -use crate::tree_helpers::{ProseContext, is_non_prose_container, node_text, opens_prose_context}; -use crate::types::{ArtifactKind, ArtifactRecord, LinkClass, LinkRecord, Section, TableRecord}; - -/// Inputs collected from the AST walk that feed both §15 and §17.6 / -/// §17.2 specificity / artifact-density computations. -#[derive(Debug, Default, Clone)] -pub(crate) struct GroundingTokenCounts { - /// `identifier_like_token` occurrences inside prose contexts. - pub(crate) identifier_like_tokens: u64, - /// `path_like_token` occurrences inside prose contexts. - pub(crate) path_like_tokens: u64, - /// `path_like_token` occurrences that resolve to a repo file/dir. - #[allow(dead_code)] - pub(crate) resolved_path_like_tokens: u64, - /// Numeric tokens matching `^v?\d+\.\d+(\.\d+)?$`. Subset of - /// `numeric_tokens`. - #[allow(dead_code)] - pub(crate) version_tokens: u64, - /// All `numeric_token` occurrences inside prose. - pub(crate) numeric_tokens: u64, - /// Raw inline code tokens (inline_code nodes). - pub(crate) inline_code_tokens: u64, -} - -/// Final §15 output plus per-section anchor counts used for §16 / §17. -/// -/// Several fields here are populated for auditability and Phase F's -/// `mehen diff` sticky comment, and are not read by the analyzer itself; -/// they are annotated with `#[allow(dead_code)]` rather than dropped so the -/// intermediate surface stays traceable. The analyzer only reads -/// `repository_grounding_score`, `evidence_coverage_score`, `anchored_words`, -/// and `tokens`. -#[derive(Debug, Clone)] -pub(crate) struct GroundingOutputs { - pub(crate) repository_grounding_score: f64, - pub(crate) evidence_coverage_score: f64, - /// Per-section evidence anchor counts, indexed by `section_id`. - /// Sections at index 0 → section_id 0, etc. Length matches `sections.len()`. - #[allow(dead_code)] - pub(crate) per_section_anchors: Vec, - /// Normalized per-section evidence score per §16.2 (saturated - /// `anchor_density_s`). Indexed by `section_id`. - #[allow(dead_code)] - pub(crate) per_section_evidence: Vec, - /// Words in sections that have at least one evidence anchor. - pub(crate) anchored_words: u64, - /// Copy-back of the §15 intermediate token counts so Phase D - /// filler/specificity modules don't walk the tree again. - pub(crate) tokens: GroundingTokenCounts, - /// Labelled code fences (info_string non-empty). Re-exported so §15 - /// code_example_density and §19 artifact debt don't recount. - #[allow(dead_code)] - pub(crate) labelled_code_fences: u64, - /// Command-shell fences (`bash`, `sh`, `shell`, `zsh`). Subset of - /// `labelled_code_fences`. - #[allow(dead_code)] - pub(crate) command_blocks: u64, - /// Path-like tokens containing at least one `.` (heuristic for - /// package/API/config identifiers per §15). - #[allow(dead_code)] - pub(crate) package_api_config_tokens: u64, - /// Resolved relative links. - #[allow(dead_code)] - pub(crate) resolved_relative_links: u64, - /// Resolved internal anchors. - #[allow(dead_code)] - pub(crate) resolved_internal_anchors: u64, - /// Issue/PR references. - #[allow(dead_code)] - pub(crate) issue_pr_refs: u64, -} - -/// Top-level Phase-D entry point for grounding + evidence. -#[allow(clippy::too_many_arguments)] -pub(crate) fn analyze_grounding( - root: &Node<'_>, - source: &str, - file_path: &Path, - words: u64, - sections: &[Section], - links: &[LinkRecord], - artifacts: &[ArtifactRecord], - tables: &[TableRecord], -) -> GroundingOutputs { - let tokens = collect_token_counts(root, source, file_path); - let labelled_code_fences = artifacts - .iter() - .filter(|a| a.kind == ArtifactKind::Code && a.has_label) - .count() as u64; - let command_blocks = artifacts - .iter() - .filter(|a| { - a.kind == ArtifactKind::Code - && a.language_tag - .as_deref() - .map(is_command_shell) - .unwrap_or(false) - }) - .count() as u64; - let package_api_config_tokens = collect_package_api_config_tokens(root, source, file_path); - - let resolved_relative_links = links - .iter() - .filter(|l| l.class == LinkClass::Relative && matches!(l.resolved, Some(true))) - .count() as u64; - let resolved_internal_anchors = links - .iter() - .filter(|l| l.class == LinkClass::Internal && matches!(l.resolved, Some(true))) - .count() as u64; - let issue_pr_refs = links - .iter() - .filter(|l| l.class == LinkClass::IssuePr) - .count() as u64; - - // §15.2 densities. - let w = words as f64; - let repo_link_density = resolved_relative_links as f64 / (w / 500.0).max(1.0); - let path_resolution_rate = if tokens.path_like_tokens == 0 { - // §15.2: max(1, path_like_tokens). No paths → score 0 for this term. - 0.0 - } else { - tokens.resolved_path_like_tokens as f64 / tokens.path_like_tokens as f64 - }; - let code_example_density = labelled_code_fences as f64 / (w / 800.0).max(1.0); - let identifier_density = tokens.identifier_like_tokens as f64 / w.max(1.0); - let version_fact_density = tokens.version_tokens as f64 / w.max(1.0); - - let repository_grounding_score = clamp01( - 0.25 * sat(repo_link_density, 0.5, 4.0) - + 0.25 * path_resolution_rate.clamp(0.0, 1.0) - + 0.20 * sat(code_example_density, 0.5, 3.0) - + 0.15 * sat(identifier_density, 0.02, 0.12) - + 0.15 * sat(version_fact_density, 0.01, 0.08), - ); - - // §16: per-section evidence anchors. - // - // Walk the tree once more to attribute each resolved `path_like_token` - // to its enclosing section so §16.1 "path-like token resolved to - // repository" actually shows up in per-section anchor density. - let base_dir = file_path - .parent() - .map(std::path::Path::to_path_buf) - .unwrap_or_else(|| std::path::PathBuf::from(".")); - let per_section_resolved_paths = - collect_per_section_resolved_paths(root, source, &base_dir, sections); - let per_section_anchors = compute_per_section_anchors( - sections, - links, - artifacts, - tables, - &per_section_resolved_paths, - ); - - let mut per_section_evidence: Vec = Vec::with_capacity(sections.len()); - let mut anchored_words: u64 = 0; - for (i, section) in sections.iter().enumerate() { - let ws = section.word_count as f64; - let anchor_density = per_section_anchors[i] as f64 / (ws / 250.0).max(1.0); - let sec_ev = sat(anchor_density, 0.2, 1.5); - per_section_evidence.push(sec_ev); - if per_section_anchors[i] > 0 { - anchored_words += section.word_count; - } - } - - // §16.3 aggregate: 0.5 * mean + 0.5 * p25. - let evidence_coverage_score = if per_section_evidence.is_empty() { - 0.0 - } else { - let mean: f64 = - per_section_evidence.iter().sum::() / per_section_evidence.len() as f64; - let p25 = percentile(&per_section_evidence, 0.25); - 0.5 * mean + 0.5 * p25 - }; - - GroundingOutputs { - repository_grounding_score, - evidence_coverage_score, - per_section_anchors, - per_section_evidence, - anchored_words, - tokens, - labelled_code_fences, - command_blocks, - package_api_config_tokens, - resolved_relative_links, - resolved_internal_anchors, - issue_pr_refs, - } -} - -/// Count §15.1 / §17.6 token classes. Only walks prose contexts so shell -/// snippets inside a code fence don't inflate the identifier density. -fn collect_token_counts(root: &Node<'_>, source: &str, file_path: &Path) -> GroundingTokenCounts { - let mut out = GroundingTokenCounts::default(); - let base = file_path.parent().unwrap_or_else(|| Path::new(".")); - visit_token_counts(root, source, &base.to_path_buf(), &mut out, false); - out -} - -fn visit_token_counts( - node: &Node<'_>, - source: &str, - base: &std::path::PathBuf, - out: &mut GroundingTokenCounts, - inside_prose: bool, -) { - use NodeKind::*; - - let kind = node.kind(); - - // Inline code is machine-readable but still a grounding signal inside - // prose, so count the node itself and skip its children. - if kind == InlineCode { - if inside_prose { - out.inline_code_tokens += 1; - } - return; - } - - if is_non_prose_container(kind) { - return; - } - - let next_inside = - inside_prose || opens_prose_context(kind, ProseContext::BODY_AND_HEADING_TEXT); - - if next_inside { - match kind { - IdentifierLikeToken => { - out.identifier_like_tokens += 1; - } - PathLikeToken => { - out.path_like_tokens += 1; - let text = node_text(node, source); - if repo_resolves(base, &text) { - out.resolved_path_like_tokens += 1; - } - } - NumericToken => { - out.numeric_tokens += 1; - let text = node_text(node, source); - if is_version_like(&text) { - out.version_tokens += 1; - } - } - _ => {} - } - } - - for child in node.children() { - visit_token_counts(&child, source, base, out, next_inside); - } -} - -/// Count `path_like_token` occurrences that contain at least one `.`. -/// Heuristic per task spec for "package/API/config identifier" signals. -fn collect_package_api_config_tokens(root: &Node<'_>, source: &str, _file_path: &Path) -> u64 { - let mut total = 0u64; - visit_package_api_config(root, source, &mut total, false); - total -} - -fn visit_package_api_config(node: &Node<'_>, source: &str, total: &mut u64, inside_prose: bool) { - use NodeKind::*; - let kind = node.kind(); - if is_non_prose_container(kind) { - return; - } - let next_inside = - inside_prose || opens_prose_context(kind, ProseContext::BODY_AND_HEADING_TEXT); - - if next_inside && kind == PathLikeToken { - let text = node_text(node, source); - if text.contains('.') { - *total += 1; - } - } - - for child in node.children() { - visit_package_api_config(&child, source, total, next_inside); - } -} - -fn repo_resolves(base: &Path, path: &str) -> bool { - if path.is_empty() { - return false; - } - if path.contains("://") - || path.starts_with("http:") - || path.starts_with("https:") - || path.starts_with("mailto:") - || path.starts_with("tel:") - { - return false; - } - // Strip fragment / query, since path_like_tokens may carry them. - let path = path.split_once('#').map(|x| x.0).unwrap_or(path); - let path = path.split_once('?').map(|x| x.0).unwrap_or(path); - if path.is_empty() { - return false; - } - let stripped = path.strip_prefix('/').unwrap_or(path); - let candidate = base.join(stripped); - candidate.exists() -} - -/// Matches `\d+\.\d+(\.\d+)?` with an optional leading `v`. -fn is_version_like(text: &str) -> bool { - let s = text.trim(); - let s = s.strip_prefix('v').or(s.strip_prefix('V')).unwrap_or(s); - let mut iter = s.split('.'); - let Some(first) = iter.next() else { - return false; - }; - let Some(second) = iter.next() else { - return false; - }; - let third = iter.next(); - if iter.next().is_some() { - return false; - } - if !is_all_ascii_digits(first) || !is_all_ascii_digits(second) { - return false; - } - match third { - None => true, - Some(t) => is_all_ascii_digits(t), - } -} - -fn is_all_ascii_digits(s: &str) -> bool { - !s.is_empty() && s.chars().all(|c| c.is_ascii_digit()) -} - -fn is_command_shell(lang: &str) -> bool { - matches!( - lang.trim().to_ascii_lowercase().as_str(), - "bash" | "sh" | "shell" | "zsh" - ) -} - -/// Count per-section evidence anchors per §16.1. An anchor is: -/// - resolved relative link OR external link OR internal-link to non-trivial section -/// - labelled code fence, table with header, parseable diagram -/// - image with alt/caption -/// - math block with nearby explanation -/// - issue/PR/scholarly reference link -/// - path-like token resolved to repository -/// -/// Each artifact / link / token counts the section it falls inside once. -fn compute_per_section_anchors( - sections: &[Section], - links: &[LinkRecord], - artifacts: &[ArtifactRecord], - tables: &[TableRecord], - per_section_resolved_paths: &[u64], -) -> Vec { - let n = sections.len(); - if n == 0 { - return Vec::new(); - } - let mut anchors: Vec = vec![0; n]; - - for l in links { - let is_anchor = match l.class { - LinkClass::Relative => matches!(l.resolved, Some(true)), - LinkClass::External | LinkClass::ExternalVendor | LinkClass::Scholarly => true, - LinkClass::Internal => { - // internal link to non-trivial section: treat resolved internal as evidence. - matches!(l.resolved, Some(true)) - } - LinkClass::IssuePr => true, - LinkClass::AbsoluteSameRepo - | LinkClass::Footnote - | LinkClass::UnresolvedReferenceUse - | LinkClass::ReferenceDefinition => false, - }; - if !is_anchor { - continue; - } - if let Some(idx) = locate_section_by_line(sections, l.line) { - anchors[idx] += 1; - } - } - - for a in artifacts { - let is_anchor = match a.kind { - ArtifactKind::Code => a.has_label, // labelled fence - // §16.1 "parseable diagram": a diagram counts only when it - // has a label AND parsed cleanly — diagrams that errored - // during parsing (Phase C sets `oversized`/parse-error in - // the diagram analyzer) are not evidence. - ArtifactKind::Diagram => a.has_label && !a.oversized, - ArtifactKind::Image => a.has_label, // image with alt/caption - ArtifactKind::Math => a.has_explanation, // math with nearby explanation - ArtifactKind::Table => false, // handled below to check header separately - ArtifactKind::Html => false, - }; - if !is_anchor { - continue; - } - if let Some(idx) = locate_section_by_line(sections, a.start_line) { - anchors[idx] += 1; - } - } - - for t in tables { - if !t.has_header { - continue; - } - if let Some(idx) = locate_section_by_line(sections, t.start_line) { - anchors[idx] += 1; - } - } - - // §16.1 "path-like token resolved to repository": credit each - // section for every resolved `path_like_token` that lives inside it. - for (idx, count) in per_section_resolved_paths.iter().enumerate() { - if idx < anchors.len() { - anchors[idx] = anchors[idx].saturating_add(*count); - } - } - - anchors -} - -/// Walk the AST and tally the number of resolved `path_like_token`s per -/// section. Prose-context-gated (same logic as `visit_token_counts`) so -/// tokens inside code fences / HTML / front-matter don't double-count. -fn collect_per_section_resolved_paths( - root: &Node<'_>, - source: &str, - base: &Path, - sections: &[Section], -) -> Vec { - let mut counts: Vec = vec![0; sections.len()]; - if sections.is_empty() { - return counts; - } - visit_per_section_resolved_paths(root, source, base, &mut counts, sections, false); - counts -} - -fn visit_per_section_resolved_paths( - node: &Node<'_>, - source: &str, - base: &Path, - counts: &mut [u64], - sections: &[Section], - inside_prose: bool, -) { - use NodeKind::*; - let kind = node.kind(); - if is_non_prose_container(kind) { - return; - } - let next_inside = inside_prose || opens_prose_context(kind, ProseContext::SECTION_TEXT); - if next_inside && matches!(kind, PathLikeToken) { - let text = node_text(node, source); - if repo_resolves(base, &text) { - let line = (node.start_row() as u64) + 1; - if let Some(idx) = locate_section_by_line(sections, line) { - counts[idx] = counts[idx].saturating_add(1); - } - } - } - for child in node.children() { - visit_per_section_resolved_paths(&child, source, base, counts, sections, next_inside); - } -} - -fn locate_section_by_line(sections: &[Section], line: u64) -> Option { - // §3.4: walk the leaf-most section whose [start_line, end_line] contains `line`. - // Sections are stored in a pre-order walk, so the last matching section is - // the innermost. - let mut best: Option<(usize, u64)> = None; - for (i, s) in sections.iter().enumerate() { - if line >= s.start_line && line <= s.end_line { - let width = s.end_line.saturating_sub(s.start_line); - match best { - Some((_, best_width)) if width >= best_width => {} - _ => best = Some((i, width)), - } - } - } - best.map(|(i, _)| i) -} - -fn percentile(values: &[f64], q: f64) -> f64 { - if values.is_empty() { - return 0.0; - } - let mut sorted: Vec = values.to_vec(); - sorted.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)); - // Linear interpolation between closest ranks (NIST C=1 / type 7). - let n = sorted.len(); - if n == 1 { - return sorted[0]; - } - let pos = q * (n as f64 - 1.0); - let lo = pos.floor() as usize; - let hi = pos.ceil() as usize; - if lo == hi { - sorted[lo] - } else { - let frac = pos - lo as f64; - sorted[lo] * (1.0 - frac) + sorted[hi] * frac - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn version_like_detects_common_shapes() { - assert!(is_version_like("1.0")); - assert!(is_version_like("1.2.3")); - assert!(is_version_like("v12.4")); - assert!(is_version_like("V1.0.0")); - assert!(!is_version_like("1")); - assert!(!is_version_like("1.2.3.4")); - assert!(!is_version_like("v.1.2")); - assert!(!is_version_like("abc")); - } - - #[test] - fn percentile_q25_of_four_values() { - // Type-7 percentile of [1, 2, 3, 4] at q=0.25 → pos = 0.75, so - // 1 * 0.25 + 2 * 0.75 = 1.75. Reference value for the §16.3 p25 - // term. - let p = percentile(&[1.0, 2.0, 3.0, 4.0], 0.25); - assert!((p - 1.75).abs() < 1e-9, "got {p}"); - } - - #[test] - fn percentile_single_element() { - assert_eq!(percentile(&[5.0], 0.25), 5.0); - assert_eq!(percentile(&[], 0.25), 0.0); - } - - #[test] - fn command_shell_matches_canonical_tags() { - assert!(is_command_shell("bash")); - assert!(is_command_shell("SH")); - assert!(is_command_shell(" shell")); - assert!(is_command_shell("zsh")); - assert!(!is_command_shell("rust")); - } -} diff --git a/crates/mehen-markdown/src/halstead.rs b/crates/mehen-markdown/src/halstead.rs deleted file mode 100644 index 75be07c3..00000000 --- a/crates/mehen-markdown/src/halstead.rs +++ /dev/null @@ -1,497 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Markdown Halstead metrics per §9. -//! -//! Walks the AST once and classifies each leaf / inline / block node as -//! operator or operand following §§9.1-9.2, using the Pulldown-backed Markdown -//! syntax node kinds. Operators are identified by kind (so all `##` H2 -//! markers share one operator class); operands are identified by their byte -//! text (so two occurrences of the same word count once in n2 but twice in -//! N2, matching classical Halstead). -//! -//! §9.3 formulas: -//! -//! ```text -//! vocab = n1 + n2 -//! length = N1 + N2 -//! volume = length * log2(max(2, vocab)) -//! diff = (n1 / 2) * (N2 / max(1, n2)) -//! effort = volume * diff -//! ``` -//! -//! §9.4 embedded-code adjustment happens outside this module in -//! `embedded_code.rs` and is composed into the final `Halstead` record by -//! the analyzer. - -use std::collections::BTreeMap; - -use crate::document::MarkdownDocument; -use crate::kind::{HeadingStyle, NodeKind}; -use crate::syntax_tree::Node; -use crate::types::Halstead; - -/// Distinct operator classes (rich enough that MCC and Halstead use the same -/// shape). Each variant represents one row in §9.1. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -enum OperatorKind { - HeadingMarkerH1, - HeadingMarkerH2, - HeadingMarkerH3, - HeadingMarkerH4, - HeadingMarkerH5, - HeadingMarkerH6, - SetextMarkerH1, - SetextMarkerH2, - ListMarker, - TaskMarkerChecked, - TaskMarkerUnchecked, - TableDelim, - TableAlignLeft, - TableAlignRight, - LinkOp, - ImageOp, - /// Code fence by language tag (empty for unlabelled). Stored - /// separately as a string so each tag is its own operator class. - FenceTag(String), - InlineCodeOp, - BlockquoteMarker, - CalloutOp, - MathDelimiter, - RawHtmlOp, - /// Terminator (`. ? ! 。 …`). - Terminator, - /// Separator (`, ; :`). - Separator, - /// Bracket (`() [] {} <>`). - Bracket, - /// Operator-like (`= + - * / | & :: -> =>`). - OperatorLike, -} - -/// Maps a heading marker's level and style to its operator class. -/// -/// Each ATX level (`#`..`######`) is a distinct operator, as is each setext -/// underline level; this mirrors the pre-refactor per-marker operator table. -/// Setext is only defined for levels 1 and 2 (see `resolve_heading`), so -/// higher setext levels fall back to the ATX class for that level. -fn heading_marker_op(level: u8, style: HeadingStyle) -> OperatorKind { - match (style, level) { - (HeadingStyle::Setext, 1) => OperatorKind::SetextMarkerH1, - (HeadingStyle::Setext, 2) => OperatorKind::SetextMarkerH2, - (_, 1) => OperatorKind::HeadingMarkerH1, - (_, 2) => OperatorKind::HeadingMarkerH2, - (_, 3) => OperatorKind::HeadingMarkerH3, - (_, 4) => OperatorKind::HeadingMarkerH4, - (_, 5) => OperatorKind::HeadingMarkerH5, - _ => OperatorKind::HeadingMarkerH6, - } -} - -/// Core public entry point. Walks the AST and emits the §9.3 derived values. -pub(crate) fn compute_halstead( - root: &Node<'_>, - document: &MarkdownDocument, - source: &str, -) -> Halstead { - let mut operator_counts: BTreeMap = BTreeMap::new(); - let mut operand_counts: BTreeMap = BTreeMap::new(); - - let mut state = Ctx { - operator_counts: &mut operator_counts, - operand_counts: &mut operand_counts, - source, - document, - }; - state.walk(root); - - // §9.3. - let n1 = operator_counts.len() as u64; - let big_n1: u64 = operator_counts.values().sum(); - let n2 = operand_counts.len() as u64; - let big_n2: u64 = operand_counts.values().sum(); - - let vocabulary = n1 + n2; - let length = big_n1 + big_n2; - let vocab_f = vocabulary.max(2) as f64; - let volume = length as f64 * vocab_f.log2(); - let difficulty = if n2 > 0 { - (n1 as f64 / 2.0) * (big_n2 as f64 / n2 as f64) - } else { - 0.0 - }; - let effort = volume * difficulty; - - Halstead { - operators_distinct: n1, - operators_total: big_n1, - operands_distinct: n2, - operands_total: big_n2, - vocabulary, - length, - volume, - difficulty, - effort, - // embedded_volume + total_volume are filled in by the analyzer after - // embedded-code dispatch. - embedded_volume: 0.0, - total_volume: volume, - } -} - -struct Ctx<'counts, 'source, 'doc> { - operator_counts: &'counts mut BTreeMap, - operand_counts: &'counts mut BTreeMap, - source: &'source str, - document: &'doc MarkdownDocument, -} - -impl Ctx<'_, '_, '_> { - fn bump_op(&mut self, k: OperatorKind) { - *self.operator_counts.entry(k).or_insert(0) += 1; - } - - fn bump_operand(&mut self, key: String) { - if key.is_empty() { - return; - } - *self.operand_counts.entry(key).or_insert(0) += 1; - } - - fn walk(&mut self, node: &Node<'_>) { - use NodeKind::*; - - let kind = node.kind(); - - // Stop containers for operands that are URL / code text — still - // classify them as operators at the wrapper level. - let mut descend = true; - - match kind { - // Heading markers — one operator per level/style. `#` and `##` - // are distinct operators; setext underlines have their own class. - HeadingMarker { level, style } => { - self.bump_op(heading_marker_op(level, style)); - } - - // List markers — every bullet/number style is one operator class. - ListMarker => self.bump_op(OperatorKind::ListMarker), - - // Task list markers. - TaskListMarkerChecked => self.bump_op(OperatorKind::TaskMarkerChecked), - TaskListMarkerUnchecked => self.bump_op(OperatorKind::TaskMarkerUnchecked), - - // Table operators. - PipeTableDelimiterRow | PipeTableDelimiterCell => { - self.bump_op(OperatorKind::TableDelim) - } - PipeTableAlignLeft => self.bump_op(OperatorKind::TableAlignLeft), - PipeTableAlignRight => self.bump_op(OperatorKind::TableAlignRight), - - // Link / image wrappers — each whole `Link` is one operator - // occurrence for `[…](…)`. Inner LinkLabel prose descends as - // operand text; destination operands come from pulldown-resolved - // document facts so reference-style links use the definition - // target instead of the local reference key. - Link => { - self.bump_op(OperatorKind::LinkOp); - if let Some(dest) = self - .document - .link_destination_by_span(node.start_byte(), node.end_byte()) - { - self.bump_operand(dest.to_string()); - } - } - Image => { - self.bump_op(OperatorKind::ImageOp); - if let Some(dest) = self - .document - .link_destination_by_span(node.start_byte(), node.end_byte()) - { - self.bump_operand(dest.to_string()); - } - } - - // Code fences: record the language tag as the operator's - // discriminator so e.g. `rust` and `python` are distinct - // operators. - FencedCodeBlock | IndentedCodeBlock => { - if let Some(block) = self.document.code_block_by_start_row(node.start_row()) { - let tag = block.language.clone().unwrap_or_default(); - self.bump_op(OperatorKind::FenceTag(tag)); - // Embedded content is a single opaque operand so §9.4's - // embedded-code scaling can own language-specific detail. - let prefix = if block.is_fenced() { - "code" - } else { - "indent_code" - }; - self.bump_operand(format!("{prefix}:{}", sha_hex(block.content.as_bytes()))); - } - descend = false; - } - - InlineCode => { - self.bump_op(OperatorKind::InlineCodeOp); - // The inline-code content is opaque; hash it so two identical - // `` `foo` `` references count as one operand. - if let Some(text) = inline_code_text(node, self.source) { - self.bump_operand(format!("inline:{}", sha_hex(text.as_bytes()))); - } - descend = false; - } - - // Blockquote and callout markers. - BlockQuoteMarker => self.bump_op(OperatorKind::BlockquoteMarker), - CalloutMarkerOpen | CalloutMarkerClose | CalloutType => { - self.bump_op(OperatorKind::CalloutOp) - } - - // Math delimiters. Only the block delimiter is emitted by the - // pulldown-backed builder; inline math carries no delimiter node. - MathBlockDelimiter => self.bump_op(OperatorKind::MathDelimiter), - - // Raw HTML operators. - HtmlOpenTag - | HtmlCloseTag - | HtmlComment - | HtmlCdata - | HtmlDeclaration - | HtmlProcessingInstruction => self.bump_op(OperatorKind::RawHtmlOp), - - // Punctuation classes per §3.3. - Terminator => self.bump_op(OperatorKind::Terminator), - Separator => self.bump_op(OperatorKind::Separator), - Bracket => self.bump_op(OperatorKind::Bracket), - OperatorLike => self.bump_op(OperatorKind::OperatorLike), - - // Operand leaves. - WordToken => { - self.push_text_operand(node); - } - NumericToken => { - self.push_text_operand(node); - } - IdentifierLikeToken => { - self.push_text_operand(node); - } - PathLikeToken => { - self.push_text_operand(node); - } - - // Link definitions are plumbing for reference-style links. The - // rendered link use owns the semantic destination operand. - LinkReferenceDefinition => { - descend = false; - } - - // Link destinations are handled at the `Link` / `Image` wrapper - // so reference-style links can resolve semantically. Autolink - // URIs have no wrapper destination, so keep counting those here. - LinkDestination => { - descend = false; - } - Uri => { - self.push_text_operand(node); - descend = false; - } - - // Table headers (header row cells) — count each cell's text as - // an operand in addition to any word-like tokens inside it. - // §9.2 lists "table headers" as a distinct operand class. - PipeTableHeader => { - for cell in node.children() { - if matches!(cell.kind(), NodeKind::PipeTableCell) { - let text = node_text(&cell, self.source).trim().to_string(); - if !text.is_empty() { - self.bump_operand(format!("th:{}", text)); - } - } - } - // Fall through: descend so each word token in the header - // row also contributes as a regular word operand. - } - - _ => {} - } - - if !descend { - return; - } - - for child in node.children() { - self.walk(&child); - } - } - - fn push_text_operand(&mut self, node: &Node<'_>) { - let bytes = self.source.as_bytes(); - let start = node.start_byte(); - let end = node.end_byte(); - if end <= bytes.len() && start < end { - let text = std::str::from_utf8(&bytes[start..end]) - .unwrap_or("") - .trim() - .to_string(); - if !text.is_empty() { - self.bump_operand(text); - } - } - } -} - -fn inline_code_text(node: &Node<'_>, source: &str) -> Option { - let bytes = source.as_bytes(); - let start = node.start_byte(); - let end = node.end_byte(); - if end <= bytes.len() && start < end { - return std::str::from_utf8(&bytes[start..end]) - .ok() - .map(|s| s.trim().trim_matches('`').to_string()); - } - None -} - -fn node_text(node: &Node<'_>, source: &str) -> String { - let bytes = source.as_bytes(); - let start = node.start_byte(); - let end = node.end_byte(); - if end <= bytes.len() && start < end { - std::str::from_utf8(&bytes[start..end]) - .unwrap_or("") - .to_string() - } else { - String::new() - } -} - -/// Cheap deterministic hash → lowercase hex. We only need stable -/// equivalence, so the FNV-1a 64-bit variant is plenty. -fn sha_hex(bytes: &[u8]) -> String { - // FNV-1a 64-bit. - let mut h: u64 = 0xcbf29ce484222325; - for &b in bytes { - h ^= b as u64; - h = h.wrapping_mul(0x100000001b3); - } - format!("{h:016x}") -} - -#[cfg(test)] -mod tests { - use super::*; - use std::collections::BTreeMap; - - fn compute(src: &str) -> Halstead { - let (tree, document) = crate::syntax_tree::parse_with_document(src); - compute_halstead(&tree.root(), &document, src) - } - - fn operand_counts(src: &str) -> BTreeMap { - let (tree, document) = crate::syntax_tree::parse_with_document(src); - let mut operator_counts = BTreeMap::new(); - let mut operand_counts = BTreeMap::new(); - let mut state = Ctx { - operator_counts: &mut operator_counts, - operand_counts: &mut operand_counts, - source: src, - document: &document, - }; - state.walk(&tree.root()); - operand_counts - } - - fn assert_halstead_close(a: &Halstead, b: &Halstead) { - assert_eq!(a.operators_distinct, b.operators_distinct); - assert_eq!(a.operators_total, b.operators_total); - assert_eq!(a.operands_distinct, b.operands_distinct); - assert_eq!(a.operands_total, b.operands_total); - assert_eq!(a.vocabulary, b.vocabulary); - assert_eq!(a.length, b.length); - assert!((a.volume - b.volume).abs() < 1e-9, "{a:?} != {b:?}"); - assert!((a.difficulty - b.difficulty).abs() < 1e-9, "{a:?} != {b:?}"); - assert!((a.effort - b.effort).abs() < 1e-9, "{a:?} != {b:?}"); - assert!( - (a.total_volume - b.total_volume).abs() < 1e-9, - "{a:?} != {b:?}" - ); - } - - #[test] - fn empty_halstead_is_zero() { - let h = compute(""); - assert_eq!(h.operators_distinct, 0); - assert_eq!(h.operators_total, 0); - assert_eq!(h.operands_distinct, 0); - assert_eq!(h.operands_total, 0); - assert_eq!(h.vocabulary, 0); - assert_eq!(h.length, 0); - assert_eq!(h.volume, 0.0); - assert_eq!(h.total_volume, 0.0); - } - - #[test] - fn heading_plus_prose_counts() { - let src = "# Hello world\n"; - let h = compute(src); - // Operators: 1 H1 marker → n1=1, N1=1. - assert_eq!(h.operators_distinct, 1); - assert_eq!(h.operators_total, 1); - // Operands: `Hello`, `world` → n2=2, N2=2. - assert_eq!(h.operands_distinct, 2); - assert_eq!(h.operands_total, 2); - assert_eq!(h.vocabulary, 3); - assert_eq!(h.length, 3); - // Volume = 3 * log2(3) ≈ 4.754887. - assert!((h.volume - 3.0 * (3.0_f64).log2()).abs() < 1e-6); - } - - #[test] - fn link_counts_as_operator_and_url_as_operand() { - let src = "# H\n\nSee [here](https://example.com).\n"; - let h = compute(src); - // Operators include: one H1 marker, one Link, one Terminator (`.`). - assert!(h.operators_distinct >= 3); - // The URL is one operand; `See` and `here` are word operands. - assert!(h.operands_distinct >= 3); - } - - #[test] - fn reference_style_link_destinations_match_inline_halstead() { - let inline = "# H\n\nSee [docs](https://example.com).\n"; - let cases = [ - "# H\n\nSee [docs][api].\n\n[api]: https://example.com\n", - "# H\n\nSee [docs][].\n\n[docs]: https://example.com\n", - "# H\n\nSee [docs].\n\n[docs]: https://example.com\n", - "# H\n\nSee [docs][api\\]].\n\n[api\\]]: https://example.com\n", - ]; - - let expected = compute(inline); - for reference in cases { - let actual = compute(reference); - assert_halstead_close(&expected, &actual); - } - - let full_reference_operands = operand_counts(cases[0]); - assert_eq!(full_reference_operands.get("https://example.com"), Some(&1)); - assert!( - !full_reference_operands.contains_key("api"), - "reference key leaked into Halstead operands: {full_reference_operands:?}" - ); - } - - #[test] - fn reference_style_image_destinations_match_inline_halstead() { - let inline = "# H\n\n![diagram](https://example.com/diagram.png)\n"; - let reference = "# H\n\n![diagram][asset]\n\n[asset]: https://example.com/diagram.png\n"; - - assert_halstead_close(&compute(inline), &compute(reference)); - - let operands = operand_counts(reference); - assert_eq!(operands.get("https://example.com/diagram.png"), Some(&1)); - assert!( - !operands.contains_key("asset"), - "image reference key leaked into Halstead operands: {operands:?}" - ); - } -} diff --git a/crates/mehen-markdown/src/kind.rs b/crates/mehen-markdown/src/kind.rs deleted file mode 100644 index 7e314c65..00000000 --- a/crates/mehen-markdown/src/kind.rs +++ /dev/null @@ -1,199 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Node kinds for the internal Markdown syntax tree. -//! -//! This is a hand-authored vocabulary that mirrors the `pulldown-cmark` -//! event surface the [`crate::syntax_tree`] builder consumes — not a -//! generated tree-sitter kind table. The crate migrated off tree-sitter to -//! `pulldown-cmark` (see `Cargo.toml`), so kinds are modeled directly as a -//! Rust enum: levels and flags that tree-sitter would encode as separate -//! node *types* (`atx_heading` vs `atx_heading2` …) are carried here as -//! *data* on a single variant instead. -//! -//! Only kinds the builder actually constructs are represented. Passes match -//! on [`NodeKind`] by value; heading level and the atx/setext distinction are -//! read from the variant payload rather than from a child marker or a named -//! field. - -use pulldown_cmark::HeadingLevel; - -/// The style of a heading marker. -/// -/// `Atx` is `#`-prefixed; `Setext` is the underlined form (`===` / `---`). -/// Halstead treats each as a distinct operator (`heading_marker_op`), so the -/// flag is preserved as data on `Heading` / `HeadingMarker`. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(crate) enum HeadingStyle { - Atx, - Setext, -} - -/// A node kind in the compact Markdown tree. -/// -/// Variants correspond to the blocks, inlines, and synthesized sub-spans the -/// builder emits. Numbered tree-sitter families (`atx_heading2..6`, -/// `list_item2..5`, `section1..6`) are folded into data-carrying variants: -/// the level/flag lives in the payload, and passes that previously matched -/// the whole family now match one variant. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(crate) enum NodeKind { - // ── Document root & structure ────────────────────────────────────── - /// The document root. - Document, - /// A synthesized section wrapper introduced by heading nesting. - /// - /// `level` is the 1..=6 level of the heading that opens the section; - /// heading-less top-level content is not wrapped in a `Section`. - Section { - level: u8, - }, - - // ── Headings ─────────────────────────────────────────────────────── - /// A heading. `level` is 1..=6; `style` distinguishes `#` from setext. - Heading { - level: u8, - style: HeadingStyle, - }, - /// The heading marker span (`#`/`##`/… or the `===`/`---` underline). - /// - /// Kept distinct from the heading because Halstead counts the marker as - /// a per-level operator. - HeadingMarker { - level: u8, - style: HeadingStyle, - }, - /// The inline-content span of a heading. - HeadingContent, - - // ── Block containers ─────────────────────────────────────────────── - Paragraph, - BlockQuote, - /// A blockquote carrying a callout marker (`> [!NOTE]`). - Callout, - CalloutMarkerOpen, - CalloutType, - CalloutMarkerClose, - BlockQuoteMarker, - List, - /// A list item. `task` marks a `- [ ]`/`- [x]` checklist item. - ListItem { - task: bool, - }, - ListItemContent { - task: bool, - }, - ListMarker, - TaskListMarkerChecked, - TaskListMarkerUnchecked, - - // ── Code ─────────────────────────────────────────────────────────── - FencedCodeBlock, - IndentedCodeBlock, - CodeFenceContent, - IndentedChunk, - InfoString, - Language, - InlineCode, - InlineCodeContent, - - // ── Math ─────────────────────────────────────────────────────────── - MathBlock, - MathBlockDelimiter, - MathBlockContent, - MathInline, - MathInlineContent, - - // ── Tables ───────────────────────────────────────────────────────── - PipeTable, - PipeTableHeader, - PipeTableRow, - PipeTableCell, - PipeTableDelimiterRow, - PipeTableDelimiterCell, - PipeTableAlignLeft, - PipeTableAlignRight, - - // ── Links, images, references ────────────────────────────────────── - Link, - Image, - Autolink, - Uri, - Email, - LinkLabel, - LinkDestination, - LinkTitle, - LinkReferenceDefinition, - FootnoteDefinition, - FootnoteLabel, - FootnoteReference, - FootnoteReferenceLabel, - - // ── HTML ─────────────────────────────────────────────────────────── - HtmlBlock, - HtmlInline, - HtmlOpenTag, - HtmlCloseTag, - HtmlComment, - HtmlCdata, - HtmlProcessingInstruction, - HtmlDeclaration, - - // ── Inline emphasis ──────────────────────────────────────────────── - Emphasis, - Strong, - Strikethrough, - - // ── Front matter ─────────────────────────────────────────────────── - MinusMetadata, - PlusMetadata, - - // ── Breaks & tokens ──────────────────────────────────────────────── - Newline, - ThematicBreak, - /// A word-shaped token classified by shape (see [`Self::WordToken`] etc.). - WordToken, - NumericToken, - PathLikeToken, - IdentifierLikeToken, - /// Sentence-terminating punctuation (`.`/`?`/`!`/`。`/`…`). - Terminator, - /// Clause-separating punctuation (`,`/`;`/`:`). - Separator, - /// Bracketing punctuation. - Bracket, - /// Operator-like punctuation. - OperatorLike, -} - -impl NodeKind { - /// The heading level (1..=6) when this kind is a [`NodeKind::Heading`]. - pub(crate) fn heading_level(self) -> Option { - match self { - NodeKind::Heading { level, .. } => Some(level), - _ => None, - } - } - - /// Whether this kind is a heading (of any level or style). - pub(crate) fn is_heading(self) -> bool { - matches!(self, NodeKind::Heading { .. }) - } - - /// Whether this kind is a list item (task or plain). - pub(crate) fn is_list_item(self) -> bool { - matches!(self, NodeKind::ListItem { .. }) - } -} - -/// Converts a `pulldown-cmark` [`HeadingLevel`] to a 1..=6 level. -pub(crate) fn level_number(level: HeadingLevel) -> u8 { - match level { - HeadingLevel::H1 => 1, - HeadingLevel::H2 => 2, - HeadingLevel::H3 => 3, - HeadingLevel::H4 => 4, - HeadingLevel::H5 => 5, - HeadingLevel::H6 => 6, - } -} diff --git a/crates/mehen-markdown/src/lib.rs b/crates/mehen-markdown/src/lib.rs deleted file mode 100644 index b9fe6b20..00000000 --- a/crates/mehen-markdown/src/lib.rs +++ /dev/null @@ -1,432 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-markdown` — Markdown documentation metrics analyzer. -//! -//! Per the rewrite plan §4.7 / §6.6 / §8.1, the pre-1.0 -//! `src/markdown/**` analyzer was physically moved here intact. The -//! high-level entry point [`analyze_markdown`] retains its original -//! signature so existing fixtures and snapshot tests pass without -//! modification. -//! -//! Markdown parsing is centered on pulldown-cmark events. Metric passes that -//! need document semantics consume `document`; passes that need nested byte -//! spans use the compact structural tree fed by the same event stream. -//! -//! Embedded-code analysis is supplied by `mehen-engine` through -//! [`set_embedded_dispatch`], keeping this crate focused on Markdown -//! metrics instead of depending on each source-language analyzer crate. - -#![allow(clippy::upper_case_acronyms)] - -mod analyzer; -mod artifact_debt; -mod code_burden; -pub mod diagrams; -mod dmi; -mod document; -mod ecu; -mod embedded_code; -mod evidence; -mod filler; -mod good_scaffold; -mod grounding; -mod halstead; -mod kind; -mod links; -mod loc; -mod math_burden; -mod mathops; -mod mcc; -mod mrpc; -mod nearby; -pub mod prose; -mod rci; -mod section_balance; -mod sections; -mod source_text; -mod syntax_tree; -mod tables; -mod tree_helpers; -pub mod types; -mod visuals; -mod words; - -pub use analyzer::analyze_markdown; -use analyzer::analyze_markdown_with_evidence; -pub use embedded_code::{EmbeddedFenceMetrics, FenceLanguage, set_embedded_dispatch}; - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, ContributionCollector, Language, LanguageAnalysis, - LanguageAnalyzer, MetricKey, MetricSet, MetricSpace, SourceFile, SourceSpan, SpaceId, - SpaceKind, byte_offset_clamped, -}; - -use crate::types::{LinkClass, MarkdownMetrics}; - -/// Pulldown-cmark-backed Markdown analyzer for the engine registry. -/// -/// The rich metric pipeline runs through [`analyze_markdown`] and -/// produces [`types::MarkdownMetrics`] (a Markdown-specific report -/// shape). This `LanguageAnalyzer::analyze` implementation drives that -/// same pipeline and translates the headline numbers (LOC family, -/// size, complexity, Halstead, links, visuals, tables, maintainability, -/// grounding, AI-era risk, review criticality) into the shared -/// `MetricSet` flat-key shape so `mehen metrics README.md` returns -/// real values instead of an empty space. -pub struct MarkdownAnalyzer; - -impl MarkdownAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for MarkdownAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for MarkdownAnalyzer { - fn language(&self) -> Language { - Language::Markdown - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::PulldownCmark - } - - fn analyze( - &self, - source: &SourceFile, - config: &AnalysisConfig, - ) -> mehen_core::Result { - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: source.line_index.line_count(), - }; - let mut evidence = ContributionCollector::new(config.emit_contributions); - let metrics = - analyze_markdown_with_evidence(&source.text, source.path.as_std_path(), &mut evidence); - record_broken_link_evidence(&metrics, source, &mut evidence); - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, span); - publish_markdown_metrics(&metrics, &mut root.metrics); - Ok(LanguageAnalysis { - language: Language::Markdown, - backend: AnalysisBackend::PulldownCmark, - diagnostics: Vec::new(), - root, - contributions: evidence.finish(), - }) - } -} - -/// Record one contribution per broken link (plan §5.4 / research §39.4): -/// each `LinkRecord` whose resolution failed adds +1 toward the published -/// `markdown.links.broken` count, spanning the link's source line. The -/// aggregate in `links.rs` counts exactly the `resolved == Some(false)` -/// records, so the evidence amounts sum to the metric by construction. -fn record_broken_link_evidence( - metrics: &MarkdownMetrics, - source: &SourceFile, - evidence: &mut ContributionCollector, -) { - if !evidence.is_enabled() { - return; - } - let total_len = byte_offset_clamped(source.text.len()); - for record in &metrics.link_records { - if !matches!(record.resolved, Some(false)) { - continue; - } - let line = u32::try_from(record.line).unwrap_or(u32::MAX); - let (start_byte, end_byte) = source - .line_index - .line_byte_range(line, total_len) - .unwrap_or((0, 0)); - let span = SourceSpan { - start_byte, - end_byte, - start_line: line, - end_line: line, - }; - evidence.record( - "markdown.links.broken", - span, - 1.0, - format!("markdown.broken_link.{}", link_class_label(record.class)), - ); - } -} - -/// The snake_case label a [`LinkClass`] serializes as — reused for -/// broken-link evidence reason codes. -fn link_class_label(class: LinkClass) -> &'static str { - match class { - LinkClass::Internal => "internal", - LinkClass::Relative => "relative", - LinkClass::AbsoluteSameRepo => "absolute_same_repo", - LinkClass::External => "external", - LinkClass::ExternalVendor => "external_vendor", - LinkClass::Scholarly => "scholarly", - LinkClass::IssuePr => "issue_pr", - LinkClass::Footnote => "footnote", - LinkClass::UnresolvedReferenceUse => "unresolved_reference_use", - LinkClass::ReferenceDefinition => "reference_definition", - } -} - -/// Publish the headline `MarkdownMetrics` numbers into the shared -/// `MetricSet` flat-key shape that the `mehen metrics --format json` -/// envelope serializes. Keys mirror the §23 export schema documented -/// in `docs/metrics/markdown/overview.mdx` so the registry-driven -/// path returns the same numeric values that `analyze_markdown` does. -/// -/// The full `MarkdownMetrics` record (sections, link records, prose -/// detail, etc.) is intentionally not flattened — those live in the -/// Markdown-specific report shape that the diff renderer in -/// `mehen-report::github_markdown_docs` consumes directly. Flat-key -/// publishing covers the scalar headline values consumed by the CLI's -/// JSON output and any threshold/selector lookup. -fn publish_markdown_metrics(m: &MarkdownMetrics, target: &mut MetricSet) { - // LOC family (§5). - target.insert(MetricKey::new("markdown.loc.dloc"), m.loc.dloc); - target.insert(MetricKey::new("markdown.loc.ploc"), m.loc.ploc); - target.insert(MetricKey::new("markdown.loc.cloc"), m.loc.cloc); - target.insert(MetricKey::new("markdown.loc.tloc"), m.loc.tloc); - target.insert(MetricKey::new("markdown.loc.mloc"), m.loc.mloc); - target.insert(MetricKey::new("markdown.loc.bloc"), m.loc.bloc); - target.insert(MetricKey::new("markdown.loc.aloc"), m.loc.aloc); - - // LOC ratios (§5.1). - target.insert( - MetricKey::new("markdown.loc_ratios.artifact_line_ratio"), - m.loc_ratios.artifact_line_ratio, - ); - target.insert( - MetricKey::new("markdown.loc_ratios.code_line_ratio"), - m.loc_ratios.code_line_ratio, - ); - target.insert( - MetricKey::new("markdown.loc_ratios.table_line_ratio"), - m.loc_ratios.table_line_ratio, - ); - target.insert( - MetricKey::new("markdown.loc_ratios.math_line_ratio"), - m.loc_ratios.math_line_ratio, - ); - target.insert( - MetricKey::new("markdown.loc_ratios.blank_line_ratio"), - m.loc_ratios.blank_line_ratio, - ); - - // Size (§4 / §6). - target.insert(MetricKey::new("markdown.size.words"), m.size.words); - target.insert( - MetricKey::new("markdown.size.effective_content_units"), - m.size.effective_content_units, - ); - target.insert(MetricKey::new("markdown.size.sections"), m.size.sections); - target.insert(MetricKey::new("markdown.size.headings"), m.size.headings); - - // Complexity (§7 / §8 / §9). - target.insert( - MetricKey::new("markdown.complexity.reading_path_complexity"), - m.complexity.reading_path_complexity, - ); - target.insert( - MetricKey::new("markdown.complexity.reading_path_complexity_raw"), - m.complexity.reading_path_complexity_raw, - ); - target.insert( - MetricKey::new("markdown.complexity.cognitive_complexity"), - m.complexity.cognitive_complexity, - ); - - // Halstead under complexity (§9). - let h = &m.complexity.halstead; - target.insert( - MetricKey::new("markdown.halstead.operators_distinct"), - h.operators_distinct, - ); - target.insert( - MetricKey::new("markdown.halstead.operators_total"), - h.operators_total, - ); - target.insert( - MetricKey::new("markdown.halstead.operands_distinct"), - h.operands_distinct, - ); - target.insert( - MetricKey::new("markdown.halstead.operands_total"), - h.operands_total, - ); - target.insert(MetricKey::new("markdown.halstead.vocabulary"), h.vocabulary); - target.insert(MetricKey::new("markdown.halstead.length"), h.length); - target.insert(MetricKey::new("markdown.halstead.volume"), h.volume); - target.insert(MetricKey::new("markdown.halstead.difficulty"), h.difficulty); - target.insert(MetricKey::new("markdown.halstead.effort"), h.effort); - target.insert( - MetricKey::new("markdown.halstead.embedded_volume"), - h.embedded_volume, - ); - target.insert( - MetricKey::new("markdown.halstead.total_volume"), - h.total_volume, - ); - - // Links (§11). - target.insert(MetricKey::new("markdown.links.total"), m.links.total); - target.insert(MetricKey::new("markdown.links.broken"), m.links.broken); - target.insert( - MetricKey::new("markdown.links.link_debt_score"), - m.links.link_debt_score, - ); - target.insert( - MetricKey::new("markdown.links.information_scent_score"), - m.links.information_scent_score, - ); - target.insert( - MetricKey::new("markdown.links.review_burden"), - m.links.review_burden, - ); - - // Visuals (§12). - target.insert(MetricKey::new("markdown.visuals.images"), m.visuals.images); - target.insert( - MetricKey::new("markdown.visuals.diagrams"), - m.visuals.diagrams, - ); - target.insert( - MetricKey::new("markdown.visuals.diagram_parse_error_count"), - m.visuals.diagram_parse_error_count, - ); - target.insert( - MetricKey::new("markdown.visuals.visual_net_effect"), - m.visuals.visual_net_effect, - ); - - // Tables (§13). - target.insert(MetricKey::new("markdown.tables.count"), m.tables.count); - target.insert( - MetricKey::new("markdown.tables.max_cells"), - m.tables.max_cells, - ); - target.insert( - MetricKey::new("markdown.tables.table_burden_score"), - m.tables.table_burden_score, - ); - target.insert( - MetricKey::new("markdown.tables.hard_warnings"), - m.tables.hard_warnings, - ); - - // Maintainability (§10 / §19 / §20 / §21). - target.insert( - MetricKey::new("markdown.maintainability.documentation_maintainability_index"), - m.maintainability.documentation_maintainability_index, - ); - target.insert( - MetricKey::new("markdown.maintainability.section_balance_score"), - m.maintainability.section_balance_score, - ); - target.insert( - MetricKey::new("markdown.maintainability.good_scaffold_score"), - m.maintainability.good_scaffold_score, - ); - target.insert( - MetricKey::new("markdown.maintainability.artifact_debt_score"), - m.maintainability.artifact_debt_score, - ); - - // Grounding (§15 / §16). - target.insert( - MetricKey::new("markdown.grounding.repository_grounding_score"), - m.grounding.repository_grounding_score, - ); - target.insert( - MetricKey::new("markdown.grounding.evidence_coverage_score"), - m.grounding.evidence_coverage_score, - ); - - // AI era (§17) and review (§18). - target.insert( - MetricKey::new("markdown.ai_era.filler_lazy_structure_risk"), - m.ai_era.filler_lazy_structure_risk, - ); - target.insert( - MetricKey::new("markdown.review.review_criticality_index"), - m.review.review_criticality_index, - ); -} - -/// Every metric key the Markdown analyzer can publish, for -/// configuration validation and typo suggestions. -/// -/// Kept honest by `published_key_catalogue_is_in_sync` in the tests -/// below, which analyzes a feature-rich document and asserts every -/// published key validates. -pub const PUBLISHED_METRIC_KEYS: &[&str] = &[ - "markdown.ai_era.filler_lazy_structure_risk", - "markdown.complexity.cognitive_complexity", - "markdown.complexity.reading_path_complexity", - "markdown.complexity.reading_path_complexity_raw", - "markdown.grounding.evidence_coverage_score", - "markdown.grounding.repository_grounding_score", - "markdown.halstead.difficulty", - "markdown.halstead.effort", - "markdown.halstead.embedded_volume", - "markdown.halstead.length", - "markdown.halstead.operands_distinct", - "markdown.halstead.operands_total", - "markdown.halstead.operators_distinct", - "markdown.halstead.operators_total", - "markdown.halstead.total_volume", - "markdown.halstead.vocabulary", - "markdown.halstead.volume", - "markdown.links.broken", - "markdown.links.information_scent_score", - "markdown.links.link_debt_score", - "markdown.links.review_burden", - "markdown.links.total", - "markdown.loc.aloc", - "markdown.loc.bloc", - "markdown.loc.cloc", - "markdown.loc.dloc", - "markdown.loc.mloc", - "markdown.loc.ploc", - "markdown.loc.tloc", - "markdown.loc_ratios.artifact_line_ratio", - "markdown.loc_ratios.blank_line_ratio", - "markdown.loc_ratios.code_line_ratio", - "markdown.loc_ratios.math_line_ratio", - "markdown.loc_ratios.table_line_ratio", - "markdown.maintainability.artifact_debt_score", - "markdown.maintainability.documentation_maintainability_index", - "markdown.maintainability.good_scaffold_score", - "markdown.maintainability.section_balance_score", - "markdown.review.review_criticality_index", - "markdown.size.effective_content_units", - "markdown.size.headings", - "markdown.size.sections", - "markdown.size.words", - "markdown.tables.count", - "markdown.tables.hard_warnings", - "markdown.tables.max_cells", - "markdown.tables.table_burden_score", - "markdown.visuals.diagram_parse_error_count", - "markdown.visuals.diagrams", - "markdown.visuals.images", - "markdown.visuals.visual_net_effect", -]; - -/// Whether the Markdown analyzer can publish `name` onto a -/// `MetricSpace`. Used by `mehen.toml` threshold validation so a typo -/// like `markdown.links.borken` is rejected at load time instead of -/// becoming a gate that can never fire. -pub fn is_published_metric_key(name: &str) -> bool { - PUBLISHED_METRIC_KEYS.contains(&name) -} diff --git a/crates/mehen-markdown/src/links.rs b/crates/mehen-markdown/src/links.rs deleted file mode 100644 index 9079a479..00000000 --- a/crates/mehen-markdown/src/links.rs +++ /dev/null @@ -1,791 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Link classification, debt, and scent metrics per §11. -//! -//! This module classifies pulldown-cmark document facts for every link, -//! image, autolink, footnote reference, and link reference definition. It -//! computes the aggregate scores in §11.2-§11.4. Internal anchors are resolved -//! against a GFM-style heading slug table, and relative paths are resolved -//! against the filesystem (scanning relative to the directory of the source -//! file). -//! External URLs are never checked on the network by default — they are -//! tagged `unchecked` (`resolved = None`) and a future `--link-check` flag -//! will wire up active probing. - -use std::collections::HashSet; -use std::path::{Path, PathBuf}; - -use crate::document::{LinkUse, LinkUseKind, MarkdownDocument, normalize_reference_label}; -use crate::mathops::{clamp01, sat}; -use crate::types::{LinkClass, LinkRecord, Links, Section}; - -/// Entry point. Classifies every link/image/autolink/footnote fact, resolves -/// anchors + relative paths, and returns a deterministic record vector plus -/// the aggregate Links struct. -pub(crate) fn analyze_links( - document: &MarkdownDocument, - file_path: &Path, - sections: &[Section], - same_repo_prefixes: &[String], -) -> (Vec, Links) { - let anchors = collect_anchor_slugs(document); - let footnote_labels = collect_footnote_labels(document); - let base_dir = file_path - .parent() - .map(Path::to_path_buf) - .unwrap_or_else(|| PathBuf::from(".")); - - let mut records: Vec = Vec::new(); - let definitions = document.reference_definition_labels(); - - for definition in &document.reference_definitions { - records.push(LinkRecord { - line: definition.line, - class: LinkClass::ReferenceDefinition, - destination: definition.destination.clone(), - text: definition.label.clone(), - is_image: false, - is_bare_url: false, - resolved: None, - }); - } - - for link in &document.links { - if let Some(record) = classify_link_or_image(link) { - records.push(record); - } - } - - for footnote in &document.footnote_references { - records.push(LinkRecord { - line: footnote.line, - class: LinkClass::Footnote, - destination: footnote.label.clone(), - text: format!("[^{}]", footnote.label), - is_image: false, - is_bare_url: false, - resolved: None, - }); - } - - // Resolve internal anchors + relative paths + reference shortcuts. - for r in records.iter_mut() { - match r.class { - LinkClass::Internal => { - let slug = slugify_fragment(&r.destination); - r.resolved = Some(anchors.contains(&slug)); - } - LinkClass::Relative => { - if r.destination.trim().is_empty() { - r.resolved = Some(false); - } else { - let (path_part, fragment) = split_fragment(&r.destination); - let file_ok = resolve_relative(&base_dir, path_part); - let fragment_ok = fragment_ok_same_file(fragment, &anchors, path_part); - r.resolved = Some(file_ok && fragment_ok); - } - } - LinkClass::AbsoluteSameRepo - | LinkClass::External - | LinkClass::ExternalVendor - | LinkClass::Scholarly - | LinkClass::IssuePr => { - r.resolved = None; - } - LinkClass::Footnote => { - r.resolved = Some(footnote_labels.contains(&r.destination)); - } - LinkClass::UnresolvedReferenceUse => { - let resolved = - definitions.contains_key(normalize_reference_label(&r.text).as_str()); - r.resolved = Some(resolved); - } - LinkClass::ReferenceDefinition => { - r.resolved = None; - } - } - - // Promote plain `External` URLs that point back at the same repo. - if matches!(r.class, LinkClass::External) - && !same_repo_prefixes.is_empty() - && same_repo_prefixes - .iter() - .any(|p| r.destination.starts_with(p.as_str())) - { - r.class = LinkClass::AbsoluteSameRepo; - } - } - - // Determinism: sort by line, then destination, then class. - records.sort_by(|a, b| { - a.line - .cmp(&b.line) - .then(a.destination.cmp(&b.destination)) - .then((a.class as u8).cmp(&(b.class as u8))) - }); - - let aggregate = aggregate_links(&records, sections); - (records, aggregate) -} - -fn classify_link_or_image(link: &LinkUse) -> Option { - let (class, destination, text) = - if link.kind.is_reference_style() && link.destination.is_empty() { - let reference = link - .reference_label - .as_deref() - .filter(|label| !label.is_empty()) - .unwrap_or_else(|| link.text.trim()); - ( - LinkClass::UnresolvedReferenceUse, - String::new(), - reference.to_string(), - ) - } else { - let destination = link.destination.clone(); - let class = match link.kind { - LinkUseKind::Email => LinkClass::External, - _ => classify_destination(&destination), - }; - (class, destination, link.text.clone()) - }; - - if destination.is_empty() && text.is_empty() { - return None; - } - - let is_bare_url = matches!(link.kind, LinkUseKind::Autolink | LinkUseKind::Email) - || (!text.is_empty() && text.trim() == destination.trim() && looks_like_url(&destination)); - - Some(LinkRecord { - line: link.line, - class, - destination, - text, - is_image: link.is_image, - is_bare_url, - resolved: None, - }) -} - -fn classify_destination(dest: &str) -> LinkClass { - let trimmed = dest.trim(); - if trimmed.is_empty() { - return LinkClass::Relative; - } - if trimmed.starts_with('#') { - return LinkClass::Internal; - } - if looks_like_absolute_url(trimmed) { - if is_scholarly(trimmed) { - return LinkClass::Scholarly; - } - if is_issue_pr(trimmed) { - return LinkClass::IssuePr; - } - if is_external_vendor(trimmed) { - return LinkClass::ExternalVendor; - } - return LinkClass::External; - } - LinkClass::Relative -} - -fn looks_like_absolute_url(s: &str) -> bool { - if s.starts_with("http://") - || s.starts_with("https://") - || s.starts_with("ftp://") - || s.starts_with("ftps://") - || s.starts_with("file://") - || s.starts_with("data:") - || s.starts_with("mailto:") - || s.starts_with("tel:") - { - return true; - } - if let Some((scheme, rest)) = s.split_once("://") - && rest.starts_with(|c: char| !c.is_whitespace()) - && scheme - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '+') - { - return true; - } - false -} - -fn looks_like_url(s: &str) -> bool { - looks_like_absolute_url(s) || s.starts_with("www.") -} - -fn is_scholarly(s: &str) -> bool { - let host = host_of(s).unwrap_or(""); - matches!( - host, - "doi.org" - | "dx.doi.org" - | "arxiv.org" - | "www.arxiv.org" - | "datatracker.ietf.org" - | "rfc-editor.org" - | "www.rfc-editor.org" - | "tools.ietf.org" - | "www.w3.org" - | "w3.org" - | "pubmed.ncbi.nlm.nih.gov" - | "www.ncbi.nlm.nih.gov" - | "ncbi.nlm.nih.gov" - ) -} - -fn is_issue_pr(s: &str) -> bool { - let host = host_of(s).unwrap_or(""); - let after_host = after_host(s).unwrap_or(""); - match host { - "github.com" | "www.github.com" | "gitlab.com" | "www.gitlab.com" => { - let segs: Vec<&str> = after_host.split('/').filter(|s| !s.is_empty()).collect(); - if segs.len() >= 4 { - let kind = segs[2]; - let id = segs[3]; - let is_int = id.chars().all(|c| c.is_ascii_digit()) && !id.is_empty(); - let kind_ok = matches!(kind, "issues" | "pull" | "pulls" | "merge_requests"); - return is_int && kind_ok; - } - false - } - _ => { - s.contains("/browse/") - || (host.contains("atlassian.net") && s.contains("/browse/")) - || (host == "linear.app" && s.contains("/issue/")) - } - } -} - -fn is_external_vendor(s: &str) -> bool { - let host = host_of(s).unwrap_or(""); - matches!( - host, - "docs.aws.amazon.com" - | "aws.amazon.com" - | "developer.mozilla.org" - | "doc.rust-lang.org" - | "docs.rs" - | "crates.io" - | "rust-lang.org" - | "www.rust-lang.org" - | "learn.microsoft.com" - | "docs.microsoft.com" - | "kubernetes.io" - | "docs.python.org" - | "nodejs.org" - | "reactjs.org" - | "react.dev" - | "developer.apple.com" - | "developer.android.com" - | "cloud.google.com" - | "cloud.ibm.com" - | "azure.microsoft.com" - | "spec.commonmark.org" - | "github.github.com" - | "docs.github.com" - | "docs.gitlab.com" - ) -} - -fn host_of(s: &str) -> Option<&str> { - let after_scheme = s.split_once("://").map(|(_, rest)| rest)?; - let end = after_scheme - .find(['/', '?', '#']) - .unwrap_or(after_scheme.len()); - Some(&after_scheme[..end]) -} - -fn after_host(s: &str) -> Option<&str> { - let after_scheme = s.split_once("://").map(|(_, rest)| rest)?; - let host_end = after_scheme - .find(['/', '?', '#']) - .unwrap_or(after_scheme.len()); - Some(&after_scheme[host_end..]) -} - -fn split_fragment(s: &str) -> (&str, &str) { - match s.find('#') { - Some(i) => (&s[..i], &s[i + 1..]), - None => (s, ""), - } -} - -fn fragment_ok_same_file(fragment: &str, anchors: &HashSet, path_part: &str) -> bool { - if fragment.is_empty() { - return true; - } - if path_part.is_empty() { - return anchors.contains(&slugify(fragment)); - } - // Cross-file fragment: we don't currently re-parse the target, so we - // optimistically accept once the file itself resolves. Marking it as - // true here avoids a false positive in the broken-link count. - true -} - -fn resolve_relative(base_dir: &Path, rel: &str) -> bool { - if rel.is_empty() { - return true; - } - // Strip a single leading `/` so absolute-style relatives resolve from - // the Markdown file's directory. Do NOT strip leading `.` — `./foo.md` - // and `../bar.md` are valid relative paths that Path::join handles - // natively. Previously trimming `.` turned them into `/foo.md` and - // reported valid sibling/parent links as broken (Codex P1). - let rel = rel.strip_prefix('/').unwrap_or(rel); - let candidate = base_dir.join(rel); - candidate.exists() -} - -/// GFM-style slug used by GitHub's Markdown renderer. The algorithm is: -/// -/// 1. Lowercase (for ASCII). -/// 2. Strip punctuation except `-`, `_`, and alphanumerics. -/// 3. Replace whitespace runs with a single `-`. -fn slugify(text: &str) -> String { - let mut out = String::with_capacity(text.len()); - let mut prev_dash = false; - for ch in text.chars() { - let lower = ch.to_ascii_lowercase(); - if lower.is_alphanumeric() || lower == '_' { - out.push(lower); - prev_dash = false; - } else if lower.is_whitespace() || lower == '-' { - if !prev_dash && !out.is_empty() { - out.push('-'); - prev_dash = true; - } - } else { - continue; - } - } - while out.ends_with('-') { - out.pop(); - } - out -} - -fn slugify_fragment(s: &str) -> String { - slugify(s.trim_start_matches('#')) -} - -/// Compute GitHub-style anchor slugs from pulldown heading text. -fn collect_anchor_slugs(document: &MarkdownDocument) -> HashSet { - let mut out: HashSet = HashSet::new(); - for heading in &document.headings { - // GitHub-style de-duplication: the first heading with a given slug - // keeps the bare slug; subsequent headings get `-1`, `-2`, etc. - // appended. Anchor links like `#intro-1` in a doc with two - // `## Intro` headings should resolve to the second one. - let base = slugify(&heading.text); - if out.insert(base.clone()) { - // first occurrence - } else { - for n in 1.. { - let candidate = format!("{base}-{n}"); - if out.insert(candidate) { - break; - } - } - } - } - out -} - -fn collect_footnote_labels(document: &MarkdownDocument) -> HashSet { - document - .footnote_definitions - .iter() - .map(|definition| definition.label.clone()) - .collect() -} - -fn aggregate_links(records: &[LinkRecord], sections: &[Section]) -> Links { - let mut links = Links::default(); - - for r in records { - match r.class { - LinkClass::Internal => links.internal += 1, - LinkClass::Relative => links.relative += 1, - LinkClass::External => links.external += 1, - LinkClass::ExternalVendor => { - links.external += 1; - links.external_vendor += 1; - } - LinkClass::Scholarly => { - links.external += 1; - links.scholarly += 1; - } - LinkClass::IssuePr => { - links.external += 1; - links.issue_pr += 1; - } - LinkClass::AbsoluteSameRepo => { - links.absolute_same_repo += 1; - } - LinkClass::Footnote => links.footnote += 1, - LinkClass::UnresolvedReferenceUse => { - links.relative += 1; - } - LinkClass::ReferenceDefinition => { - // Reference definitions are anchors for the reference-style - // `[abc]` links, not outbound links of their own. They are - // tracked via `records` for shortcut resolution but not in - // the `total`/`broken` aggregates. - continue; - } - } - links.total += 1; - if r.is_image { - links.image += 1; - } - if r.is_bare_url { - links.bare_url += 1; - } - if matches!(r.resolved, Some(false)) { - links.broken += 1; - } - } - - let total = links.total.max(1) as f64; - let total_internal = links.internal.max(1) as f64; - let l_broken = links.broken as f64; - let l_ext = links.external as f64; - - let broken_rate = l_broken / total; - let bare_rate = links.bare_url as f64 / total; - let external_rate = l_ext / total; - - let missing_internal_anchors = records - .iter() - .filter(|r| r.class == LinkClass::Internal && matches!(r.resolved, Some(false))) - .count() as f64; - let anchor_miss_rate = missing_internal_anchors / total_internal; - - let words = sections.iter().map(|s| s.word_count).sum::().max(1) as f64; - let link_density_per_100w = links.total as f64 / (words / 100.0).max(1.0); - - links.link_debt_score = clamp01( - 0.45 * sat(broken_rate, 0.00, 0.10) - + 0.20 * sat(anchor_miss_rate, 0.00, 0.10) - + 0.15 * sat(bare_rate, 0.05, 0.30) - + 0.10 * sat(external_rate, 0.60, 0.90) - + 0.10 * sat(link_density_per_100w, 6.0, 14.0), - ); - - let descriptive_rate = if links.total == 0 { - 0.0 - } else { - records - .iter() - .filter(|r| { - !matches!( - r.class, - LinkClass::ReferenceDefinition | LinkClass::UnresolvedReferenceUse - ) && is_descriptive_text(&r.text) - }) - .count() as f64 - / links.total as f64 - }; - let resolved_relative_rate = if links.relative == 0 { - 0.0 - } else { - records - .iter() - .filter(|r| r.class == LinkClass::Relative && matches!(r.resolved, Some(true))) - .count() as f64 - / links.relative as f64 - }; - let anchor_success_rate = if links.internal == 0 { - 0.0 - } else { - records - .iter() - .filter(|r| r.class == LinkClass::Internal && matches!(r.resolved, Some(true))) - .count() as f64 - / links.internal as f64 - }; - let reference_section_present = if has_reference_section(sections) { - 1.0 - } else { - 0.0 - }; - links.information_scent_score = clamp01( - 0.30 * descriptive_rate - + 0.30 * resolved_relative_rate - + 0.20 * anchor_success_rate - + 0.20 * reference_section_present, - ); - - links.review_burden = 0.3 * links.internal as f64 - + 0.8 * links.relative as f64 - + 1.0 * l_ext - + 2.5 * l_broken - + 0.5 * links.footnote as f64; - - links -} - -fn is_descriptive_text(text: &str) -> bool { - let t = text.trim().to_lowercase(); - if t.is_empty() { - return false; - } - if looks_like_url(&t) { - return false; - } - !matches!( - t.as_str(), - "here" | "link" | "click here" | "this" | "read more" | "more" | ">" | "..." | "…" - ) -} - -fn has_reference_section(sections: &[Section]) -> bool { - sections.iter().any(|s| { - s.heading_text - .as_deref() - .map(|t| { - let l = t.trim().to_lowercase(); - l == "references" - || l == "bibliography" - || l == "works cited" - || l == "further reading" - || l == "see also" - }) - .unwrap_or(false) - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn slugify_applies_gfm_rules() { - assert_eq!(slugify("Hello World"), "hello-world"); - assert_eq!(slugify("Section 1!"), "section-1"); - assert_eq!(slugify(" Leading & Trailing "), "leading-trailing"); - assert_eq!(slugify("snake_case"), "snake_case"); - assert_eq!(slugify("Dash-Case"), "dash-case"); - } - - #[test] - fn classify_detects_external() { - assert_eq!( - classify_destination("https://example.com"), - LinkClass::External - ); - assert_eq!(classify_destination("#top"), LinkClass::Internal); - assert_eq!(classify_destination("docs/api.md"), LinkClass::Relative); - assert_eq!( - classify_destination("https://doi.org/10.1/abc"), - LinkClass::Scholarly - ); - assert_eq!( - classify_destination("https://github.com/foo/bar/issues/1"), - LinkClass::IssuePr - ); - assert_eq!( - classify_destination("https://docs.aws.amazon.com/lambda/"), - LinkClass::ExternalVendor - ); - } - - #[test] - fn host_and_after_host_split_url() { - assert_eq!(host_of("https://foo.bar/baz?x=1"), Some("foo.bar")); - assert_eq!(after_host("https://foo.bar/baz?x=1"), Some("/baz?x=1")); - } - - #[test] - fn resolve_relative_preserves_dot_prefixed_paths() { - // Codex P1 on PR #84: `./foo.md` and `../bar.md` must resolve - // against `base_dir`, not against the filesystem root. Previously - // `trim_start_matches('.')` turned them into absolute-style paths - // that reported valid sibling/parent links as broken. - let tmp = tempfile::tempdir().expect("tempdir"); - let base_dir = tmp.path(); - let sibling = base_dir.join("foo.md"); - std::fs::write(&sibling, b"# Foo\n").expect("write sibling"); - let parent = base_dir.parent().expect("parent dir exists"); - // `./foo.md` should resolve inside base_dir. - assert!( - resolve_relative(base_dir, "./foo.md"), - "./foo.md must resolve against base_dir" - ); - // `../` with a non-existent target should NOT resolve… - assert!( - !resolve_relative(base_dir, "../definitely-not-a-real-file-xyz.md"), - "missing parent file must report unresolved" - ); - // …but a real parent path does. - if let Some(parent_name) = base_dir.file_name().and_then(|s| s.to_str()) { - // Create a sibling of base_dir so `..//foo.md` exists. - let nested = parent.join(parent_name).join("foo.md"); - assert!(nested.exists()); - assert!(resolve_relative( - base_dir, - &format!("../{}/foo.md", parent_name) - )); - } - } - - #[test] - fn collect_heading_slugs_dedups_with_github_numeric_suffix() { - // Codex P2 on PR #84: GitHub appends `-1`, `-2`, … to duplicate - // heading slugs. Anchor collection must match so `#intro-1` on - // a doc with two `## Intro` headings resolves cleanly. - let src = "## Intro\n\nfirst\n\n## Intro\n\nsecond\n\n## Intro\n\nthird\n"; - let document = crate::document::parse_document(src); - let slugs = collect_anchor_slugs(&document); - assert!(slugs.contains("intro"), "base slug present"); - assert!(slugs.contains("intro-1"), "second occurrence gets -1"); - assert!(slugs.contains("intro-2"), "third occurrence gets -2"); - // `-3` should NOT be generated unless there's a fourth heading. - assert!(!slugs.contains("intro-3")); - } - - #[test] - fn unresolved_reference_link_does_not_resolve_against_itself() { - let src = "See [missing][nope].\n"; - let document = crate::document::parse_document(src); - let (records, _) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - let missing = records - .iter() - .find(|record| record.text == "nope") - .expect("nope reference link record"); - assert_eq!(missing.class, LinkClass::UnresolvedReferenceUse); - assert_eq!(missing.resolved, Some(false)); - } - - #[test] - fn unresolved_reference_image_counts_as_image_and_broken() { - let src = "![alt][missing]\n"; - let document = crate::document::parse_document(src); - let (records, aggregate) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - let image = records - .iter() - .find(|record| record.is_image) - .expect("unresolved reference image record"); - assert_eq!(image.class, LinkClass::UnresolvedReferenceUse); - assert_eq!(image.resolved, Some(false)); - assert_eq!(aggregate.image, 1); - assert_eq!(aggregate.broken, 1); - } - - #[test] - fn empty_inline_link_is_unresolved() { - let src = "See [placeholder]().\n"; - let document = crate::document::parse_document(src); - let (records, aggregate) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - let placeholder = records - .iter() - .find(|record| record.text == "placeholder") - .expect("empty inline link record"); - assert_eq!(placeholder.class, LinkClass::Relative); - assert_eq!(placeholder.resolved, Some(false)); - assert_eq!(aggregate.broken, 1); - } - - #[test] - fn autolinks_are_bare_links() { - let src = "See and .\n"; - let document = crate::document::parse_document(src); - let (records, aggregate) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - assert_eq!(records.len(), 2); - assert!(records.iter().all(|record| record.is_bare_url)); - assert_eq!(aggregate.bare_url, 2); - } - - #[test] - fn duplicate_reference_definitions_are_counted() { - let src = "[dup]: /one\n[dup]: /two\n"; - let document = crate::document::parse_document(src); - let (records, _) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - let destinations = records - .iter() - .filter(|record| record.class == LinkClass::ReferenceDefinition) - .map(|record| record.destination.as_str()) - .collect::>(); - assert_eq!(destinations, vec!["/one", "/two"]); - } - - #[test] - fn escaped_reference_label_resolves() { - let src = "# Target\n\n[foo\\]]: #target\n\nSee [visible][foo\\]].\n"; - let document = crate::document::parse_document(src); - let (records, aggregate) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - let link_use = records - .iter() - .find(|record| record.text == "visible") - .expect("escaped-label reference use"); - assert_eq!(link_use.class, LinkClass::Internal); - assert_eq!(link_use.destination, "#target"); - assert_eq!(link_use.resolved, Some(true)); - assert_eq!(aggregate.broken, 0); - } - - #[test] - fn non_escapable_reference_label_backslash_resolves() { - let src = "# Target\n\n[foo\\q]: #target\n\nSee [visible][foo\\q].\n"; - let document = crate::document::parse_document(src); - let (records, aggregate) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - let link_use = records - .iter() - .find(|record| record.text == "visible") - .expect("non-escapable escaped-label reference use"); - assert_eq!(link_use.class, LinkClass::Internal); - assert_eq!(link_use.destination, "#target"); - assert_eq!(link_use.resolved, Some(true)); - assert_eq!(aggregate.broken, 0); - } - - #[test] - fn malformed_reference_destination_does_not_resolve_reference_use() { - let src = "[id]: /docs(\n\nSee [visible][id].\n"; - let document = crate::document::parse_document(src); - let (records, _) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - assert!( - records - .iter() - .all(|record| record.class != LinkClass::ReferenceDefinition) - ); - let link_use = records - .iter() - .find(|record| record.line == 3 && record.text == "id") - .expect("unresolved reference link use"); - assert_eq!(link_use.class, LinkClass::UnresolvedReferenceUse); - assert_eq!(link_use.resolved, Some(false)); - } - - #[test] - fn full_reference_link_resolves_with_reference_key_not_visible_text() { - let src = "# Target\n\nSee [visible][ref].\n\n[ref]: #target\n"; - let document = crate::document::parse_document(src); - let (records, aggregate) = analyze_links(&document, Path::new("README.md"), &[], &[]); - - let link_use = records - .iter() - .find(|record| record.line == 3) - .expect("reference link use"); - assert_eq!(link_use.class, LinkClass::Internal); - assert_eq!(link_use.destination, "#target"); - assert_eq!(link_use.text, "visible"); - assert_eq!(link_use.resolved, Some(true)); - assert_eq!(aggregate.broken, 0); - } -} diff --git a/crates/mehen-markdown/src/loc.rs b/crates/mehen-markdown/src/loc.rs deleted file mode 100644 index e0993493..00000000 --- a/crates/mehen-markdown/src/loc.rs +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Line classification for the Markdown LOC family (§5). -//! -//! Each physical line of the source is assigned to exactly one class: -//! prose, code, table, math, blank, or "other-artifact" (raw HTML / MDX / -//! directive / front-matter / image-block / footnote / reference definition -//! / thematic break / heading marker outside headings). `ALOC` (§4) is -//! `CLOC + TLOC + MLOC + other_artifact`. Callers read the final counts via -//! [`LineClasses::loc_family`]. - -use crate::kind::NodeKind; -use crate::syntax_tree::Node; -use crate::types::{LocFamily, LocRatios}; - -/// One-of line categories, in precedence order when multiple nodes claim the -/// same physical line. Lower-index variants win ties, because code / math / -/// tables own their lines even when an inline prose span touches them. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(crate) enum LineClass { - /// Covered by a fenced or indented code block (including fence markers). - Code, - /// Covered by a pipe table (header, delimiter, or row). - Table, - /// Covered by a math block (including `$$` delimiters). - Math, - /// Covered by raw HTML / MDX / directive / front-matter / image-block / - /// footnote-definition / link-reference-definition / thematic-break. - OtherArtifact, - /// Covered by paragraph / heading / blockquote / callout / list-item - /// prose. - Prose, - /// Not touched by any classified node: a blank line. - Blank, -} - -/// Per-line classification map. Indexed by zero-based line number. -pub(crate) struct LineClasses { - classes: Vec, -} - -impl LineClasses { - /// Builds the map by walking the AST. `total_lines` must equal the number - /// of physical lines in the source (see [`physical_line_count`]). - pub(crate) fn build(root: &Node<'_>, total_lines: usize) -> Self { - let mut classes = vec![LineClass::Blank; total_lines]; - - // The walk assigns each block-level node's covered line range to the - // tightest category it represents. Later nodes (children inside - // parents) can tighten a parent's "prose" default by overwriting - // with a higher-precedence class. Precedence is enforced via - // [`LineClass::replace_if_stronger`]. - let mut stack = vec![*root]; - while let Some(node) = stack.pop() { - classify_node(&node, &mut classes); - stack.extend(node.children()); - } - - Self { classes } - } - - /// Aggregates the classification map into the §5 LOC family. - pub(crate) fn loc_family(&self) -> LocFamily { - let mut loc = LocFamily { - dloc: self.classes.len() as u64, - ..LocFamily::default() - }; - for class in &self.classes { - match class { - LineClass::Code => loc.cloc += 1, - LineClass::Table => loc.tloc += 1, - LineClass::Math => loc.mloc += 1, - LineClass::OtherArtifact => {} - LineClass::Prose => loc.ploc += 1, - LineClass::Blank => loc.bloc += 1, - } - } - // ALOC is the sum of every artifact bucket (§4 / §5). - let other_artifact = loc - .dloc - .saturating_sub(loc.ploc + loc.cloc + loc.tloc + loc.mloc + loc.bloc); - loc.aloc = loc.cloc + loc.tloc + loc.mloc + other_artifact; - loc - } - - /// Returns the line class for a zero-based line number, if in range. - pub(crate) fn class_at(&self, line: usize) -> Option { - self.classes.get(line).copied() - } -} - -impl LineClass { - /// Returns the stronger of two classes for precedence in line assignment. - /// `Code` > `Table` > `Math` > `OtherArtifact` > `Prose` > `Blank`. - fn rank(self) -> u8 { - match self { - LineClass::Code => 5, - LineClass::Table => 4, - LineClass::Math => 3, - LineClass::OtherArtifact => 2, - LineClass::Prose => 1, - LineClass::Blank => 0, - } - } - - fn replace_if_stronger(current: &mut LineClass, candidate: LineClass) { - if candidate.rank() > current.rank() { - *current = candidate; - } - } -} - -fn classify_node(node: &Node<'_>, classes: &mut [LineClass]) { - let class = match node.kind() { - // Code — both fenced and indented blocks. Fence markers are covered - // because the `fenced_code_block` span includes them. - NodeKind::FencedCodeBlock | NodeKind::IndentedCodeBlock => LineClass::Code, - - // Tables. - NodeKind::PipeTable => LineClass::Table, - - // Math blocks (`$$…$$`). - NodeKind::MathBlock => LineClass::Math, - - // Raw HTML / footnote / link reference / thematic break / front-matter. - NodeKind::HtmlBlock - | NodeKind::FootnoteDefinition - | NodeKind::LinkReferenceDefinition - | NodeKind::ThematicBreak - | NodeKind::MinusMetadata - | NodeKind::PlusMetadata => LineClass::OtherArtifact, - - // Prose-shaped blocks. Children like inline code / math inline do - // not relabel their line — they appear inside a paragraph whose - // line bucket is prose, consistent with §5. List items are prose - // too: tight lists omit paragraph wrappers, so without this the - // list lines would fall through to Blank and inflate BLOC. - NodeKind::Paragraph - | NodeKind::Heading { .. } - | NodeKind::BlockQuote - | NodeKind::Callout - | NodeKind::ListItem { .. } => LineClass::Prose, - - _ => return, - }; - - let start = node.start_row(); - let (end_row, end_col) = node.end_position(); - let mut end = end_row; - // Tree-sitter reports `end_row` as the row of the byte *after* the last - // child. A block-level node that ends exactly at a line break leaves - // that trailing row dangling; skip it so blank lines downstream of the - // block are not miscounted. - if end > start && end_col == 0 { - end -= 1; - } - if classes.is_empty() { - return; - } - for row in start..=end.min(classes.len() - 1) { - LineClass::replace_if_stronger(&mut classes[row], class); - } -} - -/// Returns the number of physical lines in `source`, counting a trailing -/// newline-less line and handling CRLF consistently with parser byte spans. -pub(crate) fn physical_line_count(source: &str) -> usize { - if source.is_empty() { - return 0; - } - let mut count = 1usize; - for byte in source.bytes() { - if byte == b'\n' { - count += 1; - } - } - // A file that ends with `\n` has a trailing empty line we shouldn't - // double-count. - if source.ends_with('\n') { - count -= 1; - } - count -} - -/// Computes §5.1 ratios from a [`LocFamily`]. -pub(crate) fn derive_ratios(loc: &LocFamily) -> LocRatios { - let dloc = loc.dloc.max(1) as f64; - LocRatios { - artifact_line_ratio: loc.aloc as f64 / dloc, - code_line_ratio: loc.cloc as f64 / dloc, - table_line_ratio: loc.tloc as f64 / dloc, - math_line_ratio: loc.mloc as f64 / dloc, - blank_line_ratio: loc.bloc as f64 / dloc, - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn physical_line_count_handles_trailing_newlines() { - assert_eq!(physical_line_count(""), 0); - assert_eq!(physical_line_count("a"), 1); - assert_eq!(physical_line_count("a\n"), 1); - assert_eq!(physical_line_count("a\nb"), 2); - assert_eq!(physical_line_count("a\nb\n"), 2); - assert_eq!(physical_line_count("\n"), 1); - } -} diff --git a/crates/mehen-markdown/src/math_burden.rs b/crates/mehen-markdown/src/math_burden.rs deleted file mode 100644 index 386a743c..00000000 --- a/crates/mehen-markdown/src/math_burden.rs +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Per-block math burden per §14.3. -//! -//! ```text -//! MathBurden(m) = -//! 1.0 -//! + 0.10 * math_tokens -//! + 0.25 * distinct_math_commands -//! + 1.00 * no_nearby_explanation -//! ``` -//! -//! `distinct_math_commands` is the count of distinct `\command` tokens -//! inside the math body — a crude proxy for LaTeX vocabulary but enough -//! for §14.3. `no_nearby_explanation = 1 - has_nearby_prose`. - -use std::collections::BTreeSet; - -use crate::kind::NodeKind; -use crate::nearby::{BlockSpan, has_prose_within}; -use crate::syntax_tree::Node; - -#[derive(Debug, Clone)] -pub(crate) struct MathBlock { - pub(crate) start_line: u64, - pub(crate) end_line: u64, - pub(crate) tokens: u64, - /// Distinct `\command` tokens. Not serialized directly; read by Phase D's - /// grounding / filler metrics that want math vocabulary spread. - #[allow(dead_code)] - pub(crate) distinct_commands: u64, - pub(crate) has_nearby_prose: bool, - pub(crate) burden: f64, -} - -/// Walks the tree and builds per-`math_block` records. Inline math is -/// excluded because §14.3 explicitly scores display math blocks only. -pub(crate) fn analyze_math_blocks( - root: &Node<'_>, - source: &str, - blocks: &[BlockSpan], -) -> Vec { - let mut out: Vec = Vec::new(); - walk(root, source, blocks, &mut out); - out.sort_by_key(|a| a.start_line); - out -} - -fn walk(node: &Node<'_>, source: &str, blocks: &[BlockSpan], out: &mut Vec) { - let kind = node.kind(); - if matches!(kind, NodeKind::MathBlock) { - out.push(build(node, source, blocks)); - return; - } - for child in node.children() { - walk(&child, source, blocks, out); - } -} - -fn build(node: &Node<'_>, source: &str, blocks: &[BlockSpan]) -> MathBlock { - let start_line = (node.start_row() as u64) + 1; - let (end_row, end_col) = node.end_position(); - let mut end = end_row; - if end > node.start_row() && end_col == 0 { - end -= 1; - } - let end_line = (end as u64) + 1; - - let start = node.start_byte(); - let end_b = node.end_byte(); - let body = &source[start..end_b]; - - let tokens = body - .split_whitespace() - .filter(|t| !t.is_empty() && *t != "$$") - .count() as u64; - - let mut commands: BTreeSet = Default::default(); - let bytes = body.as_bytes(); - let mut i = 0; - while i < bytes.len() { - if bytes[i] == b'\\' { - let mut j = i + 1; - while j < bytes.len() && (bytes[j].is_ascii_alphabetic()) { - j += 1; - } - if j > i + 1 { - commands.insert(body[i..j].to_string()); - i = j; - continue; - } - } - i += 1; - } - - let has_nearby_prose = has_prose_within(blocks, start_line, end_line, 2); - let no_nearby_explanation = if has_nearby_prose { 0.0 } else { 1.0 }; - - let burden = - 1.0 + 0.10 * tokens as f64 + 0.25 * commands.len() as f64 + 1.00 * no_nearby_explanation; - - MathBlock { - start_line, - end_line, - tokens, - distinct_commands: commands.len() as u64, - has_nearby_prose, - burden, - } -} diff --git a/crates/mehen-markdown/src/mathops.rs b/crates/mehen-markdown/src/mathops.rs deleted file mode 100644 index e7e0508a..00000000 --- a/crates/mehen-markdown/src/mathops.rs +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Shared §4 helpers used across Phase C modules. -//! -//! `clamp01` and `sat` appear in nearly every formula from §§11–19; rather -//! than duplicate them in every submodule we expose them here. All metric -//! code should prefer these over inline implementations so behavior stays -//! consistent if we ever revisit NaN handling. - -/// `clamp01(x) = min(1, max(0, x))` per §4. -#[inline] -pub(crate) fn clamp01(x: f64) -> f64 { - x.clamp(0.0, 1.0) -} - -/// `sat(x; lo, hi) = clamp01((x - lo) / (hi - lo))` per §4. Degenerate -/// ranges (`hi <= lo`) snap to 1.0 once `x` crosses the threshold. -#[inline] -pub(crate) fn sat(x: f64, lo: f64, hi: f64) -> f64 { - if hi <= lo { - return if x >= hi { 1.0 } else { 0.0 }; - } - clamp01((x - lo) / (hi - lo)) -} - -/// Normalizes `-0.0` to `+0.0` so YAML / JSON emitters never emit the -/// negative-zero variant in snapshots. IEEE 754 allows `-0.0 + 0.0` to -/// collapse to `+0.0`, but we guard explicitly for determinism on every -/// platform. -#[inline] -pub(crate) fn normalize_zero(x: f64) -> f64 { - if x == 0.0 { 0.0 } else { x } -} diff --git a/crates/mehen-markdown/src/mcc.rs b/crates/mehen-markdown/src/mcc.rs deleted file mode 100644 index 20a1fb3c..00000000 --- a/crates/mehen-markdown/src/mcc.rs +++ /dev/null @@ -1,754 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Markdown Cognitive Complexity (MCC) per §8. -//! -//! Walks the AST, accumulates per-element base weights from §8.1, applies the -//! §8.2 nesting multiplier (`1 + 0.18 * nest(n)`), and the §8.3 cluster -//! multiplier computed from a rolling 20-line window of artifact density, -//! then subtracts scaffold credit per §8.4 (capped at `0.25 * MCC_positive`). -//! -//! Phase-B stubs: -//! - Broken internal/relative link (+3.00) → 0.00 until Phase C link -//! validator lands. -//! - External link unchecked (+0.30) → applied (external link always adds a -//! small penalty pending validation). -//! - External link broken (+4.00) → 0.00 until Phase C. -//! - Diagram parse error (+3.00) → 0.00 until Phase C diagram parser lands. - -use crate::document::{MarkdownDocument, is_diagram_language}; -use crate::kind::NodeKind; -use crate::syntax_tree::Node; -use crate::tree_helpers::{ - count_table_cells, find_link_label, has_scheme as is_external, node_line_span, -}; -use mehen_core::{ContributionCollector, SourceSpan}; - -/// The published metric key MCC evidence attaches to. -const MCC_KEY: &str = "markdown.complexity.cognitive_complexity"; - -/// §8 aggregate: positive weight before credit, credit amount used, final -/// MCC. Only `mcc` is exported to the public record; `positive` and -/// `credit_used` stay accessible to in-crate tests so we can assert the -/// intermediate arithmetic. -#[derive(Debug, Default, Clone, Copy)] -pub(crate) struct MccResult { - #[cfg_attr(not(test), allow(dead_code))] - pub(crate) positive: f64, - #[cfg_attr(not(test), allow(dead_code))] - pub(crate) credit_used: f64, - pub(crate) mcc: f64, -} - -/// Public entry point. -/// -/// `evidence` receives one contribution record (plan §5.4) for **every** -/// MCC adjustment: each §8.1 element charge is recorded with the exact -/// weighted amount it added to the positive term, and each §8.4 scaffold -/// credit is recorded as a negative amount scaled by the global -/// `0.25 * positive` cap — so the recorded amounts sum to the published -/// score. Reason codes: `markdown.` for charges (e.g. -/// `markdown.heading_skip`, `markdown.code_fence`) and -/// `markdown.scaffold_credit.` for credits. -pub(crate) fn compute_mcc( - root: &Node<'_>, - document: &MarkdownDocument, - source: &str, - evidence: &mut ContributionCollector, -) -> MccResult { - let mut ctx = Walker::new(source, document, evidence); - // Pass 1: collect artifact lines for the 20-line-window cluster density - // and record each block's sequence index for §8.4 locality lookup. - ctx.scan_blocks(root); - // Pass 2: accumulate weights and queue scaffold-credit candidates. - ctx.walk(root); - - let credit_raw: f64 = ctx.pending_credits.iter().map(|c| c.raw).sum(); - let credit = credit_raw.min(0.25 * ctx.positive); - // Evidence the applied credit per §8.4 candidate. The cap is global, so - // each candidate's share is its raw credit scaled by `credit / - // credit_raw` — negative amounts, keeping Σ(evidence) == mcc. - if credit > 0.0 && ctx.evidence.is_enabled() { - let scale = credit / credit_raw; - for pending in &ctx.pending_credits { - ctx.evidence.record( - MCC_KEY, - pending.span, - -(pending.raw * scale), - format!("markdown.scaffold_credit.{}", pending.kind), - ); - } - } - let mcc = (ctx.positive - credit).max(0.0); - MccResult { - positive: ctx.positive, - credit_used: credit, - mcc, - } -} - -/// A queued §8.4 scaffold-credit candidate. The raw amounts are summed and -/// capped at `0.25 * positive` after the walk; the span + kind let the cap -/// be attributed back to each candidate as negative evidence. -struct PendingCredit { - span: SourceSpan, - kind: &'static str, - raw: f64, -} - -struct Walker<'a, 'doc, 'ev> { - source: &'a str, - document: &'doc MarkdownDocument, - /// Contribution-evidence sink (plan §5.4). `record` is a no-op when - /// collection is disabled. - evidence: &'ev mut ContributionCollector, - positive: f64, - /// Individual scaffold-credit contributions queued during the walk. - /// They are summed and capped at `0.25 * positive` after the walk. - pending_credits: Vec, - last_heading_level: Option, - /// Each physical line has `1` if an artifact block touches it, else `0`. - /// Used for the §8.3 cluster multiplier. - artifact_line: Vec, - /// The ordered list of block-level node starts keyed by `BlockKind`. - /// Used to check "prose / heading within ±2 blocks" for §8.4. - blocks: Vec<(BlockKind, u32)>, - // Nesting depths tracked during recursive walk. - list_depth: u32, - blockquote_depth: u32, - callout_depth: u32, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum BlockKind { - Paragraph, - Code, - Table, - Math, - RawHtml, - Heading, - Other, -} - -impl<'a, 'doc, 'ev> Walker<'a, 'doc, 'ev> { - fn new( - source: &'a str, - document: &'doc MarkdownDocument, - evidence: &'ev mut ContributionCollector, - ) -> Self { - let mut lines = 1usize; - for b in source.bytes() { - if b == b'\n' { - lines += 1; - } - } - if source.ends_with('\n') { - lines = lines.saturating_sub(1); - } - Self { - source, - document, - evidence, - positive: 0.0, - pending_credits: Vec::new(), - last_heading_level: None, - artifact_line: vec![false; lines.max(1)], - blocks: Vec::new(), - list_depth: 0, - blockquote_depth: 0, - callout_depth: 0, - } - } - - /// Span of `node` in byte + 1-based-line coordinates for evidence - /// records. The syntax tree exposes byte offsets and 0-based rows - /// directly, so no `LineIndex` round-trip is needed. - fn node_span(node: &Node<'_>) -> SourceSpan { - let (end_row, end_col) = node.end_position(); - let mut end = end_row; - if end > node.start_row() && end_col == 0 { - end -= 1; - } - SourceSpan { - start_byte: mehen_core::byte_offset_clamped(node.start_byte()), - end_byte: mehen_core::byte_offset_clamped(node.end_byte()), - start_line: node.start_row() as u32 + 1, - end_line: end as u32 + 1, - } - } - - /// Add `amount` to the positive MCC term and record it as evidence. - /// Every §8.1 charge funnels through here so the recorded amounts sum - /// to the positive term by construction. - fn charge(&mut self, node: &Node<'_>, amount: f64, reason: &'static str) { - self.positive += amount; - self.evidence - .record(MCC_KEY, Self::node_span(node), amount, reason); - } - - /// Queue a §8.4 scaffold-credit candidate. Credits are capped and - /// recorded as negative evidence in [`compute_mcc`]. - fn queue_credit(&mut self, node: &Node<'_>, kind: &'static str, raw: f64) { - if raw > 0.0 { - self.pending_credits.push(PendingCredit { - span: Self::node_span(node), - kind, - raw, - }); - } - } - - fn scan_blocks(&mut self, node: &Node<'_>) { - use NodeKind::*; - let kind = node.kind(); - let bk = classify_block(kind); - let is_artifact = matches!( - kind, - FencedCodeBlock | IndentedCodeBlock | PipeTable | MathBlock | HtmlBlock - ); - if is_artifact { - let start = node.start_row(); - let (end_row, end_col) = node.end_position(); - let mut end = end_row; - if end > start && end_col == 0 { - end -= 1; - } - for row in start..=end.min(self.artifact_line.len().saturating_sub(1)) { - self.artifact_line[row] = true; - } - } - if bk != BlockKind::Other { - self.blocks.push((bk, node.start_row() as u32)); - } - for child in node.children() { - self.scan_blocks(&child); - } - } - - fn walk(&mut self, node: &Node<'_>) { - use NodeKind::*; - - let kind = node.kind(); - - // Headings. - if kind.is_heading() { - let level = kind.heading_level().unwrap_or(1); - if let Some(prev) = self.last_heading_level - && level > prev - { - // Deeper level. Penalize a heading skip (>= 2 steps) - // with 1.00; a smooth +1 step earns the normal 0.20. - // The skip reason is plan §5.4's canonical Markdown - // example — a structure defect a reader can point at. - let delta = level.saturating_sub(prev); - if delta == 1 { - let amount = 0.20 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.heading_step"); - } else { - let amount = 1.00 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.heading_skip"); - } - } - // First heading and going-shallower: no penalty. - self.last_heading_level = Some(level); - } - - // Section without subheading + > 800 words — checked only when the - // node is a `Section` container. - if is_section(kind) && section_has_no_sub_heading(node) { - let words = count_section_words(node); - if words > 800 { - let amount = 2.00 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.oversized_flat_section"); - } - } - - // Paragraph > 160 words → 1.25. - if matches!(kind, Paragraph) { - let words = count_word_tokens(node); - if words > 160 { - let amount = 1.25 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.overlong_paragraph"); - } - // Dense link cluster: > 4 inline links in a paragraph → 1.50. - let links = count_inline_links(node); - if links > 4 { - let amount = 1.50 * self.cluster_multiplier(node) * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.dense_link_cluster"); - } - } - - // Lists and list structures. - match kind { - List => { - let amount = 0.40 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.list"); - self.list_depth += 1; - self.recurse(node); - self.list_depth -= 1; - return; - } - ListItem { task: false } => { - // Nested list level: charge 0.50 * depth per §8.1. `depth` - // here is the current list-depth *before* the list-item - // increments it further; using list_depth directly approximates - // "level" since each outer list already incremented the depth. - let amount = 0.50 * self.list_depth.max(1) as f64 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.list_item"); - } - ListItem { task: true } => { - let amount = 0.35 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.task_list_item"); - } - BlockQuote => { - let amount = 0.50 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.blockquote"); - self.blockquote_depth += 1; - self.recurse(node); - self.blockquote_depth -= 1; - return; - } - Callout => { - let amount = 0.75 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.callout"); - self.callout_depth += 1; - self.recurse(node); - self.callout_depth -= 1; - return; - } - _ => {} - } - - // Inline links / images (not the whole paragraph). - if matches!(kind, Link) { - let amount = 0.25 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.link"); - // External link unchecked → +0.30 per §8.1. Phase B applies this - // universally until Phase C differentiates valid / broken. - if let Some(dest) = self - .document - .link_destination_by_span(node.start_byte(), node.end_byte()) - && is_external(dest) - { - let amount = 0.30 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.external_link_unchecked"); - } - // TODO(Phase C): broken internal/relative link → +3.00; - // external broken → +4.00. Left at 0.00 until the link - // validator lands. - } - - // Footnote reference. - if matches!(kind, FootnoteReference) { - let amount = 0.60 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.footnote_reference"); - } - - // Images. - if matches!(kind, Image) { - let amount = 0.50 * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.image"); - // §8.4 credit: image with alt/caption + nearby explanation, - // bounded. We approximate `alt` as the non-empty link-label - // text inside the Image node. - let label = find_link_label(node, self.source).unwrap_or_default(); - let has_label = !label.trim().is_empty(); - if has_label { - let start = node.start_row() as u32; - let local = local_explanation(&self.blocks, start); - // Base credit for image 0.80; bounded = 1 since we have no - // size for the rendered image yet — Phase C can refine. - let credit = 0.80 * (local as f64) * 1.0; - self.queue_credit(node, "image", credit); - } - } - // Code fences. - if matches!(kind, FencedCodeBlock | IndentedCodeBlock) - && let Some(block) = self.document.code_block_by_start_row(node.start_row()) - { - // LOC counts pulldown code text only — fence markers never - // enter the size-based weighting. - let loc = block.content_line_count(); - let is_diagram = block.language.as_deref().is_some_and(is_diagram_language); - if is_diagram { - let amount = 1.50 * self.cluster_multiplier(node) * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.diagram_fence"); - // §8.4 diagram credit: 1.25 * local_explanation * - // has_label * bounded. Phase B doesn't have a caption - // detector yet — use a conservative `has_label = 1` - // (the diagram language tag makes the type clear) and - // local explanation via ±2 blocks. - let start = block.start_line.saturating_sub(1) as u32; - let local = local_explanation(&self.blocks, start); - let credit = 1.25 * (local as f64) * 1.0; - self.queue_credit(node, "diagram", credit); - // TODO(Phase C): diagram parse error → +3.00. Stub. - } else { - let base = if loc <= 12 { - 1.00 - } else { - 1.00 + 0.08 * (loc as f64 - 12.0) - }; - let unlabelled = !block.is_fenced() || block.language.is_none(); - let multipliers = self.cluster_multiplier(node) * self.current_nest_multiplier(); - // The size-based base and the missing-label penalty are - // separate explainable facts — two evidence rows whose - // sum is the §8.1 weight. - self.charge(node, base * multipliers, "markdown.code_fence"); - if unlabelled { - self.charge(node, 1.50 * multipliers, "markdown.unlabelled_code_fence"); - } - // §8.4 scaffold credit for code examples: - // 0.75 * local_explanation * has_label * bounded - // where has_label = language tag present, bounded = 1 if - // loc <= 30 decaying to 0 at loc == 60. - if !unlabelled { - let start = block.start_line.saturating_sub(1) as u32; - let local = local_explanation(&self.blocks, start); - let bounded = bounded_size(loc as f64, 30.0, 60.0); - let credit = 0.75 * (local as f64) * bounded; - self.queue_credit(node, "code_example", credit); - } - } - } - - // Pipe tables. - if matches!(kind, PipeTable) { - let cells = count_table_cells(node); - let weight = if cells <= 60 { - 0.75 - } else { - 0.75 + 0.03 * (cells as f64 - 60.0).powf(0.85) - }; - let amount = weight * self.cluster_multiplier(node) * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.table"); - // §8.4 table credit: 1.00 * local_explanation * has_header * - // bounded. `bounded` fades from 1 at 60 cells to 0 at 150. - let has_header = pipe_table_has_header(node); - if has_header && cells > 0 { - let start = node.start_row() as u32; - let local = local_explanation(&self.blocks, start); - let bounded = bounded_size(cells as f64, 60.0, 150.0); - let credit = 1.00 * (local as f64) * bounded; - self.queue_credit(node, "table", credit); - } - } - - // Math blocks. - if matches!(kind, MathBlock) { - let amount = 1.50 * self.cluster_multiplier(node) * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.math_block"); - // §8.4 math credit: 0.50 * local_explanation * bounded. Use - // line span as the size proxy. - let start = node.start_row() as u32; - let local = local_explanation(&self.blocks, start); - let lines = node_line_span(node) as f64; - let bounded = bounded_size(lines, 6.0, 20.0); - let credit = 0.50 * (local as f64) * bounded; - self.queue_credit(node, "math", credit); - } - - // Raw HTML blocks: 0.30 * lines, cap 8. - if matches!(kind, HtmlBlock) { - let lines = node_line_span(node) as f64; - let weight = (0.30 * lines).min(8.0); - let amount = weight * self.cluster_multiplier(node) * self.current_nest_multiplier(); - self.charge(node, amount, "markdown.raw_html_block"); - } - - self.recurse(node); - } - - fn recurse(&mut self, node: &Node<'_>) { - for child in node.children() { - self.walk(&child); - } - } - - fn current_nest_multiplier(&self) -> f64 { - let nest = self.list_depth + self.blockquote_depth + self.callout_depth; - 1.0 + 0.18 * nest as f64 - } - - fn cluster_multiplier(&self, node: &Node<'_>) -> f64 { - // 20-line window centered on the node's start row. - let start = node.start_row(); - let lo = start.saturating_sub(10); - let hi = (start + 10).min(self.artifact_line.len()); - let window = &self.artifact_line[lo..hi]; - if window.is_empty() { - return 1.0; - } - let hits = window.iter().filter(|b| **b).count() as f64; - let density = hits / window.len() as f64; - 1.0 + saturate(density, 0.15, 0.45) * 0.35 - } -} - -/// `1` if a prose / heading block exists within ±2 blocks of the `start_row`. -/// -/// `blocks` is the document-order block list. We find the nearest block -/// matching `start_row` and peek 2 neighbours to each side. A prose block -/// (Paragraph) or Heading counts as a local explanation. -fn local_explanation(blocks: &[(BlockKind, u32)], start_row: u32) -> u8 { - let idx = match blocks.iter().position(|(_, row)| *row == start_row) { - Some(i) => i, - None => { - // Fall back: closest block by absolute row distance. - let mut best: Option = None; - let mut best_d = u32::MAX; - for (i, (_, r)) in blocks.iter().enumerate() { - let d = r.abs_diff(start_row); - if d < best_d { - best_d = d; - best = Some(i); - } - } - match best { - Some(i) => i, - None => return 0, - } - } - }; - let lo = idx.saturating_sub(2); - let hi = (idx + 3).min(blocks.len()); - for (i, (bk, _)) in blocks[lo..hi].iter().enumerate() { - let abs = lo + i; - if abs == idx { - continue; - } - if matches!(bk, BlockKind::Paragraph | BlockKind::Heading) { - return 1; - } - } - 0 -} - -/// Returns `1 - sat(size; useful_hi, severe_hi)` per §8.4 `bounded(a)`. -fn bounded_size(size: f64, useful_hi: f64, severe_hi: f64) -> f64 { - 1.0 - saturate(size, useful_hi, severe_hi) -} - -fn saturate(x: f64, lo: f64, hi: f64) -> f64 { - if hi <= lo { - return 0.0; - } - ((x - lo) / (hi - lo)).clamp(0.0, 1.0) -} - -fn classify_block(kind: NodeKind) -> BlockKind { - use NodeKind::*; - match kind { - Paragraph => BlockKind::Paragraph, - FencedCodeBlock | IndentedCodeBlock => BlockKind::Code, - PipeTable => BlockKind::Table, - MathBlock => BlockKind::Math, - HtmlBlock => BlockKind::RawHtml, - Heading { .. } => BlockKind::Heading, - _ => BlockKind::Other, - } -} - -fn is_section(kind: NodeKind) -> bool { - matches!(kind, NodeKind::Section { .. }) -} - -fn section_has_no_sub_heading(section: &Node<'_>) -> bool { - !section.children().any(|child| is_section(child.kind())) -} - -fn count_section_words(node: &Node<'_>) -> u64 { - let mut total = 0u64; - walk_words(node, &mut total); - total -} - -fn walk_words(node: &Node<'_>, total: &mut u64) { - use NodeKind::*; - let kind = node.kind(); - // Don't descend into stop-containers — mirrors `words.rs` rules. - match kind { - FencedCodeBlock - | IndentedCodeBlock - | InlineCode - | CodeFenceContent - | InlineCodeContent - | InfoString - | Language - | MathBlock - | MathInline - | MathBlockContent - | MathInlineContent - | HtmlBlock - | HtmlInline - | Autolink - | Uri - | Email - | LinkDestination - | LinkTitle - | MinusMetadata - | PlusMetadata - | PipeTableDelimiterRow => { - return; - } - _ => {} - } - if matches!( - kind, - WordToken | NumericToken | IdentifierLikeToken | PathLikeToken - ) { - *total += 1; - } - for child in node.children() { - walk_words(&child, total); - } -} - -fn count_word_tokens(node: &Node<'_>) -> u64 { - let mut total = 0u64; - walk_words(node, &mut total); - total -} - -fn count_inline_links(node: &Node<'_>) -> u64 { - let mut total = 0u64; - let mut stack = vec![*node]; - while let Some(n) = stack.pop() { - if matches!(n.kind(), NodeKind::Link) { - total += 1; - } - stack.extend(n.children()); - } - total -} - -fn pipe_table_has_header(node: &Node<'_>) -> bool { - node.children() - .any(|child| matches!(child.kind(), NodeKind::PipeTableHeader)) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn compute(src: &str) -> MccResult { - let (tree, document) = crate::syntax_tree::parse_with_document(src); - let mut evidence = ContributionCollector::new(false); - compute_mcc(&tree.root(), &document, src, &mut evidence) - } - - fn compute_with_evidence(src: &str) -> (MccResult, Vec) { - let (tree, document) = crate::syntax_tree::parse_with_document(src); - let mut evidence = ContributionCollector::new(true); - let result = compute_mcc(&tree.root(), &document, src, &mut evidence); - (result, evidence.finish()) - } - - #[test] - fn heading_skip_records_evidence_with_the_applied_weight() { - let src = "# Top\n\n### Skipped\n"; - let (result, contributions) = compute_with_evidence(src); - let skip: Vec<_> = contributions - .iter() - .filter(|c| c.reason.as_str() == "markdown.heading_skip") - .collect(); - assert_eq!(skip.len(), 1); - assert_eq!(skip[0].amount, 1.0); - assert_eq!(skip[0].span.start_line, 3); - assert_eq!( - skip[0].metric.as_str(), - "markdown.complexity.cognitive_complexity" - ); - assert!(result.positive >= skip[0].amount); - } - - #[test] - fn oversized_flat_section_and_overlong_paragraph_record_evidence() { - let filler = "word ".repeat(801); - let src = format!("# Title\n\n{}\n", filler); - let (_, contributions) = compute_with_evidence(&src); - let reasons: Vec<&str> = contributions.iter().map(|c| c.reason.as_str()).collect(); - assert!(reasons.contains(&"markdown.oversized_flat_section")); - assert!(reasons.contains(&"markdown.overlong_paragraph")); - } - - #[test] - fn empty_doc_mcc_zero() { - let r = compute(""); - assert_eq!(r.mcc, 0.0); - assert_eq!(r.positive, 0.0); - } - - #[test] - fn heading_skip_penalizes() { - let src = "# Top\n\n### Skipped\n"; - let r = compute(src); - // Heading skip H1→H3 contributes 1.00 with nest_multiplier=1. - assert!(r.positive >= 1.0, "positive: {}", r.positive); - } - - #[test] - fn section_800_words_charges() { - // Build a section with ≥ 801 words. - let filler = "word ".repeat(801); - let src = format!("# Title\n\n{}\n", filler); - let r = compute(&src); - // §8.1 charges 2.00 per section-without-subheading > 800 words. - assert!(r.positive >= 2.0, "positive: {}", r.positive); - } - - #[test] - fn fences_and_tables_adjust_cluster() { - let src = "# T\n\n```\nfoo\n```\n\n```\nbar\n```\n"; - let r = compute(src); - // Two unlabelled code fences: 1.00 + 1.50 penalty each. They sit in - // an artifact-dense window, so cluster multiplier > 1. - assert!(r.positive > 5.0, "positive: {}", r.positive); - } - - #[test] - fn unlabelled_code_fence_adds_1_5() { - let labelled = "# H\n\nIntro prose.\n\n```rust\nlet x = 1;\n```\n\nExplanation.\n"; - let unlabelled = "# H\n\nIntro prose.\n\n```\nlet x = 1;\n```\n\nExplanation.\n"; - let r1 = compute(labelled); - let r2 = compute(unlabelled); - // The positive difference between unlabelled and labelled should be - // at least 1.50 (after matching cluster multipliers). Allow for tiny - // numeric drift due to cluster windows. - assert!( - r2.positive - r1.positive >= 1.49, - "unlabelled delta: {:.4}", - r2.positive - r1.positive - ); - } - - #[test] - fn reference_style_external_link_matches_inline_mcc() { - let inline = "# H\n\nSee [docs](https://example.com).\n"; - let reference = "# H\n\nSee [docs][api\\]].\n\n[api\\]]: https://example.com\n"; - let a = compute(inline); - let b = compute(reference); - - assert_eq!( - a.positive, b.positive, - "inline vs external reference positive mismatch: {:?} vs {:?}", - a, b - ); - assert_eq!( - a.mcc, b.mcc, - "inline vs external reference mcc mismatch: {:?} vs {:?}", - a, b - ); - } - - #[test] - fn scaffold_credit_subtracts_cap() { - // A code example with language tag + adjacent prose → non-zero - // credit. MCC should be lower than positive. - let src = "# Example\n\nThis shows how to print:\n\n```rust\nfn main() { println!(\"hi\"); }\n```\n\nThat prints `hi`.\n"; - let r = compute(src); - assert!(r.credit_used > 0.0, "credit should apply"); - assert!(r.mcc < r.positive, "{} !< {}", r.mcc, r.positive); - assert!(r.credit_used <= 0.25 * r.positive + 1e-9); - } -} diff --git a/crates/mehen-markdown/src/mod.rs b/crates/mehen-markdown/src/mod.rs deleted file mode 100644 index f2f260af..00000000 --- a/crates/mehen-markdown/src/mod.rs +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Dedicated Markdown document-metrics pipeline. -//! -//! The Markdown analyzer runs outside the generic -//! `spaces::metrics()` source-code pipeline because prose / tables / -//! diagrams / fences do not map onto function spaces. Its inputs are a raw -//! source buffer and path; its output is a serializable -//! [`types::MarkdownMetrics`] record matching §23's exported schema -//! (Phase-A LOC/size + Phase-B complexity / maintainability core + Phase-C -//! links / visuals / tables / artifact debt + Phase-D grounding / evidence -//! / filler / RCI / section balance / good scaffold + Phase-E language-aware -//! prose metrics). -//! -//! The high-level entry point is [`analyzer::analyze_markdown`]. It is -//! invoked from `main.rs` when the detected language is `LANG::Markdown`; -//! when the `markdown` Cargo feature is disabled this entire module -//! disappears and the routing falls through, so `default-features = false` -//! still produces a functional binary. - -pub(crate) mod analyzer; -pub(crate) mod artifact_debt; -pub(crate) mod code_burden; -pub(crate) mod diagrams; -pub(crate) mod dmi; -pub(crate) mod ecu; -pub(crate) mod embedded_code; -pub(crate) mod evidence; -pub(crate) mod filler; -pub(crate) mod good_scaffold; -pub(crate) mod grounding; -pub(crate) mod halstead; -pub(crate) mod links; -pub(crate) mod loc; -pub(crate) mod math_burden; -pub(crate) mod mathops; -pub(crate) mod mcc; -pub(crate) mod mrpc; -pub(crate) mod nearby; -pub(crate) mod prose; -pub(crate) mod rci; -pub(crate) mod section_balance; -pub(crate) mod sections; -pub(crate) mod tables; -pub(crate) mod types; -pub(crate) mod visuals; -pub(crate) mod words; - -pub(crate) use analyzer::analyze_markdown; - -#[cfg(test)] -mod tests; diff --git a/crates/mehen-markdown/src/mrpc.rs b/crates/mehen-markdown/src/mrpc.rs deleted file mode 100644 index 017eba75..00000000 --- a/crates/mehen-markdown/src/mrpc.rs +++ /dev/null @@ -1,968 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Markdown Reading Path Complexity (MRPC) per §7. -//! -//! Builds a navigation graph `G_doc = (N, E)`: -//! -//! - Nodes: sections, large code blocks (≥ 12 LOC), tables with ≥ 12 cells, -//! diagrams, footnotes/reference definitions, linked documents, and -//! external domains (one node per domain). -//! - Edges: sequential section, parent-child heading, internal link (to -//! same-doc anchor or other section), relative repo link, external link, -//! artifact explanation, footnote/reference. -//! -//! §7.2: `mrpc_raw = |E| - |N| + 2P`. -//! §7.3: `mrpc = max(1, sum(edge_weight) - |N| + 2P)`. -//! -//! Phase B treats external links as valid (weight 1.00). Phase C will add the -//! link validator and bump broken links to 1.20. - -use std::collections::BTreeMap; - -use crate::document::{MarkdownDocument, is_diagram_language}; -// `crate::kind::NodeKind` is aliased to `MdKind` to avoid clashing with the -// local graph-node `NodeKind` enum defined below. -use crate::kind::NodeKind as MdKind; -use crate::syntax_tree::Node; -use crate::tree_helpers::{count_table_cells, has_scheme}; - -/// Per-edge weights from §7.3. -mod weights { - pub(super) const HIERARCHY: f64 = 0.15; - pub(super) const SEQUENTIAL: f64 = 0.20; - pub(super) const INTERNAL: f64 = 0.50; - pub(super) const FOOTNOTE: f64 = 0.65; - pub(super) const RELATIVE: f64 = 0.80; - pub(super) const EXTERNAL: f64 = 1.00; - // TODO(Phase C): link validator bumps broken links from EXTERNAL (1.00) / - // INTERNAL (0.50) to BROKEN (1.20). - #[allow(dead_code)] - pub(super) const _BROKEN: f64 = 1.20; - pub(super) const ARTIFACT: f64 = 0.40; -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -enum NodeKind { - Section, - LargeCode, - LargeTable, - Diagram, - Footnote, - LinkedDoc, - ExternalDomain, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -struct GraphNodeId { - kind: NodeKind, - /// Stable deterministic index within its kind (e.g. 0-based section id - /// in document order or alphabetical domain index). - index: u32, -} - -#[derive(Debug, Clone, Copy)] -enum EdgeKind { - Hierarchy, - Sequential, - InternalAnchor, - Footnote, - Relative, - External, - // TODO(Phase D): artifact-explanation edges fire when a section's - // adjacency table shows explanatory prose near an artifact. Held - // here so the edge-weight table stays intact once Phase D adds the - // nearby-prose walker. - #[allow(dead_code)] - Artifact, -} - -impl EdgeKind { - fn weight(self) -> f64 { - match self { - EdgeKind::Hierarchy => weights::HIERARCHY, - EdgeKind::Sequential => weights::SEQUENTIAL, - EdgeKind::InternalAnchor => weights::INTERNAL, - EdgeKind::Footnote => weights::FOOTNOTE, - EdgeKind::Relative => weights::RELATIVE, - EdgeKind::External => weights::EXTERNAL, - EdgeKind::Artifact => weights::ARTIFACT, - } - } -} - -#[derive(Debug)] -struct Edge { - from: GraphNodeId, - to: GraphNodeId, - kind: EdgeKind, -} - -/// Minimum rows/cells/LOC thresholds from §7.1. -const LARGE_CODE_LOC: usize = 12; -const LARGE_TABLE_CELLS: usize = 12; - -/// Classification of a link's destination URL for MRPC edge typing. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum LinkClass { - /// Starts with `#` — same-document anchor. - InternalAnchor, - /// Relative path like `foo.md`, `../src/lib.rs` or `docs/api#auth`. - Relative, - /// Absolute URL with a scheme (http / https / mailto / etc.). - External, -} - -/// MRPC output bundle. -#[derive(Debug, Default, Clone, Copy)] -pub(crate) struct MrpcResult { - pub(crate) weighted: f64, - pub(crate) raw: f64, -} - -/// Public entry point: walks the parsed AST to build `G_doc` and compute -/// both the §7.2 raw form and the §7.3 weighted form. -pub(crate) fn compute_mrpc( - root: &Node<'_>, - document: &MarkdownDocument, - source: &str, -) -> MrpcResult { - let mut graph = GraphBuilder::new(document); - graph.walk(root, source); - graph.emit() -} - -struct GraphBuilder<'doc> { - document: &'doc MarkdownDocument, - sections: Vec, - large_codes: u32, - large_tables: u32, - diagrams: u32, - footnotes: BTreeMap, - linked_docs: BTreeMap, - external_domains: BTreeMap, - /// Sequential order in which block-level nodes occurred within each - /// section — the artifact-explanation edge fires when an artifact - /// (large code / table / diagram) is adjacent to a paragraph. - section_artifacts: Vec>, - edges: Vec, - /// Current section stack by level (index = depth - 1). The top of the - /// stack is the current enclosing section for artifacts and links. - section_stack: Vec, - /// Slug (GFM style) → section id, built as sections are opened so - /// internal anchors can resolve to an existing section node instead - /// of fabricating one per unique anchor (Codex P1 on PR #83). - section_slugs: BTreeMap, -} - -struct SectionInfo { - _id: u32, - parent: Option, -} - -impl<'doc> GraphBuilder<'doc> { - fn new(document: &'doc MarkdownDocument) -> Self { - GraphBuilder { - document, - sections: Vec::new(), - large_codes: 0, - large_tables: 0, - diagrams: 0, - footnotes: BTreeMap::new(), - linked_docs: BTreeMap::new(), - external_domains: BTreeMap::new(), - section_artifacts: Vec::new(), - edges: Vec::new(), - section_stack: Vec::new(), - section_slugs: BTreeMap::new(), - } - } - - fn walk(&mut self, root: &Node<'_>, source: &str) { - self.walk_recurse(root, source); - // Sequential section edges (document order, only within the same - // parent). - self.add_sequential_edges(); - } - - fn walk_recurse(&mut self, node: &Node<'_>, source: &str) { - let kind = node.kind(); - - match kind { - MdKind::Section { .. } => { - // §3.4 defines the derived section tree as "one section per - // heading". Tree-sitter emits headingless wrapper sections - // for pre-heading / blank content — those must not inflate - // the MRPC node set, otherwise a newline-only file reports - // non-zero `reading_path_complexity_raw` while - // `size.sections` correctly reports 0. Only create a - // Section graph node when an actual heading exists - // (Codex P2 on PR #83). - let Some(slug) = extract_heading_slug(node, source) else { - // Headingless wrapper: recurse into children so their - // artifacts/links reach the enclosing section, but do - // not create a graph node. - self.recurse_children(node, source); - return; - }; - let parent = self.section_stack.last().copied(); - let id = self.sections.len() as u32; - self.sections.push(SectionInfo { _id: id, parent }); - self.section_artifacts.push(Vec::new()); - if let Some(p) = parent { - self.edges.push(Edge { - from: GraphNodeId { - kind: NodeKind::Section, - index: p, - }, - to: GraphNodeId { - kind: NodeKind::Section, - index: id, - }, - kind: EdgeKind::Hierarchy, - }); - } - self.section_slugs.entry(slug).or_insert(id); - self.section_stack.push(id); - self.recurse_children(node, source); - self.section_stack.pop(); - return; - } - MdKind::FencedCodeBlock | MdKind::IndentedCodeBlock => { - if let Some(block) = self.document.code_block_by_start_row(node.start_row()) { - let loc = block.content_line_count(); - let is_diagram = block.language.as_deref().is_some_and(is_diagram_language); - if is_diagram { - let id = self.diagrams; - self.diagrams += 1; - self.add_artifact_node(GraphNodeId { - kind: NodeKind::Diagram, - index: id, - }); - } else if loc >= LARGE_CODE_LOC { - let id = self.large_codes; - self.large_codes += 1; - self.add_artifact_node(GraphNodeId { - kind: NodeKind::LargeCode, - index: id, - }); - } - } - return; - } - MdKind::PipeTable => { - let cells = count_table_cells(node); - if cells >= LARGE_TABLE_CELLS { - let id = self.large_tables; - self.large_tables += 1; - self.add_artifact_node(GraphNodeId { - kind: NodeKind::LargeTable, - index: id, - }); - } - return; - } - MdKind::FootnoteDefinition => { - let label = footnote_def_label(node, source).unwrap_or_default(); - let next = self.footnotes.len() as u32; - let id = *self.footnotes.entry(label).or_insert(next); - // Create an artifact-style node for the footnote so it - // contributes to N even without any reference edge. - let gid = GraphNodeId { - kind: NodeKind::Footnote, - index: id, - }; - // Link from the enclosing section (if any) to the footnote — - // definitions are traversed alongside their referencing - // section, so model that as a hierarchy edge so it counts as - // part of N but does not inflate weighted MRPC above the - // footnote reference's own weight. - if let Some(section_id) = self.section_stack.last().copied() { - self.edges.push(Edge { - from: GraphNodeId { - kind: NodeKind::Section, - index: section_id, - }, - to: gid, - kind: EdgeKind::Hierarchy, - }); - } - // Recurse into children so any Link/Image nodes inside the - // footnote body still emit relative/external/internal edges - // — long-form docs often store references inside footnotes - // (Codex P2 on PR #83). - self.recurse_children(node, source); - return; - } - MdKind::LinkReferenceDefinition => { - // Reference definitions never contribute a graph node of - // their own. Reference-style links resolve through - // `MarkdownDocument` facts in the `Link | Image` branch, so - // `[text][id]` + `[id]: ...` carries the same navigation cost - // as the equivalent inline `[text](...)`. - return; - } - MdKind::FootnoteReference => { - // Edge from enclosing section to the footnote node. - let label = footnote_ref_label(node, source).unwrap_or_default(); - let next = self.footnotes.len() as u32; - let id = *self.footnotes.entry(label).or_insert(next); - if let Some(section_id) = self.section_stack.last().copied() { - self.edges.push(Edge { - from: GraphNodeId { - kind: NodeKind::Section, - index: section_id, - }, - to: GraphNodeId { - kind: NodeKind::Footnote, - index: id, - }, - kind: EdgeKind::Footnote, - }); - } - // Fall through in case nested content matters — but a - // footnote reference has no relevant children. - return; - } - MdKind::Link | MdKind::Image => { - // Pulldown resolves inline and reference-style destinations - // before these compact syntax nodes are walked. - if let Some(dest) = self - .document - .link_destination_by_span(node.start_byte(), node.end_byte()) - { - self.handle_link(dest); - } - return; - } - MdKind::Autolink => { - // Autolinks (``) are semantically - // equivalent to inline external links — they should emit - // the same navigation edge (Codex P2 on PR #83). - if let Some(dest) = autolink_destination(node, source) { - self.handle_link(&dest); - } - return; - } - _ => {} - } - - self.recurse_children(node, source); - } - - fn recurse_children(&mut self, node: &Node<'_>, source: &str) { - for child in node.children() { - self.walk_recurse(&child, source); - } - } - - fn add_artifact_node(&mut self, node: GraphNodeId) { - // The artifact-explanation edge fires only when explanatory prose - // lives adjacent to the artifact — §7.1 describes it that way, and - // unconditionally adding the edge for every artifact inflates MRPC - // for artifact-heavy docs and erases the explained/unexplained - // distinction (Codex P2 on PR #83). The adjacency check itself is - // Phase D (via the section-level paragraph walker); until then, - // the artifact node is created (contributing to |N|) without an - // edge. Phase D will insert the edge when the nearby-prose table - // is populated. - if let Some(section_id) = self.section_stack.last().copied() { - let idx = section_id as usize; - if idx < self.section_artifacts.len() { - self.section_artifacts[idx].push(node); - } - } - } - - fn handle_link(&mut self, dest: &str) { - let Some(section_id) = self.section_stack.last().copied() else { - // Pre-heading links: no MRPC section to anchor on, so they do not - // contribute an edge. This matches the research-doc philosophy - // that MRPC measures navigation between sections of a structured - // document. - return; - }; - let from = GraphNodeId { - kind: NodeKind::Section, - index: section_id, - }; - let class = classify_link(dest); - match class { - LinkClass::InternalAnchor => { - // Internal anchors target another section of the *same* - // document. §7.1 nodes already include every section, so - // anchor resolution should land on one of those — not - // fabricate a new node. Phase C will build the authoritative - // heading-slug → section map; until then, match on GFM slug - // built from the source text of each known heading. - // - // If the anchor fails to match any heading, route the edge - // to section 0 (the enclosing document) so it still - // contributes to the edge budget and the graph's connected - // component count stays stable. Fabricating a per-anchor - // `LinkedDoc` node would inflate |N| and depress MRPC on - // TOC-heavy documents (Codex P1). - let target_section = resolve_anchor_to_section(dest, &self.section_slugs) - .or_else(|| (!self.sections.is_empty()).then_some(0usize)); - if let Some(sid) = target_section { - self.edges.push(Edge { - from, - to: GraphNodeId { - kind: NodeKind::Section, - index: sid as u32, - }, - kind: EdgeKind::InternalAnchor, - }); - } - } - LinkClass::Relative => { - let key = normalize_relative_path(dest); - let next = self.linked_docs.len() as u32; - let id = *self.linked_docs.entry(key).or_insert(next); - self.edges.push(Edge { - from, - to: GraphNodeId { - kind: NodeKind::LinkedDoc, - index: id, - }, - kind: EdgeKind::Relative, - }); - } - LinkClass::External => { - let domain = extract_domain(dest).unwrap_or_else(|| "unknown".to_string()); - let next = self.external_domains.len() as u32; - let id = *self.external_domains.entry(domain).or_insert(next); - self.edges.push(Edge { - from, - to: GraphNodeId { - kind: NodeKind::ExternalDomain, - index: id, - }, - // TODO(Phase C): link validator promotes `External` to - // `Broken` (weight 1.20) when the target is unreachable. - kind: EdgeKind::External, - }); - } - } - } - - fn add_sequential_edges(&mut self) { - // Group sections by parent, then connect siblings in document order. - let mut siblings: BTreeMap, Vec> = BTreeMap::new(); - for (i, s) in self.sections.iter().enumerate() { - siblings.entry(s.parent).or_default().push(i as u32); - } - for (_parent, ids) in siblings { - for pair in ids.windows(2) { - self.edges.push(Edge { - from: GraphNodeId { - kind: NodeKind::Section, - index: pair[0], - }, - to: GraphNodeId { - kind: NodeKind::Section, - index: pair[1], - }, - kind: EdgeKind::Sequential, - }); - } - } - } - - fn emit(self) -> MrpcResult { - let n_sections = self.sections.len() as u32; - let n_large_code = self.large_codes; - let n_large_table = self.large_tables; - let n_diagram = self.diagrams; - let n_footnote = self.footnotes.len() as u32; - let n_linked_doc = self.linked_docs.len() as u32; - let n_external = self.external_domains.len() as u32; - - let total_nodes = n_sections - + n_large_code - + n_large_table - + n_diagram - + n_footnote - + n_linked_doc - + n_external; - - if total_nodes == 0 { - return MrpcResult::default(); - } - - // Connected components via union-find. We only care about components - // among reachable nodes in the edge list; isolated artifact nodes - // that were created but never referenced are rare (§7.1 says edges - // make the node exist), but we count every declared node to stay - // faithful to `|N|`. - let p = connected_components(&self, total_nodes); - let n = total_nodes as f64; - - let sum_w: f64 = self.edges.iter().map(|e| e.kind.weight()).sum(); - let raw_edges = self.edges.len() as f64; - - let weighted = (sum_w - n + 2.0 * p).max(1.0); - let raw = raw_edges - n + 2.0 * p; - - MrpcResult { weighted, raw } - } -} - -fn connected_components(g: &GraphBuilder<'_>, total_nodes: u32) -> f64 { - use std::collections::HashMap; - - // Assign a compact integer id to every declared node so union-find is - // dense. - let mut ids: HashMap = HashMap::new(); - for i in 0..g.sections.len() { - ids.insert( - GraphNodeId { - kind: NodeKind::Section, - index: i as u32, - }, - ids.len(), - ); - } - for i in 0..g.large_codes { - ids.insert( - GraphNodeId { - kind: NodeKind::LargeCode, - index: i, - }, - ids.len(), - ); - } - for i in 0..g.large_tables { - ids.insert( - GraphNodeId { - kind: NodeKind::LargeTable, - index: i, - }, - ids.len(), - ); - } - for i in 0..g.diagrams { - ids.insert( - GraphNodeId { - kind: NodeKind::Diagram, - index: i, - }, - ids.len(), - ); - } - for idx in g.footnotes.values() { - ids.insert( - GraphNodeId { - kind: NodeKind::Footnote, - index: *idx, - }, - ids.len(), - ); - } - for idx in g.linked_docs.values() { - ids.insert( - GraphNodeId { - kind: NodeKind::LinkedDoc, - index: *idx, - }, - ids.len(), - ); - } - for idx in g.external_domains.values() { - ids.insert( - GraphNodeId { - kind: NodeKind::ExternalDomain, - index: *idx, - }, - ids.len(), - ); - } - - let mut parent: Vec = (0..(total_nodes as usize)).collect(); - - fn find(parent: &mut [usize], mut i: usize) -> usize { - while parent[i] != i { - parent[i] = parent[parent[i]]; - i = parent[i]; - } - i - } - fn union(parent: &mut [usize], a: usize, b: usize) { - let ra = find(parent, a); - let rb = find(parent, b); - if ra != rb { - parent[ra] = rb; - } - } - - for e in &g.edges { - let (Some(&a), Some(&b)) = (ids.get(&e.from), ids.get(&e.to)) else { - continue; - }; - union(&mut parent, a, b); - } - - let mut roots = std::collections::HashSet::new(); - for i in 0..(total_nodes as usize) { - roots.insert(find(&mut parent, i)); - } - roots.len() as f64 -} - -fn classify_link(dest: &str) -> LinkClass { - if dest.starts_with('#') { - LinkClass::InternalAnchor - } else if has_scheme(dest) { - LinkClass::External - } else { - LinkClass::Relative - } -} - -fn extract_domain(dest: &str) -> Option { - let pos = dest.find("://")?; - let rest = &dest[pos + 3..]; - let host_end = rest.find(['/', '?', '#']).unwrap_or(rest.len()); - let host = &rest[..host_end]; - if host.is_empty() { - return None; - } - // Strip userinfo ("user:pass@host"). - let host = match host.rfind('@') { - Some(at) => &host[at + 1..], - None => host, - }; - // Strip port. Bracketed IPv6 literals need special handling — a naive - // `rfind(':')` would split the address (`https://[2001:db8::1]/` → - // `[2001:db8:`) because the host itself contains colons. Per RFC 3986 - // the bracketed host is `[ … ]` and any port follows the closing `]`. - let host = if host.starts_with('[') { - match host.find(']') { - // `[ipv6]` or `[ipv6]:port` — keep everything up to and - // including the closing `]`; anything after (including an - // optional `:port`) is discarded. - Some(close) => &host[..=close], - // Malformed host (no closing `]`) — fall back to the whole - // slice rather than produce something worse. - None => host, - } - } else { - match host.rfind(':') { - Some(p) => &host[..p], - None => host, - } - }; - Some(host.to_ascii_lowercase()) -} - -fn normalize_relative_path(dest: &str) -> String { - // Drop any fragment so `foo.md#section` and `foo.md` collapse to one - // linked-doc node. Keep query components — they usually point at - // different targets. - if let Some(pos) = dest.find('#') { - dest[..pos].to_string() - } else { - dest.to_string() - } -} - -/// GFM slug builder: lowercases the source text of a heading, strips -/// punctuation except `-` and whitespace, collapses whitespace runs to `-`. -/// Returns `None` when the section has no heading (shouldn't happen in -/// well-formed grammars but we guard anyway). -fn extract_heading_slug(section: &Node<'_>, source: &str) -> Option { - let heading_node = find_heading_text_node(section)?; - let start = heading_node.start_byte(); - let end = heading_node.end_byte(); - let text = source.get(start..end)?.trim(); - Some(gfm_slug(text)) -} - -fn find_heading_text_node<'a>(section: &Node<'a>) -> Option> { - for child in section.children() { - if child.kind().is_heading() { - // The visible text lives in the heading-content child; fall back - // to the heading node itself if the grammar surface changes. - for n in child.children() { - if matches!(n.kind(), MdKind::HeadingContent) { - return Some(n); - } - } - return Some(child); - } - } - None -} - -/// Compute a GFM-style anchor slug. This intentionally mirrors GitHub's -/// anchor generation: lowercase, drop punctuation (except `-`/`_`), -/// collapse whitespace to `-`, strip leading/trailing dashes. -fn gfm_slug(text: &str) -> String { - let mut out = String::with_capacity(text.len()); - let mut last_dash = false; - for ch in text.chars() { - if ch.is_ascii_alphanumeric() { - out.push(ch.to_ascii_lowercase()); - last_dash = false; - } else if (ch.is_whitespace() || ch == '-' || ch == '_') && !last_dash && !out.is_empty() { - out.push('-'); - last_dash = true; - } - // drop everything else - } - while out.ends_with('-') { - out.pop(); - } - out -} - -/// Resolve `#anchor` to an existing section id. Leading `#` is stripped, -/// and the remainder is slugified the same way section headings were, -/// so the two forms compare equal even with upper-case or punctuated -/// source text. -fn resolve_anchor_to_section(dest: &str, section_slugs: &BTreeMap) -> Option { - let stripped = dest.strip_prefix('#')?; - let slug = gfm_slug(stripped); - if slug.is_empty() { - return None; - } - section_slugs.get(&slug).copied().map(|x| x as usize) -} - -/// Extract the URL from an `autolink` node. Autolinks wrap the URL in -/// `<>` and emit a `Uri` child; the text between the angle brackets is -/// the destination. -fn autolink_destination(node: &Node<'_>, source: &str) -> Option { - // Look for the `Uri` (or fallback to the whole node text) and strip - // the surrounding angle brackets. - for child in node.children() { - if matches!(child.kind(), MdKind::Uri) { - let bytes = source.as_bytes(); - let start = child.start_byte(); - let end = child.end_byte(); - if end <= bytes.len() && start < end { - let text = std::str::from_utf8(&bytes[start..end]).ok()?.trim(); - if !text.is_empty() { - return Some(text.to_string()); - } - } - } - } - // Fallback: strip `<>` from the raw node text. - let bytes = source.as_bytes(); - let start = node.start_byte(); - let end = node.end_byte(); - if end <= bytes.len() && start < end { - let text = std::str::from_utf8(&bytes[start..end]).ok()?.trim(); - let clean = text.trim_start_matches('<').trim_end_matches('>'); - if !clean.is_empty() { - return Some(clean.to_string()); - } - } - None -} - -fn footnote_def_label(node: &Node<'_>, source: &str) -> Option { - label_text(node, source, MdKind::FootnoteLabel) -} - -fn footnote_ref_label(node: &Node<'_>, source: &str) -> Option { - label_text(node, source, MdKind::FootnoteReferenceLabel) - .or_else(|| label_text(node, source, MdKind::FootnoteLabel)) -} - -fn label_text(node: &Node<'_>, source: &str, target: MdKind) -> Option { - let mut stack = vec![*node]; - while let Some(n) = stack.pop() { - if n.kind() == target { - let bytes = source.as_bytes(); - let start = n.start_byte(); - let end = n.end_byte(); - if end <= bytes.len() { - return std::str::from_utf8(&bytes[start..end]) - .ok() - .map(|s| s.trim().to_string()); - } - } - stack.extend(n.children()); - } - None -} - -#[cfg(test)] -mod tests { - use super::*; - - fn compute(src: &str) -> MrpcResult { - let (tree, document) = crate::syntax_tree::parse_with_document(src); - compute_mrpc(&tree.root(), &document, src) - } - - #[test] - fn empty_document_has_zero_mrpc() { - let r = compute(""); - assert_eq!(r.weighted, 0.0); - assert_eq!(r.raw, 0.0); - } - - #[test] - fn pure_prose_has_minimal_mrpc() { - let src = "# Title\n\nSome prose with no links or artifacts.\n"; - let r = compute(src); - // One section, no edges → weighted = max(1, 0 - 1 + 2*1) = 1.0. - assert_eq!(r.weighted, 1.0); - } - - #[test] - fn internal_anchor_resolves_to_existing_section() { - // Codex P1 on PR #83: `#anchor` links must resolve to an existing - // section node rather than fabricate a new LinkedDoc node per - // unique anchor. TOC-heavy documents used to bleed MRPC because - // every anchor added one node and one edge. - let src = "# Intro\n\n- [Install](#install)\n- [Usage](#usage)\n\n\ - # Install\n\nInstall prose.\n\n# Usage\n\nUsage prose.\n"; - let r = compute(src); - // 3 sections, 2 sequential edges (Intro→Install, Install→Usage), - // 2 internal-anchor edges (Intro→Install, Intro→Usage). No extra - // LinkedDoc nodes → node count stays at 3. - // Weighted: 2*0.20 (sequential) + 2*0.50 (internal) = 1.40. - // MRPC = max(1, 1.40 - 3 + 2*1) = max(1, 0.40) = 1.0. - assert_eq!(r.weighted, 1.0); - // Raw: 4 edges - 3 nodes + 2*1 = 3. - assert_eq!(r.raw, 3.0); - } - - #[test] - fn code_block_fact_line_count_excludes_delimiters() { - // Codex P2 on PR #83: LOC for a fenced code block must count - // content only. A fence with exactly 10 content lines used to - // report 12 LOC (opening + closing + 10) and trip the ≥12 LARGE - // threshold. - let src = "# Demo\n\n```text\n\ - a\nb\nc\nd\ne\nf\ng\nh\ni\nj\n\ - ```\n"; - let (_tree, document) = crate::syntax_tree::parse_with_document(src); - let block = document.code_blocks.first().expect("fenced block"); - assert_eq!(block.content_line_count(), 10); - } - - #[test] - fn gfm_slug_matches_github_style() { - assert_eq!(gfm_slug("Hello World!"), "hello-world"); - assert_eq!(gfm_slug("Install & Use"), "install-use"); - assert_eq!(gfm_slug("§3.4 Section"), "34-section"); - assert_eq!(gfm_slug(" "), ""); - assert_eq!(gfm_slug("__underscore__"), "underscore"); - } - - #[test] - fn external_link_gets_external_weight() { - let src = "# Title\n\nSee [rust-lang](https://www.rust-lang.org) for more.\n"; - let r = compute(src); - // N = 2 (section + external domain); E = 1 with weight 1.0. - // Weighted MRPC = max(1, 1.0 - 2 + 2*1) = 1.0. - assert_eq!(r.weighted, 1.0); - } - - #[test] - fn multi_section_mrpc_grows() { - let src = "# A\n\ntext\n\n## B\n\ntext\n\n## C\n\n[x](https://example.com)\n"; - let r = compute(src); - // 3 sections + 1 external domain = 4 nodes. - // Edges: 2 hierarchy (A→B, A→C), 1 sequential (B→C), 1 external. - // Sum weights = 0.15 + 0.15 + 0.20 + 1.00 = 1.50 - // |N| = 4, P = 1 → weighted = 1.50 - 4 + 2 = -0.50 → max(1, …) = 1.0 - assert_eq!(r.weighted, 1.0); - } - - #[test] - fn classify_link_behaves() { - assert_eq!(classify_link("#intro"), LinkClass::InternalAnchor); - assert_eq!(classify_link("./foo.md"), LinkClass::Relative); - assert_eq!(classify_link("foo.md#x"), LinkClass::Relative); - assert_eq!(classify_link("https://example.com/"), LinkClass::External); - assert_eq!(classify_link("mailto:x@y.z"), LinkClass::External); - } - - #[test] - fn extract_domain_handles_userinfo_and_port() { - assert_eq!( - extract_domain("https://user:pw@Example.COM:8443/x?y=1"), - Some("example.com".to_string()) - ); - assert_eq!(extract_domain("http://a.b/"), Some("a.b".to_string())); - assert_eq!(extract_domain("mailto:x@y.z"), None); - } - - #[test] - fn extract_domain_handles_bracketed_ipv6() { - // Codex P2 + Gemini medium on PR #83: bracketed IPv6 hosts with or - // without a port must not collapse onto a prefix-of-address key. - // Previously `rfind(':')` struck inside the literal and returned - // `[2001:db8:`, merging distinct endpoints into one external-domain - // node. - assert_eq!( - extract_domain("https://[2001:db8::1]/"), - Some("[2001:db8::1]".to_string()) - ); - assert_eq!( - extract_domain("https://[::1]:8080/path"), - Some("[::1]".to_string()) - ); - assert_eq!(extract_domain("https://[::1]/"), Some("[::1]".to_string())); - // Upper-case hex digits inside the literal lowercase as a unit; - // brackets are kept intact. - assert_eq!( - extract_domain("https://[FE80::1]:443/"), - Some("[fe80::1]".to_string()) - ); - // Non-bracketed hosts with port continue to work. - assert_eq!( - extract_domain("https://example.com:443/"), - Some("example.com".to_string()) - ); - } - - #[test] - fn reference_style_link_mrpc_matches_inline() { - // Codex P1 on PR #83: reference-style links must produce the same - // MRPC as their inline counterpart. Both links point at - // `../api.md` so the graph has 1 section + 1 linked_doc and the - // weighted form collapses to max(1, 0.80 - 2 + 2) = 1.0. - let inline = "# Title\n\nSee [docs](../api.md) for details.\n"; - let reference = - "# Title\n\nSee [docs][api-docs\\]] for details.\n\n[api-docs\\]]: ../api.md\n"; - let a = compute(inline); - let b = compute(reference); - assert_eq!( - a.weighted, b.weighted, - "inline vs reference-style weighted mismatch: {:?} vs {:?}", - a, b - ); - assert_eq!( - a.raw, b.raw, - "inline vs reference-style raw mismatch: {:?} vs {:?}", - a, b - ); - } - - #[test] - fn reference_style_external_links_match_inline_mrpc() { - let inline = "# Title\n\n[A](https://example.com/a) [B](https://example.com/b)\n"; - let reference = - "# Title\n\n[A][a] [B][b]\n\n[a]: https://example.com/a\n[b]: https://example.com/b\n"; - let a = compute(inline); - let b = compute(reference); - - assert_eq!( - a.weighted, b.weighted, - "inline vs external reference weighted mismatch: {:?} vs {:?}", - a, b - ); - assert_eq!( - a.raw, b.raw, - "inline vs external reference raw mismatch: {:?} vs {:?}", - a, b - ); - } -} diff --git a/crates/mehen-markdown/src/nearby.rs b/crates/mehen-markdown/src/nearby.rs deleted file mode 100644 index e81251ca..00000000 --- a/crates/mehen-markdown/src/nearby.rs +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Block-level neighborhood lookups shared by tables, visuals, and code. -//! -//! Several §§11–14 formulas ask whether a prose block explains or -//! introduces a nearby artifact. "Nearby" here is the §19 convention: -//! within ±2 top-level blocks (i.e. two blocks before or after the artifact -//! in the document order). This module walks the AST once, collects a -//! flat list of block rows, and exposes a helper that tells you whether a -//! given artifact line range has a prose block ±2 positions away. - -use crate::kind::NodeKind; -use crate::syntax_tree::Node; - -/// A flattened block descriptor. One entry per top-level block in the -/// document. Lines are one-based and inclusive. -#[derive(Debug, Clone, Copy)] -pub(crate) struct BlockSpan { - pub(crate) start_line: u64, - pub(crate) end_line: u64, - pub(crate) is_prose: bool, -} - -/// Collects every top-level block in the document, preserving order. A -/// "top-level block" is a direct child of a `section`, `document`, or -/// generic `block` container. We deliberately do not descend into -/// artifacts — they cover exactly the same line range and we need the -/// prose blocks around them, not inside them. -pub(crate) fn collect_blocks(root: &Node<'_>) -> Vec { - let mut out: Vec = Vec::new(); - walk(root, &mut out); - out -} - -fn walk(node: &Node<'_>, out: &mut Vec) { - let kind = node.kind(); - - if is_block_like(&kind) { - let start = (node.start_row() as u64) + 1; - let (end_row, end_col) = node.end_position(); - let mut end = end_row; - if end > node.start_row() && end_col == 0 { - end -= 1; - } - let end_line = (end as u64) + 1; - out.push(BlockSpan { - start_line: start, - end_line, - is_prose: is_prose_block(&kind), - }); - return; - } - - for child in node.children() { - walk(&child, out); - } -} - -fn is_block_like(kind: &NodeKind) -> bool { - matches!( - kind, - NodeKind::Paragraph - | NodeKind::FencedCodeBlock - | NodeKind::IndentedCodeBlock - | NodeKind::HtmlBlock - | NodeKind::MathBlock - | NodeKind::PipeTable - | NodeKind::BlockQuote - | NodeKind::Callout - | NodeKind::List - | NodeKind::ThematicBreak - | NodeKind::FootnoteDefinition - | NodeKind::LinkReferenceDefinition - | NodeKind::Heading { .. } - ) -} - -fn is_prose_block(kind: &NodeKind) -> bool { - matches!( - kind, - NodeKind::Paragraph - | NodeKind::BlockQuote - | NodeKind::Callout - | NodeKind::List - | NodeKind::Heading { .. } - ) -} - -/// True when the artifact spanning `[start_line, end_line]` has a prose -/// block within ±`radius` positions in the block-order index. -pub(crate) fn has_prose_within( - blocks: &[BlockSpan], - start_line: u64, - end_line: u64, - radius: usize, -) -> bool { - let Some(idx) = blocks - .iter() - .position(|b| b.start_line <= start_line && b.end_line >= end_line) - else { - return false; - }; - let lo = idx.saturating_sub(radius); - let hi = (idx + radius).min(blocks.len().saturating_sub(1)); - for (i, block) in blocks.iter().enumerate().take(hi + 1).skip(lo) { - if i == idx { - continue; - } - if block.is_prose { - return true; - } - } - false -} diff --git a/crates/mehen-markdown/src/prose/english/inclusive.rs b/crates/mehen-markdown/src/prose/english/inclusive.rs deleted file mode 100644 index 22b57871..00000000 --- a/crates/mehen-markdown/src/prose/english/inclusive.rs +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Inclusive-language flags (§33.12) — alex / retext-equality style. -//! -//! The bundled data file `inclusive_flags.txt` carries one entry per line: -//! `\t\t` -//! where `surface` is matched case-insensitively against word-boundaries -//! in the prose text. Preferred is informational. - -use std::sync::OnceLock; - -use regex::Regex; -use serde::Serialize; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct InclusiveReport { - pub flags: Vec, - pub inclusive_language_score: f64, - /// Total distinct surfaces flagged. - pub flag_count: u64, -} - -#[derive(Debug, Clone, Serialize)] -pub struct Flag { - pub category: String, - pub surface: String, - pub preferred: String, - pub count: u64, -} - -struct Entry { - category: String, - surface: String, - preferred: String, - // Pre-compiled regex with `\b` boundaries. - re: Regex, -} - -fn entries() -> &'static Vec { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - let raw = include_str!("../../data/inclusive_flags.txt"); - let mut out = Vec::new(); - for line in raw.lines() { - let line = line.trim(); - if line.is_empty() || line.starts_with('#') { - continue; - } - let parts: Vec<&str> = line.split('\t').collect(); - if parts.len() < 3 { - continue; - } - let surface = parts[1].trim(); - if surface.is_empty() { - continue; - } - let pattern = format!(r"(?i)\b{}\b", regex::escape(surface)); - if let Ok(re) = Regex::new(&pattern) { - out.push(Entry { - category: parts[0].trim().to_string(), - surface: surface.to_string(), - preferred: parts[2].trim().to_string(), - re, - }); - } - } - out - }) -} - -pub fn analyze(_words: &[String], raw_text: &str) -> InclusiveReport { - let mut flags: Vec = Vec::new(); - let mut total = 0u64; - for entry in entries() { - let count = entry.re.find_iter(raw_text).count() as u64; - if count > 0 { - total += count; - flags.push(Flag { - category: entry.category.clone(), - surface: entry.surface.clone(), - preferred: entry.preferred.clone(), - count, - }); - } - } - - // Score: start from 1.0, subtract 0.05 per hit, clamp to 0. - let score = (1.0 - 0.05 * total as f64).clamp(0.0, 1.0); - - InclusiveReport { - flags, - inclusive_language_score: (score * 1000.0).round() / 1000.0, - flag_count: total, - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn flags_whitelist() { - let text = "Please add IP to the whitelist."; - let r = analyze(&[], text); - assert!(r.flag_count >= 1); - assert!(r.flags.iter().any(|f| f.surface == "whitelist")); - } - - #[test] - fn no_flags_clean_text() { - let text = "Please add IP to the allowlist."; - let r = analyze(&[], text); - assert_eq!(r.flag_count, 0); - assert!((r.inclusive_language_score - 1.0).abs() < 0.01); - } -} diff --git a/crates/mehen-markdown/src/prose/english/lexical.rs b/crates/mehen-markdown/src/prose/english/lexical.rs deleted file mode 100644 index 1ad087a4..00000000 --- a/crates/mehen-markdown/src/prose/english/lexical.rs +++ /dev/null @@ -1,212 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! English lexical diversity and sentence/word moments (§32). -//! -//! Tier 0 scope: MATTR₅₀, hapax ratio, dis-legomena ratio, lexical density -//! (via NLTK stopwords), sentence/word-length moments. MTLD / HD-D / Yule's K -//! are Tier 2 and live behind `--features lexical-diversity` (not implemented -//! here). - -use std::collections::HashMap; -use std::collections::HashSet; -use std::sync::OnceLock; - -use serde::Serialize; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct EnglishLexical { - pub mattr_50: f64, - pub hapax_ratio: f64, - pub dis_ratio: f64, - pub lexical_density: f64, - pub avg_sentence_words: f64, - pub p90_sentence_words: u64, - pub max_sentence_words: u64, - pub stddev_sentence_words: f64, - pub avg_word_chars: f64, - pub p90_word_chars: u64, - pub sentence_count: u64, - pub words_total: u64, -} - -fn stopwords_set() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - let raw = include_str!("../../data/nltk_stopwords_en.txt"); - raw.lines() - .map(|l| l.trim()) - .filter(|l| !l.is_empty() && !l.starts_with('#')) - .map(|l| l.to_ascii_lowercase()) - .collect() - }) -} - -pub fn analyze(words_per_sent: &[Vec], words_flat: &[String]) -> EnglishLexical { - let words_total = words_flat.len() as u64; - let sentence_lengths: Vec = words_per_sent - .iter() - .filter(|s| !s.is_empty()) - .map(|s| s.len() as u64) - .collect(); - let sentence_count = sentence_lengths.len() as u64; - - // Sentence-length moments. - let avg_sent = if !sentence_lengths.is_empty() { - sentence_lengths.iter().sum::() as f64 / sentence_lengths.len() as f64 - } else { - 0.0 - }; - let p90_sent = percentile_u64(&sentence_lengths, 90); - let max_sent = sentence_lengths.iter().copied().max().unwrap_or(0); - let stddev_sent = stddev(&sentence_lengths, avg_sent); - - // Word-char moments. `chars().count()` is the Unicode scalar length. - let word_lens: Vec = words_flat - .iter() - .map(|w| w.chars().count() as u64) - .collect(); - let avg_word = if !word_lens.is_empty() { - word_lens.iter().sum::() as f64 / word_lens.len() as f64 - } else { - 0.0 - }; - let p90_word = percentile_u64(&word_lens, 90); - - // Diversity: MATTR, hapax, dis. Lowercase the tokens so case doesn't - // double-count types. - let norm: Vec = words_flat.iter().map(|w| w.to_ascii_lowercase()).collect(); - let types_total = { - let s: HashSet<&String> = norm.iter().collect(); - s.len() as f64 - }; - - let mattr_50 = mattr(&norm, 50); - let (hapax, dis) = hapax_and_dis_ratio(&norm); - - // Lexical density ≈ 1 − stopwords/tokens. - let stop_set = stopwords_set(); - let stop_count = norm.iter().filter(|w| stop_set.contains(*w)).count() as f64; - let lexical_density = if !norm.is_empty() { - 1.0 - (stop_count / norm.len() as f64) - } else { - 0.0 - }; - // Unused variable suppression: types_total is returned implicitly via - // hapax/dis denominators; we drop it. - let _ = types_total; - - EnglishLexical { - mattr_50: round3(mattr_50), - hapax_ratio: round3(hapax), - dis_ratio: round3(dis), - lexical_density: round3(lexical_density), - avg_sentence_words: round3(avg_sent), - p90_sentence_words: p90_sent, - max_sentence_words: max_sent, - stddev_sentence_words: round3(stddev_sent), - avg_word_chars: round3(avg_word), - p90_word_chars: p90_word, - sentence_count, - words_total, - } -} - -fn round3(x: f64) -> f64 { - if !x.is_finite() { - return 0.0; - } - (x * 1000.0).round() / 1000.0 -} - -/// Returns the p-th percentile (0..100) of a `u64` vector using -/// nearest-rank. Deterministic; no interpolation. -fn percentile_u64(values: &[u64], p: u8) -> u64 { - if values.is_empty() { - return 0; - } - let mut sorted = values.to_vec(); - sorted.sort(); - let rank = ((p as f64 / 100.0) * sorted.len() as f64).ceil() as usize; - let idx = rank.saturating_sub(1).min(sorted.len() - 1); - sorted[idx] -} - -fn stddev(values: &[u64], mean: f64) -> f64 { - if values.len() < 2 { - return 0.0; - } - let var: f64 = values - .iter() - .map(|&v| { - let d = v as f64 - mean; - d * d - }) - .sum::() - / values.len() as f64; - var.sqrt() -} - -/// Moving-average type-token ratio. Window size `w` (§32.2). If fewer than -/// `w` tokens are available, returns the single TTR over the full corpus. -fn mattr(tokens: &[String], w: usize) -> f64 { - if tokens.is_empty() { - return 0.0; - } - if tokens.len() < w { - let types: HashSet<&String> = tokens.iter().collect(); - return types.len() as f64 / tokens.len() as f64; - } - let mut sum = 0.0f64; - let mut windows = 0usize; - for start in 0..=(tokens.len() - w) { - let window = &tokens[start..start + w]; - let types: HashSet<&String> = window.iter().collect(); - sum += types.len() as f64 / w as f64; - windows += 1; - } - if windows == 0 { - return 0.0; - } - sum / windows as f64 -} - -/// Returns (`V1/V`, `V2/V`) — hapax ratio and dis-legomena ratio. -fn hapax_and_dis_ratio(tokens: &[String]) -> (f64, f64) { - if tokens.is_empty() { - return (0.0, 0.0); - } - let mut counts: HashMap<&String, u64> = HashMap::new(); - for t in tokens { - *counts.entry(t).or_insert(0) += 1; - } - let v = counts.len() as f64; - if v == 0.0 { - return (0.0, 0.0); - } - let v1 = counts.values().filter(|&&c| c == 1).count() as f64; - let v2 = counts.values().filter(|&&c| c == 2).count() as f64; - (v1 / v, v2 / v) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn mattr_single_window() { - let t: Vec = vec!["a", "b", "c", "a", "b", "c"] - .into_iter() - .map(String::from) - .collect(); - let m = mattr(&t, 3); - assert!((m - 1.0).abs() < 0.01); - } - - #[test] - fn hapax_all_unique() { - let t: Vec = vec!["a", "b", "c"].into_iter().map(String::from).collect(); - let (h, _) = hapax_and_dis_ratio(&t); - assert!((h - 1.0).abs() < 0.01); - } -} diff --git a/crates/mehen-markdown/src/prose/english/mod.rs b/crates/mehen-markdown/src/prose/english/mod.rs deleted file mode 100644 index 8198447c..00000000 --- a/crates/mehen-markdown/src/prose/english/mod.rs +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! English prose pipeline (§§31–33). -//! -//! Works on a concatenated-across-blocks plain-text string, post-stripping. -//! Sub-modules partition responsibility: -//! - [`sentences`]: UAX #29 + abbreviation-aware sentence segmentation. -//! - [`syllables`]: vowel-group heuristic. -//! - [`readability`]: FRES, FKGL, Fog, SMOG, ARI, CLI, Dale-Chall -//! (NGSL-backed), FORCAST, LIX, RIX, ensemble band. -//! - [`lexical`]: MATTR₅₀, hapax ratio, lexical density, moments. -//! - [`wording`]: passive, hedges, weasels, wordy phrases, adverbs, -//! nominalizations, expletives, lexical illusions, clichés, nonwords, -//! long sentences, WQS. -//! - [`inclusive`]: alex-style inclusive-language flags. - -pub mod inclusive; -pub mod lexical; -pub mod readability; -pub mod sentences; -pub mod syllables; -pub mod wording; - -use serde::Serialize; - -use self::inclusive::InclusiveReport; -pub use self::lexical::EnglishLexical; -use self::readability::ReadabilityReport; -use self::wording::WordingReport; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct EnglishReport { - pub readability: ReadabilityReport, - pub lexical: EnglishLexical, - pub wording: WordingReport, - pub inclusive_language: InclusiveReport, - pub short_doc_warning: bool, -} - -/// Runs the full English pipeline against `text`. -pub fn analyze(text: &str) -> EnglishReport { - // 1. Tokenize into sentences + words. Later stages reuse these. - let sents = sentences::split(text); - let words_per_sent: Vec> = sents - .iter() - .map(|s| sentences::words_in_sentence(s)) - .collect(); - let words_flat: Vec = words_per_sent.iter().flatten().cloned().collect(); - - let sentences_count = sents.iter().filter(|s| !s.trim().is_empty()).count(); - let words_count = words_flat.len(); - - // 2. Short-doc refusal per §37.5 / §29.1. - let short_doc = words_count < 100 || sentences_count < 5; - - let lexical = lexical::analyze(&words_per_sent, &words_flat); - - let readability = if short_doc { - // Emit zeros + explicit null-grades via a short-doc-only report. - readability::short_doc_report(&lexical) - } else { - readability::analyze(&sents, &words_per_sent) - }; - - let wording = wording::analyze(&sents, &words_per_sent); - let inclusive = inclusive::analyze(&words_flat, text); - - EnglishReport { - readability, - lexical, - wording, - inclusive_language: inclusive, - short_doc_warning: short_doc, - } -} diff --git a/crates/mehen-markdown/src/prose/english/readability.rs b/crates/mehen-markdown/src/prose/english/readability.rs deleted file mode 100644 index d739d0b5..00000000 --- a/crates/mehen-markdown/src/prose/english/readability.rs +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Classical English readability formulas (§31). -//! -//! Every formula is emitted with provenance — no averaging. Grade-level -//! refusal for SMOG when `sentences < 30` is baked in here. - -use std::collections::HashSet; -use std::sync::OnceLock; - -use serde::Serialize; - -use super::lexical::EnglishLexical; -use super::sentences::count_letters; -use super::syllables::{count_fog_syllables, count_syllables}; - -/// Cap on letter count contribution per word (§37.5 anti-gaming): a -/// CamelCase / snake_case identifier is at most 20 letters in ARI / CLI. -pub const IDENTIFIER_LEN_CAP: usize = 20; - -/// One complete readability report. Grade-level fields use `Option` so -/// they can be `null` on sub-threshold inputs (SMOG and short-doc guard). -#[derive(Debug, Clone, Serialize, Default)] -pub struct ReadabilityReport { - pub flesch_reading_ease: Option, - pub flesch_kincaid_grade: Option, - pub gunning_fog: Option, - pub smog: Option, - pub ari: Option, - pub coleman_liau: Option, - pub dale_chall_new: Option, - pub dale_chall_list: String, - pub forcast: Option, - pub lix: Option, - pub rix: Option, - pub ensemble_grade_band: [Option; 2], -} - -/// Returns an all-null report for inputs below the short-doc threshold. -pub fn short_doc_report(_lex: &EnglishLexical) -> ReadabilityReport { - ReadabilityReport { - dale_chall_list: "ngsl-1.2".to_string(), - ..ReadabilityReport::default() - } -} - -pub fn analyze(sents: &[String], words_per_sent: &[Vec]) -> ReadabilityReport { - let words: Vec<&str> = words_per_sent - .iter() - .flatten() - .map(|s| s.as_str()) - .collect(); - let words_count = words.len() as f64; - let sent_count = sents.iter().filter(|s| !s.trim().is_empty()).count() as f64; - if words_count == 0.0 || sent_count == 0.0 { - return ReadabilityReport { - dale_chall_list: "ngsl-1.2".to_string(), - ..ReadabilityReport::default() - }; - } - - let syllables_total: usize = words.iter().map(|w| count_syllables(w)).sum(); - let polysyllables_total = words.iter().filter(|w| count_syllables(w) >= 3).count() as f64; - let letters_total: usize = words - .iter() - .map(|w| count_letters(w, IDENTIFIER_LEN_CAP)) - .sum(); - - // FRES §31.1 - let fres = 206.835 - - 1.015 * (words_count / sent_count) - - 84.6 * (syllables_total as f64 / words_count); - - // FKGL §31.2 - let fkgl = - 0.39 * (words_count / sent_count) + 11.8 * (syllables_total as f64 / words_count) - 15.59; - - // Fog §31.3 — complex_word = >=3 syllables after stripping inflection + - // not proper-noun mid-sentence. - let fog = gunning_fog(sents, words_per_sent); - - // SMOG §31.4 — null if sentences < 30. - let smog = if sent_count < 30.0 { - None - } else { - Some(1.0430 * ((polysyllables_total * 30.0 / sent_count).sqrt()) + 3.1291) - }; - - // ARI §31.5 — cap word length at IDENTIFIER_LEN_CAP. - let ari = - 4.71 * (letters_total as f64 / words_count) + 0.5 * (words_count / sent_count) - 21.43; - - // Coleman-Liau §31.6 - let l = 100.0 * letters_total as f64 / words_count; - let s_per_100w = 100.0 * sent_count / words_count; - let cli = 0.0588 * l - 0.296 * s_per_100w - 15.8; - - // New Dale-Chall §31.7 — NGSL-backed. - let dc = dale_chall(&words, words_count, sent_count); - - // FORCAST §31.8 — 150-word sample, monosyllables count. - let forcast = forcast_score(&words); - - // LIX and RIX §31.9 - let long_words = words.iter().filter(|w| w.chars().count() >= 7).count() as f64; - let lix = (words_count / sent_count) + 100.0 * (long_words / words_count); - let rix = long_words / sent_count; - - // Ensemble band (min/max over FKGL, Fog, ARI, CLI). - let band_values = [fkgl, fog, ari, cli]; - let ensemble_lo = band_values.iter().copied().fold(f64::INFINITY, f64::min); - let ensemble_hi = band_values - .iter() - .copied() - .fold(f64::NEG_INFINITY, f64::max); - - ReadabilityReport { - flesch_reading_ease: Some(clamp_round(fres)), - flesch_kincaid_grade: Some(clamp_round(fkgl)), - gunning_fog: Some(clamp_round(fog)), - smog: smog.map(clamp_round), - ari: Some(clamp_round(ari)), - coleman_liau: Some(clamp_round(cli)), - dale_chall_new: Some(clamp_round(dc)), - dale_chall_list: "ngsl-1.2".to_string(), - forcast: forcast.map(clamp_round), - lix: Some(clamp_round(lix)), - rix: Some(clamp_round(rix)), - ensemble_grade_band: [ - Some(clamp_round(ensemble_lo)), - Some(clamp_round(ensemble_hi)), - ], - } -} - -fn clamp_round(x: f64) -> f64 { - // Guard against NaN / infinities; round to 3 decimals for stable - // snapshots. - if !x.is_finite() { - return 0.0; - } - (x * 1000.0).round() / 1000.0 -} - -/// Gunning Fog with the §31.3 proper-noun filter (skip capitalize-mid-sentence -/// tokens) and inflection-suffix stripping before syllable counting. -fn gunning_fog(sents: &[String], words_per_sent: &[Vec]) -> f64 { - let mut total_words = 0usize; - let mut complex = 0usize; - let mut total_sents = 0usize; - - for (sent, words) in sents.iter().zip(words_per_sent.iter()) { - if sent.trim().is_empty() { - continue; - } - total_sents += 1; - for (i, w) in words.iter().enumerate() { - total_words += 1; - // Skip mid-sentence proper nouns: capitalized first char but not - // the first word of the sentence. - let first_char = w.chars().next(); - let is_cap = first_char.map(|c| c.is_ascii_uppercase()).unwrap_or(false); - if is_cap && i > 0 { - continue; - } - let syl = count_fog_syllables(w); - if syl >= 3 { - complex += 1; - } - } - } - if total_words == 0 || total_sents == 0 { - return 0.0; - } - 0.4 * ((total_words as f64 / total_sents as f64) - + 100.0 * (complex as f64 / total_words as f64)) -} - -/// Returns the NGSL 1.2 headword set, lazy-initialised. -fn ngsl_set() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - let raw = include_str!("../../data/ngsl_1_2.txt"); - raw.lines() - .map(|l| l.trim()) - .filter(|l| !l.is_empty() && !l.starts_with('#')) - .map(|l| l.to_ascii_lowercase()) - .collect() - }) -} - -/// New Dale-Chall score using NGSL 1.2 as the familiar-word list. -fn dale_chall(words: &[&str], words_count: f64, sent_count: f64) -> f64 { - let ngsl = ngsl_set(); - let difficult = words.iter().filter(|w| !is_familiar(w, ngsl)).count() as f64; - let pdw = 100.0 * difficult / words_count; - let asl = words_count / sent_count; - let raw = 0.1579 * pdw + 0.0496 * asl; - if pdw > 5.0 { raw + 3.6365 } else { raw } -} - -/// Strips common inflectional suffixes before NGSL lookup, matching the -/// "inflectional stripping" rule in §31.7. -fn is_familiar(word: &str, set: &HashSet) -> bool { - let w = word.to_ascii_lowercase(); - if set.contains(&w) { - return true; - } - for suf in ["es", "ed", "ing", "ly", "s"] { - if let Some(base) = w.strip_suffix(suf) - && set.contains(base) - { - return true; - } - } - // Adjective -> adverb (`quick` -> `quickly`). - // Plural / possessive (`runner's`) — drop non-alpha tail. - let clean: String = w.chars().filter(|c| c.is_alphabetic()).collect(); - if clean != w && set.contains(&clean) { - return true; - } - false -} - -/// FORCAST §31.8 — `20 − N/10` where `N` = single-syllable words in a 150-word -/// sample. Returns `None` if `words.len() < 150`. -fn forcast_score(words: &[&str]) -> Option { - if words.len() < 150 { - return None; - } - let sample = &words[..150]; - let monosyllables = sample.iter().filter(|w| count_syllables(w) == 1).count() as f64; - Some(20.0 - (monosyllables / 10.0)) -} - -#[cfg(test)] -mod tests { - use super::super::sentences; - use super::*; - - #[test] - fn fres_reasonable_for_simple_text() { - let text = "The cat sat. It looked out. A bird flew. The sun was warm. \ - The grass was green. It played with a toy. It ran around. \ - Then it took a nap. It felt happy. It was a good day for the cat."; - let sents = sentences::split(text); - let wps: Vec> = sents - .iter() - .map(|s| sentences::words_in_sentence(s)) - .collect(); - let r = analyze(&sents, &wps); - // Easy text: FRES should be high. - let fres = r.flesch_reading_ease.unwrap(); - assert!(fres > 70.0, "expected easy text FRES > 70, got {fres}"); - } -} diff --git a/crates/mehen-markdown/src/prose/english/sentences.rs b/crates/mehen-markdown/src/prose/english/sentences.rs deleted file mode 100644 index 69d95a86..00000000 --- a/crates/mehen-markdown/src/prose/english/sentences.rs +++ /dev/null @@ -1,201 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! English sentence segmentation (§31.12). -//! -//! UAX #29 boundaries via `unicode-segmentation`, post-processed to: -//! - never break inside a known abbreviation (`Mr.`, `e.g.`, `U.S.`, ...) -//! - never break when the period is followed by a lowercase letter or digit -//! - always break at hard `\n\n` boundaries (Markdown block separation) -//! -//! The caller passes text that has already had inline code, URLs, HTML, MDX, -//! front-matter, image-alt targets and pipe-table delimiters stripped. - -use std::collections::HashSet; -use std::sync::OnceLock; - -use unicode_segmentation::UnicodeSegmentation; - -/// Returns the bundled abbreviation set. Lazy-initialised once per process. -fn abbreviations() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - let raw = include_str!("../../data/abbreviations_en.txt"); - raw.lines() - .map(|l| l.trim()) - .filter(|l| !l.is_empty() && !l.starts_with('#')) - .map(|l| l.to_string()) - .collect() - }) -} - -/// Splits `text` into sentences. Returns each sentence as an owned trimmed -/// string (empty strings are not returned). -pub fn split(text: &str) -> Vec { - // First, split on hard Markdown block boundaries. `\n\n` is the canonical - // Markdown paragraph break and is always a terminator. - let mut out: Vec = Vec::new(); - for block in text.split("\n\n") { - let block = block.trim(); - if block.is_empty() { - continue; - } - for s in split_block(block) { - let t = s.trim().to_string(); - if !t.is_empty() { - out.push(t); - } - } - } - out -} - -/// Splits a single Markdown-block span using UAX #29 + abbreviation fixups. -fn split_block(block: &str) -> Vec { - // Pull UAX #29 sentence boundaries as candidate splits. - let candidates: Vec<(usize, &str)> = - UnicodeSegmentation::split_sentence_bound_indices(block).collect(); - - if candidates.is_empty() { - return vec![block.to_string()]; - } - - let mut out: Vec = Vec::new(); - let mut buffer = String::new(); - let abbrevs = abbreviations(); - - for (_, piece) in candidates { - buffer.push_str(piece); - - // Decide whether to commit the buffer as a sentence at this - // boundary. The default UAX boundary is aggressive; we reject it - // when one of the abbreviation / trailing-char rules fires. - if ends_sentence(&buffer, abbrevs, block, piece) { - let trimmed = buffer.trim().to_string(); - if !trimmed.is_empty() { - out.push(trimmed); - } - buffer.clear(); - } - } - - if !buffer.trim().is_empty() { - out.push(buffer.trim().to_string()); - } - out -} - -/// Decides whether the buffer's trailing boundary represents a real sentence -/// end. -fn ends_sentence(buffer: &str, abbrevs: &HashSet, _full: &str, _piece: &str) -> bool { - // Must end in a terminator candidate. - let trimmed = buffer.trim_end(); - let last = trimmed.chars().last(); - let ends_terminator = matches!(last, Some('.') | Some('!') | Some('?')); - if !ends_terminator { - return false; - } - - // Abbreviation rule: take the last whitespace-delimited token and drop a - // trailing period. If that matches a bundled abbreviation, do not split. - if let Some(token) = last_token(trimmed) - && let Some(stripped) = token.strip_suffix('.') - { - // Case-sensitive exact and case-insensitive compare both handled - // — the bundled list stores forms like `e.g.`, `U.S.`, `Mr`. - // Many abbreviations store no trailing dot, so compare `stripped`. - if abbrevs.contains(stripped) || abbrevs.contains(stripped.to_lowercase().as_str()) { - return false; - } - // Full token including dot is sometimes the canonical form - // (e.g. `i.e.`, `e.g.`, `U.S.`). Try that too. - if abbrevs.contains(token) || abbrevs.contains(token.to_lowercase().as_str()) { - return false; - } - // Single-uppercase-letter initial (e.g. "A." "J." in "J. Smith"): - // never split; treat as an initial. - if stripped.chars().count() == 1 && stripped.chars().all(|c| c.is_ascii_uppercase()) { - return false; - } - } - - // Following-char rule: if the next char of the run is lowercase or digit, - // suppress. The caller feeds pieces; we peek at the next candidate. - // This is approximated by checking the char that comes after the last - // terminator across the full text — we don't have direct access here, so - // rely on the UAX boundary for that edge case. - // - // The next piece would handle this via `ends_sentence` too; for now we - // accept UAX's decision as long as abbreviation rule is satisfied. - - true -} - -/// Returns the last whitespace-delimited token in `s` (no trailing punct -/// stripping — caller handles that). -fn last_token(s: &str) -> Option<&str> { - s.split_whitespace().next_back() -} - -/// Tokenizes a sentence into words using UAX #29 word boundaries, then -/// filters out pure punctuation / whitespace tokens. -pub fn words_in_sentence(sentence: &str) -> Vec { - let mut out = Vec::new(); - for w in UnicodeSegmentation::unicode_words(sentence) { - // Keep tokens that contain at least one alphabetic or digit char. - if w.chars().any(|c| c.is_alphanumeric()) { - out.push(w.to_string()); - } - } - out -} - -/// Counts characters (ASCII letter + digit + some common word chars) in the -/// sentence, matching §31.5 conventions. Identifier-length cap is applied at -/// the caller (ARI / CLI). -pub fn count_letters(word: &str, cap: usize) -> usize { - let count = word - .chars() - .filter(|c| c.is_alphabetic() || c.is_ascii_digit()) - .count(); - count.min(cap) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn splits_simple_sentences() { - let text = "The quick brown fox. It jumps over the lazy dog."; - let s = split(text); - assert_eq!(s.len(), 2); - } - - #[test] - fn does_not_split_on_mr() { - let text = "I met Mr. Smith today. He was late."; - let s = split(text); - assert_eq!(s.len(), 2); - } - - #[test] - fn does_not_split_on_eg() { - let text = "Some compilers, e.g. gcc, are pedantic. Others are not."; - let s = split(text); - assert_eq!(s.len(), 2); - } - - #[test] - fn splits_on_paragraph_break() { - let text = "First paragraph.\n\nSecond paragraph."; - let s = split(text); - assert_eq!(s.len(), 2); - } - - #[test] - fn words_in_sentence_skip_punct() { - let w = words_in_sentence("Hello, world! How are you?"); - assert_eq!(w, vec!["Hello", "world", "How", "are", "you"]); - } -} diff --git a/crates/mehen-markdown/src/prose/english/syllables.rs b/crates/mehen-markdown/src/prose/english/syllables.rs deleted file mode 100644 index 874ca7ba..00000000 --- a/crates/mehen-markdown/src/prose/english/syllables.rs +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Vowel-group syllable counter (§31.11). -//! -//! Pure heuristic — no dictionary, no features — matching the Tier 0 -//! contract of §38. Exact CMU-backed counts ship behind `syllables-cmu` -//! (Tier 1a, currently unimplemented). - -/// Counts the number of heuristic syllables in `word`. Returns `≥ 1` for -/// any non-empty word. -pub fn count_syllables(word: &str) -> usize { - let w: String = word - .chars() - .filter(|c| c.is_ascii_alphabetic()) - .flat_map(|c| c.to_lowercase()) - .collect(); - if w.is_empty() { - return 0; - } - let vowels = ['a', 'e', 'i', 'o', 'u', 'y']; - let mut count = 0usize; - let mut prev_vowel = false; - for c in w.chars() { - let is_v = vowels.contains(&c); - if is_v && !prev_vowel { - count += 1; - } - prev_vowel = is_v; - } - if w.ends_with('e') && !w.ends_with("le") && count > 1 { - count -= 1; - } - if w.ends_with("ed") && count > 1 { - let second_last = w.chars().rev().nth(2); - if !matches!(second_last, Some('t') | Some('d')) { - count -= 1; - } - } - count.max(1) -} - -/// Gunning-Fog inflection-aware syllable counter (§31.3). Strips common -/// inflectional suffixes before counting so `preceded` doesn't trip the 3+ -/// threshold via `-ed`. -pub fn count_fog_syllables(word: &str) -> usize { - let w = word.to_ascii_lowercase(); - let w: String = w.chars().filter(|c| c.is_ascii_alphabetic()).collect(); - if w.is_empty() { - return 0; - } - let stripped: &str = if let Some(s) = w.strip_suffix("ing") { - s - } else if let Some(s) = w.strip_suffix("ed") { - s - } else if let Some(s) = w.strip_suffix("es") { - s - } else { - &w - }; - // Avoid zero-length stripped-token corner case. - let base = if stripped.is_empty() { &w } else { stripped }; - count_syllables(base) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn counts_basic() { - assert_eq!(count_syllables("hello"), 2); - assert_eq!(count_syllables("the"), 1); - assert_eq!(count_syllables("syllable"), 3); - // `cookie` demonstrates a known limitation of the vowel-group - // heuristic (§31.11): the trailing `-ie` is one vowel group, and - // the silent-`e` rule then drops it. CMU-backed counts (Tier 1a) - // return 2. We document the Tier-0 answer. - assert_eq!(count_syllables("cookie"), 1); - } - - #[test] - fn drops_silent_e() { - assert_eq!(count_syllables("make"), 1); - assert_eq!(count_syllables("wave"), 1); - assert_eq!(count_syllables("little"), 2); - } - - #[test] - fn non_alpha_safe() { - assert_eq!(count_syllables(""), 0); - assert_eq!(count_syllables("1234"), 0); - } - - #[test] - fn fog_strips_inflection() { - // The Fog count should be `≤` the raw count for any inflected form - // (i.e. stripping never lengthens syllables). That is the invariant - // the Gunning Fog index depends on — whether a particular word - // crosses the 3-syllable threshold is incidental. - let raw = count_syllables("preceded"); - let fog = count_fog_syllables("preceded"); - assert!(fog <= raw, "fog {fog} must be <= raw {raw}"); - - let raw2 = count_syllables("running"); - let fog2 = count_fog_syllables("running"); - assert!(fog2 <= raw2, "fog {fog2} must be <= raw {raw2}"); - } -} diff --git a/crates/mehen-markdown/src/prose/english/wording.rs b/crates/mehen-markdown/src/prose/english/wording.rs deleted file mode 100644 index d1fe1fce..00000000 --- a/crates/mehen-markdown/src/prose/english/wording.rs +++ /dev/null @@ -1,457 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! English wording and style heuristics (§33). -//! -//! Produces per-document density metrics and the §33.11 Wording Quality -//! Score. Every sub-score is emitted alongside the composite so writers can -//! see which axis drove a drop. - -use std::collections::HashSet; -use std::sync::OnceLock; - -use regex::Regex; -use serde::Serialize; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct WordingReport { - pub passive_ratio: f64, - pub hedge_density: f64, - pub weasel_density: f64, - pub wordy_density: f64, - pub adverb_density: f64, - pub nominalization_density: f64, - pub expletive_count: u64, - pub lexical_illusions: u64, - pub cliche_density: f64, - pub nonword_count: u64, - pub long_sentence_count: u64, - pub wording_quality_score: f64, -} - -pub fn analyze(sents: &[String], words_per_sent: &[Vec]) -> WordingReport { - let sent_count = sents.iter().filter(|s| !s.trim().is_empty()).count() as f64; - let words_flat: Vec = words_per_sent.iter().flatten().cloned().collect(); - let words_total = words_flat.len() as f64; - if words_total == 0.0 || sent_count == 0.0 { - return WordingReport::default(); - } - - let passive_ratio = passive_sentence_ratio(sents); - let hedge_density = hedge_density(&words_flat); - let weasel_density = weasel_density(&words_flat, sents); - let wordy_density = wordy_density(sents, words_total); - let adverb_density = adverb_density(&words_flat); - let nominalization_density = nominalization_density(&words_flat); - let expletive_count = expletive_count(sents); - let lexical_illusions = lexical_illusions(sents); - let cliche_density = cliche_density(sents, words_total); - let nonword_count = nonword_count(&words_flat); - let long_sentence_count = words_per_sent.iter().filter(|s| s.len() > 30).count() as u64; - let long_rate = if sent_count > 0.0 { - long_sentence_count as f64 / sent_count - } else { - 0.0 - }; - - // Wording Quality Score §33.11. - let wqs = clamp01( - 1.0 - 0.18 * sat(passive_ratio, 0.25, 0.60) - - 0.15 * sat(hedge_density, 0.02, 0.08) - - 0.12 * sat(weasel_density, 0.01, 0.05) - - 0.12 * sat(wordy_density, 0.01, 0.05) - - 0.10 * sat(adverb_density, 0.02, 0.06) - - 0.08 * sat(nominalization_density, 0.08, 0.20) - - 0.08 * sat(long_rate, 0.05, 0.30) - - 0.07 * sat(cliche_density, 0.002, 0.02) - - 0.05 * bool01(lexical_illusions > 0) - - 0.05 * bool01(nonword_count > 0), - ); - - WordingReport { - passive_ratio: round3(passive_ratio), - hedge_density: round3(hedge_density), - weasel_density: round3(weasel_density), - wordy_density: round3(wordy_density), - adverb_density: round3(adverb_density), - nominalization_density: round3(nominalization_density), - expletive_count: expletive_count as u64, - lexical_illusions: lexical_illusions as u64, - cliche_density: round3(cliche_density), - nonword_count: nonword_count as u64, - long_sentence_count, - wording_quality_score: round3(wqs), - } -} - -fn round3(x: f64) -> f64 { - if !x.is_finite() { - return 0.0; - } - (x * 1000.0).round() / 1000.0 -} - -fn clamp01(x: f64) -> f64 { - x.clamp(0.0, 1.0) -} - -/// Saturates at `lo..=hi`. Maps `x ≤ lo` to 0 and `x ≥ hi` to 1 linearly. -fn sat(x: f64, lo: f64, hi: f64) -> f64 { - if hi <= lo { - return 0.0; - } - ((x - lo) / (hi - lo)).clamp(0.0, 1.0) -} - -fn bool01(b: bool) -> f64 { - if b { 1.0 } else { 0.0 } -} - -// ---------- §33.1 Passive voice ----------------------------------------- - -fn irregular_past_participles() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - let raw = include_str!("../../data/passive_irregulars.txt"); - raw.lines() - .map(|l| l.trim()) - .filter(|l| !l.is_empty() && !l.starts_with('#')) - .map(|l| l.to_ascii_lowercase()) - .collect() - }) -} - -fn passive_regex() -> &'static Regex { - static CELL: OnceLock = OnceLock::new(); - CELL.get_or_init(|| { - // (?i) case-insensitive; \b...\b word boundaries. - Regex::new(r"(?i)\b(am|is|are|was|were|be|been|being)\s+(\w+)\b").unwrap() - }) -} - -/// Proportion of sentences with at least one passive match. -fn passive_sentence_ratio(sents: &[String]) -> f64 { - let irregs = irregular_past_participles(); - let re = passive_regex(); - let mut passive = 0usize; - let mut total = 0usize; - for s in sents { - if s.trim().is_empty() { - continue; - } - total += 1; - for cap in re.captures_iter(s) { - let Some(verb) = cap.get(2) else { - continue; - }; - let v = verb.as_str().to_ascii_lowercase(); - if v.ends_with("ed") || irregs.contains(&v) { - passive += 1; - break; - } - } - } - if total == 0 { - 0.0 - } else { - passive as f64 / total as f64 - } -} - -// ---------- §33.2 Hedges ------------------------------------------------ - -fn hedge_set() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| load_phrase_set(include_str!("../../data/hedges.txt"))) -} - -fn hedge_density(words: &[String]) -> f64 { - phrase_density(words, hedge_set()) -} - -// ---------- §33.3 Weasels ----------------------------------------------- - -fn weasel_set() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| load_phrase_set(include_str!("../../data/weasels.txt"))) -} - -fn weasel_density(words: &[String], sents: &[String]) -> f64 { - // Quoted-literal suppression (§37.5 item 3): skip sentences that carry - // an inline-code token. Backticks are stripped upstream in - // `extract_prose_text`, but `InlineCode` spans leave behind - // `INLINE_CODE_SENTINEL` — the sentinel survives sentence splitting - // and is filtered out of word tokenization, so it costs nothing at - // the metric level while still flagging the original technical - // context. Sentences containing it typically describe a - // backtick-wrapped identifier and shouldn't contribute to weasel - // density. - let suppressed: HashSet = sents - .iter() - .enumerate() - .filter_map(|(i, s)| { - if s.contains(crate::prose::lang_detect::INLINE_CODE_SENTINEL) { - Some(i) - } else { - None - } - }) - .collect(); - let set = weasel_set(); - let mut matches = 0usize; - // Multi-word phrases are handled by joining neighboring tokens. - for (i, s) in sents.iter().enumerate() { - if suppressed.contains(&i) { - continue; - } - let toks: Vec = s - .split_whitespace() - .map(|t| t.trim_matches(|c: char| !c.is_alphanumeric())) - .filter(|t| !t.is_empty()) - .map(|t| t.to_ascii_lowercase()) - .collect(); - for start in 0..toks.len() { - for end in (start + 1)..=(start + 4).min(toks.len()) { - let phrase = toks[start..end].join(" "); - if set.contains(&phrase) { - matches += 1; - } - } - } - } - if words.is_empty() { - 0.0 - } else { - matches as f64 / words.len() as f64 - } -} - -// ---------- §33.4 Wordy phrases ----------------------------------------- - -fn wordy_set() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| load_phrase_set(include_str!("../../data/wordy_phrases.txt"))) -} - -fn wordy_density(sents: &[String], words_total: f64) -> f64 { - let set = wordy_set(); - let mut matches = 0usize; - for s in sents { - let lower = s.to_ascii_lowercase(); - for phrase in set.iter() { - if lower.contains(phrase) { - matches += 1; - } - } - } - if words_total == 0.0 { - 0.0 - } else { - matches as f64 / words_total - } -} - -// ---------- §33.5 Adverbs ----------------------------------------------- - -fn adverb_exceptions() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - let raw = "only reply apply supply family early likely lovely silly holy \ - daily weekly monthly yearly lonely ugly belly hourly \ - ally rely ply imply comply multiply reply fly try dry"; - raw.split_whitespace() - .map(|s| s.to_ascii_lowercase()) - .collect() - }) -} - -fn adverb_density(words: &[String]) -> f64 { - if words.is_empty() { - return 0.0; - } - let exc = adverb_exceptions(); - let count = words - .iter() - .map(|w| w.to_ascii_lowercase()) - .filter(|w| w.ends_with("ly") && w.chars().count() > 3) - .filter(|w| !exc.contains(w)) - .count() as f64; - count / words.len() as f64 -} - -// ---------- §33.6 Nominalizations --------------------------------------- - -fn nominalization_density(words: &[String]) -> f64 { - if words.is_empty() { - return 0.0; - } - let suffixes = ["tion", "sion", "ment", "ence", "ance", "ity", "ness", "ism"]; - let count = words - .iter() - .map(|w| w.to_ascii_lowercase()) - .filter(|w| w.chars().count() > 5 && suffixes.iter().any(|s| w.ends_with(s))) - .count() as f64; - count / words.len() as f64 -} - -// ---------- §33.7 Expletive constructions ------------------------------- - -fn expletive_regex() -> &'static Regex { - static CELL: OnceLock = OnceLock::new(); - CELL.get_or_init(|| Regex::new(r"(?i)^\s*(there|it)\s+(is|are|was|were)\b").unwrap()) -} - -fn expletive_count(sents: &[String]) -> usize { - let re = expletive_regex(); - sents.iter().filter(|s| re.is_match(s)).count() -} - -// ---------- §33.8 Lexical illusions (doubled words) --------------------- - -fn lexical_illusions(sents: &[String]) -> usize { - let mut total = 0usize; - for s in sents { - let toks: Vec = s - .split_whitespace() - .map(|t| { - t.trim_matches(|c: char| !c.is_alphanumeric()) - .to_ascii_lowercase() - }) - .filter(|t| !t.is_empty() && t.chars().any(|c| c.is_alphabetic())) - .collect(); - for i in 1..toks.len() { - if toks[i] == toks[i - 1] { - total += 1; - } - } - } - total -} - -// ---------- §33.9 Clichés & non-words ----------------------------------- - -fn cliche_set() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| load_phrase_set(include_str!("../../data/cliches.txt"))) -} - -fn cliche_density(sents: &[String], words_total: f64) -> f64 { - let set = cliche_set(); - let mut matches = 0usize; - for s in sents { - let lower = s.to_ascii_lowercase(); - for phrase in set.iter() { - if lower.contains(phrase) { - matches += 1; - } - } - } - if words_total == 0.0 { - 0.0 - } else { - matches as f64 / (words_total / 1000.0).max(1.0) - } -} - -fn nonword_set() -> &'static HashSet { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| load_phrase_set(include_str!("../../data/nonwords.txt"))) -} - -fn nonword_count(words: &[String]) -> usize { - let set = nonword_set(); - words - .iter() - .filter(|w| set.contains(&w.to_ascii_lowercase())) - .count() -} - -// ---------- Helpers ----------------------------------------------------- - -fn load_phrase_set(raw: &str) -> HashSet { - raw.lines() - .map(|l| l.trim()) - .filter(|l| !l.is_empty() && !l.starts_with('#')) - .map(|l| l.to_ascii_lowercase()) - .collect() -} - -fn phrase_density(words: &[String], set: &HashSet) -> f64 { - if words.is_empty() { - return 0.0; - } - let mut matches = 0usize; - for start in 0..words.len() { - for end in (start + 1)..=(start + 4).min(words.len()) { - let phrase = words[start..end] - .iter() - .map(|w| w.to_ascii_lowercase()) - .collect::>() - .join(" "); - if set.contains(&phrase) { - matches += 1; - } - } - } - matches as f64 / words.len() as f64 -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn passive_detects_simple_case() { - let sents = vec![ - "The ball was thrown by the boy.".to_string(), - "The cat sleeps on the mat.".to_string(), - ]; - let r = passive_sentence_ratio(&sents); - assert!((r - 0.5).abs() < 0.01); - } - - #[test] - fn expletive_detects_there_is() { - let sents = vec!["There is no doubt.".to_string(), "The cat sat.".to_string()]; - assert_eq!(expletive_count(&sents), 1); - } - - #[test] - fn weasel_density_suppresses_sentinel_sentences() { - // Codex P2 regression: a sentence like `` `foo` is very fast `` - // used to bypass backtick-suppression because `InlineCode` spans - // are stripped upstream of sentence splitting, leaving no - // backtick in the sentence for `weasel_density` to detect. The - // fix substitutes `InlineCode` spans with `INLINE_CODE_SENTINEL` - // (U+FFFC), which survives sentence splitting and word - // tokenization. `weasel_density` now suppresses any sentence that - // carries the sentinel. - // - // Construct the post-strip sentence directly so this test - // doesn't depend on the Markdown parser pipeline. - let sentinel = crate::prose::lang_detect::INLINE_CODE_SENTINEL.to_string(); - // "very" is in the bundled weasel list — ensures the control - // case below actually fires. - let sent_sentinel = format!("{sentinel} is very fast"); - let words_sentinel: Vec = sent_sentinel - .split_whitespace() - .map(|s| s.to_string()) - .collect(); - - let with_density = weasel_density(&words_sentinel, &[sent_sentinel]); - assert_eq!( - with_density, 0.0, - "sentinel-carrying sentence must not contribute to weasel density, got {with_density}" - ); - - // Control: same weasel word in a sentence without the sentinel - // still registers. - let plain = "this is very fast".to_string(); - let words_plain: Vec = plain.split_whitespace().map(|s| s.to_string()).collect(); - let plain_density = weasel_density(&words_plain, &[plain]); - assert!( - plain_density > 0.0, - "sanity: weasel `very` must still register without sentinel, got {plain_density}" - ); - } -} diff --git a/crates/mehen-markdown/src/prose/japanese/jouyou.rs b/crates/mehen-markdown/src/prose/japanese/jouyou.rs deleted file mode 100644 index 5bbe5a7f..00000000 --- a/crates/mehen-markdown/src/prose/japanese/jouyou.rs +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Jōyō grade proxy (§35.2). -//! -//! Bundled list: `data/jouyou_kanji.txt` maps each Jōyō kanji to a grade -//! 1..=7 (1–6 elementary Kyōiku, 7 secondary Jōyō). Every kanji not in the -//! list is treated as grade 8 (hyōgai / 表外). - -use std::collections::HashMap; -use std::sync::OnceLock; - -use serde::Serialize; -use unicode_script::{Script, UnicodeScript}; - -#[derive(Debug, Clone, Serialize)] -pub struct JouyouStats { - pub grade_mean: f64, - pub hyougai_ratio: f64, - pub counted: u64, - /// Number of kanji classified as Jōyō. - pub jouyou_kanji: u64, - /// Number of kanji outside the Jōyō list. - pub hyougai_kanji: u64, -} - -impl Default for JouyouStats { - fn default() -> Self { - Self { - grade_mean: 0.0, - hyougai_ratio: 0.0, - counted: 0, - jouyou_kanji: 0, - hyougai_kanji: 0, - } - } -} - -fn grade_table() -> &'static HashMap { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - let raw = include_str!("../../data/jouyou_kanji.txt"); - let mut map = HashMap::new(); - for line in raw.lines() { - let line = line.trim(); - if line.is_empty() || line.starts_with('#') { - continue; - } - let mut parts = line.split('\t'); - let kanji = parts.next().unwrap_or("").trim(); - let grade = parts.next().unwrap_or("").trim(); - if kanji.is_empty() || grade.is_empty() { - continue; - } - let c = match kanji.chars().next() { - Some(c) => c, - None => continue, - }; - let g: u8 = match grade.parse() { - Ok(g) => g, - Err(_) => continue, - }; - map.insert(c, g); - } - map - }) -} - -pub fn analyze(text: &str) -> JouyouStats { - let table = grade_table(); - let mut total_kanji: u64 = 0; - let mut in_jouyou: u64 = 0; - let mut hyougai: u64 = 0; - let mut grade_sum: u64 = 0; - - for c in text.chars() { - if !matches!(c.script(), Script::Han) { - continue; - } - total_kanji += 1; - if let Some(&g) = table.get(&c) { - in_jouyou += 1; - grade_sum += g as u64; - } else { - hyougai += 1; - // Grade 8 contributes to the mean — high-weight penalty. - grade_sum += 8; - } - } - - let grade_mean = if total_kanji == 0 { - 0.0 - } else { - grade_sum as f64 / total_kanji as f64 - }; - let hyougai_ratio = if total_kanji == 0 { - 0.0 - } else { - hyougai as f64 / total_kanji as f64 - }; - - JouyouStats { - grade_mean: (grade_mean * 1000.0).round() / 1000.0, - hyougai_ratio: (hyougai_ratio * 1000.0).round() / 1000.0, - counted: total_kanji, - jouyou_kanji: in_jouyou, - hyougai_kanji: hyougai, - } -} diff --git a/crates/mehen-markdown/src/prose/japanese/jtf.rs b/crates/mehen-markdown/src/prose/japanese/jtf.rs deleted file mode 100644 index e3850d50..00000000 --- a/crates/mehen-markdown/src/prose/japanese/jtf.rs +++ /dev/null @@ -1,245 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! JTF (Japan Translation Federation) Japanese Style Guide conformance -//! (§36.5). Tier-0 rules 1, 3, 5, 7, 8, 11 are mechanically checkable. -//! -//! Output is a list of `{rule, severity, count}` entries plus the density -//! per 1,000 characters used by the Japanese WQS §36.7. - -use serde::Serialize; - -use super::jouyou::JouyouStats; -use super::scripts::ScriptComposition; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct JtfReport { - pub violations: Vec, - pub total_violations: u64, - pub violation_density_per_1000: f64, -} - -#[derive(Debug, Clone, Serialize)] -pub struct JtfViolation { - pub rule: String, - pub severity: String, - pub count: u64, -} - -pub fn analyze( - text: &str, - sents: &[String], - composition: &ScriptComposition, - jouyou: &JouyouStats, -) -> JtfReport { - let mut violations: Vec = Vec::new(); - - // Rule 1: keitai/jōtai consistency (warn). Flagged by wording module; we - // count mix cases here. - let mix = keitai_jotai_mix_count(sents); - if mix > 0 { - violations.push(JtfViolation { - rule: "rule-1-keitai-jotai-consistency".to_string(), - severity: "warn".to_string(), - count: mix, - }); - } - - // Rule 3: stick to Jōyō kanji — hyōgai count (warn). - if jouyou.hyougai_kanji > 0 { - violations.push(JtfViolation { - rule: "rule-3-jouyou-only".to_string(), - severity: "warn".to_string(), - count: jouyou.hyougai_kanji, - }); - } - - // Rule 5: trailing long-vowel on katakana compound endings — warn. - // Flag katakana compounds ending in certain chars where the long-vowel - // mark `ー` should have been kept (`コンピュータ` vs `コンピューター`). - let rule5 = count_missing_chouonpu(text); - if rule5 > 0 { - violations.push(JtfViolation { - rule: "rule-5-trailing-chouonpu".to_string(), - severity: "warn".to_string(), - count: rule5, - }); - } - - // Rule 7: kanji/hiragana/katakana must be full-width (error). - // Detect halfwidth kana U+FF66–U+FF9F. - let rule7 = text - .chars() - .filter(|c| { - let u = *c as u32; - (0xFF66..=0xFF9F).contains(&u) - }) - .count() as u64; - if rule7 > 0 { - violations.push(JtfViolation { - rule: "rule-7-fullwidth-kana".to_string(), - severity: "error".to_string(), - count: rule7, - }); - } - - // Rule 8: digits and Latin alphabet must be halfwidth (warn). - // Fullwidth digit / Latin inside Japanese text is a violation. - let mut rule8 = 0u64; - for c in text.chars() { - let u = c as u32; - if (0xFF10..=0xFF19).contains(&u) - || (0xFF21..=0xFF3A).contains(&u) - || (0xFF41..=0xFF5A).contains(&u) - { - rule8 += 1; - } - } - if rule8 > 0 { - violations.push(JtfViolation { - rule: "rule-8-halfwidth-digits-latin".to_string(), - severity: "warn".to_string(), - count: rule8, - }); - } - - // Rule 11: `.` `,` `` should be halfwidth (info). Detect - // fullwidth period `.`, fullwidth comma `,`, fullwidth space ` `. - let rule11 = text - .chars() - .filter(|&c| matches!(c, '.' | ',' | '\u{3000}')) - .count() as u64; - if rule11 > 0 { - violations.push(JtfViolation { - rule: "rule-11-halfwidth-punct".to_string(), - severity: "info".to_string(), - count: rule11, - }); - } - - let total: u64 = violations.iter().map(|v| v.count).sum(); - let density = if composition.visible_chars == 0 { - 0.0 - } else { - (total as f64 * 1000.0) / composition.visible_chars as f64 - }; - - JtfReport { - violations, - total_violations: total, - violation_density_per_1000: (density * 1000.0).round() / 1000.0, - } -} - -fn keitai_jotai_mix_count(sents: &[String]) -> u64 { - let mut keitai = 0u64; - let mut jotai = 0u64; - for s in sents { - let t: String = s - .chars() - .filter(|c| !c.is_whitespace()) - .collect::() - .trim_end_matches(['。', '!', '?', '!', '?', '.']) - .to_string(); - if t.is_empty() { - continue; - } - if t.ends_with("です") - || t.ends_with("ます") - || t.ends_with("でした") - || t.ends_with("ました") - || t.ends_with("ません") - || t.ends_with("ですか") - || t.ends_with("ますか") - { - keitai += 1; - } else if t.ends_with("だ") || t.ends_with("である") || t.ends_with("だった") { - jotai += 1; - } - } - if keitai > 0 && jotai > 0 { - keitai.min(jotai) - } else { - 0 - } -} - -/// Counts katakana compounds ending on specific characters where JTF -/// rule 5 prefers a trailing `ー`. Heuristic: a katakana run of length -/// ≥ 3 ending in one of the stem-ending vowels without a trailing `ー`. -/// -/// This is intentionally conservative — false positives are preferred to -/// false negatives because the output is advisory. -fn count_missing_chouonpu(text: &str) -> u64 { - let mut count = 0u64; - let chars: Vec = text.chars().collect(); - let mut i = 0; - let katakana_range = |c: char| { - let u = c as u32; - (0x30A0..=0x30FF).contains(&u) - }; - while i < chars.len() { - if katakana_range(chars[i]) { - let mut end = i; - while end < chars.len() && katakana_range(chars[end]) { - end += 1; - } - let len = end - i; - if len >= 3 { - // JTF rule 5: the run's final character must be one of the - // stem-ending vowels AND must not already be a `ー`. We do - // NOT skip runs that contain an internal `ー` — e.g. - // `コンピュータ` (internal `ー`, missing trailing `ー`) is - // still a rule-5 violation. The only exception is when the - // final character is itself `ー`, which means the chōonpu - // is already present. - let last = chars[end - 1]; - if last != 'ー' { - let ends = ['タ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'サ', 'ザ', 'ダ', 'バ']; - if ends.contains(&last) { - count += 1; - } - } - } - i = end; - } else { - i += 1; - } - } - count -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn rule5_flags_internal_chouonpu_missing_trailing() { - // Codex P2 regression: `コンピュータ` contains an internal `ー` but - // is missing the trailing `ー` (JTF rule 5 prefers `コンピューター`). - // The previous `has_internal` gate skipped runs that contained any - // `ー`, so this canonical violation was never counted. After the fix - // the rule only looks at the final character — present `ー` ⇒ OK, - // missing trailing stem-vowel ⇒ violation. - assert_eq!( - count_missing_chouonpu("コンピュータ"), - 1, - "コンピュータ has trailing タ without closing ー: must be a rule-5 violation" - ); - - // Negative control: `コンピューター` already has the trailing `ー`, - // so it must NOT be flagged. - assert_eq!( - count_missing_chouonpu("コンピューター"), - 0, - "コンピューター already ends in ー: must not fire" - ); - } - - #[test] - fn rule5_ignores_runs_shorter_than_three() { - // Short runs (< 3 katakana chars) are outside the heuristic band — - // they're too ambiguous to flag safely. - assert_eq!(count_missing_chouonpu("タラ"), 0); - } -} diff --git a/crates/mehen-markdown/src/prose/japanese/mod.rs b/crates/mehen-markdown/src/prose/japanese/mod.rs deleted file mode 100644 index b44c2e95..00000000 --- a/crates/mehen-markdown/src/prose/japanese/mod.rs +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Japanese prose pipeline (§§34–36). -//! -//! Tier-0 only. Works on concatenated block text. Sub-modules: -//! - [`scripts`]: Unicode script classification, ratios, script-run stats. -//! - [`sentences`]: bracket-aware `。!?` segmentation. -//! - [`tateishi`]: Tateishi simplified RS (§35.1). -//! - [`jouyou`]: Jōyō grade + hyōgai ratio (§35.2). -//! - [`wording`]: politeness, comma/period ratio, jukugo density, -//! long-kanji runs, weak-phrase / redundant / doubled-joshi heuristics. -//! - [`jtf`]: JTF rules 1, 3, 5, 7, 8, 11. - -pub mod jouyou; -pub mod jtf; -pub mod scripts; -pub mod sentences; -pub mod tateishi; -pub mod wording; - -use serde::Serialize; - -pub use self::jtf::JtfReport; -pub use self::scripts::ScriptComposition; -pub use self::wording::{JapaneseLexical, JapaneseWording}; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct JapaneseReport { - pub script_composition: ScriptComposition, - pub readability: JapaneseReadability, - pub lexical: JapaneseLexical, - pub wording: JapaneseWording, - pub style_conformance: JtfReport, - pub short_doc_warning: bool, -} - -#[derive(Debug, Clone, Serialize, Default)] -pub struct JapaneseReadability { - pub tateishi_rs: Option, - pub jouyou_grade_mean: Option, - pub hyougai_ratio: f64, -} - -pub fn analyze(text: &str) -> JapaneseReport { - // 1. Script composition + script runs — inputs for nearly everything. - let (script_composition, runs) = scripts::analyze(text); - - // 2. Sentences (bracket-aware). - let sents = sentences::split(text); - let sent_count = sents.len(); - - // Short-doc guard (§35.1): refuse readability when < 300 visible chars - // or when hiragana_ratio > 0.90. - let short = script_composition.visible_chars < 300 - || script_composition.hiragana_ratio > 0.90 - || sent_count < 5; - - // 3. Tateishi simplified RS (§35.1). - let tateishi_rs = if short { - None - } else { - Some(tateishi::tateishi_simplified_rs( - &runs, - &sents, - &script_composition, - )) - }; - - // 4. Jōyō grade stats (§35.2). - let jouyou = jouyou::analyze(text); - let jouyou_grade_mean = if jouyou.counted == 0 { - None - } else { - Some(jouyou.grade_mean) - }; - let hyougai_ratio = jouyou.hyougai_ratio; - - // 5. Lexical (comma/period ratio, avg sent chars, p90, jukugo). - let lexical = wording::lexical(&sents, &script_composition, &runs); - - // 6. JTF mechanical rules — computed first so wording's WQS can consume - // the resulting violation density per §36.7. - let style_conformance = jtf::analyze(text, &sents, &script_composition, &jouyou); - - // 7. Wording / politeness / weak phrases. Threads hyougai_ratio and - // the JTF violation density through so the composite Wording - // Quality Score (§36.7) covers those axes directly. - let wording = wording::wording( - text, - &sents, - &script_composition, - &runs, - &lexical, - jouyou.hyougai_ratio, - style_conformance.violation_density_per_1000, - ); - - JapaneseReport { - script_composition, - readability: JapaneseReadability { - tateishi_rs, - jouyou_grade_mean, - hyougai_ratio, - }, - lexical, - wording, - style_conformance, - short_doc_warning: short, - } -} diff --git a/crates/mehen-markdown/src/prose/japanese/scripts.rs b/crates/mehen-markdown/src/prose/japanese/scripts.rs deleted file mode 100644 index 1bae30df..00000000 --- a/crates/mehen-markdown/src/prose/japanese/scripts.rs +++ /dev/null @@ -1,217 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Japanese Unicode-script classification and script-run statistics -//! (§§34.1–34.4). -//! -//! Each grapheme cluster is bucketed into one of five visible classes: -//! hiragana, katakana, kanji (Han), latin, digit. Whitespace and CJK/ASCII -//! punctuation are excluded from ratios (§34.2). -//! -//! Script-run statistics feed Tateishi's formula (§35.1). A "run" is a -//! maximal substring of the same script class. - -use serde::Serialize; -use unicode_script::{Script, UnicodeScript}; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct ScriptComposition { - pub kanji_ratio: f64, - pub hiragana_ratio: f64, - pub katakana_ratio: f64, - pub latin_ratio: f64, - pub digit_ratio: f64, - pub script_entropy: f64, - pub visible_chars: u64, -} - -/// A run of characters in a single script class. -#[derive(Debug, Clone, Copy)] -pub struct Run { - pub class: Class, - pub length: u32, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Class { - Hiragana, - Katakana, - Kanji, - Latin, - Digit, - Other, // whitespace / punctuation / symbol -} - -/// Computes both the visible composition and the run list in a single pass. -pub fn analyze(text: &str) -> (ScriptComposition, Vec) { - let mut hira = 0u64; - let mut kata = 0u64; - let mut han = 0u64; - let mut lat = 0u64; - let mut dig = 0u64; - let mut visible = 0u64; - - let mut runs: Vec = Vec::new(); - let mut current_class: Option = None; - let mut current_len: u32 = 0; - - for c in text.chars() { - let class = classify(c); - - // Count visible chars and their category shares. - match class { - Class::Hiragana => { - hira += 1; - visible += 1; - } - Class::Katakana => { - kata += 1; - visible += 1; - } - Class::Kanji => { - han += 1; - visible += 1; - } - Class::Latin => { - lat += 1; - visible += 1; - } - Class::Digit => { - dig += 1; - visible += 1; - } - Class::Other => { - // Don't count toward visible or ratios. - } - } - - // Update run list — `Other` breaks a run but is not itself a run. - if class == Class::Other { - if let Some(cl) = current_class.take() { - if current_len > 0 { - runs.push(Run { - class: cl, - length: current_len, - }); - } - current_len = 0; - } - continue; - } - match current_class { - Some(cl) if cl == class => { - current_len += 1; - } - Some(_) => { - runs.push(Run { - class: current_class.unwrap(), - length: current_len, - }); - current_class = Some(class); - current_len = 1; - } - None => { - current_class = Some(class); - current_len = 1; - } - } - } - if let Some(cl) = current_class { - runs.push(Run { - class: cl, - length: current_len, - }); - } - - let total = visible.max(1) as f64; - let hir_r = hira as f64 / total; - let kat_r = kata as f64 / total; - let kan_r = han as f64 / total; - let lat_r = lat as f64 / total; - let dig_r = dig as f64 / total; - let entropy = shannon_entropy(&[hir_r, kat_r, kan_r, lat_r, dig_r]); - - let composition = ScriptComposition { - kanji_ratio: round3(kan_r), - hiragana_ratio: round3(hir_r), - katakana_ratio: round3(kat_r), - latin_ratio: round3(lat_r), - digit_ratio: round3(dig_r), - script_entropy: round3(entropy), - visible_chars: visible, - }; - (composition, runs) -} - -fn classify(c: char) -> Class { - let u = c as u32; - if c.is_whitespace() { - return Class::Other; - } - // CJK punctuation / full-width punctuation: Other. - if (0x3000..=0x303F).contains(&u) || (0xFF00..=0xFF0F).contains(&u) { - return Class::Other; - } - if c.is_ascii_punctuation() { - return Class::Other; - } - if (0x3040..=0x309F).contains(&u) || (0x1B130..=0x1B16F).contains(&u) { - return Class::Hiragana; - } - if (0x30A0..=0x30FF).contains(&u) - || (0x31F0..=0x31FF).contains(&u) - || (0xFF65..=0xFF9F).contains(&u) - { - return Class::Katakana; - } - if matches!(c.script(), Script::Han) { - return Class::Kanji; - } - if c.is_ascii_alphabetic() || (0xFF21..=0xFF3A).contains(&u) || (0xFF41..=0xFF5A).contains(&u) { - return Class::Latin; - } - if c.is_ascii_digit() || (0xFF10..=0xFF19).contains(&u) { - return Class::Digit; - } - Class::Other -} - -fn shannon_entropy(probs: &[f64]) -> f64 { - let mut e = 0.0; - for &p in probs { - if p > 0.0 { - e -= p * p.log2(); - } - } - e -} - -fn round3(x: f64) -> f64 { - if !x.is_finite() { - return 0.0; - } - (x * 1000.0).round() / 1000.0 -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn classify_hiragana() { - let (c, runs) = analyze("あいうえお"); - assert_eq!(c.visible_chars, 5); - assert!((c.hiragana_ratio - 1.0).abs() < 0.01); - assert_eq!(runs.len(), 1); - assert_eq!(runs[0].length, 5); - } - - #[test] - fn classify_mixed() { - let (c, _) = analyze("日本語は hello と ABC123 です"); - assert!(c.kanji_ratio > 0.0); - assert!(c.hiragana_ratio > 0.0); - assert!(c.latin_ratio > 0.0); - assert!(c.digit_ratio > 0.0); - } -} diff --git a/crates/mehen-markdown/src/prose/japanese/sentences.rs b/crates/mehen-markdown/src/prose/japanese/sentences.rs deleted file mode 100644 index 721f8e7b..00000000 --- a/crates/mehen-markdown/src/prose/japanese/sentences.rs +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Japanese sentence segmentation (§34.5). -//! -//! Tier-0 rules: -//! - Primary terminators: `。` `!` `?` (and `.!?` when the context is JA). -//! - Do not split inside `「…」` `『…』` `(…)` `(...)` brackets. -//! - Treat `\n\n` (paragraph break) as a terminator. -//! - Ellipsis `…` / `‥` / `...` is NOT a terminator. - -pub fn split(text: &str) -> Vec { - let mut out: Vec = Vec::new(); - for paragraph in text.split("\n\n") { - let p = paragraph.trim(); - if p.is_empty() { - continue; - } - for s in split_paragraph(p) { - let t = s.trim(); - if !t.is_empty() { - out.push(t.to_string()); - } - } - } - out -} - -fn split_paragraph(p: &str) -> Vec { - let mut out: Vec = Vec::new(); - let mut buf = String::new(); - let chars: Vec = p.chars().collect(); - let mut depth = 0i32; - let mut i = 0usize; - - while i < chars.len() { - let c = chars[i]; - - match c { - '「' | '『' | '(' | '(' | '[' | '【' | '《' | '〈' => depth += 1, - '」' | '』' | ')' | ')' | ']' | '】' | '》' | '〉' => { - depth = depth.saturating_sub(1).max(0); - } - _ => {} - } - - buf.push(c); - - // Ellipsis check — three dots (ASCII or Japanese `…`) are NOT - // terminators. - let is_ellipsis = c == '…' - || (c == '.' && { - let next = chars.get(i + 1).copied(); - let nnext = chars.get(i + 2).copied(); - next == Some('.') && nnext == Some('.') - }); - - if is_ellipsis && c == '.' { - // Emit the three dots as part of the buffer without terminating. - if let Some(&dot2) = chars.get(i + 1) { - buf.push(dot2); - } - if let Some(&dot3) = chars.get(i + 2) { - buf.push(dot3); - } - i += 3; - continue; - } - if is_ellipsis { - i += 1; - continue; - } - - let is_terminator = matches!(c, '。' | '!' | '?' | '!' | '?'); - // ASCII `.` is a terminator only when the preceding char was a kana - // or kanji (JA-context heuristic). - let ascii_period_as_term = c == '.' && { - chars - .get(i.saturating_sub(1)) - .map(|&p| is_ja_char(p)) - .unwrap_or(false) - }; - - if (is_terminator || ascii_period_as_term) && depth == 0 { - out.push(std::mem::take(&mut buf)); - } - i += 1; - } - - if !buf.trim().is_empty() { - out.push(buf); - } - out -} - -fn is_ja_char(c: char) -> bool { - let u = c as u32; - (0x3040..=0x309F).contains(&u) - || (0x30A0..=0x30FF).contains(&u) - || (0x4E00..=0x9FFF).contains(&u) - || (0x3400..=0x4DBF).contains(&u) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn splits_kuten() { - let t = "これは一文です。これも一文です。"; - let s = split(t); - assert_eq!(s.len(), 2); - } - - #[test] - fn keeps_brackets_intact() { - let t = "彼は「これは本だ。あれも本だ。」と言った。"; - let s = split(t); - // Only the outermost `。` terminates; the two inner ones are inside - // the quote. - assert_eq!(s.len(), 1); - } - - #[test] - fn ellipsis_is_not_terminator() { - let t = "そして…続きがあります。"; - let s = split(t); - assert_eq!(s.len(), 1); - } -} diff --git a/crates/mehen-markdown/src/prose/japanese/tateishi.rs b/crates/mehen-markdown/src/prose/japanese/tateishi.rs deleted file mode 100644 index 737a38d3..00000000 --- a/crates/mehen-markdown/src/prose/japanese/tateishi.rs +++ /dev/null @@ -1,133 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Tateishi simplified Japanese readability score (§35.1). -//! -//! ```text -//! RS = −0.12 * ls − 1.37 * la + 7.4 * lh − 23.18 * lc − 5.4 * lk -//! − 4.67 * cp + 115.79 -//! ``` -//! -//! Where: -//! ls = mean chars per sentence -//! la = mean chars per alphabet run -//! lh = mean chars per hiragana run -//! lc = mean chars per kanji run -//! lk = mean chars per katakana run -//! cp = `、` per `。` -//! -//! Calibrated so mean=50, SD=10; higher = easier. - -use super::scripts::{Class, Run, ScriptComposition}; - -pub fn tateishi_simplified_rs( - runs: &[Run], - sents: &[String], - _composition: &ScriptComposition, -) -> f64 { - let (la, lh, lc, lk) = run_means(runs); - - // Mean chars per sentence — only visible chars (ignore whitespace / - // punctuation terminators). - let mut total_visible = 0u64; - for s in sents { - for c in s.chars() { - if !c.is_whitespace() && !is_sentence_end_punct(c) { - total_visible += 1; - } - } - } - let ls = if !sents.is_empty() { - total_visible as f64 / sents.len() as f64 - } else { - 0.0 - }; - - // Comma/period ratio — count `、` and `。` across all sentences. - let mut comma = 0u64; - let mut period = 0u64; - for s in sents { - for c in s.chars() { - if c == '、' { - comma += 1; - } - if c == '。' { - period += 1; - } - } - } - let cp = if period == 0 { - 0.0 - } else { - comma as f64 / period as f64 - }; - - let rs = -0.12 * ls - 1.37 * la + 7.4 * lh - 23.18 * lc - 5.4 * lk - 4.67 * cp + 115.79; - round3(rs) -} - -fn run_means(runs: &[Run]) -> (f64, f64, f64, f64) { - let mut la_total = 0u64; - let mut la_count = 0u64; - let mut lh_total = 0u64; - let mut lh_count = 0u64; - let mut lc_total = 0u64; - let mut lc_count = 0u64; - let mut lk_total = 0u64; - let mut lk_count = 0u64; - - for r in runs { - let len = r.length as u64; - match r.class { - Class::Latin => { - la_total += len; - la_count += 1; - } - Class::Hiragana => { - lh_total += len; - lh_count += 1; - } - Class::Kanji => { - lc_total += len; - lc_count += 1; - } - Class::Katakana => { - lk_total += len; - lk_count += 1; - } - _ => {} - } - } - let la = if la_count == 0 { - 0.0 - } else { - la_total as f64 / la_count as f64 - }; - let lh = if lh_count == 0 { - 0.0 - } else { - lh_total as f64 / lh_count as f64 - }; - let lc = if lc_count == 0 { - 0.0 - } else { - lc_total as f64 / lc_count as f64 - }; - let lk = if lk_count == 0 { - 0.0 - } else { - lk_total as f64 / lk_count as f64 - }; - (la, lh, lc, lk) -} - -fn is_sentence_end_punct(c: char) -> bool { - matches!(c, '。' | '!' | '?' | '!' | '?' | '.') -} - -fn round3(x: f64) -> f64 { - if !x.is_finite() { - return 0.0; - } - (x * 1000.0).round() / 1000.0 -} diff --git a/crates/mehen-markdown/src/prose/japanese/wording.rs b/crates/mehen-markdown/src/prose/japanese/wording.rs deleted file mode 100644 index b3e5836f..00000000 --- a/crates/mehen-markdown/src/prose/japanese/wording.rs +++ /dev/null @@ -1,457 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Japanese wording heuristics (§§36.1–36.7). -//! -//! Tier-0: all checks run off static lists and regex-free substring matches -//! so the default binary needs no morphological analyzer. The Wording -//! Quality Score follows §36.7 verbatim. - -use std::sync::OnceLock; - -use serde::Serialize; - -use super::scripts::{Class, Run, ScriptComposition}; - -#[derive(Debug, Clone, Serialize, Default)] -pub struct JapaneseLexical { - pub avg_sentence_chars: f64, - pub p90_sentence_chars: u64, - pub max_sentence_chars: u64, - pub comma_period_ratio: f64, - pub jukugo_density: f64, - pub sentence_count: u64, - pub char_count: u64, -} - -#[derive(Debug, Clone, Serialize, Default)] -pub struct JapaneseWording { - pub politeness_dominant: String, - pub keitai_count: u64, - pub jotai_count: u64, - pub honorific_count: u64, - pub keitai_jotai_mix_count: u64, - pub weak_phrase_count: u64, - pub redundant_expression_count: u64, - pub doubled_joshi_count: u64, - pub long_kanji_run_count: u64, - pub max_comma_violation_count: u64, - pub max_ten_violation_count: u64, - pub long_sentence_count: u64, - pub wording_quality_score: f64, -} - -pub fn lexical( - sents: &[String], - _composition: &ScriptComposition, - runs: &[Run], -) -> JapaneseLexical { - let sent_lens: Vec = sents - .iter() - .map(|s| { - s.chars() - .filter(|c| { - !c.is_whitespace() && !matches!(*c, '。' | '!' | '?' | '!' | '?' | '.') - }) - .count() as u64 - }) - .collect(); - - let char_count: u64 = sent_lens.iter().sum(); - let avg_sent = if !sent_lens.is_empty() { - sent_lens.iter().sum::() as f64 / sent_lens.len() as f64 - } else { - 0.0 - }; - let max_sent = sent_lens.iter().copied().max().unwrap_or(0); - let p90_sent = percentile_u64(&sent_lens, 90); - - // comma/period ratio. - let mut comma = 0u64; - let mut period = 0u64; - for s in sents { - for c in s.chars() { - if c == '、' { - comma += 1; - } - if c == '。' { - period += 1; - } - } - } - let cpr = if period == 0 { - 0.0 - } else { - comma as f64 / period as f64 - }; - - // Jukugo density: kanji runs with length >= 2 divided by total kanji - // runs (§36.2). - let mut total_kanji_runs = 0u64; - let mut jukugo_runs = 0u64; - for r in runs { - if r.class == Class::Kanji { - total_kanji_runs += 1; - if r.length >= 2 { - jukugo_runs += 1; - } - } - } - let jukugo_density = if total_kanji_runs == 0 { - 0.0 - } else { - jukugo_runs as f64 / total_kanji_runs as f64 - }; - - JapaneseLexical { - avg_sentence_chars: round3(avg_sent), - p90_sentence_chars: p90_sent, - max_sentence_chars: max_sent, - comma_period_ratio: round3(cpr), - jukugo_density: round3(jukugo_density), - sentence_count: sents.len() as u64, - char_count, - } -} - -pub fn wording( - text: &str, - sents: &[String], - _composition: &ScriptComposition, - runs: &[Run], - lexical: &JapaneseLexical, - hyougai_ratio: f64, - jtf_violation_density_per_1000: f64, -) -> JapaneseWording { - // Politeness classification. - let (keitai, jotai, honorific) = classify_politeness(sents); - let total_sents = (keitai + jotai + honorific) as f64; - let politeness_dominant = if total_sents == 0.0 { - "none".to_string() - } else { - // Honorific + keitai are both polite styles; aggregate as keitai. - let polite = keitai + honorific; - let plain = jotai; - if polite > plain { - "keitai".to_string() - } else if plain > polite { - "jotai".to_string() - } else { - "mixed".to_string() - } - }; - let keitai_jotai_mix_count = if politeness_dominant == "keitai" { - jotai - } else if politeness_dominant == "jotai" { - keitai + honorific - } else { - // Mixed: count the smaller group. - (keitai + honorific).min(jotai) - }; - - // Weak / redundant. - let weak_phrase_count = count_phrase_occurrences(text, weak_phrases()); - let redundant_expression_count = count_phrase_occurrences(text, redundant_expressions()); - - // Doubled joshi (simple pattern): any of `を・は・が・に` appearing twice - // within the same sentence with at least 1 char separation. - let doubled_joshi_count = count_doubled_joshi(sents); - - // Long kanji runs: run length >= 7 (§36.6 max-kanji-continuous-len ≤ 6). - let long_kanji_run_count = runs - .iter() - .filter(|r| r.class == Class::Kanji && r.length >= 7) - .count() as u64; - - // max-comma (,): > 3 per sentence violates (halfwidth and fullwidth). - let max_comma_violation_count = sents - .iter() - .filter(|s| s.chars().filter(|&c| c == ',' || c == ',').count() > 3) - .count() as u64; - // max-ten (、): > 3 per sentence violates. - let max_ten_violation_count = sents - .iter() - .filter(|s| s.chars().filter(|&c| c == '、').count() > 3) - .count() as u64; - // sentence-length: > 100 visible chars per sentence violates. - let long_sentence_count = sents - .iter() - .filter(|s| { - s.chars() - .filter(|c| { - !c.is_whitespace() && !matches!(*c, '。' | '!' | '?' | '!' | '?' | '.') - }) - .count() - > 100 - }) - .count() as u64; - - let sent_n = lexical.sentence_count.max(1) as f64; - let weak_rate = weak_phrase_count as f64 / sent_n; - let redundant_rate = redundant_expression_count as f64 / sent_n; - let long_rate = long_sentence_count as f64 / sent_n; - let long_kanji_rate = long_kanji_run_count as f64 / sent_n; - let max_comma_rate = max_comma_violation_count as f64 / sent_n; - let mix_ratio = if total_sents > 0.0 { - keitai_jotai_mix_count as f64 / total_sents - } else { - 0.0 - }; - - // Japanese Wording Quality Score §36.7. - // - // The §36.7 formula has explicit `hyougai_ratio` and - // `jtf_violation_density` terms; earlier revisions reused - // `long_kanji_rate` as a placeholder for both, which let hyōgai-heavy - // or JTF-violating documents keep a clean WQS. The jouyou + JTF signals - // are now threaded in directly so the score responds to those axes. - let wqs = clamp01( - 1.0 - 0.15 * sat(long_rate, 0.05, 0.30) - - 0.12 * sat(weak_rate, 0.01, 0.05) - - 0.12 * sat(redundant_rate, 0.01, 0.05) - - 0.10 * sat(doubled_joshi_count as f64 / sent_n, 0.02, 0.10) - - 0.10 * sat(long_kanji_rate, 0.05, 0.25) - - 0.10 - * if keitai_jotai_mix_count > 0 { - sat(mix_ratio, 0.02, 0.20) - } else { - 0.0 - } - - 0.08 * sat(max_comma_rate, 0.02, 0.15) - - 0.08 * sat(hyougai_ratio, 0.05, 0.25) - - 0.07 * sat(jtf_violation_density_per_1000, 0.5, 5.0), - ); - - JapaneseWording { - politeness_dominant, - keitai_count: keitai, - jotai_count: jotai, - honorific_count: honorific, - keitai_jotai_mix_count, - weak_phrase_count, - redundant_expression_count, - doubled_joshi_count, - long_kanji_run_count, - max_comma_violation_count, - max_ten_violation_count, - long_sentence_count, - wording_quality_score: round3(wqs), - } -} - -fn classify_politeness(sents: &[String]) -> (u64, u64, u64) { - let mut keitai = 0u64; - let mut jotai = 0u64; - let mut honorific = 0u64; - - let honor_suffixes = [ - "いらっしゃる", - "いらっしゃいます", - "召し上がる", - "おります", - "ございます", - "ございました", - ]; - let keitai_suffixes = [ - "です", - "ます", - "でした", - "ました", - "ません", - "でしょう", - "ましょう", - "ですか", - "ますか", - ]; - let jotai_suffixes = ["だ", "である", "だった", "であった", "なのだ"]; - - for s in sents { - // Work on the sentence after trimming trailing punctuation. - let trimmed: String = s - .chars() - .filter(|c| !c.is_whitespace()) - .collect::() - .trim_end_matches(['。', '!', '?', '!', '?', '.']) - .to_string(); - if trimmed.is_empty() { - continue; - } - - let mut classified = false; - for suf in honor_suffixes { - if trimmed.ends_with(suf) { - honorific += 1; - classified = true; - break; - } - } - if classified { - continue; - } - for suf in keitai_suffixes { - if trimmed.ends_with(suf) { - keitai += 1; - classified = true; - break; - } - } - if classified { - continue; - } - for suf in jotai_suffixes { - if trimmed.ends_with(suf) { - jotai += 1; - break; - } - } - } - - (keitai, jotai, honorific) -} - -fn weak_phrases() -> &'static Vec { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - include_str!("../../data/ja_weak_phrases.txt") - .lines() - .map(|l| l.trim()) - .filter(|l| !l.is_empty() && !l.starts_with('#')) - .map(String::from) - .collect() - }) -} - -fn redundant_expressions() -> &'static Vec { - static CELL: OnceLock> = OnceLock::new(); - CELL.get_or_init(|| { - include_str!("../../data/ja_redundant.txt") - .lines() - .map(|l| l.trim()) - .filter(|l| !l.is_empty() && !l.starts_with('#')) - .map(String::from) - .collect() - }) -} - -fn count_phrase_occurrences(text: &str, phrases: &[String]) -> u64 { - let mut total = 0u64; - for p in phrases { - // Walk the text, counting non-overlapping matches. - let mut haystack = text; - while let Some(idx) = haystack.find(p.as_str()) { - total += 1; - haystack = &haystack[idx + p.len()..]; - } - } - total -} - -fn count_doubled_joshi(sents: &[String]) -> u64 { - let mut total = 0u64; - let joshi = ['を', 'は', 'が', 'に', 'で', 'と', 'も']; - for s in sents { - for j in joshi { - let occurrences: Vec = s - .chars() - .enumerate() - .filter_map(|(i, c)| if c == j { Some(i) } else { None }) - .collect(); - // Count pairs separated by at least 1 char (min_interval=1). - for w in occurrences.windows(2) { - if w[1] - w[0] > 1 { - total += 1; - } - } - } - } - total -} - -fn percentile_u64(values: &[u64], p: u8) -> u64 { - if values.is_empty() { - return 0; - } - let mut sorted = values.to_vec(); - sorted.sort(); - let rank = ((p as f64 / 100.0) * sorted.len() as f64).ceil() as usize; - let idx = rank.saturating_sub(1).min(sorted.len() - 1); - sorted[idx] -} - -fn clamp01(x: f64) -> f64 { - x.clamp(0.0, 1.0) -} - -fn sat(x: f64, lo: f64, hi: f64) -> f64 { - if hi <= lo { - return 0.0; - } - ((x - lo) / (hi - lo)).clamp(0.0, 1.0) -} - -fn round3(x: f64) -> f64 { - if !x.is_finite() { - return 0.0; - } - (x * 1000.0).round() / 1000.0 -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn politeness_keitai() { - let s = vec!["これはテストです。".to_string(), "動作します。".to_string()]; - let (k, j, _) = classify_politeness(&s); - assert_eq!(k, 2); - assert_eq!(j, 0); - } - - #[test] - fn politeness_jotai() { - let s = vec!["これはテストだ。".to_string()]; - let (_, j, _) = classify_politeness(&s); - assert_eq!(j, 1); - } - - #[test] - fn weak_phrase_detected() { - let text = "このバージョンは動くかもしれない。"; - assert!(count_phrase_occurrences(text, weak_phrases()) > 0); - } - - #[test] - fn wqs_responds_to_hyougai_and_jtf_signals() { - // Codex P1 regression: §36.7 has explicit hyougai_ratio and - // jtf_violation_density terms. Earlier revisions reused - // long_kanji_rate as a stand-in, which left the composite WQS - // blind to both axes. After the fix, the same document scored - // with clean jouyou/JTF signals must score HIGHER than one with - // hyougai_ratio=0.30 and jtf_violation_density=3.0. - use super::super::scripts::ScriptComposition; - let text = "これはテストです。動作します。"; - let sents = vec!["これはテストです。".to_string(), "動作します。".to_string()]; - let composition = ScriptComposition::default(); - let runs: Vec = Vec::new(); - let lexical = JapaneseLexical { - avg_sentence_chars: 10.0, - p90_sentence_chars: 10, - max_sentence_chars: 10, - comma_period_ratio: 0.0, - jukugo_density: 0.0, - sentence_count: 2, - char_count: 20, - }; - - let clean = wording(text, &sents, &composition, &runs, &lexical, 0.0, 0.0); - let dirty = wording(text, &sents, &composition, &runs, &lexical, 0.30, 3.0); - - assert!( - dirty.wording_quality_score < clean.wording_quality_score, - "WQS must drop when hyougai/JTF signals are present: clean={}, dirty={}", - clean.wording_quality_score, - dirty.wording_quality_score - ); - } -} diff --git a/crates/mehen-markdown/src/prose/lang_detect.rs b/crates/mehen-markdown/src/prose/lang_detect.rs deleted file mode 100644 index 92b4c264..00000000 --- a/crates/mehen-markdown/src/prose/lang_detect.rs +++ /dev/null @@ -1,700 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Block-level language detection (§30). -//! -//! Tier 0 uses a zero-dependency Unicode-script block-ratio heuristic: -//! -//! ```text -//! kana = hiragana + katakana -//! cjk = kana + han -//! latin = ascii_letter + fullwidth_latin_letter -//! total = non_whitespace_non_punct -//! -//! if kana / total >= 0.15 -> ja -//! elif cjk / total >= 0.40 and kana == 0 -> other (Chinese) -//! elif latin / total >= 0.80 -> en -//! else -> other -//! ``` -//! -//! Short blocks (< 15 visible chars) that classify as `Other` inherit the -//! enclosing heading's language — a stable deterministic fallback that keeps -//! short list items from fragmenting a document's classification. -//! -//! Code fences, link destinations, front-matter, HTML, MDX, math and tables -//! are tagged [`Language::None`] and excluded from prose analysis entirely. - -use serde::Serialize; -use unicode_script::{Script, UnicodeScript}; - -use crate::kind::NodeKind; -use crate::syntax_tree::Node; - -/// Sentinel character inserted where an `InlineCode` span was stripped. -/// -/// Downstream stages (sentence splitter, word tokenizer, wording metrics) -/// see this as a single "object" placeholder. It survives sentence -/// splitting (it isn't a sentence terminator) and gets filtered out of -/// word tokenization (it isn't alphanumeric), so metric rates are -/// unchanged — but a sentence that originally contained `` `foo` `` can -/// still be detected as "had inline code" by checking for the sentinel. -/// -/// U+FFFC OBJECT REPLACEMENT CHARACTER is the canonical Unicode marker -/// for a removed inline object and will never appear in real prose. -pub const INLINE_CODE_SENTINEL: char = '\u{FFFC}'; - -/// Per-block language tag. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Language { - /// English (or other Latin-script prose). - En, - /// Japanese (any hiragana/katakana presence above threshold). - Ja, - /// Non-EN, non-JA — e.g. Chinese, Korean, Thai, Arabic, etc. - Other, - /// Mixed — aggregated at document level when both en and ja appear. - Mixed, - /// Not prose: code, front-matter, HTML, table, math, image target. - None, -} - -impl Language { - pub fn as_str(&self) -> &'static str { - match self { - Language::En => "en", - Language::Ja => "ja", - Language::Other => "other", - Language::Mixed => "mixed", - Language::None => "none", - } - } -} - -/// One prose-eligible block extracted from the tree. -#[derive(Debug, Clone)] -pub(crate) struct ProseBlock<'a> { - pub(crate) kind: NodeKind, - pub start_line: u64, - pub end_line: u64, - /// Stripped prose text: inline code / URLs / alt-text destination already - /// removed so script ratios aren't polluted by literal tokens. - pub text: String, - pub _raw: &'a [u8], -} - -/// Like [`ProseBlock`] but carries a resolved language tag for downstream -/// metric dispatch. -#[derive(Debug, Clone)] -pub(crate) struct DetectedBlock { - pub(crate) kind: NodeKind, - pub start_line: u64, - pub end_line: u64, - pub text: String, - pub language: Language, -} - -/// Walks the parse tree and collects every prose-eligible block in document -/// order. -pub(crate) fn collect_prose_blocks<'a>(root: &Node<'_>, source: &'a [u8]) -> Vec> { - let mut blocks = Vec::new(); - walk(root, source, &mut blocks); - blocks -} - -fn walk<'a>(node: &Node<'_>, source: &'a [u8], blocks: &mut Vec>) { - let kind = node.kind(); - - // Prose-carrying blocks we record. For list items we recurse so that - // nested paragraphs / blockquotes / callouts are recorded individually - // — matching §30.3's per-block tagging requirement. - let is_prose_block = kind.is_heading() - || matches!( - kind, - NodeKind::Paragraph - | NodeKind::BlockQuote - | NodeKind::Callout - | NodeKind::ListItemContent { .. } - ); - - // Stop containers: never descend, never emit. - let is_stop = matches!( - kind, - NodeKind::FencedCodeBlock - | NodeKind::IndentedCodeBlock - | NodeKind::HtmlBlock - | NodeKind::MinusMetadata - | NodeKind::PlusMetadata - | NodeKind::MathBlock - | NodeKind::PipeTable - | NodeKind::LinkReferenceDefinition - | NodeKind::ThematicBreak - ); - - if is_stop { - return; - } - - if is_prose_block { - let start_line = (node.start_row() as u64) + 1; - let (end_row, end_col) = node.end_position(); - let mut end_line = (end_row as u64) + 1; - if end_col == 0 && end_line > start_line { - end_line -= 1; - } - let is_container = matches!(kind, NodeKind::BlockQuote | NodeKind::Callout) - || (matches!(kind, NodeKind::ListItemContent { .. }) && has_nested_prose_block(node)); - - if is_container { - // Containers (blockquote / callout) don't emit their own slice: - // recurse into children so nested paragraphs are counted exactly - // once. Emitting both the container text AND descending into - // children would double-count every word / sentence inside. - for child in node.children() { - walk(&child, source, blocks); - } - return; - } - - // Leaf prose block (paragraph / heading): emit its own slice and - // don't recurse further — paragraphs / headings never nest more - // prose blocks. - let text = extract_prose_text(node, source); - if !text.trim().is_empty() { - blocks.push(ProseBlock { - kind, - start_line, - end_line, - text, - _raw: source, - }); - } - return; - } - - // Recurse into everything else (sections, lists, list items, documents). - for child in node.children() { - walk(&child, source, blocks); - } -} - -fn has_nested_prose_block(node: &Node<'_>) -> bool { - for child in node.children() { - let kind = child.kind(); - if kind.is_heading() - || matches!( - kind, - NodeKind::Paragraph | NodeKind::BlockQuote | NodeKind::Callout - ) - { - return true; - } - if has_nested_prose_block(&child) { - return true; - } - } - false -} - -/// Produces the clean prose text for a prose-block node. -/// -/// Strategy: take the block's full byte slice from the source, then excise -/// every descendant sub-range that belongs to a skip class (inline code, -/// URLs, HTML inline, MDX inline, math inline, autolinks, front-matter, -/// pipe-table delimiters, heading markers). -/// -/// Excised ranges are substituted with a single replacement character so -/// adjacent tokens never fuse: -/// - `InlineCode` spans leave behind [`INLINE_CODE_SENTINEL`] so -/// downstream wording metrics can detect that a sentence originally -/// carried an inline-code token (used to suppress weasel / hedge -/// noise around backtick-wrapped identifiers — §37.5 item 3). -/// - All other skip kinds collapse to a single space. -/// -/// This byte-slice approach preserves the original whitespace between -/// tokens, which is critical for sentence- and word-segmentation. -pub(crate) fn extract_prose_text(node: &Node<'_>, source: &[u8]) -> String { - let block_start = node.start_byte(); - let block_end = node.end_byte(); - if block_end <= block_start || block_end > source.len() { - return String::new(); - } - - // Collect skip ranges relative to the source buffer. Each entry - // carries whether the skip was an `InlineCode` (so we can emit a - // sentinel) or another skip kind (emit a space). - let mut skip_ranges: Vec<(usize, usize, SkipKind)> = Vec::new(); - collect_skip_ranges(node, &mut skip_ranges); - - // Sort + merge overlapping skip ranges so we can linearly excise them. - // When two overlapping ranges disagree on kind, `InlineCode` wins so - // the sentinel is still emitted. - skip_ranges.sort_by_key(|r| r.0); - let mut merged: Vec<(usize, usize, SkipKind)> = Vec::with_capacity(skip_ranges.len()); - for (s, e, k) in skip_ranges { - if let Some(last) = merged.last_mut() - && s <= last.1 - { - last.1 = last.1.max(e); - if k == SkipKind::InlineCode { - last.2 = SkipKind::InlineCode; - } - } else { - merged.push((s, e, k)); - } - } - - let mut out = String::new(); - let mut cursor = block_start; - for (s, e, k) in merged { - let s = s.max(block_start).min(block_end); - let e = e.max(block_start).min(block_end); - if cursor < s - && let Ok(slice) = std::str::from_utf8(&source[cursor..s]) - { - out.push_str(slice); - } - match k { - SkipKind::InlineCode => out.push(INLINE_CODE_SENTINEL), - SkipKind::Other => out.push(' '), - } - cursor = e.max(cursor); - } - if cursor < block_end - && let Ok(slice) = std::str::from_utf8(&source[cursor..block_end]) - { - out.push_str(slice); - } - - normalize_whitespace(&out) -} - -/// Internal tag on a skip range so the extractor knows whether to emit a -/// sentinel or just a space. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum SkipKind { - /// `InlineCode` span — emit [`INLINE_CODE_SENTINEL`] so wording metrics - /// can still detect the original inline-code context. - InlineCode, - /// Every other skip kind (math, HTML, URLs, markers…) collapses to a - /// single space. - Other, -} - -/// Walks the subtree at `node` and appends (start_byte, end_byte, kind) -/// entries for every descendant whose kind should be stripped from prose. -fn collect_skip_ranges(node: &Node<'_>, out: &mut Vec<(usize, usize, SkipKind)>) { - let kind = node.kind(); - if is_skip_kind(&kind) { - let sk = match kind { - NodeKind::InlineCode | NodeKind::InlineCodeContent => SkipKind::InlineCode, - _ => SkipKind::Other, - }; - out.push((node.start_byte(), node.end_byte(), sk)); - return; - } - for child in node.children() { - collect_skip_ranges(&child, out); - } -} - -fn is_skip_kind(kind: &NodeKind) -> bool { - matches!( - kind, - NodeKind::InlineCode - | NodeKind::CodeFenceContent - | NodeKind::InlineCodeContent - | NodeKind::MathInline - | NodeKind::MathInlineContent - | NodeKind::MathBlock - | NodeKind::MathBlockContent - | NodeKind::HtmlInline - | NodeKind::HtmlBlock - | NodeKind::HtmlOpenTag - | NodeKind::HtmlCloseTag - | NodeKind::HtmlComment - | NodeKind::HtmlCdata - | NodeKind::HtmlDeclaration - | NodeKind::HtmlProcessingInstruction - | NodeKind::Autolink - | NodeKind::Uri - | NodeKind::Email - | NodeKind::LinkDestination - | NodeKind::LinkTitle - | NodeKind::MinusMetadata - | NodeKind::PlusMetadata - | NodeKind::PipeTableDelimiterRow - | NodeKind::PipeTableDelimiterCell - | NodeKind::HeadingMarker { .. } - | NodeKind::BlockQuoteMarker - | NodeKind::CalloutMarkerOpen - | NodeKind::CalloutMarkerClose - | NodeKind::CalloutType - | NodeKind::ListMarker - | NodeKind::TaskListMarkerChecked - | NodeKind::TaskListMarkerUnchecked - ) -} - -/// Collapses runs of whitespace and line breaks to a single space. -fn normalize_whitespace(s: &str) -> String { - let mut out = String::with_capacity(s.len()); - let mut prev_ws = false; - for c in s.chars() { - if c.is_whitespace() { - if !prev_ws { - out.push(' '); - } - prev_ws = true; - } else { - out.push(c); - prev_ws = false; - } - } - out.trim().to_string() -} - -/// Applies the Unicode-script block-ratio heuristic to one prose block. -pub(crate) fn classify_block(block: &ProseBlock<'_>) -> DetectedBlock { - let language = classify_text(&block.text); - DetectedBlock { - kind: block.kind, - start_line: block.start_line, - end_line: block.end_line, - text: block.text.clone(), - language, - } -} - -/// Classifies a text span using the Tier-0 rule from §30.1. -pub fn classify_text(text: &str) -> Language { - let mut kana = 0usize; - let mut han = 0usize; - let mut ascii_letter = 0usize; - let mut fullwidth_letter = 0usize; - let mut total = 0usize; - let mut visible_chars = 0usize; - - for c in text.chars() { - if c.is_whitespace() || c == INLINE_CODE_SENTINEL { - // Skip inline-code sentinels so substituting `InlineCode` - // spans with U+FFFC doesn't skew the script ratios. - continue; - } - visible_chars += 1; - // Filter out punctuation and digits from the denominator. Digits are - // technical tokens that don't signal language; punctuation is shared. - // Fullwidth digits (`0`–`9`, U+FF10–U+FF19) must also be excluded - // or they stay in `total` but never count as kana/han/latin, pushing - // the ratios down and misclassifying Japanese headings with - // fullwidth numerals as `other` (Codex P2 on PR #85). - if c.is_ascii_punctuation() - || is_cjk_punctuation(c) - || c.is_ascii_digit() - || ('\u{FF10}'..='\u{FF19}').contains(&c) - { - continue; - } - total += 1; - - // Classify. - if is_hiragana(c) || is_katakana(c) { - kana += 1; - } else if is_han(c) { - han += 1; - } else if c.is_ascii_alphabetic() { - ascii_letter += 1; - } else if is_fullwidth_latin(c) { - fullwidth_letter += 1; - } - } - - if total == 0 { - // Block contained only punctuation / digits / whitespace. Very short. - if visible_chars == 0 { - return Language::None; - } - return Language::Other; - } - - let cjk = kana + han; - let latin = ascii_letter + fullwidth_letter; - let t = total as f64; - - let kana_ratio = kana as f64 / t; - let cjk_ratio = cjk as f64 / t; - let latin_ratio = latin as f64 / t; - - if kana_ratio >= 0.15 { - Language::Ja - } else if cjk_ratio >= 0.40 && kana == 0 { - // Likely Chinese (no kana); treat as Other for our metric pipelines. - Language::Other - } else if latin_ratio >= 0.80 { - Language::En - } else { - Language::Other - } -} - -fn is_hiragana(c: char) -> bool { - let u = c as u32; - (0x3040..=0x309F).contains(&u) || (0x1B130..=0x1B16F).contains(&u) -} - -fn is_katakana(c: char) -> bool { - let u = c as u32; - (0x30A0..=0x30FF).contains(&u) - || (0x31F0..=0x31FF).contains(&u) - || (0xFF65..=0xFF9F).contains(&u) -} - -fn is_han(c: char) -> bool { - // Use unicode-script for Han detection: covers CJK Unified, Ext A-G, - // and compatibility blocks. Cheaper than enumerating explicitly. - matches!(c.script(), Script::Han) -} - -fn is_fullwidth_latin(c: char) -> bool { - let u = c as u32; - (0xFF21..=0xFF3A).contains(&u) || (0xFF41..=0xFF5A).contains(&u) -} - -fn is_cjk_punctuation(c: char) -> bool { - let u = c as u32; - (0x3000..=0x303F).contains(&u) - || (0xFF00..=0xFF0F).contains(&u) - || (0xFF1A..=0xFF20).contains(&u) - || (0xFF3B..=0xFF40).contains(&u) - || (0xFF5B..=0xFF65).contains(&u) -} - -/// Second pass: short blocks that came back `Other` inherit from the -/// surrounding context. Deterministic because the block list is in document -/// order. -/// -/// Rules: -/// 1. Non-heading short blocks (< 15 visible chars) that classified as Other -/// inherit the preceding heading's language. -/// 2. Headings that classified as Other inherit the nearest non-`Other` -/// neighboring block's language (earlier preferred; else later). -pub(crate) fn propagate_heading_inheritance(blocks: Vec) -> Vec { - let mut out = blocks; - - // Pass 1: non-heading short blocks inherit from preceding heading. - inherit_short_blocks_from_headings(&mut out); - - // Pass 2: headings that came back `Other` inherit from nearest neighbor. - // Kanji-only headings ("## 目的") are a common trigger. - let langs: Vec = out.iter().map(|b| b.language).collect(); - for (i, block) in out.iter_mut().enumerate() { - if !is_heading_kind(&block.kind) { - continue; - } - if !matches!(block.language, Language::Other) { - continue; - } - // Search forward and backward for the nearest non-Other, non-None - // language. Prefer the next-neighboring paragraph because it - // represents the section's body. - let mut inh: Option = langs - .iter() - .skip(i + 1) - .copied() - .find(|l| matches!(l, Language::En | Language::Ja)); - if inh.is_none() { - inh = langs - .iter() - .take(i) - .rev() - .copied() - .find(|l| matches!(l, Language::En | Language::Ja)); - } - if let Some(l) = inh { - block.language = l; - } - } - - // Pass 3: re-apply short-block inheritance now that pass 2 resolved - // kanji-only headings like `## 目的`. Without this pass, short body - // blocks right after such a heading stayed `Other` because pass 1 had - // no `last_heading_lang` yet (Codex P2 on PR #85). - inherit_short_blocks_from_headings(&mut out); - - out -} - -fn inherit_short_blocks_from_headings(blocks: &mut [DetectedBlock]) { - let mut last_heading_lang: Option = None; - for b in blocks.iter_mut() { - if is_heading_kind(&b.kind) { - if !matches!(b.language, Language::None | Language::Other) { - last_heading_lang = Some(b.language); - } - continue; - } - let visible_len = b.text.chars().filter(|c| !c.is_whitespace()).count(); - if visible_len < 15 - && matches!(b.language, Language::Other) - && let Some(inh) = last_heading_lang - { - b.language = inh; - } - } -} - -fn is_heading_kind(kind: &NodeKind) -> bool { - kind.is_heading() -} - -/// Picks the document-level dominant language by simple majority over -/// detected blocks. Ties and mixed-bilingual documents return `Mixed`. -pub(crate) fn dominant_language(blocks: &[DetectedBlock]) -> Language { - let mut en_blocks = 0usize; - let mut ja_blocks = 0usize; - let mut other_blocks = 0usize; - - for b in blocks { - match b.language { - Language::En => en_blocks += 1, - Language::Ja => ja_blocks += 1, - Language::Other => other_blocks += 1, - _ => {} - } - } - - if en_blocks == 0 && ja_blocks == 0 { - if other_blocks == 0 { - // No prose at all. - return Language::Other; - } - return Language::Other; - } - if en_blocks > 0 && ja_blocks > 0 { - return Language::Mixed; - } - if en_blocks > 0 { - Language::En - } else { - Language::Ja - } -} - -/// Concatenates the text of all blocks tagged with `language` into a single -/// string separated by `\n\n` so downstream sentence segmentation treats -/// block boundaries as hard terminators (§31.12). -pub(crate) fn concat_lang_text(blocks: &[DetectedBlock], language: Language) -> String { - let mut out = String::new(); - for b in blocks { - if b.language == language { - if !out.is_empty() { - out.push_str("\n\n"); - } - out.push_str(&b.text); - } - } - out -} - -// `Serialize` for Language is only used in BlockLangReport indirectly -// via `as_str()`. Declared here for completeness if the enum ever grows. -impl Serialize for Language { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(self.as_str()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn classify_en() { - let t = "This paragraph contains ten words of ordinary English prose."; - assert_eq!(classify_text(t), Language::En); - } - - #[test] - fn classify_ja() { - let t = "これは日本語のテキストです。読みやすい文章を書きましょう。"; - assert_eq!(classify_text(t), Language::Ja); - } - - #[test] - fn classify_chinese_as_other() { - // No hiragana/katakana, all Han: treated as Other. - let t = "这是一段中文文本没有任何假名字符存在"; - assert_eq!(classify_text(t), Language::Other); - } - - #[test] - fn classify_empty() { - assert_eq!(classify_text(""), Language::None); - } - - #[test] - fn classify_bilingual_picks_ja_when_kana_present() { - // Mixed, but kana ≥ 15 % → ja. - let t = "設定 config file を open して編集します"; - assert_eq!(classify_text(t), Language::Ja); - } - - fn parse_blocks(src: &str) -> Vec> { - // Leak the buffer so we can return borrowed `ProseBlock` values with - // a 'static lifetime for this test-only helper. - let bytes: &'static [u8] = Box::leak(src.as_bytes().to_vec().into_boxed_slice()); - let source = std::str::from_utf8(bytes).unwrap(); - let tree = crate::syntax_tree::parse(source); - let root = tree.root(); - // SAFETY: the source buffer `bytes` outlives the returned Vec; tree - // goes out of scope at function end but the collected blocks own - // their extracted text and only borrow `_raw` which points at the - // leaked buffer. - let blocks: Vec> = - collect_prose_blocks(&root, bytes).into_iter().collect(); - std::mem::forget(tree); - blocks - } - - #[test] - fn blockquote_with_paragraph_emits_one_block() { - // Codex P1 regression: a blockquote containing a single paragraph - // used to emit TWO prose blocks — once for the container's full - // slice and again for the nested paragraph — which caused every - // word and sentence inside quoted material to be counted twice. - // - // Fix: containers (blockquote / callout) recurse into children and - // do NOT emit their own slice. Only the nested paragraph surfaces - // as a prose block. - let src = "> A quoted paragraph with exactly nine common English words.\n"; - let blocks = parse_blocks(src); - let paragraph_blocks: Vec<_> = blocks - .iter() - .filter(|b| matches!(b.kind, NodeKind::Paragraph)) - .collect(); - let container_blocks: Vec<_> = blocks - .iter() - .filter(|b| matches!(b.kind, NodeKind::BlockQuote | NodeKind::Callout)) - .collect(); - assert_eq!( - paragraph_blocks.len(), - 1, - "expected exactly one paragraph block inside the blockquote, got {}: {:?}", - paragraph_blocks.len(), - blocks - .iter() - .map(|b| (b.kind, b.text.clone())) - .collect::>() - ); - assert!( - container_blocks.is_empty(), - "container blocks (blockquote/callout) must not emit their own slice, got: {:?}", - container_blocks - .iter() - .map(|b| (b.kind, b.text.clone())) - .collect::>() - ); - } -} diff --git a/crates/mehen-markdown/src/prose/mod.rs b/crates/mehen-markdown/src/prose/mod.rs deleted file mode 100644 index 0c20620d..00000000 --- a/crates/mehen-markdown/src/prose/mod.rs +++ /dev/null @@ -1,313 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Language-aware prose metric layer (§§29–38). -//! -//! This module adds a *separate* top-level `prose` section to the Markdown -//! output schema. It never modifies the structural scores computed by Phase A -//! (LOC, words, sections, ECU) or later phases (MCC, DMI, FillerLazyRisk). -//! -//! Entry point: [`analyze_prose`] takes the parsed tree + the source buffer -//! and produces a [`ProseReport`] that the analyzer attaches to -//! [`crate::types::MarkdownMetrics`]. -//! -//! Tier 0 scope (§38): -//! - Unicode-script block-ratio language detection (no trigram model). -//! - UAX #29 word + sentence segmentation (English), with abbreviation list. -//! - Vowel-group English syllables (no CMU, no hyphenation). -//! - Classical English readability: FRES, FKGL, Fog, SMOG, ARI, CLI, -//! Dale-Chall (NGSL-backed), FORCAST, LIX, RIX. -//! - English wording: passive, hedges, weasels, wordy phrases, adverbs, -//! nominalizations, expletives, lexical illusions, clichés, nonwords, -//! long sentences, WQS. -//! - Inclusive-language flags. -//! - Japanese script composition, Tateishi simplified RS, Jōyō grade, -//! jukugo density, politeness, JTF mechanical rules, textlint subset. -//! -//! Tier 1/2 features (CMU syllables, Lindera, Vibrato, JLPT, Lingua) are -//! feature-gated and OFF by default. See `Cargo.toml`. - -pub mod english; -pub mod japanese; -pub mod lang_detect; - -use serde::Serialize; - -use crate::syntax_tree::Node; - -use self::english::EnglishReport; -use self::japanese::JapaneseReport; -use self::lang_detect::{DetectedBlock, Language}; - -/// Whole-document prose output (§29.2). -#[derive(Debug, Clone, Serialize, Default)] -pub struct ProseReport { - pub language_detection: LanguageDetection, - pub english: Option, - pub japanese: Option, - pub meta: ProseMeta, -} - -#[derive(Debug, Clone, Serialize, Default)] -pub struct LanguageDetection { - pub dominant_language: String, - pub blocks: Vec, -} - -#[derive(Debug, Clone, Serialize)] -pub struct BlockLangReport { - pub start_line: u64, - pub end_line: u64, - pub language: String, -} - -#[derive(Debug, Clone, Serialize, Default)] -pub struct ProseMeta { - pub short_doc_warning: bool, - pub words_counted: u64, - pub sentences_counted: u64, - /// The kinds of blocks stripped from prose input. - pub blocks_stripped: Vec, -} - -/// Analyzes prose layers over the Markdown parse tree. `source` is the raw -/// file bytes so we can slice text without re-walking the tree repeatedly. -pub(crate) fn analyze_prose(root: &Node<'_>, source: &[u8]) -> ProseReport { - // 1. Enumerate prose-eligible blocks with per-block text spans. - let blocks = lang_detect::collect_prose_blocks(root, source); - - // 2. Per-block language tagging. - let detected: Vec = blocks - .iter() - .map(|b| lang_detect::classify_block(b)) - .collect(); - - // Inherit parent-heading language for short blocks that classify as - // Other. This is a second pass over `detected` because a block's - // inheritance depends on the preceding heading context. - let detected = lang_detect::propagate_heading_inheritance(detected); - - // 3. Document-level dominant language: majority among {en, ja}, falling - // back to `mixed` when both appear, `other` otherwise. - let dominant = lang_detect::dominant_language(&detected); - - // 4. Run per-language pipelines on the concatenated text of their blocks. - let en_text = lang_detect::concat_lang_text(&detected, Language::En); - let ja_text = lang_detect::concat_lang_text(&detected, Language::Ja); - - let english = if !en_text.trim().is_empty() { - Some(english::analyze(&en_text)) - } else { - None - }; - let japanese = if !ja_text.trim().is_empty() { - Some(japanese::analyze(&ja_text)) - } else { - None - }; - - // 5. Meta: word / sentence totals, short-doc warning, blocks-stripped. - let (words_counted, sentences_counted) = match (english.as_ref(), japanese.as_ref()) { - (Some(en), Some(ja)) => ( - en.lexical.words_total + ja.lexical.char_count, - en.lexical.sentence_count + ja.lexical.sentence_count, - ), - (Some(en), None) => (en.lexical.words_total, en.lexical.sentence_count), - (None, Some(ja)) => (ja.lexical.char_count, ja.lexical.sentence_count), - (None, None) => (0, 0), - }; - - // Either language crossing the short-doc threshold propagates up to the - // document-level warning. This matters for bilingual docs where the - // English half can be very short (e.g. a README with a long Japanese - // body and a tiny English summary): we must not hide the warning just - // because the dominant language has enough prose. - let short_doc_warning = match (english.as_ref(), japanese.as_ref()) { - (Some(en), Some(ja)) => en.short_doc_warning || ja.short_doc_warning, - (Some(en), None) => en.short_doc_warning, - (None, Some(ja)) => ja.short_doc_warning, - (None, None) => true, - }; - - let blocks_stripped = blocks_stripped_kinds(root); - - let blocks_out: Vec = detected - .iter() - .filter_map(|b| { - if matches!(b.language, Language::None) { - None - } else { - Some(BlockLangReport { - start_line: b.start_line, - end_line: b.end_line, - language: b.language.as_str().to_string(), - }) - } - }) - .collect(); - - ProseReport { - language_detection: LanguageDetection { - dominant_language: dominant.as_str().to_string(), - blocks: blocks_out, - }, - english, - japanese, - meta: ProseMeta { - short_doc_warning, - words_counted, - sentences_counted, - blocks_stripped, - }, - } -} - -/// Enumerates the kinds of blocks that were excluded from prose analysis. -/// Deterministic: always emitted in a fixed order so snapshots are stable. -fn blocks_stripped_kinds(root: &Node<'_>) -> Vec { - use crate::kind::NodeKind; - - let mut has_code = false; - let mut has_frontmatter = false; - let mut has_html = false; - let mut has_math = false; - let mut has_table = false; - - fn walk( - node: &Node<'_>, - code: &mut bool, - fm: &mut bool, - html: &mut bool, - math: &mut bool, - table: &mut bool, - ) { - let kind = node.kind(); - match kind { - NodeKind::FencedCodeBlock | NodeKind::IndentedCodeBlock | NodeKind::InlineCode => { - *code = true; - } - NodeKind::MinusMetadata | NodeKind::PlusMetadata => { - *fm = true; - } - NodeKind::HtmlBlock | NodeKind::HtmlInline => { - *html = true; - } - NodeKind::MathBlock | NodeKind::MathInline => { - *math = true; - } - NodeKind::PipeTable => { - *table = true; - } - _ => {} - } - for child in node.children() { - walk(&child, code, fm, html, math, table); - } - } - - walk( - root, - &mut has_code, - &mut has_frontmatter, - &mut has_html, - &mut has_math, - &mut has_table, - ); - - // Note: pulldown-cmark never emits MDX nodes, so no "mdx" entry is - // produced (the tree-sitter grammar had MDX kinds; this backend does not). - let mut out = Vec::new(); - if has_code { - out.push("code".to_string()); - } - if has_frontmatter { - out.push("frontmatter".to_string()); - } - if has_html { - out.push("html".to_string()); - } - if has_math { - out.push("math".to_string()); - } - if has_table { - out.push("table".to_string()); - } - out -} - -#[cfg(test)] -mod tests { - use super::*; - - fn analyze_src(src: &str) -> ProseReport { - let tree = crate::syntax_tree::parse(src); - let root = tree.root(); - analyze_prose(&root, src.as_bytes()) - } - - #[test] - fn bilingual_short_english_triggers_warning() { - // Codex P2 regression: when both English and Japanese prose are - // present, `meta.short_doc_warning` was taken from the English branch - // only. If English was long enough but Japanese was short (or vice - // versa), the warning never propagated. The fix is a logical OR so - // EITHER language hitting the short-doc threshold surfaces the flag. - // - // Fixture: ~3 English words (way below 100 / 5 sentences) + a long - // Japanese body far beyond the 300-char / 5-sentence threshold. - let src = "\ -# Bilingual short-English doc - -Hi there. - -## 本文 - -\ -これは日本語の長い本文です。最初の段落では、言語検出と短文警告の挙動を確認します。\ -検出器はひらがなとカタカナの比率に基づいてブロック単位で言語を判定し、それぞれの言語に対して別々のパイプラインを実行します。\ -短文警告はそれぞれの言語パイプラインが独立に判断するため、片方が短ければ文書全体で警告を出すべきです。 - -続く段落では、文書全体の評価について述べます。\ -英語側の段落が短くても、日本語側に十分な量のテキストがあれば、メトリックは日本語に対して計算されます。\ -ただし、短文警告は英語側の判断も反映しなければなりません。なぜなら、バイリンガル文書で片方の言語が不足している場合、\ -読者はその情報を必要とするからです。従来のコードでは英語側の判断だけを採用していたため、日本語だけが短いケースでは警告が出ませんでした。 - -最後の段落として、修正後の挙動をまとめます。今後はどちらかの言語パイプラインが短文判定を返した時点で、\ -文書全体の短文警告を真にします。この変更によって、バイリンガル文書の信頼性が向上し、\ -片方の言語だけが不足しているケースを見逃すことがなくなります。テストはこの挙動を保証します。 -"; - let report = analyze_src(src); - - // Sanity: both pipelines fired. - assert!( - report.english.is_some(), - "expected English pipeline to fire, got {:?}", - report.english - ); - assert!( - report.japanese.is_some(), - "expected Japanese pipeline to fire, got {:?}", - report.japanese - ); - - // English must have flagged short; Japanese must NOT have flagged. - let en = report.english.as_ref().unwrap(); - let ja = report.japanese.as_ref().unwrap(); - assert!( - en.short_doc_warning, - "sanity: English half is short; en.short_doc_warning must be true" - ); - assert!( - !ja.short_doc_warning, - "sanity: Japanese half is long; ja.short_doc_warning must be false, got {}", - ja.short_doc_warning - ); - - // Regression: top-level meta must carry the English short flag - // through even when Japanese is not short. - assert!( - report.meta.short_doc_warning, - "bilingual doc with short English half must set meta.short_doc_warning=true" - ); - } -} diff --git a/crates/mehen-markdown/src/rci.rs b/crates/mehen-markdown/src/rci.rs deleted file mode 100644 index bd5ecfbe..00000000 --- a/crates/mehen-markdown/src/rci.rs +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Review Criticality Index (RCI) per §18. -//! -//! RCI answers: "Should I review this document carefully?" A small document -//! can still be high-priority if it is dense with technical anchors. -//! -//! ```text -//! DensityScore = clamp01( -//! 0.25 * sat(MCC / max(1, W / 500); 4, 18) -//! + 0.20 * sat(MDH_volume_total / max(1, W); 20, 120) -//! + 0.20 * RepositoryGroundingScore -//! + 0.15 * EvidenceCoverageScore -//! + 0.10 * sat(LinkReviewBurden / max(1, W / 500); 2, 10) -//! + 0.10 * sat(embedded_code_complexity / max(1, W / 500); 2, 12) -//! ) -//! ``` -//! -//! ```text -//! RCI = clamp01( -//! 0.65 * DensityScore -//! + 0.20 * sat(abs(metric_delta_percent); 10, 60) -//! + 0.15 * sat(changed_links_or_artifacts; 2, 20) -//! ) * 100 -//! ``` -//! -//! `metric_delta_percent` and `changed_links_or_artifacts` are activated by -//! `mehen diff` (Phase F). In Phase D the baseline is absent so both -//! default to `0` — DensityScore drives RCI directly. - -use crate::mathops::{clamp01, sat}; - -/// Inputs RCI needs from Phase A/B/C/D outputs. All densities are already -/// pre-aggregated; the formula is a weighted sum. -#[derive(Debug, Clone, Copy)] -pub(crate) struct RciInputs { - /// §8 MCC final value. - pub(crate) mcc: f64, - /// §4 narrative word count `W`. - pub(crate) words: u64, - /// §9 Markdown Halstead `total_volume` (includes embedded §9.4). - pub(crate) mdh_volume_total: f64, - /// §15 RepositoryGroundingScore in `[0, 1]`. - pub(crate) repository_grounding_score: f64, - /// §16 EvidenceCoverageScore in `[0, 1]`. - pub(crate) evidence_coverage_score: f64, - /// §11.4 Link Review Burden (unbounded, typically 0-100). - pub(crate) link_review_burden: f64, - /// §9.4 embedded_volume. A proxy for embedded_code_complexity. - pub(crate) embedded_code_complexity: f64, - /// Absolute % change vs baseline. Always `0.0` in Phase D. - pub(crate) metric_delta_percent: f64, - /// Baseline diff: count of changed links + artifacts. Always `0` in Phase D. - pub(crate) changed_links_or_artifacts: u64, -} - -/// Output on the `[0, 100]` scale. -#[derive(Debug, Default, Clone, Copy)] -pub(crate) struct RciResult { - pub(crate) review_criticality_index: f64, - /// DensityScore before the diff-aware aggregation. Retained for - /// Phase F (`mehen diff`) and auditability; not read by the analyzer. - #[allow(dead_code)] - pub(crate) density_score: f64, -} - -/// Computes RCI per §18.1. -pub(crate) fn compute_rci(inputs: RciInputs) -> RciResult { - let w = inputs.words as f64; - let denom_500 = (w / 500.0).max(1.0); - let denom_w = w.max(1.0); - - let density = clamp01( - 0.25 * sat(inputs.mcc / denom_500, 4.0, 18.0) - + 0.20 * sat(inputs.mdh_volume_total / denom_w, 20.0, 120.0) - + 0.20 * inputs.repository_grounding_score.clamp(0.0, 1.0) - + 0.15 * inputs.evidence_coverage_score.clamp(0.0, 1.0) - + 0.10 * sat(inputs.link_review_burden / denom_500, 2.0, 10.0) - + 0.10 * sat(inputs.embedded_code_complexity / denom_500, 2.0, 12.0), - ); - - let raw = 0.65 * density - + 0.20 * sat(inputs.metric_delta_percent.abs(), 10.0, 60.0) - + 0.15 * sat(inputs.changed_links_or_artifacts as f64, 2.0, 20.0); - let review_criticality_index = clamp01(raw) * 100.0; - RciResult { - review_criticality_index, - density_score: density, - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn zero_inputs_produce_zero_rci() { - let r = compute_rci(RciInputs { - mcc: 0.0, - words: 0, - mdh_volume_total: 0.0, - repository_grounding_score: 0.0, - evidence_coverage_score: 0.0, - link_review_burden: 0.0, - embedded_code_complexity: 0.0, - metric_delta_percent: 0.0, - changed_links_or_artifacts: 0, - }); - assert_eq!(r.review_criticality_index, 0.0); - } - - #[test] - fn dense_small_doc_rci_is_high() { - // A small but technically dense doc should tip DensityScore above - // 0.7. Without a baseline (metric_delta / changed_artifacts both 0) - // RCI caps at 0.65 × DensityScore × 100, so we expect > 45. - let r = compute_rci(RciInputs { - mcc: 40.0, - words: 650, - mdh_volume_total: 200.0, - repository_grounding_score: 0.9, - evidence_coverage_score: 0.85, - link_review_burden: 15.0, - embedded_code_complexity: 40.0, - metric_delta_percent: 0.0, - changed_links_or_artifacts: 0, - }); - assert!( - r.review_criticality_index > 45.0, - "got {}", - r.review_criticality_index - ); - } - - #[test] - fn rci_is_bounded() { - let r = compute_rci(RciInputs { - mcc: 1e9, - words: 1, - mdh_volume_total: 1e9, - repository_grounding_score: 1.0, - evidence_coverage_score: 1.0, - link_review_burden: 1e9, - embedded_code_complexity: 1e9, - metric_delta_percent: 1e6, - changed_links_or_artifacts: 1_000_000, - }); - assert!(r.review_criticality_index <= 100.0 + 1e-9); - } -} diff --git a/crates/mehen-markdown/src/section_balance.rs b/crates/mehen-markdown/src/section_balance.rs deleted file mode 100644 index 8b92a8db..00000000 --- a/crates/mehen-markdown/src/section_balance.rs +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Section Balance Score per §20. -//! -//! ```text -//! section_word_counts = [W_s for each section s] -//! median_section_words = median(section_word_counts) -//! p95_section_words = percentile(section_word_counts, 95) -//! large_section_rate = count(W_s > 1200) / max(1, S) -//! tiny_section_rate = count(W_s < 40) / max(1, S) -//! heading_skip_rate = heading_skips / max(1, H) -//! ``` -//! -//! ```text -//! SectionBalanceScore = clamp01( -//! 1 -//! - 0.30 * sat(p95_section_words; 900, 2000) -//! - 0.25 * sat(large_section_rate; 0.05, 0.40) -//! - 0.15 * sat(tiny_section_rate; 0.20, 0.70) -//! - 0.20 * sat(heading_skip_rate; 0.02, 0.20) -//! - 0.10 * sat(abs(max_heading_depth - expected_depth); 2, 5) -//! ) -//! ``` -//! -//! `expected_depth` is profile-specific. Phase D uses a single default of -//! `3` (typical for README / technical reference docs) until profile-aware -//! thresholds ship in a later phase. Document-type profiles live in §22. - -use crate::mathops::{clamp01, sat}; -use crate::types::Section; - -/// Default `expected_depth` for §20 until profile-aware thresholds land. -const EXPECTED_DEPTH_DEFAULT: f64 = 3.0; - -/// Computed §20 output plus the intermediate signals so §17.4 (lazy -/// sectioning) and the DMI (S_norm = 1 - SectionBalanceScore) can reuse -/// them. -/// -/// Fields marked `#[allow(dead_code)]` are kept for Phase F's `mehen diff` -/// sticky comment even though the analyzer does not read them directly. -#[derive(Debug, Default, Clone)] -pub(crate) struct SectionBalance { - pub(crate) section_balance_score: f64, - #[allow(dead_code)] - pub(crate) p95_section_words: f64, - #[allow(dead_code)] - pub(crate) median_section_words: f64, - #[allow(dead_code)] - pub(crate) large_section_rate: f64, - #[allow(dead_code)] - pub(crate) tiny_section_rate: f64, - #[allow(dead_code)] - pub(crate) heading_skip_rate: f64, - #[allow(dead_code)] - pub(crate) max_heading_depth: u8, - pub(crate) long_section_rate: f64, - #[allow(dead_code)] - pub(crate) heading_count: u64, - pub(crate) shallow_large_doc: bool, -} - -/// Computes §20's Section Balance Score from the Phase-A section list. -pub(crate) fn analyze_section_balance(sections: &[Section], words: u64) -> SectionBalance { - // A document with no sections is structurally balanced by definition - // (there is nothing to imbalance). Return a perfect score instead of - // computing abs(0 - expected_depth) which would spuriously penalize an - // empty document. - if sections.is_empty() { - return SectionBalance { - section_balance_score: 1.0, - ..SectionBalance::default() - }; - } - - let s = sections.len() as f64; - let s_max = s.max(1.0); - - let mut word_counts: Vec = sections.iter().map(|sec| sec.word_count).collect(); - let large = word_counts.iter().filter(|w| **w > 1200).count() as f64; - let tiny = word_counts.iter().filter(|w| **w < 40).count() as f64; - - let large_section_rate = large / s_max; - let tiny_section_rate = tiny / s_max; - let long_section_rate = large_section_rate; - - let p95 = percentile_u64(&mut word_counts, 0.95); - let median = percentile_u64(&mut word_counts, 0.50); - - // §8.1-style heading skip count: Σ max(0, child_level - parent_level - 1) - // over parent / child heading pairs; plus the count of top-level headings - // that start at level > 1 (document opens with `###` etc. is a skip). - let heading_skip_rate = heading_skip_rate(sections); - let max_depth = max_heading_depth(sections); - - let shallow_large_doc = words > 2500 && max_depth <= 2; - - let raw = 1.0 - - 0.30 * sat(p95, 900.0, 2000.0) - - 0.25 * sat(large_section_rate, 0.05, 0.40) - - 0.15 * sat(tiny_section_rate, 0.20, 0.70) - - 0.20 * sat(heading_skip_rate, 0.02, 0.20) - - 0.10 * sat((max_depth as f64 - EXPECTED_DEPTH_DEFAULT).abs(), 2.0, 5.0); - - SectionBalance { - section_balance_score: clamp01(raw), - p95_section_words: p95, - median_section_words: median, - large_section_rate, - tiny_section_rate, - heading_skip_rate, - max_heading_depth: max_depth, - long_section_rate, - heading_count: sections.len() as u64, - shallow_large_doc, - } -} - -/// Percentile of `u64` word counts using type-7 linear interpolation. -fn percentile_u64(values: &mut [u64], q: f64) -> f64 { - if values.is_empty() { - return 0.0; - } - values.sort(); - let n = values.len(); - if n == 1 { - return values[0] as f64; - } - let pos = q * (n as f64 - 1.0); - let lo = pos.floor() as usize; - let hi = pos.ceil() as usize; - if lo == hi { - values[lo] as f64 - } else { - let frac = pos - lo as f64; - values[lo] as f64 * (1.0 - frac) + values[hi] as f64 * frac - } -} - -/// `heading_skip_rate` = (heading skips) / max(1, H). A heading skip is a -/// child heading that jumps more than one level below its parent (e.g. H1 → -/// H3). Top-level sections whose heading level is > 1 also count as a skip -/// because the document implicitly "jumps" past H1. -fn heading_skip_rate(sections: &[Section]) -> f64 { - let h = sections.len(); - if h == 0 { - return 0.0; - } - let mut skips = 0u64; - for s in sections { - let child_level = s.heading_level.unwrap_or(1); - let parent_level = match s.parent_section_id { - Some(p) => sections - .iter() - .find(|x| x.section_id == p) - .and_then(|x| x.heading_level) - .unwrap_or(0), - None => 0, // top-level: "parent" is level 0 conceptually - }; - let jump = (child_level as i32) - (parent_level as i32); - // A top-level H1 (parent_level=0, child_level=1, jump=1) is NOT a - // skip. A top-level H3 (parent_level=0, child_level=3, jump=3) IS. - // Nested H3 under H1 (parent_level=1, child_level=3, jump=2) IS. - let is_skip = if parent_level == 0 { - child_level > 1 && jump >= 2 - } else { - jump >= 2 - }; - if is_skip { - skips += 1; - } - } - skips as f64 / h as f64 -} - -fn max_heading_depth(sections: &[Section]) -> u8 { - sections - .iter() - .filter_map(|s| s.heading_level) - .max() - .unwrap_or(0) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn mk_section(id: usize, level: u8, parent: Option, words: u64) -> Section { - Section { - section_id: id, - heading_level: Some(level), - heading_text: None, - start_line: id as u64 + 1, - end_line: id as u64 + 2, - parent_section_id: parent, - child_section_ids: Vec::new(), - word_count: words, - block_count: 1, - } - } - - #[test] - fn empty_sections_produce_perfect_balance() { - let out = analyze_section_balance(&[], 0); - assert_eq!(out.section_balance_score, 1.0); - assert_eq!(out.heading_count, 0); - } - - #[test] - fn heading_skip_rate_counts_h1_to_h3_jump() { - let sections = vec![mk_section(0, 1, None, 50), mk_section(1, 3, Some(0), 50)]; - let out = analyze_section_balance(§ions, 100); - assert!(out.heading_skip_rate > 0.0); - } - - #[test] - fn large_sections_lower_the_score() { - let sections = vec![mk_section(0, 1, None, 3000)]; - let out = analyze_section_balance(§ions, 3000); - // p95 is 3000 → saturates to 1.0, losing 0.30. Large rate = 1.0 → -0.25. - assert!(out.section_balance_score < 0.6); - } - - #[test] - fn shallow_large_doc_flag_fires() { - let sections = vec![mk_section(0, 1, None, 3000)]; - let out = analyze_section_balance(§ions, 3000); - assert!(out.shallow_large_doc); - } -} diff --git a/crates/mehen-markdown/src/sections.rs b/crates/mehen-markdown/src/sections.rs deleted file mode 100644 index 7c595f3b..00000000 --- a/crates/mehen-markdown/src/sections.rs +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Derived section tree per §3.4. -//! -//! The Markdown syntax layer synthesizes a nested `section` AST: each heading -//! opens a `section` that contains all downstream blocks until the next -//! same-or-higher-level heading. Heading skips (e.g. H1 → H3) keep the -//! intervening depth collapsed — no virtual sections are synthesized. This -//! module flattens that tree into the -//! [`crate::types::Section`] list consumed by the exported schema. -//! -//! Parent/child relationships are preserved by walking in pre-order and -//! emitting the parent section before its children. This matches §3.4 -//! which requires a `parent_section_id` pointing to the enclosing heading's -//! section and a `child_section_ids` list of directly-nested subsections. - -use crate::kind::NodeKind; -use crate::syntax_tree::Node; -use crate::types::Section; -use crate::words::count_words; - -/// Collects sections (one per heading) in document order. -/// -/// §3.4 defines the derived section tree as *one section per heading*. A -/// document with no headings returns an empty list. Pre-heading content -/// is accounted for in `size.words` but has no section of its own. -/// -/// Internally we keep a synthetic "file" placeholder so the tree walk can -/// attribute pre-heading content and preserve parent/child ids during -/// construction; that placeholder is dropped and the remaining sections -/// are renumbered before returning to the caller. -pub(crate) fn collect_sections(root: &Node<'_>) -> Vec
{ - let mut sections: Vec
= Vec::new(); - - // Synthetic root used only during walk. Dropped before return. - sections.push(Section { - section_id: 0, - heading_level: None, - heading_text: None, - start_line: (root.start_row() as u64) + 1, - end_line: section_end_line(root), - parent_section_id: None, - child_section_ids: Vec::new(), - word_count: 0, - block_count: 0, - }); - - walk(root, 0, &mut sections); - - populate_word_and_block_counts(root, &mut sections); - - // Strip the synthetic root and renumber remaining sections so the - // exported `sections` array reflects only heading-rooted sections with - // contiguous ids starting at 0. - sections.remove(0); - renumber_sections(&mut sections); - - sections -} - -/// Renumbers `sections` so `section_id` is the array index and every -/// `parent_section_id` / `child_section_ids` entry refers to the renumbered -/// ids. Sections whose parent was the dropped synthetic root become -/// top-level (`parent_section_id = None`). -fn renumber_sections(sections: &mut [Section]) { - // Map old section_id -> new index. Since the synthetic root lived at - // id 0, every remaining section's old id is >= 1. The new order is - // the current vector order. - let old_to_new: std::collections::HashMap = sections - .iter() - .enumerate() - .map(|(new_idx, s)| (s.section_id, new_idx)) - .collect(); - - for (new_idx, section) in sections.iter_mut().enumerate() { - section.section_id = new_idx; - section.parent_section_id = match section.parent_section_id { - Some(0) | None => None, - Some(old_parent) => old_to_new.get(&old_parent).copied(), - }; - section.child_section_ids = section - .child_section_ids - .iter() - .filter_map(|old_id| old_to_new.get(old_id).copied()) - .collect(); - } -} - -fn walk(node: &Node<'_>, parent_id: usize, sections: &mut Vec
) { - for child in node.children() { - if is_section_node(child.kind()) { - if let Some(heading) = find_heading_in_section(&child) { - let (level, heading_text) = { - let (lvl, txt) = describe_heading(&heading); - (Some(lvl), txt) - }; - let section_id = sections.len(); - // Sections nest H1 → H2 → H3 by construction. Heading - // skips (H1 → H3) keep the H3 under whichever section wraps - // it — we do not fabricate virtual sections. - sections[parent_id].child_section_ids.push(section_id); - sections.push(Section { - section_id, - heading_level: level, - heading_text, - start_line: (child.start_row() as u64) + 1, - end_line: section_end_line(&child), - parent_section_id: Some(parent_id), - child_section_ids: Vec::new(), - word_count: 0, - block_count: 0, - }); - walk(&child, section_id, sections); - } else { - // A `Section` node without a heading is a structural - // wrapper (empty or pre-heading). Recurse into it but treat - // its content as belonging to the enclosing section. - walk(&child, parent_id, sections); - } - } else { - // Non-section nodes can still contain sections (e.g. when a - // block is between sections), so recurse. - walk(&child, parent_id, sections); - } - } -} - -fn is_section_node(kind: NodeKind) -> bool { - matches!(kind, NodeKind::Section { .. }) -} - -fn find_heading_in_section<'a>(section: &Node<'a>) -> Option> { - section.children().find(|child| child.kind().is_heading()) -} - -fn describe_heading(heading: &Node<'_>) -> (u8, Option) { - let level = heading.kind().heading_level().unwrap_or(1); - let text = heading_content_node(heading).map(|node| { - let start = node.start_byte(); - let end = node.end_byte(); - let _ = (start, end); - // Heading text extraction from source bytes is Phase-B territory - // (needed for information-scent / RCI). Phase A leaves it as `None` - // until the source-bytes-aware constructor lands. - String::new() - }); - // Drop the empty string — return `None` to preserve semantic meaning. - let text = text.filter(|s| !s.is_empty()); - (level, text) -} - -fn heading_content_node<'a>(heading: &Node<'a>) -> Option> { - heading - .children() - .find(|child| matches!(child.kind(), NodeKind::HeadingContent)) -} - -fn section_end_line(section: &Node<'_>) -> u64 { - let (end_row, end_col) = section.end_position(); - let end = if end_col == 0 && end_row > section.start_row() { - end_row - 1 - } else { - end_row - }; - (end as u64) + 1 -} - -fn populate_word_and_block_counts(root: &Node<'_>, sections: &mut [Section]) { - if sections.is_empty() { - return; - } - - // Block counts: count paragraph / list / table / code / html / math / - // callout / thematic-break / image-block blocks per section range. Since - // the grammar already nests blocks inside the correct section, walking - // each section's subtree yields the right count. - // - // Word counts: each section's subtree minus nested sub-section subtrees - // to avoid double-counting. This is achieved by computing the subtree - // word count, then subtracting the children's subtree counts. - - // Root section: every block and every word in the document. - // We compute the root's subtree first, then per-sub-section. - let mut subtree_words: Vec = vec![0; sections.len()]; - let mut subtree_blocks: Vec = vec![0; sections.len()]; - - // For the root "document" section (id 0), traverse the whole tree. - subtree_words[0] = count_words(root); - subtree_blocks[0] = count_blocks(root); - - // For every other section, find its subtree by matching its start/end - // line range against the tree. - for s in sections.iter().skip(1) { - if let Some(node) = find_section_node(root, s.start_line, s.end_line) { - subtree_words[s.section_id] = count_words(&node); - subtree_blocks[s.section_id] = count_blocks(&node); - } - } - - // Convert subtree counts → own counts (subtree minus children). - let child_ids: Vec> = sections - .iter() - .map(|s| s.child_section_ids.clone()) - .collect(); - for (i, section) in sections.iter_mut().enumerate() { - let mut words_own = subtree_words[i]; - let mut blocks_own = subtree_blocks[i]; - for &c in &child_ids[i] { - words_own = words_own.saturating_sub(subtree_words[c]); - blocks_own = blocks_own.saturating_sub(subtree_blocks[c]); - } - section.word_count = words_own; - section.block_count = blocks_own; - } -} - -fn count_blocks(node: &Node<'_>) -> u64 { - let mut total: u64 = 0; - visit_blocks(node, &mut total); - total -} - -fn visit_blocks(node: &Node<'_>, total: &mut u64) { - if is_block(node.kind()) { - *total += 1; - } - for child in node.children() { - visit_blocks(&child, total); - } -} - -fn is_block(kind: NodeKind) -> bool { - matches!( - kind, - NodeKind::Paragraph - | NodeKind::FencedCodeBlock - | NodeKind::IndentedCodeBlock - | NodeKind::HtmlBlock - | NodeKind::MathBlock - | NodeKind::PipeTable - | NodeKind::ListItem { .. } - | NodeKind::BlockQuote - | NodeKind::Callout - | NodeKind::List - | NodeKind::ThematicBreak - | NodeKind::FootnoteDefinition - | NodeKind::LinkReferenceDefinition - ) -} - -/// Locates the AST node whose start/end lines match a section's recorded -/// range. The section walk is small so a linear search is fine. -fn find_section_node<'a>(root: &Node<'a>, start_line: u64, end_line: u64) -> Option> { - let mut stack = vec![*root]; - while let Some(node) = stack.pop() { - let (s_row, _) = node.start_position(); - let (e_row, e_col) = node.end_position(); - let s = (s_row as u64) + 1; - let mut e = (e_row as u64) + 1; - if e_col == 0 && e > s { - e -= 1; - } - if is_section_node(node.kind()) && s == start_line && e == end_line { - return Some(node); - } - stack.extend(node.children()); - } - None -} diff --git a/crates/mehen-markdown/src/source_text.rs b/crates/mehen-markdown/src/source_text.rs deleted file mode 100644 index 6c415e7b..00000000 --- a/crates/mehen-markdown/src/source_text.rs +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Small source-buffer helpers shared by semantic and structural Markdown -//! passes. - -pub(crate) fn normalize_line_endings(text: &str) -> String { - if !text.as_bytes().contains(&b'\r') { - return text.to_string(); - } - - let mut out = String::with_capacity(text.len()); - let mut chars = text.chars().peekable(); - while let Some(ch) = chars.next() { - if ch == '\r' { - if matches!(chars.peek(), Some('\n')) { - chars.next(); - } - out.push('\n'); - } else { - out.push(ch); - } - } - out -} diff --git a/crates/mehen-markdown/src/syntax_tree.rs b/crates/mehen-markdown/src/syntax_tree.rs deleted file mode 100644 index f03dcdee..00000000 --- a/crates/mehen-markdown/src/syntax_tree.rs +++ /dev/null @@ -1,1314 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Small Markdown syntax tree used internally by the metric passes. -//! -//! The analyzer consumes a compact owned tree built from `pulldown-cmark` -//! events. It exposes byte spans, row positions, a `children()` iterator, and -//! the [`NodeKind`] of each node — the shape the metric modules navigate. -//! -//! The tree is deliberately event-shaped: `pulldown-cmark` is a single-pass, -//! consuming event stream with no parent/child access, so the builder reifies -//! it once into this owned structure that the many independent metric passes -//! can each walk top-down. - -use std::ops::Range; - -use pulldown_cmark::{ - Alignment, BlockQuoteKind, CodeBlockKind, Event, HeadingLevel, LinkType, MetadataBlockKind, - Parser, Tag, TagEnd, -}; - -use crate::document::{ - DocumentBuilder, MarkdownDocument, ReferenceDefinition, line_starts, markdown_options, - preserve_broken_reference_link, reference_definitions_from_source, row_at, -}; -use crate::kind::{HeadingStyle, NodeKind, level_number}; - -#[derive(Debug)] -pub(crate) struct Tree { - nodes: Vec, -} - -#[derive(Clone, Debug)] -struct NodeData { - kind: NodeKind, - start_byte: usize, - end_byte: usize, - start_row: usize, - start_col: usize, - end_row: usize, - end_col: usize, - children: Vec, -} - -#[derive(Clone, Copy, Debug)] -pub(crate) struct Node<'a> { - tree: &'a Tree, - index: usize, -} - -impl Tree { - pub(crate) fn root(&self) -> Node<'_> { - Node { - tree: self, - index: 0, - } - } -} - -impl<'a> Node<'a> { - fn data(&self) -> &NodeData { - &self.tree.nodes[self.index] - } - - pub(crate) fn kind(&self) -> NodeKind { - self.data().kind - } - - pub(crate) fn start_byte(&self) -> usize { - self.data().start_byte - } - - pub(crate) fn end_byte(&self) -> usize { - self.data().end_byte - } - - #[allow(dead_code)] - pub(crate) fn start_position(&self) -> (usize, usize) { - (self.data().start_row, self.data().start_col) - } - - pub(crate) fn end_position(&self) -> (usize, usize) { - (self.data().end_row, self.data().end_col) - } - - pub(crate) fn start_row(&self) -> usize { - self.data().start_row - } - - /// Iterates the direct children of this node in document order. - pub(crate) fn children(&self) -> Children<'a> { - Children { - tree: self.tree, - children: &self.tree.nodes[self.index].children, - pos: 0, - } - } -} - -/// Iterator over a node's direct children. -/// -/// Replaces the former tree-sitter-style mutable `Cursor` -/// (`goto_first_child` / `goto_next_sibling`): all navigation in this crate is -/// strictly top-down over direct children, which a plain iterator expresses -/// directly. -pub(crate) struct Children<'a> { - tree: &'a Tree, - children: &'a [usize], - pos: usize, -} - -impl<'a> Iterator for Children<'a> { - type Item = Node<'a>; - - fn next(&mut self) -> Option { - let index = *self.children.get(self.pos)?; - self.pos += 1; - Some(Node { - tree: self.tree, - index, - }) - } -} - -#[cfg(test)] -pub(crate) fn parse(source: &str) -> Tree { - parse_with_document(source).0 -} - -pub(crate) fn parse_with_document(source: &str) -> (Tree, MarkdownDocument) { - Builder::new(source).parse_with_document() -} - -struct Builder<'a> { - source: &'a str, - line_starts: Vec, - nodes: Vec, - stack: Vec, -} - -impl<'a> Builder<'a> { - fn new(source: &'a str) -> Self { - let line_starts = line_starts(source); - let mut builder = Self { - source, - line_starts, - nodes: Vec::new(), - stack: Vec::new(), - }; - let root = builder.new_node(NodeKind::Document, 0..source.len()); - builder.stack.push(root); - builder - } - - fn parse_with_document(mut self) -> (Tree, MarkdownDocument) { - let reference_definitions = reference_definitions_from_source(self.source); - let mut document = DocumentBuilder::new(self.source, reference_definitions.clone()); - let parser = Parser::new_with_broken_link_callback( - self.source, - markdown_options(), - Some(preserve_broken_reference_link), - ); - let offset_iter = parser.into_offset_iter(); - - for (event, range) in offset_iter { - document.handle_event(event.clone(), range.clone()); - self.handle_event(event, range); - } - - self.add_reference_definitions(reference_definitions); - self.recompute_empty_spans(); - self.wrap_sections(); - self.recompute_all_spans(); - - (Tree { nodes: self.nodes }, document.finish()) - } - - fn handle_event(&mut self, event: Event<'a>, range: Range) { - match event { - Event::Start(tag) => self.start_tag(tag, range), - Event::End(tag) => self.end_tag(tag), - Event::Text(_) => self.add_text(range), - Event::Code(text) => self.add_inline_code(range, &text), - Event::InlineMath(_) => self.add_math_inline(range), - Event::DisplayMath(_) => self.add_math_block(range), - Event::Html(_) => self.add_html(range, false), - Event::InlineHtml(_) => self.add_html(range, true), - Event::FootnoteReference(label) => self.add_footnote_reference(&label, range), - Event::SoftBreak | Event::HardBreak => { - self.add_child(NodeKind::Newline, range); - } - Event::Rule => { - self.add_child(NodeKind::ThematicBreak, range); - } - Event::TaskListMarker(checked) => self.add_task_marker(checked, range), - } - } - - fn start_tag(&mut self, tag: Tag<'a>, range: Range) { - match tag { - Tag::Paragraph => self.push(NodeKind::Paragraph, range), - Tag::Heading { level, .. } => self.push_heading(level, range), - Tag::BlockQuote(kind) => self.push_blockquote(kind, range), - Tag::CodeBlock(CodeBlockKind::Fenced(info)) => self.push_fenced_code(&info, range), - Tag::CodeBlock(CodeBlockKind::Indented) => { - self.push(NodeKind::IndentedCodeBlock, range) - } - Tag::HtmlBlock => self.push(NodeKind::HtmlBlock, range), - Tag::List(start) => self.push_list(start, range), - Tag::Item => self.push_list_item(range), - Tag::FootnoteDefinition(label) => self.push_footnote_definition(&label, range), - Tag::Table(alignments) => self.push_table(alignments, range), - Tag::TableHead => self.push(NodeKind::PipeTableHeader, range), - Tag::TableRow => self.push(NodeKind::PipeTableRow, range), - Tag::TableCell => self.push(NodeKind::PipeTableCell, range), - Tag::Emphasis => self.push(NodeKind::Emphasis, range), - Tag::Strong => self.push(NodeKind::Strong, range), - Tag::Strikethrough => self.push(NodeKind::Strikethrough, range), - Tag::Superscript | Tag::Subscript => self.push(NodeKind::Emphasis, range), - Tag::Link { - link_type, - dest_url, - title, - id, - } => self.push_link(link_type, &dest_url, &title, &id, range, false), - Tag::Image { - link_type, - dest_url, - title, - id, - } => self.push_link(link_type, &dest_url, &title, &id, range, true), - Tag::MetadataBlock(kind) => { - let kind = metadata_kind(kind); - self.push(kind, range); - } - Tag::DefinitionList => self.push(NodeKind::List, range), - Tag::DefinitionListTitle | Tag::DefinitionListDefinition => { - self.push(NodeKind::ListItem { task: false }, range) - } - } - } - - fn end_tag(&mut self, tag: TagEnd) { - match tag { - TagEnd::Heading(_) => { - self.pop_if(NodeKind::HeadingContent); - self.pop_if_matches(NodeKind::is_heading); - } - TagEnd::Item => { - self.pop_if_matches(|kind| matches!(kind, NodeKind::ListItemContent { .. })); - self.pop_if_matches(NodeKind::is_list_item); - } - TagEnd::Link | TagEnd::Image => { - self.pop_if(NodeKind::LinkLabel); - self.pop_one_of(&[NodeKind::Link, NodeKind::Image, NodeKind::Autolink]); - } - TagEnd::Paragraph => self.pop_if(NodeKind::Paragraph), - TagEnd::BlockQuote(_) => self.pop_one_of(&[NodeKind::BlockQuote, NodeKind::Callout]), - TagEnd::CodeBlock => { - self.pop_one_of(&[NodeKind::FencedCodeBlock, NodeKind::IndentedCodeBlock]); - } - TagEnd::HtmlBlock => self.pop_if(NodeKind::HtmlBlock), - TagEnd::List(_) => self.pop_if(NodeKind::List), - TagEnd::FootnoteDefinition => self.pop_if(NodeKind::FootnoteDefinition), - TagEnd::Table => self.pop_if(NodeKind::PipeTable), - TagEnd::TableHead => self.pop_if(NodeKind::PipeTableHeader), - TagEnd::TableRow => self.pop_if(NodeKind::PipeTableRow), - TagEnd::TableCell => self.pop_if(NodeKind::PipeTableCell), - TagEnd::Emphasis | TagEnd::Superscript | TagEnd::Subscript => { - self.pop_if(NodeKind::Emphasis) - } - TagEnd::Strong => self.pop_if(NodeKind::Strong), - TagEnd::Strikethrough => self.pop_if(NodeKind::Strikethrough), - TagEnd::MetadataBlock(kind) => { - let kind = metadata_kind(kind); - self.pop_if(kind); - } - TagEnd::DefinitionList => self.pop_if(NodeKind::List), - TagEnd::DefinitionListTitle | TagEnd::DefinitionListDefinition => { - self.pop_if_matches(NodeKind::is_list_item) - } - } - } - - fn push_heading(&mut self, level: HeadingLevel, range: Range) { - let (level, style) = resolve_heading(level, is_setext_heading(self.source, &range)); - // The resolved style (not the raw detection) drives the marker range: - // a degenerate setext level (>2) is coerced to ATX, so its marker is - // the `#` scan, not the underline scan. - let setext = matches!(style, HeadingStyle::Setext); - let heading = self.add_child(NodeKind::Heading { level, style }, range.clone()); - if let Some(marker_range) = heading_marker_range(self.source, &range, setext) { - self.add_child_to( - heading, - NodeKind::HeadingMarker { level, style }, - marker_range, - ); - } - let content = self.add_child_to(heading, NodeKind::HeadingContent, empty_at(range.start)); - self.stack.push(heading); - self.stack.push(content); - } - - fn push_blockquote(&mut self, kind: Option, range: Range) { - let node_kind = if kind.is_some() { - NodeKind::Callout - } else { - NodeKind::BlockQuote - }; - let node = self.add_child(node_kind, range.clone()); - self.add_child_to(node, NodeKind::BlockQuoteMarker, first_byte(range.start)); - if kind.is_some() - && let Some(marker) = callout_marker_ranges(self.source, &range) - { - self.add_child_to(node, NodeKind::CalloutMarkerOpen, marker.open); - self.add_child_to(node, NodeKind::CalloutType, marker.callout_type); - self.add_child_to(node, NodeKind::CalloutMarkerClose, marker.close); - } - self.stack.push(node); - } - - fn push_fenced_code(&mut self, info: &str, range: Range) { - let node = self.add_child(NodeKind::FencedCodeBlock, range.clone()); - if !info.trim().is_empty() { - let info_range = find_in_range(self.source, &range, info).unwrap_or_else(|| { - let start = range.start.min(range.end); - start..start - }); - let info_node = self.add_child_to(node, NodeKind::InfoString, info_range.clone()); - let lang_end = info - .find(|c: char| c.is_whitespace() || c == ',' || c == '{') - .unwrap_or(info.len()); - let lang = &info[..lang_end]; - if !lang.is_empty() { - let lang_range = - find_in_range(self.source, &info_range, lang).unwrap_or(info_range); - self.add_child_to(info_node, NodeKind::Language, lang_range); - } - } - self.stack.push(node); - } - - fn push_list(&mut self, start: Option, range: Range) { - let node = self.add_child(NodeKind::List, range.clone()); - let _ = start; - self.stack.push(node); - } - - fn push_list_item(&mut self, range: Range) { - let item = self.add_child(NodeKind::ListItem { task: false }, range.clone()); - self.add_child_to( - item, - NodeKind::ListMarker, - list_item_marker_range(self.source, &range), - ); - let content = self.add_child_to( - item, - NodeKind::ListItemContent { task: false }, - empty_at(range.start), - ); - self.stack.push(item); - self.stack.push(content); - } - - fn push_footnote_definition(&mut self, label: &str, range: Range) { - let node = self.add_child(NodeKind::FootnoteDefinition, range.clone()); - if let Some(label_range) = find_footnote_label_range(self.source, &range, label) { - self.add_child_to(node, NodeKind::FootnoteLabel, label_range); - } - self.stack.push(node); - } - - fn push_table(&mut self, alignments: Vec, range: Range) { - let table = self.add_child(NodeKind::PipeTable, range.clone()); - let delim = self.add_child_to( - table, - NodeKind::PipeTableDelimiterRow, - empty_at(range.start), - ); - for align in alignments { - let cell = self.add_child_to( - delim, - NodeKind::PipeTableDelimiterCell, - empty_at(range.start), - ); - match align { - Alignment::Left => { - self.add_child_to(cell, NodeKind::PipeTableAlignLeft, empty_at(range.start)); - } - Alignment::Right => { - self.add_child_to(cell, NodeKind::PipeTableAlignRight, empty_at(range.start)); - } - Alignment::Center => { - self.add_child_to(cell, NodeKind::PipeTableAlignLeft, empty_at(range.start)); - self.add_child_to(cell, NodeKind::PipeTableAlignRight, empty_at(range.start)); - } - Alignment::None => {} - } - } - self.stack.push(table); - } - - fn push_link( - &mut self, - link_type: LinkType, - dest_url: &str, - title: &str, - reference_id: &str, - range: Range, - image: bool, - ) { - if !image && matches!(link_type, LinkType::Autolink | LinkType::Email) { - let node = self.add_child(NodeKind::Autolink, range.clone()); - let kind = if matches!(link_type, LinkType::Email) { - NodeKind::Email - } else { - NodeKind::Uri - }; - let dest_range = visible_autolink_range(self.source, &range, dest_url) - .or_else(|| find_in_range(self.source, &range, dest_url)) - .unwrap_or_else(|| range.clone()); - self.add_child_to(node, kind, dest_range); - self.stack.push(node); - return; - } - - let node = self.add_child( - if image { - NodeKind::Image - } else { - NodeKind::Link - }, - range.clone(), - ); - let dest_range = - find_link_destination_range(self.source, &range, link_type, dest_url, reference_id); - if let Some(dest_range) = dest_range.clone() { - self.add_child_to(node, NodeKind::LinkDestination, dest_range); - } - if !title.is_empty() - && let Some(title_range) = - find_link_title_range(self.source, &range, title, dest_range.as_ref()) - { - self.add_child_to(node, NodeKind::LinkTitle, title_range); - } - let label = self.add_child_to(node, NodeKind::LinkLabel, empty_at(range.start)); - self.stack.push(node); - self.stack.push(label); - } - - fn add_text(&mut self, range: Range) { - if range.start >= range.end { - return; - } - let parent = self.current(); - let parent_kind = self.nodes[parent].kind; - if matches!(parent_kind, NodeKind::FencedCodeBlock) { - self.add_child_to(parent, NodeKind::CodeFenceContent, range); - return; - } - if matches!(parent_kind, NodeKind::IndentedCodeBlock) { - self.add_child_to(parent, NodeKind::IndentedChunk, range); - return; - } - self.tokenize_text(range); - } - - fn add_inline_code(&mut self, range: Range, text: &str) { - let node = self.add_child(NodeKind::InlineCode, range.clone()); - let content = inline_code_content_range(self.source, &range, text); - self.add_child_to(node, NodeKind::InlineCodeContent, content); - } - - fn add_math_inline(&mut self, range: Range) { - let node = self.add_child(NodeKind::MathInline, range.clone()); - self.add_child_to(node, NodeKind::MathInlineContent, range.clone()); - self.tokenize_text_into(node, range); - } - - fn add_math_block(&mut self, range: Range) { - let node = self.add_child(NodeKind::MathBlock, range.clone()); - self.add_child_to(node, NodeKind::MathBlockDelimiter, first_byte(range.start)); - self.add_child_to(node, NodeKind::MathBlockContent, range.clone()); - self.tokenize_text_into(node, range); - } - - fn add_html(&mut self, range: Range, inline: bool) { - let text = self.source.get(range.clone()).unwrap_or(""); - if text.trim().is_empty() { - return; - } - let parent = self.current(); - let node = if inline || !matches!(self.nodes[parent].kind, NodeKind::HtmlBlock) { - self.add_child( - if inline { - NodeKind::HtmlInline - } else { - NodeKind::HtmlBlock - }, - range.clone(), - ) - } else { - parent - }; - let kind = classify_html(text); - self.add_child_to(node, kind, range); - } - - fn add_footnote_reference(&mut self, label: &str, range: Range) { - let node = self.add_child(NodeKind::FootnoteReference, range.clone()); - if let Some(label_range) = find_footnote_label_range(self.source, &range, label) { - self.add_child_to(node, NodeKind::FootnoteReferenceLabel, label_range); - } - } - - fn add_task_marker(&mut self, checked: bool, range: Range) { - let marker = if checked { - NodeKind::TaskListMarkerChecked - } else { - NodeKind::TaskListMarkerUnchecked - }; - self.add_child(marker, range); - for &idx in self.stack.iter().rev() { - match self.nodes[idx].kind { - NodeKind::ListItem { .. } => { - self.nodes[idx].kind = NodeKind::ListItem { task: true }; - break; - } - NodeKind::ListItemContent { .. } => { - self.nodes[idx].kind = NodeKind::ListItemContent { task: true }; - } - _ => {} - } - } - } - - fn tokenize_text(&mut self, range: Range) { - let parent = self.current(); - self.tokenize_text_into(parent, range); - } - - fn tokenize_text_into(&mut self, parent: usize, range: Range) { - let Some(text) = self.source.get(range.clone()) else { - return; - }; - let chars: Vec<_> = text.char_indices().collect(); - let mut token_start: Option = None; - for (idx, (offset, ch)) in chars.iter().copied().enumerate() { - let abs = range.start + offset; - let prev = idx - .checked_sub(1) - .and_then(|prev_idx| chars.get(prev_idx)) - .map(|(_, ch)| *ch); - let next = chars.get(idx + 1).map(|(_, ch)| *ch); - if is_token_char(ch, prev, next) { - token_start.get_or_insert(abs); - continue; - } - if let Some(start) = token_start.take() { - self.add_wordish_token(parent, start..abs); - } - if !ch.is_whitespace() { - let end = abs + ch.len_utf8(); - if let Some(kind) = punctuation_kind(ch) { - self.add_child_to(parent, kind, abs..end); - } - } - } - if let Some(start) = token_start { - self.add_wordish_token(parent, start..range.end); - } - } - - fn add_wordish_token(&mut self, parent: usize, range: Range) { - let text = self.source.get(range.clone()).unwrap_or(""); - let kind = classify_wordish(text); - self.add_child_to(parent, kind, range); - } - - fn add_reference_definitions(&mut self, refdefs: Vec) { - for def in refdefs { - let parent_span = def.label_span.start..def.span.end; - let parent = self.reference_definition_parent(&parent_span); - let node = - self.add_child_to(parent, NodeKind::LinkReferenceDefinition, def.span.clone()); - self.add_child_to(node, NodeKind::LinkLabel, def.label_span); - self.add_child_to(node, NodeKind::LinkDestination, def.destination_span); - if let Some(title_span) = def.title_span { - self.add_child_to(node, NodeKind::LinkTitle, title_span); - } - } - } - - fn reference_definition_parent(&self, span: &Range) -> usize { - let mut best = 0; - let mut best_width = usize::MAX; - for (idx, node) in self.nodes.iter().enumerate().skip(1) { - if !is_reference_definition_container(node.kind) { - continue; - } - if node.start_byte <= span.start && span.end <= node.end_byte { - let width = node.end_byte.saturating_sub(node.start_byte); - if width <= best_width { - best = idx; - best_width = width; - } - } - } - best - } - - fn wrap_sections(&mut self) { - let mut top = self.nodes[0].children.clone(); - top.sort_by_key(|idx| (self.nodes[*idx].start_byte, self.nodes[*idx].end_byte)); - self.nodes[0].children.clear(); - - let mut section_stack: Vec<(u8, usize)> = Vec::new(); - for child in top { - if let Some(level) = self.nodes[child].kind.heading_level() { - while section_stack - .last() - .map(|(stack_level, _)| *stack_level >= level) - .unwrap_or(false) - { - section_stack.pop(); - } - let section = self.new_node( - NodeKind::Section { level }, - self.nodes[child].start_byte..self.nodes[child].end_byte, - ); - self.nodes[section].children.push(child); - if let Some((_, parent)) = section_stack.last().copied() { - self.nodes[parent].children.push(section); - } else { - self.nodes[0].children.push(section); - } - section_stack.push((level, section)); - } else if let Some((_, section)) = section_stack.last().copied() { - self.nodes[section].children.push(child); - } else { - self.nodes[0].children.push(child); - } - } - } - - fn recompute_empty_spans(&mut self) { - for idx in 0..self.nodes.len() { - if self.nodes[idx].start_byte == self.nodes[idx].end_byte { - self.refresh_span_from_children(idx); - } - } - } - - fn recompute_all_spans(&mut self) { - self.recompute_span_rec(0); - } - - fn recompute_span_rec(&mut self, idx: usize) -> Option> { - let children = self.nodes[idx].children.clone(); - let mut start = self.nodes[idx].start_byte; - let mut end = self.nodes[idx].end_byte; - for child in children { - if let Some(child_range) = self.recompute_span_rec(child) { - start = start.min(child_range.start); - end = end.max(child_range.end); - } - } - if !self.nodes[idx].children.is_empty() - && recompute_span_from_children(self.nodes[idx].kind) - { - self.set_range(idx, start..end); - } - Some(self.nodes[idx].start_byte..self.nodes[idx].end_byte) - } - - fn refresh_span_from_children(&mut self, idx: usize) { - let children = self.nodes[idx].children.clone(); - let Some(first) = children.first().copied() else { - return; - }; - let mut start = self.nodes[first].start_byte; - let mut end = self.nodes[first].end_byte; - for child in children.iter().copied().skip(1) { - start = start.min(self.nodes[child].start_byte); - end = end.max(self.nodes[child].end_byte); - } - self.set_range(idx, start..end); - } - - fn push(&mut self, kind: NodeKind, range: Range) { - let node = self.add_child(kind, range); - self.stack.push(node); - } - - fn add_child(&mut self, kind: NodeKind, range: Range) -> usize { - let parent = self.current(); - self.add_child_to(parent, kind, range) - } - - fn add_child_to(&mut self, parent: usize, kind: NodeKind, range: Range) -> usize { - let node = self.new_node(kind, range); - self.nodes[parent].children.push(node); - node - } - - fn new_node(&mut self, kind: NodeKind, range: Range) -> usize { - let range = clamp_range(range, self.source.len()); - let (start_row, start_col) = self.position(range.start); - let (end_row, end_col) = self.position(range.end); - let idx = self.nodes.len(); - self.nodes.push(NodeData { - kind, - start_byte: range.start, - end_byte: range.end, - start_row, - start_col, - end_row, - end_col, - children: Vec::new(), - }); - idx - } - - fn set_range(&mut self, idx: usize, range: Range) { - let range = clamp_range(range, self.source.len()); - let (start_row, start_col) = self.position(range.start); - let (end_row, end_col) = self.position(range.end); - let node = &mut self.nodes[idx]; - node.start_byte = range.start; - node.end_byte = range.end; - node.start_row = start_row; - node.start_col = start_col; - node.end_row = end_row; - node.end_col = end_col; - } - - fn current(&self) -> usize { - *self.stack.last().expect("builder stack is empty") - } - - fn pop_if(&mut self, kind: NodeKind) { - if self.stack.last().map(|idx| self.nodes[*idx].kind) == Some(kind) { - self.stack.pop(); - } - } - - /// Pops the stack top when its kind satisfies `pred`. - /// - /// Used for the folded families (headings, list items) where the top can - /// be any level/flag variant of a group. - fn pop_if_matches(&mut self, pred: impl Fn(NodeKind) -> bool) { - if self - .stack - .last() - .map(|idx| pred(self.nodes[*idx].kind)) - .unwrap_or(false) - { - self.stack.pop(); - } - } - - fn pop_one_of(&mut self, kinds: &[NodeKind]) { - let Some(idx) = self.stack.last().copied() else { - return; - }; - let actual = self.nodes[idx].kind; - if kinds.contains(&actual) { - self.stack.pop(); - } else { - debug_assert!( - self.stack.len() <= 1, - "unexpected markdown builder stack top: expected one of {kinds:?}, got {actual:?}" - ); - } - } - - fn position(&self, byte: usize) -> (usize, usize) { - let byte = byte.min(self.source.len()); - let row = row_at(&self.line_starts, self.source.len(), byte); - (row, byte.saturating_sub(self.line_starts[row])) - } -} - -fn metadata_kind(kind: MetadataBlockKind) -> NodeKind { - match kind { - MetadataBlockKind::YamlStyle => NodeKind::MinusMetadata, - MetadataBlockKind::PlusesStyle => NodeKind::PlusMetadata, - } -} - -/// Whether a container's span should be widened to cover its children. -/// -/// These are synthesized or empty-initialized spans (sections, content -/// wrappers, table delimiter scaffolding) whose true extent is only known -/// once children are attached. -fn recompute_span_from_children(kind: NodeKind) -> bool { - matches!( - kind, - NodeKind::Section { .. } - | NodeKind::HeadingContent - | NodeKind::LinkLabel - | NodeKind::ListItemContent { .. } - | NodeKind::PipeTableDelimiterRow - | NodeKind::PipeTableDelimiterCell - ) -} - -fn clamp_range(range: Range, len: usize) -> Range { - let start = range.start.min(len); - let end = range.end.min(len).max(start); - start..end -} - -fn empty_at(byte: usize) -> Range { - byte..byte -} - -fn first_byte(byte: usize) -> Range { - byte..byte.saturating_add(1) -} - -/// Resolves the `(level, style)` of a heading from its pulldown level and -/// whether the source span looks like a setext underline. -/// -/// pulldown-cmark only surfaces setext headings at H1/H2. A detected setext -/// underline at any other level is a degenerate case; it is coerced to ATX -/// H1, preserving the pre-refactor `heading_kinds` fallback behavior. -fn resolve_heading(level: HeadingLevel, setext: bool) -> (u8, HeadingStyle) { - match (level, setext) { - (HeadingLevel::H1, true) => (1, HeadingStyle::Setext), - (HeadingLevel::H2, true) => (2, HeadingStyle::Setext), - (_, true) => (1, HeadingStyle::Atx), - (level, false) => (level_number(level), HeadingStyle::Atx), - } -} - -fn is_setext_heading(source: &str, range: &Range) -> bool { - let Some(slice) = source.get(range.clone()) else { - return false; - }; - let mut non_empty = slice.lines().filter(|line| !line.trim().is_empty()); - let Some(_first) = non_empty.next() else { - return false; - }; - let Some(last) = non_empty.next_back() else { - return false; - }; - let trimmed = last.trim(); - !trimmed.is_empty() && trimmed.chars().all(|c| c == '=' || c == '-') -} - -fn heading_marker_range(source: &str, range: &Range, setext: bool) -> Option> { - let slice = source.get(range.clone())?; - if setext { - let mut offset = range.start; - for line in slice.split_inclusive('\n') { - let trimmed = line.trim(); - if !trimmed.is_empty() && trimmed.chars().all(|c| c == '=' || c == '-') { - let ws = line.len() - line.trim_start().len(); - let len = trimmed.len(); - return Some(offset + ws..offset + ws + len); - } - offset += line.len(); - } - return None; - } - let line = slice.lines().next().unwrap_or(slice); - let leading = line.len() - line.trim_start().len(); - let hashes = line[leading..].bytes().take_while(|b| *b == b'#').count(); - (hashes > 0).then_some(range.start + leading..range.start + leading + hashes) -} - -fn list_item_marker_range(source: &str, range: &Range) -> Range { - let Some(line) = source - .get(range.clone()) - .and_then(|slice| slice.lines().next()) - else { - return first_byte(range.start); - }; - let leading = line.len() - line.trim_start().len(); - let trimmed = &line[leading..]; - let len = if trimmed.chars().next().is_some_and(|ch| ch.is_ascii_digit()) { - trimmed - .find(|ch| ['.', ')'].contains(&ch)) - .map(|idx| idx + 1) - .unwrap_or(1) - } else { - 1 - }; - range.start + leading..range.start + leading + len -} - -fn callout_type_range(source: &str, range: &Range) -> Option> { - let slice = source.get(range.clone())?; - let local = slice.find("[!")?; - let start = range.start + local + 2; - let end = source[start..].find(']').map(|n| start + n)?; - Some(start..end) -} - -struct CalloutMarkerRanges { - open: Range, - callout_type: Range, - close: Range, -} - -fn callout_marker_ranges(source: &str, range: &Range) -> Option { - let callout_type = callout_type_range(source, range)?; - let open_start = callout_type.start.checked_sub(2)?; - let close_start = callout_type.end.min(range.end); - let close_end = close_start.saturating_add(1).min(range.end); - Some(CalloutMarkerRanges { - open: open_start..callout_type.start, - callout_type, - close: close_start..close_end, - }) -} - -fn visible_autolink_range(source: &str, range: &Range, dest: &str) -> Option> { - let slice = source.get(range.clone())?; - let inner = slice.trim().trim_start_matches('<').trim_end_matches('>'); - if inner.is_empty() { - return None; - } - find_in_range(source, range, inner).or_else(|| find_in_range(source, range, dest)) -} - -fn find_footnote_label_range( - source: &str, - range: &Range, - label: &str, -) -> Option> { - find_in_range(source, range, &format!("[^{label}]")) -} - -fn find_link_destination_range( - source: &str, - range: &Range, - link_type: LinkType, - destination: &str, - reference_id: &str, -) -> Option> { - match link_type { - LinkType::Inline | LinkType::WikiLink { .. } if !destination.is_empty() => { - let search_range = - inline_link_payload_range(source, range).unwrap_or_else(|| range.clone()); - find_in_range(source, &search_range, destination) - } - LinkType::Reference | LinkType::ReferenceUnknown if !reference_id.is_empty() => { - reference_link_key_range(source, range) - } - _ => None, - } -} - -fn find_link_title_range( - source: &str, - range: &Range, - title: &str, - destination: Option<&Range>, -) -> Option> { - let search_range = destination - .map(|dest| dest.end..range.end) - .or_else(|| inline_link_payload_range(source, range)) - .unwrap_or_else(|| range.clone()); - find_in_range(source, &search_range, title) -} - -fn inline_link_payload_range(source: &str, range: &Range) -> Option> { - let slice = source.get(range.clone())?; - let payload_start = slice.find("](")? + 2; - Some(range.start + payload_start..range.end) -} - -fn reference_link_key_range(source: &str, range: &Range) -> Option> { - let slice = source.get(range.clone())?; - let close = slice.rfind(']')?; - let before_close = &slice[..close]; - let open = before_close.rfind('[')?; - if open == 0 || !before_close[..open].ends_with(']') { - return None; - } - trim_byte_range(source, range.start + open + 1..range.start + close) -} - -fn trim_byte_range(source: &str, range: Range) -> Option> { - let slice = source.get(range.clone())?; - let start_offset = slice.len() - slice.trim_start().len(); - let end_offset = slice.trim_end().len(); - let trimmed = range.start + start_offset..range.start + end_offset; - (trimmed.start < trimmed.end).then_some(trimmed) -} - -fn inline_code_content_range(source: &str, range: &Range, text: &str) -> Range { - let Some(slice) = source.get(range.clone()) else { - return range.clone(); - }; - let opening = slice.bytes().take_while(|byte| *byte == b'`').count(); - let closing = slice.bytes().rev().take_while(|byte| *byte == b'`').count(); - let inner_start = range.start.saturating_add(opening).min(range.end); - let inner_end = range.end.saturating_sub(closing).max(inner_start); - let inner = inner_start..inner_end; - find_in_range(source, &inner, text).unwrap_or(inner) -} - -fn find_in_range(source: &str, range: &Range, needle: &str) -> Option> { - if needle.is_empty() { - return None; - } - let slice = source.get(range.clone())?; - let local = slice.find(needle)?; - Some(range.start + local..range.start + local + needle.len()) -} - -fn classify_html(text: &str) -> NodeKind { - let trimmed = text.trim_start(); - if trimmed.starts_with(" Proxy - Proxy --> Dispatcher - Dispatcher --> Analyzer - Analyzer --> Cache - Analyzer --> Response - Response --> Client -``` - -Readers who need the exact proxy configuration should consult the -operators runbook. The diagram is intentionally high-level; it does -not show retry loops or rate-limiting edges because those are -implementation details that would clutter the architectural picture. - -Some additional context: the proxy is a thin layer that primarily -handles TLS termination and HTTP/2 multiplexing. It does not perform -any business logic and is therefore easy to scale horizontally. The -dispatcher in contrast is stateful and coordinates outstanding work -across the analyzer fleet. - -## Component decomposition - -Figure 2 breaks the analyzer into its major internal components. The -frontend parses the source buffer, the structural pass extracts the -LOC family and section tree, the complexity pass computes MRPC and -MCC, the Halstead pass counts tokens, and the grounding pass resolves -paths and links. The components are not independent — later passes -read data produced by earlier ones — but they are conceptually -separate. - -```mermaid ---- -title: Figure 2. Analyzer component decomposition ---- -graph TD - Frontend --> Structural - Structural --> Complexity - Structural --> Halstead - Structural --> Grounding - Complexity --> Reporter - Halstead --> Reporter - Grounding --> Reporter -``` - -The reporter assembles the final metric record and hands it back to -the dispatcher. The decomposition is useful because it lets us reason -about each pass in isolation and add new passes without perturbing -the existing ones. It also lets us parallelize the three middle passes -when the input document is large enough to justify the extra -scheduling overhead. - -Readers familiar with compiler architecture will recognize a loose -analogy: the frontend produces an AST, several analysis passes decorate -the AST with derived data, and a final reporter consumes the decorated -form to emit the public output. The analogy is loose because the AST -here is a tree-sitter parse tree rather than a full compiler IR, but -the overall shape is similar. - -## Scheduling - -Figure 3 shows how the dispatcher schedules incoming work across the -analyzer pool. When a request arrives the dispatcher assigns it to a -worker based on a weighted round-robin policy that accounts for each -worker's outstanding load. Workers pull work from their queue and -report completion back to the dispatcher. If a worker becomes -unresponsive the dispatcher reassigns its outstanding tasks. - -```mermaid ---- -title: Figure 3. Dispatcher-worker scheduling loop ---- -graph LR - Dispatcher -->|assign| Worker1 - Dispatcher -->|assign| Worker2 - Dispatcher -->|assign| Worker3 - Worker1 -->|ack| Dispatcher - Worker2 -->|ack| Dispatcher - Worker3 -->|ack| Dispatcher - Worker1 -->|result| Cache - Worker2 -->|result| Cache - Worker3 -->|result| Cache -``` - -The scheduling policy is tunable. The default weights favor recently -responsive workers which tends to keep latency low under steady load. -Operators can override the weights through a configuration file when -the workload has unusual characteristics that the default policy does -not handle well. - -Worker health is tracked through periodic heartbeats. A worker that -misses three consecutive heartbeats is marked suspect and its -outstanding work is reassigned to other workers after a short grace -period. This mechanism is primarily defensive and is rarely triggered -in normal operation. - -## Storage topology - -Figure 4 shows the storage topology. The system uses three stores: a -primary relational database for metric aggregates and run metadata, -an in-memory cache for hot-path lookup, and a blob store for archived -metric records older than 30 days. - -```mermaid ---- -title: Figure 4. Storage topology ---- -graph TD - API --> Primary - API --> Cache - Primary --> Replica - Primary --> Archive - Cache --> Primary - Archive --> Blob -``` - -The relational primary is the source of truth. The cache improves read -latency for recent runs and is invalidated whenever the primary is -updated. The archive tier is append-only and is optimized for -long-term cost rather than for query performance. A background job -migrates records older than 30 days from the primary to the archive. - -Consistency guarantees differ across the stores. The primary is -strongly consistent, the cache is eventually consistent with a -bounded staleness window, and the archive is effectively immutable -once a record has been migrated. Callers who need strong consistency -should read from the primary directly; callers who can tolerate -slight staleness should read from the cache for lower latency. - -## Rollback path - -Figure 5 illustrates the rollback path for a failed deploy. The -rollout controller monitors health probes after each deploy. If -health probes fail within the bake window, the controller scales the -new replica set to zero and restores the previous replica set. - -```mermaid ---- -title: Figure 5. Rollback path on failed deploy ---- -graph TD - Deploy --> Healthcheck - Healthcheck -->|fail| Rollback - Rollback --> Previous - Previous --> Healthcheck2 - Healthcheck2 -->|ok| Stable - Healthcheck -->|ok| Stable -``` - -The rollback path is intentionally simple. It does not attempt to -repair the failing deploy in place; instead it reverts to a known-good -state and surfaces an alert for operators to investigate. This -conservative policy trades some recovery speed for predictability and -has proved more reliable than more aggressive self-repair strategies -in our experience. - -## Summary - -The five diagrams together describe the system from five complementary -angles. Request flow explains what happens at runtime; component -decomposition explains how the analyzer is structured internally; -scheduling explains how work is distributed; storage topology explains -where data lives; and the rollback path explains how we recover from -failed deploys. Readers who need deeper detail should consult the -respective source files, which are linked from the architecture -overview page. diff --git a/crates/mehen-markdown/tests/fixtures/diagram_mermaid.md b/crates/mehen-markdown/tests/fixtures/diagram_mermaid.md deleted file mode 100644 index 82ff605c..00000000 --- a/crates/mehen-markdown/tests/fixtures/diagram_mermaid.md +++ /dev/null @@ -1,13 +0,0 @@ -# Diagram Mermaid Fixture - -The diagram below encodes the §12.2 two-node cycle invariant referenced in -the Phase-C spec: nodes=2, edges=2, components=1, cycles=1. - -```mermaid -graph TD - A --> B - B --> A -``` - -A trailing explanation paragraph keeps the nearby-prose flag on so the -diagram has a scaffold credit even without an explicit caption. diff --git a/crates/mehen-markdown/tests/fixtures/diagram_parse_error.md b/crates/mehen-markdown/tests/fixtures/diagram_parse_error.md deleted file mode 100644 index 8e0ccad6..00000000 --- a/crates/mehen-markdown/tests/fixtures/diagram_parse_error.md +++ /dev/null @@ -1,19 +0,0 @@ -# Diagram Parse Error Fixture - -A fenced block labelled with an unknown diagram language ("tikz") goes -through the diagram pipeline but yields `parse_error = true`, adding the -+2.0 diagram-complexity term per §12.2. - -```plantuml -@startuml -[*] -> Idle -Idle -> Running : start -Running -> Idle : stop -@enduml -``` - -```tikz -\node (A) at (0,0) {A}; -\node (B) at (1,1) {B}; -\draw (A) -- (B); -``` diff --git a/crates/mehen-markdown/tests/fixtures/embedded_code_large.md b/crates/mehen-markdown/tests/fixtures/embedded_code_large.md deleted file mode 100644 index ea69dd2c..00000000 --- a/crates/mehen-markdown/tests/fixtures/embedded_code_large.md +++ /dev/null @@ -1,89 +0,0 @@ -# Embedded Code Large Fixture - -Exercises §9.4 embedded-volume accumulation across supported languages. -Each fence is large enough to move the sqrt-scaled contribution noticeably. - -## Rust - -```rust -fn collatz(n: u64) -> u64 { - let mut steps = 0; - let mut x = n; - while x > 1 { - if x % 2 == 0 { - x /= 2; - } else { - x = 3 * x + 1; - } - steps += 1; - } - steps -} - -fn main() { - let args: Vec = std::env::args().collect(); - for a in &args[1..] { - if let Ok(n) = a.parse::() { - println!("{}: {}", n, collatz(n)); - } - } -} -``` - -## Python - -```python -def fibonacci(n): - a, b = 0, 1 - for _ in range(n): - a, b = b, a + b - return a - -def main(): - import sys - for arg in sys.argv[1:]: - try: - n = int(arg) - except ValueError: - continue - print(n, fibonacci(n)) - -if __name__ == "__main__": - main() -``` - -## TypeScript - -```typescript -interface Shape { - area(): number; -} - -class Circle implements Shape { - constructor(private radius: number) {} - area(): number { - return Math.PI * this.radius * this.radius; - } -} - -class Rectangle implements Shape { - constructor(private w: number, private h: number) {} - area(): number { - return this.w * this.h; - } -} - -function totalArea(shapes: Shape[]): number { - return shapes.reduce((t, s) => t + s.area(), 0); -} -``` - -## Unsupported Tag - -This fence is ignored by the §9.4 dispatcher because `sql` is not in mehen's -language list — its content still contributes to the `FenceTag` operator, -but not to `embedded_volume`. - -```sql -SELECT id, name FROM users WHERE active = 1 ORDER BY id; -``` diff --git a/crates/mehen-markdown/tests/fixtures/empty.md b/crates/mehen-markdown/tests/fixtures/empty.md deleted file mode 100644 index 8b137891..00000000 --- a/crates/mehen-markdown/tests/fixtures/empty.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/mehen-markdown/tests/fixtures/frontmatter.md b/crates/mehen-markdown/tests/fixtures/frontmatter.md deleted file mode 100644 index d6867694..00000000 --- a/crates/mehen-markdown/tests/fixtures/frontmatter.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Frontmatter Fixture -tags: - - metrics - - markdown ---- - -# Frontmatter Fixture - -The front matter above declares a title and two tags. - -This paragraph sits entirely outside the front-matter block. diff --git a/crates/mehen-markdown/tests/fixtures/giant_table_debt.md b/crates/mehen-markdown/tests/fixtures/giant_table_debt.md deleted file mode 100644 index 035e9b59..00000000 --- a/crates/mehen-markdown/tests/fixtures/giant_table_debt.md +++ /dev/null @@ -1,54 +0,0 @@ -# Ambassador service port matrix - -This document catalogs the network port matrix for the ambassador service -fleet. The table below is large enough to be a maintenance liability and -is intended to trip the §13 Table Burden threshold. - -## Port matrix - -| Host | Port 0 | Port 1 | Port 2 | Port 3 | Port 4 | Port 5 | Port 6 | Port 7 | Port 8 | Port 9 | Port 10 | Port 11 | Port 12 | Port 13 | Port 14 | Port 15 | Port 16 | Port 17 | Port 18 | Port 19 | -|------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| -| h0 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h1 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h2 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h3 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h4 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h5 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h6 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h7 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h8 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h9 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h10 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h11 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h12 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h13 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h14 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h15 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h16 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h17 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h18 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h19 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h20 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h21 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h22 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h23 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h24 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h25 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h26 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h27 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h28 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h29 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h30 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h31 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h32 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h33 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h34 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h35 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h36 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h37 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h38 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | -| h39 | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | tcp | - -This table contains 40 rows × 21 columns = 840 cells and should trip the -§13 Table Burden hard-warning threshold. The surrounding prose is -intentionally thin so the burden score is not offset by a strong scaffold. diff --git a/crates/mehen-markdown/tests/fixtures/halstead_mixed.md b/crates/mehen-markdown/tests/fixtures/halstead_mixed.md deleted file mode 100644 index 37fd1dd5..00000000 --- a/crates/mehen-markdown/tests/fixtures/halstead_mixed.md +++ /dev/null @@ -1,38 +0,0 @@ -# Halstead Mixed Fixture - -This fixture mixes many operator classes to exercise the Halstead operator -and operand table: headings, list markers, blockquote, link, image, table, -inline code, math, and punctuation. - -## Prose - -Regular prose. It ends with a period. - -## List - -- one -- two - -## Link And Image - -![alt text](./local.png) - -See [rust-lang](https://www.rust-lang.org). - -## Table - -| key | value | -|-----|-------| -| a | 1 | -| b | 2 | - -## Inline And Math - -Use `let x: i32 = 1;` inline. The energy is $E = mc^2$. - -## Fence With Language Tag - -```python -def foo(x): - return x * 2 -``` diff --git a/crates/mehen-markdown/tests/fixtures/heading_skip.md b/crates/mehen-markdown/tests/fixtures/heading_skip.md deleted file mode 100644 index 9a6acc8a..00000000 --- a/crates/mehen-markdown/tests/fixtures/heading_skip.md +++ /dev/null @@ -1,11 +0,0 @@ -# Top Heading - -Prose under the H1 heading. - -### Skipped To H3 - -The above H3 directly follows the H1 without an intervening H2. - -## Following H2 - -Final paragraph under the H2 that comes afterwards. diff --git a/crates/mehen-markdown/tests/fixtures/images_no_alt.md b/crates/mehen-markdown/tests/fixtures/images_no_alt.md deleted file mode 100644 index 938ef98c..00000000 --- a/crates/mehen-markdown/tests/fixtures/images_no_alt.md +++ /dev/null @@ -1,9 +0,0 @@ -# Images No Alt Fixture - -Two images below. The first has alt text but points at a missing file — -so `repo_resolved = 0` collapses its V_scaffold to zero. The second has -alt text and a repo-resolvable target. - -![broken](./missing-image.png) - -![alt here](code_fences.md "title") diff --git a/crates/mehen-markdown/tests/fixtures/links_mixed.md b/crates/mehen-markdown/tests/fixtures/links_mixed.md deleted file mode 100644 index 56abb4d2..00000000 --- a/crates/mehen-markdown/tests/fixtures/links_mixed.md +++ /dev/null @@ -1,29 +0,0 @@ -# Links Mixed Fixture - -Internal anchor to [Details](#details) and [Broken anchor](#missing). - -Relative to the fixture directory: [this file](links_mixed.md) and -[sibling](code_fences.md). Missing relative: [dead](nowhere.md). - -External to [example](https://example.com) and a bare URL: -. - -Issue / PR: [Ticket 42](https://github.com/foo/bar/issues/42). - -Scholarly: [DOI](https://doi.org/10.1/abc). - -Reference-style: [abc][abc-ref] and [missing][nope]. - -Footnote use[^1]. - -## Details - -Footnote body below. - -[abc-ref]: https://example.org - -[^1]: the explanation. - -## References - -- [MDN](https://developer.mozilla.org/en-US/) diff --git a/crates/mehen-markdown/tests/fixtures/long_linear_filler.md b/crates/mehen-markdown/tests/fixtures/long_linear_filler.md deleted file mode 100644 index 8ab39abe..00000000 --- a/crates/mehen-markdown/tests/fixtures/long_linear_filler.md +++ /dev/null @@ -1,302 +0,0 @@ -# Overview - -This document provides a broad introduction to the subject matter and offers -a general perspective on the topic at hand. The discussion aims to present -a comprehensive view without committing to any particular concrete example, -method, or implementation detail that might otherwise assist the reader in -understanding the practical applications of the ideas presented here. Instead -the narrative prefers a generic treatment that keeps the content accessible -to a wide audience and does not rely on specialized technical knowledge. - -The purpose of this introduction is to set the stage and convey the broader -context in which these ideas arise. We deliberately avoid overly concrete -references so that the writing remains broadly applicable. Readers seeking -specific pointers should therefore refer to subject-matter references in -other places. - -## Context and background - -The context in which these ideas emerged spans many years of ongoing thought -and gradual consensus forming across loosely coupled communities. Various -perspectives have contributed to the current understanding and numerous -discussions have shaped the way we think about the subject. These -perspectives include technical viewpoints, philosophical frameworks and -practical considerations that together inform the contemporary discussion. - -It is worth noting that different communities hold different perspectives -and that no single viewpoint captures the full picture. Each community -contributes unique insights and collectively the field benefits from this -diversity of thought. The resulting conversation is both rich and -multifaceted and it continues to evolve as new perspectives emerge. - -In this context the present writing draws on multiple traditions and seeks -to synthesize them into a coherent narrative that can serve as a useful -reference. However this synthesis is necessarily incomplete and readers -should treat it as one starting point among many. Additional reading and -engagement with primary sources is strongly encouraged for anyone seeking -a deeper understanding of the material. - -The background section is intended to set up the subsequent discussion and -to orient the reader to the central themes that will be developed in later -sections. It does so by surveying general terrain and by pointing out some -of the key issues that will receive more sustained attention later on. The -reader is invited to engage with this material at whatever level of depth -serves their particular interests. - -It is important to remember that documents of this kind are inherently -limited and that no single document can serve as a complete guide to every -aspect of the topic. Readers are therefore encouraged to consult additional -materials and to engage with the subject matter through multiple channels. -The present writing should be seen as one contribution among many and not -as a definitive statement on the topic. - -## General considerations - -There are many general considerations that apply to this kind of work and -that inform the decisions that have been made in assembling this material. -These considerations include matters of scope, matters of audience, matters -of tone and matters of emphasis. Each of these dimensions shapes the -resulting document in subtle but important ways and each deserves at least -brief acknowledgement before we proceed. - -Scope refers to the range of topics that the document attempts to cover. -A narrower scope allows for deeper treatment of each topic but sacrifices -breadth. A broader scope allows for more topics to be addressed but -necessarily requires more superficial treatment of each one. The scope of -this document has been chosen to strike a balance between these two poles -and to provide reasonable coverage of a representative set of topics -without going into exhaustive detail on any single one. - -Audience refers to the expected readership of the document and the level -of background knowledge that readers are assumed to possess. This document -is aimed at a general audience with some familiarity with the subject matter -but without any specific technical prerequisites. The writing style has -been chosen accordingly and the level of detail provided is intended to -be appropriate for this audience. Readers with more advanced backgrounds -may find some of the material overly basic and should feel free to skim -or skip sections that cover familiar territory. - -Tone refers to the overall voice and register of the writing. The tone -here is intended to be informative and neutral without being overly dry -or overly enthusiastic. The aim is to convey the material clearly and -without undue emphasis on any particular point of view. Readers should -feel that the document is a trustworthy guide to the material without -feeling that they are being lectured or persuaded. This balance is -difficult to maintain perfectly and readers may occasionally detect -traces of bias but the aim throughout has been to minimize such bias. - -Emphasis refers to which particular aspects of the topic receive more or -less attention in the document. Choices about emphasis inevitably reflect -the interests and background of the author and readers should be aware -that different authors would likely emphasize different aspects of the -same topic. The particular emphasis chosen here reflects a general -orientation toward practical applicability and accessibility and readers -seeking a different emphasis may want to consult other sources. - -Taken together these general considerations shape the document in various -ways and readers should keep them in mind as they work through the material. -It is sometimes helpful to reflect on these meta-level considerations -before diving into the substantive content because doing so can help -readers calibrate their expectations and make the most of the material. - -## Discussion - -The main body of the discussion addresses the central themes of the topic -in a loosely organized way that moves from more general considerations to -more particular ones. The discussion is not intended to be exhaustive and -readers should feel free to focus on whichever sections most closely align -with their interests. Connections between sections are highlighted where -they are relevant but no attempt has been made to produce a strictly -hierarchical or linear argument. - -Throughout the discussion we rely primarily on prose rather than on more -structured forms of presentation. This choice reflects the nature of the -material and the aims of the document but it does mean that readers who -prefer more structured formats may find some sections harder to navigate. -Where structure would have been particularly helpful we have tried to -provide clear topic sentences and to signpost transitions but the overall -organization remains relatively loose. - -The topics addressed in this section include general background material, -some broad considerations that apply across the subject area, and a number -of particular observations that we think are especially worth highlighting. -Each of these topics is addressed in turn and each receives roughly equal -attention in the discussion. Readers who are more interested in some -topics than others may wish to adjust their reading accordingly but we -hope that the overall treatment provides a balanced perspective. - -We begin by considering some general background material that situates -the subsequent discussion. This material covers a wide range of considerations -and readers should not expect any particular point to be addressed in -exhaustive detail. Instead the aim is to provide enough context that -readers will be able to follow the subsequent discussion without undue -difficulty. Readers seeking more comprehensive background are encouraged -to consult other sources. - -Having set the stage with some general background we then turn to some -broader considerations that apply across the subject area. These -considerations include matters of methodology, matters of interpretation, -and matters of application. Each of these areas is treated at some length -although the treatment is necessarily superficial given the broad scope -of the document. Readers seeking more specialized treatment are encouraged -to consult the references section or to explore related literature -independently. - -After addressing these broader considerations we turn to some particular -observations that we believe are especially worth highlighting. These -observations are not meant to be definitive conclusions but rather to -point toward areas that we think merit further attention. Readers may -find that they agree with some of these observations and disagree with -others and that is to be expected. The aim here is not to persuade but -to invite further reflection. - -The overall discussion in this section is relatively long and readers may -find it helpful to break their reading up into multiple sessions rather -than attempting to work through the whole thing in a single sitting. The -material is not particularly difficult but there is a lot of it and -sustained engagement is likely to be more productive than rapid consumption. -Readers should feel free to set the document aside periodically and to -return to it when they have time for further reflection. - -## Further thoughts - -Beyond the material addressed in the main discussion there are a number -of further thoughts and observations that did not fit neatly into the -earlier sections but that nonetheless seemed worth including. These -further thoughts are presented here in a relatively unstructured way -and readers should feel free to engage with them selectively rather than -attempting to work through them systematically. - -The first further thought concerns the relationship between different -aspects of the topic and the ways in which these aspects inform one -another. There is considerable complexity in these relationships and -a full treatment would require much more space than we have available -here. For present purposes we simply note that these relationships -exist and that they are worth bearing in mind as readers work through -the material. - -A second further thought concerns the implications of the material for -practice and for future work. While we have tried to provide some -practical guidance throughout the document the primary aim has been -descriptive rather than prescriptive. Readers seeking more specific -practical guidance should consult other sources or engage directly with -practitioners in the relevant fields. The present document is intended -to provide general orientation rather than specific recommendations. - -A third further thought concerns the limitations of the present treatment -and the many topics that have not been addressed. No document of this -kind can hope to cover every relevant topic and readers should be aware -that significant omissions are inevitable. We have tried to be -transparent about the scope of the discussion and to signal where -readers might look for material that has not been included here. However -we recognize that readers may have different priorities and that the -omissions that seem minor to us may be significant to them. - -A fourth further thought concerns the broader context in which the -material is situated and the connections to adjacent areas of inquiry. -Although we have tried to draw such connections where they seem especially -relevant we have necessarily had to limit our treatment of adjacent -areas in order to keep the document to a manageable size. Readers -interested in these connections are encouraged to explore related -literature independently and to draw their own conclusions about the -relationships between the material covered here and other areas of -inquiry. - -A fifth further thought concerns the ongoing evolution of the subject -matter and the ways in which the present document is likely to become -dated. Fields of inquiry evolve over time and what seems current today -may look outdated in a few years. We have tried to focus on relatively -stable aspects of the topic but some portions of the document will -inevitably become less relevant as the field continues to evolve. -Readers using the document some time after its original preparation -should bear this in mind and should supplement the material here with -more current sources as appropriate. - -## Conclusion - -The preceding discussion has surveyed the subject in broad strokes and -offered some general observations about the material. While the -discussion has been relatively long it has necessarily been superficial -in many places and readers should not take the present document as a -substitute for deeper engagement with the source material. Instead the -aim has been to provide an accessible entry point and to orient readers -to the broader terrain. Readers seeking more depth are encouraged to -consult primary sources and specialized references. - -The material is intended to serve as a starting point for further -exploration rather than as a definitive treatment. Readers are encouraged -to bring their own perspectives to the material and to form their own -views about the topics addressed. We have tried to present the material -fairly and to acknowledge different perspectives where they are relevant -but we recognize that our treatment reflects our own perspective and -priorities in various ways. - -Thank you for reading. We hope that the document has been useful and -that it has provided a helpful orientation to the topic. If you have -questions or feedback we would be interested to hear them although we -may not be able to respond to every comment in detail. Further -discussions of the material may be found in various venues and readers -are encouraged to seek them out as appropriate. - -## Appendix - -This appendix provides additional material that did not fit into the -main body of the discussion but that some readers may find useful. -The appendix covers a variety of topics in a somewhat unstructured way -and readers should feel free to engage with the material selectively -rather than attempting to work through it systematically. - -The first appendix topic concerns questions of style and presentation -that were briefly mentioned earlier in the document but that deserve -further elaboration. Style is often underappreciated in technical -writing and decisions about presentation can have significant effects -on how material is received and understood. We offer here some further -thoughts on style choices that informed the present document and some -suggestions that readers may find helpful when preparing their own -material. These suggestions are not meant to be prescriptive but rather -to offer one perspective among many. - -The second appendix topic concerns considerations about accessibility -and inclusion that are increasingly important in contemporary writing. -Writers should be mindful of the language they use and should make -conscious choices to ensure that their material is accessible to as -wide an audience as possible. This includes attention to the vocabulary -used as well as attention to the cultural references and assumptions -embedded in the writing. There are many resources available for writers -who want to improve in this area and readers are encouraged to seek -them out and to engage with them thoughtfully. - -The third appendix topic concerns questions of revision and iteration -in the writing process. Good writing is rarely produced in a single -pass and most documents benefit from multiple rounds of revision and -refinement. We have tried to apply this principle to the present -document and we have gone through multiple drafts in preparing it for -publication. However we recognize that further revisions would likely -continue to improve the material and that the document as it stands -is not the final word on the topic. - -The fourth appendix topic concerns the broader community of writers -and practitioners who work on similar material. This is a lively and -diverse community that includes people from many different backgrounds -and with many different interests. Readers who want to engage more -deeply with the material are encouraged to connect with this community -through conferences workshops online forums and other venues. The -community can be a valuable source of support and guidance for anyone -seeking to develop their understanding of the topic further. - -The fifth and final appendix topic concerns the relationship between -theory and practice in the field. There is often a tension between -theoretical and practical concerns and different writers place different -emphases on these two dimensions. The present document has tried to -maintain a balance between theory and practice but readers with stronger -preferences for one or the other may find the balance imperfect for -their own needs. Readers seeking more theoretical treatment or more -practical guidance are encouraged to consult the respective literatures. - -We close with a brief acknowledgement of the many people and resources -that have contributed to the present document in various ways. While -we have not named specific contributors here we are grateful for the -many conversations readings and interactions that have informed our -thinking. Any errors that remain are our own responsibility but the -strengths of the document reflect the collective contributions of -many others. diff --git a/crates/mehen-markdown/tests/fixtures/mixed_bilingual.md b/crates/mehen-markdown/tests/fixtures/mixed_bilingual.md deleted file mode 100644 index 4d950fba..00000000 --- a/crates/mehen-markdown/tests/fixtures/mixed_bilingual.md +++ /dev/null @@ -1,24 +0,0 @@ -# Bilingual Documentation Sample - -このドキュメントは英語と日本語の両方で書かれています。バイリンガルな構成のテスト用サンプルです。 - -## English Section - -The following paragraphs demonstrate how per-block language detection works -across heading boundaries. Each paragraph is classified independently so a -single document can hold multiple locales without losing fidelity. - -Software documentation frequently mixes English prose with Japanese commentary, -especially in internationalization guides and migration notes. - -## 日本語セクション - -この段落は日本語で書かれています。検出器はひらがなとカタカナの比率を確認して、ブロック単位で言語を判定します。 - -複数のブロックに日本語が含まれている場合でも、各ブロックが独立して分類されるため、適切な読みやすさメトリックを計算できます。 - -## Shared Conclusions - -The mehen analyzer reports both English and Japanese metrics when a document -is bilingual. The overall document-level language is labeled `mixed` and each -block carries its own classification in the output. diff --git a/crates/mehen-markdown/tests/fixtures/navigation_heavy.md b/crates/mehen-markdown/tests/fixtures/navigation_heavy.md deleted file mode 100644 index 3d9f513b..00000000 --- a/crates/mehen-markdown/tests/fixtures/navigation_heavy.md +++ /dev/null @@ -1,29 +0,0 @@ -# Navigation Heavy Fixture - -This fixture exercises §7 MRPC: many sections, internal anchors, relative -repo links, external links across multiple domains, and footnote / reference -definitions. - -## Overview - -See the [installation](#install) and [usage](#usage) sections below, and the -[architecture doc](./architecture.md#runtime) for deeper context. - -## Install - -Install guide: follow [official docs](https://docs.example.com/install), -then run the [setup script](../scripts/setup.sh) as described in -[contributing](../CONTRIBUTING.md). - -## Usage - -See [quickstart](./quickstart.md) and the [API reference][api-ref] for -details. Further reading: [vendor-a](https://vendor-a.com/api), -[vendor-b](https://vendor-b.org), [vendor-c](https://vendor-c.io). - -More context in [^1] and [^2]. - -[^1]: Source: _The Architecture Handbook_, 3rd edition. -[^2]: Related ADR: [adr-007](./adr/007.md). - -[api-ref]: https://api.example.com/reference diff --git a/crates/mehen-markdown/tests/fixtures/near_duplicate_paragraphs.md b/crates/mehen-markdown/tests/fixtures/near_duplicate_paragraphs.md deleted file mode 100644 index 1ac47e3c..00000000 --- a/crates/mehen-markdown/tests/fixtures/near_duplicate_paragraphs.md +++ /dev/null @@ -1,27 +0,0 @@ -# Overview of the analyzer service - -The analyzer service is a stateless process that receives document text from the dispatcher and returns metric records computed from that text. It runs as a containerized workload and scales horizontally based on queue depth. Operators manage it through the standard platform tooling. - -The analyzer service is a stateless process that receives document text from the dispatcher and returns metric records computed from that content. It runs as a containerized workload and scales horizontally based on queue depth. Operators manage it through the standard platform tooling. - -## Configuration - -The configuration file lives at a well known path and is read once at process startup. Any changes to the file take effect after a restart of the service. The file follows the standard YAML format and is validated against a schema at load time. - -The configuration file lives at a well known path and is read once at process startup. Any changes to the file take effect after a restart of the service. The file follows the standard YAML format and is validated against a schema at load time. - -## Deployment - -Deployments follow the standard platform flow for containerized services. The image is built during the release pipeline and pushed to the internal registry. Each deploy creates a new rollout and waits for health probes to pass before marking the rollout complete. - -Deployments follow the standard platform flow for containerized services. The image is built during the release pipeline and pushed to the internal registry. Each deploy creates a new rollout and waits for health probes to succeed before marking the rollout complete. - -## Monitoring - -Metrics are emitted from the analyzer process using the standard client library. Dashboards visualize request rates, error rates, and latency distributions. Alerts fire when error rates exceed configured thresholds or when latency percentiles drift outside expected ranges. - -Logs are structured JSON and are aggregated through the central logging infrastructure. Traces are emitted through the standard tracing library and allow operators to follow request flow across services. - -## Security - -Access to the analyzer is controlled through the standard authentication layer. Requests must carry a valid authentication token or they are rejected with an HTTP 401 response. Rate limits apply per tenant and are enforced at the ingress layer rather than inside the analyzer itself. diff --git a/crates/mehen-markdown/tests/fixtures/passive_heavy.md b/crates/mehen-markdown/tests/fixtures/passive_heavy.md deleted file mode 100644 index 3970681b..00000000 --- a/crates/mehen-markdown/tests/fixtures/passive_heavy.md +++ /dev/null @@ -1,22 +0,0 @@ -# Passive-Heavy Document - -The configuration is loaded by the bootstrap routine. The state is maintained -by the coordinator. Values are stored in the primary cache. Errors are logged -by the instrumentation layer. - -Connections are managed by a pool. Requests are routed by the dispatcher. -Responses are serialized by the encoder. Failed operations are retried by -the fault handler. - -The primary datastore is backed by a replicated key-value store. Writes are -committed through a quorum mechanism. Reads are served from the nearest -replica. Consistency is guaranteed by a vector-clock algorithm. - -Queue messages are consumed by worker threads. Each task is processed in a -dedicated goroutine. Results are published back to the coordinator. Failures -are recorded in the audit log. Partial successes are reconciled by a -background job. - -Temporary data is garbage-collected periodically. Expired entries are evicted -by the LRU policy. Free slots are reclaimed by the compaction routine. Disk -space is monitored by the operator. diff --git a/crates/mehen-markdown/tests/fixtures/placeholder_heavy.md b/crates/mehen-markdown/tests/fixtures/placeholder_heavy.md deleted file mode 100644 index dfab5bcc..00000000 --- a/crates/mehen-markdown/tests/fixtures/placeholder_heavy.md +++ /dev/null @@ -1,58 +0,0 @@ -# Draft runbook - -This runbook is a work in progress. Many sections are TODO and should be -filled out before production use. - -## Preflight - -TODO: describe preflight checks. We need to cover at least the following -items before deploy: - -- TODO: verify build artifact exists -- FIXME: add link to the build pipeline -- TBD: owner of the preflight step - -See [the CI dashboard](TBD) for the latest run status. Related docs: -[incident response](TODO) and [rollback flow](FIXME). - -## Deploy - -TODO: write the deploy procedure. The `deploy.sh` script is a placeholder -and will be rewritten before this runbook is finalised. XXX: the current -script does not handle the `staging` environment correctly. - -Sample placeholder: lorem ipsum dolor sit amet, consectetur adipiscing -elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. - -## Health checks - -FIXME: document the health check endpoints. Owner: TBD. Target completion -date: TBD. - -## Rollback - -TODO: describe the rollback path. The previous runbook had a diagram -here but it has been removed as a placeholder. - -See also [historical rollback notes](TBD) and [postmortems](TODO). - -## Troubleshooting - -TODO: fill in common troubleshooting steps. The placeholder section below -captures a few ideas but none of them have been verified. - -### Slow response times - -FIXME: add specifics. This section is a placeholder. - -### High error rates - -TODO: document the error budget and the alert thresholds. - -## References - -- TODO: link to the deploy pipeline -- FIXME: link to the monitoring dashboard -- TBD: link to the security review -- [placeholder entry](TBD) -- [another placeholder]() diff --git a/crates/mehen-markdown/tests/fixtures/pure_prose.md b/crates/mehen-markdown/tests/fixtures/pure_prose.md deleted file mode 100644 index c886530d..00000000 --- a/crates/mehen-markdown/tests/fixtures/pure_prose.md +++ /dev/null @@ -1,7 +0,0 @@ -# Pure Prose Fixture - -This paragraph contains ten words of ordinary English prose content. - -Another paragraph follows, with seven simple prose words. - -A final paragraph concludes the fixture with five words. diff --git a/crates/mehen-markdown/tests/fixtures/readme_en.md b/crates/mehen-markdown/tests/fixtures/readme_en.md deleted file mode 100644 index 5debcdf0..00000000 --- a/crates/mehen-markdown/tests/fixtures/readme_en.md +++ /dev/null @@ -1,32 +0,0 @@ -# My Project - -This library helps developers manage distributed state across service -boundaries. It is designed for high-throughput scenarios and supports -multiple consensus protocols. - -## Installation - -Install the package using your preferred package manager. The library has -no external dependencies and works on every major platform. - -## Usage - -Start by creating a new client instance. Pass the configuration object -that contains your endpoint and authentication credentials. The client -manages connection lifecycle automatically. - -Retrieve values with the standard getter. Commit changes through the -writer. Every operation returns a result that you can inspect for errors. - -## Contributing - -We welcome contributions from the community. Please read the contributing -guide before opening a pull request. All code must include unit tests. - -Bug reports should include a minimal reproduction. Feature requests must -describe the use case in enough detail that a stranger can implement it. - -## License - -The project is released under the Apache 2.0 license. See the LICENSE file -for the complete text. diff --git a/crates/mehen-markdown/tests/fixtures/readme_ja.md b/crates/mehen-markdown/tests/fixtures/readme_ja.md deleted file mode 100644 index 101fa960..00000000 --- a/crates/mehen-markdown/tests/fixtures/readme_ja.md +++ /dev/null @@ -1,23 +0,0 @@ -# プロジェクト概要 - -このライブラリは分散サービス間の状態管理を支援します。高スループットのシナリオ向けに設計され、複数のコンセンサスプロトコルをサポートします。 - -## インストール - -お使いのパッケージマネージャーを利用してインストールしてください。外部依存関係はなく、主要なプラットフォームすべてで動作します。 - -## 使い方 - -クライアントインスタンスを作成することから始めます。エンドポイントと認証情報を含む設定オブジェクトを渡してください。クライアントは接続ライフサイクルを自動的に管理します。 - -標準のゲッターで値を取得できます。ライターを通じて変更をコミットしてください。各操作は結果を返すため、エラーを確認できます。 - -## コントリビューション - -コミュニティからのコントリビューションを歓迎いたします。プルリクエストを作成する前に、コントリビューションガイドをご確認ください。すべてのコードには単体テストを含める必要があります。 - -バグレポートには最小限の再現方法を含めてください。機能要求については、実装者が利用シーンを理解できる十分な詳細を記述してください。 - -## ライセンス - -本プロジェクトはApache 2.0ライセンスのもとで公開されています。完全なテキストはLICENSEファイルをご参照ください。 diff --git a/crates/mehen-markdown/tests/fixtures/short_doc.md b/crates/mehen-markdown/tests/fixtures/short_doc.md deleted file mode 100644 index 994be24e..00000000 --- a/crates/mehen-markdown/tests/fixtures/short_doc.md +++ /dev/null @@ -1,4 +0,0 @@ -# Short Note - -This is a very short document. It contains only a few words. -Less than one hundred for sure. Maybe forty. diff --git a/crates/mehen-markdown/tests/fixtures/small_dense_valuable.md b/crates/mehen-markdown/tests/fixtures/small_dense_valuable.md deleted file mode 100644 index cb228f26..00000000 --- a/crates/mehen-markdown/tests/fixtures/small_dense_valuable.md +++ /dev/null @@ -1,139 +0,0 @@ -# Deployment runbook - -Operators run this playbook to deploy the `mehen-core` service to the -`us-east-1` region. The runbook assumes the operator has push access to -[`ophidiarium/mehen`](../README.md) and AWS credentials configured for the -`mehen-deploy` IAM role (version 1.4.2 or later). - -## Preflight - -Check that the current commit builds cleanly: - -```bash -cargo check --all-features --locked -cargo clippy --all-targets --all-features --locked -- -D warnings -``` - -Confirm that the last release passed CI: - -```bash -gh run list --branch main --limit 5 --json status,conclusion -``` - -If CI shows red, stop here and open an issue linking the run id. - -## Apply the migration - -The schema migration lives in [`migrations/0018_docs_index.sql`](../README.md). -Apply it to the staging database first: - -```sh -psql "$MEHEN_STAGING_URL" -f migrations/0018_docs_index.sql -``` - -Verify the new index: - -```sql -SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'docs'; -``` - -You should see `docs_text_idx` in the result set. If the index is missing, -roll back with `migrations/0018_docs_index.down.sql` before proceeding. - -## Promote the build - -Trigger a new release build. The Docker image tag follows semver -(`v0.5.0`, `v0.5.1`, …): - -```sh -./scripts/release.sh v0.5.0 -``` - -The script runs `cargo build --release --locked`, tags the image with -`ghcr.io/ophidiarium/mehen:v0.5.0`, and pushes it to the registry. It also -updates the `deploy/staging/kustomization.yaml` manifest to pin the new -image digest. - -## Verify rollout - -After the staging deploy completes, confirm health with: - -```bash -curl -sf https://staging.mehen.example.com/healthz -``` - -The endpoint should return `200 OK` with the JSON body: - -```json -{"version":"0.5.0","git":"abcdef1","ready":true} -``` - -## Rollback - -If the `/healthz` check fails within 10 minutes, run: - -```bash -./scripts/rollback.sh v0.4.3 -``` - -See also [`docs/mehen_markdown_metrics_research_foundation.md`](../docs/mehen_markdown_metrics_research_foundation.md) -for the metric thresholds the rollout dashboard uses. - -## Configuration reference - -The service reads configuration from `/etc/mehen/config.yaml`. The file -must define these keys: - -```yaml -database_url: postgres://mehen@db.internal/mehen -redis_url: redis://cache.internal:6379/0 -log_level: info -listen_port: 8080 -metrics: - enabled: true - bind: 0.0.0.0:9090 -features: - experimental_diff: false -``` - -The `listen_port` setting defaults to `8080` when unset. Override it via -`MEHEN_LISTEN_PORT` for ephemeral staging runs. See also -[`config/defaults.yaml`](../README.md) for the baseline values. - -Known API endpoints exposed by this service: - -- `GET /healthz` — liveness probe (returns `200 OK`). -- `GET /readyz` — readiness probe (returns `200 OK` after warmup). -- `POST /v1/analyze` — primary document analysis API. -- `GET /metrics` — Prometheus scrape endpoint. - -## Troubleshooting - -If the deploy stalls, inspect the pod logs with `kubectl logs` and grep for -`ERROR`: - -```sh -kubectl -n mehen logs deploy/mehen-core | grep -F ERROR | head -n 20 -``` - -Common causes and remedies: - -| Symptom | Likely cause | Fix | -|---------|--------------|-----| -| `OOMKilled` | Memory limit too low for v0.5.0 | Raise `resources.limits.memory` to `512Mi` | -| `connect ECONNREFUSED` | Pod can't reach Redis | Check `NetworkPolicy` | -| `timeout 5s` on `/v1/analyze` | Document too large | Increase `timeout_secs: 30` | -| `permission denied` on `/etc/mehen/config.yaml` | Wrong secret mount | Reapply `helm upgrade --install mehen-core` | - -Tracking issue: https://github.com/ophidiarium/mehen/issues/12345 -See also https://github.com/ophidiarium/mehen/issues/12346 for the related -follow-up. - -## References - -| Runbook | Purpose | Owner | -|---------|---------|-------| -| `deploy.md` | Primary deploy path | `@platform` | -| `rollback.md` | Rollback procedure | `@platform` | -| `incident.md` | Incident response | `@sre` | -| `config.md` | Config reference | `@platform` | diff --git a/crates/mehen-markdown/tests/fixtures/table_large.md b/crates/mehen-markdown/tests/fixtures/table_large.md deleted file mode 100644 index 73d650b5..00000000 --- a/crates/mehen-markdown/tests/fixtures/table_large.md +++ /dev/null @@ -1,14 +0,0 @@ -# Table Large Fixture - -Below is a deliberately wide and long table. It should trigger the §13 -hard-warning flag (cells > 300 or cols > 12 or rows > 100), drive the -per-table burden score high, and drop the scaffold score. - -| a | b | c | d | e | f | g | h | i | j | k | l | m | -|---|---|---|---|---|---|---|---|---|---|---|---|---| -| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | diff --git a/crates/mehen-markdown/tests/fixtures/table_mixed.md b/crates/mehen-markdown/tests/fixtures/table_mixed.md deleted file mode 100644 index f69db293..00000000 --- a/crates/mehen-markdown/tests/fixtures/table_mixed.md +++ /dev/null @@ -1,10 +0,0 @@ -# Table Mixed Fixture - -Prose introduces a small pipe table below. - -| Column A | Column B | Column C | -|----------|:--------:|---------:| -| row one | value | 1 | -| row two | other | 2 | - -Trailing prose after the table. diff --git a/crates/mehen-markdown/tests/fixtures/tateishi_sample.md b/crates/mehen-markdown/tests/fixtures/tateishi_sample.md deleted file mode 100644 index 4a18afaf..00000000 --- a/crates/mehen-markdown/tests/fixtures/tateishi_sample.md +++ /dev/null @@ -1,23 +0,0 @@ -# 日本語読みやすさテスト - -このサンプルは立石らの読みやすさ公式を評価するために用意された文章です。技術文書の典型的な書き方を模倣し、漢字とひらがな、カタカナ、半角英数字の適切な混合比率を保っています。 - -## 目的 - -立石らの読みやすさ公式は、文章の構成要素を統計的に分析することで、読者にとっての難易度を数値化する手法です。漢字の連続長、ひらがなの比率、文の長さなどが主要な入力値となります。 - -## 背景 - -日本語の文章は、英語と異なり、単語境界が表面上は存在しません。したがって、形態素解析を用いない Tier-0 実装では、スクリプトランを擬似的な単語境界として利用します。 - -## 結論 - -立石の簡略式は形態素解析を必要としない点で、mehen の Tier-0 方針と整合性があります。辞書データを同梱する必要がないため、バイナリサイズが小さく保たれます。カタカナ複合語、例えばコンピューター、データベース、サーバー、インターフェースなども適切に計測されます。 - -## 補足 - -Tateishi の公式の出力は平均50、標準偏差10にキャリブレーションされており、値が大きいほど読みやすいことを示します。mehen では簡略式を採用し、形態素解析ライブラリに依存せずに推定値を提供します。 - -## 今後の展望 - -将来の拡張として、Lindera や Vibrato などの形態素解析器を組み込むことで、jReadability や芝崎の予測式にも対応する予定です。ただし、これらはオプトインのフィーチャーフラグとして提供されます。 diff --git a/crates/mehen-markdown/tests/fixtures/tight_list.md b/crates/mehen-markdown/tests/fixtures/tight_list.md deleted file mode 100644 index 136c2efc..00000000 --- a/crates/mehen-markdown/tests/fixtures/tight_list.md +++ /dev/null @@ -1,8 +0,0 @@ -# Grocery list - -- Apples -- Oranges -- Bananas -- Pears - -Do not forget the fruit. diff --git a/crates/mehen-markdown/tests/fixtures/weak_phrase_ja.md b/crates/mehen-markdown/tests/fixtures/weak_phrase_ja.md deleted file mode 100644 index 97620ecb..00000000 --- a/crates/mehen-markdown/tests/fixtures/weak_phrase_ja.md +++ /dev/null @@ -1,15 +0,0 @@ -# 弱い表現を多く含む日本語文書 - -この文書には弱い表現が多く含まれているかもしれません。おそらくこの機能は動作すると思います。多分、すべてのケースで正常にふるまうでしょう。 - -## 詳細 - -ほぼすべてのテストがパスしているようです。もしかすると一部のエッジケースで問題が発生する可能性があります。的な表現が散見される文書として設計されています。 - -## 実装 - -することができるコードをすることができない場合に備えて、代替処理を用意しています。のほうが読みやすいかもしれないとも考えられます。 - -## 結論 - -本実装はおおむね動作すると思われます。ただし、データ量がかなり大きい場合には処理時間が長くなる可能性があります。 diff --git a/crates/mehen-markdown/tests/markdown.rs b/crates/mehen-markdown/tests/markdown.rs deleted file mode 100644 index 0de171c4..00000000 --- a/crates/mehen-markdown/tests/markdown.rs +++ /dev/null @@ -1,751 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Snapshot tests for the Markdown pipeline (Phase A + Phase B + Phase C + -//! Phase E). -//! -//! Each fixture under `fixtures/` exercises a distinct aspect of the -//! analyzer so regressions in any single dimension (LOC bucket, word count, -//! section tree, ECU, MRPC graph weight, MCC penalty, Halstead class -//! coverage, DMI normalization, link class, table burden, diagram -//! complexity, artifact debt, prose EN/JA readability and wording) surface -//! as an isolated snapshot diff. - -use std::path::PathBuf; - -use mehen_markdown::analyze_markdown; -use mehen_markdown::diagrams; - -/// Register the embedded-code dispatch once per test process. -/// -/// Tests that exercise fenced-code metrics need a real -/// `volume`/`cognitive_sum`/`sloc` for each fence body. The dispatch -/// callback is registered globally via `OnceLock`, so multiple `init` -/// calls are idempotent. -fn ensure_dispatch() { - mehen_engine::init_markdown(); -} - -fn load_fixture(name: &str) -> (String, PathBuf) { - let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - path.push("tests/fixtures"); - path.push(name); - let contents = - std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("reading fixture {name}: {e}")); - (contents, path) -} - -fn assert_fixture_snapshot(name: &str) { - ensure_dispatch(); - let (source, path) = load_fixture(name); - let metrics = analyze_markdown(&source, &path); - // Redact the absolute path so snapshots are portable across workspaces. - insta::with_settings!({ - snapshot_suffix => name, - omit_expression => true, - }, { - insta::assert_yaml_snapshot!(metrics, { - ".path" => "" - }); - }); -} - -#[test] -fn empty_fixture() { - assert_fixture_snapshot("empty.md"); -} - -#[test] -fn pure_prose_fixture() { - assert_fixture_snapshot("pure_prose.md"); -} - -#[test] -fn code_fences_fixture() { - assert_fixture_snapshot("code_fences.md"); -} - -#[test] -fn fenced_code_fixture_metrics_are_crlf_stable() { - ensure_dispatch(); - for name in [ - "artifact_debt_high.md", - "code_fences.md", - "diagram_heavy_scaffolded.md", - "diagram_mermaid.md", - "diagram_parse_error.md", - "embedded_code_large.md", - "halstead_mixed.md", - "small_dense_valuable.md", - ] { - let (source, path) = load_fixture(name); - let lf_source = source.replace("\r\n", "\n").replace('\r', "\n"); - let crlf_source = lf_source.replace('\n', "\r\n"); - let lf_metrics = analyze_markdown(&lf_source, &path); - let crlf_metrics = analyze_markdown(&crlf_source, &path); - assert_eq!( - serde_json::to_value(crlf_metrics).expect("serializing CRLF metrics"), - serde_json::to_value(lf_metrics).expect("serializing LF metrics"), - "{name} metrics should be stable under CRLF line endings" - ); - } -} - -#[test] -fn table_mixed_fixture() { - assert_fixture_snapshot("table_mixed.md"); -} - -#[test] -fn frontmatter_fixture() { - assert_fixture_snapshot("frontmatter.md"); -} - -#[test] -fn heading_skip_fixture() { - assert_fixture_snapshot("heading_skip.md"); -} - -#[test] -fn tight_list_fixture() { - // Tight bullet lists land in the `list_item` container without a - // paragraph child. LOC classification must count them as PLOC; if a - // future regression drops ListItem from the prose arm they fall - // through to Blank and land in BLOC instead. - assert_fixture_snapshot("tight_list.md"); -} - -#[test] -fn navigation_heavy_fixture() { - // Exercises §7 MRPC: many sections, internal anchors, relative - // repo links, external links across multiple domains, and - // footnote/reference definitions. - assert_fixture_snapshot("navigation_heavy.md"); -} - -#[test] -fn cognitive_cluster_fixture() { - // Exercises §8 MCC penalties: unlabelled code, dense links, nested - // lists, blockquote, callout. - assert_fixture_snapshot("cognitive_cluster.md"); -} - -#[test] -fn halstead_mixed_fixture() { - // Exercises §9 Halstead operator/operand classes. - assert_fixture_snapshot("halstead_mixed.md"); -} - -#[test] -fn deep_nesting_fixture() { - // Exercises §8.2 nesting multiplier — lists, blockquotes, callouts - // interleaved. - assert_fixture_snapshot("deep_nesting.md"); -} - -#[test] -fn embedded_code_large_fixture() { - // Exercises §9.4 embedded-volume dispatch across Rust / Python / TS; - // unsupported fences (sql) must not contribute. - assert_fixture_snapshot("embedded_code_large.md"); -} - -#[test] -fn links_mixed_fixture() { - // Exercises every §11.1 link class: internal anchor (resolving + not), - // relative file (resolving + not), external (and bare URL), IssuePR, - // Scholarly, ExternalVendor, reference-definition, shortcut reference, - // and footnote. The aggregate link_debt / scent / review_burden pin - // the §11.2–§11.4 formulas. - assert_fixture_snapshot("links_mixed.md"); -} - -#[test] -fn broken_links_fixture() { - // High broken-rate case: drives link_debt_score past the 0.10 sat - // threshold. - assert_fixture_snapshot("broken_links.md"); -} - -#[test] -fn table_large_fixture() { - // Hard-warning table per §13: cols > 12 so the burden score dominates - // the aggregate. - assert_fixture_snapshot("table_large.md"); -} - -#[test] -fn diagram_mermaid_fixture() { - // Codifies the §12.2 two-node cycle invariant. - assert_fixture_snapshot("diagram_mermaid.md"); -} - -#[test] -fn diagram_parse_error_fixture() { - // Unknown language ("tikz") flips parse_error, adding the +2.0 term. - assert_fixture_snapshot("diagram_parse_error.md"); -} - -#[test] -fn images_no_alt_fixture() { - // One image without alt-text + missing target vs. one with alt and a - // resolving target — pins the V_scaffold asymmetry. - assert_fixture_snapshot("images_no_alt.md"); -} - -#[test] -fn artifact_debt_high_fixture() { - // Several unlabelled fences, a parse-error diagram, and raw HTML. - assert_fixture_snapshot("artifact_debt_high.md"); -} - -#[test] -fn long_linear_filler_fixture() { - // §24.1 scenario: long (2,500+ words), shallow linear prose with - // no code, links, tables, or diagrams. Expected outcome per the - // foundation doc's §24 is `FillerLazyRisk > 0.6`, high DMI (simple - // structure), and low RCI. - let (source, path) = load_fixture("long_linear_filler.md"); - let metrics = analyze_markdown(&source, &path); - assert!( - metrics.ai_era.filler_lazy_structure_risk > 0.6, - "expected FillerLazyRisk > 0.6, got {}", - metrics.ai_era.filler_lazy_structure_risk - ); - assert!( - metrics.review.review_criticality_index < 50.0, - "expected RCI < 50, got {}", - metrics.review.review_criticality_index - ); - assert_fixture_snapshot("long_linear_filler.md"); -} - -#[test] -fn small_dense_valuable_fixture() { - // §24.2 scenario: short but dense doc with code, tables, and relative - // links. FillerLazyRisk should be low; RCI high relative to DMI. - let (source, path) = load_fixture("small_dense_valuable.md"); - let metrics = analyze_markdown(&source, &path); - assert!( - metrics.ai_era.filler_lazy_structure_risk < 0.30, - "expected FillerLazyRisk < 0.30, got {}", - metrics.ai_era.filler_lazy_structure_risk - ); - assert_fixture_snapshot("small_dense_valuable.md"); -} - -#[test] -fn diagram_heavy_scaffolded_fixture() { - // §24.3 scenario: 5 mermaid diagrams with captions and nearby prose. - // VisualScaffoldScore should be high; VisualNetEffect negative (net - // help). - let (source, path) = load_fixture("diagram_heavy_scaffolded.md"); - let metrics = analyze_markdown(&source, &path); - assert!( - metrics.visuals.visual_scaffold_score > 0.5, - "expected VisualScaffoldScore > 0.5, got {}", - metrics.visuals.visual_scaffold_score - ); - assert_fixture_snapshot("diagram_heavy_scaffolded.md"); -} - -#[test] -fn giant_table_debt_fixture() { - // §24.4 scenario: 800+ cell table → TableBurdenScore dominates the - // aggregate. Phase C's §13.3 formula caps each penalty at 0.25 and a - // single-table doc therefore tops out near 0.56 in practice (§24.4's - // 0.93 expectation assumes stacked penalty contributions from - // multiple bad tables — a future tuning pass). What we can pin - // today is that the single giant table trips the hard-warning and - // drags the DMI down meaningfully. - let (source, path) = load_fixture("giant_table_debt.md"); - let metrics = analyze_markdown(&source, &path); - assert!( - metrics.tables.table_burden_score > 0.5, - "expected TableBurdenScore > 0.5, got {}", - metrics.tables.table_burden_score - ); - assert!( - metrics.tables.hard_warnings >= 1, - "expected hard-warning tables, got {}", - metrics.tables.hard_warnings - ); - assert_fixture_snapshot("giant_table_debt.md"); -} - -#[test] -fn near_duplicate_paragraphs_fixture() { - // §17.5 repetition density — 3 pairs of Jaccard ≥ 0.82 paragraphs. - // `ai_era.labels` must contain `near-duplicate-paragraphs`. - let (source, path) = load_fixture("near_duplicate_paragraphs.md"); - let metrics = analyze_markdown(&source, &path); - assert!( - metrics - .ai_era - .labels - .iter() - .any(|l| l == "near-duplicate-paragraphs"), - "expected `near-duplicate-paragraphs` label, got {:?}", - metrics.ai_era.labels - ); - assert_fixture_snapshot("near_duplicate_paragraphs.md"); -} - -#[test] -fn placeholder_heavy_fixture() { - // §17.8 placeholder density — TODO/TBD/FIXME scattered throughout. - // `ai_era.labels` must contain `placeholder-heavy`. - let (source, path) = load_fixture("placeholder_heavy.md"); - let metrics = analyze_markdown(&source, &path); - assert!( - metrics - .ai_era - .labels - .iter() - .any(|l| l == "placeholder-heavy"), - "expected `placeholder-heavy` label, got {:?}", - metrics.ai_era.labels - ); - assert_fixture_snapshot("placeholder_heavy.md"); -} - -#[test] -fn tiny_file_produces_metrics() { - // Codex P1: tiny Markdown files (1-3 bytes) used to be swallowed by - // `read_file_inner`'s `file_size <= 3` early return. The analyzer - // itself must still produce metrics — `read_file_raw` handles the - // file-size heuristic on the CLI side, but the analyzer is the last - // line of defense and must not assume a minimum input length. - for src in ["", "a", "#", "#\n", "a\n"] { - let path = PathBuf::from("tiny.md"); - let metrics = analyze_markdown(src, &path); - // The only invariant we care about here: no panic, and metric - // fields are populated (even with zero values) so JSON emission - // never produces malformed output. - assert!( - metrics.loc.dloc <= 2, - "dloc {}: input {src:?}", - metrics.loc.dloc - ); - } -} - -#[test] -fn readme_en_fixture() { - // Pure-English README-style fixture. Validates that the prose layer - // populates english.* with non-null readability numbers and leaves - // japanese absent. Also stresses the ensemble grade band calculation. - assert_fixture_snapshot("readme_en.md"); -} - -#[test] -fn readme_ja_fixture() { - // Pure-Japanese README. Validates the Tateishi RS path, script - // composition, Jōyō grade proxy, and politeness classification. - assert_fixture_snapshot("readme_ja.md"); -} - -#[test] -fn mixed_bilingual_fixture() { - // Bilingual doc: blocks array must carry per-block language tags and - // both english.* and japanese.* must populate. dominant_language is - // `mixed`. - assert_fixture_snapshot("mixed_bilingual.md"); -} - -#[test] -fn passive_heavy_fixture() { - // Passive-voice-heavy document. `english.wording.passive_ratio` must - // rise above 0.5 and WordingQualityScore must drop correspondingly. - let (source, path) = load_fixture("passive_heavy.md"); - let metrics = analyze_markdown(&source, &path); - let en = metrics - .prose - .english - .as_ref() - .expect("passive-heavy doc has English content"); - assert!( - en.wording.passive_ratio > 0.5, - "expected passive_ratio > 0.5, got {}", - en.wording.passive_ratio - ); - assert!( - en.wording.wording_quality_score < 0.9, - "expected WQS < 0.9 due to passive voice, got {}", - en.wording.wording_quality_score - ); - assert_fixture_snapshot("passive_heavy.md"); -} - -#[test] -fn tateishi_sample_fixture() { - // Large Japanese fixture. Validates Tateishi RS surface, jouyou grade - // non-null, and jukugo density > 0. - let (source, path) = load_fixture("tateishi_sample.md"); - let metrics = analyze_markdown(&source, &path); - let ja = metrics - .prose - .japanese - .as_ref() - .expect("tateishi sample has Japanese content"); - assert!( - ja.readability.tateishi_rs.is_some(), - "Tateishi RS must be populated" - ); - assert!( - ja.readability.jouyou_grade_mean.is_some(), - "Jōyō grade mean must be populated" - ); - assert!( - ja.lexical.jukugo_density > 0.0, - "expected non-zero jukugo density, got {}", - ja.lexical.jukugo_density - ); - assert_fixture_snapshot("tateishi_sample.md"); -} - -#[test] -fn short_doc_fixture() { - // Short-doc guard: words < 100 / sentences < 5 → suppress grade - // formulas, raise short_doc_warning. - let (source, path) = load_fixture("short_doc.md"); - let metrics = analyze_markdown(&source, &path); - assert!( - metrics.prose.meta.short_doc_warning, - "short doc must emit warning" - ); - let en = metrics - .prose - .english - .as_ref() - .expect("short doc still has EN prose"); - assert!( - en.readability.flesch_reading_ease.is_none(), - "FRES must be null for short doc" - ); - assert!( - en.readability.flesch_kincaid_grade.is_none(), - "FKGL must be null for short doc" - ); - assert_fixture_snapshot("short_doc.md"); -} - -#[test] -fn weak_phrase_ja_fixture() { - // Japanese document with many weak phrases. `weak_phrase_count` must - // be non-zero. - let (source, path) = load_fixture("weak_phrase_ja.md"); - let metrics = analyze_markdown(&source, &path); - let ja = metrics - .prose - .japanese - .as_ref() - .expect("weak-phrase fixture is Japanese"); - assert!( - ja.wording.weak_phrase_count > 0, - "expected weak_phrase_count > 0, got {}", - ja.wording.weak_phrase_count - ); - assert_fixture_snapshot("weak_phrase_ja.md"); -} - -#[test] -fn prose_no_modification_of_structural_scores() { - // §29.1 non-negotiable: prose layer must NEVER modify DMI, MCC, MRPC, - // or any structural score. This test re-analyzes the pure-prose fixture - // and captures its structural fields, then confirms they match what - // Phase A alone would produce. - let (source, path) = load_fixture("pure_prose.md"); - let metrics = analyze_markdown(&source, &path); - // Phase-A baseline for pure_prose.md: - // loc.dloc = 7, ploc = 4, bloc = 3; size.words = 27; sections = 1. - assert_eq!(metrics.loc.dloc, 7); - assert_eq!(metrics.loc.ploc, 4); - assert_eq!(metrics.loc.bloc, 3); - assert_eq!(metrics.size.words, 27); - assert_eq!(metrics.sections.len(), 1); -} - -#[test] -fn trailing_newlines_preserved_in_dloc() { - // `read_file_raw` feeds `analyze_markdown` the file-on-disk bytes, so - // trailing blank lines survive and count toward DLOC/BLOC. Guards - // against the Codex P1 regression: if a future change routes Markdown - // through `remove_blank_lines` again, the trailing blanks collapse and - // this assertion breaks. - // - // Input: "Alpha.\n\nBeta.\n\n\n" - // line 1: Alpha. (prose) - // line 2: blank - // line 3: Beta. (prose) - // line 4: blank - // line 5: blank - // (the final \n is the line-5 terminator, not a new line) - let src = "Alpha.\n\nBeta.\n\n\n"; - let path = PathBuf::from("trailing_newlines.md"); - let metrics = analyze_markdown(src, &path); - assert_eq!( - metrics.loc.dloc, 5, - "dloc must count every physical line including trailing blanks" - ); - assert!( - metrics.loc.bloc >= 3, - "three blank lines (one between, two trailing) must land in BLOC" - ); - - // Cross-check: stripping all trailing newlines (the `remove_blank_lines` - // regression path) would drop DLOC to 3. - let normalized = "Alpha.\n\nBeta.\n"; - let normalized_metrics = analyze_markdown(normalized, &path); - assert_eq!( - normalized_metrics.loc.dloc, 3, - "sanity check: the normalized form undercounts lines — that is why \ - Markdown must receive raw bytes" - ); -} - -#[test] -fn embedded_volume_scales_with_fence_size() { - ensure_dispatch(); - // Invariant (§9.4): a 100-LOC supported-language code fence must - // produce an `embedded_volume` that scales sub-linearly with the - // fence's internal Halstead volume (due to the 0.20 * sqrt(volume_c) - // term) but non-zero. Doubling the fence content should NOT double the - // embedded_volume — the sqrt term grows by ~1.41× only. - let small = build_rust_fence(5); - let medium = build_rust_fence(50); - let large = build_rust_fence(100); - - let path = PathBuf::from("scale.md"); - let s = analyze_markdown(&small, &path); - let m = analyze_markdown(&medium, &path); - let l = analyze_markdown(&large, &path); - - let ev_s = s.complexity.halstead.embedded_volume; - let ev_m = m.complexity.halstead.embedded_volume; - let ev_l = l.complexity.halstead.embedded_volume; - - assert!(ev_s > 0.0, "small fence embedded volume must be > 0"); - assert!(ev_m > ev_s, "medium > small"); - assert!(ev_l > ev_m, "large > medium"); - // total_volume = markdown_volume + embedded_volume. - assert!( - (l.complexity.halstead.total_volume - l.complexity.halstead.volume - ev_l).abs() < 1e-6, - "total_volume must equal volume + embedded_volume" - ); -} - -fn build_rust_fence(repeats: usize) -> String { - let mut s = String::from("# Title\n\n```rust\n"); - for _ in 0..repeats { - s.push_str("fn a() { let x = 1 + 2; let y = x * 3; }\n"); - } - s.push_str("```\n"); - s -} - -#[test] -fn dmi_stays_in_range() { - // §10.4: DMI is bounded to [0, 100]. After Phase D wires every §10 - // term there is no artificial floor — a badly-grounded filler-heavy - // doc can plausibly descend below 50. The only hard invariant is the - // clamp to `[0, 100]`. - for name in [ - "empty.md", - "pure_prose.md", - "code_fences.md", - "navigation_heavy.md", - "cognitive_cluster.md", - "halstead_mixed.md", - "deep_nesting.md", - "embedded_code_large.md", - ] { - let (source, path) = load_fixture(name); - let metrics = analyze_markdown(&source, &path); - let dmi = metrics.maintainability.documentation_maintainability_index; - assert!( - (0.0..=100.0).contains(&dmi), - "{name}: DMI {dmi} outside [0,100]" - ); - } -} - -#[test] -fn mrpc_raw_matches_classic_formula() { - // §7.2: `mrpc_raw = |E| - |N| + 2P`. Phase B does not expose |N|/|E|/P - // directly, but we can cross-check by computing both raw and weighted - // for fixtures where we know the graph shape. - let (source, path) = load_fixture("navigation_heavy.md"); - let metrics = analyze_markdown(&source, &path); - // At least one section + some edges, so raw cannot be 0. - assert!(metrics.complexity.reading_path_complexity_raw.abs() > 0.0); -} - -#[test] -fn halstead_vocabulary_is_non_negative() { - for name in [ - "halstead_mixed.md", - "embedded_code_large.md", - "code_fences.md", - ] { - let (source, path) = load_fixture(name); - let metrics = analyze_markdown(&source, &path); - let h = &metrics.complexity.halstead; - assert_eq!(h.vocabulary, h.operators_distinct + h.operands_distinct); - assert_eq!(h.length, h.operators_total + h.operands_total); - assert!(h.volume >= 0.0); - } -} - -#[test] -fn unlabelled_code_fence_penalty_shows_up() { - // Two documents identical except for the fence's language tag. The - // unlabelled variant must have higher MCC per §8.1 `Unlabelled code - // fence +1.50`. - let with_tag = "# T\n\nIntro.\n\n```rust\nlet x = 1;\n```\n\nOutro.\n"; - let without_tag = "# T\n\nIntro.\n\n```\nlet x = 1;\n```\n\nOutro.\n"; - let path = PathBuf::from("cmp.md"); - let a = analyze_markdown(with_tag, &path); - let b = analyze_markdown(without_tag, &path); - assert!( - b.complexity.cognitive_complexity > a.complexity.cognitive_complexity, - "unlabelled MCC ({}) should be > labelled MCC ({})", - b.complexity.cognitive_complexity, - a.complexity.cognitive_complexity - ); -} - -/// Spec-pinned sanity check for the §12.2 cycle formula. Independent of the -/// Markdown analyzer so regressions in the diagram parser surface before -/// the insta snapshots start drifting. -#[test] -fn mermaid_two_node_cycle_matches_spec() { - let sig = diagrams::mermaid::parse("graph TD\n A --> B\n B --> A\n"); - assert_eq!(sig.nodes, 2); - assert_eq!(sig.edges, 2); - assert_eq!(sig.components, 1); - assert_eq!(sig.cycles, 1); - assert!(!sig.parse_error); -} - -/// Regression: `MarkdownAnalyzer::analyze` (the registry path -/// reached via `mehen metrics README.md`) must populate the -/// `MetricSet` from the rich `analyze_markdown` pipeline. PR #95 -/// discussion_r3265727847 flagged that the analyzer was returning a -/// fresh empty `MetricSpace`, so every Markdown file's flat-keyed -/// JSON came back as zeros. -#[test] -fn markdown_analyzer_publishes_loc_and_complexity_keys() { - use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, MetricKey, SourceFile}; - use mehen_markdown::MarkdownAnalyzer; - - let (source, path) = load_fixture("readme_en.md"); - let analyzer = MarkdownAnalyzer::new(); - let utf8_path = camino::Utf8PathBuf::try_from(path).unwrap(); - let file = SourceFile::new(utf8_path, Language::Markdown, source); - let analysis = analyzer.analyze(&file, &AnalysisConfig::default()).unwrap(); - - let metrics = &analysis.root.metrics; - let dloc = metrics - .get(&MetricKey::new("markdown.loc.dloc")) - .expect("markdown.loc.dloc must be published"); - assert!( - dloc.as_f64() > 0.0, - "real Markdown file must report non-zero documentation LOC, got {}", - dloc.as_f64() - ); - - let words = metrics - .get(&MetricKey::new("markdown.size.words")) - .expect("markdown.size.words must be published"); - assert!( - words.as_f64() > 0.0, - "real Markdown file must report non-zero word count, got {}", - words.as_f64() - ); - - let cognitive = metrics - .get(&MetricKey::new("markdown.complexity.cognitive_complexity")) - .expect("markdown.complexity.cognitive_complexity must be published"); - assert!( - cognitive.as_f64() >= 0.0, - "cognitive complexity must be present and non-negative, got {}", - cognitive.as_f64() - ); - - let dmi = metrics - .get(&MetricKey::new( - "markdown.maintainability.documentation_maintainability_index", - )) - .expect("DMI must be published"); - assert!( - dmi.as_f64() > 0.0, - "real Markdown fixture should yield a positive DMI, got {}", - dmi.as_f64() - ); -} - -/// Regression: an empty Markdown buffer must still go through the -/// rich pipeline (returning zeros, not panicking) — exercising the -/// `analyze` impl on the smallest input guards against future -/// regressions where someone shortcut the empty case. -#[test] -fn markdown_analyzer_handles_empty_input() { - use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, MetricKey, SourceFile}; - use mehen_markdown::MarkdownAnalyzer; - - let analyzer = MarkdownAnalyzer::new(); - let file = SourceFile::new("empty.md".into(), Language::Markdown, String::new()); - let analysis = analyzer.analyze(&file, &AnalysisConfig::default()).unwrap(); - - // Headline keys exist even on an empty input so consumers can - // rely on the shape of the JSON output. - let metrics = &analysis.root.metrics; - assert!(metrics.get(&MetricKey::new("markdown.loc.dloc")).is_some()); - assert!( - metrics - .get(&MetricKey::new("markdown.size.words")) - .is_some() - ); - assert!( - metrics - .get(&MetricKey::new("markdown.complexity.cognitive_complexity")) - .is_some() - ); -} - -/// Every key the analyzer publishes must validate through -/// `is_published_metric_key`, or `mehen.toml` threshold validation -/// would reject a real metric. -#[test] -fn published_key_catalogue_is_in_sync() { - use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; - - let body = "# Title\n\nIntro paragraph with a [link](https://example.com) and \ - ![image](img.png).\n\n## Section\n\n- item one\n- item two\n\n\ - | a | b |\n|---|---|\n| 1 | 2 |\n\n```python\nprint(1)\n```\n\n\ - > quote\n\nAnother paragraph mentioning `code` and a bare URL \ - https://example.org for grounding.\n"; - let analysis = mehen_markdown::MarkdownAnalyzer::new() - .analyze( - &SourceFile::new("doc.md".into(), Language::Markdown, body.to_string()), - &AnalysisConfig::production(), - ) - .expect("analysis ok"); - let mut seen = 0usize; - for (key, _) in analysis.root.metrics.iter() { - seen += 1; - assert!( - mehen_markdown::is_published_metric_key(key.as_str()), - "published key `{key}` is missing from the catalogue" - ); - } - assert!( - seen > 30, - "fixture must exercise a rich key set, saw {seen}" - ); - // Near-misses stay invalid. - assert!(!mehen_markdown::is_published_metric_key( - "markdown.links.borken" - )); -} diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@artifact_debt_high.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@artifact_debt_high.md.snap deleted file mode 100644 index 10dd4f7e..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@artifact_debt_high.md.snap +++ /dev/null @@ -1,224 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 23 - ploc: 4 - cloc: 9 - tloc: 3 - mloc: 0 - bloc: 6 - aloc: 13 -loc_ratios: - artifact_line_ratio: 0.5652173913043478 - code_line_ratio: 0.391304347826087 - table_line_ratio: 0.13043478260869565 - math_line_ratio: 0 - blank_line_ratio: 0.2608695652173913 -size: - words: 36 - effective_content_units: 3.74 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 4 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 1 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 23 - parent_section_id: ~ - child_section_ids: [] - word_count: 36 - block_count: 6 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 9.481041666666666 - halstead: - operators_distinct: 7 - operators_total: 13 - operands_distinct: 41 - operands_total: 45 - vocabulary: 48 - length: 58 - volume: 323.9278250418271 - difficulty: 3.8414634146341466 - effort: 1244.3568888801894 - embedded_volume: 0 - total_volume: 323.9278250418271 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 1 - max_cells: 4 - table_burden_score: 0.025 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.696 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0.4 -grounding: - repository_grounding_score: 0.04000000000000001 - evidence_coverage_score: 1 -ai_era: - filler_lazy_structure_risk: 0.29616666666666663 - labels: - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-repository-grounding - - 0.96 - - - specificity-scarcity - - 0.5555555555555556 - - - lazy-sectioning - - 0.24999999999999994 -review: - review_criticality_index: 16.63192336309524 -artifacts: - - id: 0 - kind: code - start_line: 7 - end_line: 9 - language_tag: ~ - size: 1 - has_explanation: true - has_label: false - oversized: false - burden: 2.5 - - id: 1 - kind: html - start_line: 11 - end_line: 11 - language_tag: ~ - size: 1 - has_explanation: true - has_label: false - oversized: false - burden: 1 - - id: 2 - kind: code - start_line: 13 - end_line: 15 - language_tag: ~ - size: 1 - has_explanation: false - has_label: false - oversized: false - burden: 2.5 - - id: 3 - kind: code - start_line: 17 - end_line: 19 - language_tag: tikz - size: 1 - has_explanation: false - has_label: true - oversized: false - burden: 1 - - id: 4 - kind: table - start_line: 21 - end_line: 23 - language_tag: ~ - size: 4 - has_explanation: false - has_label: true - oversized: false - burden: 0.025 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.892 - hapax_ratio: 0.879 - dis_ratio: 0.121 - lexical_density: 0.73 - avg_sentence_words: 18.5 - p90_sentence_words: 33 - max_sentence_words: 33 - stddev_sentence_words: 14.5 - avg_word_chars: 4.811 - p90_word_chars: 8 - sentence_count: 2 - words_total: 37 - wording: - passive_ratio: 0.5 - hedge_density: 0.027 - weasel_density: 0.027 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 1 - wording_quality_score: 0.723 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 37 - sentences_counted: 2 - blocks_stripped: - - code - - html - - table diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@broken_links.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@broken_links.md.snap deleted file mode 100644 index a7f4937b..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@broken_links.md.snap +++ /dev/null @@ -1,231 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 13 - ploc: 10 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 3 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.23076923076923078 -size: - words: 34 - effective_content_units: 0.14166666666666666 - sections: 2 - headings: 2 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 13 - parent_section_id: ~ - child_section_ids: - - 1 - word_count: 25 - block_count: 6 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 11 - end_line: 13 - parent_section_id: 0 - child_section_ids: [] - word_count: 9 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 2 - cognitive_complexity: 4.494 - halstead: - operators_distinct: 7 - operators_total: 17 - operands_distinct: 40 - operands_total: 44 - vocabulary: 47 - length: 61 - volume: 338.8299199523359 - difficulty: 3.8500000000000005 - effort: 1304.4951918164934 - embedded_volume: 0 - total_volume: 338.8299199523359 -links: - total: 4 - internal: 1 - relative: 2 - external: 1 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 3 - link_debt_score: 0.65 - information_scent_score: 0.15 - review_burden: 10.4 -link_records: - - line: 6 - class: relative - destination: "./does-not-exist.md" - text: Missing file - is_image: false - is_bare_url: false - resolved: false - - line: 7 - class: internal - destination: "#nowhere" - text: Missing anchor - is_image: false - is_bare_url: false - resolved: false - - line: 8 - class: unresolved_reference_use - destination: "" - text: stale - is_image: false - is_bare_url: false - resolved: false - - line: 9 - class: external - destination: "https://example.com" - text: click here - is_image: false - is_bare_url: false - resolved: ~ -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 82.99659663865546 - section_balance_score: 0.85 - good_scaffold_score: 0.0225 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0.23076923076923078 -ai_era: - filler_lazy_structure_risk: 0.4440336134453781 - labels: - - low-artifact-density - - low-repository-grounding - - placeholder-heavy - - specificity-scarcity - top_contributors: - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 - - - specificity-scarcity - - 0.7598039215686274 -review: - review_criticality_index: 9.323392857142856 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 4 - language: en - - start_line: 6 - end_line: 6 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 8 - end_line: 8 - language: en - - start_line: 9 - end_line: 9 - language: en - - start_line: 11 - end_line: 11 - language: en - - start_line: 13 - end_line: 13 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.85 - hapax_ratio: 0.853 - dis_ratio: 0.118 - lexical_density: 0.75 - avg_sentence_words: 5 - p90_sentence_words: 15 - max_sentence_words: 15 - stddev_sentence_words: 4.416 - avg_word_chars: 5.325 - p90_word_chars: 7 - sentence_count: 8 - words_total: 40 - wording: - passive_ratio: 0 - hedge_density: 0.025 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.025 - nominalization_density: 0.05 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.975 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 40 - sentences_counted: 8 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@code_fences.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@code_fences.md.snap deleted file mode 100644 index 96de76a1..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@code_fences.md.snap +++ /dev/null @@ -1,198 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 20 - ploc: 4 - cloc: 11 - tloc: 0 - mloc: 0 - bloc: 5 - aloc: 11 -loc_ratios: - artifact_line_ratio: 0.55 - code_line_ratio: 0.55 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.25 -size: - words: 15 - effective_content_units: 3.9124999999999996 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 20 - parent_section_id: ~ - child_section_ids: [] - word_count: 15 - block_count: 5 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 2.0250000000000004 - halstead: - operators_distinct: 4 - operators_total: 6 - operands_distinct: 18 - operands_total: 20 - vocabulary: 22 - length: 26 - volume: 115.94522208456974 - difficulty: 2.2222222222222223 - effort: 257.65604907682166 - embedded_volume: 0.981458449927413 - total_volume: 116.92668053449715 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 96.49799999999999 - section_balance_score: 0.85 - good_scaffold_score: 0.2 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.12 - evidence_coverage_score: 1 -ai_era: - filler_lazy_structure_risk: 0.3335 - labels: - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - specificity-scarcity - - 1 - - - low-repository-grounding - - 0.88 - - - lazy-sectioning - - 0.24999999999999994 -review: - review_criticality_index: 11.309999999999999 -artifacts: - - id: 0 - kind: code - start_line: 5 - end_line: 9 - language_tag: rust - size: 3 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 1 - kind: code - start_line: 13 - end_line: 18 - language_tag: json - size: 4 - has_explanation: true - has_label: true - oversized: false - burden: 1 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: en - - start_line: 11 - end_line: 11 - language: en - - start_line: 20 - end_line: 20 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.722 - hapax_ratio: 0.692 - dis_ratio: 0.231 - lexical_density: 0.778 - avg_sentence_words: 4.5 - p90_sentence_words: 5 - max_sentence_words: 5 - stddev_sentence_words: 0.866 - avg_word_chars: 5.722 - p90_word_chars: 8 - sentence_count: 4 - words_total: 18 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 18 - sentences_counted: 4 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@cognitive_cluster.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@cognitive_cluster.md.snap deleted file mode 100644 index 051b7553..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@cognitive_cluster.md.snap +++ /dev/null @@ -1,322 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 42 - ploc: 23 - cloc: 6 - tloc: 0 - mloc: 0 - bloc: 13 - aloc: 6 -loc_ratios: - artifact_line_ratio: 0.14285714285714285 - code_line_ratio: 0.14285714285714285 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.30952380952380953 -size: - words: 63 - effective_content_units: 2.3625 - sections: 6 - headings: 6 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 42 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - - 5 - word_count: 19 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 6 - end_line: 14 - parent_section_id: 0 - child_section_ids: [] - word_count: 12 - block_count: 9 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 15 - end_line: 20 - parent_section_id: 0 - child_section_ids: [] - word_count: 11 - block_count: 4 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 22 - end_line: 26 - parent_section_id: 0 - child_section_ids: [] - word_count: 8 - block_count: 1 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 28 - end_line: 32 - parent_section_id: 0 - child_section_ids: [] - word_count: 0 - block_count: 1 - - section_id: 5 - heading_level: 2 - heading_text: ~ - start_line: 34 - end_line: 42 - parent_section_id: 0 - child_section_ids: [] - word_count: 13 - block_count: 3 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 5 - cognitive_complexity: 19.51933333333334 - halstead: - operators_distinct: 10 - operators_total: 42 - operands_distinct: 72 - operands_total: 85 - vocabulary: 82 - length: 127 - volume: 807.4091045864966 - difficulty: 5.902777777777778 - effort: 4765.956520128626 - embedded_volume: 0 - total_volume: 807.4091045864966 -links: - total: 6 - internal: 0 - relative: 0 - external: 6 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0.1 - information_scent_score: 0.3 - review_burden: 6 -link_records: - - line: 24 - class: external - destination: "https://a.example.com" - text: one - is_image: false - is_bare_url: false - resolved: ~ - - line: 24 - class: external - destination: "https://b.example.com" - text: two - is_image: false - is_bare_url: false - resolved: ~ - - line: 25 - class: external - destination: "https://c.example.com" - text: three - is_image: false - is_bare_url: false - resolved: ~ - - line: 25 - class: external - destination: "https://d.example.com" - text: four - is_image: false - is_bare_url: false - resolved: ~ - - line: 26 - class: external - destination: "https://e.example.com" - text: five - is_image: false - is_bare_url: false - resolved: ~ - - line: 26 - class: external - destination: "https://f.example.com" - text: six - is_image: false - is_bare_url: false - resolved: ~ -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 89.11734945054943 - section_balance_score: 0.85 - good_scaffold_score: 0.14500000000000002 - artifact_debt_score: 0.35 -grounding: - repository_grounding_score: 0.04000000000000001 - evidence_coverage_score: 0.1346153846153846 -ai_era: - filler_lazy_structure_risk: 0.37342857142857144 - labels: - - large-unanchored-prose - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-repository-grounding - - 0.96 - - - large-unanchored-prose - - 0.6333333333333333 - - - specificity-scarcity - - 0.4563492063492064 -review: - review_criticality_index: 21.3325 -artifacts: - - id: 0 - kind: code - start_line: 30 - end_line: 32 - language_tag: ~ - size: 1 - has_explanation: true - has_label: false - oversized: false - burden: 2.5 - - id: 1 - kind: code - start_line: 38 - end_line: 40 - language_tag: bash - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 4 - language: en - - start_line: 6 - end_line: 6 - language: en - - start_line: 8 - end_line: 12 - language: en - - start_line: 13 - end_line: 13 - language: en - - start_line: 15 - end_line: 15 - language: en - - start_line: 17 - end_line: 17 - language: en - - start_line: 20 - end_line: 20 - language: en - - start_line: 22 - end_line: 22 - language: en - - start_line: 24 - end_line: 26 - language: en - - start_line: 28 - end_line: 28 - language: en - - start_line: 34 - end_line: 34 - language: en - - start_line: 36 - end_line: 36 - language: en - - start_line: 42 - end_line: 42 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.735 - hapax_ratio: 0.66 - dis_ratio: 0.226 - lexical_density: 0.779 - avg_sentence_words: 5.5 - p90_sentence_words: 10 - max_sentence_words: 19 - stddev_sentence_words: 4.516 - avg_word_chars: 4.909 - p90_word_chars: 9 - sentence_count: 14 - words_total: 77 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.013 - nominalization_density: 0.026 - expletive_count: 0 - lexical_illusions: 1 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.95 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 77 - sentences_counted: 14 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@deep_nesting.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@deep_nesting.md.snap deleted file mode 100644 index aa1e0df7..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@deep_nesting.md.snap +++ /dev/null @@ -1,210 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 26 - ploc: 21 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 5 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.19230769230769232 -size: - words: 46 - effective_content_units: 0.19166666666666668 - sections: 2 - headings: 2 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 26 - parent_section_id: ~ - child_section_ids: - - 1 - word_count: 34 - block_count: 15 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 17 - end_line: 26 - parent_section_id: 0 - child_section_ids: [] - word_count: 12 - block_count: 8 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 16.038 - halstead: - operators_distinct: 7 - operators_total: 23 - operands_distinct: 37 - operands_total: 51 - vocabulary: 44 - length: 74 - volume: 403.99793977916 - difficulty: 4.824324324324324 - effort: 1949.0170878535148 - embedded_volume: 0 - total_volume: 403.99793977916 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.2329265169613 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.025155279503105588 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.6649689440993789 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - specificity-scarcity - - 1 -review: - review_criticality_index: 14.299697204968945 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 4 - language: en - - start_line: 6 - end_line: 6 - language: en - - start_line: 8 - end_line: 11 - language: en - - start_line: 12 - end_line: 12 - language: en - - start_line: 14 - end_line: 15 - language: en - - start_line: 17 - end_line: 17 - language: en - - start_line: 20 - end_line: 20 - language: en - - start_line: 22 - end_line: 23 - language: en - - start_line: 24 - end_line: 24 - language: en - - start_line: 26 - end_line: 26 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.65 - hapax_ratio: 0.667 - dis_ratio: 0.242 - lexical_density: 0.863 - avg_sentence_words: 4.636 - p90_sentence_words: 9 - max_sentence_words: 11 - stddev_sentence_words: 3.17 - avg_word_chars: 5.451 - p90_word_chars: 9 - sentence_count: 11 - words_total: 51 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 51 - sentences_counted: 11 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_heavy_scaffolded.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_heavy_scaffolded.md.snap deleted file mode 100644 index 97d599bf..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_heavy_scaffolded.md.snap +++ /dev/null @@ -1,349 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 186 - ploc: 95 - cloc: 64 - tloc: 0 - mloc: 0 - bloc: 27 - aloc: 64 -loc_ratios: - artifact_line_ratio: 0.34408602150537637 - code_line_ratio: 0.34408602150537637 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.14516129032258066 -size: - words: 831 - effective_content_units: 45.9625 - sections: 7 - headings: 7 -ecu_inputs: - table_cells: 0 - diagram_nodes: 29 - diagram_edges: 34 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 186 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - word_count: 51 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 10 - end_line: 40 - parent_section_id: 0 - child_section_ids: [] - word_count: 129 - block_count: 4 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 42 - end_line: 78 - parent_section_id: 0 - child_section_ids: [] - word_count: 185 - block_count: 4 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 80 - end_line: 115 - parent_section_id: 0 - child_section_ids: [] - word_count: 149 - block_count: 4 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 117 - end_line: 148 - parent_section_id: 0 - child_section_ids: [] - word_count: 152 - block_count: 4 - - section_id: 5 - heading_level: 2 - heading_text: ~ - start_line: 150 - end_line: 175 - parent_section_id: 0 - child_section_ids: [] - word_count: 96 - block_count: 3 - - section_id: 6 - heading_level: 2 - heading_text: ~ - start_line: 177 - end_line: 186 - parent_section_id: 0 - child_section_ids: [] - word_count: 69 - block_count: 1 -complexity: - reading_path_complexity: 1.9000000000000004 - reading_path_complexity_raw: 11 - cognitive_complexity: 7.74375 - halstead: - operators_distinct: 6 - operators_total: 90 - operands_distinct: 443 - operands_total: 849 - vocabulary: 449 - length: 939 - volume: 8273.126765021936 - difficulty: 5.749435665914221 - effort: 47565.810091446656 - embedded_volume: 0 - total_volume: 8273.126765021936 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 5 - diagram_nodes_total: 29 - diagram_edges_total: 34 - diagram_cycles_total: 10 - visual_scaffold_score: 1 - visual_net_effect: 35.300000000000004 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 96.0348577113937 - section_balance_score: 1 - good_scaffold_score: 0.25 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0.37362637362637363 -ai_era: - filler_lazy_structure_risk: 0.32 - labels: - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-repository-grounding - - 1 - - - specificity-scarcity - - 1 - - - hollow-references - - 0 -review: - review_criticality_index: 4.4081114620938635 -artifacts: - - id: 0 - kind: diagram - start_line: 18 - end_line: 29 - language_tag: mermaid - size: 6 - has_explanation: true - has_label: true - oversized: false - burden: 7.200000000000001 - - id: 1 - kind: diagram - start_line: 52 - end_line: 64 - language_tag: mermaid - size: 6 - has_explanation: true - has_label: true - oversized: false - burden: 9.25 - - id: 2 - kind: diagram - start_line: 89 - end_line: 103 - language_tag: mermaid - size: 5 - has_explanation: true - has_label: true - oversized: false - burden: 14.45 - - id: 3 - kind: diagram - start_line: 124 - end_line: 135 - language_tag: mermaid - size: 6 - has_explanation: true - has_label: true - oversized: false - burden: 7.200000000000001 - - id: 4 - kind: diagram - start_line: 157 - end_line: 168 - language_tag: mermaid - size: 6 - has_explanation: true - has_label: true - oversized: false - burden: 7.200000000000001 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 8 - language: en - - start_line: 10 - end_line: 10 - language: en - - start_line: 12 - end_line: 16 - language: en - - start_line: 31 - end_line: 34 - language: en - - start_line: 36 - end_line: 40 - language: en - - start_line: 42 - end_line: 42 - language: en - - start_line: 44 - end_line: 50 - language: en - - start_line: 66 - end_line: 71 - language: en - - start_line: 73 - end_line: 78 - language: en - - start_line: 80 - end_line: 80 - language: en - - start_line: 82 - end_line: 87 - language: en - - start_line: 105 - end_line: 109 - language: en - - start_line: 111 - end_line: 115 - language: en - - start_line: 117 - end_line: 117 - language: en - - start_line: 119 - end_line: 122 - language: en - - start_line: 137 - end_line: 141 - language: en - - start_line: 143 - end_line: 148 - language: en - - start_line: 150 - end_line: 150 - language: en - - start_line: 152 - end_line: 155 - language: en - - start_line: 170 - end_line: 175 - language: en - - start_line: 177 - end_line: 177 - language: en - - start_line: 179 - end_line: 186 - language: en - english: - readability: - flesch_reading_ease: 40.458 - flesch_kincaid_grade: 11.478 - gunning_fog: 13.563 - smog: 13.719 - ari: 11.749 - coleman_liau: 14.014 - dale_chall_new: 11.296 - dale_chall_list: ngsl-1.2 - forcast: 12.6 - lix: 48.762 - rix: 5.164 - ensemble_grade_band: - - 11.478 - - 14.014 - lexical: - mattr_50: 0.804 - hapax_ratio: 0.697 - dis_ratio: 0.138 - lexical_density: 0.637 - avg_sentence_words: 15.545 - p90_sentence_words: 27 - max_sentence_words: 39 - stddev_sentence_words: 9.62 - avg_word_chars: 5.395 - p90_word_chars: 9 - sentence_count: 55 - words_total: 855 - wording: - passive_ratio: 0.145 - hedge_density: 0.02 - weasel_density: 0.002 - wordy_density: 0.002 - adverb_density: 0.015 - nominalization_density: 0.027 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 4 - wording_quality_score: 0.993 - inclusive_language: - flags: - - category: condescending - surface: easy - preferred: (remove — describe steps instead) - count: 1 - inclusive_language_score: 0.95 - flag_count: 1 - short_doc_warning: false - japanese: ~ - meta: - short_doc_warning: false - words_counted: 855 - sentences_counted: 55 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_mermaid.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_mermaid.md.snap deleted file mode 100644 index c41f2117..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_mermaid.md.snap +++ /dev/null @@ -1,185 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 13 - ploc: 5 - cloc: 5 - tloc: 0 - mloc: 0 - bloc: 3 - aloc: 5 -loc_ratios: - artifact_line_ratio: 0.38461538461538464 - code_line_ratio: 0.38461538461538464 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.23076923076923078 -size: - words: 43 - effective_content_units: 3.229166666666667 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 2 - diagram_edges: 2 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 13 - parent_section_id: ~ - child_section_ids: [] - word_count: 43 - block_count: 3 -complexity: - reading_path_complexity: 2 - reading_path_complexity_raw: 2 - cognitive_complexity: 1.4329326923076922 - halstead: - operators_distinct: 5 - operators_total: 12 - operands_distinct: 41 - operands_total: 47 - vocabulary: 46 - length: 59 - volume: 325.89015540736375 - difficulty: 2.8658536585365852 - effort: 933.9534941552497 - embedded_volume: 0 - total_volume: 325.89015540736375 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 1 - diagram_nodes_total: 2 - diagram_edges_total: 2 - diagram_cycles_total: 1 - visual_scaffold_score: 0.9595886165829116 - visual_net_effect: 1.4000000000000004 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 98.01249313614167 - section_balance_score: 1 - good_scaffold_score: 0.2398971541457279 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.028405315614617933 - evidence_coverage_score: 0.6153846153846154 -ai_era: - filler_lazy_structure_risk: 0.36553986710963454 - labels: - - low-artifact-density - - low-repository-grounding - top_contributors: - - - low-repository-grounding - - 0.9715946843853821 - - - low-artifact-density - - 0.6666666666666667 - - - specificity-scarcity - - 0.28100775193798444 -review: - review_criticality_index: 6.369269102990034 -artifacts: - - id: 0 - kind: diagram - start_line: 6 - end_line: 10 - language_tag: mermaid - size: 2 - has_explanation: true - has_label: true - oversized: false - burden: 3.4000000000000004 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 4 - language: en - - start_line: 12 - end_line: 13 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.816 - hapax_ratio: 0.875 - dis_ratio: 0.075 - lexical_density: 0.735 - avg_sentence_words: 16.333 - p90_sentence_words: 24 - max_sentence_words: 24 - stddev_sentence_words: 9.463 - avg_word_chars: 4.857 - p90_word_chars: 9 - sentence_count: 3 - words_total: 49 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0.041 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 49 - sentences_counted: 3 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_parse_error.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_parse_error.md.snap deleted file mode 100644 index 6ce370fe..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@diagram_parse_error.md.snap +++ /dev/null @@ -1,191 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 19 - ploc: 4 - cloc: 12 - tloc: 0 - mloc: 0 - bloc: 3 - aloc: 12 -loc_ratios: - artifact_line_ratio: 0.631578947368421 - code_line_ratio: 0.631578947368421 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.15789473684210525 -size: - words: 24 - effective_content_units: 5.849999999999999 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 2 - diagram_edges: 3 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 19 - parent_section_id: ~ - child_section_ids: [] - word_count: 24 - block_count: 3 -complexity: - reading_path_complexity: 2 - reading_path_complexity_raw: 2 - cognitive_complexity: 2.5312500000000004 - halstead: - operators_distinct: 8 - operators_total: 9 - operands_distinct: 29 - operands_total: 31 - vocabulary: 37 - length: 40 - volume: 208.378134625158 - difficulty: 4.275862068965517 - effort: 890.9961618455031 - embedded_volume: 0 - total_volume: 208.378134625158 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 1 - diagram_nodes_total: 2 - diagram_edges_total: 3 - diagram_cycles_total: 0 - visual_scaffold_score: 0.9768308314557045 - visual_net_effect: 0.4500000000000002 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 100 - section_balance_score: 0.85 - good_scaffold_score: 0.44420770786392616 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.19 - evidence_coverage_score: 1 -ai_era: - filler_lazy_structure_risk: 0.2245 - labels: - - low-repository-grounding - top_contributors: - - - low-repository-grounding - - 0.81 - - - lazy-sectioning - - 0.24999999999999994 - - - specificity-scarcity - - 0.20833333333333326 -review: - review_criticality_index: 12.22 -artifacts: - - id: 0 - kind: diagram - start_line: 7 - end_line: 13 - language_tag: plantuml - size: 2 - has_explanation: true - has_label: true - oversized: false - burden: 2.45 - - id: 1 - kind: code - start_line: 15 - end_line: 19 - language_tag: tikz - size: 3 - has_explanation: true - has_label: true - oversized: false - burden: 1 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.862 - hapax_ratio: 0.92 - dis_ratio: 0.04 - lexical_density: 0.759 - avg_sentence_words: 14.5 - p90_sentence_words: 25 - max_sentence_words: 25 - stddev_sentence_words: 10.5 - avg_word_chars: 5.31 - p90_word_chars: 8 - sentence_count: 2 - words_total: 29 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0.034 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 29 - sentences_counted: 2 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@embedded_code_large.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@embedded_code_large.md.snap deleted file mode 100644 index b7ed0c60..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@embedded_code_large.md.snap +++ /dev/null @@ -1,266 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 89 - ploc: 10 - cloc: 69 - tloc: 0 - mloc: 0 - bloc: 10 - aloc: 69 -loc_ratios: - artifact_line_ratio: 0.7752808988764045 - code_line_ratio: 0.7752808988764045 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.11235955056179775 -size: - words: 44 - effective_content_units: 24.333333333333332 - sections: 5 - headings: 5 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 89 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - word_count: 18 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 6 - end_line: 31 - parent_section_id: 0 - child_section_ids: [] - word_count: 0 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 33 - end_line: 53 - parent_section_id: 0 - child_section_ids: [] - word_count: 0 - block_count: 1 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 55 - end_line: 79 - parent_section_id: 0 - child_section_ids: [] - word_count: 0 - block_count: 1 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 81 - end_line: 89 - parent_section_id: 0 - child_section_ids: [] - word_count: 26 - block_count: 2 -complexity: - reading_path_complexity: 1.2000000000000002 - reading_path_complexity_raw: 7 - cognitive_complexity: 6.144 - halstead: - operators_distinct: 9 - operators_total: 16 - operands_distinct: 51 - operands_total: 60 - vocabulary: 60 - length: 76 - volume: 448.92368526624745 - difficulty: 5.294117647058823 - effort: 2376.654804350722 - embedded_volume: 25.825071751093375 - total_volume: 474.74875701734084 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 98.32488311688311 - section_balance_score: 0.85 - good_scaffold_score: 0.2 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.28006493506493507 - evidence_coverage_score: 0.5538461538461539 -ai_era: - filler_lazy_structure_risk: 0.18125974025974026 - labels: - - low-repository-grounding - top_contributors: - - - low-repository-grounding - - 0.7199350649350649 - - - large-unanchored-prose - - 0.11818181818181828 - - - specificity-scarcity - - 0.11363636363636365 -review: - review_criticality_index: 18.029415584415585 -artifacts: - - id: 0 - kind: code - start_line: 8 - end_line: 31 - language_tag: rust - size: 22 - has_explanation: true - has_label: true - oversized: false - burden: 1.8 - - id: 1 - kind: code - start_line: 35 - end_line: 53 - language_tag: python - size: 17 - has_explanation: true - has_label: true - oversized: false - burden: 1.4 - - id: 2 - kind: code - start_line: 57 - end_line: 79 - language_tag: typescript - size: 21 - has_explanation: true - has_label: true - oversized: false - burden: 1.72 - - id: 3 - kind: code - start_line: 87 - end_line: 89 - language_tag: sql - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 4 - language: en - - start_line: 6 - end_line: 6 - language: en - - start_line: 33 - end_line: 33 - language: en - - start_line: 55 - end_line: 55 - language: en - - start_line: 81 - end_line: 81 - language: en - - start_line: 83 - end_line: 85 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.832 - hapax_ratio: 0.814 - dis_ratio: 0.116 - lexical_density: 0.667 - avg_sentence_words: 6.75 - p90_sentence_words: 25 - max_sentence_words: 25 - stddev_sentence_words: 7.838 - avg_word_chars: 5.537 - p90_word_chars: 10 - sentence_count: 8 - words_total: 54 - wording: - passive_ratio: 0.125 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.019 - nominalization_density: 0.037 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 54 - sentences_counted: 8 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@empty.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@empty.md.snap deleted file mode 100644 index b12eaa3d..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@empty.md.snap +++ /dev/null @@ -1,102 +0,0 @@ ---- -source: src/markdown/tests/mod.rs ---- -path: "" -loc: - dloc: 1 - ploc: 0 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 1 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 1 -size: - words: 0 - effective_content_units: 0 - sections: 0 - headings: 0 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: [] -complexity: - reading_path_complexity: 0 - reading_path_complexity_raw: 0 - cognitive_complexity: 0 - halstead: - operators_distinct: 0 - operators_total: 0 - operands_distinct: 0 - operands_total: 0 - vocabulary: 0 - length: 0 - volume: 0 - difficulty: 0 - effort: 0 - embedded_volume: 0 - total_volume: 0 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 100 - section_balance_score: 1 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0 - labels: [] - top_contributors: [] -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: other - blocks: [] - english: ~ - japanese: ~ - meta: - short_doc_warning: true - words_counted: 0 - sentences_counted: 0 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@frontmatter.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@frontmatter.md.snap deleted file mode 100644 index 065d6222..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@frontmatter.md.snap +++ /dev/null @@ -1,177 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 12 - ploc: 3 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 3 - aloc: 6 -loc_ratios: - artifact_line_ratio: 0.5 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.25 -size: - words: 18 - effective_content_units: 0.075 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 8 - end_line: 12 - parent_section_id: ~ - child_section_ids: [] - word_count: 18 - block_count: 2 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 0 - halstead: - operators_distinct: 4 - operators_total: 7 - operands_distinct: 22 - operands_total: 26 - vocabulary: 26 - length: 33 - volume: 155.11451069865603 - difficulty: 2.3636363636363638 - effort: 366.6342980150052 - embedded_volume: 0 - total_volume: 155.11451069865603 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.01 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.7075 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 8 - end_line: 8 - language: en - - start_line: 10 - end_line: 10 - language: en - - start_line: 12 - end_line: 12 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.857 - hapax_ratio: 0.833 - dis_ratio: 0.167 - lexical_density: 0.714 - avg_sentence_words: 7 - p90_sentence_words: 10 - max_sentence_words: 10 - stddev_sentence_words: 3.559 - avg_word_chars: 5.333 - p90_word_chars: 8 - sentence_count: 3 - words_total: 21 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.048 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.931 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 21 - sentences_counted: 3 - blocks_stripped: - - frontmatter diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@giant_table_debt.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@giant_table_debt.md.snap deleted file mode 100644 index 8343687e..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@giant_table_debt.md.snap +++ /dev/null @@ -1,199 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 54 - ploc: 8 - cloc: 0 - tloc: 42 - mloc: 0 - bloc: 4 - aloc: 42 -loc_ratios: - artifact_line_ratio: 0.7777777777777778 - code_line_ratio: 0 - table_line_ratio: 0.7777777777777778 - math_line_ratio: 0 - blank_line_ratio: 0.07407407407407407 -size: - words: 949 - effective_content_units: 55.61416666666666 - sections: 2 - headings: 2 -ecu_inputs: - table_cells: 861 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 54 - parent_section_id: ~ - child_section_ids: - - 1 - word_count: 33 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 7 - end_line: 54 - parent_section_id: 0 - child_section_ids: [] - word_count: 916 - block_count: 2 -complexity: - reading_path_complexity: 1.15 - reading_path_complexity_raw: 2 - cognitive_complexity: 15.112382190832793 - halstead: - operators_distinct: 5 - operators_total: 29 - operands_distinct: 134 - operands_total: 976 - vocabulary: 139 - length: 1005 - volume: 7154.535778087125 - difficulty: 18.208955223880597 - effort: 130276.62163084019 - embedded_volume: 0 - total_volume: 7154.535778087125 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 1 - max_cells: 861 - table_burden_score: 0.5648809523809524 - table_scaffold_score: 0 - hard_warnings: 1 -maintainability: - documentation_maintainability_index: 84.74552382091251 - section_balance_score: 0.91 - good_scaffold_score: 0 - artifact_debt_score: 0.15 -grounding: - repository_grounding_score: 0.03322444678609062 - evidence_coverage_score: 0.02103627813234799 -ai_era: - filler_lazy_structure_risk: 0.4102413066385669 - labels: - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-repository-grounding - - 0.9667755532139094 - - - low-artifact-density - - 0.7713382507903056 - - - specificity-scarcity - - 0.6792237442922375 -review: - review_criticality_index: 5.236081078982659 -artifacts: - - id: 0 - kind: table - start_line: 9 - end_line: 50 - language_tag: ~ - size: 861 - has_explanation: true - has_label: true - oversized: true - burden: 0.5648809523809524 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 52 - end_line: 54 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.708 - hapax_ratio: 0.688 - dis_ratio: 0.188 - lexical_density: 0.653 - avg_sentence_words: 12.5 - p90_sentence_words: 21 - max_sentence_words: 21 - stddev_sentence_words: 7.274 - avg_word_chars: 4.947 - p90_word_chars: 9 - sentence_count: 6 - words_total: 75 - wording: - passive_ratio: 0.167 - hedge_density: 0.013 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.013 - nominalization_density: 0.04 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 75 - sentences_counted: 6 - blocks_stripped: - - table diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@halstead_mixed.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@halstead_mixed.md.snap deleted file mode 100644 index a4f33d83..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@halstead_mixed.md.snap +++ /dev/null @@ -1,316 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 38 - ploc: 17 - cloc: 4 - tloc: 4 - mloc: 0 - bloc: 13 - aloc: 8 -loc_ratios: - artifact_line_ratio: 0.21052631578947367 - code_line_ratio: 0.10526315789473684 - table_line_ratio: 0.10526315789473684 - math_line_ratio: 0 - blank_line_ratio: 0.34210526315789475 -size: - words: 50 - effective_content_units: 2.328333333333333 - sections: 7 - headings: 7 -ecu_inputs: - table_cells: 6 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 3 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 38 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - word_count: 26 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 7 - end_line: 9 - parent_section_id: 0 - child_section_ids: [] - word_count: 7 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 11 - end_line: 15 - parent_section_id: 0 - child_section_ids: [] - word_count: 2 - block_count: 3 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 16 - end_line: 20 - parent_section_id: 0 - child_section_ids: [] - word_count: 4 - block_count: 2 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 22 - end_line: 27 - parent_section_id: 0 - child_section_ids: [] - word_count: 6 - block_count: 1 - - section_id: 5 - heading_level: 2 - heading_text: ~ - start_line: 29 - end_line: 31 - parent_section_id: 0 - child_section_ids: [] - word_count: 5 - block_count: 1 - - section_id: 6 - heading_level: 2 - heading_text: ~ - start_line: 33 - end_line: 38 - parent_section_id: 0 - child_section_ids: [] - word_count: 0 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 6 - cognitive_complexity: 3.7303124999999993 - halstead: - operators_distinct: 11 - operators_total: 33 - operands_distinct: 67 - operands_total: 75 - vocabulary: 78 - length: 108 - volume: 678.8234396371229 - difficulty: 6.156716417910447 - effort: 4179.323415676316 - embedded_volume: 1.2392304845413264 - total_volume: 680.0626701216642 -links: - total: 2 - internal: 0 - relative: 1 - external: 1 - external_vendor: 1 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 1 - footnote: 0 - bare_url: 0 - broken: 1 - link_debt_score: 0.45 - information_scent_score: 0.3 - review_burden: 4.3 -link_records: - - line: 18 - class: relative - destination: "./local.png" - text: alt text - is_image: true - is_bare_url: false - resolved: false - - line: 20 - class: external_vendor - destination: "https://www.rust-lang.org" - text: rust-lang - is_image: false - is_bare_url: false - resolved: ~ -visuals: - images: 1 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 1 -tables: - count: 1 - max_cells: 6 - table_burden_score: 0.025 - table_scaffold_score: 1 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 89.48933333333332 - section_balance_score: 0.85 - good_scaffold_score: 0.445 - artifact_debt_score: 0.04666666666666666 -grounding: - repository_grounding_score: 0.04000000000000001 - evidence_coverage_score: 0.15934065934065936 -ai_era: - filler_lazy_structure_risk: 0.4620000000000001 - labels: - - large-unanchored-prose - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-repository-grounding - - 0.96 - - - large-unanchored-prose - - 0.9000000000000001 - - - specificity-scarcity - - 0.75 -review: - review_criticality_index: 3.942321428571429 -artifacts: - - id: 0 - kind: image - start_line: 18 - end_line: 18 - language_tag: ~ - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 1 - kind: table - start_line: 24 - end_line: 27 - language_tag: ~ - size: 6 - has_explanation: true - has_label: true - oversized: false - burden: 0.025 - - id: 2 - kind: code - start_line: 35 - end_line: 38 - language_tag: python - size: 2 - has_explanation: true - has_label: true - oversized: false - burden: 1 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 9 - end_line: 9 - language: en - - start_line: 11 - end_line: 11 - language: en - - start_line: 13 - end_line: 13 - language: en - - start_line: 14 - end_line: 14 - language: en - - start_line: 16 - end_line: 16 - language: en - - start_line: 18 - end_line: 18 - language: en - - start_line: 20 - end_line: 20 - language: en - - start_line: 22 - end_line: 22 - language: en - - start_line: 29 - end_line: 29 - language: en - - start_line: 31 - end_line: 31 - language: en - - start_line: 33 - end_line: 33 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.735 - hapax_ratio: 0.705 - dis_ratio: 0.227 - lexical_density: 0.787 - avg_sentence_words: 3.813 - p90_sentence_words: 5 - max_sentence_words: 26 - stddev_sentence_words: 5.844 - avg_word_chars: 4.951 - p90_word_chars: 8 - sentence_count: 16 - words_total: 61 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0.016 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0.016 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.981 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 61 - sentences_counted: 16 - blocks_stripped: - - code - - math - - table diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@heading_skip.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@heading_skip.md.snap deleted file mode 100644 index 08a8a19e..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@heading_skip.md.snap +++ /dev/null @@ -1,204 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 11 - ploc: 6 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 5 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.45454545454545453 -size: - words: 24 - effective_content_units: 0.1 - sections: 3 - headings: 3 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 11 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - word_count: 5 - block_count: 1 - - section_id: 1 - heading_level: 3 - heading_text: ~ - start_line: 5 - end_line: 7 - parent_section_id: 0 - child_section_ids: [] - word_count: 11 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 9 - end_line: 11 - parent_section_id: 0 - child_section_ids: [] - word_count: 8 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 2 - cognitive_complexity: 1 - halstead: - operators_distinct: 4 - operators_total: 6 - operands_distinct: 24 - operands_total: 31 - vocabulary: 28 - length: 37 - volume: 177.87213211613133 - difficulty: 2.5833333333333335 - effort: 459.5030079666726 - embedded_volume: 0 - total_volume: 177.87213211613133 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.25999999999999 - section_balance_score: 0.6499999999999999 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.15 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.52 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 0.85 -review: - review_criticality_index: 1.95 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: en - - start_line: 5 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 9 - end_line: 9 - language: en - - start_line: 11 - end_line: 11 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.71 - hapax_ratio: 0.727 - dis_ratio: 0.182 - lexical_density: 0.677 - avg_sentence_words: 5.167 - p90_sentence_words: 11 - max_sentence_words: 11 - stddev_sentence_words: 3.337 - avg_word_chars: 4.806 - p90_word_chars: 9 - sentence_count: 6 - words_total: 31 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.032 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.969 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 31 - sentences_counted: 6 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@images_no_alt.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@images_no_alt.md.snap deleted file mode 100644 index 5955a5b5..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@images_no_alt.md.snap +++ /dev/null @@ -1,213 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 9 - ploc: 6 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 3 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.3333333333333333 -size: - words: 32 - effective_content_units: 0.13333333333333333 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 9 - parent_section_id: ~ - child_section_ids: [] - word_count: 32 - block_count: 3 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 0.75 - halstead: - operators_distinct: 4 - operators_total: 7 - operands_distinct: 33 - operands_total: 39 - vocabulary: 37 - length: 46 - volume: 239.6348548189317 - difficulty: 2.3636363636363638 - effort: 566.4096568447477 - embedded_volume: 0 - total_volume: 239.6348548189317 -links: - total: 2 - internal: 0 - relative: 2 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 2 - footnote: 0 - bare_url: 0 - broken: 1 - link_debt_score: 0.45 - information_scent_score: 0.44999999999999996 - review_burden: 4.1 -link_records: - - line: 7 - class: relative - destination: "./missing-image.png" - text: broken - is_image: true - is_bare_url: false - resolved: false - - line: 9 - class: relative - destination: code_fences.md - text: alt here - is_image: true - is_bare_url: false - resolved: true -visuals: - images: 2 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0.9694584179118516 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.6248603304939 - section_balance_score: 0.85 - good_scaffold_score: 0.3098646044779629 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.05258928571428571 - evidence_coverage_score: 1 -ai_era: - filler_lazy_structure_risk: 0.3144821428571428 - labels: - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-repository-grounding - - 0.9474107142857143 - - - specificity-scarcity - - 0.7291666666666666 - - - lazy-sectioning - - 0.24999999999999994 -review: - review_criticality_index: 12.139910714285714 -artifacts: - - id: 0 - kind: image - start_line: 7 - end_line: 7 - language_tag: ~ - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 1 - kind: image - start_line: 9 - end_line: 9 - language_tag: ~ - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 9 - end_line: 9 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.784 - hapax_ratio: 0.793 - dis_ratio: 0.172 - lexical_density: 0.595 - avg_sentence_words: 6.167 - p90_sentence_words: 17 - max_sentence_words: 17 - stddev_sentence_words: 5.64 - avg_word_chars: 4.297 - p90_word_chars: 7 - sentence_count: 6 - words_total: 37 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 37 - sentences_counted: 6 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@links_mixed.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@links_mixed.md.snap deleted file mode 100644 index bc7ee311..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@links_mixed.md.snap +++ /dev/null @@ -1,325 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 29 - ploc: 14 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 12 - aloc: 3 -loc_ratios: - artifact_line_ratio: 0.10344827586206896 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.41379310344827586 -size: - words: 44 - effective_content_units: 0.18333333333333332 - sections: 3 - headings: 3 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 29 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - word_count: 38 - block_count: 7 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 19 - end_line: 26 - parent_section_id: 0 - child_section_ids: [] - word_count: 5 - block_count: 4 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 27 - end_line: 29 - parent_section_id: 0 - child_section_ids: [] - word_count: 1 - block_count: 2 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 5 - cognitive_complexity: 6.138999999999999 - halstead: - operators_distinct: 7 - operators_total: 32 - operands_distinct: 51 - operands_total: 61 - vocabulary: 58 - length: 93 - volume: 544.7922325468642 - difficulty: 4.186274509803922 - effort: 2280.649836250108 - embedded_volume: 0 - total_volume: 544.7922325468642 -links: - total: 13 - internal: 2 - relative: 4 - external: 6 - external_vendor: 1 - scholarly: 1 - issue_pr: 1 - absolute_same_repo: 0 - image: 0 - footnote: 1 - bare_url: 1 - broken: 3 - link_debt_score: 0.7536538461538462 - information_scent_score: 0.5038461538461538 - review_burden: 17.8 -link_records: - - line: 3 - class: internal - destination: "#details" - text: Details - is_image: false - is_bare_url: false - resolved: true - - line: 3 - class: internal - destination: "#missing" - text: Broken anchor - is_image: false - is_bare_url: false - resolved: false - - line: 5 - class: relative - destination: links_mixed.md - text: this file - is_image: false - is_bare_url: false - resolved: true - - line: 6 - class: relative - destination: code_fences.md - text: sibling - is_image: false - is_bare_url: false - resolved: true - - line: 6 - class: relative - destination: nowhere.md - text: dead - is_image: false - is_bare_url: false - resolved: false - - line: 8 - class: external - destination: "https://example.com" - text: example - is_image: false - is_bare_url: false - resolved: ~ - - line: 9 - class: external - destination: "https://www.mozilla.org" - text: "https://www.mozilla.org" - is_image: false - is_bare_url: true - resolved: ~ - - line: 11 - class: issue_pr - destination: "https://github.com/foo/bar/issues/42" - text: Ticket 42 - is_image: false - is_bare_url: false - resolved: ~ - - line: 13 - class: scholarly - destination: "https://doi.org/10.1/abc" - text: DOI - is_image: false - is_bare_url: false - resolved: ~ - - line: 15 - class: unresolved_reference_use - destination: "" - text: nope - is_image: false - is_bare_url: false - resolved: false - - line: 15 - class: external - destination: "https://example.org" - text: abc - is_image: false - is_bare_url: false - resolved: ~ - - line: 17 - class: footnote - destination: "1" - text: "[^1]" - is_image: false - is_bare_url: false - resolved: true - - line: 23 - class: reference_definition - destination: "https://example.org" - text: abc-ref - is_image: false - is_bare_url: false - resolved: ~ - - line: 29 - class: external_vendor - destination: "https://developer.mozilla.org/en-US/" - text: MDN - is_image: false - is_bare_url: false - resolved: ~ -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 82.28016483516484 - section_balance_score: 0.85 - good_scaffold_score: 0.12557692307692309 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.10714285714285714 - evidence_coverage_score: 0.4230769230769231 -ai_era: - filler_lazy_structure_risk: 0.45142857142857146 - labels: - - low-artifact-density - - low-repository-grounding - - placeholder-heavy - - specificity-scarcity - top_contributors: - - - low-artifact-density - - 1 - - - specificity-scarcity - - 1 - - - low-repository-grounding - - 0.8928571428571429 -review: - review_criticality_index: 14.500625 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: en - - start_line: 5 - end_line: 6 - language: en - - start_line: 8 - end_line: 9 - language: en - - start_line: 11 - end_line: 11 - language: en - - start_line: 13 - end_line: 13 - language: en - - start_line: 15 - end_line: 15 - language: en - - start_line: 17 - end_line: 17 - language: en - - start_line: 19 - end_line: 19 - language: en - - start_line: 21 - end_line: 21 - language: en - - start_line: 25 - end_line: 25 - language: en - - start_line: 27 - end_line: 27 - language: en - - start_line: 29 - end_line: 29 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.76 - hapax_ratio: 0.769 - dis_ratio: 0.179 - lexical_density: 0.765 - avg_sentence_words: 3.643 - p90_sentence_words: 7 - max_sentence_words: 9 - stddev_sentence_words: 2.409 - avg_word_chars: 5.216 - p90_word_chars: 8 - sentence_count: 14 - words_total: 51 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0.02 - adverb_density: 0.02 - nominalization_density: 0.039 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.971 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 51 - sentences_counted: 14 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@long_linear_filler.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@long_linear_filler.md.snap deleted file mode 100644 index eb18ad8b..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@long_linear_filler.md.snap +++ /dev/null @@ -1,368 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 302 - ploc: 260 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 42 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.1390728476821192 -size: - words: 2664 - effective_content_units: 11.1 - sections: 7 - headings: 7 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 302 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - word_count: 125 - block_count: 2 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 17 - end_line: 51 - parent_section_id: 0 - child_section_ids: [] - word_count: 307 - block_count: 5 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 53 - end_line: 100 - parent_section_id: 0 - child_section_ids: [] - word_count: 455 - block_count: 6 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 102 - end_line: 159 - parent_section_id: 0 - child_section_ids: [] - word_count: 522 - block_count: 7 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 161 - end_line: 213 - parent_section_id: 0 - child_section_ids: [] - word_count: 476 - block_count: 6 - - section_id: 5 - heading_level: 2 - heading_text: ~ - start_line: 215 - end_line: 239 - parent_section_id: 0 - child_section_ids: [] - word_count: 225 - block_count: 3 - - section_id: 6 - heading_level: 2 - heading_text: ~ - start_line: 241 - end_line: 302 - parent_section_id: 0 - child_section_ids: [] - word_count: 554 - block_count: 7 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 6 - cognitive_complexity: 0.2 - halstead: - operators_distinct: 4 - operators_total: 138 - operands_distinct: 720 - operands_total: 2675 - vocabulary: 724 - length: 2813 - volume: 26723.066480365058 - difficulty: 7.430555555555555 - effort: 198567.23009715704 - embedded_volume: 0 - total_volume: 26723.066480365058 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 85.70773749059775 - section_balance_score: 1 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.7210247747747748 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 9 - language: en - - start_line: 11 - end_line: 15 - language: en - - start_line: 17 - end_line: 17 - language: en - - start_line: 19 - end_line: 24 - language: en - - start_line: 26 - end_line: 30 - language: en - - start_line: 32 - end_line: 37 - language: en - - start_line: 39 - end_line: 44 - language: en - - start_line: 46 - end_line: 51 - language: en - - start_line: 53 - end_line: 53 - language: en - - start_line: 55 - end_line: 60 - language: en - - start_line: 62 - end_line: 68 - language: en - - start_line: 70 - end_line: 77 - language: en - - start_line: 79 - end_line: 86 - language: en - - start_line: 88 - end_line: 94 - language: en - - start_line: 96 - end_line: 100 - language: en - - start_line: 102 - end_line: 102 - language: en - - start_line: 104 - end_line: 110 - language: en - - start_line: 112 - end_line: 118 - language: en - - start_line: 120 - end_line: 126 - language: en - - start_line: 128 - end_line: 134 - language: en - - start_line: 136 - end_line: 143 - language: en - - start_line: 145 - end_line: 151 - language: en - - start_line: 153 - end_line: 159 - language: en - - start_line: 161 - end_line: 161 - language: en - - start_line: 163 - end_line: 168 - language: en - - start_line: 170 - end_line: 176 - language: en - - start_line: 178 - end_line: 184 - language: en - - start_line: 186 - end_line: 193 - language: en - - start_line: 195 - end_line: 203 - language: en - - start_line: 205 - end_line: 213 - language: en - - start_line: 215 - end_line: 215 - language: en - - start_line: 217 - end_line: 224 - language: en - - start_line: 226 - end_line: 232 - language: en - - start_line: 234 - end_line: 239 - language: en - - start_line: 241 - end_line: 241 - language: en - - start_line: 243 - end_line: 247 - language: en - - start_line: 249 - end_line: 257 - language: en - - start_line: 259 - end_line: 267 - language: en - - start_line: 269 - end_line: 276 - language: en - - start_line: 278 - end_line: 285 - language: en - - start_line: 287 - end_line: 294 - language: en - - start_line: 296 - end_line: 302 - language: en - english: - readability: - flesch_reading_ease: 37.335 - flesch_kincaid_grade: 13.207 - gunning_fog: 15.921 - smog: 15.053 - ari: 14.208 - coleman_liau: 14.311 - dale_chall_new: 9.904 - dale_chall_list: ngsl-1.2 - forcast: 13.1 - lix: 55.866 - rix: 7.287 - ensemble_grade_band: - - 13.207 - - 15.921 - lexical: - mattr_50: 0.81 - hapax_ratio: 0.525 - dis_ratio: 0.182 - lexical_density: 0.531 - avg_sentence_words: 20.752 - p90_sentence_words: 31 - max_sentence_words: 36 - stddev_sentence_words: 7.387 - avg_word_chars: 5.363 - p90_word_chars: 10 - sentence_count: 129 - words_total: 2677 - wording: - passive_ratio: 0.248 - hedge_density: 0.04 - weasel_density: 0.012 - wordy_density: 0.009 - adverb_density: 0.02 - nominalization_density: 0.049 - expletive_count: 7 - lexical_illusions: 0 - cliche_density: 0.374 - nonword_count: 0 - long_sentence_count: 13 - wording_quality_score: 0.86 - inclusive_language: - flags: - - category: condescending - surface: clearly - preferred: (remove) - count: 1 - - category: condescending - surface: simply - preferred: (remove) - count: 1 - - category: condescending - surface: basic - preferred: (remove or restate) - count: 1 - inclusive_language_score: 0.85 - flag_count: 3 - short_doc_warning: false - japanese: ~ - meta: - short_doc_warning: false - words_counted: 2677 - sentences_counted: 129 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@mixed_bilingual.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@mixed_bilingual.md.snap deleted file mode 100644 index 91752bf4..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@mixed_bilingual.md.snap +++ /dev/null @@ -1,270 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 24 - ploc: 15 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 9 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.375 -size: - words: 82 - effective_content_units: 0.3416666666666667 - sections: 4 - headings: 4 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 24 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - word_count: 2 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 5 - end_line: 12 - parent_section_id: 0 - child_section_ids: [] - word_count: 44 - block_count: 2 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 14 - end_line: 18 - parent_section_id: 0 - child_section_ids: [] - word_count: 6 - block_count: 2 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 20 - end_line: 24 - parent_section_id: 0 - child_section_ids: [] - word_count: 30 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 3 - cognitive_complexity: 0.2 - halstead: - operators_distinct: 5 - operators_total: 16 - operands_distinct: 78 - operands_total: 91 - vocabulary: 83 - length: 107 - volume: 682.129219154121 - difficulty: 2.916666666666667 - effort: 1989.5435558661864 - embedded_volume: 0 - total_volume: 682.129219154121 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.46 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.67 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: mixed - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: ja - - start_line: 5 - end_line: 5 - language: en - - start_line: 7 - end_line: 9 - language: en - - start_line: 11 - end_line: 12 - language: en - - start_line: 14 - end_line: 14 - language: ja - - start_line: 16 - end_line: 16 - language: ja - - start_line: 18 - end_line: 18 - language: ja - - start_line: 20 - end_line: 20 - language: en - - start_line: 22 - end_line: 24 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.898 - hapax_ratio: 0.797 - dis_ratio: 0.125 - lexical_density: 0.711 - avg_sentence_words: 10.375 - p90_sentence_words: 17 - max_sentence_words: 17 - stddev_sentence_words: 6.343 - avg_word_chars: 6.47 - p90_word_chars: 10 - sentence_count: 8 - words_total: 83 - wording: - passive_ratio: 0.25 - hedge_density: 0.048 - weasel_density: 0 - wordy_density: 0.012 - adverb_density: 0.036 - nominalization_density: 0.133 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.848 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: - script_composition: - kanji_ratio: 0.309 - hiragana_ratio: 0.418 - katakana_ratio: 0.273 - latin_ratio: 0 - digit_ratio: 0 - script_entropy: 1.561 - visible_chars: 165 - readability: - tateishi_rs: ~ - jouyou_grade_mean: 2.922 - hyougai_ratio: 0 - lexical: - avg_sentence_chars: 28 - p90_sentence_chars: 61 - max_sentence_chars: 61 - comma_period_ratio: 0.6 - jukugo_density: 0.769 - sentence_count: 6 - char_count: 168 - wording: - politeness_dominant: keitai - keitai_count: 5 - jotai_count: 0 - honorific_count: 0 - keitai_jotai_mix_count: 0 - weak_phrase_count: 0 - redundant_expression_count: 0 - doubled_joshi_count: 3 - long_kanji_run_count: 0 - max_comma_violation_count: 0 - max_ten_violation_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.83 - style_conformance: - violations: - - rule: rule-5-trailing-chouonpu - severity: warn - count: 2 - total_violations: 2 - violation_density_per_1000: 12.121 - short_doc_warning: true - meta: - short_doc_warning: true - words_counted: 251 - sentences_counted: 14 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@navigation_heavy.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@navigation_heavy.md.snap deleted file mode 100644 index c64d4c01..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@navigation_heavy.md.snap +++ /dev/null @@ -1,335 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 29 - ploc: 16 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 9 - aloc: 4 -loc_ratios: - artifact_line_ratio: 0.13793103448275862 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.3103448275862069 -size: - words: 75 - effective_content_units: 0.3125 - sections: 4 - headings: 4 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 29 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - word_count: 21 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 7 - end_line: 10 - parent_section_id: 0 - child_section_ids: [] - word_count: 14 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 12 - end_line: 16 - parent_section_id: 0 - child_section_ids: [] - word_count: 14 - block_count: 1 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 18 - end_line: 29 - parent_section_id: 0 - child_section_ids: [] - word_count: 26 - block_count: 7 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 7 - cognitive_complexity: 7.399999999999999 - halstead: - operators_distinct: 6 - operators_total: 39 - operands_distinct: 78 - operands_total: 93 - vocabulary: 84 - length: 132 - volume: 843.7858998067965 - difficulty: 3.5769230769230766 - effort: 3018.157257001233 - embedded_volume: 0 - total_volume: 843.7858998067965 -links: - total: 14 - internal: 2 - relative: 5 - external: 5 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 2 - bare_url: 0 - broken: 5 - link_debt_score: 0.55 - information_scent_score: 0.5 - review_burden: 23.1 -link_records: - - line: 9 - class: internal - destination: "#install" - text: installation - is_image: false - is_bare_url: false - resolved: true - - line: 9 - class: internal - destination: "#usage" - text: usage - is_image: false - is_bare_url: false - resolved: true - - line: 10 - class: relative - destination: "./architecture.md#runtime" - text: architecture doc - is_image: false - is_bare_url: false - resolved: false - - line: 14 - class: external - destination: "https://docs.example.com/install" - text: official docs - is_image: false - is_bare_url: false - resolved: ~ - - line: 15 - class: relative - destination: "../scripts/setup.sh" - text: setup script - is_image: false - is_bare_url: false - resolved: false - - line: 16 - class: relative - destination: "../CONTRIBUTING.md" - text: contributing - is_image: false - is_bare_url: false - resolved: false - - line: 20 - class: relative - destination: "./quickstart.md" - text: quickstart - is_image: false - is_bare_url: false - resolved: false - - line: 20 - class: external - destination: "https://api.example.com/reference" - text: API reference - is_image: false - is_bare_url: false - resolved: ~ - - line: 21 - class: external - destination: "https://vendor-a.com/api" - text: vendor-a - is_image: false - is_bare_url: false - resolved: ~ - - line: 22 - class: external - destination: "https://vendor-b.org" - text: vendor-b - is_image: false - is_bare_url: false - resolved: ~ - - line: 22 - class: external - destination: "https://vendor-c.io" - text: vendor-c - is_image: false - is_bare_url: false - resolved: ~ - - line: 24 - class: footnote - destination: "1" - text: "[^1]" - is_image: false - is_bare_url: false - resolved: true - - line: 24 - class: footnote - destination: "2" - text: "[^2]" - is_image: false - is_bare_url: false - resolved: true - - line: 27 - class: relative - destination: "./adr/007.md" - text: adr-007 - is_image: false - is_bare_url: false - resolved: false - - line: 29 - class: reference_definition - destination: "https://api.example.com/reference" - text: api-ref - is_image: false - is_bare_url: false - resolved: ~ -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 85.954 - section_balance_score: 0.85 - good_scaffold_score: 0.175 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.010000000000000002 - evidence_coverage_score: 0.5576923076923077 -ai_era: - filler_lazy_structure_risk: 0.45799999999999996 - labels: - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-artifact-density - - 1 - - - low-repository-grounding - - 0.99 - - - specificity-scarcity - - 0.9166666666666666 -review: - review_criticality_index: 16.013928571428572 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 9 - end_line: 10 - language: en - - start_line: 12 - end_line: 12 - language: en - - start_line: 14 - end_line: 16 - language: en - - start_line: 18 - end_line: 18 - language: en - - start_line: 20 - end_line: 22 - language: en - - start_line: 24 - end_line: 24 - language: en - - start_line: 26 - end_line: 26 - language: en - - start_line: 27 - end_line: 27 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.79 - hapax_ratio: 0.773 - dis_ratio: 0.182 - lexical_density: 0.77 - avg_sentence_words: 7.25 - p90_sentence_words: 14 - max_sentence_words: 21 - stddev_sentence_words: 5.988 - avg_word_chars: 5.506 - p90_word_chars: 9 - sentence_count: 12 - words_total: 87 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0.011 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0.057 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.996 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 87 - sentences_counted: 12 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@near_duplicate_paragraphs.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@near_duplicate_paragraphs.md.snap deleted file mode 100644 index 0c247495..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@near_duplicate_paragraphs.md.snap +++ /dev/null @@ -1,250 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 27 - ploc: 14 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 13 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.48148148148148145 -size: - words: 369 - effective_content_units: 1.5375 - sections: 5 - headings: 5 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 27 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - word_count: 86 - block_count: 2 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 7 - end_line: 11 - parent_section_id: 0 - child_section_ids: [] - word_count: 90 - block_count: 2 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 13 - end_line: 17 - parent_section_id: 0 - child_section_ids: [] - word_count: 82 - block_count: 2 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 19 - end_line: 23 - parent_section_id: 0 - child_section_ids: [] - word_count: 66 - block_count: 2 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 25 - end_line: 27 - parent_section_id: 0 - child_section_ids: [] - word_count: 45 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 4 - cognitive_complexity: 0.2 - halstead: - operators_distinct: 4 - operators_total: 33 - operands_distinct: 159 - operands_total: 378 - vocabulary: 163 - length: 411 - volume: 3020.327271388973 - difficulty: 4.754716981132075 - effort: 14360.801365849455 - embedded_volume: 0 - total_volume: 3020.327271388973 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.8454104088815 - section_balance_score: 1 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.76 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - near-duplicate-paragraphs - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: en - - start_line: 5 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 9 - end_line: 9 - language: en - - start_line: 11 - end_line: 11 - language: en - - start_line: 13 - end_line: 13 - language: en - - start_line: 15 - end_line: 15 - language: en - - start_line: 17 - end_line: 17 - language: en - - start_line: 19 - end_line: 19 - language: en - - start_line: 21 - end_line: 21 - language: en - - start_line: 23 - end_line: 23 - language: en - - start_line: 25 - end_line: 25 - language: en - - start_line: 27 - end_line: 27 - language: en - english: - readability: - flesch_reading_ease: 46.52 - flesch_kincaid_grade: 9.8 - gunning_fog: 10.168 - smog: 11.143 - ari: 9.961 - coleman_liau: 13.35 - dale_chall_new: 10.549 - dale_chall_list: ngsl-1.2 - forcast: 11.7 - lix: 48.172 - rix: 4.387 - ensemble_grade_band: - - 9.8 - - 13.35 - lexical: - mattr_50: 0.753 - hapax_ratio: 0.381 - dis_ratio: 0.439 - lexical_density: 0.614 - avg_sentence_words: 12.194 - p90_sentence_words: 18 - max_sentence_words: 22 - stddev_sentence_words: 5.772 - avg_word_chars: 5.37 - p90_word_chars: 8 - sentence_count: 31 - words_total: 378 - wording: - passive_ratio: 0.387 - hedge_density: 0.003 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.005 - nominalization_density: 0.024 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.929 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: false - japanese: ~ - meta: - short_doc_warning: false - words_counted: 378 - sentences_counted: 31 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@passive_heavy.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@passive_heavy.md.snap deleted file mode 100644 index d090c1d0..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@passive_heavy.md.snap +++ /dev/null @@ -1,185 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 22 - ploc: 17 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 5 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.22727272727272727 -size: - words: 151 - effective_content_units: 0.6291666666666667 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 22 - parent_section_id: ~ - child_section_ids: [] - word_count: 151 - block_count: 5 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 0 - halstead: - operators_distinct: 2 - operators_total: 22 - operands_distinct: 97 - operands_total: 153 - vocabulary: 99 - length: 175 - volume: 1160.1374085139316 - difficulty: 1.577319587628866 - effort: 1829.9074587900159 - embedded_volume: 0 - total_volume: 1160.1374085139316 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 91.51 - section_balance_score: 1 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.7075 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - - start_line: 7 - end_line: 9 - language: en - - start_line: 11 - end_line: 13 - language: en - - start_line: 15 - end_line: 18 - language: en - - start_line: 20 - end_line: 22 - language: en - english: - readability: - flesch_reading_ease: 53.023 - flesch_kincaid_grade: 7.636 - gunning_fog: 9.479 - smog: ~ - ari: 7.248 - coleman_liau: 11.4 - dale_chall_new: 12.841 - dale_chall_list: ngsl-1.2 - forcast: 11.4 - lix: 43.442 - rix: 2.591 - ensemble_grade_band: - - 7.248 - - 11.4 - lexical: - mattr_50: 0.739 - hapax_ratio: 0.91 - dis_ratio: 0.03 - lexical_density: 0.592 - avg_sentence_words: 7.136 - p90_sentence_words: 8 - max_sentence_words: 11 - stddev_sentence_words: 1.391 - avg_word_chars: 5.331 - p90_word_chars: 10 - sentence_count: 22 - words_total: 157 - wording: - passive_ratio: 0.909 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.006 - nominalization_density: 0.032 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.82 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: false - japanese: ~ - meta: - short_doc_warning: false - words_counted: 157 - sentences_counted: 22 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@placeholder_heavy.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@placeholder_heavy.md.snap deleted file mode 100644 index 50fb136b..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@placeholder_heavy.md.snap +++ /dev/null @@ -1,383 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 58 - ploc: 38 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 20 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.3448275862068966 -size: - words: 217 - effective_content_units: 0.9041666666666667 - sections: 9 - headings: 9 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 58 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - - 5 - - 8 - word_count: 19 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 6 - end_line: 16 - parent_section_id: 0 - child_section_ids: [] - word_count: 49 - block_count: 6 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 18 - end_line: 25 - parent_section_id: 0 - child_section_ids: [] - word_count: 50 - block_count: 2 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 27 - end_line: 30 - parent_section_id: 0 - child_section_ids: [] - word_count: 12 - block_count: 1 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 32 - end_line: 37 - parent_section_id: 0 - child_section_ids: [] - word_count: 27 - block_count: 2 - - section_id: 5 - heading_level: 2 - heading_text: ~ - start_line: 39 - end_line: 50 - parent_section_id: 0 - child_section_ids: - - 6 - - 7 - word_count: 21 - block_count: 1 - - section_id: 6 - heading_level: 3 - heading_text: ~ - start_line: 44 - end_line: 46 - parent_section_id: 5 - child_section_ids: [] - word_count: 8 - block_count: 1 - - section_id: 7 - heading_level: 3 - heading_text: ~ - start_line: 48 - end_line: 50 - parent_section_id: 5 - child_section_ids: [] - word_count: 9 - block_count: 1 - - section_id: 8 - heading_level: 2 - heading_text: ~ - start_line: 52 - end_line: 58 - parent_section_id: 0 - child_section_ids: [] - word_count: 22 - block_count: 6 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 10 - cognitive_complexity: 7.759999999999999 - halstead: - operators_distinct: 8 - operators_total: 67 - operands_distinct: 152 - operands_total: 240 - vocabulary: 160 - length: 307 - volume: 2247.83192513042 - difficulty: 6.315789473684211 - effort: 14196.833211350022 - embedded_volume: 0 - total_volume: 2247.83192513042 -links: - total: 7 - internal: 0 - relative: 7 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 7 - link_debt_score: 0.45 - information_scent_score: 0.3 - review_burden: 23.1 -link_records: - - line: 15 - class: relative - destination: TBD - text: the CI dashboard - is_image: false - is_bare_url: false - resolved: false - - line: 16 - class: relative - destination: FIXME - text: rollback flow - is_image: false - is_bare_url: false - resolved: false - - line: 16 - class: relative - destination: TODO - text: incident response - is_image: false - is_bare_url: false - resolved: false - - line: 37 - class: relative - destination: TBD - text: historical rollback notes - is_image: false - is_bare_url: false - resolved: false - - line: 37 - class: relative - destination: TODO - text: postmortems - is_image: false - is_bare_url: false - resolved: false - - line: 57 - class: relative - destination: TBD - text: placeholder entry - is_image: false - is_bare_url: false - resolved: false - - line: 58 - class: relative - destination: "" - text: another placeholder - is_image: false - is_bare_url: false - resolved: false -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 83.46999999999998 - section_balance_score: 0.85 - good_scaffold_score: 0.045 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.6900000000000001 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - placeholder-heavy - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 10.864285714285716 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 4 - language: en - - start_line: 6 - end_line: 6 - language: en - - start_line: 8 - end_line: 9 - language: en - - start_line: 11 - end_line: 11 - language: en - - start_line: 12 - end_line: 12 - language: en - - start_line: 13 - end_line: 13 - language: en - - start_line: 15 - end_line: 16 - language: en - - start_line: 18 - end_line: 18 - language: en - - start_line: 20 - end_line: 22 - language: en - - start_line: 24 - end_line: 25 - language: en - - start_line: 27 - end_line: 27 - language: en - - start_line: 29 - end_line: 30 - language: en - - start_line: 32 - end_line: 32 - language: en - - start_line: 34 - end_line: 35 - language: en - - start_line: 37 - end_line: 37 - language: en - - start_line: 39 - end_line: 39 - language: en - - start_line: 41 - end_line: 42 - language: en - - start_line: 44 - end_line: 44 - language: en - - start_line: 46 - end_line: 46 - language: en - - start_line: 48 - end_line: 48 - language: en - - start_line: 50 - end_line: 50 - language: en - - start_line: 52 - end_line: 52 - language: en - - start_line: 54 - end_line: 54 - language: en - - start_line: 55 - end_line: 55 - language: en - - start_line: 56 - end_line: 56 - language: en - - start_line: 57 - end_line: 57 - language: en - - start_line: 58 - end_line: 58 - language: en - english: - readability: - flesch_reading_ease: 54.776 - flesch_kincaid_grade: 7.136 - gunning_fog: 8.477 - smog: 8.766 - ari: 6.411 - coleman_liau: 10.298 - dale_chall_new: 12.039 - dale_chall_list: ngsl-1.2 - forcast: 12.2 - lix: 33.691 - rix: 1.684 - ensemble_grade_band: - - 6.411 - - 10.298 - lexical: - mattr_50: 0.833 - hapax_ratio: 0.746 - dis_ratio: 0.141 - lexical_density: 0.685 - avg_sentence_words: 6.105 - p90_sentence_words: 14 - max_sentence_words: 21 - stddev_sentence_words: 4.57 - avg_word_chars: 5.263 - p90_word_chars: 9 - sentence_count: 38 - words_total: 232 - wording: - passive_ratio: 0.105 - hedge_density: 0.009 - weasel_density: 0.009 - wordy_density: 0.004 - adverb_density: 0.004 - nominalization_density: 0.034 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: false - japanese: ~ - meta: - short_doc_warning: false - words_counted: 232 - sentences_counted: 38 - blocks_stripped: - - code diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@pure_prose.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@pure_prose.md.snap deleted file mode 100644 index 3cc08264..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@pure_prose.md.snap +++ /dev/null @@ -1,179 +0,0 @@ ---- -source: src/markdown/tests/mod.rs ---- -path: "" -loc: - dloc: 7 - ploc: 4 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 3 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.42857142857142855 -size: - words: 27 - effective_content_units: 0.1125 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 7 - parent_section_id: ~ - child_section_ids: [] - word_count: 27 - block_count: 3 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 0 - halstead: - operators_distinct: 3 - operators_total: 5 - operands_distinct: 24 - operands_total: 30 - vocabulary: 27 - length: 35 - volume: 166.42106257572138 - difficulty: 1.875 - effort: 312.0394923294776 - embedded_volume: 0 - total_volume: 166.42106257572138 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.01 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.7075 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: en - - start_line: 5 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.733 - hapax_ratio: 0.773 - dis_ratio: 0.091 - lexical_density: 0.8 - avg_sentence_words: 7.5 - p90_sentence_words: 10 - max_sentence_words: 10 - stddev_sentence_words: 2.693 - avg_word_chars: 5.633 - p90_word_chars: 9 - sentence_count: 4 - words_total: 30 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 30 - sentences_counted: 4 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@readme_en.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@readme_en.md.snap deleted file mode 100644 index d501f989..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@readme_en.md.snap +++ /dev/null @@ -1,243 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 32 - ploc: 21 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 11 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.34375 -size: - words: 149 - effective_content_units: 0.6208333333333333 - sections: 5 - headings: 5 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 32 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - word_count: 21 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 7 - end_line: 10 - parent_section_id: 0 - child_section_ids: [] - word_count: 20 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 12 - end_line: 19 - parent_section_id: 0 - child_section_ids: [] - word_count: 46 - block_count: 2 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 21 - end_line: 27 - parent_section_id: 0 - child_section_ids: [] - word_count: 45 - block_count: 2 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 29 - end_line: 32 - parent_section_id: 0 - child_section_ids: [] - word_count: 17 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 4 - cognitive_complexity: 0.2 - halstead: - operators_distinct: 3 - operators_total: 22 - operands_distinct: 126 - operands_total: 155 - vocabulary: 129 - length: 177 - volume: 1240.987224209916 - difficulty: 1.8452380952380953 - effort: 2289.9169018159164 - embedded_volume: 0 - total_volume: 1240.987224209916 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.75999999999999 - section_balance_score: 0.88 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.67 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - - start_line: 7 - end_line: 7 - language: en - - start_line: 9 - end_line: 10 - language: en - - start_line: 12 - end_line: 12 - language: en - - start_line: 14 - end_line: 16 - language: en - - start_line: 18 - end_line: 19 - language: en - - start_line: 21 - end_line: 21 - language: en - - start_line: 23 - end_line: 24 - language: en - - start_line: 26 - end_line: 27 - language: en - - start_line: 29 - end_line: 29 - language: en - - start_line: 31 - end_line: 32 - language: en - english: - readability: - flesch_reading_ease: 43.453 - flesch_kincaid_grade: 8.96 - gunning_fog: 10.272 - smog: ~ - ari: 9.258 - coleman_liau: 13.911 - dale_chall_new: 10.365 - dale_chall_list: ngsl-1.2 - forcast: 13.2 - lix: 48.117 - rix: 2.909 - ensemble_grade_band: - - 8.96 - - 13.911 - lexical: - mattr_50: 0.864 - hapax_ratio: 0.85 - dis_ratio: 0.1 - lexical_density: 0.673 - avg_sentence_words: 7.091 - p90_sentence_words: 12 - max_sentence_words: 16 - stddev_sentence_words: 4.067 - avg_word_chars: 5.769 - p90_word_chars: 9 - sentence_count: 22 - words_total: 156 - wording: - passive_ratio: 0.091 - hedge_density: 0.019 - weasel_density: 0 - wordy_density: 0.006 - adverb_density: 0.006 - nominalization_density: 0.058 - expletive_count: 1 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: false - japanese: ~ - meta: - short_doc_warning: false - words_counted: 156 - sentences_counted: 22 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@readme_ja.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@readme_ja.md.snap deleted file mode 100644 index a31ebe7d..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@readme_ja.md.snap +++ /dev/null @@ -1,242 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 23 - ploc: 12 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 11 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.4782608695652174 -size: - words: 23 - effective_content_units: 0.09583333333333334 - sections: 5 - headings: 5 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 23 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - word_count: 3 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 5 - end_line: 7 - parent_section_id: 0 - child_section_ids: [] - word_count: 3 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 9 - end_line: 13 - parent_section_id: 0 - child_section_ids: [] - word_count: 7 - block_count: 2 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 15 - end_line: 19 - parent_section_id: 0 - child_section_ids: [] - word_count: 7 - block_count: 2 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 21 - end_line: 23 - parent_section_id: 0 - child_section_ids: [] - word_count: 3 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 4 - cognitive_complexity: 0.2 - halstead: - operators_distinct: 3 - operators_total: 22 - operands_distinct: 28 - operands_total: 28 - vocabulary: 31 - length: 50 - volume: 247.70981551934375 - difficulty: 1.5 - effort: 371.56472327901565 - embedded_volume: 0 - total_volume: 247.70981551934375 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.70626086956521 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.035217391304347825 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.6494782608695653 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 0.9647826086956521 -review: - review_criticality_index: 0.4578260869565217 -artifacts: [] -prose: - language_detection: - dominant_language: ja - blocks: - - start_line: 1 - end_line: 1 - language: ja - - start_line: 3 - end_line: 3 - language: ja - - start_line: 5 - end_line: 5 - language: ja - - start_line: 7 - end_line: 7 - language: ja - - start_line: 9 - end_line: 9 - language: ja - - start_line: 11 - end_line: 11 - language: ja - - start_line: 13 - end_line: 13 - language: ja - - start_line: 15 - end_line: 15 - language: ja - - start_line: 17 - end_line: 17 - language: ja - - start_line: 19 - end_line: 19 - language: ja - - start_line: 21 - end_line: 21 - language: ja - - start_line: 23 - end_line: 23 - language: ja - english: ~ - japanese: - script_composition: - kanji_ratio: 0.216 - hiragana_ratio: 0.344 - katakana_ratio: 0.411 - latin_ratio: 0.026 - digit_ratio: 0.004 - script_entropy: 1.701 - visible_chars: 509 - readability: - tateishi_rs: 39.972 - jouyou_grade_mean: 4 - hyougai_ratio: 0.027 - lexical: - avg_sentence_chars: 23.364 - p90_sentence_chars: 36 - max_sentence_chars: 42 - comma_period_ratio: 0.294 - jukugo_density: 0.709 - sentence_count: 22 - char_count: 514 - wording: - politeness_dominant: keitai - keitai_count: 10 - jotai_count: 0 - honorific_count: 0 - keitai_jotai_mix_count: 0 - weak_phrase_count: 0 - redundant_expression_count: 1 - doubled_joshi_count: 6 - long_kanji_run_count: 0 - max_comma_violation_count: 0 - max_ten_violation_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.724 - style_conformance: - violations: - - rule: rule-3-jouyou-only - severity: warn - count: 3 - - rule: rule-5-trailing-chouonpu - severity: warn - count: 6 - total_violations: 9 - violation_density_per_1000: 17.682 - short_doc_warning: false - meta: - short_doc_warning: false - words_counted: 514 - sentences_counted: 22 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@short_doc.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@short_doc.md.snap deleted file mode 100644 index c944f4b5..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@short_doc.md.snap +++ /dev/null @@ -1,173 +0,0 @@ ---- -source: src/markdown/tests/mod.rs ---- -path: "" -loc: - dloc: 4 - ploc: 3 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 1 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.25 -size: - words: 20 - effective_content_units: 0.08333333333333333 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 4 - parent_section_id: ~ - child_section_ids: [] - word_count: 20 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 0 - halstead: - operators_distinct: 2 - operators_total: 5 - operands_distinct: 21 - operands_total: 22 - vocabulary: 23 - length: 27 - volume: 122.13617281353935 - difficulty: 1.0476190476190477 - effort: 127.95218104275551 - embedded_volume: 0 - total_volume: 122.13617281353935 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.01 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.7075 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 4 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.909 - hapax_ratio: 0.9 - dis_ratio: 0.1 - lexical_density: 0.545 - avg_sentence_words: 4.4 - p90_sentence_words: 6 - max_sentence_words: 6 - stddev_sentence_words: 1.96 - avg_word_chars: 4.136 - p90_word_chars: 7 - sentence_count: 5 - words_total: 22 - wording: - passive_ratio: 0 - hedge_density: 0.091 - weasel_density: 0.091 - wordy_density: 0.045 - adverb_density: 0 - nominalization_density: 0.045 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.624 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 22 - sentences_counted: 5 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@small_dense_valuable.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@small_dense_valuable.md.snap deleted file mode 100644 index 6e4977c7..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@small_dense_valuable.md.snap +++ /dev/null @@ -1,491 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 139 - ploc: 49 - cloc: 39 - tloc: 12 - mloc: 0 - bloc: 39 - aloc: 51 -loc_ratios: - artifact_line_ratio: 0.3669064748201439 - code_line_ratio: 0.2805755395683453 - table_line_ratio: 0.08633093525179857 - math_line_ratio: 0 - blank_line_ratio: 0.2805755395683453 -size: - words: 280 - effective_content_units: 16.616666666666664 - sections: 9 - headings: 9 -ecu_inputs: - table_cells: 30 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 139 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - word_count: 32 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 8 - end_line: 23 - parent_section_id: 0 - child_section_ids: [] - word_count: 28 - block_count: 5 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 25 - end_line: 41 - parent_section_id: 0 - child_section_ids: [] - word_count: 33 - block_count: 5 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 43 - end_line: 55 - parent_section_id: 0 - child_section_ids: [] - word_count: 35 - block_count: 3 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 57 - end_line: 69 - parent_section_id: 0 - child_section_ids: [] - word_count: 16 - block_count: 4 - - section_id: 5 - heading_level: 2 - heading_text: ~ - start_line: 71 - end_line: 80 - parent_section_id: 0 - child_section_ids: [] - word_count: 18 - block_count: 3 - - section_id: 6 - heading_level: 2 - heading_text: ~ - start_line: 82 - end_line: 109 - parent_section_id: 0 - child_section_ids: [] - word_count: 52 - block_count: 9 - - section_id: 7 - heading_level: 2 - heading_text: ~ - start_line: 110 - end_line: 130 - parent_section_id: 0 - child_section_ids: [] - word_count: 54 - block_count: 5 - - section_id: 8 - heading_level: 2 - heading_text: ~ - start_line: 132 - end_line: 139 - parent_section_id: 0 - child_section_ids: [] - word_count: 12 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 12 - cognitive_complexity: 13.651249999999997 - halstead: - operators_distinct: 14 - operators_total: 132 - operands_distinct: 256 - operands_total: 363 - vocabulary: 270 - length: 495 - volume: 3998.023720540162 - difficulty: 9.92578125 - effort: 39683.50888239278 - embedded_volume: 0 - total_volume: 3998.023720540162 -links: - total: 4 - internal: 0 - relative: 4 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 4 - link_debt_score: 0.45 - information_scent_score: 0.3 - review_burden: 13.2 -link_records: - - line: 5 - class: relative - destination: "../README.md" - text: ophidiarium/mehen - is_image: false - is_bare_url: false - resolved: false - - line: 27 - class: relative - destination: "../README.md" - text: migrations/0018_docs_index.sql - is_image: false - is_bare_url: false - resolved: false - - line: 79 - class: relative - destination: "../docs/mehen_markdown_metrics_research_foundation.md" - text: docs/mehen_markdown_metrics_research_foundation.md - is_image: false - is_bare_url: false - resolved: false - - line: 101 - class: relative - destination: "../README.md" - text: config/defaults.yaml - is_image: false - is_bare_url: false - resolved: false -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 2 - max_cells: 15 - table_burden_score: 0.016666666666666666 - table_scaffold_score: 1 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 92.90783337218346 - section_balance_score: 0.85 - good_scaffold_score: 0.445 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.2 - evidence_coverage_score: 0.6666666666666667 -ai_era: - filler_lazy_structure_risk: 0.16000000000000003 - labels: - - low-repository-grounding - top_contributors: - - - low-repository-grounding - - 0.8 - - - hollow-references - - 0 - - - large-unanchored-prose - - 0 -review: - review_criticality_index: 26.802343750000002 -artifacts: - - id: 0 - kind: code - start_line: 12 - end_line: 15 - language_tag: bash - size: 2 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 1 - kind: code - start_line: 19 - end_line: 21 - language_tag: bash - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 2 - kind: code - start_line: 30 - end_line: 32 - language_tag: sh - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 3 - kind: code - start_line: 36 - end_line: 38 - language_tag: sql - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 4 - kind: code - start_line: 48 - end_line: 50 - language_tag: sh - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 5 - kind: code - start_line: 61 - end_line: 63 - language_tag: bash - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 6 - kind: code - start_line: 67 - end_line: 69 - language_tag: json - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 7 - kind: code - start_line: 75 - end_line: 77 - language_tag: bash - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 8 - kind: code - start_line: 87 - end_line: 97 - language_tag: yaml - size: 9 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 9 - kind: code - start_line: 115 - end_line: 117 - language_tag: sh - size: 1 - has_explanation: true - has_label: true - oversized: false - burden: 1 - - id: 10 - kind: table - start_line: 121 - end_line: 126 - language_tag: ~ - size: 15 - has_explanation: true - has_label: true - oversized: false - burden: 0.016666666666666666 - - id: 11 - kind: table - start_line: 134 - end_line: 139 - language_tag: ~ - size: 15 - has_explanation: true - has_label: true - oversized: false - burden: 0.016666666666666666 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 6 - language: en - - start_line: 8 - end_line: 8 - language: en - - start_line: 10 - end_line: 10 - language: en - - start_line: 17 - end_line: 17 - language: en - - start_line: 23 - end_line: 23 - language: en - - start_line: 25 - end_line: 25 - language: en - - start_line: 27 - end_line: 28 - language: en - - start_line: 34 - end_line: 34 - language: en - - start_line: 40 - end_line: 41 - language: en - - start_line: 43 - end_line: 43 - language: en - - start_line: 45 - end_line: 46 - language: en - - start_line: 52 - end_line: 55 - language: en - - start_line: 57 - end_line: 57 - language: en - - start_line: 59 - end_line: 59 - language: en - - start_line: 65 - end_line: 65 - language: en - - start_line: 71 - end_line: 71 - language: en - - start_line: 73 - end_line: 73 - language: en - - start_line: 79 - end_line: 80 - language: en - - start_line: 82 - end_line: 82 - language: en - - start_line: 84 - end_line: 85 - language: en - - start_line: 99 - end_line: 101 - language: en - - start_line: 103 - end_line: 103 - language: en - - start_line: 105 - end_line: 105 - language: en - - start_line: 106 - end_line: 106 - language: en - - start_line: 107 - end_line: 107 - language: en - - start_line: 108 - end_line: 108 - language: en - - start_line: 110 - end_line: 110 - language: en - - start_line: 112 - end_line: 113 - language: en - - start_line: 119 - end_line: 119 - language: en - - start_line: 128 - end_line: 130 - language: en - - start_line: 132 - end_line: 132 - language: en - english: - readability: - flesch_reading_ease: 62.228 - flesch_kincaid_grade: 6.238 - gunning_fog: 7.314 - smog: 8.623 - ari: 5.74 - coleman_liau: 9.518 - dale_chall_new: 10.709 - dale_chall_list: ngsl-1.2 - forcast: 11.3 - lix: 33.641 - rix: 1.8 - ensemble_grade_band: - - 5.74 - - 9.518 - lexical: - mattr_50: 0.792 - hapax_ratio: 0.736 - dis_ratio: 0.172 - lexical_density: 0.67 - avg_sentence_words: 6.675 - p90_sentence_words: 12 - max_sentence_words: 21 - stddev_sentence_words: 4.692 - avg_word_chars: 5.075 - p90_word_chars: 8 - sentence_count: 40 - words_total: 267 - wording: - passive_ratio: 0 - hedge_density: 0.007 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.004 - nominalization_density: 0.037 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: false - japanese: ~ - meta: - short_doc_warning: false - words_counted: 267 - sentences_counted: 40 - blocks_stripped: - - code - - table diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@table_large.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@table_large.md.snap deleted file mode 100644 index 0e21d2e6..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@table_large.md.snap +++ /dev/null @@ -1,182 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 14 - ploc: 4 - cloc: 0 - tloc: 8 - mloc: 0 - bloc: 2 - aloc: 8 -loc_ratios: - artifact_line_ratio: 0.5714285714285714 - code_line_ratio: 0 - table_line_ratio: 0.5714285714285714 - math_line_ratio: 0 - blank_line_ratio: 0.14285714285714285 -size: - words: 125 - effective_content_units: 5.980833333333333 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 91 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 14 - parent_section_id: ~ - child_section_ids: [] - word_count: 125 - block_count: 2 -complexity: - reading_path_complexity: 2 - reading_path_complexity_raw: 2 - cognitive_complexity: 1.3219413178184862 - halstead: - operators_distinct: 5 - operators_total: 24 - operands_distinct: 68 - operands_total: 141 - vocabulary: 73 - length: 165 - volume: 1021.3210522152029 - difficulty: 5.183823529411765 - effort: 5294.348101556751 - embedded_volume: 0 - total_volume: 1021.3210522152029 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 1 - max_cells: 91 - table_burden_score: 0.2861378205128205 - table_scaffold_score: 0.7416666666666667 - hard_warnings: 1 -maintainability: - documentation_maintainability_index: 94.57195512820513 - section_balance_score: 1 - good_scaffold_score: 0.14833333333333334 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0.6153846153846154 -ai_era: - filler_lazy_structure_risk: 0.3375 - labels: - - low-artifact-density - - low-repository-grounding - top_contributors: - - - low-repository-grounding - - 1 - - - low-artifact-density - - 0.6666666666666667 - - - lazy-sectioning - - 0.24999999999999994 -review: - review_criticality_index: 6.000000000000001 -artifacts: - - id: 0 - kind: table - start_line: 7 - end_line: 14 - language_tag: ~ - size: 91 - has_explanation: true - has_label: true - oversized: false - burden: 0.2861378205128205 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 5 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.821 - hapax_ratio: 0.844 - dis_ratio: 0.094 - lexical_density: 0.692 - avg_sentence_words: 13 - p90_sentence_words: 28 - max_sentence_words: 28 - stddev_sentence_words: 10.801 - avg_word_chars: 4.282 - p90_word_chars: 7 - sentence_count: 3 - words_total: 39 - wording: - passive_ratio: 0 - hedge_density: 0.026 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0.026 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.972 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 39 - sentences_counted: 3 - blocks_stripped: - - table diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@table_mixed.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@table_mixed.md.snap deleted file mode 100644 index 3ffe9010..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@table_mixed.md.snap +++ /dev/null @@ -1,186 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 10 - ploc: 3 - cloc: 0 - tloc: 4 - mloc: 0 - bloc: 3 - aloc: 4 -loc_ratios: - artifact_line_ratio: 0.4 - code_line_ratio: 0 - table_line_ratio: 0.4 - math_line_ratio: 0 - blank_line_ratio: 0.3 -size: - words: 26 - effective_content_units: 0.6483333333333334 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 9 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 10 - parent_section_id: ~ - child_section_ids: [] - word_count: 26 - block_count: 3 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 0.7265624999999999 - halstead: - operators_distinct: 5 - operators_total: 10 - operands_distinct: 28 - operands_total: 32 - vocabulary: 33 - length: 42 - volume: 211.86455301305503 - difficulty: 2.8571428571428568 - effort: 605.3272943230143 - embedded_volume: 0 - total_volume: 211.86455301305503 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 1 - max_cells: 9 - table_burden_score: 0.05 - table_scaffold_score: 1 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 95.07307692307693 - section_balance_score: 0.85 - good_scaffold_score: 0.2 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0.6153846153846154 -ai_era: - filler_lazy_structure_risk: 0.41057692307692306 - labels: - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - low-repository-grounding - - 1 - - - low-artifact-density - - 0.6666666666666667 - - - specificity-scarcity - - 0.6089743589743589 -review: - review_criticality_index: 6.000000000000001 -artifacts: - - id: 0 - kind: table - start_line: 5 - end_line: 8 - language_tag: ~ - size: 9 - has_explanation: true - has_label: true - oversized: false - burden: 0.05 -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: en - - start_line: 10 - end_line: 10 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 0.8 - hapax_ratio: 0.833 - dis_ratio: 0.083 - lexical_density: 0.733 - avg_sentence_words: 5 - p90_sentence_words: 7 - max_sentence_words: 7 - stddev_sentence_words: 1.633 - avg_word_chars: 5.2 - p90_word_chars: 8 - sentence_count: 3 - words_total: 15 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 15 - sentences_counted: 3 - blocks_stripped: - - table diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@tateishi_sample.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@tateishi_sample.md.snap deleted file mode 100644 index 3fa36cb3..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@tateishi_sample.md.snap +++ /dev/null @@ -1,251 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 23 - ploc: 12 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 11 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.4782608695652174 -size: - words: 47 - effective_content_units: 0.19583333333333333 - sections: 6 - headings: 6 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 23 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - - 4 - - 5 - word_count: 5 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 5 - end_line: 7 - parent_section_id: 0 - child_section_ids: [] - word_count: 6 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 9 - end_line: 11 - parent_section_id: 0 - child_section_ids: [] - word_count: 8 - block_count: 1 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 13 - end_line: 15 - parent_section_id: 0 - child_section_ids: [] - word_count: 12 - block_count: 1 - - section_id: 4 - heading_level: 2 - heading_text: ~ - start_line: 17 - end_line: 19 - parent_section_id: 0 - child_section_ids: [] - word_count: 7 - block_count: 1 - - section_id: 5 - heading_level: 2 - heading_text: ~ - start_line: 21 - end_line: 23 - parent_section_id: 0 - child_section_ids: [] - word_count: 9 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 5 - cognitive_complexity: 0.2 - halstead: - operators_distinct: 3 - operators_total: 19 - operands_distinct: 51 - operands_total: 53 - vocabulary: 54 - length: 72 - volume: 414.3519001557697 - difficulty: 1.558823529411765 - effort: 645.9014914192882 - embedded_volume: 0 - total_volume: 414.3519001557697 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 91.6875744680851 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0.1295744680851064 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.5677021276595744 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 0.8704255319148936 -review: - review_criticality_index: 1.6844680851063831 -artifacts: [] -prose: - language_detection: - dominant_language: ja - blocks: - - start_line: 1 - end_line: 1 - language: ja - - start_line: 3 - end_line: 3 - language: ja - - start_line: 5 - end_line: 5 - language: ja - - start_line: 7 - end_line: 7 - language: ja - - start_line: 9 - end_line: 9 - language: ja - - start_line: 11 - end_line: 11 - language: ja - - start_line: 13 - end_line: 13 - language: ja - - start_line: 15 - end_line: 15 - language: ja - - start_line: 17 - end_line: 17 - language: ja - - start_line: 19 - end_line: 19 - language: ja - - start_line: 21 - end_line: 21 - language: ja - - start_line: 23 - end_line: 23 - language: ja - english: ~ - japanese: - script_composition: - kanji_ratio: 0.366 - hiragana_ratio: 0.39 - katakana_ratio: 0.145 - latin_ratio: 0.089 - digit_ratio: 0.01 - script_entropy: 1.843 - visible_chars: 585 - readability: - tateishi_rs: 27.779 - jouyou_grade_mean: 3.692 - hyougai_ratio: 0.009 - lexical: - avg_sentence_chars: 32.105 - p90_sentence_chars: 61 - max_sentence_chars: 71 - comma_period_ratio: 1.769 - jukugo_density: 0.798 - sentence_count: 19 - char_count: 610 - wording: - politeness_dominant: keitai - keitai_count: 13 - jotai_count: 0 - honorific_count: 0 - keitai_jotai_mix_count: 0 - weak_phrase_count: 0 - redundant_expression_count: 0 - doubled_joshi_count: 14 - long_kanji_run_count: 0 - max_comma_violation_count: 0 - max_ten_violation_count: 1 - long_sentence_count: 0 - wording_quality_score: 0.83 - style_conformance: - violations: - - rule: rule-3-jouyou-only - severity: warn - count: 2 - - rule: rule-5-trailing-chouonpu - severity: warn - count: 3 - total_violations: 5 - violation_density_per_1000: 8.547 - short_doc_warning: false - meta: - short_doc_warning: false - words_counted: 610 - sentences_counted: 19 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@tight_list.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@tight_list.md.snap deleted file mode 100644 index 4de7e32b..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@tight_list.md.snap +++ /dev/null @@ -1,185 +0,0 @@ ---- -source: src/markdown/tests/mod.rs ---- -path: "" -loc: - dloc: 8 - ploc: 7 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 1 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.125 -size: - words: 9 - effective_content_units: 0.0375 - sections: 1 - headings: 1 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 8 - parent_section_id: ~ - child_section_ids: [] - word_count: 9 - block_count: 6 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 1 - cognitive_complexity: 2.76 - halstead: - operators_distinct: 3 - operators_total: 6 - operands_distinct: 11 - operands_total: 11 - vocabulary: 14 - length: 17 - volume: 64.72503367497927 - difficulty: 1.5 - effort: 97.08755051246891 - embedded_volume: 0 - total_volume: 64.72503367497927 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.01 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.7075 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: en - blocks: - - start_line: 1 - end_line: 1 - language: en - - start_line: 3 - end_line: 3 - language: en - - start_line: 4 - end_line: 4 - language: en - - start_line: 5 - end_line: 5 - language: en - - start_line: 6 - end_line: 6 - language: en - - start_line: 8 - end_line: 8 - language: en - english: - readability: - flesch_reading_ease: ~ - flesch_kincaid_grade: ~ - gunning_fog: ~ - smog: ~ - ari: ~ - coleman_liau: ~ - dale_chall_new: ~ - dale_chall_list: ngsl-1.2 - forcast: ~ - lix: ~ - rix: ~ - ensemble_grade_band: - - ~ - - ~ - lexical: - mattr_50: 1 - hapax_ratio: 1 - dis_ratio: 0 - lexical_density: 0.727 - avg_sentence_words: 1.833 - p90_sentence_words: 5 - max_sentence_words: 5 - stddev_sentence_words: 1.462 - avg_word_chars: 5 - p90_word_chars: 7 - sentence_count: 6 - words_total: 11 - wording: - passive_ratio: 0 - hedge_density: 0 - weasel_density: 0 - wordy_density: 0 - adverb_density: 0 - nominalization_density: 0 - expletive_count: 0 - lexical_illusions: 0 - cliche_density: 0 - nonword_count: 0 - long_sentence_count: 0 - wording_quality_score: 1 - inclusive_language: - flags: [] - inclusive_language_score: 1 - flag_count: 0 - short_doc_warning: true - japanese: ~ - meta: - short_doc_warning: true - words_counted: 11 - sentences_counted: 6 - blocks_stripped: [] diff --git a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@weak_phrase_ja.md.snap b/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@weak_phrase_ja.md.snap deleted file mode 100644 index 4535f7ff..00000000 --- a/crates/mehen-markdown/tests/snapshots/markdown__assert_fixture_snapshot@weak_phrase_ja.md.snap +++ /dev/null @@ -1,217 +0,0 @@ ---- -source: crates/mehen-markdown/tests/markdown.rs ---- -path: "" -loc: - dloc: 15 - ploc: 8 - cloc: 0 - tloc: 0 - mloc: 0 - bloc: 7 - aloc: 0 -loc_ratios: - artifact_line_ratio: 0 - code_line_ratio: 0 - table_line_ratio: 0 - math_line_ratio: 0 - blank_line_ratio: 0.4666666666666667 -size: - words: 13 - effective_content_units: 0.05416666666666667 - sections: 4 - headings: 4 -ecu_inputs: - table_cells: 0 - diagram_nodes: 0 - diagram_edges: 0 - math_tokens: 0 - raw_html_or_mdx_lines: 0 -sections: - - section_id: 0 - heading_level: 1 - heading_text: ~ - start_line: 1 - end_line: 15 - parent_section_id: ~ - child_section_ids: - - 1 - - 2 - - 3 - word_count: 4 - block_count: 1 - - section_id: 1 - heading_level: 2 - heading_text: ~ - start_line: 5 - end_line: 7 - parent_section_id: 0 - child_section_ids: [] - word_count: 3 - block_count: 1 - - section_id: 2 - heading_level: 2 - heading_text: ~ - start_line: 9 - end_line: 11 - parent_section_id: 0 - child_section_ids: [] - word_count: 3 - block_count: 1 - - section_id: 3 - heading_level: 2 - heading_text: ~ - start_line: 13 - end_line: 15 - parent_section_id: 0 - child_section_ids: [] - word_count: 3 - block_count: 1 -complexity: - reading_path_complexity: 1 - reading_path_complexity_raw: 3 - cognitive_complexity: 0.2 - halstead: - operators_distinct: 3 - operators_total: 14 - operands_distinct: 17 - operands_total: 17 - vocabulary: 20 - length: 31 - volume: 133.97977094150824 - difficulty: 1.5 - effort: 200.96965641226234 - embedded_volume: 0 - total_volume: 133.97977094150824 -links: - total: 0 - internal: 0 - relative: 0 - external: 0 - external_vendor: 0 - scholarly: 0 - issue_pr: 0 - absolute_same_repo: 0 - image: 0 - footnote: 0 - bare_url: 0 - broken: 0 - link_debt_score: 0 - information_scent_score: 0 - review_burden: 0 -visuals: - images: 0 - diagrams: 0 - diagram_nodes_total: 0 - diagram_edges_total: 0 - diagram_cycles_total: 0 - visual_scaffold_score: 0 - visual_net_effect: 0 -tables: - count: 0 - max_cells: 0 - table_burden_score: 0 - table_scaffold_score: 0 - hard_warnings: 0 -maintainability: - documentation_maintainability_index: 90.46 - section_balance_score: 0.85 - good_scaffold_score: 0 - artifact_debt_score: 0 -grounding: - repository_grounding_score: 0 - evidence_coverage_score: 0 -ai_era: - filler_lazy_structure_risk: 0.67 - labels: - - large-unanchored-prose - - low-artifact-density - - low-repository-grounding - - specificity-scarcity - top_contributors: - - - large-unanchored-prose - - 1 - - - low-artifact-density - - 1 - - - low-repository-grounding - - 1 -review: - review_criticality_index: 0 -artifacts: [] -prose: - language_detection: - dominant_language: ja - blocks: - - start_line: 1 - end_line: 1 - language: ja - - start_line: 3 - end_line: 3 - language: ja - - start_line: 5 - end_line: 5 - language: ja - - start_line: 7 - end_line: 7 - language: ja - - start_line: 9 - end_line: 9 - language: ja - - start_line: 11 - end_line: 11 - language: ja - - start_line: 13 - end_line: 13 - language: ja - - start_line: 15 - end_line: 15 - language: ja - english: ~ - japanese: - script_composition: - kanji_ratio: 0.288 - hiragana_ratio: 0.639 - katakana_ratio: 0.073 - latin_ratio: 0 - digit_ratio: 0 - script_entropy: 1.206 - visible_chars: 274 - readability: - tateishi_rs: ~ - jouyou_grade_mean: 3.152 - hyougai_ratio: 0 - lexical: - avg_sentence_chars: 19.786 - p90_sentence_chars: 36 - max_sentence_chars: 40 - comma_period_ratio: 0.3 - jukugo_density: 0.643 - sentence_count: 14 - char_count: 277 - wording: - politeness_dominant: keitai - keitai_count: 10 - jotai_count: 0 - honorific_count: 0 - keitai_jotai_mix_count: 0 - weak_phrase_count: 10 - redundant_expression_count: 5 - doubled_joshi_count: 9 - long_kanji_run_count: 0 - max_comma_violation_count: 0 - max_ten_violation_count: 0 - long_sentence_count: 0 - wording_quality_score: 0.611 - style_conformance: - violations: - - rule: rule-5-trailing-chouonpu - severity: warn - count: 1 - total_violations: 1 - violation_density_per_1000: 3.65 - short_doc_warning: true - meta: - short_doc_warning: true - words_counted: 277 - sentences_counted: 14 - blocks_stripped: [] diff --git a/crates/mehen-metrics/Cargo.toml b/crates/mehen-metrics/Cargo.toml deleted file mode 100644 index 523aa7d8..00000000 --- a/crates/mehen-metrics/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "mehen-metrics" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — shared metric contracts, formulas, and accumulators (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -serde = { workspace = true } -smol_str = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-metrics/src/abc.rs b/crates/mehen-metrics/src/abc.rs deleted file mode 100644 index 039d52cb..00000000 --- a/crates/mehen-metrics/src/abc.rs +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::Serialize; - -/// ABC metric accumulator. -/// -/// Mirrors the pre-1.0 `abc::Stats`. Per-space `assignments` / -/// `branches` / `conditions` are the running counts for the current -/// space. `*_sum` are the rolled-up totals across closed spaces -/// (snapshotted by `finalize_minmax`). Min/max bounds track per-space -/// values across the rolled-up tree. Averages divide by `space_count`. -/// `magnitude` follows Fitzpatrick (1997): sqrt(A² + B² + C²) over the -/// rolled-up sums. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct AbcStats { - pub assignments: u32, - pub branches: u32, - pub conditions: u32, - pub assignments_sum: u32, - pub branches_sum: u32, - pub conditions_sum: u32, - pub assignments_min: u32, - pub assignments_max: u32, - pub branches_min: u32, - pub branches_max: u32, - pub conditions_min: u32, - pub conditions_max: u32, - pub space_count: u32, - pub minmax_seen: bool, -} - -impl AbcStats { - pub fn record_assignment(&mut self) { - self.assignments = self.assignments.saturating_add(1); - } - - pub fn record_branch(&mut self) { - self.branches = self.branches.saturating_add(1); - } - - pub fn record_condition(&mut self) { - self.conditions = self.conditions.saturating_add(1); - } - - /// Snapshot the per-space `assignments` / `branches` / `conditions` - /// into `*_sum`, `*_min`, `*_max` and bump `space_count`. Mirrors - /// the pre-1.0 `compute_minmax`. - pub fn finalize_minmax(&mut self) { - self.assignments_sum = self.assignments_sum.saturating_add(self.assignments); - self.branches_sum = self.branches_sum.saturating_add(self.branches); - self.conditions_sum = self.conditions_sum.saturating_add(self.conditions); - self.space_count = self.space_count.saturating_add(1); - if self.minmax_seen { - self.assignments_min = self.assignments_min.min(self.assignments); - self.branches_min = self.branches_min.min(self.branches); - self.conditions_min = self.conditions_min.min(self.conditions); - } else { - self.assignments_min = self.assignments; - self.branches_min = self.branches; - self.conditions_min = self.conditions; - self.minmax_seen = true; - } - self.assignments_max = self.assignments_max.max(self.assignments); - self.branches_max = self.branches_max.max(self.branches); - self.conditions_max = self.conditions_max.max(self.conditions); - } - - pub fn merge(&mut self, other: &AbcStats) { - self.assignments_sum = self.assignments_sum.saturating_add(other.assignments_sum); - self.branches_sum = self.branches_sum.saturating_add(other.branches_sum); - self.conditions_sum = self.conditions_sum.saturating_add(other.conditions_sum); - self.space_count = self.space_count.saturating_add(other.space_count); - if !other.minmax_seen { - return; - } - if self.minmax_seen { - self.assignments_min = self.assignments_min.min(other.assignments_min); - self.branches_min = self.branches_min.min(other.branches_min); - self.conditions_min = self.conditions_min.min(other.conditions_min); - } else { - self.assignments_min = other.assignments_min; - self.branches_min = other.branches_min; - self.conditions_min = other.conditions_min; - self.minmax_seen = true; - } - self.assignments_max = self.assignments_max.max(other.assignments_max); - self.branches_max = self.branches_max.max(other.branches_max); - self.conditions_max = self.conditions_max.max(other.conditions_max); - } - - /// Magnitude over the rolled-up sums: `sqrt(A² + B² + C²)`. - pub fn magnitude(&self) -> f64 { - let a = f64::from(self.assignments_sum); - let b = f64::from(self.branches_sum); - let c = f64::from(self.conditions_sum); - (a.mul_add(a, b.mul_add(b, c * c))).sqrt() - } - - pub fn assignments_average(&self) -> f64 { - average(self.assignments_sum, self.space_count) - } - pub fn branches_average(&self) -> f64 { - average(self.branches_sum, self.space_count) - } - pub fn conditions_average(&self) -> f64 { - average(self.conditions_sum, self.space_count) - } -} - -fn average(numerator: u32, denominator: u32) -> f64 { - if denominator == 0 { - 0.0 - } else { - f64::from(numerator) / f64::from(denominator) - } -} diff --git a/crates/mehen-metrics/src/cognitive.rs b/crates/mehen-metrics/src/cognitive.rs deleted file mode 100644 index 2dc2831f..00000000 --- a/crates/mehen-metrics/src/cognitive.rs +++ /dev/null @@ -1,190 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::Serialize; - -/// Cognitive complexity accumulator. -/// -/// Mirrors the pre-1.0 `cognitive::Stats`. Per-space `structural` is -/// the running cognitive count; `cognitive_sum` is the rolled-up total -/// across closed spaces; `min`/`max` are per-space bounds. Averages -/// divide by the function count (NOM total). The accumulator also -/// carries the `nesting` counter (used by `increase_nesting`) and the -/// `BoolSequence` state machine that collapses same-operator boolean -/// runs per Sonar's whitepaper. -/// -/// `cognitive` is exposed as a field for backwards compatibility with -/// existing callers; it mirrors `structural` (the running per-space -/// count). -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct CognitiveStats { - pub cognitive: u32, - pub structural: u32, - pub nesting: u32, - pub min: u32, - pub max: u32, - pub cognitive_sum: u32, - pub cognitive_average: f64, - pub boolean_seq: BoolSequence, - pub minmax_seen: bool, -} - -/// Same-operator sequence collapser per Sonar's whitepaper. Each -/// observed boolean operator is compared against the last; same kind -/// adds nothing, different kind (or first occurrence) adds +1. Reset -/// at statement boundaries (assignment, pipeline, control-flow -/// clause). -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct BoolSequence { - /// Stable string identifier for the most recent boolean operator. - /// `None` when the sequence has been reset or not yet started. - pub last_op: Option, -} - -impl BoolSequence { - pub fn reset(&mut self) { - self.last_op = None; - } - - pub fn not_operator(&mut self, not_id: &str) { - self.last_op = Some(smol_str::SmolStr::new(not_id)); - } - - /// Update `structural` and the recorded last-op based on the new - /// boolean operator. Returns the new structural value. - pub fn eval_based_on_prev(&mut self, op_id: &str, structural: u32) -> u32 { - let new_value = if let Some(prev) = &self.last_op { - if prev.as_str() != op_id { - structural.saturating_add(1) - } else { - structural - } - } else { - structural.saturating_add(1) - }; - self.last_op = Some(smol_str::SmolStr::new(op_id)); - new_value - } -} - -impl CognitiveStats { - /// Record `amount` cognitive complexity points for the current - /// space. Adds to `structural` (and the legacy `cognitive` mirror). - pub fn record_increment(&mut self, amount: u32) { - self.structural = self.structural.saturating_add(amount); - self.cognitive = self.structural; - } - - /// Add `nesting + 1` to the structural count. Mirrors the pre-1.0 - /// `increment(stats)` (which used `stats.structural += stats.nesting + 1`). - pub fn increase_nesting(&mut self, nesting: u32) { - self.nesting = nesting; - let bump = nesting.saturating_add(1); - self.structural = self.structural.saturating_add(bump); - self.cognitive = self.structural; - } - - /// Add 1 to the structural count without touching nesting. Used for - /// `elseif`, `else`, `finally`, `trap` clauses. - pub fn increment_by_one(&mut self) { - self.structural = self.structural.saturating_add(1); - self.cognitive = self.structural; - } - - /// Feed one boolean operator through the BoolSequence collapser. - /// Updates `structural` according to the same-op vs. transition - /// rule, mirroring the pre-1.0 - /// `stats.structural = boolean_seq.eval_based_on_prev(...)`. - pub fn observe_boolean(&mut self, op_id: &str) { - self.structural = self.boolean_seq.eval_based_on_prev(op_id, self.structural); - self.cognitive = self.structural; - } - - /// Combine another space's stats into this one. - pub fn merge(&mut self, other: &CognitiveStats) { - self.cognitive_sum = self.cognitive_sum.saturating_add(other.cognitive_sum); - if !other.minmax_seen { - return; - } - if self.minmax_seen { - self.min = self.min.min(other.min); - } else { - self.min = other.min; - self.minmax_seen = true; - } - self.max = self.max.max(other.max); - } - - /// Fold the current per-space `structural` into `cognitive_sum` / - /// min / max. Should be called once per space before merging into - /// the parent. - pub fn finalize_minmax(&mut self) { - let value = self.structural; - self.cognitive_sum = self.cognitive_sum.saturating_add(value); - if self.minmax_seen { - self.min = self.min.min(value); - } else { - self.min = value; - self.minmax_seen = true; - } - self.max = self.max.max(value); - } - - /// Compute `cognitive_average = cognitive_sum / function_count`. - pub fn finalize(&mut self, function_count: u32) { - if function_count == 0 { - self.cognitive_average = 0.0; - } else { - self.cognitive_average = f64::from(self.cognitive_sum) / f64::from(function_count); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn record_increment_only_bumps_per_space_count() { - let mut s = CognitiveStats::default(); - s.record_increment(2); - s.record_increment(3); - assert_eq!(s.structural, 5); - assert_eq!(s.cognitive, 5); - // sum stays 0 until finalize_minmax snapshots a closed space. - assert_eq!(s.cognitive_sum, 0); - } - - #[test] - fn finalize_minmax_snapshots_per_space_value() { - let mut s = CognitiveStats::default(); - s.record_increment(5); - s.finalize_minmax(); - assert_eq!(s.cognitive_sum, 5); - assert_eq!(s.min, 5); - assert_eq!(s.max, 5); - } - - #[test] - fn merge_preserves_min_max() { - let mut a = CognitiveStats::default(); - a.record_increment(4); - a.finalize_minmax(); - let mut b = CognitiveStats::default(); - b.record_increment(9); - b.finalize_minmax(); - a.merge(&b); - assert_eq!(a.min, 4); - assert_eq!(a.max, 9); - assert_eq!(a.cognitive_sum, 13); - } - - #[test] - fn boolean_sequence_collapses_same_operator() { - let mut s = CognitiveStats::default(); - s.observe_boolean("-and"); // first → +1 - s.observe_boolean("-and"); // same → no bump - s.observe_boolean("-or"); // transition → +1 - assert_eq!(s.structural, 2); - } -} diff --git a/crates/mehen-metrics/src/counters.rs b/crates/mehen-metrics/src/counters.rs deleted file mode 100644 index 80f9faea..00000000 --- a/crates/mehen-metrics/src/counters.rs +++ /dev/null @@ -1,661 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::Serialize; - -/// Number of arguments accumulator (NArgs). -/// -/// Mirrors the pre-1.0 `nargs::Stats`. Per-space, `fn_nargs` / -/// `closure_nargs` hold the arg count of that function or closure -/// space (set once when the space opens); `*_sum` are the rolled-up -/// totals across closed spaces; `*_min` / `*_max` are bounds. Averages -/// divide by the function / closure counts (NOM totals), set via -/// `finalize_average`. -/// -/// `is_function` / `is_closure` mark whether this space *is itself* a -/// function or closure. Only such spaces fold their own per-space -/// `fn_nargs` / `closure_nargs` into the rolled-up min/max during -/// `finalize_minmax`. Without this discriminator, the unit space's -/// always-zero `fn_nargs` would dilute any merged child's `_min` to -/// 0 — see `closures_min` in the legacy `python_single_lambda` test. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct NargsStats { - pub fn_nargs: u32, - pub closure_nargs: u32, - pub fn_nargs_sum: u32, - pub closure_nargs_sum: u32, - pub fn_nargs_min: u32, - pub fn_nargs_max: u32, - pub closure_nargs_min: u32, - pub closure_nargs_max: u32, - pub fn_nargs_average: f64, - pub closure_nargs_average: f64, - pub minmax_seen: bool, - /// `true` when this space *is* a function (its own - /// `fn_nargs` should fold into the rolled-up min/max). - pub is_function: bool, - /// `true` when this space *is* a closure (its own - /// `closure_nargs` should fold into the rolled-up min/max). - pub is_closure: bool, - /// `true` when any descendant has contributed function nargs to - /// this space's rolled-up sum/min/max. Used by `merge` to decide - /// whether to seed parent's fn_min from a fresh child or fold it - /// into existing parent state. - pub merged_function: bool, - /// As `merged_function`, for closure nargs. - pub merged_closure: bool, -} - -impl NargsStats { - /// Set the function arg count for this space. Called once when a - /// `Function` space opens. - pub fn record_function_args(&mut self, count: u32) { - self.fn_nargs = count; - self.is_function = true; - } - - /// Set the closure arg count for this space. Called once when a - /// `Closure` space opens. - pub fn record_closure_args(&mut self, count: u32) { - self.closure_nargs = count; - self.is_closure = true; - } - - /// Snapshot the per-space `fn_nargs` / `closure_nargs` into `*_sum`, - /// `*_min`, `*_max`. Mirrors the pre-1.0 `compute_minmax` but folds - /// only into the dimension matching this space's kind: functions - /// fold into `fn_nargs_*`, closures fold into `closure_nargs_*`, - /// and the unit / class / enclosing scopes fold into neither - /// (their per-space counters are always zero and would only dilute - /// merged child bounds). - pub fn finalize_minmax(&mut self) { - self.fn_nargs_sum = self.fn_nargs_sum.saturating_add(self.fn_nargs); - self.closure_nargs_sum = self.closure_nargs_sum.saturating_add(self.closure_nargs); - if self.is_function { - if self.merged_function { - self.fn_nargs_min = self.fn_nargs_min.min(self.fn_nargs); - } else { - self.fn_nargs_min = self.fn_nargs; - self.merged_function = true; - } - self.fn_nargs_max = self.fn_nargs_max.max(self.fn_nargs); - self.minmax_seen = true; - } - if self.is_closure { - if self.merged_closure { - self.closure_nargs_min = self.closure_nargs_min.min(self.closure_nargs); - } else { - self.closure_nargs_min = self.closure_nargs; - self.merged_closure = true; - } - self.closure_nargs_max = self.closure_nargs_max.max(self.closure_nargs); - self.minmax_seen = true; - } - } - - /// Compute averages once `*_sum` has been merged across all spaces. - /// Divides by the NOM `functions_sum` and `closures_sum` - /// respectively; both fall back to `1` when the count is zero - /// (matching the pre-1.0 `total_functions.max(1)` guard). - pub fn finalize_average(&mut self, function_count: u32, closure_count: u32) { - let fn_denom = function_count.max(1); - let cl_denom = closure_count.max(1); - self.fn_nargs_average = f64::from(self.fn_nargs_sum) / f64::from(fn_denom); - self.closure_nargs_average = f64::from(self.closure_nargs_sum) / f64::from(cl_denom); - } - - pub fn merge(&mut self, other: &NargsStats) { - self.fn_nargs_sum = self.fn_nargs_sum.saturating_add(other.fn_nargs_sum); - self.closure_nargs_sum = self - .closure_nargs_sum - .saturating_add(other.closure_nargs_sum); - // Each dimension is only folded when the other side actually - // contributed to it. `merged_function` / `merged_closure` - // track whether the parent has already absorbed a value in - // that dimension — if so, we fold; otherwise we seed with the - // child's value. `is_function` / `is_closure` alone aren't - // enough as a gate here: the parent's own per-space - // `fn_nargs` / `closure_nargs` is folded later in - // `finalize_minmax`, not during merge. - let other_has_fn = other.is_function || other.merged_function; - let other_has_closure = other.is_closure || other.merged_closure; - if other_has_fn { - if self.merged_function { - self.fn_nargs_min = self.fn_nargs_min.min(other.fn_nargs_min); - } else { - self.fn_nargs_min = other.fn_nargs_min; - } - self.fn_nargs_max = self.fn_nargs_max.max(other.fn_nargs_max); - self.merged_function = true; - self.minmax_seen = true; - } - if other_has_closure { - if self.merged_closure { - self.closure_nargs_min = self.closure_nargs_min.min(other.closure_nargs_min); - } else { - self.closure_nargs_min = other.closure_nargs_min; - } - self.closure_nargs_max = self.closure_nargs_max.max(other.closure_nargs_max); - self.merged_closure = true; - self.minmax_seen = true; - } - } - - pub fn total(&self) -> u32 { - self.fn_nargs_sum.saturating_add(self.closure_nargs_sum) - } - - pub fn nargs_average(&self, function_count: u32, closure_count: u32) -> f64 { - let denom = function_count.saturating_add(closure_count).max(1); - f64::from(self.total()) / f64::from(denom) - } -} - -/// Number of methods/functions (NOM) accumulator. -/// -/// `functions`/`closures` track the per-space count (number of nested -/// function/closure spaces directly opened from this one). `*_sum` are -/// the running totals across closed spaces; `finalize_minmax` snapshots -/// the per-space values into the bounds and adds them into `*_sum`. -/// `space_count` is bumped at the same time so averages divide by the -/// total number of spaces folded in. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct NomStats { - pub functions: u32, - pub closures: u32, - pub functions_sum: u32, - pub closures_sum: u32, - pub functions_min: u32, - pub functions_max: u32, - pub closures_min: u32, - pub closures_max: u32, - pub space_count: u32, - /// Sentinel — set on first finalize so 0-valued bounds don't get - /// overwritten on subsequent finalizes. - pub minmax_seen: bool, -} - -impl NomStats { - pub fn record_function(&mut self) { - self.functions = self.functions.saturating_add(1); - } - - pub fn record_closure(&mut self) { - self.closures = self.closures.saturating_add(1); - } - - /// Fold the current per-space `functions`/`closures` values into - /// `*_sum`, `*_min`, `*_max` and bump `space_count`. Called once - /// per space before merging into the parent. - pub fn finalize_minmax(&mut self) { - self.functions_sum = self.functions_sum.saturating_add(self.functions); - self.closures_sum = self.closures_sum.saturating_add(self.closures); - self.space_count = self.space_count.saturating_add(1); - if self.minmax_seen { - self.functions_min = self.functions_min.min(self.functions); - self.closures_min = self.closures_min.min(self.closures); - } else { - self.functions_min = self.functions; - self.closures_min = self.closures; - self.minmax_seen = true; - } - self.functions_max = self.functions_max.max(self.functions); - self.closures_max = self.closures_max.max(self.closures); - } - - pub fn merge(&mut self, other: &NomStats) { - self.functions_sum = self.functions_sum.saturating_add(other.functions_sum); - self.closures_sum = self.closures_sum.saturating_add(other.closures_sum); - self.space_count = self.space_count.saturating_add(other.space_count); - if !other.minmax_seen { - return; - } - if self.minmax_seen { - self.functions_min = self.functions_min.min(other.functions_min); - self.closures_min = self.closures_min.min(other.closures_min); - } else { - self.functions_min = other.functions_min; - self.closures_min = other.closures_min; - self.minmax_seen = true; - } - self.functions_max = self.functions_max.max(other.functions_max); - self.closures_max = self.closures_max.max(other.closures_max); - } - - /// `functions_sum + closures_sum` — the rolled-up total across all - /// folded spaces. Used as the average denominator for cognitive, - /// nexit, and nargs (per `mehen-engine::legacy::spaces::compute_averages`). - pub fn total(&self) -> u32 { - self.functions_sum.saturating_add(self.closures_sum) - } - - pub fn functions_average(&self) -> f64 { - average(self.functions_sum, self.space_count) - } - pub fn closures_average(&self) -> f64 { - average(self.closures_sum, self.space_count) - } - pub fn average(&self) -> f64 { - average(self.total(), self.space_count) - } -} - -fn average(numerator: u32, denominator: u32) -> f64 { - if denominator == 0 { - 0.0 - } else { - f64::from(numerator) / f64::from(denominator) - } -} - -/// Number of exits (return/throw/raise/exit) accumulator. -/// -/// Per the pre-1.0 `src/metrics/exit.rs` and the rewrite plan §5.2: -/// language crates decide which constructs are exits. The accumulator -/// keeps the per-space `exits` count (raw, not McCabe-style); on space -/// close `finalize_minmax` snapshots that into `sum`/`min`/`max`. The -/// `average` denominator is the function count (NOM total), not the -/// space count — set externally via `finalize_average(function_count)`. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct NexitStats { - pub exits: u32, - pub min: u32, - pub max: u32, - pub average: f64, - pub sum: u32, - /// `true` once `finalize_minmax` has snapshotted at least one space - /// — used as the "min initialized" sentinel so the first close sets - /// `min`, even when its value is 0. - pub minmax_seen: bool, -} - -impl NexitStats { - /// Record one exit point. The `+0` constant for sum aggregation is - /// added at finalize time; `sum` stays 0 until `finalize_minmax` - /// snapshots a closed space. - pub fn record_exit(&mut self) { - self.exits = self.exits.saturating_add(1); - } - - /// Fold the current per-space `exits` value into `sum`, `min`, - /// `max`. Should be called once per space before merging into the - /// parent. - pub fn finalize_minmax(&mut self) { - let value = self.exits; - self.sum = self.sum.saturating_add(value); - if self.minmax_seen { - self.min = self.min.min(value); - } else { - self.min = value; - self.minmax_seen = true; - } - self.max = self.max.max(value); - } - - /// Compute the average exits per function once `sum` has been - /// merged across all spaces. The denominator is the **NOM total** - /// (functions + closures), not the space count. - pub fn finalize_average(&mut self, function_count: u32) { - self.average = if function_count == 0 { - 0.0 - } else { - f64::from(self.sum) / f64::from(function_count) - }; - } - - pub fn merge(&mut self, other: &NexitStats) { - self.sum = self.sum.saturating_add(other.sum); - if !other.minmax_seen { - return; - } - if self.minmax_seen { - self.min = self.min.min(other.min); - } else { - self.min = other.min; - self.minmax_seen = true; - } - self.max = self.max.max(other.max); - } -} - -/// Number of public attributes accumulator (NPA). -/// -/// Mirrors the pre-1.0 `npa::Stats`. Tracks per-class and per-interface -/// public-attribute counts plus the totals; the rolled-up CDA (Class -/// Data Accessibility) is `class_npa_sum / class_na_sum` and similarly -/// for interfaces. `class_*` increment when the enclosing space is -/// `Class` / `Impl`; `interface_*` increment when the enclosing space -/// is `Interface` / `Trait`. Languages without class-like constructs -/// flip `not_applicable` so the metric is omitted from output. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct NpaStats { - pub class_npa: u32, - pub interface_npa: u32, - pub class_na: u32, - pub interface_na: u32, - pub class_npa_sum: u32, - pub interface_npa_sum: u32, - pub class_na_sum: u32, - pub interface_na_sum: u32, - pub not_applicable: bool, - pub has_class_like: bool, -} - -impl NpaStats { - /// Record one attribute observation. `container` is the kind of - /// the enclosing class-like or interface-like space; pass other - /// kinds to skip recording. - pub fn record_attribute(&mut self, container: ContainerKind, is_public: bool) { - match container { - ContainerKind::Class => { - self.class_na = self.class_na.saturating_add(1); - if is_public { - self.class_npa = self.class_npa.saturating_add(1); - } - } - ContainerKind::Interface => { - self.interface_na = self.interface_na.saturating_add(1); - if is_public { - self.interface_npa = self.interface_npa.saturating_add(1); - } - } - ContainerKind::Other => {} - } - } - - pub fn record_class_like(&mut self) { - self.has_class_like = true; - } - - pub fn finalize_minmax(&mut self) { - self.class_npa_sum = self.class_npa_sum.saturating_add(self.class_npa); - self.interface_npa_sum = self.interface_npa_sum.saturating_add(self.interface_npa); - self.class_na_sum = self.class_na_sum.saturating_add(self.class_na); - self.interface_na_sum = self.interface_na_sum.saturating_add(self.interface_na); - } - - pub fn merge(&mut self, other: &NpaStats) { - self.class_npa_sum = self.class_npa_sum.saturating_add(other.class_npa_sum); - self.interface_npa_sum = self - .interface_npa_sum - .saturating_add(other.interface_npa_sum); - self.class_na_sum = self.class_na_sum.saturating_add(other.class_na_sum); - self.interface_na_sum = self.interface_na_sum.saturating_add(other.interface_na_sum); - self.not_applicable |= other.not_applicable; - self.has_class_like |= other.has_class_like; - } - - pub fn class_cda(&self) -> f64 { - if self.class_na_sum == 0 { - f64::NAN - } else { - f64::from(self.class_npa_sum) / f64::from(self.class_na_sum) - } - } - - pub fn interface_cda(&self) -> f64 { - if self.interface_npa_sum == self.interface_na_sum && self.interface_npa_sum != 0 { - 1.0 - } else if self.interface_na_sum == 0 { - f64::NAN - } else { - f64::from(self.interface_npa_sum) / f64::from(self.interface_na_sum) - } - } - - pub fn total_npa(&self) -> u32 { - self.class_npa_sum.saturating_add(self.interface_npa_sum) - } - - pub fn total_na(&self) -> u32 { - self.class_na_sum.saturating_add(self.interface_na_sum) - } - - pub fn total_cda(&self) -> f64 { - let na = self.total_na(); - if na == 0 { - f64::NAN - } else { - f64::from(self.total_npa()) / f64::from(na) - } - } - - pub fn is_disabled(&self) -> bool { - self.not_applicable || !self.has_class_like - } -} - -/// Number of public methods accumulator (NPM). -/// -/// Same shape as [`NpaStats`] but counts methods rather than -/// attributes. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct NpmStats { - pub class_npm: u32, - pub interface_npm: u32, - pub class_nm: u32, - pub interface_nm: u32, - pub class_npm_sum: u32, - pub interface_npm_sum: u32, - pub class_nm_sum: u32, - pub interface_nm_sum: u32, - pub not_applicable: bool, - pub has_class_like: bool, -} - -impl NpmStats { - pub fn record_method(&mut self, container: ContainerKind, is_public: bool) { - match container { - ContainerKind::Class => { - self.class_nm = self.class_nm.saturating_add(1); - if is_public { - self.class_npm = self.class_npm.saturating_add(1); - } - } - ContainerKind::Interface => { - self.interface_nm = self.interface_nm.saturating_add(1); - if is_public { - self.interface_npm = self.interface_npm.saturating_add(1); - } - } - ContainerKind::Other => {} - } - } - - pub fn record_class_like(&mut self) { - self.has_class_like = true; - } - - pub fn finalize_minmax(&mut self) { - self.class_npm_sum = self.class_npm_sum.saturating_add(self.class_npm); - self.interface_npm_sum = self.interface_npm_sum.saturating_add(self.interface_npm); - self.class_nm_sum = self.class_nm_sum.saturating_add(self.class_nm); - self.interface_nm_sum = self.interface_nm_sum.saturating_add(self.interface_nm); - } - - pub fn merge(&mut self, other: &NpmStats) { - self.class_npm_sum = self.class_npm_sum.saturating_add(other.class_npm_sum); - self.interface_npm_sum = self - .interface_npm_sum - .saturating_add(other.interface_npm_sum); - self.class_nm_sum = self.class_nm_sum.saturating_add(other.class_nm_sum); - self.interface_nm_sum = self.interface_nm_sum.saturating_add(other.interface_nm_sum); - self.not_applicable |= other.not_applicable; - self.has_class_like |= other.has_class_like; - } - - pub fn class_avg(&self) -> f64 { - if self.class_nm_sum == 0 { - f64::NAN - } else { - f64::from(self.class_npm_sum) / f64::from(self.class_nm_sum) - } - } - - pub fn interface_avg(&self) -> f64 { - if self.interface_npm_sum == self.interface_nm_sum && self.interface_npm_sum != 0 { - 1.0 - } else if self.interface_nm_sum == 0 { - f64::NAN - } else { - f64::from(self.interface_npm_sum) / f64::from(self.interface_nm_sum) - } - } - - pub fn total_npm(&self) -> u32 { - self.class_npm_sum.saturating_add(self.interface_npm_sum) - } - - pub fn total_nm(&self) -> u32 { - self.class_nm_sum.saturating_add(self.interface_nm_sum) - } - - pub fn total_avg(&self) -> f64 { - let nm = self.total_nm(); - if nm == 0 { - f64::NAN - } else { - f64::from(self.total_npm()) / f64::from(nm) - } - } - - pub fn is_disabled(&self) -> bool { - self.not_applicable || !self.has_class_like - } -} - -/// Container kind for NPA / NPM accounting. Class-like (`Class` / -/// `Impl`) and interface-like (`Interface` / `Trait`) are tracked in -/// separate buckets per the pre-1.0 distinction; everything else is -/// ignored. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum ContainerKind { - Class, - Interface, - Other, -} - -/// Weighted methods per class accumulator (WMC). -/// -/// WMC sums the cyclomatic complexity of every method on a class. -/// Per-space `*_sum` are the rolled-up totals; the unit publishes the -/// total. `not_applicable` lets languages without class-like constructs -/// (Go, C, Markdown) opt out so the metric is omitted from output. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct WmcStats { - /// Per-space cyclomatic value (snapshotted from the function/method - /// space's cyclomatic at finalize time). - pub wmc: u32, - pub class_wmc_sum: u32, - pub interface_wmc_sum: u32, - pub not_applicable: bool, - pub has_class_like: bool, -} - -impl WmcStats { - /// Set the per-space cyclomatic value. Called by the walker at - /// space close on function/method spaces — pass the finalized - /// `cyclomatic` count for that space. - pub fn set_cyclomatic(&mut self, cyclomatic: u32) { - self.wmc = cyclomatic; - } - - pub fn record_class_like(&mut self) { - self.has_class_like = true; - } - - /// Snapshot this method-space's cyclomatic into the parent's - /// `class_wmc_sum` / `interface_wmc_sum`. The walker calls this - /// when merging a function/method space into its enclosing class - /// or interface. - pub fn finalize_method_into(&self, container: ContainerKind, parent: &mut WmcStats) { - match container { - ContainerKind::Class => { - parent.class_wmc_sum = parent.class_wmc_sum.saturating_add(self.wmc); - } - ContainerKind::Interface => { - parent.interface_wmc_sum = parent.interface_wmc_sum.saturating_add(self.wmc); - } - ContainerKind::Other => {} - } - } - - pub fn merge(&mut self, other: &WmcStats) { - self.class_wmc_sum = self.class_wmc_sum.saturating_add(other.class_wmc_sum); - self.interface_wmc_sum = self - .interface_wmc_sum - .saturating_add(other.interface_wmc_sum); - self.not_applicable |= other.not_applicable; - self.has_class_like |= other.has_class_like; - } - - pub fn total(&self) -> u32 { - self.class_wmc_sum.saturating_add(self.interface_wmc_sum) - } - - pub fn is_disabled(&self) -> bool { - self.not_applicable || !self.has_class_like - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn nargs_record_then_finalize_snapshots_per_space_value() { - let mut s = NargsStats::default(); - s.record_function_args(3); - s.finalize_minmax(); - assert_eq!(s.fn_nargs_sum, 3); - assert_eq!(s.fn_nargs_min, 3); - assert_eq!(s.fn_nargs_max, 3); - } - - #[test] - fn nargs_merge_combines_bounds() { - let mut a = NargsStats::default(); - a.record_function_args(3); - a.finalize_minmax(); - let mut b = NargsStats::default(); - b.record_function_args(5); - b.finalize_minmax(); - a.merge(&b); - assert_eq!(a.fn_nargs_sum, 8); - assert_eq!(a.fn_nargs_min, 3); - assert_eq!(a.fn_nargs_max, 5); - } - - #[test] - fn nexit_record_exit_only_bumps_per_space_count() { - let mut s = NexitStats::default(); - s.record_exit(); - s.record_exit(); - assert_eq!(s.exits, 2); - // sum stays 0 until finalize_minmax snapshots a closed space. - assert_eq!(s.sum, 0); - } - - #[test] - fn nexit_finalize_minmax_snapshots_per_space_count_into_sum() { - let mut s = NexitStats::default(); - s.record_exit(); - s.record_exit(); - s.finalize_minmax(); - assert_eq!(s.sum, 2); - assert_eq!(s.min, 2); - assert_eq!(s.max, 2); - } - - #[test] - fn nexit_finalize_average_handles_zero() { - let mut s = NexitStats { - sum: 6, - ..Default::default() - }; - s.finalize_average(0); - assert_eq!(s.average, 0.0); - s.finalize_average(3); - assert_eq!(s.average, 2.0); - } -} diff --git a/crates/mehen-metrics/src/cyclomatic.rs b/crates/mehen-metrics/src/cyclomatic.rs deleted file mode 100644 index 1ed66f6b..00000000 --- a/crates/mehen-metrics/src/cyclomatic.rs +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::Serialize; - -/// Cyclomatic complexity accumulator. -/// -/// Per the rewrite plan §5.2, the language crate decides which syntax -/// constructs are decisions (`if`, `while`, `for`, `case`, `&&`, `||`, -/// `?`, …) and emits an increment via `record_decision`. Min/max/sum/avg -/// across nested spaces are computed in `mehen-metrics`. -/// -/// The pre-1.0 implementation lives at `src/metrics/cyclomatic.rs`; the -/// field set here matches it so parity snapshots compare directly. -/// -/// `cyclomatic` stores the raw *decision* count for the current space. -/// The published McCabe value is `cyclomatic + 1`. `cyclomatic_sum` is -/// the running total of *McCabe* values across closed spaces; it stays -/// 0 until `finalize_minmax` snapshots the current space. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct CyclomaticStats { - pub cyclomatic: u32, - pub min: u32, - pub max: u32, - pub cyclomatic_sum: u32, - pub cyclomatic_average: f64, - /// Number of spaces folded into `cyclomatic_sum` — used by - /// `finalize_average` so callers don't have to track nspace - /// separately. - pub n: u32, -} - -impl CyclomaticStats { - /// Record one decision point. The `+1` McCabe constant is added at - /// finalize time; `cyclomatic_sum` aggregates closed-space values. - pub fn record_decision(&mut self) { - self.cyclomatic = self.cyclomatic.saturating_add(1); - } - - /// Combine another space's already-finalized stats into this one. - pub fn merge(&mut self, other: &CyclomaticStats) { - self.cyclomatic_sum = self.cyclomatic_sum.saturating_add(other.cyclomatic_sum); - self.n = self.n.saturating_add(other.n); - self.min = match (self.min, other.min) { - (0, b) => b, - (a, 0) => a, - (a, b) => a.min(b), - }; - self.max = self.max.max(other.max); - } - - /// Compute the average cyclomatic-per-space once `cyclomatic_sum` - /// has been merged across all spaces. - pub fn finalize_average(&mut self) { - self.cyclomatic_average = if self.n == 0 { - 0.0 - } else { - f64::from(self.cyclomatic_sum) / f64::from(self.n) - }; - } - - /// Fold the current per-space McCabe value (`decisions + 1`) into - /// `cyclomatic_sum`, `min`, `max`, and bump `n`. Should be called - /// once per space before merging into the parent. - pub fn finalize_minmax(&mut self) { - let value = self.cyclomatic.saturating_add(1); - self.cyclomatic_sum = self.cyclomatic_sum.saturating_add(value); - self.n = self.n.saturating_add(1); - self.min = if self.min == 0 { - value - } else { - self.min.min(value) - }; - self.max = self.max.max(value); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn record_decision_only_bumps_per_space_count() { - let mut s = CyclomaticStats::default(); - s.record_decision(); - s.record_decision(); - assert_eq!(s.cyclomatic, 2); - // sum stays 0 until finalize_minmax snapshots a closed space. - assert_eq!(s.cyclomatic_sum, 0); - } - - #[test] - fn finalize_minmax_publishes_mccabe_value() { - let mut s = CyclomaticStats::default(); - s.record_decision(); - s.record_decision(); - s.finalize_minmax(); - // 2 decisions + 1 = 3 (McCabe). - assert_eq!(s.cyclomatic_sum, 3); - assert_eq!(s.min, 3); - assert_eq!(s.max, 3); - assert_eq!(s.n, 1); - } - - #[test] - fn merge_preserves_min_max() { - let mut a = CyclomaticStats { - cyclomatic_sum: 3, - min: 3, - max: 3, - n: 1, - ..Default::default() - }; - let b = CyclomaticStats { - cyclomatic_sum: 7, - min: 7, - max: 7, - n: 1, - ..Default::default() - }; - a.merge(&b); - assert_eq!(a.cyclomatic_sum, 10); - assert_eq!(a.min, 3); - assert_eq!(a.max, 7); - assert_eq!(a.n, 2); - } - - #[test] - fn finalize_average_handles_zero_n() { - let mut s = CyclomaticStats::default(); - s.finalize_average(); - assert_eq!(s.cyclomatic_average, 0.0); - s.cyclomatic_sum = 5; - s.n = 2; - s.finalize_average(); - assert_eq!(s.cyclomatic_average, 2.5); - } -} diff --git a/crates/mehen-metrics/src/evidence.rs b/crates/mehen-metrics/src/evidence.rs deleted file mode 100644 index f9dfc4ac..00000000 --- a/crates/mehen-metrics/src/evidence.rs +++ /dev/null @@ -1,345 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Shared contribution-evidence sink for language walkers. -//! -//! Per the rewrite plan §5.4, every metric movement should be able to -//! answer "why did this metric move here" with a source span and a -//! namespaced reason code. Language walkers already own the call sites -//! where each increment happens (a decision node, an exit statement, a -//! public member declaration, …) — this type gives those call sites a -//! uniform, cheap way to attach evidence without duplicating the -//! metric-key catalogue or the reason-code format in every crate. -//! -//! Coverage policy: evidence is recorded for the *event-shaped* metric -//! families — cyclomatic, cognitive, nexit, ABC, NOM, NArgs, NPA, NPM — -//! where each contribution is a discrete syntax construct a reader can -//! look at. Per-token / per-line families (Halstead, LOC) and derived -//! aggregates (MI, WMC) are intentionally not evidenced: listing every -//! token or physical line is noise, not explanation, and WMC/MI are -//! arithmetic over already-evidenced inputs. -//! -//! Reason codes follow `.[.]`, e.g. -//! `c.cyclomatic.if_statement`, `java.abc.assignment.update_expression`, -//! `powershell.nom.closure.script_block_expression`. The `detail` -//! segment is the language crate's choice (usually the AST node kind); -//! an empty detail collapses to `.`. - -use mehen_core::{ContributionCollector, MetricContribution, MetricSpace, SourceSpan, keys}; - -/// A language-prefixed evidence sink wrapping [`ContributionCollector`]. -/// -/// All record methods are no-ops when the sink is disabled (the -/// `emit_contributions` flag from `AnalysisConfig`), so walkers can call -/// them unconditionally next to the corresponding stat increment. -#[derive(Debug)] -pub struct MetricEvidence { - collector: ContributionCollector, - lang: &'static str, -} - -impl MetricEvidence { - /// Create a sink for `lang` (the reason-code prefix, e.g. `"c"`, - /// `"powershell"`). `enabled` normally comes from - /// `AnalysisConfig::emit_contributions`. - pub fn new(lang: &'static str, enabled: bool) -> Self { - Self { - collector: ContributionCollector::new(enabled), - lang, - } - } - - pub fn is_enabled(&self) -> bool { - self.collector.is_enabled() - } - - /// Sort and yield the recorded contributions (source order, then - /// metric/reason/amount — see [`ContributionCollector::finish`]). - pub fn finish(self) -> Vec { - self.collector.finish() - } - - fn record(&mut self, metric: &'static str, span: SourceSpan, amount: f64, reason: String) { - self.collector.record(metric, span, amount, reason); - } - - fn reason(&self, family: &str, detail: &str) -> String { - if detail.is_empty() { - format!("{}.{family}", self.lang) - } else { - format!("{}.{family}.{detail}", self.lang) - } - } - - /// One cyclomatic decision point (`if`, `case`, `&&`, …). Amount +1, - /// attached to the rolled-up `cyclomatic.sum` key — the aggregate - /// that moves when a nested space gains a decision. - pub fn decision(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("cyclomatic", detail); - self.record(keys::CYCLOMATIC_SUM, span, 1.0, reason); - } - - /// Record the per-space McCabe base (+1) for every space in a finished - /// metric tree, the unit included. - /// - /// `cyclomatic.sum` rolls up `decisions + 1` per folded space, so - /// decision evidence alone can neither explain nor sum to it — adding - /// an empty function moves the metric without adding a decision. - /// Walkers call this once after the walk with the assembled root; each - /// space contributes one `.cyclomatic.base.` row spanning - /// the space, making Σ(cyclomatic evidence) == `cyclomatic.sum` by - /// construction. - pub fn record_cyclomatic_bases(&mut self, root: &MetricSpace) { - if !self.is_enabled() { - return; - } - let mut stack = vec![root]; - while let Some(space) = stack.pop() { - let reason = self.reason("cyclomatic.base", space.kind.as_str()); - self.record(keys::CYCLOMATIC_SUM, space.span, 1.0, reason); - stack.extend(space.spaces.iter()); - } - } - - /// One cognitive-complexity increment. `amount` is the structural - /// delta actually applied (`nesting + 1` for nesting constructs, - /// `1` for flat clauses and boolean-run transitions). Zero-amount - /// events (a same-operator boolean that did not move the metric) - /// are skipped. - pub fn cognitive(&mut self, span: SourceSpan, amount: u32, detail: &str) { - if !self.is_enabled() || amount == 0 { - return; - } - let reason = self.reason("cognitive", detail); - self.record(keys::COGNITIVE_SUM, span, f64::from(amount), reason); - } - - /// One exit point (`return`, `throw`, `raise`, …). Amount +1, - /// attached to the rolled-up `nexit.sum` key. - pub fn exit(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("nexit", detail); - self.record(keys::NEXIT_SUM, span, 1.0, reason); - } - - /// One ABC assignment (`A`). Amount +1. - pub fn abc_assignment(&mut self, span: SourceSpan, detail: &str) { - self.abc_assignments_n(span, 1, detail); - } - - /// `count` ABC assignments recorded as one event — for multi-target - /// assignment forms (Go's `a, b = f()`, destructuring). Zero counts - /// are skipped. - pub fn abc_assignments_n(&mut self, span: SourceSpan, count: u32, detail: &str) { - if !self.is_enabled() || count == 0 { - return; - } - let reason = self.reason("abc.assignment", detail); - self.record(keys::ABC_ASSIGNMENTS, span, f64::from(count), reason); - } - - /// One ABC branch (`B` — calls, `goto`, object creation). Amount +1. - pub fn abc_branch(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("abc.branch", detail); - self.record(keys::ABC_BRANCHES, span, 1.0, reason); - } - - /// One ABC condition (`C` — comparisons, conditional clauses). - /// Amount +1. - pub fn abc_condition(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("abc.condition", detail); - self.record(keys::ABC_CONDITIONS, span, 1.0, reason); - } - - /// One function declaration (NOM). Amount +1. - pub fn function(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("nom.function", detail); - self.record(keys::NOM_FUNCTIONS, span, 1.0, reason); - } - - /// One closure / lambda declaration (NOM). Amount +1. - pub fn closure(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("nom.closure", detail); - self.record(keys::NOM_CLOSURES, span, 1.0, reason); - } - - /// The declared parameter count of a function space (NArgs). - /// Zero-argument declarations are skipped — they don't move the - /// metric. - pub fn function_args(&mut self, span: SourceSpan, count: u32, detail: &str) { - if !self.is_enabled() || count == 0 { - return; - } - let reason = self.reason("nargs.function", detail); - self.record(keys::NARGS, span, f64::from(count), reason); - } - - /// The declared parameter count of a closure space (NArgs). Zero - /// counts are skipped. - pub fn closure_args(&mut self, span: SourceSpan, count: u32, detail: &str) { - if !self.is_enabled() || count == 0 { - return; - } - let reason = self.reason("nargs.closure", detail); - self.record(keys::NARGS, span, f64::from(count), reason); - } - - /// One public attribute of a class-like container (NPA). Amount +1. - /// Non-public members are not evidenced — the headline metric - /// counts public members only. - pub fn public_attribute(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("npa", detail); - self.record(keys::NPA, span, 1.0, reason); - } - - /// One public method of a class-like container (NPM). Amount +1. - pub fn public_method(&mut self, span: SourceSpan, detail: &str) { - if !self.is_enabled() { - return; - } - let reason = self.reason("npm", detail); - self.record(keys::NPM, span, 1.0, reason); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{MetricKey, MetricSet}; - - fn span(start: u32) -> SourceSpan { - SourceSpan::new(start, start + 4, 1, 1) - } - - #[test] - fn disabled_sink_records_nothing() { - let mut e = MetricEvidence::new("t", false); - e.decision(span(0), "if"); - e.cognitive(span(4), 2, "if"); - e.exit(span(8), "return"); - e.abc_assignment(span(12), "assign"); - e.function(span(16), "def"); - e.public_method(span(20), "method"); - assert!(e.finish().is_empty()); - } - - #[test] - fn reason_codes_are_language_prefixed_and_detail_optional() { - let mut e = MetricEvidence::new("c", true); - e.decision(span(0), "if_statement"); - e.function(span(4), ""); - let entries = e.finish(); - assert_eq!(entries[0].reason.as_str(), "c.cyclomatic.if_statement"); - assert_eq!(entries[1].reason.as_str(), "c.nom.function"); - } - - #[test] - fn zero_amount_events_are_skipped() { - let mut e = MetricEvidence::new("t", true); - e.cognitive(span(0), 0, "same_op_boolean"); - e.function_args(span(4), 0, "def"); - e.closure_args(span(8), 0, "lambda"); - assert!(e.finish().is_empty()); - } - - #[test] - fn amounts_carry_the_applied_delta() { - let mut e = MetricEvidence::new("t", true); - e.cognitive(span(0), 3, "nested_if"); - e.function_args(span(4), 5, "def"); - let entries = e.finish(); - assert_eq!(entries[0].amount, 3.0); - assert_eq!(entries[1].amount, 5.0); - } - - #[test] - fn cyclomatic_bases_cover_every_space_in_the_tree() { - use mehen_core::{SpaceId, SpaceKind}; - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, span(0)); - let mut class = MetricSpace::new(SpaceId(1), SpaceKind::Class, span(10)); - class - .spaces - .push(MetricSpace::new(SpaceId(2), SpaceKind::Function, span(20))); - root.spaces.push(class); - - let mut e = MetricEvidence::new("t", true); - e.record_cyclomatic_bases(&root); - let entries = e.finish(); - let reasons: Vec<&str> = entries.iter().map(|c| c.reason.as_str()).collect(); - assert_eq!( - reasons, - vec![ - "t.cyclomatic.base.unit", - "t.cyclomatic.base.class", - "t.cyclomatic.base.function" - ] - ); - assert!(entries.iter().all(|c| c.amount == 1.0)); - assert!( - entries - .iter() - .all(|c| c.metric.as_str() == keys::CYCLOMATIC_SUM) - ); - - let mut disabled = MetricEvidence::new("t", false); - disabled.record_cyclomatic_bases(&root); - assert!(disabled.finish().is_empty()); - } - - #[test] - fn contribution_metric_keys_match_published_key_names() { - // Evidence must attach to keys that `apply_state_to` actually - // publishes, so a report reader can join contributions to the - // metric table. Build a State, publish it, and assert every - // evidence key is present in the output. - let mut state = crate::State::new(); - state.nom.record_function(); - state.npa.record_class_like(); - state.npm.record_class_like(); - crate::finalize_state(&mut state); - let mut set = MetricSet::new(); - crate::apply_state_to(state, &mut set); - - let mut e = MetricEvidence::new("t", true); - e.decision(span(0), "d"); - e.cognitive(span(1), 1, "c"); - e.exit(span(2), "e"); - e.abc_assignment(span(3), "a"); - e.abc_branch(span(4), "b"); - e.abc_condition(span(5), "c"); - e.function(span(6), "f"); - e.closure(span(7), "l"); - e.function_args(span(8), 1, "f"); - e.closure_args(span(9), 1, "l"); - e.public_attribute(span(10), "a"); - e.public_method(span(11), "m"); - - for entry in e.finish() { - assert!( - set.get(&MetricKey::new(entry.metric.as_str())).is_some(), - "evidence key `{}` is not a published metric key", - entry.metric - ); - } - } -} diff --git a/crates/mehen-metrics/src/halstead.rs b/crates/mehen-metrics/src/halstead.rs deleted file mode 100644 index d64dd914..00000000 --- a/crates/mehen-metrics/src/halstead.rs +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::ser::SerializeStruct; -use serde::{Serialize, Serializer}; - -use crate::halstead_builder::HalsteadCounts; - -/// Finalized Halstead measurements for one space. -/// -/// All formulas are pure math. The pre-1.0 implementation lives at -/// `src/metrics/halstead.rs`; the formulas reproduced here come from the -/// classic Halstead definitions and match the existing reference output. -/// -/// Built by feeding token-level events into `HalsteadBuilder`, then calling -/// `HalsteadStats::from_counts(builder.counts())`. Language crates own -/// what counts as an operator or operand; the math is shared. -#[derive(Default, Clone, Debug, PartialEq)] -pub struct HalsteadStats { - /// `n1` — distinct operators. - pub u_operators: u64, - /// `N1` — total operators. - pub operators: u64, - /// `n2` — distinct operands. - pub u_operands: u64, - /// `N2` — total operands. - pub operands: u64, -} - -impl HalsteadStats { - pub fn from_counts(counts: HalsteadCounts) -> Self { - Self { - u_operators: counts.n1 as u64, - operators: counts.big_n1 as u64, - u_operands: counts.n2 as u64, - operands: counts.big_n2 as u64, - } - } - - pub fn vocabulary(&self) -> f64 { - (self.u_operators + self.u_operands) as f64 - } - - pub fn length(&self) -> f64 { - (self.operators + self.operands) as f64 - } - - pub fn estimated_program_length(&self) -> f64 { - // `n * log2(n)` is `0 * -inf = NaN` when `n == 0`. Guard each - // term so an empty token stream serializes a finite `0.0`. - Self::n_log2_n(self.u_operators) + Self::n_log2_n(self.u_operands) - } - - fn n_log2_n(n: u64) -> f64 { - if n == 0 { - 0.0 - } else { - let nf = n as f64; - nf * nf.log2() - } - } - - pub fn purity_ratio(&self) -> f64 { - let len = self.length(); - if len == 0.0 { - 0.0 - } else { - self.estimated_program_length() / len - } - } - - pub fn volume(&self) -> f64 { - let voc = self.vocabulary(); - if voc <= 0.0 { - 0.0 - } else { - self.length() * voc.log2() - } - } - - pub fn difficulty(&self) -> f64 { - let n2 = self.u_operands as f64; - if n2 == 0.0 { - 0.0 - } else { - (self.u_operators as f64) / 2.0 * (self.operands as f64) / n2 - } - } - - pub fn level(&self) -> f64 { - let d = self.difficulty(); - if d == 0.0 { 0.0 } else { 1.0 / d } - } - - pub fn effort(&self) -> f64 { - self.difficulty() * self.volume() - } - - /// Time to write the program in seconds, per Halstead's heuristic. - pub fn time(&self) -> f64 { - self.effort() / 18.0 - } - - /// Estimated number of bugs delivered, per Halstead's - /// `B = E^(2/3) / 3000` formula. Matches the pre-1.0 implementation - /// in `crates/mehen-engine/src/legacy/metrics/halstead.rs::bugs`. - pub fn bugs(&self) -> f64 { - self.effort().powf(2.0 / 3.0) / 3000.0 - } -} - -impl Serialize for HalsteadStats { - fn serialize(&self, serializer: S) -> Result { - // Field set kept in sync with the pre-1.0 output shape so parity - // snapshots can compare directly. - let mut st = serializer.serialize_struct("halstead", 14)?; - st.serialize_field("n1", &(self.u_operators as f64))?; - st.serialize_field("N1", &(self.operators as f64))?; - st.serialize_field("n2", &(self.u_operands as f64))?; - st.serialize_field("N2", &(self.operands as f64))?; - st.serialize_field("length", &self.length())?; - st.serialize_field("estimated_program_length", &self.estimated_program_length())?; - st.serialize_field("purity_ratio", &self.purity_ratio())?; - st.serialize_field("vocabulary", &self.vocabulary())?; - st.serialize_field("volume", &self.volume())?; - st.serialize_field("difficulty", &self.difficulty())?; - st.serialize_field("level", &self.level())?; - st.serialize_field("effort", &self.effort())?; - st.serialize_field("time", &self.time())?; - st.serialize_field("bugs", &self.bugs())?; - st.end() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::halstead_builder::{HalsteadBuilder, HalsteadOperand, HalsteadOperator}; - use smol_str::SmolStr; - - #[test] - fn empty_stats_have_zero_volume() { - let s = HalsteadStats::default(); - assert_eq!(s.volume(), 0.0); - assert_eq!(s.difficulty(), 0.0); - } - - #[test] - fn from_builder_round_trips() { - let mut b = HalsteadBuilder::new(); - b.observe_operator(HalsteadOperator { - kind: SmolStr::new("+"), - text: None, - }); - b.observe_operator(HalsteadOperator { - kind: SmolStr::new("="), - text: None, - }); - b.observe_operand(HalsteadOperand { - kind: SmolStr::new("ident"), - text: Some(SmolStr::new("x")), - }); - b.observe_operand(HalsteadOperand { - kind: SmolStr::new("number"), - text: Some(SmolStr::new("1")), - }); - let stats = HalsteadStats::from_counts(b.counts()); - assert_eq!(stats.u_operators, 2); - assert_eq!(stats.operators, 2); - assert_eq!(stats.u_operands, 2); - assert_eq!(stats.operands, 2); - assert_eq!(stats.vocabulary(), 4.0); - assert_eq!(stats.length(), 4.0); - } -} diff --git a/crates/mehen-metrics/src/halstead_builder.rs b/crates/mehen-metrics/src/halstead_builder.rs deleted file mode 100644 index 4d74bc99..00000000 --- a/crates/mehen-metrics/src/halstead_builder.rs +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::collections::HashSet; - -use smol_str::SmolStr; - -/// One operator token observed by a language analyzer. -/// -/// Per the rewrite plan §5.1: -/// - language crates emit per-token operator/operand events, -/// - `mehen-metrics` owns set-based `n1`/`n2` deduplication and `N1`/`N2` -/// totals, -/// - language crates own classification (e.g. "Python `String` is operand -/// only when not a docstring"); they decide *what* to emit, the builder -/// decides *how to count it*. -/// -/// The `kind` field is the language-side classification (the AST kind name -/// or a stable token category). The `text` field, when present, is used for -/// operand-text deduplication where the language wants it (variable names, -/// numeric literals normalized to a canonical form, …). -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct HalsteadOperator { - pub kind: SmolStr, - pub text: Option, -} - -/// One operand token observed by a language analyzer. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct HalsteadOperand { - pub kind: SmolStr, - pub text: Option, -} - -/// Counts derived from a [`HalsteadBuilder`]: distinct operators (`n1`), -/// distinct operands (`n2`), total operators (`N1`), total operands (`N2`). -/// -/// Volume / difficulty / effort live on `mehen_metrics::HalsteadStats` -/// once Phase 3 finalizes that struct; this builder only owns the -/// dedup/totalling step. -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub struct HalsteadCounts { - pub n1: u32, - pub n2: u32, - pub big_n1: u32, - pub big_n2: u32, -} - -/// Accumulates operator/operand events for one space. -/// -/// The dedup key is the operator/operand value as emitted by the language -/// crate. The crate is responsible for normalizing token text where it -/// wants language-specific behavior (Python docstrings → not operands; -/// JavaScript numeric `0x10` and `16` should canonicalize to the same -/// operand if the language crate chooses to). -#[derive(Default, Debug, Clone)] -pub struct HalsteadBuilder { - operators: HashSet, - operands: HashSet, - big_n1: u32, - big_n2: u32, -} - -impl HalsteadBuilder { - pub fn new() -> Self { - Self::default() - } - - pub fn observe_operator(&mut self, op: HalsteadOperator) { - self.big_n1 = self.big_n1.saturating_add(1); - self.operators.insert(op); - } - - pub fn observe_operand(&mut self, op: HalsteadOperand) { - self.big_n2 = self.big_n2.saturating_add(1); - self.operands.insert(op); - } - - pub fn counts(&self) -> HalsteadCounts { - HalsteadCounts { - n1: self.operators.len() as u32, - n2: self.operands.len() as u32, - big_n1: self.big_n1, - big_n2: self.big_n2, - } - } - - /// Iterator over distinct operator entries — for tests / diagnostics. - pub fn operators(&self) -> impl Iterator { - self.operators.iter() - } - - /// Iterator over distinct operand entries — for tests / diagnostics. - pub fn operands(&self) -> impl Iterator { - self.operands.iter() - } - - /// Merge counts from a child space (post-finalize) into this one. - pub fn merge(&mut self, other: &HalsteadBuilder) { - for op in &other.operators { - self.operators.insert(op.clone()); - } - for op in &other.operands { - self.operands.insert(op.clone()); - } - self.big_n1 = self.big_n1.saturating_add(other.big_n1); - self.big_n2 = self.big_n2.saturating_add(other.big_n2); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn op(kind: &str) -> HalsteadOperator { - HalsteadOperator { - kind: SmolStr::new(kind), - text: None, - } - } - - fn operand(text: &str) -> HalsteadOperand { - HalsteadOperand { - kind: SmolStr::new("identifier"), - text: Some(SmolStr::new(text)), - } - } - - #[test] - fn dedups_operators() { - let mut b = HalsteadBuilder::new(); - b.observe_operator(op("+")); - b.observe_operator(op("+")); - b.observe_operator(op("-")); - let c = b.counts(); - assert_eq!(c.n1, 2); - assert_eq!(c.big_n1, 3); - } - - #[test] - fn dedups_operands_by_text() { - let mut b = HalsteadBuilder::new(); - b.observe_operand(operand("x")); - b.observe_operand(operand("x")); - b.observe_operand(operand("y")); - let c = b.counts(); - assert_eq!(c.n2, 2); - assert_eq!(c.big_n2, 3); - } - - #[test] - fn merge_unions_distinct_sets() { - let mut a = HalsteadBuilder::new(); - a.observe_operator(op("+")); - let mut b = HalsteadBuilder::new(); - b.observe_operator(op("-")); - a.merge(&b); - let c = a.counts(); - assert_eq!(c.n1, 2); - assert_eq!(c.big_n1, 2); - } -} diff --git a/crates/mehen-metrics/src/halstead_routing.rs b/crates/mehen-metrics/src/halstead_routing.rs deleted file mode 100644 index 5c24e6ff..00000000 --- a/crates/mehen-metrics/src/halstead_routing.rs +++ /dev/null @@ -1,566 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Per-space Halstead token routing. -//! -//! Most Mehen analyzers compute Halstead by walking a flat token stream -//! after the AST walk has already opened (and possibly closed) every -//! function / class / closure space. A naive token sweep that records -//! every event onto the unit space is wrong: the per-space `MetricSpace` -//! entries in the JSON report end up with zero Halstead even though the -//! root rollup is correct. -//! -//! This module owns the bookkeeping that maps each token to the deepest -//! enclosing scope and propagates the per-space counts through the -//! parent chain via set-union (matching what -//! [`crate::HalsteadBuilder::merge`] does on every other code path). -//! -//! # Walker flow -//! -//! 1. As the walker's `open_space` (or equivalent) hook runs, it calls -//! [`SpaceRangeTracker::record_open`] with the `SpaceId` minted by -//! [`crate::MetricTreeBuilder::open`] and the AST node's byte range. -//! The tracker uses insertion-vs-still-active order to recover the -//! parent link — each new entry's parent is the most recent entry -//! whose byte range encloses it. -//! 2. As the walker's `close_space` runs (still during the AST walk), -//! it calls [`SpaceRangeTracker::record_close`] with the closing -//! space's `LocStats` and `CyclomaticStats`. These are the inputs -//! the [Maintainability Index][mi] needs alongside Halstead, so we -//! stash them now while they're still in scope. -//! 3. After the AST walk finishes, the walker iterates the source's -//! token stream; for each operator/operand event it calls -//! [`SpaceRangeTracker::observe_operator`] / `observe_operand` with -//! the token's byte range. The tracker routes the event to the -//! deepest still-open scope at that range, falling back to the unit -//! [`HalsteadBuilder`] when no recorded entry encloses it. -//! 4. The walker calls [`SpaceRangeTracker::finalize_into_tree`] which: -//! - propagates each entry's `HalsteadBuilder` up its parent chain -//! (set-union for `n1`/`n2`, sum for `N1`/`N2`), -//! - merges the rolled-up sets into `unit_halstead` so the unit -//! space's keys reflect the file-wide rollup, -//! - overwrites the Halstead-derived metric keys (and the -//! Halstead-dependent MI keys) inside the matching `MetricSpace` -//! of the `tree`. -//! -//! [mi]: crate::MiStats - -use std::collections::HashMap; - -use mehen_core::{MetricKey, MetricSet, MetricSpace, SpaceId}; - -use crate::cyclomatic::CyclomaticStats; -use crate::halstead::HalsteadStats; -use crate::halstead_builder::{HalsteadBuilder, HalsteadOperand, HalsteadOperator}; -use crate::keys; -use crate::loc::LocStats; -use crate::mi::MiStats; -use crate::state::publish_halstead; - -/// Tracks every space opened during the AST walk so a post-AST token -/// sweep can route each operator/operand event to the deepest enclosing -/// scope. -/// -/// The unit (`SpaceId(0)`) is implicit — any token that does not fall -/// inside a recorded entry routes to the caller-supplied unit -/// [`HalsteadBuilder`]. -#[derive(Debug, Default)] -pub struct SpaceRangeTracker { - entries: Vec, -} - -#[derive(Debug)] -struct Entry { - space_id: SpaceId, - start: u32, - end: u32, - /// Index of the parent entry in `entries`, or `None` when the - /// parent is the unit scope. `record_open` is called in source - /// order while the AST walk is still descending; the most recent - /// still-active entry whose byte range encloses ours is the - /// parent. - parent: Option, - halstead: HalsteadBuilder, - /// AST-driven LOC + cyclomatic snapshots taken at space-close - /// time. The overlay recomputes Halstead-derived keys + MI from - /// these against the post-token-sweep Halstead, and folds - /// `loc_token_events` into a final per-space LocStats so the - /// overlay also corrects per-space PLOC/CLOC keys (PR #95 - /// discussion_r3265962147 — without routing tokens into the - /// active space, post-AST token sweeps left - /// `root.spaces[*].metrics["loc.ploc"]` at zero). - loc: LocStats, - cyclomatic: CyclomaticStats, - /// Token-driven LOC events routed to this space. Always merged - /// into `loc` (and propagated up the parent chain) by - /// [`SpaceRangeTracker::finalize_into_tree`] before the LOC keys - /// are overlaid. - loc_token_events: LocStats, -} - -impl SpaceRangeTracker { - pub fn new() -> Self { - Self::default() - } - - /// Record a newly-opened space's `SpaceId` and byte range. Call - /// from the walker's `open_space` hook, right after the - /// [`MetricTreeBuilder::open`][crate::MetricTreeBuilder::open] - /// call has minted the `SpaceId`. - pub fn record_open(&mut self, space_id: SpaceId, start: u32, end: u32) { - let parent = self.deepest_enclosing_index(start, end); - self.entries.push(Entry { - space_id, - start, - end, - parent, - halstead: HalsteadBuilder::new(), - loc: LocStats::default(), - cyclomatic: CyclomaticStats::default(), - loc_token_events: LocStats::default(), - }); - } - - /// Stash the LOC and cyclomatic snapshots needed to recompute MI - /// after the token sweep. Call from the walker's `close_space` - /// hook with the about-to-be-published state's values. Quietly - /// no-ops when the `space_id` was not previously recorded via - /// [`record_open`] — the unit scope is implicit. - /// - /// The captured AST `LocStats` also seeds the entry's - /// `loc_token_events.ploc_lines` so that subsequent - /// `observe_comment` calls correctly classify a comment as - /// "code-comment" (same line as code) vs. "only-comment" — without - /// the seed, every token-stream comment inside a function body - /// reads as only-comment because the tracker's accumulator started - /// fresh and did not see the AST-walk's PLOC observations. - pub fn record_close( - &mut self, - space_id: SpaceId, - loc: &LocStats, - cyclomatic: &CyclomaticStats, - ) { - if let Some(entry) = self.entries.iter_mut().find(|e| e.space_id == space_id) { - entry.loc = loc.clone(); - entry.cyclomatic = cyclomatic.clone(); - // Seed the token accumulator's `ploc_lines` from the AST - // snapshot so `observe_comment`'s "after-code on same - // line" check sees the function's existing code lines. - entry.loc_token_events.seed_ploc_lines(loc); - } - } - - /// Return the deepest entry whose range strictly encloses - /// `[start, end)`, or `None` if no such entry exists. - fn deepest_enclosing_index(&self, start: u32, end: u32) -> Option { - // Reverse insertion order — the deepest still-active entry is - // the most recent one whose range encloses ours. - self.entries - .iter() - .enumerate() - .rev() - .find(|(_, e)| e.start <= start && end <= e.end) - .map(|(i, _)| i) - } - - /// Observe an operator event into the deepest scope containing - /// `[span_start, span_end)`, falling back to `unit_halstead` when - /// no recorded entry encloses it. - pub fn observe_operator( - &mut self, - span_start: u32, - span_end: u32, - unit_halstead: &mut HalsteadBuilder, - op: HalsteadOperator, - ) { - match self.deepest_enclosing_index(span_start, span_end) { - Some(idx) => self.entries[idx].halstead.observe_operator(op), - None => unit_halstead.observe_operator(op), - } - } - - /// Observe an operand event into the deepest scope containing - /// `[span_start, span_end)`, falling back to `unit_halstead`. - pub fn observe_operand( - &mut self, - span_start: u32, - span_end: u32, - unit_halstead: &mut HalsteadBuilder, - op: HalsteadOperand, - ) { - match self.deepest_enclosing_index(span_start, span_end) { - Some(idx) => self.entries[idx].halstead.observe_operand(op), - None => unit_halstead.observe_operand(op), - } - } - - /// Route a PLOC code-line observation to the deepest scope - /// containing `[span_start, span_end)`, falling back to - /// `unit_loc`. Lines are deduplicated per scope by the underlying - /// `LocStats::observe_code_line` (set semantics). - pub fn observe_code_line( - &mut self, - span_start: u32, - span_end: u32, - unit_loc: &mut LocStats, - start_row: u32, - ) { - match self.deepest_enclosing_index(span_start, span_end) { - Some(idx) => self.entries[idx] - .loc_token_events - .observe_code_line(start_row), - None => unit_loc.observe_code_line(start_row), - } - } - - /// Route a comment observation to the deepest scope containing - /// `[span_start, span_end)`, falling back to `unit_loc`. - pub fn observe_comment( - &mut self, - span_start: u32, - span_end: u32, - unit_loc: &mut LocStats, - start_row: u32, - end_row: u32, - ) { - match self.deepest_enclosing_index(span_start, span_end) { - Some(idx) => self.entries[idx] - .loc_token_events - .observe_comment(start_row, end_row), - None => unit_loc.observe_comment(start_row, end_row), - } - } - - /// Propagate each entry's per-space Halstead counts up its parent - /// chain (set-union for `n1`/`n2`, sum for `N1`/`N2`), merge them - /// into `unit_halstead`, and overwrite the Halstead-derived keys - /// (and the Halstead-dependent MI keys) for every matching space - /// inside `tree`. - /// - /// The unit space's metrics are written by the caller via - /// [`crate::apply_state_to`] using `unit_halstead` after this - /// function returns; this overlay only touches recorded child - /// spaces. - pub fn finalize_into_tree( - mut self, - tree: &mut MetricSpace, - unit_halstead: &mut HalsteadBuilder, - unit_loc: &mut LocStats, - ) { - // Walk deepest-first so each parent has absorbed every - // descendant by the time we touch it. `record_open` pushes in - // source-prefix order, so iterating `entries` in reverse - // visits children before parents. - for i in (0..self.entries.len()).rev() { - // Halstead — merge child's set-based counts into parent. - let child_h = std::mem::take(&mut self.entries[i].halstead); - // LOC token events — merge child's token-only LocStats - // into parent's token-only LocStats so the parent's - // overlay sees the file-wide rollup. Uses - // `merge_token_observations` to avoid touching min/max - // bounds (those were finalized at AST close time). - let child_loc_token = std::mem::take(&mut self.entries[i].loc_token_events); - match self.entries[i].parent { - Some(p) => { - self.entries[p].halstead.merge(&child_h); - self.entries[p] - .loc_token_events - .merge_token_observations(&child_loc_token); - } - None => { - unit_halstead.merge(&child_h); - unit_loc.merge_token_observations(&child_loc_token); - } - } - self.entries[i].halstead = child_h; - self.entries[i].loc_token_events = child_loc_token; - } - - // Build a `SpaceId -> overlay inputs` lookup so the recursive - // overlay pass below is a simple `get`. Each entry's `loc` is - // cloned and folded with `loc_token_events` into a final - // per-space LocStats; the overlay writes the LOC headline - // keys and recomputes MI from the combined value. - let mut by_space: HashMap = HashMap::new(); - for entry in &self.entries { - let mut combined = entry.loc.clone(); - combined.merge_token_observations(&entry.loc_token_events); - by_space.insert( - entry.space_id, - OverlayInputs { - halstead: entry.halstead.clone(), - loc: combined, - cyclomatic: entry.cyclomatic.clone(), - }, - ); - } - overlay(tree, &by_space); - } -} - -struct OverlayInputs { - halstead: HalsteadBuilder, - loc: LocStats, - cyclomatic: CyclomaticStats, -} - -fn overlay(space: &mut MetricSpace, by_space: &HashMap) { - if let Some(inputs) = by_space.get(&space.id) { - let counts = inputs.halstead.counts(); - let token_halstead_observed = counts.big_n1 > 0 || counts.big_n2 > 0; - // Pattern A walkers (Go, Ruby) record Halstead *during* the - // AST walk via `current()`, so the per-space MetricSet already - // has the correct Halstead keys — `apply_state_to` at close - // wrote them, and the AST close path rolled them up via - // `merge_child_into_parent`. The tracker's `halstead` for - // those walkers is empty, so we must NOT overwrite the - // already-correct keys with zeros. - // - // Pattern B walkers (Python, TypeScript, Rust, PHP) emit - // Halstead in a post-AST token sweep into the tracker, so the - // tracker's `halstead` is the source of truth and the overlay - // is what makes per-space JSON entries non-zero. - if token_halstead_observed { - let halstead = HalsteadStats::from_counts(counts); - publish_halstead(&halstead, &mut space.metrics); - // MI re-computation depends on Halstead volume — only - // recompute when Halstead actually changed; otherwise the - // MI keys written by `apply_state_to` at AST close are - // already correct. - let mi = MiStats::compute(&inputs.loc, &inputs.cyclomatic, &halstead); - space - .metrics - .insert(MetricKey::new(keys::MI_VS), mi.mi_visual_studio); - space - .metrics - .insert(MetricKey::new(keys::MI_ORIGINAL), mi.mi_original); - space - .metrics - .insert(MetricKey::new(keys::MI_SEI), mi.mi_sei); - } - write_loc_token_keys(&inputs.loc, &mut space.metrics); - } - for child in &mut space.spaces { - overlay(child, by_space); - } -} - -/// Overwrite the LOC headline keys (`loc.ploc`, `loc.cloc`, -/// `loc.sloc`, `loc.lloc`, `loc.blank`, `loc`) on a `MetricSet` from -/// the combined `LocStats`. The min/max/avg keys are intentionally -/// not rewritten — those reflect AST-walk roll-ups across spaces and -/// were already published correctly by `apply_state_to` at close -/// time. This overlay corrects the *per-space* PLOC / CLOC counts -/// the post-AST token sweep contributed (PR #95 -/// discussion_r3265962147). -fn write_loc_token_keys(stats: &LocStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::LOC_PLOC), stats.ploc() as i64); - target.insert(MetricKey::new(keys::LOC_CLOC), stats.cloc() as i64); - target.insert(MetricKey::new(keys::LOC_LLOC), stats.lloc() as i64); - target.insert(MetricKey::new(keys::LOC_SLOC), stats.sloc() as i64); - target.insert(MetricKey::new(keys::LOC_BLANK), stats.blank() as i64); - target.insert(MetricKey::new(keys::LOC), stats.sloc() as i64); -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{SourceSpan, SpaceKind}; - use smol_str::SmolStr; - - fn op(kind: &str) -> HalsteadOperator { - HalsteadOperator { - kind: SmolStr::new(kind), - text: None, - } - } - fn opd(text: &str) -> HalsteadOperand { - HalsteadOperand { - kind: SmolStr::new("Operand"), - text: Some(SmolStr::new(text)), - } - } - - fn span(start: u32, end: u32) -> SourceSpan { - SourceSpan { - start_byte: start, - end_byte: end, - start_line: 1, - end_line: 1, - } - } - - #[test] - fn route_picks_deepest_enclosing_entry() { - let mut t = SpaceRangeTracker::new(); - t.record_open(SpaceId(1), 0, 100); // outer function - t.record_open(SpaceId(2), 20, 80); // nested function - let mut unit = HalsteadBuilder::new(); - - // Inside both — deepest is SpaceId(2). - t.observe_operator(50, 51, &mut unit, op("+")); - // Inside SpaceId(1) only. - t.observe_operator(5, 6, &mut unit, op("-")); - // Outside everything — unit. - t.observe_operator(200, 201, &mut unit, op("*")); - // Inside SpaceId(1) only (after the inner range ends). - t.observe_operand(85, 88, &mut unit, opd("foo")); - - let inner_n1 = t - .entries - .iter() - .find(|e| e.space_id == SpaceId(2)) - .unwrap() - .halstead - .counts(); - assert_eq!(inner_n1.big_n1, 1, "deepest entry got the deepest token"); - - let outer = t - .entries - .iter() - .find(|e| e.space_id == SpaceId(1)) - .unwrap() - .halstead - .counts(); - assert_eq!(outer.big_n1, 1); - assert_eq!(outer.big_n2, 1); - assert_eq!(unit.counts().big_n1, 1); - } - - #[test] - fn finalize_propagates_counts_up_parent_chain_and_overlays_tree() { - let mut t = SpaceRangeTracker::new(); - t.record_open(SpaceId(1), 0, 100); - t.record_open(SpaceId(2), 20, 80); - // Stash the MI inputs the close hook would supply. - t.record_close( - SpaceId(1), - &LocStats::default(), - &CyclomaticStats::default(), - ); - t.record_close( - SpaceId(2), - &LocStats::default(), - &CyclomaticStats::default(), - ); - - let mut unit = HalsteadBuilder::new(); - t.observe_operator(50, 51, &mut unit, op("+")); - t.observe_operator(5, 6, &mut unit, op("-")); - - // Build a tree: unit > SpaceId(1) > SpaceId(2). - let mut tree = MetricSpace::new(SpaceId(0), SpaceKind::Unit, span(0, 100)); - let mut outer = MetricSpace::new(SpaceId(1), SpaceKind::Function, span(0, 100)); - let inner = MetricSpace::new(SpaceId(2), SpaceKind::Function, span(20, 80)); - outer.spaces.push(inner); - tree.spaces.push(outer); - - let mut unit_loc = LocStats::default(); - t.finalize_into_tree(&mut tree, &mut unit, &mut unit_loc); - - let inner_n1 = tree.spaces[0].spaces[0] - .metrics - .get(&MetricKey::new(format!("{}.N1", keys::HALSTEAD))) - .unwrap() - .as_f64(); - let outer_n1 = tree.spaces[0] - .metrics - .get(&MetricKey::new(format!("{}.N1", keys::HALSTEAD))) - .unwrap() - .as_f64(); - assert_eq!(inner_n1, 1.0, "inner observed only the +"); - assert_eq!(outer_n1, 2.0, "outer rolls up inner's + plus its own -"); - assert_eq!(unit.counts().big_n1, 2, "unit absorbs the rolled-up outer"); - } - - #[test] - fn unit_only_token_does_not_touch_recorded_entries() { - let mut t = SpaceRangeTracker::new(); - t.record_open(SpaceId(1), 0, 100); - t.record_close( - SpaceId(1), - &LocStats::default(), - &CyclomaticStats::default(), - ); - - let mut unit = HalsteadBuilder::new(); - t.observe_operator(500, 501, &mut unit, op("+")); - - let mut tree = MetricSpace::new(SpaceId(0), SpaceKind::Unit, span(0, 1000)); - let outer = MetricSpace::new(SpaceId(1), SpaceKind::Function, span(0, 100)); - tree.spaces.push(outer); - let mut unit_loc = LocStats::default(); - t.finalize_into_tree(&mut tree, &mut unit, &mut unit_loc); - - // The outer space received no tokens, so the overlay must - // leave its Halstead keys alone — Pattern A walkers (Go, - // Ruby) record Halstead via `current()` during the AST walk - // and rely on the overlay NOT clobbering those values with - // tracker-derived zeros. - let outer_n1 = tree.spaces[0] - .metrics - .get(&MetricKey::new(format!("{}.N1", keys::HALSTEAD))); - assert!( - outer_n1.is_none(), - "overlay must skip Halstead keys for tracker entries with zero tokens, got {outer_n1:?}" - ); - assert_eq!(unit.counts().big_n1, 1); - } - - /// Regression: PLOC code-line observations route to the deepest - /// enclosing scope. Without routing, every line ends up on the - /// unit and the per-space `loc.ploc` reads as 0. - #[test] - fn loc_code_lines_route_to_deepest_enclosing_scope() { - use crate::keys; - let mut t = SpaceRangeTracker::new(); - t.record_open(SpaceId(1), 0, 100); - t.record_open(SpaceId(2), 20, 80); - t.record_close( - SpaceId(1), - &LocStats::default(), - &CyclomaticStats::default(), - ); - t.record_close( - SpaceId(2), - &LocStats::default(), - &CyclomaticStats::default(), - ); - - let mut unit_h = HalsteadBuilder::new(); - let mut unit_loc = LocStats::default(); - // Line 5 — inside SpaceId(2) (the inner). - t.observe_code_line(50, 51, &mut unit_loc, 5); - t.observe_code_line(60, 61, &mut unit_loc, 6); - // Line 9 — inside SpaceId(1) only (between 80 and 100). - t.observe_code_line(85, 86, &mut unit_loc, 9); - // Line 99 — outside both. - t.observe_code_line(500, 501, &mut unit_loc, 99); - - let mut tree = MetricSpace::new(SpaceId(0), SpaceKind::Unit, span(0, 1000)); - let mut outer = MetricSpace::new(SpaceId(1), SpaceKind::Function, span(0, 100)); - let inner = MetricSpace::new(SpaceId(2), SpaceKind::Function, span(20, 80)); - outer.spaces.push(inner); - tree.spaces.push(outer); - - t.finalize_into_tree(&mut tree, &mut unit_h, &mut unit_loc); - - let inner_ploc = tree.spaces[0].spaces[0] - .metrics - .get(&MetricKey::new(keys::LOC_PLOC)) - .unwrap() - .as_f64(); - assert_eq!(inner_ploc, 2.0, "inner sees lines 5 and 6"); - - let outer_ploc = tree.spaces[0] - .metrics - .get(&MetricKey::new(keys::LOC_PLOC)) - .unwrap() - .as_f64(); - assert_eq!( - outer_ploc, 3.0, - "outer rolls up inner's two lines + own line 9" - ); - assert_eq!(unit_loc.ploc(), 4, "unit absorbs all four lines"); - } -} diff --git a/crates/mehen-metrics/src/lib.rs b/crates/mehen-metrics/src/lib.rs deleted file mode 100644 index 672a42b2..00000000 --- a/crates/mehen-metrics/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-metrics` — shared metric contracts, formulas, accumulators, and -//! aggregation helpers. -//! -//! This crate must not become a central all-language calculator. Per the -//! rewrite plan §4.3: -//! - It owns the metric *math* (Halstead volume, MI formulas, min/max/avg -//! finalization, set-based n1/n2 dedup, …). -//! - It does not own language interpretation (which Python AST nodes are -//! decisions, whether a Ruby rescue modifier counts toward cognitive, -//! etc.). -//! -//! Phase 1 ships the typed accumulator surface — `LocStats`, -//! `CyclomaticStats`, `CognitiveStats`, `HalsteadStats`, `AbcStats`, -//! `NargsStats`, `NomStats`, `NexitStats`, `MiStats`, `WmcStats`, -//! `NpaStats`, `NpmStats` — plus the `HalsteadBuilder` event sink and the -//! `MetricTreeBuilder` helper that language crates use to assemble a -//! `MetricSpace` tree without each crate re-implementing id allocation. - -#![forbid(unsafe_code)] - -mod abc; -mod cognitive; -mod counters; -mod cyclomatic; -mod evidence; -mod halstead; -mod halstead_builder; -mod halstead_routing; -mod loc; -mod mi; -mod state; -mod tree_builder; - -pub use abc::AbcStats; -pub use cognitive::CognitiveStats; -pub use counters::{ContainerKind, NargsStats, NexitStats, NomStats, NpaStats, NpmStats, WmcStats}; -pub use cyclomatic::CyclomaticStats; -pub use evidence::MetricEvidence; -pub use halstead::HalsteadStats; -pub use halstead_builder::{HalsteadBuilder, HalsteadCounts, HalsteadOperand, HalsteadOperator}; -pub use halstead_routing::SpaceRangeTracker; -pub use loc::{LineClass, LocStats}; -pub use mi::MiStats; -pub use state::{State, apply_state_to, close_space, finalize_state, merge_child_into_parent}; -pub use tree_builder::MetricTreeBuilder; - -// Re-export the metric key namespace and the selector/threshold contract -// surface from `mehen-core` so existing `mehen_metrics::*` consumers -// keep compiling. Per the plan §4.2 these are contract types that -// belong to `mehen-core`; per §8.2 the selector catalogue may live in -// either crate. -pub use mehen_core::{ - MetricKey, MetricSelector, Polarity, SelectorAggregator, SelectorParseError, Threshold, - ThresholdEvaluation, ThresholdViolation, keys, -}; diff --git a/crates/mehen-metrics/src/loc.rs b/crates/mehen-metrics/src/loc.rs deleted file mode 100644 index 68c68b08..00000000 --- a/crates/mehen-metrics/src/loc.rs +++ /dev/null @@ -1,403 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::collections::HashSet; - -use serde::ser::SerializeStruct; -use serde::{Serialize, Serializer}; - -/// Legacy line-class enum, kept for the small number of generic helpers -/// (`default_line_classifier`) that still classify whole physical lines -/// rather than AST nodes. Per-language LOC computation now goes through -/// the AST-based observation methods on [`LocStats`] so the per- -/// language rules (which nodes are containers, statements, comments) -/// match the pre-1.0 `Loc::compute` semantics exactly. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum LineClass { - Blank, - Comment, - Code, - Logical, -} - -/// Accumulator for the LOC family. -/// -/// Mirrors the pre-1.0 `src/metrics/loc.rs` algorithm exactly so parity -/// snapshots compare directly: -/// -/// - **SLOC**: physical line span of the space — `end_row - start_row` -/// for the unit, `end_row - start_row + 1` for nested spaces. Set -/// once via [`LocStats::set_span`] when the space opens. -/// - **PLOC**: number of distinct lines on which a "code" AST node -/// started — tracked as a `HashSet`. -/// - **LLOC**: count of statement-shaped AST nodes. Each language -/// classifies a node as LLOC via its rules. -/// - **CLOC**: tracks comment-only lines vs. comments adjacent to code -/// lines per the pre-1.0 `add_cloc_lines` / -/// `check_comment_ends_on_code_line` rules. -/// - **Blank** = `sloc - ploc - only_comment_lines`. -/// -/// On space close, [`LocStats::finalize_minmax`] snapshots the per- -/// space totals into the rolled-up sums and `*_min` / `*_max` bounds -/// and bumps `space_count`. Averages divide by `space_count`. -#[derive(Default, Clone, Debug, PartialEq)] -pub struct LocStats { - // Span (set once at space open; SLOC is derived). - span_start: u32, - span_end: u32, - span_is_unit: bool, - span_set: bool, - - /// Distinct line numbers on which a non-container, non-comment, - /// non-LLOC-statement node started. Counts as PLOC. - ploc_lines: HashSet, - /// Per-language statement count. Each LLOC node bumps this by one. - lloc_count: u32, - /// Lines that are *only* comments — neither preceded by code nor - /// followed by it on the same line. - only_comment_lines: u32, - /// Comments that share their line with a code line. - code_comment_lines: u32, - /// End row of the most recent comment, used to detect a comment - /// that ends just before a code line. - last_comment_end: Option, - - // Rolled-up min/max bounds across spaces. - pub sloc_min: u32, - pub sloc_max: u32, - pub ploc_min: u32, - pub ploc_max: u32, - pub lloc_min: u32, - pub lloc_max: u32, - pub cloc_min: u32, - pub cloc_max: u32, - pub blank_min: u32, - pub blank_max: u32, - - /// Number of spaces folded into the bounds. Bumped by - /// `finalize_minmax`; used as the average denominator. - pub space_count: u32, - /// Sentinel — set on first finalize so 0-valued bounds don't get - /// wiped on subsequent finalizes. - pub minmax_seen: bool, -} - -impl LocStats { - /// Set the physical line span of this space. The walker calls this - /// once when the space opens (before any node observations). - pub fn set_span(&mut self, start_row: u32, end_row: u32, is_unit: bool) { - self.span_start = start_row; - self.span_end = end_row; - self.span_is_unit = is_unit; - self.span_set = true; - } - - /// Per-space SLOC = span (rows). The legacy convention adds `+1` - /// for non-unit spaces to count the function-signature line, and - /// uses bare `end - start` for the unit (where `end` is exclusive). - pub fn sloc(&self) -> u32 { - if !self.span_set { - return 0; - } - let span = self.span_end.saturating_sub(self.span_start); - if self.span_is_unit { span } else { span + 1 } - } - - /// Per-space PLOC = number of distinct code lines. - pub fn ploc(&self) -> u32 { - self.ploc_lines.len() as u32 - } - - /// Per-space LLOC = number of statement-shaped nodes. - pub fn lloc(&self) -> u32 { - self.lloc_count - } - - /// Per-space CLOC = comment-only lines + code-comment lines. - pub fn cloc(&self) -> u32 { - self.only_comment_lines - .saturating_add(self.code_comment_lines) - } - - /// Per-space blank = sloc - ploc - only_comment_lines. - pub fn blank(&self) -> u32 { - self.sloc() - .saturating_sub(self.ploc()) - .saturating_sub(self.only_comment_lines) - } - - /// Record a code line — a non-comment, non-container, non-LLOC - /// node started on this row. Mirrors the `_` arm of the pre-1.0 - /// per-language `Loc::compute` match. - pub fn observe_code_line(&mut self, start_row: u32) { - self.check_comment_ends_on_code_line(start_row); - self.ploc_lines.insert(start_row); - } - - /// Record an LLOC statement. - pub fn observe_lloc(&mut self) { - self.lloc_count = self.lloc_count.saturating_add(1); - } - - /// Record a comment node spanning rows `[start, end]` (inclusive). - /// Mirrors `add_cloc_lines` semantics. - pub fn observe_comment(&mut self, start_row: u32, end_row: u32) { - let comment_diff = end_row.saturating_sub(start_row); - let is_after_code = self.ploc_lines.contains(&start_row); - if is_after_code && comment_diff == 0 { - self.code_comment_lines = self.code_comment_lines.saturating_add(1); - } else if is_after_code && comment_diff > 0 { - self.code_comment_lines = self.code_comment_lines.saturating_add(1); - self.only_comment_lines = self.only_comment_lines.saturating_add(comment_diff); - } else if comment_diff > 0 && self.ploc_lines.contains(&end_row) { - // Multi-line comment whose *closing* row carries code (e.g. - // `/* c\n*/ val x = 1`). That last row is a code-comment, not - // comment-only; only the rows strictly before it are - // comment-only. Without this, the code-bearing closing row is - // double-counted as comment-only and masks a real blank line - // elsewhere (`blank = sloc - ploc - only_comment`). - self.code_comment_lines = self.code_comment_lines.saturating_add(1); - self.only_comment_lines = self.only_comment_lines.saturating_add(comment_diff); - } else { - self.only_comment_lines = self.only_comment_lines.saturating_add(comment_diff + 1); - self.last_comment_end = Some(end_row); - } - } - - /// Pre-1.0 `check_comment_ends_on_code_line`: when a code node - /// starts on the line right after the last comment ends, that - /// comment is reclassified from "independent" to "before code". - fn check_comment_ends_on_code_line(&mut self, start_code_row: u32) { - if let Some(end) = self.last_comment_end - && end == start_code_row - && !self.ploc_lines.contains(&start_code_row) - { - self.only_comment_lines = self.only_comment_lines.saturating_sub(1); - self.code_comment_lines = self.code_comment_lines.saturating_add(1); - } - } - - /// Snapshot the per-space totals into the `*_min` / `*_max` bounds. - /// Mirrors the pre-1.0 `compute_minmax`: the parent space only - /// snapshots its own values when no children have already - /// initialized the bounds via merge. The `space_count` always - /// bumps so averages divide by total spaces. - pub fn finalize_minmax(&mut self) { - self.space_count = self.space_count.saturating_add(1); - if self.minmax_seen { - // Children already initialized the bounds via merge — the - // parent's per-space values were already part of `self`'s - // accumulators, but the legacy convention does NOT fold - // them into min/max again at the parent close. - return; - } - let sloc = self.sloc(); - let ploc = self.ploc(); - let lloc = self.lloc(); - let cloc = self.cloc(); - let blank = self.blank(); - self.sloc_min = sloc; - self.ploc_min = ploc; - self.lloc_min = lloc; - self.cloc_min = cloc; - self.blank_min = blank; - self.sloc_max = sloc; - self.ploc_max = ploc; - self.lloc_max = lloc; - self.cloc_max = cloc; - self.blank_max = blank; - self.minmax_seen = true; - } - - /// Copy the `ploc_lines` set from another `LocStats` into this - /// one. Used by [`crate::SpaceRangeTracker::record_close`] to - /// seed a token-routed accumulator with the AST-walk's known - /// PLOC lines so comment-after-code classification works - /// correctly. Does NOT touch any other field — only the set is - /// copied. - pub fn seed_ploc_lines(&mut self, source: &LocStats) { - for line in &source.ploc_lines { - self.ploc_lines.insert(*line); - } - } - - /// Adopt the source's code rows that fall in `[start_row, end_row)` into - /// this space's PLOC set. Used when a member's own-line modifiers/ - /// annotations were observed on the enclosing class (they are visited - /// before the member's space is pushed): the member space adopts those - /// rows so its PLOC covers its full declaration. PLOC is hierarchical, so - /// the enclosing space legitimately keeps the rows too. Only rows the - /// source actually recorded as code are adopted (blank lines are skipped). - pub fn adopt_code_lines_in_range(&mut self, source: &LocStats, start_row: u32, end_row: u32) { - for line in &source.ploc_lines { - if *line >= start_row && *line < end_row { - self.ploc_lines.insert(*line); - } - } - } - - /// Absorb a sibling's *token-only* observations into this state. - /// - /// Used by [`crate::SpaceRangeTracker`] to fold post-AST token - /// events (PLOC code lines, CLOC comment lines) into a space's - /// AST-driven LocStats without mutating min/max bounds, the - /// space-count denominator, or the LLOC counter (which is - /// AST-driven and would double-count if folded here). - /// - /// Semantics: - /// - `ploc_lines` is set-unioned (a code line is counted once - /// regardless of how many tokens started on it). - /// - `only_comment_lines` and `code_comment_lines` accumulate - /// (each comment-token contribution adds to the count). - /// - `lloc_count`, `space_count`, span fields, and min/max - /// bounds are intentionally NOT touched here — those are - /// AST-driven invariants finalized before token routing. - pub fn merge_token_observations(&mut self, other: &LocStats) { - for line in &other.ploc_lines { - self.ploc_lines.insert(*line); - } - self.only_comment_lines = self - .only_comment_lines - .saturating_add(other.only_comment_lines); - self.code_comment_lines = self - .code_comment_lines - .saturating_add(other.code_comment_lines); - } - - /// Merge a finalized child's stats into this (parent) one. - /// - /// Mirrors the pre-1.0 `loc::Stats::merge`: - /// - SLOC: parent's span is unchanged; child contributes only via - /// min/max bounds (already snapshotted into `child.sloc_min/max`). - /// - PLOC: parent's `ploc_lines` set absorbs the child's lines. - /// - LLOC / CLOC: parent's per-space counters add the child's. - /// - Blank is recomputed at publish time from the merged values. - pub fn merge(&mut self, other: &LocStats) { - for line in &other.ploc_lines { - self.ploc_lines.insert(*line); - } - self.lloc_count = self.lloc_count.saturating_add(other.lloc_count); - self.only_comment_lines = self - .only_comment_lines - .saturating_add(other.only_comment_lines); - self.code_comment_lines = self - .code_comment_lines - .saturating_add(other.code_comment_lines); - self.space_count = self.space_count.saturating_add(other.space_count); - if !other.minmax_seen { - return; - } - if self.minmax_seen { - self.sloc_min = self.sloc_min.min(other.sloc_min); - self.ploc_min = self.ploc_min.min(other.ploc_min); - self.lloc_min = self.lloc_min.min(other.lloc_min); - self.cloc_min = self.cloc_min.min(other.cloc_min); - self.blank_min = self.blank_min.min(other.blank_min); - } else { - self.sloc_min = other.sloc_min; - self.ploc_min = other.ploc_min; - self.lloc_min = other.lloc_min; - self.cloc_min = other.cloc_min; - self.blank_min = other.blank_min; - self.minmax_seen = true; - } - self.sloc_max = self.sloc_max.max(other.sloc_max); - self.ploc_max = self.ploc_max.max(other.ploc_max); - self.lloc_max = self.lloc_max.max(other.lloc_max); - self.cloc_max = self.cloc_max.max(other.cloc_max); - self.blank_max = self.blank_max.max(other.blank_max); - } - - /// Comments-as-fraction-of-sloc, used by the maintainability index. - pub fn comments_percentage(&self) -> f64 { - let sloc = self.sloc(); - if sloc == 0 { - 0.0 - } else { - f64::from(self.cloc()) / f64::from(sloc) - } - } - - pub fn sloc_average(&self) -> f64 { - average(self.sloc(), self.space_count) - } - pub fn ploc_average(&self) -> f64 { - average(self.ploc(), self.space_count) - } - pub fn lloc_average(&self) -> f64 { - average(self.lloc(), self.space_count) - } - pub fn cloc_average(&self) -> f64 { - average(self.cloc(), self.space_count) - } - pub fn blank_average(&self) -> f64 { - average(self.blank(), self.space_count) - } -} - -fn average(numerator: u32, denominator: u32) -> f64 { - if denominator == 0 { - 0.0 - } else { - f64::from(numerator) / f64::from(denominator) - } -} - -impl Serialize for LocStats { - fn serialize(&self, serializer: S) -> Result { - let mut st = serializer.serialize_struct("loc", 20)?; - st.serialize_field("sloc", &self.sloc())?; - st.serialize_field("ploc", &self.ploc())?; - st.serialize_field("lloc", &self.lloc())?; - st.serialize_field("cloc", &self.cloc())?; - st.serialize_field("blank", &self.blank())?; - st.serialize_field("sloc_average", &self.sloc_average())?; - st.serialize_field("ploc_average", &self.ploc_average())?; - st.serialize_field("lloc_average", &self.lloc_average())?; - st.serialize_field("cloc_average", &self.cloc_average())?; - st.serialize_field("blank_average", &self.blank_average())?; - st.serialize_field("sloc_min", &self.sloc_min)?; - st.serialize_field("sloc_max", &self.sloc_max)?; - st.serialize_field("cloc_min", &self.cloc_min)?; - st.serialize_field("cloc_max", &self.cloc_max)?; - st.serialize_field("ploc_min", &self.ploc_min)?; - st.serialize_field("ploc_max", &self.ploc_max)?; - st.serialize_field("lloc_min", &self.lloc_min)?; - st.serialize_field("lloc_max", &self.lloc_max)?; - st.serialize_field("blank_min", &self.blank_min)?; - st.serialize_field("blank_max", &self.blank_max)?; - st.end() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn comments_percentage_when_empty() { - let s = LocStats::default(); - assert_eq!(s.comments_percentage(), 0.0); - } - - #[test] - fn merge_sums_buckets() { - let mut a = LocStats::default(); - a.set_span(0, 1, true); - a.observe_code_line(0); - a.observe_lloc(); - a.finalize_minmax(); - - let mut b = LocStats::default(); - b.set_span(2, 4, false); - b.observe_code_line(2); - b.observe_lloc(); - b.observe_comment(3, 3); - b.finalize_minmax(); - - a.merge(&b); - assert_eq!(a.lloc(), 2); - assert_eq!(a.space_count, 2); - assert_eq!(a.cloc(), 1); - } -} diff --git a/crates/mehen-metrics/src/mi.rs b/crates/mehen-metrics/src/mi.rs deleted file mode 100644 index 820c1bf2..00000000 --- a/crates/mehen-metrics/src/mi.rs +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use serde::Serialize; - -use crate::cyclomatic::CyclomaticStats; -use crate::halstead::HalsteadStats; -use crate::loc::LocStats; - -/// Maintainability index variants. All three flavors are reported because -/// downstream tooling depends on different conventions; the pre-1.0 output -/// shape (Visual Studio is the headline number) is preserved. -#[derive(Default, Clone, Debug, PartialEq, Serialize)] -pub struct MiStats { - pub mi_original: f64, - pub mi_sei: f64, - pub mi_visual_studio: f64, -} - -impl MiStats { - /// Compute the MI variants from the underlying LOC, cyclomatic, and - /// Halstead measurements. All three formulas are pure math; the - /// Visual Studio variant clamps at zero. - pub fn compute(loc: &LocStats, cyclomatic: &CyclomaticStats, halstead: &HalsteadStats) -> Self { - let halstead_volume = halstead.volume(); - let cy = cyclomatic.cyclomatic_sum as f64; - let sloc = f64::from(loc.sloc()); - let comments_percentage = loc.comments_percentage(); - - let original = if sloc > 0.0 && halstead_volume > 0.0 { - 16.2_f64.mul_add( - -sloc.ln(), - 0.23_f64.mul_add(-cy, 5.2_f64.mul_add(-halstead_volume.ln(), 171.0)), - ) - } else { - 0.0 - }; - - let sei = if sloc > 0.0 && halstead_volume > 0.0 { - 50.0_f64.mul_add( - (comments_percentage * 2.4).sqrt().sin(), - 16.2_f64.mul_add( - -sloc.log2(), - 0.23_f64.mul_add(-cy, 5.2_f64.mul_add(-halstead_volume.log2(), 171.0)), - ), - ) - } else { - 0.0 - }; - - let visual_studio = (original * 100.0 / 171.0).max(0.0); - - Self { - mi_original: original, - mi_sei: sei, - mi_visual_studio: visual_studio, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn empty_inputs_yield_zero() { - let mi = MiStats::compute( - &LocStats::default(), - &CyclomaticStats::default(), - &HalsteadStats::default(), - ); - assert_eq!(mi.mi_original, 0.0); - assert_eq!(mi.mi_visual_studio, 0.0); - } -} diff --git a/crates/mehen-metrics/src/state.rs b/crates/mehen-metrics/src/state.rs deleted file mode 100644 index cc4debaf..00000000 --- a/crates/mehen-metrics/src/state.rs +++ /dev/null @@ -1,635 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Per-space accumulator state and metric publishing helpers. -//! -//! This module owns the *generic* metric bookkeeping that every language -//! analyzer needs: -//! -//! - the [`State`] struct holding one of every accumulator, -//! - [`finalize_state`] / [`merge_child_into_parent`] for the rolled-up -//! sum/min/max/avg lifecycle, -//! - [`apply_state_to`] which materializes a finalized [`State`] into a -//! [`MetricSet`] using the keys from `mehen_metrics::keys`. -//! -//! Per the rewrite plan §4.3 these helpers belong here (in `mehen-metrics`) -//! rather than in any one language adapter — they describe the *output -//! contract* of every per-space metric set and are reused by every -//! language crate. The shared tree-sitter walker -//! ([`mehen_tree_sitter::walk`]) and the Oxc-backed `mehen-typescript` -//! analyzer both publish through this module. -//! -//! What does *not* live here: -//! - language-specific syntax interpretation (which AST kinds count as -//! decisions, operators, exits, ...). Those live in the owning -//! language crate. -//! - the parser-side walking strategy (tree-sitter cursor vs Oxc visitor). - -use mehen_core::{MetricKey, MetricSet, SpaceKind}; - -use crate::{ - AbcStats, CognitiveStats, ContainerKind, CyclomaticStats, HalsteadBuilder, HalsteadStats, - LocStats, MetricTreeBuilder, MiStats, NargsStats, NexitStats, NomStats, NpaStats, NpmStats, - SpaceRangeTracker, WmcStats, keys, -}; - -/// Per-space accumulator state. Analyzers push one of these for the -/// `Unit` root and for every space they open via their walker's -/// scope-open hook. -#[derive(Default, Clone)] -pub struct State { - pub loc: LocStats, - pub cyclomatic: CyclomaticStats, - pub cognitive: CognitiveStats, - pub halstead: HalsteadBuilder, - pub abc: AbcStats, - pub nargs: NargsStats, - pub nom: NomStats, - pub nexit: NexitStats, - pub npa: NpaStats, - pub npm: NpmStats, - pub wmc: WmcStats, -} - -impl State { - pub fn new() -> Self { - Self::default() - } - - /// Initialize a fresh `State` for an opened space, applying the - /// kind-specific bookkeeping every walker performs: - /// - /// - `Function` records a function in `nom`. - /// - `Closure` records a closure in `nom`. - /// - `Class` / `Impl` record a class-like in `npa`/`npm`/`wmc`. - /// - `Interface` / `Trait` record a class-like in `npa`/`npm` only. - /// - Other kinds (`Unit`, `Enum`, `Custom`) do nothing. - /// - /// Callers still set their own LOC span — each walker has its own - /// `LineIndex` access pattern (Ruff `TextRange`, Oxc `Span`, - /// tree-sitter byte offsets) so we keep span resolution at the - /// call site. - pub fn for_opened_space(kind: SpaceKind) -> Self { - let mut child = Self::new(); - match kind { - SpaceKind::Function => child.nom.record_function(), - SpaceKind::Closure => child.nom.record_closure(), - SpaceKind::Class | SpaceKind::Impl => { - child.npa.record_class_like(); - child.npm.record_class_like(); - child.wmc.record_class_like(); - } - SpaceKind::Interface | SpaceKind::Trait => { - child.npa.record_class_like(); - child.npm.record_class_like(); - } - _ => {} - } - child - } -} - -/// Close a space: pop its `State` and `SpaceKind` from the walker's -/// stacks, finalize, stash the AST-side LOC + cyclomatic snapshots -/// for the post-AST Halstead overlay, publish the per-space `MetricSet`, -/// merge the rolled-up bounds into the parent, and close the -/// `MetricTreeBuilder`. -/// -/// This is byte-identical across the Python, TypeScript, Ruby, Rust, -/// PHP, Go, C, and Kotlin walkers — they all carry the same four state -/// buckets (`stack`, `kinds`, `tree`, `halstead_routing`) and run the -/// same finalize → record_close → apply → merge → close sequence. -/// CPD flagged a 30-line / 130-token cluster across them; pulling the -/// shared logic here means a fix or feature lands once instead of -/// eight times. -/// -/// Panics on stack underflow (unbalanced open/close — the same way the -/// per-walker copies did). -pub fn close_space( - stack: &mut Vec, - kinds: &mut Vec, - tree: &mut MetricTreeBuilder, - halstead_routing: &mut SpaceRangeTracker, -) { - let closed_kind = kinds.pop().expect("kinds underflow"); - let mut state = stack.pop().expect("stack underflow"); - if matches!(closed_kind, SpaceKind::Function) { - state.wmc.set_cyclomatic(state.cyclomatic.cyclomatic + 1); - } - finalize_state(&mut state); - if let Some(space_id) = tree.current_id() { - halstead_routing.record_close(space_id, &state.loc, &state.cyclomatic); - } - apply_state_to(state.clone(), tree.metrics_mut()); - if let Some(parent) = stack.last_mut() { - let parent_kind = kinds.last().cloned().unwrap_or(SpaceKind::Unit); - merge_child_into_parent(parent, &state); - if matches!(closed_kind, SpaceKind::Function) { - let container = match parent_kind { - SpaceKind::Class | SpaceKind::Impl => ContainerKind::Class, - SpaceKind::Interface | SpaceKind::Trait => ContainerKind::Interface, - _ => ContainerKind::Other, - }; - state.wmc.finalize_method_into(container, &mut parent.wmc); - } - } - tree.close(); -} - -/// Snapshot the per-space "current" values into rolled-up -/// sum/min/max/avg fields. Called on every space close before the -/// per-space MetricSet is published or merged into the parent. -pub fn finalize_state(state: &mut State) { - state.cyclomatic.finalize_minmax(); - state.cyclomatic.finalize_average(); - state.loc.finalize_minmax(); - state.nom.finalize_minmax(); - state.nargs.finalize_minmax(); - state.nexit.finalize_minmax(); - state.nexit.finalize_average(state.nom.total()); - state - .nargs - .finalize_average(state.nom.functions_sum, state.nom.closures_sum); - state.abc.finalize_minmax(); - state.npa.finalize_minmax(); - state.npm.finalize_minmax(); - state.cognitive.finalize_minmax(); - state.cognitive.finalize(state.nom.total()); -} - -/// Fold a finalized child state's rolled-up totals (sum/min/max/n) -/// into the parent state. The parent's per-space "current" values are -/// not affected — children contribute only via the bounds. -pub fn merge_child_into_parent(parent: &mut State, child: &State) { - parent.cyclomatic.merge(&child.cyclomatic); - parent.cyclomatic.finalize_average(); - parent.loc.merge(&child.loc); - parent.nom.merge(&child.nom); - parent.nargs.merge(&child.nargs); - parent.nexit.merge(&child.nexit); - parent.nexit.finalize_average(parent.nom.total()); - parent - .nargs - .finalize_average(parent.nom.functions_sum, parent.nom.closures_sum); - parent.abc.merge(&child.abc); - parent.halstead.merge(&child.halstead); - parent.npa.merge(&child.npa); - parent.npm.merge(&child.npm); - parent.wmc.merge(&child.wmc); - parent.cognitive.merge(&child.cognitive); - parent.cognitive.finalize(parent.nom.total()); -} - -/// Publish a finalized `State` into a `MetricSet` using the shared key -/// names. Per the rewrite plan §5.1 each metric publishes the rolled-up -/// `{ sum, min, max, average }` set under aggregator-suffixed selectors -/// (`cyclomatic.sum`, `cyclomatic.min`, …) plus the bare per-space -/// value at the metric's root key. -pub fn apply_state_to(state: State, target: &mut MetricSet) { - publish_cyclomatic(&state.cyclomatic, target); - publish_loc(&state.loc, target); - publish_nom(&state.nom, target); - publish_nargs(&state.nargs, &state.nom, target); - publish_nexit(&state.nexit, target); - publish_cognitive(&state.cognitive, target); - - let halstead = HalsteadStats::from_counts(state.halstead.counts()); - publish_halstead(&halstead, target); - - let mi = MiStats::compute(&state.loc, &state.cyclomatic, &halstead); - target.insert(MetricKey::new(keys::MI_VS), mi.mi_visual_studio); - target.insert(MetricKey::new(keys::MI_ORIGINAL), mi.mi_original); - target.insert(MetricKey::new(keys::MI_SEI), mi.mi_sei); - - publish_abc(&state.abc, target); - publish_npa(&state.npa, target); - publish_npm(&state.npm, target); - publish_wmc(&state.wmc, target); -} - -fn publish_npa(stats: &NpaStats, target: &mut MetricSet) { - if stats.is_disabled() { - return; - } - target.insert(MetricKey::new(keys::NPA), stats.total_npa() as i64); - target.insert( - MetricKey::new(format!("{}.classes", keys::NPA)), - stats.class_npa_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.interfaces", keys::NPA)), - stats.interface_npa_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.class_attributes", keys::NPA)), - stats.class_na_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.interface_attributes", keys::NPA)), - stats.interface_na_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.classes_average", keys::NPA)), - stats.class_cda(), - ); - target.insert( - MetricKey::new(format!("{}.interfaces_average", keys::NPA)), - stats.interface_cda(), - ); - target.insert( - MetricKey::new(format!("{}.total_attributes", keys::NPA)), - stats.total_na() as i64, - ); - target.insert( - MetricKey::new(format!("{}.average", keys::NPA)), - stats.total_cda(), - ); -} - -fn publish_npm(stats: &NpmStats, target: &mut MetricSet) { - if stats.is_disabled() { - return; - } - target.insert(MetricKey::new(keys::NPM), stats.total_npm() as i64); - target.insert( - MetricKey::new(format!("{}.classes", keys::NPM)), - stats.class_npm_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.interfaces", keys::NPM)), - stats.interface_npm_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.class_methods", keys::NPM)), - stats.class_nm_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.interface_methods", keys::NPM)), - stats.interface_nm_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.classes_average", keys::NPM)), - stats.class_avg(), - ); - target.insert( - MetricKey::new(format!("{}.interfaces_average", keys::NPM)), - stats.interface_avg(), - ); - target.insert( - MetricKey::new(format!("{}.total_methods", keys::NPM)), - stats.total_nm() as i64, - ); - target.insert( - MetricKey::new(format!("{}.average", keys::NPM)), - stats.total_avg(), - ); -} - -fn publish_wmc(stats: &WmcStats, target: &mut MetricSet) { - if stats.is_disabled() { - return; - } - target.insert(MetricKey::new(keys::WMC), stats.total() as i64); - target.insert( - MetricKey::new(format!("{}.classes", keys::WMC)), - stats.class_wmc_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.interfaces", keys::WMC)), - stats.interface_wmc_sum as i64, - ); -} - -fn publish_cognitive(stats: &CognitiveStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::COGNITIVE), stats.cognitive_sum as i64); - target.insert( - MetricKey::new(format!("{}.sum", keys::COGNITIVE)), - stats.cognitive_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.average", keys::COGNITIVE)), - stats.cognitive_average, - ); - target.insert( - MetricKey::new(format!("{}.min", keys::COGNITIVE)), - stats.min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::COGNITIVE)), - stats.max as i64, - ); -} - -/// Publish the full Halstead key set (`halstead.volume`, -/// `halstead.difficulty`, `halstead.effort`, `halstead.{n1,N1,n2,N2}`, -/// `halstead.{length,vocabulary,level,time,bugs,…}`) onto a -/// `MetricSet`. -/// -/// Visibility is `pub(crate)` because the post-AST token-routing -/// overlay in `crate::halstead_routing` needs to rewrite the same -/// keys when Pattern B walkers (Python, TypeScript, Rust, PHP) emit -/// Halstead in a separate pass after `apply_state_to` has already -/// run. Both call sites must publish identical keys with identical -/// formulas; otherwise the per-space JSON Halstead numbers drift -/// from the unit-level rollup. Funneling them through the same -/// helper makes that drift impossible. -pub(crate) fn publish_halstead(stats: &HalsteadStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::HALSTEAD_VOLUME), stats.volume()); - target.insert( - MetricKey::new(keys::HALSTEAD_DIFFICULTY), - stats.difficulty(), - ); - target.insert(MetricKey::new(keys::HALSTEAD_EFFORT), stats.effort()); - target.insert( - MetricKey::new(keys::HALSTEAD_VOCABULARY), - stats.vocabulary(), - ); - target.insert(MetricKey::new(keys::HALSTEAD_LENGTH), stats.length()); - target.insert( - MetricKey::new(format!("{}.n1", keys::HALSTEAD)), - stats.u_operators as i64, - ); - target.insert( - MetricKey::new(format!("{}.N1", keys::HALSTEAD)), - stats.operators as i64, - ); - target.insert( - MetricKey::new(format!("{}.n2", keys::HALSTEAD)), - stats.u_operands as i64, - ); - target.insert( - MetricKey::new(format!("{}.N2", keys::HALSTEAD)), - stats.operands as i64, - ); - target.insert( - MetricKey::new(format!("{}.length", keys::HALSTEAD)), - stats.length(), - ); - target.insert( - MetricKey::new(format!("{}.estimated_program_length", keys::HALSTEAD)), - stats.estimated_program_length(), - ); - target.insert( - MetricKey::new(format!("{}.purity_ratio", keys::HALSTEAD)), - stats.purity_ratio(), - ); - target.insert( - MetricKey::new(format!("{}.vocabulary", keys::HALSTEAD)), - stats.vocabulary(), - ); - target.insert( - MetricKey::new(format!("{}.level", keys::HALSTEAD)), - stats.level(), - ); - target.insert( - MetricKey::new(format!("{}.time", keys::HALSTEAD)), - stats.time(), - ); - target.insert( - MetricKey::new(format!("{}.bugs", keys::HALSTEAD)), - stats.bugs(), - ); -} - -fn publish_abc(stats: &AbcStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::ABC), stats.magnitude()); - target.insert( - MetricKey::new(keys::ABC_ASSIGNMENTS), - stats.assignments_sum as i64, - ); - target.insert( - MetricKey::new(keys::ABC_BRANCHES), - stats.branches_sum as i64, - ); - target.insert( - MetricKey::new(keys::ABC_CONDITIONS), - stats.conditions_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.assignments_average", keys::ABC)), - stats.assignments_average(), - ); - target.insert( - MetricKey::new(format!("{}.branches_average", keys::ABC)), - stats.branches_average(), - ); - target.insert( - MetricKey::new(format!("{}.conditions_average", keys::ABC)), - stats.conditions_average(), - ); - target.insert( - MetricKey::new(format!("{}.assignments_min", keys::ABC)), - stats.assignments_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.assignments_max", keys::ABC)), - stats.assignments_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.branches_min", keys::ABC)), - stats.branches_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.branches_max", keys::ABC)), - stats.branches_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.conditions_min", keys::ABC)), - stats.conditions_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.conditions_max", keys::ABC)), - stats.conditions_max as i64, - ); -} - -fn publish_nargs(stats: &NargsStats, nom: &NomStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::NARGS), stats.total() as i64); - target.insert( - MetricKey::new(format!("{}.total_functions", keys::NARGS)), - stats.fn_nargs_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.total_closures", keys::NARGS)), - stats.closure_nargs_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.average_functions", keys::NARGS)), - stats.fn_nargs_average, - ); - target.insert( - MetricKey::new(format!("{}.average_closures", keys::NARGS)), - stats.closure_nargs_average, - ); - target.insert( - MetricKey::new(format!("{}.average", keys::NARGS)), - stats.nargs_average(nom.functions_sum, nom.closures_sum), - ); - target.insert( - MetricKey::new(format!("{}.functions_min", keys::NARGS)), - stats.fn_nargs_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.functions_max", keys::NARGS)), - stats.fn_nargs_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.closures_min", keys::NARGS)), - stats.closure_nargs_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.closures_max", keys::NARGS)), - stats.closure_nargs_max as i64, - ); -} - -fn publish_nom(stats: &NomStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::NOM), stats.total() as i64); - target.insert( - MetricKey::new(keys::NOM_FUNCTIONS), - stats.functions_sum as i64, - ); - target.insert( - MetricKey::new(keys::NOM_CLOSURES), - stats.closures_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.functions_average", keys::NOM)), - stats.functions_average(), - ); - target.insert( - MetricKey::new(format!("{}.closures_average", keys::NOM)), - stats.closures_average(), - ); - target.insert( - MetricKey::new(format!("{}.average", keys::NOM)), - stats.average(), - ); - target.insert( - MetricKey::new(format!("{}.functions_min", keys::NOM)), - stats.functions_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.functions_max", keys::NOM)), - stats.functions_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.closures_min", keys::NOM)), - stats.closures_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.closures_max", keys::NOM)), - stats.closures_max as i64, - ); -} - -fn publish_nexit(stats: &NexitStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::NEXIT), stats.exits as i64); - target.insert( - MetricKey::new(format!("{}.sum", keys::NEXIT)), - stats.sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.average", keys::NEXIT)), - stats.average, - ); - target.insert( - MetricKey::new(format!("{}.min", keys::NEXIT)), - stats.min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::NEXIT)), - stats.max as i64, - ); -} - -fn publish_cyclomatic(stats: &CyclomaticStats, target: &mut MetricSet) { - let mccabe = stats.cyclomatic.saturating_add(1) as i64; - target.insert(MetricKey::new(keys::CYCLOMATIC), mccabe); - target.insert( - MetricKey::new(format!("{}.sum", keys::CYCLOMATIC)), - stats.cyclomatic_sum as i64, - ); - target.insert( - MetricKey::new(format!("{}.min", keys::CYCLOMATIC)), - stats.min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::CYCLOMATIC)), - stats.max as i64, - ); - target.insert( - MetricKey::new(format!("{}.avg", keys::CYCLOMATIC)), - stats.cyclomatic_average, - ); -} - -fn publish_loc(stats: &LocStats, target: &mut MetricSet) { - target.insert(MetricKey::new(keys::LOC_LLOC), stats.lloc() as i64); - target.insert(MetricKey::new(keys::LOC_SLOC), stats.sloc() as i64); - target.insert(MetricKey::new(keys::LOC_PLOC), stats.ploc() as i64); - target.insert(MetricKey::new(keys::LOC_CLOC), stats.cloc() as i64); - target.insert(MetricKey::new(keys::LOC_BLANK), stats.blank() as i64); - target.insert(MetricKey::new(keys::LOC), stats.sloc() as i64); - - target.insert( - MetricKey::new(format!("{}.min", keys::LOC_SLOC)), - stats.sloc_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::LOC_SLOC)), - stats.sloc_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.avg", keys::LOC_SLOC)), - stats.sloc_average(), - ); - target.insert( - MetricKey::new(format!("{}.min", keys::LOC_PLOC)), - stats.ploc_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::LOC_PLOC)), - stats.ploc_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.avg", keys::LOC_PLOC)), - stats.ploc_average(), - ); - target.insert( - MetricKey::new(format!("{}.min", keys::LOC_LLOC)), - stats.lloc_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::LOC_LLOC)), - stats.lloc_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.avg", keys::LOC_LLOC)), - stats.lloc_average(), - ); - target.insert( - MetricKey::new(format!("{}.min", keys::LOC_CLOC)), - stats.cloc_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::LOC_CLOC)), - stats.cloc_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.avg", keys::LOC_CLOC)), - stats.cloc_average(), - ); - target.insert( - MetricKey::new(format!("{}.min", keys::LOC_BLANK)), - stats.blank_min as i64, - ); - target.insert( - MetricKey::new(format!("{}.max", keys::LOC_BLANK)), - stats.blank_max as i64, - ); - target.insert( - MetricKey::new(format!("{}.avg", keys::LOC_BLANK)), - stats.blank_average(), - ); -} diff --git a/crates/mehen-metrics/src/tree_builder.rs b/crates/mehen-metrics/src/tree_builder.rs deleted file mode 100644 index aa5a8ae1..00000000 --- a/crates/mehen-metrics/src/tree_builder.rs +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use mehen_core::{MetricSet, MetricSpace, SourceSpan, SpaceId, SpaceKind}; - -/// Helper that assembles a `MetricSpace` tree with stable, monotonically -/// increasing `SpaceId`s. -/// -/// Per the rewrite plan §4.3, this is the kind of plumbing that belongs in -/// `mehen-metrics` so language analyzer crates do not each re-implement -/// id-allocation and parent-child wiring. The crate ships the builder; the -/// language crate decides what spaces to emit. -pub struct MetricTreeBuilder { - next_id: u32, - stack: Vec, -} - -impl MetricTreeBuilder { - /// Begin a new tree with a `Unit` space at the root. - pub fn new(unit_span: SourceSpan) -> Self { - let mut stack = Vec::with_capacity(8); - stack.push(MetricSpace::new(SpaceId(0), SpaceKind::Unit, unit_span)); - Self { next_id: 1, stack } - } - - /// Open a child space, becoming the new innermost space. - pub fn open(&mut self, kind: SpaceKind, span: SourceSpan, name: Option) -> SpaceId { - let id = SpaceId(self.next_id); - self.next_id += 1; - let mut space = MetricSpace::new(id, kind, span); - space.name = name; - self.stack.push(space); - id - } - - /// Close the innermost space and attach it to its parent. - /// - /// Panics if there is no innermost space — calls must balance with - /// `open`. The Phase 1 implementation is intentionally strict about - /// this so a regression in the analyzer's tree-walk is loud. - pub fn close(&mut self) { - let child = self - .stack - .pop() - .expect("MetricTreeBuilder: no space to close"); - let parent = self - .stack - .last_mut() - .expect("MetricTreeBuilder: cannot close the root unit"); - parent.spaces.push(child); - } - - /// Mutable access to the innermost space's metric set. - pub fn metrics_mut(&mut self) -> &mut MetricSet { - &mut self - .stack - .last_mut() - .expect("MetricTreeBuilder: stack is empty") - .metrics - } - - /// `SpaceId` of the innermost open space, or `None` when only the - /// unit scope is on the stack. Walkers reach for this in their - /// `close_space` hook to associate the about-to-close state with - /// the space they're publishing into (e.g. for the - /// [`crate::SpaceRangeTracker`] post-AST Halstead overlay). - pub fn current_id(&self) -> Option { - // The unit space is at index 0 — anything above it is a real - // child scope. - if self.stack.len() <= 1 { - None - } else { - self.stack.last().map(|s| s.id) - } - } - - /// Drop the unit-level outer scope and yield the assembled tree. - /// - /// Panics if the open/close calls are unbalanced. Failing fast surfaces - /// analyzer-walker bugs (a missing `close()` after a scope-opening node) - /// instead of silently emitting a tree with collapsed spaces. - pub fn finish(mut self) -> MetricSpace { - assert_eq!( - self.stack.len(), - 1, - "MetricTreeBuilder: unbalanced open/close calls (stack depth = {})", - self.stack.len() - ); - self.stack - .pop() - .expect("MetricTreeBuilder: empty after open") - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn empty_span() -> SourceSpan { - SourceSpan::empty() - } - - #[test] - fn assigns_monotonic_ids() { - let mut b = MetricTreeBuilder::new(empty_span()); - let f1 = b.open(SpaceKind::Function, empty_span(), Some("f".into())); - b.close(); - let f2 = b.open(SpaceKind::Function, empty_span(), Some("g".into())); - b.close(); - let root = b.finish(); - assert_eq!(root.id, SpaceId(0)); - assert_eq!(root.spaces.len(), 2); - assert_eq!(f1, SpaceId(1)); - assert_eq!(f2, SpaceId(2)); - } - - #[test] - fn nested_scopes_attach_correctly() { - let mut b = MetricTreeBuilder::new(empty_span()); - b.open(SpaceKind::Class, empty_span(), Some("C".into())); - b.open(SpaceKind::Function, empty_span(), Some("m".into())); - b.close(); - b.close(); - let root = b.finish(); - assert_eq!(root.spaces.len(), 1); - assert_eq!(root.spaces[0].kind, SpaceKind::Class); - assert_eq!(root.spaces[0].spaces.len(), 1); - assert_eq!(root.spaces[0].spaces[0].kind, SpaceKind::Function); - } -} diff --git a/crates/mehen-php/Cargo.toml b/crates/mehen-php/Cargo.toml deleted file mode 100644 index aa0c7c9f..00000000 --- a/crates/mehen-php/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "mehen-php" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — PHP language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -# The `mago-*` crates are pinned here (not in -# `[workspace.dependencies]`) because `mehen-php` is the only consumer. -# All five mago crates ship in lockstep — bump them together. PHP -# keyword case-insensitivity, promoted properties, hooked properties, -# match, attributes, etc. are first-class in mago's typed AST. -# `mago-allocator` provides `LocalArena`, the bump arena mago's parser -# writes into (mago 1.42 replaced the external `bumpalo` dependency -# with its own allocator). -mago-syntax = "=1.46.0" -mago-syntax-core = "=1.46.0" -mago-database = "=1.47.2" -mago-span = "=1.47.2" -mago-allocator = "=1.47.2" -smol_str = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-php/src/lib.rs b/crates/mehen-php/src/lib.rs deleted file mode 100644 index b0a7ff3f..00000000 --- a/crates/mehen-php/src/lib.rs +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-php` — PHP language analyzer. -//! -//! Phase 8 implementation: walks `mago_syntax`'s typed PHP AST to -//! produce `LanguageAnalysis`. Replaces the tree-sitter-php pipeline -//! per the rewrite plan §6.4. -//! -//! Mago provides a `Walker` trait whose generated `walk_in_` -//! / `walk_out_` callbacks let us drive the per-space `State` -//! accumulator without hand-rolling recursion. See -//! `docs/php-mago-syntax-spec.md` for design rationale and every -//! documented divergence from the legacy tree-sitter behavior. -//! -//! Mago migrations from `mago-collector`'s walk pattern: we don't -//! need its `Collector` (that's a lint-issue / pragma collector for -//! Mago's analysis pipeline). The reusable piece is the `Walker` -//! trait in `mago_syntax::walker`, which we implement directly. - -#![forbid(unsafe_code)] - -mod walker; - -use mago_allocator::LocalArena; -use mago_database::file::FileId; - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, ParseDiagnostic, - Result, SourceFile, -}; -use mehen_metrics::MetricEvidence; - -pub struct PhpAnalyzer; - -impl PhpAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for PhpAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for PhpAnalyzer { - fn language(&self) -> Language { - Language::Php - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::Mago - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - // mago-syntax allocates everything into a bump arena. The - // arena lives only for this `analyze` call; everything we - // put into `LanguageAnalysis` must be owned (no borrow - // back into the arena), which the per-space `State` - // accumulator pattern already guarantees. As of mago 1.42 - // the parser writes into mago's own `LocalArena` rather than - // the external `bumpalo::Bump`. - let arena = LocalArena::new(); - let file_id = FileId::zero(); - let program = - mago_syntax::parser::parse_file_content(&arena, file_id, source.text.as_bytes()); - - // Recovered Mago syntax errors are surfaced as `error` (not - // `warning`) so the diagnostic contract (plan §9.3) treats the - // analysis as incomplete: `mehen metrics` exits 1 and - // `analyze_diff` records the file under `analysis_errors`. - let diagnostics: Vec = program - .errors - .iter() - .map(|err| ParseDiagnostic::error("php.parse_error", format!("mago-syntax: {err}"))) - .collect(); - - let mut evidence = MetricEvidence::new("php", config.emit_contributions); - let root = walker::walk_program(program, &source.text, &source.line_index, &mut evidence); - - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::Php, - backend: AnalysisBackend::Mago, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} diff --git a/crates/mehen-php/src/walker.rs b/crates/mehen-php/src/walker.rs deleted file mode 100644 index 7a9cb904..00000000 --- a/crates/mehen-php/src/walker.rs +++ /dev/null @@ -1,1654 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! mago-syntax-based walker that produces a populated `MetricSpace`. -//! -//! Mirrors the per-space `State` accumulator pattern used by -//! `mehen-rust` (`crates/mehen-rust/src/walker.rs`), -//! `mehen-python` (`crates/mehen-python/src/walker.rs`) and -//! `mehen-typescript` (`crates/mehen-typescript/src/walker.rs`): -//! -//! - one `State` for the unit, plus one for every opened -//! function / closure / arrow function / class / interface / -//! trait / enum / anonymous-class space, -//! - finalize on close, fold child stats into parent, -//! - drive the walk through Mago's `Walker` trait so node -//! enter/leave callbacks are typed (`walk_in_class`, -//! `walk_in_method`, `walk_in_if`, `walk_in_match`, …). -//! -//! Mago's Walker is the same one used by `mago-collector` for -//! pragma-scope attachment in Mago's own lint pipeline; here we -//! reuse it to drive metric accumulation. We do NOT depend on -//! `mago-collector` itself — it's an issue/diagnostic collector -//! whose feature set (suppression pragmas, issue codes, etc.) is -//! orthogonal to metric computation. -//! -//! PHP-specific design decisions are documented in -//! `docs/php-mago-syntax-spec.md`. Highlights: -//! -//! - **`elseif` and `else if`**: both contribute a flat `+1` -//! cognitive (no extra nesting). Mago surfaces these as distinct -//! AST nodes (`IfStatementBodyElseIfClause`, -//! `IfStatementBodyElseClause`), so the flattening logic the -//! legacy walker did via `is_else_if` lookahead now becomes a -//! trivial AST-level callback. -//! - **`match` arms**: every arm is a cyclomatic decision; the -//! `match` expression itself opens a cognitive nesting frame. -//! The `default` arm contributes one ABC condition per Fitzpatrick -//! ABC, mirroring how `else_clause` is treated. -//! - **Promoted constructor properties**: `__construct(public int $id)` -//! really does declare a class property. We attribute them to the -//! enclosing class space's NPA counters (Mago surfaces this -//! directly via `FunctionLikeParameter::is_promoted_property()`). -//! - **PHP keyword case-insensitivity**: visibility modifiers -//! (`public` / `protected` / `private`) are typed via Mago's -//! `Modifier` enum, so the case-insensitive scan the legacy walker -//! did over the source text is now a typed enum match — case -//! handling falls out automatically. -//! - **`exit` / `die`**: counted as function exits (`nexit`), -//! matching legacy. Mago models them as `Construct::Exit` / -//! `Construct::Die`, which the legacy `ExitStatement` enum -//! variant did not distinguish. - -use mago_database::file::FileId; -use mago_span::{HasSpan, Span}; -use mago_syntax::cst::{ - AnonymousClass, ArrowFunction, Assignment, Binary, BinaryOperator, Call, Class, Closure, - Conditional, Construct, DoWhile, Enum, EnumCase, ExpressionStatement, For, Foreach, Function, - If, IfBody, Instantiation, Interface, Match, Method, MethodBody, Modifier, NullSafeMethodCall, - Program, Property, Return, Switch, Throw, Trait, Try, UnaryPrefix, UnaryPrefixOperator, While, - Yield, -}; -use mago_syntax::lexer::Lexer; -use mago_syntax::settings::LexerSettings; -use mago_syntax::token::TokenKind; -use mago_syntax::walker::Walker; -use mago_syntax_core::input::Input; - -use mehen_core::{LineIndex, MetricSpace, SourceSpan, SpaceKind}; -use mehen_metrics::{ - ContainerKind, HalsteadOperand, HalsteadOperator, MetricEvidence, MetricTreeBuilder, - SpaceRangeTracker, State, apply_state_to, finalize_state, merge_child_into_parent, -}; -use smol_str::SmolStr; - -/// Crate-internal entry point — drive the walker over a parsed -/// `Program`. Contribution evidence is recorded into the caller-owned -/// `evidence` sink (plan §5.4). -pub(crate) fn walk_program<'arena>( - program: &Program<'arena>, - source: &str, - line_index: &LineIndex, - evidence: &mut MetricEvidence, -) -> MetricSpace { - let unit_span = SourceSpan { - start_byte: 0, - end_byte: clamp_offset(source.len()), - start_line: 1, - end_line: line_index.line_count(), - }; - - let mut visitor = Visitor::new(source, line_index, unit_span, evidence); - - let walker = MehenPhpWalker; - walker.walk_program(program, &mut visitor); - - // Comments / docblocks live in `program.trivia`; record them - // *after* the AST walk so the `SpaceRangeTracker` has populated - // every opened space's byte range and each comment routes to its - // enclosing scope's `loc.cloc` (PR #95 discussion_r3265962147 — - // routing comments before the walk left every per-space `cloc` - // at zero). - visitor.observe_trivia(&program.trivia); - - visitor.finish() -} - -#[derive(Clone, Copy, Debug, Default)] -struct CognitiveContext { - /// Structural nesting depth (incremented by `if`, `for`, `while`, - /// `do`, `switch`, `match`, `try`, `catch`, `conditional`). - nesting: u32, - /// Function-call depth — incremented when we enter a nested - /// function/method (not a top-level one). Mirrors legacy - /// `count_specific_ancestors(FunctionDefinition | MethodDeclaration)`. - depth: u32, - /// Lambda depth — incremented inside an `AnonymousFunction` or - /// `ArrowFunction`. - lambda: u32, -} - -struct Visitor<'a> { - source: &'a str, - line_index: &'a LineIndex, - tree: MetricTreeBuilder, - /// Per-space accumulator stack — index 0 is the unit. - stack: Vec, - /// Parallel to `stack`: the SpaceKind of each open frame. - kinds: Vec, - /// Cognitive context for the currently-walked subtree. Saved on - /// nesting-bumping / function-entry events and restored on leave. - cognitive: CognitiveContext, - /// Stack of cognitive-context savepoints, parallel to `stack`, - /// so an Enter/Leave pair can roll back the nesting it added. - saved_cognitive: Vec, - /// Whether the *next* `walk_in_if` should be treated as the - /// inner `if` of an `else if` (set when leaving an else clause - /// whose statement is an `If` – mago does NOT have a dedicated - /// `ElseIf` node for the spaced form). - suppress_next_if_nesting: bool, - /// Routes Halstead tokens emitted by the post-AST sweep to the - /// deepest enclosing function/class/closure space so per-space - /// JSON entries are non-zero. PR #95 discussion_r3265658502 - /// flagged the same gap on the Python walker; the PHP walker had - /// the same `stack[0]`-only behaviour. - halstead_routing: SpaceRangeTracker, - /// Contribution-evidence sink (plan §5.4). Recording happens next - /// to each stat increment, through [`Visitor::record_evidence`]. - evidence: &'a mut MetricEvidence, -} - -impl<'a> Visitor<'a> { - fn new( - source: &'a str, - line_index: &'a LineIndex, - unit_span: SourceSpan, - evidence: &'a mut MetricEvidence, - ) -> Self { - let mut state = State::new(); - state.loc.set_span( - unit_span.start_line.saturating_sub(1), - unit_span.end_line.saturating_sub(1), - true, - ); - Self { - source, - line_index, - tree: MetricTreeBuilder::new(unit_span), - stack: vec![state], - kinds: vec![SpaceKind::Unit], - cognitive: CognitiveContext::default(), - saved_cognitive: Vec::new(), - suppress_next_if_nesting: false, - halstead_routing: SpaceRangeTracker::new(), - evidence, - } - } - - fn current(&mut self) -> &mut State { - self.stack.last_mut().expect("walker stack empty") - } - - /// Record contribution evidence for the construct at `span`. The - /// span conversion only runs when the sink is enabled, so walker - /// callbacks can call this unconditionally next to each stat - /// increment (mirrors `mehen_tree_sitter::WalkerCtx::record_evidence`). - #[inline] - fn record_evidence(&mut self, span: Span, record: F) - where - F: FnOnce(&mut MetricEvidence, SourceSpan), - { - if self.evidence.is_enabled() { - let source_span = self.span_to_source(span); - record(self.evidence, source_span); - } - } - - fn observe_trivia( - &mut self, - trivia: &mago_syntax::cst::Sequence<'_, mago_syntax::cst::Trivia<'_>>, - ) { - // Route each comment to the deepest enclosing scope so a - // `// foo` inside a method body lands on that method's - // `loc.cloc` rather than the unit's. Lines outside every - // recorded scope (file-level docblocks, license headers) - // fall through to the unit's LocStats. - for comment in trivia.iter() { - if !comment.kind.is_comment() { - continue; - } - let span = comment.span; - let start_row = self.line_at(span.start.offset).saturating_sub(1); - let end_row = self.line_at(span.end.offset).saturating_sub(1); - self.halstead_routing.observe_comment( - span.start.offset, - span.end.offset, - &mut self.stack[0].loc, - start_row, - end_row, - ); - } - } - - fn line_at(&self, offset: u32) -> u32 { - self.line_index.line_at(offset) - } - - fn span_to_source(&self, span: Span) -> SourceSpan { - SourceSpan { - start_byte: span.start.offset, - end_byte: span.end.offset, - start_line: self.line_at(span.start.offset), - end_line: self.line_at(span.end.offset), - } - } - - fn finish(mut self) -> MetricSpace { - // Final ploc/lloc accounting from a single source-text scan - // (mirrors the rust analyzer's token sweep — done once at - // the unit level so we don't re-walk the whole arena to - // derive LOC). - self.scan_source_loc(); - self.emit_halstead_from_tokens(); - - let mut unit_state = self.stack.pop().expect("walker stack underflow"); - finalize_state(&mut unit_state); - // Route post-AST tokens (Halstead operator/operand, PLOC code - // lines, comment lines) to nested spaces; see - // [`SpaceRangeTracker`]. - let mut unit_halstead = std::mem::take(&mut unit_state.halstead); - let mut unit_loc = std::mem::take(&mut unit_state.loc); - let mut tree = self.tree.finish(); - self.halstead_routing - .finalize_into_tree(&mut tree, &mut unit_halstead, &mut unit_loc); - unit_state.halstead = unit_halstead; - unit_state.loc = unit_loc; - apply_state_to(unit_state, &mut tree.metrics); - tree - } - - /// Re-lex the source via Mago's `Lexer` and emit Halstead - /// operator/operand events. Each event is routed to the deepest - /// enclosing scope via [`SpaceRangeTracker`] so per-space JSON - /// entries are non-zero; tokens that fall outside every recorded - /// scope go into the unit `HalsteadBuilder`. - fn emit_halstead_from_tokens(&mut self) { - let input = Input::new(FileId::zero(), self.source.as_bytes()); - let mut lexer = Lexer::new(input, LexerSettings::default()); - while let Some(result) = lexer.advance() { - let token = match result { - Ok(tok) => tok, - // Treat lex errors as recoverable — skip the byte - // and continue. The parse-error diagnostic was - // already attached upstream via parser errors. - Err(_) => continue, - }; - // Mago tokens carry only `start: Position` and the literal - // `value: &[u8]` (raw source bytes); the end offset is - // start + value length, which is what `Position` - // arithmetic does on every other code path in mago-syntax. - let s = token.start.offset; - let e = s + token.value.len() as u32; - match classify_token(token.kind) { - TokenClass::Operator(kind) => { - self.halstead_routing.observe_operator( - s, - e, - &mut self.stack[0].halstead, - HalsteadOperator { - kind: SmolStr::new(kind), - text: None, - }, - ); - } - TokenClass::Operand(kind) => { - let text = String::from_utf8_lossy(token.value); - self.halstead_routing.observe_operand( - s, - e, - &mut self.stack[0].halstead, - HalsteadOperand { - kind: SmolStr::new(kind), - text: Some(SmolStr::new(text.as_ref())), - }, - ); - } - TokenClass::Skip => {} - } - } - } - - fn scan_source_loc(&mut self) { - // Per-line PLOC accounting: any line whose first non-whitespace - // token is a code token contributes a code line. Comments are - // already handled in `observe_trivia`; here we just need PLOC - // / blank tracking. Halstead / LLOC are recorded at AST nodes. - // Each line is routed by its byte range so a code line inside - // a function body lands on that function's `loc.ploc` instead - // of the unit's. - let total_len = self.source.len() as u32; - let mut byte_offset: u32 = 0; - for (idx, line) in self.source.lines().enumerate() { - let line_start = byte_offset; - // `lines()` strips the line terminator; advance the cursor - // by the line's byte length plus the consumed `\n` (or - // `\r\n`). This keeps `byte_offset` valid for the next - // iteration regardless of which terminator the source - // uses. - byte_offset = byte_offset.saturating_add(line.len() as u32); - let line_end = byte_offset.min(total_len); - // Step past `\n` (and an optional preceding `\r`) so the - // next iteration's `line_start` is correct. - if (byte_offset as usize) < self.source.len() { - let after_line = self.source.as_bytes().get(byte_offset as usize).copied(); - if after_line == Some(b'\r') { - byte_offset = byte_offset.saturating_add(1); - if self.source.as_bytes().get(byte_offset as usize).copied() == Some(b'\n') { - byte_offset = byte_offset.saturating_add(1); - } - } else if after_line == Some(b'\n') { - byte_offset = byte_offset.saturating_add(1); - } - } - let trimmed = line.trim(); - if trimmed.is_empty() { - continue; - } - // Skip lines that are only PHP open/close tags or only a - // comment — those don't count as code lines. - if trimmed == "" { - continue; - } - if trimmed.starts_with("//") - || trimmed.starts_with('#') - || trimmed.starts_with("/*") - || trimmed.starts_with('*') - { - continue; - } - self.halstead_routing.observe_code_line( - line_start, - line_end, - &mut self.stack[0].loc, - idx as u32, - ); - } - } - - fn open_space(&mut self, kind: SpaceKind, span: Span, name: Option) { - let mut child = State::new(); - let start_row = self.line_at(span.start.offset).saturating_sub(1); - let end_row = self.line_at(span.end.offset).saturating_sub(1); - child.loc.set_span(start_row, end_row, false); - - match kind { - SpaceKind::Function => { - child.nom.record_function(); - } - SpaceKind::Closure => { - child.nom.record_closure(); - } - SpaceKind::Class => { - child.npa.record_class_like(); - child.npm.record_class_like(); - child.wmc.record_class_like(); - } - SpaceKind::Interface | SpaceKind::Trait | SpaceKind::Enum => { - child.npa.record_class_like(); - child.npm.record_class_like(); - } - _ => {} - } - let source_span = self.span_to_source(span); - let space_id = self.tree.open(kind.clone(), source_span, name); - // Record byte range for the post-AST Halstead routing pass. - self.halstead_routing - .record_open(space_id, span.start.offset, span.end.offset); - self.stack.push(child); - self.kinds.push(kind); - } - - fn close_space(&mut self) { - let closed_kind = self.kinds.pop().expect("kinds underflow"); - let mut state = self.stack.pop().expect("stack underflow"); - if matches!(closed_kind, SpaceKind::Function) { - state.wmc.set_cyclomatic(state.cyclomatic.cyclomatic + 1); - } - finalize_state(&mut state); - // Stash MI inputs (LOC + cyclomatic) for the post-AST Halstead - // overlay before they get consumed by `apply_state_to`. - if let Some(space_id) = self.tree.current_id() { - self.halstead_routing - .record_close(space_id, &state.loc, &state.cyclomatic); - } - apply_state_to(state.clone(), self.tree.metrics_mut()); - if let Some(parent) = self.stack.last_mut() { - let parent_kind = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - merge_child_into_parent(parent, &state); - if matches!(closed_kind, SpaceKind::Function) { - let container = match parent_kind { - SpaceKind::Class => ContainerKind::Class, - SpaceKind::Interface | SpaceKind::Trait => ContainerKind::Interface, - _ => ContainerKind::Other, - }; - state.wmc.finalize_method_into(container, &mut parent.wmc); - } - } - self.tree.close(); - } - - fn save_cognitive(&mut self) { - self.saved_cognitive.push(self.cognitive); - } - - fn restore_cognitive(&mut self) { - if let Some(saved) = self.saved_cognitive.pop() { - self.cognitive = saved; - } - } - - /// Cognitive: function entry. Reset nesting/lambda; bump depth - /// when nested inside another function/method. - fn enter_function_like(&mut self, kind: SpaceKind) { - self.save_cognitive(); - let nested = self - .kinds - .iter() - .skip(1) - .any(|k| matches!(k, SpaceKind::Function)); - let mut ctx = self.cognitive; - ctx.nesting = 0; - if matches!(kind, SpaceKind::Closure) { - ctx.lambda = ctx.lambda.saturating_add(1); - } else { - ctx.lambda = 0; - } - if nested { - ctx.depth = ctx.depth.saturating_add(1); - } - self.cognitive = ctx; - } - - fn record_method(&mut self, method: &Method<'_>) { - // NPM bookkeeping happens on the *enclosing* class-like state, - // not the method's own state. Mirrors the Rust phase. - let enclosing = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - let container = match enclosing { - SpaceKind::Class => ContainerKind::Class, - SpaceKind::Interface | SpaceKind::Trait => ContainerKind::Interface, - _ => return, - }; - let public = match enclosing { - // PHP interface methods are implicitly public (the interface - // contract; visibility modifiers may not appear). - SpaceKind::Interface => true, - _ => php_modifiers_are_public(&method.modifiers), - }; - self.current().npm.record_method(container, public); - // Only public members are evidenced — the headline NPM metric - // counts public methods only. - if public { - self.record_evidence(method.span(), |e, s| e.public_method(s, "method")); - } - } - - fn record_property(&mut self, property: &Property<'_>) { - let enclosing = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - let container = match enclosing { - SpaceKind::Class | SpaceKind::Trait | SpaceKind::Enum => ContainerKind::Class, - SpaceKind::Interface => ContainerKind::Interface, - _ => return, - }; - // Each property declaration may declare multiple property - // items: `public $a, $b;` declares two attributes — record - // one entry per item. - let (modifiers, items) = match property { - Property::Plain(p) => (&p.modifiers, &p.items), - Property::Hooked(_h) => { - // Hooked properties always declare a single property. - // Treat the modifier list as the visibility source. - return; - } - }; - let public = php_modifiers_are_public(modifiers); - for item in items.iter() { - self.current().npa.record_attribute(container, public); - // Only public members are evidenced — the headline NPA - // metric counts public attributes only. - if public { - self.record_evidence(item.span(), |e, s| e.public_attribute(s, "property")); - } - } - } -} - -fn clamp_offset(len: usize) -> u32 { - u32::try_from(len).unwrap_or(u32::MAX) -} - -#[derive(Clone, Copy)] -enum TokenClass { - Operator(&'static str), - Operand(&'static str), - Skip, -} - -/// Classify a Mago `TokenKind` for Halstead. Each operator token -/// gets its own distinct `kind` string so `n1` reflects the true -/// number of unique operators. Closing punctuation pairs with its -/// opener (classical Halstead convention) and is skipped, matching -/// the `mehen-rust` walker. -/// -/// PHP-specific note: the legacy tree-sitter walker treated PHP -/// keywords as Halstead operators (it's a long list, including -/// modifiers and `array`/`list`/`callable`). We preserve that -/// behavior — the keyword IS the construct's operator. -fn classify_token(kind: TokenKind) -> TokenClass { - use TokenClass::*; - use TokenKind as T; - match kind { - // ---------- SKIPPED (whitespace, trivia, string interior) ---------- - T::Whitespace - | T::SingleLineComment - | T::HashComment - | T::MultiLineComment - | T::DocBlockComment - | T::InlineText - | T::InlineShebang - | T::OpenTag - | T::EchoTag - | T::ShortOpenTag - | T::CloseTag - // String interior — already counted via `LiteralString`. - | T::StringPart - | T::DoubleQuote - | T::Backtick - | T::DocumentStart(_) - | T::DocumentEnd - | T::PartialLiteralString => Skip, - // Closing punctuation: pairs with the opener; skip to avoid - // double-counting. - T::RightParenthesis | T::RightBrace | T::RightBracket => Skip, - - // ---------- PUNCTUATION (operators, distinct kinds) ---------- - T::LeftParenthesis => Operator("("), - T::LeftBrace => Operator("{"), - T::LeftBracket => Operator("["), - T::Comma => Operator(","), - T::Semicolon => Operator(";"), - T::Colon => Operator(":"), - T::ColonColon => Operator("::"), - T::Dot => Operator("."), - T::DotDotDot => Operator("..."), - T::MinusGreaterThan => Operator("->"), - T::QuestionMinusGreaterThan => Operator("?->"), - T::EqualGreaterThan => Operator("=>"), - T::HashLeftBracket => Operator("#["), - T::At => Operator("@"), - T::NamespaceSeparator => Operator("\\"), - T::DollarLeftBrace => Operator("${"), - T::Dollar => Operator("$"), - - // ---------- ASSIGNMENT FAMILY ---------- - T::Equal => Operator("="), - T::PlusEqual => Operator("+="), - T::MinusEqual => Operator("-="), - T::AsteriskEqual => Operator("*="), - T::AsteriskAsteriskEqual => Operator("**="), - T::SlashEqual => Operator("/="), - T::PercentEqual => Operator("%="), - T::DotEqual => Operator(".="), - T::LeftShiftEqual => Operator("<<="), - T::RightShiftEqual => Operator(">>="), - T::AmpersandEqual => Operator("&="), - T::CaretEqual => Operator("^="), - T::PipeEqual => Operator("|="), - T::QuestionQuestionEqual => Operator("??="), - T::AmpersandAmpersandEqual => Operator("&&="), - - // ---------- ARITHMETIC / BITWISE / UNARY / NULL-COALESCE ---------- - T::Plus => Operator("+"), - T::Minus => Operator("-"), - T::Asterisk => Operator("*"), - T::AsteriskAsterisk => Operator("**"), - T::Slash => Operator("/"), - T::Percent => Operator("%"), - T::PlusPlus => Operator("++"), - T::MinusMinus => Operator("--"), - T::Tilde => Operator("~"), - T::Bang => Operator("!"), - T::AmpersandAmpersand => Operator("&&"), - T::PipePipe => Operator("||"), - T::QuestionQuestion => Operator("??"), - T::Question => Operator("?"), - T::Ampersand => Operator("&"), - T::Pipe => Operator("|"), - T::Caret => Operator("^"), - T::LeftShift => Operator("<<"), - T::RightShift => Operator(">>"), - - // ---------- COMPARISON ---------- - T::EqualEqual => Operator("=="), - T::EqualEqualEqual => Operator("==="), - T::BangEqual => Operator("!="), - T::BangEqualEqual => Operator("!=="), - T::LessThanGreaterThan => Operator("<>"), - T::LessThan => Operator("<"), - T::GreaterThan => Operator(">"), - T::LessThanEqual => Operator("<="), - T::GreaterThanEqual => Operator(">="), - T::LessThanEqualGreaterThan => Operator("<=>"), - // Pipe operator (PHP 8.5). - T::PipeGreaterThan => Operator("|>"), - - // ---------- TYPE CASTS (each cast is its own operator) ---------- - T::ArrayCast => Operator("(array)"), - T::BoolCast => Operator("(bool)"), - T::BooleanCast => Operator("(boolean)"), - T::DoubleCast => Operator("(double)"), - T::RealCast => Operator("(real)"), - T::FloatCast => Operator("(float)"), - T::IntCast => Operator("(int)"), - T::IntegerCast => Operator("(integer)"), - T::ObjectCast => Operator("(object)"), - T::UnsetCast => Operator("(unset)"), - T::StringCast => Operator("(string)"), - T::BinaryCast => Operator("(binary)"), - T::VoidCast => Operator("(void)"), - - // ---------- KEYWORDS (each keyword is its own operator) ---------- - T::Function => Operator("function"), - T::Fn => Operator("fn"), - T::Class => Operator("class"), - T::Interface => Operator("interface"), - T::Trait => Operator("trait"), - T::Enum => Operator("enum"), - T::Namespace => Operator("namespace"), - T::Use => Operator("use"), - T::As => Operator("as"), - T::Insteadof => Operator("insteadof"), - T::Const => Operator("const"), - T::Static => Operator("static"), - T::Var => Operator("var"), - T::Public => Operator("public"), - T::PublicSet => Operator("public(set)"), - T::Protected => Operator("protected"), - T::ProtectedSet => Operator("protected(set)"), - T::Private => Operator("private"), - T::PrivateSet => Operator("private(set)"), - T::Final => Operator("final"), - T::Abstract => Operator("abstract"), - T::Readonly => Operator("readonly"), - T::Extends => Operator("extends"), - T::Implements => Operator("implements"), - T::New => Operator("new"), - T::Clone => Operator("clone"), - T::Instanceof => Operator("instanceof"), - T::If => Operator("if"), - T::Else => Operator("else"), - T::ElseIf => Operator("elseif"), - T::EndIf => Operator("endif"), - T::Switch => Operator("switch"), - T::Case => Operator("case"), - T::Default => Operator("default"), - T::EndSwitch => Operator("endswitch"), - T::Match => Operator("match"), - T::While => Operator("while"), - T::EndWhile => Operator("endwhile"), - T::Do => Operator("do"), - T::For => Operator("for"), - T::EndFor => Operator("endfor"), - T::Foreach => Operator("foreach"), - T::EndForeach => Operator("endforeach"), - T::Continue => Operator("continue"), - T::Break => Operator("break"), - T::Return => Operator("return"), - T::Throw => Operator("throw"), - T::Try => Operator("try"), - T::Catch => Operator("catch"), - T::Finally => Operator("finally"), - T::Goto => Operator("goto"), - T::Yield => Operator("yield"), - T::From => Operator("from"), - T::Echo => Operator("echo"), - T::Print => Operator("print"), - T::Exit => Operator("exit"), - T::Die => Operator("die"), - T::Unset => Operator("unset"), - T::Isset => Operator("isset"), - T::Empty => Operator("empty"), - T::Eval => Operator("eval"), - T::List => Operator("list"), - T::Array => Operator("array"), - T::Include => Operator("include"), - T::IncludeOnce => Operator("include_once"), - T::Require => Operator("require"), - T::RequireOnce => Operator("require_once"), - T::And => Operator("and"), - T::Or => Operator("or"), - T::Xor => Operator("xor"), - T::Declare => Operator("declare"), - T::EndDeclare => Operator("enddeclare"), - T::Global => Operator("global"), - T::HaltCompiler => Operator("__halt_compiler"), - - // ---------- IDENTIFIERS / NAMES (operands) ---------- - T::Identifier - | T::QualifiedIdentifier - | T::FullyQualifiedIdentifier => Operand("Identifier"), - T::Variable => Operand("Variable"), - T::Self_ => Operand("self"), - T::Parent => Operand("parent"), - // `callable` is a type hint used as a name in argument lists. - T::Callable => Operand("Identifier"), - - // ---------- LITERALS (operands) ---------- - T::LiteralInteger => Operand("Integer"), - T::LiteralFloat => Operand("Float"), - T::LiteralString => Operand("String"), - T::True => Operand("True"), - T::False => Operand("False"), - T::Null => Operand("Null"), - - // ---------- STRING SUBSCRIPT / INTERPOLATION OFFSETS (operands) ---------- - // `$a[5]` numeric offset, `$a[bar]` bareword offset, and the - // `foo` name in `${foo}` interpolation. Mago 1.42 split these - // out of the generic identifier/literal tokens; each names a - // value, so they classify as operands alongside literals. - T::OffsetNumber => Operand("Integer"), - T::OffsetString => Operand("String"), - T::StringVariableName => Operand("Variable"), - - // ---------- MAGIC CONSTANTS (operands) ---------- - T::ClassConstant - | T::TraitConstant - | T::FunctionConstant - | T::MethodConstant - | T::LineConstant - | T::FileConstant - | T::DirConstant - | T::NamespaceConstant - | T::PropertyConstant => Operand("MagicConstant"), - } -} - -/// PHP visibility default is *public* when no modifier appears. -/// PHP keywords are case-insensitive — but Mago has already -/// normalized the modifier into a typed `Modifier` enum, so the -/// scan is a clean enum match (no string comparison needed). -fn php_modifiers_are_public( - modifiers: &mago_syntax::cst::sequence::Sequence<'_, Modifier<'_>>, -) -> bool { - !modifiers.iter().any(|m| { - matches!( - m, - Modifier::Private(_) - | Modifier::Protected(_) - | Modifier::PrivateSet(_) - | Modifier::ProtectedSet(_) - ) - }) -} - -/// Mago 1.28 switched identifier and token `value` fields from -/// `&str` to `&[u8]` (PHP source bytes are not guaranteed UTF-8 in -/// the literal-string lexer state). Identifiers themselves must be -/// PHP-valid (ASCII letters / digits / `_` / `\\`), so a lossy -/// conversion is exact in practice; for arbitrary token bytes we -/// accept the U+FFFD replacement on the rare invalid sequence -/// rather than failing the analysis. -fn bytes_to_string(value: &[u8]) -> String { - String::from_utf8_lossy(value).into_owned() -} - -/// PHP method names are case-insensitive — `__construct`, `__CONSTRUCT`, -/// and `__Construct` are all the constructor. -fn is_constructor(name: &str) -> bool { - name.eq_ignore_ascii_case("__construct") -} - -/// Stable reason-detail string for a comparison operator (ABC.C -/// evidence). Matches the PHP source token spelling, same convention -/// as the tree-sitter walkers' operator-token kinds. -fn comparison_op_str(op: &BinaryOperator<'_>) -> &'static str { - match op { - BinaryOperator::Equal(_) => "==", - BinaryOperator::NotEqual(_) => "!=", - BinaryOperator::Identical(_) => "===", - BinaryOperator::NotIdentical(_) => "!==", - BinaryOperator::AngledNotEqual(_) => "<>", - BinaryOperator::LessThan(_) => "<", - BinaryOperator::LessThanOrEqual(_) => "<=", - BinaryOperator::GreaterThan(_) => ">", - BinaryOperator::GreaterThanOrEqual(_) => ">=", - BinaryOperator::Spaceship(_) => "<=>", - // Callers only pass the comparison variants above. - _ => "comparison", - } -} - -// ===================================================================== -// Walker implementation -// ===================================================================== - -/// Marker type — Mago's `Walker` trait is `&self`, so the visitor's -/// state lives in the `Context` (`Visitor`). -struct MehenPhpWalker; - -impl<'arena> Walker<'_, 'arena, Visitor<'_>> for MehenPhpWalker { - // ----------------------------------------------------------------- - // Function-like spaces - // ----------------------------------------------------------------- - - fn walk_in_function(&self, function: &Function<'arena>, ctx: &mut Visitor<'_>) { - // Function declarations are themselves an LLOC line (legacy - // `FunctionDefinition` rule). Record on the enclosing space - // before we open the function's own state frame. - ctx.current().loc.observe_lloc(); - - ctx.enter_function_like(SpaceKind::Function); - let name = bytes_to_string(function.name.value); - ctx.open_space(SpaceKind::Function, function.span(), Some(name)); - - let argc = function.parameter_list.parameters.iter().count() as u32; - ctx.current().nargs.record_function_args(argc); - ctx.record_evidence(function.span(), |e, s| { - e.function(s, "function"); - e.function_args(s, argc, "function"); - }); - } - - fn walk_out_function(&self, _function: &Function<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - ctx.restore_cognitive(); - } - - fn walk_in_method(&self, method: &Method<'arena>, ctx: &mut Visitor<'_>) { - // Method declarations contribute one LLOC line on the - // enclosing class-like space (legacy `MethodDeclaration` rule). - ctx.current().loc.observe_lloc(); - - ctx.record_method(method); - - let name = bytes_to_string(method.name.value); - let constructor = is_constructor(&name); - - // Attribute promoted constructor properties NOW (before we - // open the method's child space) so they're recorded on the - // enclosing class state, not the method's own state — that - // mirrors the legacy rule that promoted properties belong to - // the *class* npa, not the method. - if constructor { - for param in method.parameter_list.parameters.iter() { - if param.is_promoted_property() { - let public = php_modifiers_are_public(¶m.modifiers); - let container = ContainerKind::Class; - ctx.current().npa.record_attribute(container, public); - // Only public members are evidenced (headline NPA - // counts public attributes only). - if public { - ctx.record_evidence(param.span(), |e, s| { - e.public_attribute(s, "promoted_property"); - }); - } - } - } - } - - // Abstract methods (`abstract public function f();`) are not a - // function space — no body to analyze. They still count for - // NPM (already recorded above), but skip the State frame. - if matches!(method.body, MethodBody::Abstract(_)) { - return; - } - - ctx.enter_function_like(SpaceKind::Function); - ctx.open_space(SpaceKind::Function, method.span(), Some(name)); - - // Method NArgs counts only "real" parameters: a promoted - // property counts both as an attribute (above) AND as a - // parameter (it really IS a parameter at the call site). - let argc = method.parameter_list.parameters.iter().count() as u32; - ctx.current().nargs.record_function_args(argc); - ctx.record_evidence(method.span(), |e, s| { - e.function(s, "method"); - e.function_args(s, argc, "method"); - }); - } - - fn walk_out_method(&self, method: &Method<'arena>, ctx: &mut Visitor<'_>) { - if matches!(method.body, MethodBody::Abstract(_)) { - return; - } - ctx.close_space(); - ctx.restore_cognitive(); - } - - fn walk_in_closure(&self, closure: &Closure<'arena>, ctx: &mut Visitor<'_>) { - ctx.enter_function_like(SpaceKind::Closure); - ctx.open_space(SpaceKind::Closure, closure.span(), None); - - let argc = closure.parameter_list.parameters.iter().count() as u32; - ctx.current().nargs.record_closure_args(argc); - ctx.record_evidence(closure.span(), |e, s| { - e.closure(s, "closure"); - e.closure_args(s, argc, "closure"); - }); - } - - fn walk_out_closure(&self, _closure: &Closure<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - ctx.restore_cognitive(); - } - - fn walk_in_arrow_function(&self, arrow: &ArrowFunction<'arena>, ctx: &mut Visitor<'_>) { - ctx.enter_function_like(SpaceKind::Closure); - ctx.open_space(SpaceKind::Closure, arrow.span(), None); - - let argc = arrow.parameter_list.parameters.iter().count() as u32; - ctx.current().nargs.record_closure_args(argc); - ctx.record_evidence(arrow.span(), |e, s| { - e.closure(s, "arrow_function"); - e.closure_args(s, argc, "arrow_function"); - }); - } - - fn walk_out_arrow_function(&self, _arrow: &ArrowFunction<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - ctx.restore_cognitive(); - } - - // ----------------------------------------------------------------- - // Class-like spaces - // ----------------------------------------------------------------- - - fn walk_in_class(&self, class: &Class<'arena>, ctx: &mut Visitor<'_>) { - // Class declaration is itself an LLOC line on its enclosing - // space (legacy `ClassDeclaration`). - ctx.current().loc.observe_lloc(); - let name = bytes_to_string(class.name.value); - ctx.open_space(SpaceKind::Class, class.span(), Some(name)); - } - fn walk_out_class(&self, _class: &Class<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - } - - fn walk_in_interface(&self, interface: &Interface<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - let name = bytes_to_string(interface.name.value); - ctx.open_space(SpaceKind::Interface, interface.span(), Some(name)); - } - fn walk_out_interface(&self, _i: &Interface<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - } - - fn walk_in_trait(&self, t: &Trait<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - let name = bytes_to_string(t.name.value); - ctx.open_space(SpaceKind::Trait, t.span(), Some(name)); - } - fn walk_out_trait(&self, _t: &Trait<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - } - - fn walk_in_enum(&self, e: &Enum<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - let name = bytes_to_string(e.name.value); - ctx.open_space(SpaceKind::Enum, e.span(), Some(name)); - } - fn walk_out_enum(&self, _e: &Enum<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - } - - fn walk_in_anonymous_class(&self, ac: &AnonymousClass<'arena>, ctx: &mut Visitor<'_>) { - // Anonymous classes are an *expression*, not a top-level - // declaration — they don't contribute their own LLOC line - // (the surrounding ExpressionStatement already does). - ctx.open_space(SpaceKind::Class, ac.span(), None); - } - fn walk_out_anonymous_class(&self, _ac: &AnonymousClass<'arena>, ctx: &mut Visitor<'_>) { - ctx.close_space(); - } - - // ----------------------------------------------------------------- - // Class-like members (NPA / NPM) - // ----------------------------------------------------------------- - - fn walk_in_property(&self, p: &Property<'arena>, ctx: &mut Visitor<'_>) { - // Each property declaration is an LLOC line (legacy - // `PropertyDeclaration`). - ctx.current().loc.observe_lloc(); - ctx.record_property(p); - } - - fn walk_in_enum_case(&self, ec: &EnumCase<'arena>, ctx: &mut Visitor<'_>) { - // PHP enum cases are typed constants on the enum, not - // instance attributes (they have no per-instance state). - // Record them as class-like attributes so NPA reflects the - // enum's "surface area" the same way it does for class - // constants — but mark them public (cases are always public - // in PHP). - let enclosing = ctx.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - if !matches!(enclosing, SpaceKind::Enum) { - return; - } - ctx.current() - .npa - .record_attribute(ContainerKind::Class, true); - ctx.record_evidence(ec.span(), |e, s| e.public_attribute(s, "enum_case")); - } - - // ----------------------------------------------------------------- - // Decision points (cyclomatic + cognitive + ABC) - // ----------------------------------------------------------------- - - fn walk_in_if(&self, if_node: &If<'arena>, ctx: &mut Visitor<'_>) { - // `if` is a statement-shaped LLOC line. Inner `else if` / `else` - // clauses do NOT bump LLOC again (they're part of the same - // logical statement). - ctx.current().loc.observe_lloc(); - // The `else if (with a space)` form parses as a nested `If` - // whose immediate parent is an `else_clause`. Mago does not - // emit a dedicated `ElseIf` AST node for that form — when the - // walk descends from an `else_clause` into another `If`, we - // suppress the structural nesting that this inner `If` would - // otherwise add (its `+1` was already paid by the outer - // `else_clause` callback). The actual flat `+1` for `else if` - // happens via `walk_in_if_statement_body_else_clause`. - let bumped_nesting = if ctx.suppress_next_if_nesting { - ctx.suppress_next_if_nesting = false; - // Cyclomatic decision still counts (each `if` is a path). - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - ctx.record_evidence(if_node.span(), |e, s| { - e.decision(s, "if"); - e.abc_condition(s, "if"); - }); - false - } else { - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.record_evidence(if_node.span(), |e, s| { - e.decision(s, "if"); - e.abc_condition(s, "if"); - e.cognitive(s, effective.saturating_add(1), "if"); - }); - true - }; - - // Mirror the legacy "if has a else clause" `+1` rule. Mago - // surfaces the else clause as a nested AST node, so we only - // need to detect its presence here. - let else_span = match &if_node.body { - IfBody::Statement(b) => b.else_clause.as_ref().map(|c| c.span()), - IfBody::ColonDelimited(b) => b.else_clause.as_ref().map(|c| c.span()), - }; - if let Some(else_span) = else_span { - ctx.current().cognitive.increment_by_one(); - ctx.record_evidence(else_span, |e, s| e.cognitive(s, 1, "else")); - } - - ctx.current().cognitive.boolean_seq.reset(); - ctx.save_cognitive(); - if bumped_nesting { - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - } - - fn walk_out_if(&self, _if_node: &If<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_if_statement_body_else_if_clause( - &self, - clause: &mago_syntax::cst::IfStatementBodyElseIfClause<'arena>, - ctx: &mut Visitor<'_>, - ) { - // `elseif` keyword form: flat +1 cognitive, no extra nesting. - // It's still a cyclomatic decision because each `elseif` - // creates a distinct path through the function. - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - ctx.current().cognitive.increment_by_one(); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(clause.span(), |e, s| { - e.decision(s, "elseif"); - e.abc_condition(s, "elseif"); - e.cognitive(s, 1, "elseif"); - }); - } - - fn walk_in_if_colon_delimited_body_else_if_clause( - &self, - clause: &mago_syntax::cst::IfColonDelimitedBodyElseIfClause<'arena>, - ctx: &mut Visitor<'_>, - ) { - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - ctx.current().cognitive.increment_by_one(); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(clause.span(), |e, s| { - e.decision(s, "elseif"); - e.abc_condition(s, "elseif"); - e.cognitive(s, 1, "elseif"); - }); - } - - fn walk_in_if_statement_body_else_clause( - &self, - clause: &mago_syntax::cst::IfStatementBodyElseClause<'arena>, - ctx: &mut Visitor<'_>, - ) { - // ABC.C: `else` counts as a condition per Fitzpatrick's - // original spec (same convention applied to `default`). - ctx.current().abc.record_condition(); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(clause.span(), |e, s| e.abc_condition(s, "else")); - // The `else if` (spaced) form is a single `If` statement - // whose direct parent is this else_clause. When that's the - // case, defer to the inner `If` callback to record the - // decision; the structural nesting it would add is suppressed - // via `suppress_next_if_nesting`. Also: the inner `If` will - // record its own ABC.C from `walk_in_if`, so we'd - // double-count. To avoid that: we already recorded one - // above, but the inner `if` records itself once more and - // that's fine — legacy did the same, an `else if` chain - // contributes both an `else` condition and an `elseif` - // condition. - if matches!(&clause.statement, mago_syntax::cst::Statement::If(_)) { - ctx.suppress_next_if_nesting = true; - } - } - - fn walk_in_if_colon_delimited_body_else_clause( - &self, - clause: &mago_syntax::cst::IfColonDelimitedBodyElseClause<'arena>, - ctx: &mut Visitor<'_>, - ) { - ctx.current().abc.record_condition(); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(clause.span(), |e, s| e.abc_condition(s, "else")); - } - - fn walk_in_while(&self, w: &While<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(w.span(), |e, s| { - e.decision(s, "while"); - e.abc_condition(s, "while"); - e.cognitive(s, effective.saturating_add(1), "while"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_while(&self, _w: &While<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_for(&self, f: &For<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(f.span(), |e, s| { - e.decision(s, "for"); - e.abc_condition(s, "for"); - e.cognitive(s, effective.saturating_add(1), "for"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_for(&self, _f: &For<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_foreach(&self, f: &Foreach<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(f.span(), |e, s| { - e.decision(s, "foreach"); - e.abc_condition(s, "foreach"); - e.cognitive(s, effective.saturating_add(1), "foreach"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_foreach(&self, _f: &Foreach<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_do_while(&self, d: &DoWhile<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(d.span(), |e, s| { - e.decision(s, "do_while"); - e.abc_condition(s, "do_while"); - e.cognitive(s, effective.saturating_add(1), "do_while"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_do_while(&self, _d: &DoWhile<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_switch(&self, sw: &Switch<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - // The `switch` itself does not contribute a decision; each - // `case` does. Cognitive: opens a nesting frame so nested - // control flow inside cases gets the depth penalty. - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(sw.span(), |e, s| { - e.abc_condition(s, "switch"); - e.cognitive(s, effective.saturating_add(1), "switch"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_switch(&self, _s: &Switch<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_switch_expression_case( - &self, - c: &mago_syntax::cst::SwitchExpressionCase<'arena>, - ctx: &mut Visitor<'_>, - ) { - // Each `case :` is its own LLOC line and a cyclomatic - // decision (Sonar's PHP rule, also Fitzpatrick's ABC). - ctx.current().loc.observe_lloc(); - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - ctx.record_evidence(c.span(), |e, s| { - e.decision(s, "switch_case"); - e.abc_condition(s, "switch_case"); - }); - } - - fn walk_in_switch_default_case( - &self, - c: &mago_syntax::cst::SwitchDefaultCase<'arena>, - ctx: &mut Visitor<'_>, - ) { - // `default` is its own LLOC line. It's *not* a cyclomatic - // decision (no new path), but it IS an ABC condition per - // Fitzpatrick — same convention we use for `else_clause`. - ctx.current().loc.observe_lloc(); - ctx.current().abc.record_condition(); - ctx.record_evidence(c.span(), |e, s| e.abc_condition(s, "switch_default_case")); - } - - fn walk_in_match(&self, m: &Match<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.current().cognitive.boolean_seq.reset(); - ctx.record_evidence(m.span(), |e, s| { - e.abc_condition(s, "match"); - e.cognitive(s, effective.saturating_add(1), "match"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_match(&self, _m: &Match<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_match_expression_arm( - &self, - a: &mago_syntax::cst::MatchExpressionArm<'arena>, - ctx: &mut Visitor<'_>, - ) { - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - ctx.record_evidence(a.span(), |e, s| { - e.decision(s, "match_arm"); - e.abc_condition(s, "match_arm"); - }); - } - - fn walk_in_match_default_arm( - &self, - a: &mago_syntax::cst::MatchDefaultArm<'arena>, - ctx: &mut Visitor<'_>, - ) { - ctx.current().abc.record_condition(); - ctx.record_evidence(a.span(), |e, s| e.abc_condition(s, "match_default_arm")); - } - - fn walk_in_try(&self, t: &Try<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.record_evidence(t.span(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "try"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_try(&self, _t: &Try<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - fn walk_in_try_catch_clause( - &self, - c: &mago_syntax::cst::TryCatchClause<'arena>, - ctx: &mut Visitor<'_>, - ) { - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.record_evidence(c.span(), |e, s| { - e.decision(s, "catch"); - e.abc_condition(s, "catch"); - e.cognitive(s, effective.saturating_add(1), "catch"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_try_catch_clause( - &self, - _c: &mago_syntax::cst::TryCatchClause<'arena>, - ctx: &mut Visitor<'_>, - ) { - ctx.restore_cognitive(); - } - - fn walk_in_conditional(&self, c: &Conditional<'arena>, ctx: &mut Visitor<'_>) { - // PHP ternary `cond ? then : else` is a cyclomatic decision. - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let effective = ctx.cognitive.nesting + ctx.cognitive.depth + ctx.cognitive.lambda; - ctx.current().cognitive.increase_nesting(effective); - ctx.record_evidence(c.span(), |e, s| { - e.decision(s, "conditional"); - e.abc_condition(s, "conditional"); - e.cognitive(s, effective.saturating_add(1), "conditional"); - }); - ctx.save_cognitive(); - ctx.cognitive.nesting = ctx.cognitive.nesting.saturating_add(1); - } - fn walk_out_conditional(&self, _c: &Conditional<'arena>, ctx: &mut Visitor<'_>) { - ctx.restore_cognitive(); - } - - // ----------------------------------------------------------------- - // Operators (cyclomatic + cognitive boolean sequences + ABC) - // ----------------------------------------------------------------- - - fn walk_in_binary(&self, b: &Binary<'arena>, ctx: &mut Visitor<'_>) { - /// Shared shape for the four short-circuiting boolean - /// operators: decision + ABC.C + boolean-run collapse. The - /// cognitive evidence amount is the delta the collapser - /// actually applied (0 for a same-operator repeat, which the - /// sink skips). Evidence spans point at the operator token, - /// same as the tree-sitter walkers. - fn boolean_op(ctx: &mut Visitor<'_>, span: Span, op: &'static str) { - ctx.current().cyclomatic.record_decision(); - ctx.current().abc.record_condition(); - let before = ctx.current().cognitive.structural; - ctx.current().cognitive.observe_boolean(op); - let delta = ctx.current().cognitive.structural.saturating_sub(before); - ctx.record_evidence(span, |e, s| { - e.decision(s, op); - e.abc_condition(s, op); - e.cognitive(s, delta, op); - }); - } - - match &b.operator { - BinaryOperator::And(_) => boolean_op(ctx, b.operator.span(), "&&"), - BinaryOperator::Or(_) => boolean_op(ctx, b.operator.span(), "||"), - BinaryOperator::LowAnd(_) => boolean_op(ctx, b.operator.span(), "and"), - BinaryOperator::LowOr(_) => boolean_op(ctx, b.operator.span(), "or"), - // `xor` is intentionally excluded: it does not short-circuit, - // so it adds no execution path. - BinaryOperator::LowXor(_) => {} - // ABC.C: every comparison is a condition. - BinaryOperator::Equal(_) - | BinaryOperator::NotEqual(_) - | BinaryOperator::Identical(_) - | BinaryOperator::NotIdentical(_) - | BinaryOperator::AngledNotEqual(_) - | BinaryOperator::LessThan(_) - | BinaryOperator::LessThanOrEqual(_) - | BinaryOperator::GreaterThan(_) - | BinaryOperator::GreaterThanOrEqual(_) - | BinaryOperator::Spaceship(_) => { - ctx.current().abc.record_condition(); - let op = comparison_op_str(&b.operator); - ctx.record_evidence(b.operator.span(), |e, s| e.abc_condition(s, op)); - } - _ => {} - } - } - - fn walk_in_unary_prefix(&self, u: &UnaryPrefix<'arena>, ctx: &mut Visitor<'_>) { - match u.operator { - UnaryPrefixOperator::Not(_) => { - // Boolean-sequence bookkeeping only — no metric moves - // here, so nothing is evidenced. - ctx.current().cognitive.boolean_seq.not_operator("!"); - } - // ABC.A: prefix `++` and `--` are assignments. - UnaryPrefixOperator::PreIncrement(_) => { - ctx.current().abc.record_assignment(); - ctx.record_evidence(u.span(), |e, s| e.abc_assignment(s, "pre_increment")); - } - UnaryPrefixOperator::PreDecrement(_) => { - ctx.current().abc.record_assignment(); - ctx.record_evidence(u.span(), |e, s| e.abc_assignment(s, "pre_decrement")); - } - _ => {} - } - } - - // ----------------------------------------------------------------- - // ABC.A: assignments and update (++/--) - // ----------------------------------------------------------------- - - fn walk_in_assignment(&self, a: &Assignment<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().abc.record_assignment(); - ctx.record_evidence(a.span(), |e, s| e.abc_assignment(s, "assignment")); - } - - fn walk_in_unary_postfix( - &self, - u: &mago_syntax::cst::UnaryPostfix<'arena>, - ctx: &mut Visitor<'_>, - ) { - use mago_syntax::cst::UnaryPostfixOperator; - match u.operator { - UnaryPostfixOperator::PostIncrement(_) => { - ctx.current().abc.record_assignment(); - ctx.record_evidence(u.span(), |e, s| e.abc_assignment(s, "post_increment")); - } - UnaryPostfixOperator::PostDecrement(_) => { - ctx.current().abc.record_assignment(); - ctx.record_evidence(u.span(), |e, s| e.abc_assignment(s, "post_decrement")); - } - } - } - - // ----------------------------------------------------------------- - // ABC.B: function / method / instantiation / construct calls - // ----------------------------------------------------------------- - - fn walk_in_call(&self, c: &Call<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().abc.record_branch(); - ctx.record_evidence(c.span(), |e, s| e.abc_branch(s, "call")); - } - - fn walk_in_null_safe_method_call( - &self, - _c: &NullSafeMethodCall<'arena>, - _ctx: &mut Visitor<'_>, - ) { - // Already covered by `walk_in_call` since `Call::NullSafeMethod` - // dispatches here too — no double-counting needed (Mago's - // walker only fires `walk_call` for the `Call` enum variant, - // not for the inner specialized struct, see `mago_syntax` - // walker macro). Keep this empty so the trait method exists. - } - - fn walk_in_instantiation(&self, i: &Instantiation<'arena>, ctx: &mut Visitor<'_>) { - // `new Foo(...)` is a branch. - ctx.current().abc.record_branch(); - ctx.record_evidence(i.span(), |e, s| e.abc_branch(s, "instantiation")); - } - - fn walk_in_construct(&self, c: &Construct<'arena>, ctx: &mut Visitor<'_>) { - // PHP language-level transfer-of-control intrinsics. - match c { - Construct::Include(_) => { - ctx.current().abc.record_branch(); - ctx.record_evidence(c.span(), |e, s| e.abc_branch(s, "include")); - } - Construct::IncludeOnce(_) => { - ctx.current().abc.record_branch(); - ctx.record_evidence(c.span(), |e, s| e.abc_branch(s, "include_once")); - } - Construct::Require(_) => { - ctx.current().abc.record_branch(); - ctx.record_evidence(c.span(), |e, s| e.abc_branch(s, "require")); - } - Construct::RequireOnce(_) => { - ctx.current().abc.record_branch(); - ctx.record_evidence(c.span(), |e, s| e.abc_branch(s, "require_once")); - } - Construct::Exit(_) => { - ctx.current().nexit.record_exit(); - ctx.record_evidence(c.span(), |e, s| e.exit(s, "exit")); - } - Construct::Die(_) => { - ctx.current().nexit.record_exit(); - ctx.record_evidence(c.span(), |e, s| e.exit(s, "die")); - } - // `print` is a quirky expression-statement (returns 1) — - // not really a branch. `isset`/`empty`/`eval` aren't - // branches either. - _ => {} - } - } - - fn walk_in_yield(&self, y: &Yield<'arena>, ctx: &mut Visitor<'_>) { - // `yield` is a branch — same convention as Ruby's `yield`. - ctx.current().abc.record_branch(); - ctx.record_evidence(y.span(), |e, s| e.abc_branch(s, "yield")); - } - - // ----------------------------------------------------------------- - // Function exits - // ----------------------------------------------------------------- - - fn walk_in_return(&self, r: &Return<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - ctx.current().nexit.record_exit(); - ctx.record_evidence(r.span(), |e, s| e.exit(s, "return")); - } - - fn walk_in_throw(&self, t: &Throw<'arena>, ctx: &mut Visitor<'_>) { - // `Throw` here is the *expression* form (`throw new …`). - // The throw token itself counts as an exit (legacy `throw` - // rule). LLOC for the *statement* form is recorded by the - // wrapping ExpressionStatement. - ctx.current().nexit.record_exit(); - ctx.record_evidence(t.span(), |e, s| e.exit(s, "throw")); - } - - fn walk_in_break(&self, _b: &mago_syntax::cst::Break<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_continue(&self, _c: &mago_syntax::cst::Continue<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_goto(&self, _g: &mago_syntax::cst::Goto<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_label(&self, _l: &mago_syntax::cst::Label<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_echo(&self, _e: &mago_syntax::cst::Echo<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_echo_tag(&self, _e: &mago_syntax::cst::EchoTag<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_unset(&self, _u: &mago_syntax::cst::Unset<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_namespace(&self, _n: &mago_syntax::cst::Namespace<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_use(&self, _u: &mago_syntax::cst::Use<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_global(&self, _g: &mago_syntax::cst::Global<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_static(&self, _s: &mago_syntax::cst::Static<'arena>, ctx: &mut Visitor<'_>) { - // PHP's `static $x = …;` *function-static-declaration* form. - // (NOT the `static` modifier on a method.) - ctx.current().loc.observe_lloc(); - } - - fn walk_in_declare(&self, _d: &mago_syntax::cst::Declare<'arena>, ctx: &mut Visitor<'_>) { - ctx.current().loc.observe_lloc(); - } - - fn walk_in_constant(&self, _c: &mago_syntax::cst::Constant<'arena>, ctx: &mut Visitor<'_>) { - // Top-level `const X = 1;` declaration (legacy `ConstDeclaration`). - ctx.current().loc.observe_lloc(); - } - - fn walk_in_class_like_constant( - &self, - _c: &mago_syntax::cst::ClassLikeConstant<'arena>, - ctx: &mut Visitor<'_>, - ) { - // `class C { const X = 1; }` — legacy `ConstDeclaration2`. - ctx.current().loc.observe_lloc(); - } - - // ----------------------------------------------------------------- - // LLOC — every statement-shaped node - // ----------------------------------------------------------------- - - fn walk_in_statement_expression( - &self, - _e: &ExpressionStatement<'arena>, - ctx: &mut Visitor<'_>, - ) { - ctx.current().loc.observe_lloc(); - ctx.current().cognitive.boolean_seq.reset(); - } - - // Statement-shaped declarations (function / class / method / etc.) - // already get one LLOC per declaration via this same mechanism if - // they wrap an `ExpressionStatement`. Direct statements like - // `return`/`break`/`continue` aren't `ExpressionStatement`s — but - // their function-exit semantics (return/throw) are already - // recorded above; LLOC for them rolls up via the `Statement` - // walker, which we don't override (Mago's default recurses into - // children, and we let the per-node callbacks do the work). -} diff --git a/crates/mehen-php/tests/abc.rs b/crates/mehen-php/tests/abc.rs deleted file mode 100644 index 834597da..00000000 --- a/crates/mehen-php/tests/abc.rs +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC tests for the Phase 8 mago-syntax-backed walker. -//! -//! Legacy tree-sitter PHP carried no ABC snapshot test (the trait -//! impl in `legacy/metrics/abc.rs` was untested). These tests pin -//! the assignment / branch / condition triple against every PHP -//! construct the legacy classifier covered. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_abc_assignments_cover_all_assignment_forms() { - // ABC.A: plain assign (1), augmented += (2), null-coalesce ??= (3), - // string concat .= (4), prefix ++ (5), prefix -- (6), - // postfix ++ (7), postfix -- (8). 8 total. - let a = analyze( - "m(); - X::s(); - $obj?->n(); - new Foo(); - include 'a.php'; - require_once 'b.php'; - yield 1; - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - assert_eq!( - abc.branches, - 8.0, - "{}", - serde_json::to_string(&abc).unwrap() - ); -} - -#[test] -fn php_abc_conditions_cover_control_flow_and_comparisons() { - // ABC.C: if (1), `===` (2), `&&` (3), elseif (4), `<` (5), - // `else` (6), foreach (7), `==` (8). 8 total. - let a = analyze( - " - -//! Cognitive complexity tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/cognitive.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_else_branch_resets_boolean_sequence() { - // The boolean-operator sequence must reset when entering the - // `else` branch so that operators inside the else body start a - // fresh sequence rather than continuing the sequence from the - // `if` condition. Without the reset, two same-operator runs - // separated only by an `else` collapse — undercounting cognitive - // complexity. - // - // The bodies are intentionally empty: a non-empty body's - // `expression_statement` would itself reset `boolean_seq` and - // mask the bug. - // - // Breakdown WITH reset (correct): - // - outer `if`: +1 nesting -> structural=1 - // - outer `&&`: fresh sequence, +1 -> 2 - // - `else` clause: +1 (no nesting), reset -> 3 - // - inner `else if`: parses as nested `if_statement` whose - // `is_else_if` is true; counted as elseif (no extra nesting) - // - inner `&&`: with the reset, fresh sequence again, +1 -> 4 - // - // WITHOUT the reset, the inner `&&` collapses with the outer - // (same operator) and contributes 0, yielding 3. - let a = analyze( - " - -//! Contribution-evidence tests for the PHP analyzer (plan §5.4). -//! -//! PHP flows through the mago-syntax `Walker` visitor, which records -//! evidence next to every stat increment — these tests pin the -//! reason-code shape and the "evidence sums to the metric" invariant -//! for every event-shaped family. - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - PhpAnalyzer::new() - .analyze( - &SourceFile::new("s.php".into(), Language::Php, source.to_string()), - config, - ) - .expect("PHP analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = r#" 0 && $b > 0) { - return 1; - } elseif ($a < 0) { - return -1; - } else { - $a = 2; - } - $total = 0; - $double = function (int $x): int { - return $x * 2; - }; - return $double($total + $a); -} - -class Point -{ - public int $x = 0; - private int $y = 0; - - public function sum(): int - { - return $this->x + $this->y; - } -} -"#; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ("npa", "npa"), - ("npm", "npm"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn reasons_are_php_namespaced_with_construct_names() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "php.cyclomatic.if", - "php.cyclomatic.elseif", - "php.cyclomatic.&&", - "php.cognitive.if", - "php.cognitive.elseif", - "php.cognitive.else", - "php.cognitive.&&", - "php.nexit.return", - "php.abc.assignment.assignment", - "php.abc.branch.call", - "php.abc.condition.if", - "php.abc.condition.elseif", - "php.abc.condition.else", - "php.abc.condition.>", - "php.abc.condition.<", - "php.nom.function.function", - "php.nom.function.method", - "php.nom.closure.closure", - "php.nargs.function.function", - "php.nargs.closure.closure", - "php.npa.property", - "php.npm.method", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("php."))); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn promoted_constructor_properties_evidence_npa() { - // PHP 8 constructor property promotion: `public int $id` in the - // ctor declares a real (public) class property. Only public - // members are evidenced — `private string $name` counts toward - // the attribute denominator but not NPA. - let source = r#"id; - } - - private function secret(): string - { - return $this->name; - } -} -"#; - let analysis = analyze(source, &AnalysisConfig::production()); - assert_eq!(evidence_sum(&analysis, "npa"), metric(&analysis, "npa")); - assert_eq!(evidence_sum(&analysis, "npm"), metric(&analysis, "npm")); - assert_eq!(evidence_sum(&analysis, "npa"), 1.0); - assert_eq!(evidence_sum(&analysis, "npm"), 2.0); - assert!( - analysis - .contributions - .iter() - .any(|item| item.reason.as_str() == "php.npa.promoted_property") - ); - assert!( - analysis - .contributions - .iter() - .any(|item| item.reason.as_str() == "php.npm.method") - ); -} - -#[test] -fn cognitive_amounts_carry_nesting_depth() { - // A doubly-nested `if` pays nesting+1 = 2 on the inner node — - // the §5.4 "why did cognitive move +2 here" answer. - let source = r#" 0) { - if ($b > 0) { - return 1; - } - } - return 2; -} -"#; - let analysis = analyze(source, &AnalysisConfig::production()); - let cognitive: Vec = analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == "cognitive.sum") - .map(|item| item.amount) - .collect(); - assert_eq!(cognitive, vec![1.0, 2.0]); - assert_eq!(metric(&analysis, "cognitive.sum"), 3.0); -} - -#[test] -fn spaced_else_if_suppresses_nesting_but_keeps_decision() { - // The spaced `else if` form parses as an `If` nested in an else - // clause. The inner `if` is still a cyclomatic decision, but its - // structural cognitive +1 was already paid by the outer if's - // else-clause rule — so cognitive evidence carries exactly the - // outer `if` (+1) and the `else` (+1), nothing for the inner if. - let source = r#" 0) { - return 1; - } else if ($a < 0) { - return -1; - } - return 0; -} -"#; - let analysis = analyze(source, &AnalysisConfig::production()); - - let decisions: Vec<&str> = analysis - .contributions - .iter() - .filter(|item| { - item.metric.as_str() == "cyclomatic.sum" - // Per-space McCabe base rows are not decision events. - && !item.reason.as_str().starts_with("php.cyclomatic.base.") - }) - .map(|item| item.reason.as_str()) - .collect(); - assert_eq!(decisions, vec!["php.cyclomatic.if", "php.cyclomatic.if"]); - - let cognitive: Vec<(&str, f64)> = analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == "cognitive.sum") - .map(|item| (item.reason.as_str(), item.amount)) - .collect(); - assert_eq!( - cognitive, - vec![("php.cognitive.if", 1.0), ("php.cognitive.else", 1.0)] - ); - assert_eq!( - evidence_sum(&analysis, "cognitive.sum"), - metric(&analysis, "cognitive.sum"), - ); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc", - "nom", - "nargs", - "npa", - "npm", - ] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-php/tests/cyclomatic.rs b/crates/mehen-php/tests/cyclomatic.rs deleted file mode 100644 index fb02006b..00000000 --- a/crates/mehen-php/tests/cyclomatic.rs +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs::tests` per -//! rewrite plan §12.3 (parity contract). Every pre-1.0 -//! `check_metrics::` PHP test is reproduced here against -//! the Phase 8 mago-syntax-backed walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - // Match legacy `check_metrics`: trim trailing newlines and append one. - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_basic_decision_points() { - // Decision points: function f opens unit (+1), function (+1), - // if (+1), elseif (+1), else (no), && (+1), || (+1). - let a = analyze( - " 0 && $b > 0) { // +2 (if + &&) - return 1; - } elseif ($a < 0 || $b < 0) { // +2 (elseif + ||) - return -1; - } - return 0; - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - }"### - ); -} diff --git a/crates/mehen-php/tests/halstead.rs b/crates/mehen-php/tests/halstead.rs deleted file mode 100644 index 252c6e09..00000000 --- a/crates/mehen-php/tests/halstead.rs +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Halstead tests for the Phase 8 mago-syntax-backed walker. -//! -//! The legacy tree-sitter PHP suite carried no Halstead snapshot -//! (Halstead was implemented but untested in `legacy/metrics/halstead.rs`), -//! so these tests are new. They lock in the operator/operand -//! classification table in `walker::classify_token` and the -//! token-sweep pipeline. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_halstead_simple_function() { - // `function add(int $a, int $b): int { return $a + $b; }` exercises - // keyword (`function`, `return`), punctuation (`(`, `,`, `:`, `{`, `;`), - // arithmetic (`+`), identifier (`add`, `int`), and variable - // (`$a`, `$b`) classification. Closing parens / braces pair with - // the openers (classical Halstead) so they don't appear in `n1`. - let a = analyze( - " N1 = 5 - // Operands: 'plain' (1× String), `f` (1× Identifier) -> n2=2, N2=2 - assert_eq!(h.n1, 5.0, "{}", serde_json::to_string(&h).unwrap()); - assert_eq!(h.n2, 2.0, "{}", serde_json::to_string(&h).unwrap()); - assert_eq!(h.length, 7.0, "{}", serde_json::to_string(&h).unwrap()); -} - -/// Regression: methods inside a class must record their own Halstead -/// counts in the per-space JSON. PR #95 discussion_r3265658502 flagged -/// this on the Python walker; PHP had the same `stack[0]`-only bug, so -/// every method's `halstead.N1`/`halstead.N2` was zero in the report. -#[test] -fn php_method_halstead_is_non_zero() { - let a = analyze( - " 0.0, - "method must record `function`, `return`, `+` operators, got {}", - serde_json::to_string(&method_h).unwrap() - ); - assert!( - method_h.big_n2 > 0.0, - "method must record `m`, `$a`, `$b` operands, got {}", - serde_json::to_string(&method_h).unwrap() - ); - let class_h = mehen_report::metrics_json::halstead(&class.metrics); - assert!( - class_h.big_n1 >= method_h.big_n1, - "class N1 must roll up the method: class={} method={}", - serde_json::to_string(&class_h).unwrap(), - serde_json::to_string(&method_h).unwrap() - ); -} diff --git a/crates/mehen-php/tests/loc.rs b/crates/mehen-php/tests/loc.rs deleted file mode 100644 index 619e3273..00000000 --- a/crates/mehen-php/tests/loc.rs +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC tests for the Phase 8 mago-syntax-backed walker. -//! -//! Legacy tree-sitter PHP carried no LOC snapshot test (LOC was -//! implemented in `legacy/metrics/loc.rs` but no PHP fixture exercised -//! it). These tests are new — they pin the LLOC accounting against -//! every statement-shaped node enumerated in `legacy/metrics/loc.rs`'s -//! PHP arm so future regressions surface immediately. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_lloc_counts_simple_function_body() { - // function (1) + if (2) + return (3) + return (4) = 4 LLOC. - let a = analyze( - " 0) { - return 1; - } - return 0; - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!(loc.lloc, 4.0, "{}", serde_json::to_string(&loc).unwrap()); -} - -#[test] -fn php_lloc_counts_namespace_use_const() { - // namespace (1) + use (2) + const (3) = 3 LLOC. - let a = analyze( - "= 1.0, - "method must record its `// inner comment` as cloc, got {}", - serde_json::to_string(&method_loc).unwrap() - ); - assert!( - method_loc.ploc >= 2.0, - "method must record `$sum = ...` and `return $sum;` as ploc, got {}", - serde_json::to_string(&method_loc).unwrap() - ); -} diff --git a/crates/mehen-php/tests/npa.rs b/crates/mehen-php/tests/npa.rs deleted file mode 100644 index 098d989e..00000000 --- a/crates/mehen-php/tests/npa.rs +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPA tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/npa.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_npa_counts_each_property_in_grouped_declaration() { - // `public $a, $b;` is one property declaration with two property - // items — count both. class_attributes: 3 (a, b, c). class_npa: 2 (a, b). - let a = analyze( - " - -//! NPM tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/npm.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_npm_visibility_keywords_are_case_insensitive() { - // PHP keywords are case-insensitive per the language spec, so - // `PRIVATE` / `Protected` must be recognized as non-public. - // public: a. non-public: b, c. - let a = analyze( - " - -//! WMC tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/wmc.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_php::PhpAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PhpAnalyzer::new(); - let file = SourceFile::new("foo.php".into(), Language::Php, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn php_wmc_class_sums_method_cyclomatics() { - // class C: a cyc=2 (if), b cyc=1 -> classes = 3 - let a = analyze( - " 0) { - return 1; - } - return 0; - } - public function b(): int { return 1; } - }", - ); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - insta::assert_json_snapshot!( - wmc, - @r###" - { - "classes": 3.0, - "interfaces": 0.0, - "total": 3.0 - }"### - ); -} diff --git a/crates/mehen-powershell/Cargo.toml b/crates/mehen-powershell/Cargo.toml deleted file mode 100644 index 71f03278..00000000 --- a/crates/mehen-powershell/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "mehen-powershell" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — PowerShell language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -mehen-tree-sitter = { workspace = true } -smol_str = { workspace = true } -tree-sitter = { workspace = true } -# `tree-sitter-pwsh` is pinned here (not in `[workspace.dependencies]`) -# because `mehen-powershell` is the only consumer. -tree-sitter-pwsh = "=0.38.1" - -[dev-dependencies] -# Tests render the per-metric JSON family object so snapshots match the -# documented `mehen metrics --format json` schema (plan §9.1). -mehen-report = { workspace = true } -insta = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-powershell/src/lib.rs b/crates/mehen-powershell/src/lib.rs deleted file mode 100644 index 2c67d459..00000000 --- a/crates/mehen-powershell/src/lib.rs +++ /dev/null @@ -1,547 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-powershell` — PowerShell language analyzer. -//! -//! Phase 3 implementation: walks tree-sitter-pwsh with PowerShell-specific -//! decision rules mirroring the pre-1.0 `Cyclomatic for PowershellCode` -//! (`src/metrics/cyclomatic.rs:250-306`). - -#![forbid(unsafe_code)] - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, ParseDiagnostic, - Result, SourceFile, SourceSpan, SpaceKind, byte_offset_clamped, -}; -use mehen_tree_sitter::{ - CognitiveFact, LanguageRules, MetricEvidence, NodeFacts, ScopeOpen, TreeSitterParser, - collect_recovered_errors, empty_space, text_of, walk, -}; -use tree_sitter::Node; - -pub struct PowerShellAnalyzer; - -impl PowerShellAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for PowerShellAnalyzer { - fn default() -> Self { - Self::new() - } -} - -struct PowerShellRules; - -impl LanguageRules for PowerShellRules { - fn scope_for(&self, node: &Node<'_>, source: &[u8]) -> Option { - let kind = node.kind(); - // Mirrors the pre-1.0 `Checker for PowershellCode::is_func_space` - // (`src/checker.rs`): `Program` (the unit, handled by the walker - // separately), `FunctionStatement`, `ClassStatement`, - // `ClassMethodDefinition`, and `ScriptBlockExpression` open a - // space. The bare `script_block` *does not* open a space — it's - // the body container for switch-clause arms etc., not a closure. - let opened = match kind { - "function_statement" | "function_definition" => ScopeOpen::Open { - kind: SpaceKind::Function, - name: node - .child_by_field_name("name") - .map(|n| text_of(&n, source).to_string()), - }, - "class_method_definition" => ScopeOpen::Open { - kind: SpaceKind::Function, - name: node - .child_by_field_name("name") - .map(|n| text_of(&n, source).to_string()), - }, - "script_block_expression" => ScopeOpen::Open { - kind: SpaceKind::Closure, - name: None, - }, - "class_statement" => ScopeOpen::Open { - kind: SpaceKind::Class, - name: node - .child_by_field_name("name") - .map(|n| text_of(&n, source).to_string()), - }, - _ => return None, - }; - Some(opened) - } - - fn classify(&self, node: &Node<'_>) -> NodeFacts { - let kind = node.kind(); - // Per pre-1.0 src/metrics/cyclomatic.rs:250-306. PowerShell adds - // -and / -or as short-circuit and v7's null-coalesce / ternary. - let cyclomatic_decision = matches!( - kind, - "if_statement" - | "elseif_clause" - | "for_statement" - | "foreach_statement" - | "while_statement" - | "do_statement" - | "switch_clause" - | "catch_clause" - | "trap_statement" - | "ternary_expression" - | "ternary_argument_expression" - | "null_coalesce_expression" - | "null_coalesce_argument_expression" - | "&&" - | "||" - | "-and" - | "-or" - ); - // NExit: `return`, `throw`, `exit` — but not `break` / `continue` - // (loop-local flow, not function exit). tree-sitter-pwsh emits all - // of those as `flow_control_statement` whose first child is the - // specific keyword token, so we match on the leading child. - let nexit = kind == "flow_control_statement" - && matches!( - node.child(0).map(|c| c.kind()), - Some("return") | Some("throw") | Some("exit") - ); - let halstead_operator = is_powershell_operator(kind); - let halstead_operand = is_powershell_operand(kind); - // ABC classification per pre-1.0 `Abc for PowershellCode` - // (`src/metrics/abc.rs:562-632`). - let abc_assignment = matches!( - kind, - "assignment_expression" - | "pre_increment_expression" - | "pre_decrement_expression" - | "post_increment_expression" - | "post_decrement_expression" - ); - let abc_branch = matches!(kind, "command" | "invocation_expression"); - // Conditions: structural conditionals + comparison / ternary / - // null-coalesce wrappers (these wrap a single operator each, so - // matching them doesn't double-count) + the leaf logical - // operator tokens. Intentionally NOT `logical_expression` / - // `logical_argument_expression` / `pipeline_chain` — those - // wrappers can hold multiple leaves, so matching them too - // would double-count. - let abc_condition = matches!( - kind, - "if_statement" - | "elseif_clause" - | "for_statement" - | "foreach_statement" - | "while_statement" - | "do_statement" - | "switch_clause" - | "catch_clause" - | "trap_statement" - | "ternary_expression" - | "ternary_argument_expression" - | "null_coalesce_expression" - | "null_coalesce_argument_expression" - | "comparison_expression" - | "comparison_argument_expression" - | "&&" - | "||" - | "-and" - | "-or" - | "-xor" - ); - NodeFacts { - cyclomatic_decision, - cognitive: powershell_cognitive_fact(node), - halstead_operator, - halstead_operand, - nexit, - abc_branch, - abc_condition, - abc_assignment, - loc: powershell_loc_fact(node), - } - } - - fn count_args(&self, node: &Node<'_>, _source: &[u8]) -> u32 { - powershell_count_args(node) - } - - fn classify_attribute( - &self, - node: &Node<'_>, - _source: &[u8], - ) -> Option { - // PowerShell properties are `class_property_definition` direct - // children of a `class_statement`. PowerShell has no - // access-modifier equivalent to `private` / `protected`; the - // `hidden` keyword only suppresses default Get-Member output — - // members remain publicly accessible. Per `about_Hidden`: - // "hidden members are still public". - if node.kind() != "class_property_definition" { - return None; - } - let in_class = node.parent().is_some_and(|p| p.kind() == "class_statement"); - if !in_class { - return None; - } - Some(mehen_tree_sitter::MemberClassification { - container: mehen_metrics::ContainerKind::Class, - is_public: true, - }) - } - - fn classify_method( - &self, - node: &Node<'_>, - _source: &[u8], - ) -> Option { - if node.kind() != "class_method_definition" { - return None; - } - let in_class = node.parent().is_some_and(|p| p.kind() == "class_statement"); - if !in_class { - return None; - } - Some(mehen_tree_sitter::MemberClassification { - container: mehen_metrics::ContainerKind::Class, - is_public: true, - }) - } -} - -/// Count the function/closure parameters declared by the -/// PowerShell space rooted at `node`. Mirrors the pre-1.0 -/// `compute_powershell_args` (`src/metrics/nargs.rs:293-370`): -/// PowerShell parameter declarations appear in three shapes — -/// `function_statement` > `function_parameter_declaration` > -/// `parameter_list` > `script_parameter`; `script_block_expression` > -/// `param_block` > `parameter_list` > `script_parameter`; or -/// `class_method_definition` > `class_method_parameter_list` > -/// `class_method_parameter`. The walker recurses ONLY through the -/// thin structural wrappers between the entry node and the parameter -/// list — never into the body — so nested closures don't leak args -/// into their enclosing function. -fn powershell_count_args(node: &Node<'_>) -> u32 { - let kind = node.kind(); - let is_method = kind == "class_method_definition"; - let mut count: u32 = 0; - let mut cursor = node.walk(); - for child in node.children(&mut cursor) { - match child.kind() { - "parameter_list" if !is_method => { - let mut pl = child.walk(); - for p in child.children(&mut pl) { - if p.kind() == "script_parameter" { - count = count.saturating_add(1); - } - } - } - "class_method_parameter_list" if is_method => { - let mut pl = child.walk(); - for p in child.children(&mut pl) { - if p.kind() == "class_method_parameter" { - count = count.saturating_add(1); - } - } - } - // Recurse only into the structural wrapper that directly - // contains the parameter list — `function_parameter_declaration` - // for functions, `param_block` for closures. The body - // `script_block` / `script_block_body` / `statement_list` is - // intentionally NOT descended (that's where nested closures - // live). - "function_parameter_declaration" | "param_block" => { - count = count.saturating_add(powershell_count_args(&child)); - } - _ => {} - } - } - count -} - -/// PowerShell Halstead operator classification per pre-1.0 -/// `Getter::get_op_type for PowershellCode` (`src/getter.rs:485-548`). -/// Wrapper rule kinds (`assignment_operator`, `comparison_operator`, -/// `format_operator`, `file_redirection_operator`, -/// `merging_redirection_operator`) are intentionally NOT included — -/// the walker visits both the wrapper and its leaf token, and matching -/// only the leaves prevents double-counting. -fn is_powershell_operator(kind: &str) -> bool { - matches!( - kind, - // Keywords and structural / control-flow markers. - "function" | "filter" | "workflow" | "if" | "elseif" | "else" - | "switch" | "for" | "foreach" | "in" | "while" | "do" | "until" - | "break" | "continue" | "return" | "throw" | "exit" - | "try" | "catch" | "finally" | "trap" - | "param" | "using" | "namespace" | "module" | "assembly" - | "static" | "this" | "base" - | "begin" | "process" | "end" | "clean" | "dynamicparam" - | "data" | "inlinescript" | "parallel" | "sequence" - // Punctuation-like. - | "(" | "{" | "[" | "," | ";" | "." | ".." | ":" | "::" - | "@(" | "@{" | "$(" - // Assignment family. - | "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "??=" - // Arithmetic / bitwise / unary. - | "+" | "-" | "*" | "/" | "%" | "\\" | "..." - | "++" | "--" | "!" - // Short-circuit / null-coalesce / ternary. - | "&&" | "||" | "?" | "??" - // Pipeline / invocation / redirection. - | "|" | "&" - // Word-form logical / comparison / typing operators. - | "-and" | "-or" | "-xor" | "-not" - | "-band" | "-bor" | "-bxor" | "-bnot" - | "-as" | "-is" | "-isnot" - | "-f" | "-join" - | "-shl" | "-shr" - | "-split" | "-isplit" | "-csplit" - | "-replace" | "-ireplace" | "-creplace" - | "-match" | "-imatch" | "-cmatch" - | "-notmatch" | "-inotmatch" | "-cnotmatch" - | "-like" | "-ilike" | "-clike" - | "-notlike" | "-inotlike" | "-cnotlike" - | "-contains" | "-icontains" | "-ccontains" - | "-notcontains" | "-inotcontains" | "-cnotcontains" - | "-in" | "-notin" - | "-eq" | "-ieq" | "-ceq" | "-ne" | "-ine" | "-cne" - | "-lt" | "-ilt" | "-clt" | "-le" | "-ile" | "-cle" - | "-gt" | "-igt" | "-cgt" | "-ge" | "-ige" | "-cge" - | "<" | ">" - // File / merging redirection leaf tokens. Names mirror - // tree-sitter-pwsh's anonymous tokens for `2>`, `2>>`, - // `2>&1`, `*>`, `3>&2`, etc. - | ">>" | "*>" | "*>>" | "*>&1" | "*>&2" - | "2>" | "2>>" | "2>&1" - | "3>" | "3>>" | "3>&1" | "3>&2" - | "4>" | "4>>" | "4>&1" | "4>&2" - | "5>" | "5>>" | "5>&1" | "5>&2" - | "6>" | "6>>" | "6>&1" | "6>&2" - | "1>&2" - ) -} - -/// PowerShell Halstead operand classification per pre-1.0 -/// `Getter::get_op_type for PowershellCode` (`src/getter.rs:485-593`). -fn is_powershell_operand(kind: &str) -> bool { - matches!( - kind, - // Identifiers, type names, variables. - "simple_name" | "type_identifier" | "variable" | "braced_variable" - | "generic_token" - // Numeric literals. - | "decimal_integer_literal" | "hexadecimal_integer_literal" | "real_literal" - // Verbatim (single-quoted) string content leaves. - | "verbatim_string_characters" | "verbatim_here_string_characters" - // Expandable (double-quoted) string wrappers — counted as one - // operand each because the wrapper's byte range carries the - // text directly (no content-leaf node). - | "expandable_string_literal" | "expandable_here_string_literal" - // Identifier leaves driving function declarations and command - // invocations. The named wrappers `command_name_expr` / - // `path_command_name` are intentionally NOT included to avoid - // double-counting against their leaf token. - | "function_name" | "command_name" | "path_command_name_token" - | "command_parameter" - ) -} - -/// PowerShell cognitive-complexity classification per pre-1.0 -/// `Cognitive for PowershellCode` (`src/metrics/cognitive.rs:640-770`). -/// -/// Returns one [`CognitiveFact`] describing how this node contributes -/// to the cognitive state machine; the walker drives the `(nesting, -/// depth, lambda)` context and the `BoolSequence` collapser based on -/// the variant. -fn powershell_cognitive_fact(node: &Node<'_>) -> CognitiveFact { - use smol_str::SmolStr; - let kind = node.kind(); - match kind { - // Nesting-increasing constructs: `if` / loops / `switch` / - // `catch` / ternary / null-coalesce. Each adds `nesting + 1` - // and bumps the descendant nesting depth. - "if_statement" - | "for_statement" - | "foreach_statement" - | "while_statement" - | "do_statement" - | "switch_statement" - | "catch_clause" - | "ternary_expression" - | "ternary_argument_expression" - | "null_coalesce_expression" - | "null_coalesce_argument_expression" => CognitiveFact::IncreaseNesting, - // Same-level conditional clauses: +1 without bumping nesting, - // and reset the boolean-sequence tracker. - "elseif_clause" | "else_clause" | "finally_clause" | "trap_statement" => { - CognitiveFact::NonNestingPlusOne - } - // Pipeline statements: statement-boundary reset + collect - // `&&` / `||` from `pipeline_chain_tail` children for the - // boolean-sequence collapser. - "pipeline" => { - let mut ops: Vec = Vec::new(); - let mut cur = node.walk(); - for child in node.children(&mut cur) { - if child.kind() != "pipeline_chain_tail" { - continue; - } - if let Some(op) = child.child(0) { - let op_kind = op.kind(); - if matches!(op_kind, "&&" | "||") { - ops.push(SmolStr::new(op_kind)); - } - } - } - CognitiveFact::StatementBoundaryWithBooleans(ops) - } - // Assignment is also a statement boundary for the bool-sequence. - "assignment_expression" => CognitiveFact::StatementBoundary, - // Negation operators — track in the bool-sequence collapser - // without bumping structural so a leading `!` / `-not` doesn't - // mistake the next real boolean for a transition. - "-not" | "!" | "-bnot" => CognitiveFact::NotOperator(SmolStr::new(kind)), - // Logical wrappers carry one or more `-and` / `-or` / `-xor` - // leaf tokens. Feed each leaf into the BoolSequence collapser. - // The wrapper itself is not a statement boundary, so this is a - // `BooleanContainer` (no reset). - "logical_expression" | "logical_argument_expression" => { - let mut ops: Vec = Vec::new(); - let mut cur = node.walk(); - for child in node.children(&mut cur) { - let k = child.kind(); - if matches!(k, "-and" | "-or" | "-xor") { - ops.push(SmolStr::new(k)); - } - } - CognitiveFact::BooleanContainer(ops) - } - // Function-like spaces reset structural nesting and bump the - // `depth` so children of nested functions count their own - // nesting from zero. - "function_statement" | "class_method_definition" => CognitiveFact::FunctionEntry, - // Closures (script-block expressions) bump `lambda` so their - // descendants pay the lambda penalty. - "script_block_expression" => CognitiveFact::LambdaEntry, - _ => CognitiveFact::None, - } -} - -/// PowerShell LOC classification per pre-1.0 -/// `Loc for PowershellCode` (`src/metrics/loc.rs:909-961`). -fn powershell_loc_fact(node: &Node<'_>) -> mehen_tree_sitter::LocFact { - use mehen_tree_sitter::LocFact; - match node.kind() { - // Containers — must NOT contribute to PLOC. - "program" | "script_block" | "script_block_body" | "statement_list" | "statement_block" - | "named_block_list" | "named_block" | "param_block" | "elseif_clauses" - | "catch_clauses" | "switch_body" | "switch_clauses" => LocFact::Container, - // Comments cover both `#` line comments and `<# ... #>` block - // comments — they share the `comment` named rule in tree-sitter-pwsh. - "comment" => LocFact::Comment, - // LLOC: each statement-shaped node bumps LLOC once. The - // tree-sitter-pwsh v0.37+ grammar emits one `pipeline` per - // statement (the assignment RHS is a dedicated `assignment_value` - // rather than a nested `pipeline`), so counting every visible - // `pipeline` once is safe. - "pipeline" - | "if_statement" - | "for_statement" - | "foreach_statement" - | "while_statement" - | "do_statement" - | "switch_statement" - | "try_statement" - | "trap_statement" - | "function_statement" - | "class_statement" - | "enum_statement" - | "data_statement" - | "flow_control_statement" - | "class_method_definition" - | "class_property_definition" => LocFact::Lloc, - _ => LocFact::Code, - } -} - -impl LanguageAnalyzer for PowerShellAnalyzer { - fn language(&self) -> Language { - Language::PowerShell - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::TreeSitter - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - let parser = match TreeSitterParser::new( - tree_sitter_pwsh::LANGUAGE.into(), - source.text.clone().into_bytes(), - ) { - Ok(p) => p, - Err(e) => { - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: source.line_index.line_count(), - }; - return Ok(LanguageAnalysis { - language: Language::PowerShell, - backend: AnalysisBackend::TreeSitter, - diagnostics: vec![ParseDiagnostic::fatal( - "powershell.parse_error", - format!("tree-sitter-pwsh failed: {e}"), - )], - root: empty_space(span), - contributions: Vec::new(), - }); - } - }; - - let mut evidence = MetricEvidence::new("powershell", config.emit_contributions); - let result = walk( - parser.root(), - parser.source(), - &source.line_index, - &PowerShellRules, - &mut evidence, - ); - // Tree-sitter recovers from syntax errors by inserting ERROR / - // missing nodes; surface them as `error` diagnostics so the - // metric output can't masquerade as clean (plan §9.3). - let diagnostics = collect_recovered_errors(parser.root(), "powershell.syntax_error", 16); - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&result.root); - Ok(LanguageAnalysis { - language: Language::PowerShell, - backend: AnalysisBackend::TreeSitter, - diagnostics, - root: result.root, - contributions: evidence.finish(), - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, Language, SourceFile}; - - #[test] - fn analyzes_simple_script() { - let a = PowerShellAnalyzer::new() - .analyze( - &SourceFile::new( - "a.ps1".into(), - Language::PowerShell, - "function Foo { 1 }".to_string(), - ), - &AnalysisConfig::default(), - ) - .unwrap(); - assert_eq!(a.root.kind, SpaceKind::Unit); - } -} diff --git a/crates/mehen-powershell/tests/abc.rs b/crates/mehen-powershell/tests/abc.rs deleted file mode 100644 index 1730e870..00000000 --- a/crates/mehen-powershell/tests/abc.rs +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell ABC tests, ported from -//! `src/metrics/abc.rs::tests` per rewrite plan §8.2. -//! -//! Snapshots are byte-identical to the pre-1.0 `metric.abc` strings. - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, MetricValue, - SourceFile, -}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -fn metric(report: &LanguageAnalysis, key: &str) -> f64 { - match report.root.metrics.get(&MetricKey::new(key)).unwrap() { - MetricValue::Int(i) => i as f64, - MetricValue::Float(f) => f, - } -} - -#[test] -fn powershell_abc_basic() { - // function f($a, $b) { $c = $a + $b; Write-Host $c; if ($c -gt 0) { return $c } } - // A=1, B=1, C=2 (1 if + 1 comparison). Magnitude = sqrt(1 + 1 + 4) ≈ 2.449. - let a = analyze( - "function f($a, $b) { - $c = $a + $b - Write-Host $c - if ($c -gt 0) { - return $c - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::abc(&a.root.metrics), - @r###" - { - "assignments": 1.0, - "branches": 1.0, - "conditions": 2.0, - "magnitude": 2.449489742783178, - "assignments_average": 0.5, - "branches_average": 0.5, - "conditions_average": 1.0, - "assignments_min": 0.0, - "assignments_max": 1.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 2.0 - } - "### - ); -} - -#[test] -fn powershell_abc_counts_argument_form_decision_operators() { - // tree-sitter-pwsh emits `*_argument_expression` for expressions - // inside method-invocation argument lists (e.g. - // `[Foo]::Bar($a -eq $b)`). Argument-form comparison / ternary / - // null-coalesce must contribute to ABC conditions. - let a = analyze( - "function f($a, $b, $cond, $x) { - [Foo]::Bar($a -eq $b) - [Foo]::Baz($cond ? 1 : 2) - [Foo]::Qux($x ?? 3) - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::abc(&a.root.metrics), - @r###" - { - "assignments": 0.0, - "branches": 3.0, - "conditions": 3.0, - "magnitude": 4.242640687119285, - "assignments_average": 0.0, - "branches_average": 1.5, - "conditions_average": 1.5, - "assignments_min": 0.0, - "assignments_max": 0.0, - "branches_min": 0.0, - "branches_max": 3.0, - "conditions_min": 0.0, - "conditions_max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_abc_logical_operators_are_not_double_counted() { - // Regression: ABC conditions match only the *leaf* logical-operator - // tokens (`-and` / `-or` / `-xor` / `&&` / `||`), NOT the - // `logical_expression` / `pipeline_chain` wrappers — a single - // wrapper can hold multiple leaves (`$a -and $b -and $c`), - // counting both wrapper and leaves would double-count. - let a = analyze( - "function f($a, $b, $c) { - if ($a -and $b -and $c) { 'x' } - [Foo]::Bar($a -or $b) - }", - ); - // Conditions: 1 (if) + 2 (-and, -and) + 1 (-or) = 4. - // Branches: 1 (`[Foo]::Bar` invocation_expression). - // Assignments: 0. - assert_eq!(metric(&a, "abc.conditions"), 4.0); - assert_eq!(metric(&a, "abc.branches"), 1.0); - assert_eq!(metric(&a, "abc.assignments"), 0.0); -} diff --git a/crates/mehen-powershell/tests/cognitive.rs b/crates/mehen-powershell/tests/cognitive.rs deleted file mode 100644 index 0c0d6ec1..00000000 --- a/crates/mehen-powershell/tests/cognitive.rs +++ /dev/null @@ -1,365 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell cognitive-complexity tests, ported from -//! `src/metrics/cognitive.rs::tests` per rewrite plan §8.2. -//! -//! Snapshots are byte-identical to the pre-1.0 `metric.cognitive` -//! strings. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_nested_if_increments_nesting() { - // function f($a, $b) { - // if ($a) { # +1 - // if ($b) { # +2 (nesting = 1) - // ... - // } - // } - // } - // sum = 3, average = sum / nom.total() = 3 / 1 = 3. - let a = analyze( - "function f($a, $b) { - if ($a) { - if ($b) { - Write-Host \"hi\" - } - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_try_catch_nesting() { - // `try` itself does NOT add; each `catch` does and bumps nesting. - // `finally` adds +1 without nesting. - let a = analyze( - "function f { - try { - if ($a) { - Write-Host \"a\" - } - } catch { - if ($b) { - throw - } - } finally { - Write-Host \"done\" - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 5.0, - "average": 5.0, - "min": 0.0, - "max": 5.0 - } - "### - ); -} - -#[test] -fn powershell_elseif_and_else_flatten() { - let a = analyze( - "function f($a) { - if ($a -gt 0) { - 'pos' - } elseif ($a -lt 0) { - 'neg' - } else { - 'zero' - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_same_op_boolean_sequence_collapses() { - // Same-op `-and -and` collapses → +2 (1 if + 1 sequence). - let a = analyze( - "function f($a, $b, $c) { - if ($a -and $b -and $c) { - 'ok' - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - } - "### - ); - - // Mixed `-and -or` adds +1 each → +3 (1 if + 1 -and + 1 -or). - let b = analyze( - "function f($a, $b, $c) { - if ($a -and $b -or $c) { - 'ok' - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&b.root.metrics), - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_wrappers_without_operators_do_not_false_trigger() { - // tree-sitter-pwsh emits `ternary_expression` / - // `null_coalesce_expression` / `logical_expression` ONLY when an - // actual operator is present. Plain `$a + $b` doesn't trigger them. - // Cognitive must be zero. - let a = analyze("function Plain { $x = $a + $b }"); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - } - "### - ); -} - -#[test] -fn powershell_boolean_sequence_does_not_leak_across_else() { - // Outer `if ($a -and $b)`'s boolean-sequence tracker must not bleed - // into an inner `if ($c -and $d)` in the `else` body. The inner - // `if`'s condition is wrapped in a `pipeline` node, which is the - // statement boundary that resets the tracker. - let a = analyze( - "function f($a, $b, $c, $d) { - if ($a -and $b) { - 'x' - } else { - if ($c -and $d) { - 'y' - } - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 6.0, - "average": 6.0, - "min": 0.0, - "max": 6.0 - } - "### - ); -} - -#[test] -fn powershell_boolean_sequence_does_not_leak_across_finally() { - // Same invariant as the else-leak regression but for `finally`. The - // reset comes from the `pipeline` wrapping the inner `if`'s - // condition, not from `finally_clause` itself. - let a = analyze( - "function f($a, $b, $c, $d) { - try { - if ($a -and $b) { 'x' } - } finally { - if ($c -and $d) { 'y' } - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 5.0, - "average": 5.0, - "min": 0.0, - "max": 5.0 - } - "### - ); -} - -#[test] -fn powershell_cognitive_counts_argument_form_decision_operators() { - // tree-sitter-pwsh emits `*_argument_expression` for expressions - // inside method-invocation argument lists. Argument-form ternary - // and null-coalesce are nesting-increasing, and argument-form - // `logical_argument_expression` participates in same-operator - // sequence collapsing. - let a = analyze( - "function f($a, $b, $cond, $x) { - [Foo]::Baz($cond ? 1 : 2) - [Foo]::Qux($x ?? 3) - [Foo]::Zig($a -and $b -and $cond) - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_cognitive_xor_participates_in_boolean_sequence() { - // `-xor` is a direct child of `logical_expression`; it must - // participate in the boolean-sequence tracker so a standalone `-xor` - // adds +1 and mixed chains add +1 per operator-transition. - let a = analyze( - "function f($a, $b, $c, $d) { - if ($a -xor $b) { 'x' } - if ($a -xor $b -xor $c) { 'y' } - if ($a -and $b -xor $c -or $d) { - 'z' - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 8.0, - "average": 8.0, - "min": 0.0, - "max": 8.0 - } - "### - ); -} - -#[test] -fn powershell_cognitive_unary_wrappers_do_not_break_boolean_collapsing() { - // `expression_with_unary_operator` is the grammar wrapper for *all* - // unary forms (`+$x`, `-$x`, `[int]$x`, `,$x`, `++$x`, `-split $x`, - // …), not just `-not` / `!`. Storing the wrapper's kind as the - // "previous boolean" would poison subsequent same-operator - // collapsing. Only the actual negation tokens (`-not` / `!` / - // `-bnot`) feed `not_operator`. - let a = analyze( - "function f($a, $b, $c) { - if ($a -and $b -and $c) { } - if (+$a -and $b -and $c) { } - if ([int]$a -and $b -and $c) { } - if (,$a -and $b -and $c) { } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 8.0, - "average": 8.0, - "min": 0.0, - "max": 8.0 - } - "### - ); -} - -#[test] -fn powershell_cognitive_not_negation_still_tracked() { - // The restricted `DASHnot | BANG | DASHbnot` arm must still feed - // `BoolSequence::not_operator` so real negation chains collapse. - // `if (-not $a -and -not $b)` has two same-shape negated operands - // joined by a single `-and` — total is +1 if +1 -and. - let a = analyze( - "function f($a, $b) { - if (-not $a -and -not $b) { } - if (!$a -or !$b -or !$c) { } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - } - "### - ); -} - -#[test] -fn powershell_cognitive_pipeline_chain_tail_operators_count() { - // `cmd1 && cmd2 || cmd3` parses as one `pipeline` containing - // alternating `pipeline_chain` / `pipeline_chain_tail` children, - // where each `pipeline_chain_tail` wraps a single `&&` or `||` - // token. The Pipeline arm scans those tails and feeds the - // boolean-sequence tracker, so mixed chains add +1 per transition - // and same-op runs collapse to +1. - let a = analyze( - "function f { - Get-Thing && Write-Host 'ok' || Write-Error 'bad' - Get-A && Get-B && Get-C - Get-D - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cognitive(&a.root.metrics), - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "### - ); -} diff --git a/crates/mehen-powershell/tests/contributions.rs b/crates/mehen-powershell/tests/contributions.rs deleted file mode 100644 index ecfac7dc..00000000 --- a/crates/mehen-powershell/tests/contributions.rs +++ /dev/null @@ -1,181 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the PowerShell analyzer (plan §5.4). -//! -//! PowerShell flows through the shared `LanguageRules` walker, which -//! records evidence centrally — these tests pin the reason-code shape -//! and the "evidence sums to the metric" invariant for every -//! event-shaped family. - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - PowerShellAnalyzer::new() - .analyze( - &SourceFile::new("s.ps1".into(), Language::PowerShell, source.to_string()), - config, - ) - .expect("PowerShell analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -function Get-Thing($a, $b) { - if ($a -and $b) { - return 1 - } - return 2 -} -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - // Families whose rolled-up value is exactly the sum of their - // per-event evidence. - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc.assignments", - "abc.branches", - "abc.conditions", - "nom.functions", - "nom.closures", - "nargs", - ] { - assert_eq!( - evidence_sum(&analysis, key), - metric(&analysis, key), - "evidence for `{key}` must sum to the published value", - ); - } -} - -#[test] -fn reasons_are_powershell_namespaced_with_node_kinds() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - assert!(reasons.contains(&"powershell.cyclomatic.if_statement")); - assert!(reasons.contains(&"powershell.cognitive.if_statement")); - assert!(reasons.contains(&"powershell.nexit.flow_control_statement")); - assert!(reasons.contains(&"powershell.nom.function.function_statement")); - assert!(reasons.contains(&"powershell.nargs.function.function_statement")); - assert!( - reasons - .iter() - .all(|reason| reason.starts_with("powershell.")) - ); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn class_members_evidence_npa_and_npm() { - let source = "\ -class Point { - [int]$X - [int]$Y - [int] Sum() { return 42 } -} -"; - let analysis = analyze(source, &AnalysisConfig::production()); - assert_eq!(evidence_sum(&analysis, "npa"), metric(&analysis, "npa")); - assert_eq!(evidence_sum(&analysis, "npm"), metric(&analysis, "npm")); - assert_eq!(evidence_sum(&analysis, "npa"), 2.0); - assert_eq!(evidence_sum(&analysis, "npm"), 1.0); - assert!( - analysis - .contributions - .iter() - .any(|item| item.reason.as_str() == "powershell.npa.class_property_definition") - ); - assert!( - analysis - .contributions - .iter() - .any(|item| item.reason.as_str() == "powershell.npm.class_method_definition") - ); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in ["cyclomatic", "cognitive.sum", "nexit", "abc", "nom"] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} - -#[test] -fn cognitive_amounts_carry_nesting_depth() { - // A doubly-nested `if` pays nesting+1 = 2 on the inner node — - // the §5.4 "why did cognitive move +2 here" answer. - let source = "\ -function Test-Nesting($a, $b) { - if ($a) { - if ($b) { - return 1 - } - } - return 2 -} -"; - let analysis = analyze(source, &AnalysisConfig::production()); - let cognitive: Vec = analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == "cognitive.sum") - .map(|item| item.amount) - .collect(); - assert_eq!(cognitive, vec![1.0, 2.0]); - assert_eq!(metric(&analysis, "cognitive.sum"), 3.0); -} diff --git a/crates/mehen-powershell/tests/cyclomatic.rs b/crates/mehen-powershell/tests/cyclomatic.rs deleted file mode 100644 index 0f675a8b..00000000 --- a/crates/mehen-powershell/tests/cyclomatic.rs +++ /dev/null @@ -1,205 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell cyclomatic-complexity tests, ported from -//! `src/metrics/cyclomatic.rs::tests` per rewrite plan §8.2. -//! -//! Each test runs [`PowerShellAnalyzer`] over a script and asserts the -//! `cyclomatic` family object rendered by -//! [`mehen_report::metrics_json::cyclomatic`] (the JSON shape used by -//! `mehen metrics --format json`, plan §9.1). The expected snapshot -//! strings are copied verbatim from the corresponding pre-1.0 tests, so -//! a difference here is a numeric regression — not a representation -//! drift. -//! -//! Decision-point classification mirrors the original -//! `Cyclomatic for PowershellCode`: `if`/`elseif`/loops/`switch_clause`/ -//! `catch_clause`/`trap_statement`, v7 ternary `?` and null-coalesce -//! `??` (operator + argument forms), short-circuit `&&` / `||`, and -//! logical `-and` / `-or`. `-xor` is intentionally excluded (Sonar's -//! rule: only short-circuit operators introduce a new path). - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, source.to_string()); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_simple_function() { - let a = analyze( - "function Greet($name) { # +2 (+1 unit, +1 function) - if ($name) { # +1 - Write-Host \"hi, $name\" - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cyclomatic(&a.root.metrics), - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - "### - ); -} - -#[test] -fn powershell_counts_each_switch_clause() { - // The `switch` statement itself does NOT add a decision; each - // `switch_clause` does. Aligns with Sonar's general cyclomatic rule. - let a = analyze( - "function Grade($score) { - switch ($score) { - 1 { 'A' } - 2 { 'B' } - 3 { 'C' } - default { 'F' } - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cyclomatic(&a.root.metrics), - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - } - "### - ); -} - -#[test] -fn powershell_short_circuit_and_word_form_boolean_operators() { - // PowerShell has two boolean operator pairs: - // - short-circuit `&&` / `||` (inside `pipeline_chain`) - // - logical `-and` / `-or` / `-xor` (inside `logical_expression`) - // Each occurrence contributes +1. - let a = analyze( - "function Check($a, $b, $c) { # +2 (+1 unit, +1 function) - if ($a -and $b -or $c) { # +3 (+1 if, +1 -and, +1 -or) - return $true - } - return $false - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cyclomatic(&a.root.metrics), - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - "### - ); -} - -#[test] -fn powershell_ternary_and_null_coalesce_wrappers_do_not_false_trigger() { - // Regression: tree-sitter-pwsh emits `ternary_expression`, - // `null_coalesce_expression`, and `logical_expression` as wrapper - // kinds in the precedence cascade even for plain expressions like - // `$a + $b`. Those wrappers must NOT contribute to cyclomatic; only - // the real `?` / `??` / `-and` / `-or` operator tokens do. - let a = analyze( - "function Plain { # +2 (+1 unit, +1 function) - $x = $a + $b # no decision point - return $x # no decision point - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cyclomatic(&a.root.metrics), - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0 - } - "### - ); -} - -#[test] -fn powershell_real_ternary_and_null_coalesce_count() { - // Real `?` / `??` expressions add one decision each. - let a = analyze( - "$a = $cond ? 1 : 2 # +1 ternary - $b = $x ?? 0 # +1 null-coalesce", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cyclomatic(&a.root.metrics), - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 3.0, - "max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_argument_form_ternary_and_null_coalesce_count() { - // Regression: tree-sitter-pwsh emits a parallel family of - // `*_argument_expression` kinds for expressions that live inside a - // method-invocation `argument_list` (e.g. - // `[Foo]::Bar($cond ? 1 : 2)`). Those argument-form decision - // operators must count the same as their regular-form twins. - let a = analyze( - "function F($a, $b, $x, $cond) { # +2 (+1 unit, +1 function) - [Foo]::Bar($a -eq $b) # comparison: no decision - [Foo]::Baz($cond ? 1 : 2) # +1 ternary - [Foo]::Qux($x ?? 3) # +1 null-coalesce - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cyclomatic(&a.root.metrics), - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_xor_is_not_a_cyclomatic_decision_point() { - // Regression: `-xor` is intentionally excluded from the cyclomatic - // decision-point set. Sonar's cyclomatic rule counts only - // *short-circuit* boolean operators across every language it - // analyzes; `-xor` always evaluates both operands so it cannot - // introduce a new control-flow path. `-and` / `-or` are counted - // because they short-circuit. - let a = analyze( - "function f($a, $b, $c) { - if ($a -xor $b) { } # +1 if, NOT +1 -xor - if ($a -and $b) { } # +1 if, +1 -and - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::cyclomatic(&a.root.metrics), - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - "### - ); -} diff --git a/crates/mehen-powershell/tests/exit.rs b/crates/mehen-powershell/tests/exit.rs deleted file mode 100644 index a1c95534..00000000 --- a/crates/mehen-powershell/tests/exit.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell NExit tests, ported from -//! `src/metrics/exit.rs::tests` per rewrite plan §8.2. -//! -//! NExit counts function exit points: `return`, `throw`, `exit`. In -//! tree-sitter-pwsh those are children of `flow_control_statement` — -//! the language analyzer inspects `child(0)`'s kind to disambiguate. -//! `break` / `continue` are loop-local control flow and are not exits -//! (mirrors the Ruby `break`/`next` vs. `return` convention). -//! -//! Snapshots are byte-identical to the pre-1.0 `metric.nexits` strings. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, source.to_string()); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_return_throw_and_exit_count_as_exits() { - // 3 exits: throw + exit + return. - let a = analyze( - "function f($a) { - if ($a -lt 0) { - throw 'bad' - } - if ($a -gt 100) { - exit 1 - } - return $a - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nexits(&a.root.metrics), - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - } - "### - ); -} - -#[test] -fn powershell_break_and_continue_do_not_count_as_exits() { - // Like other languages in mehen, `break` / `continue` are loop-local - // control flow and must not count as function exits. - let a = analyze( - "function f { - foreach ($x in 1..10) { - if ($x -eq 5) { break } - if ($x -eq 3) { continue } - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nexits(&a.root.metrics), - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - } - "### - ); -} diff --git a/crates/mehen-powershell/tests/halstead.rs b/crates/mehen-powershell/tests/halstead.rs deleted file mode 100644 index 940c18a4..00000000 --- a/crates/mehen-powershell/tests/halstead.rs +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell Halstead tests, ported from -//! `src/metrics/halstead.rs::tests` per rewrite plan §8.2. - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, MetricValue, - SourceFile, -}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -fn metric(report: &LanguageAnalysis, key: &str) -> f64 { - match report.root.metrics.get(&MetricKey::new(key)).unwrap() { - MetricValue::Int(i) => i as f64, - MetricValue::Float(f) => f, - } -} - -#[test] -fn powershell_operator_wrappers_do_not_double_count() { - // Regression: tree-sitter-pwsh nests every operator leaf token (e.g. - // `-eq`, `-f`, `=`, `2>`) inside a named wrapper rule - // (`comparison_operator`, `format_operator`, `assignment_operator`, - // `file_redirection_operator`, `merging_redirection_operator`). The - // walker visits both wrapper and leaf — classifying both as - // operators would double-count. The classifier matches only the - // leaves. - let a = analyze("$x = $a -eq $b"); - // Operators: `=` and `-eq` → 2 distinct, 2 total. - // Operands: `$x`, `$a`, `$b` → 3 distinct, 3 total. - assert_eq!(metric(&a, "halstead.n1"), 2.0); - assert_eq!(metric(&a, "halstead.N1"), 2.0); - assert_eq!(metric(&a, "halstead.n2"), 3.0); - assert_eq!(metric(&a, "halstead.N2"), 3.0); - - // Same invariant for the format operator `-f`. - let b = analyze("$s = \"{0}\" -f $a"); - // Operators: `=` and `-f` → 2 distinct, 2 total. - assert_eq!(metric(&b, "halstead.n1"), 2.0); - assert_eq!(metric(&b, "halstead.N1"), 2.0); -} - -#[test] -fn powershell_function_and_command_names_count_as_operands() { - // The PowerShell operand set must include the identifier leaves - // that drive function declarations (`function_name`) and command - // invocations (`command_name`, `path_command_name_token`). Without - // them, Halstead N2 and volume are suppressed for cmdlet-heavy - // scripts. - - // Simple cmdlet call: `Get-Item /tmp` → operands are `Get-Item` - // and `/tmp` (a generic_token argument). - let a = analyze("Get-Item /tmp"); - assert_eq!(metric(&a, "halstead.n2"), 2.0); - assert_eq!(metric(&a, "halstead.N2"), 2.0); - - // Path-style command: `./build.sh arg1` → operands are - // `./build.sh` (a `path_command_name_token` leaf) and `arg1`. Must - // not double-count the `path_command_name` wrapper. - let b = analyze("./build.sh arg1"); - assert_eq!(metric(&b, "halstead.n2"), 2.0); - assert_eq!(metric(&b, "halstead.N2"), 2.0); - - // Function declaration: the `function_name` leaf counts once. - let c = analyze("function Greet { }"); - assert_eq!(metric(&c, "halstead.n2"), 1.0); - assert_eq!(metric(&c, "halstead.N2"), 1.0); -} - -#[test] -fn powershell_string_literals_count_as_operands() { - // Double-quoted ("expandable") and here-string double-quoted - // literals have no content-leaf node (their text lives inside the - // wrapper's byte range directly), so the `expandable_string_literal` - // / `expandable_here_string_literal` *wrapper* kinds themselves are - // classified as operands — matching the verbatim - // (single-quoted) branch. - // - // 4 distinct strings (`''`, `""`, `'hello'`, `"world"`) plus 4 - // distinct `$` variables (`$a..$d`) → n2 = 8. - let a = analyze( - "$a = '' - $b = \"\" - $c = 'hello' - $d = \"world\"", - ); - assert_eq!(metric(&a, "halstead.n2"), 8.0); - assert_eq!(metric(&a, "halstead.N2"), 8.0); - - // Empty expandable `""` on its own — n2 = 2 (the empty string + `$x`). - let b = analyze("$x = \"\""); - // Operators: `=` → n1=1, N1=1. - // Operands: `$x`, `""` → n2=2, N2=2. - assert_eq!(metric(&b, "halstead.n1"), 1.0); - assert_eq!(metric(&b, "halstead.N1"), 1.0); - assert_eq!(metric(&b, "halstead.n2"), 2.0); - assert_eq!(metric(&b, "halstead.N2"), 2.0); -} diff --git a/crates/mehen-powershell/tests/loc.rs b/crates/mehen-powershell/tests/loc.rs deleted file mode 100644 index 9763fb20..00000000 --- a/crates/mehen-powershell/tests/loc.rs +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell LOC tests, ported from -//! `src/metrics/loc.rs::tests` per rewrite plan §8.2. -//! -//! Snapshots are byte-identical to the pre-1.0 `metric.loc` strings. - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, MetricValue, - SourceFile, -}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - // Match the pre-1.0 `check_metrics` test helper: trim trailing - // whitespace/newlines and re-append a single `\n`. This is the - // shape the legacy parser sees, so SLOC line counting compares - // directly. - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -fn lloc(report: &LanguageAnalysis) -> f64 { - match report - .root - .metrics - .get(&MetricKey::new("loc.lloc")) - .unwrap() - { - MetricValue::Int(i) => i as f64, - MetricValue::Float(f) => f, - } -} - -#[test] -fn powershell_simple_loc() { - let a = analyze("# header\nfunction Greet($name) {\n Write-Host \"hi, $name\"\n}"); - insta::assert_json_snapshot!( - mehen_report::metrics_json::loc(&a.root.metrics), - @r###" - { - "sloc": 4.0, - "ploc": 3.0, - "lloc": 2.0, - "cloc": 1.0, - "blank": 0.0, - "sloc_average": 2.0, - "ploc_average": 1.5, - "lloc_average": 1.0, - "cloc_average": 0.5, - "blank_average": 0.0, - "sloc_min": 3.0, - "sloc_max": 3.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 3.0, - "ploc_max": 3.0, - "lloc_min": 2.0, - "lloc_max": 2.0, - "blank_min": 0.0, - "blank_max": 0.0 - } - "### - ); -} - -#[test] -fn powershell_comment_and_block_comment_are_counted_as_cloc() { - // `#` line comments and `<# ... #>` block comments both surface as - // the named `comment` node in tree-sitter-pwsh. - let a = analyze( - "<#\n Doc comment\n #>\n # inline comment\n $x = 1 # trailing comment", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::loc(&a.root.metrics), - @r###" - { - "sloc": 5.0, - "ploc": 1.0, - "lloc": 1.0, - "cloc": 5.0, - "blank": 0.0, - "sloc_average": 5.0, - "ploc_average": 1.0, - "lloc_average": 1.0, - "cloc_average": 5.0, - "blank_average": 0.0, - "sloc_min": 5.0, - "sloc_max": 5.0, - "cloc_min": 5.0, - "cloc_max": 5.0, - "ploc_min": 1.0, - "ploc_max": 1.0, - "lloc_min": 1.0, - "lloc_max": 1.0, - "blank_min": 0.0, - "blank_max": 0.0 - } - "### - ); -} - -#[test] -fn powershell_assignment_counts_as_one_lloc() { - let a = analyze("$x = 1\n$y = 2\n$z = 3"); - assert_eq!(lloc(&a), 3.0); -} diff --git a/crates/mehen-powershell/tests/nargs.rs b/crates/mehen-powershell/tests/nargs.rs deleted file mode 100644 index 17de60ff..00000000 --- a/crates/mehen-powershell/tests/nargs.rs +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell NArgs tests, ported from -//! `src/metrics/nargs.rs::tests` per rewrite plan §8.2. -//! -//! Drift from pre-1.0: `functions_min` / `closures_min` were `0.0` -//! in the legacy snapshots whenever the unit space had no own -//! function/closure args, because the unit's always-zero counter was -//! folded into the per-space minmax during finalize. The Phase-6 -//! `NargsStats` change (gate fold on `is_function`/`is_closure`) -//! restores the metric's intended definition: "minimum number of -//! arguments across function/closure spaces". Tests below carry the -//! corrected snapshots. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_function_counts_script_parameters() { - let a = analyze( - "function Add($a, $b) { - $a + $b - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 2.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 2.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - } - "### - ); -} - -#[test] -fn powershell_class_method_counts_method_parameters() { - let a = analyze( - "class C { - [int] Add([int]$a, [int]$b, [int]$c) { - return $a + $b + $c - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 3.0, - "total_closures": 0.0, - "average_functions": 3.0, - "average_closures": 0.0, - "total": 3.0, - "average": 3.0, - "functions_min": 3.0, - "functions_max": 3.0, - "closures_min": 0.0, - "closures_max": 0.0 - } - "### - ); -} - -#[test] -fn powershell_script_block_with_param_counts_as_closure() { - let a = analyze("$sb = { param($x, $y) $x + $y }"); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 0.0, - "total_closures": 2.0, - "average_functions": 0.0, - "average_closures": 2.0, - "total": 2.0, - "average": 2.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 2.0, - "closures_max": 2.0 - } - "### - ); -} - -#[test] -fn powershell_nested_closure_params_do_not_count_toward_outer_fn() { - // `function f($a) { $sb = { param($x, $y) ... } }` — `f` owns 1 - // function arg ($a) and the inner closure owns 2 closure args ($x, - // $y). Neither bleeds into the other counter. - let a = analyze( - "function f($a) { - $sb = { param($x, $y) $x + $y } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 1.0, - "total_closures": 2.0, - "average_functions": 1.0, - "average_closures": 2.0, - "total": 3.0, - "average": 1.5, - "functions_min": 1.0, - "functions_max": 1.0, - "closures_min": 2.0, - "closures_max": 2.0 - } - "### - ); -} diff --git a/crates/mehen-powershell/tests/nom.rs b/crates/mehen-powershell/tests/nom.rs deleted file mode 100644 index f46e25ad..00000000 --- a/crates/mehen-powershell/tests/nom.rs +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell NOM tests, ported from -//! `src/metrics/nom.rs::tests` per rewrite plan §8.2. -//! -//! Snapshots are byte-identical to the pre-1.0 `metric.nom` strings. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_nom_counts_functions_methods_and_script_block_closures() { - // 3 functions (f1, f2, M) + 1 closure (the `{ ... }` scriptblock). - let a = analyze( - "function f1 { } - function f2 { } - class C { - [void] M() { } - } - $sb = { param($x) $x + 1 }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nom(&a.root.metrics), - @r###" - { - "functions": 3.0, - "closures": 1.0, - "functions_average": 0.5, - "closures_average": 0.16666666666666666, - "total": 4.0, - "average": 0.6666666666666666, - "functions_min": 0.0, - "functions_max": 1.0, - "closures_min": 0.0, - "closures_max": 1.0 - } - "### - ); -} diff --git a/crates/mehen-powershell/tests/npa.rs b/crates/mehen-powershell/tests/npa.rs deleted file mode 100644 index 328d1475..00000000 --- a/crates/mehen-powershell/tests/npa.rs +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell NPA tests, ported from -//! `src/metrics/npa.rs::tests` per rewrite plan §8.2. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_npa_counts_all_properties_as_public_including_hidden() { - // PowerShell has no access-modifier equivalent to `private` / - // `protected`. The `hidden` keyword only suppresses a property - // from default Get-Member / IntelliSense; the property is still - // publicly accessible. Per about_Hidden: "hidden members are - // still public". NPA counts every property as public. - let a = analyze( - "class C { - [int]$a = 1 - hidden [int]$b = 2 - [int]$c = 3 - hidden [int]$d = 4 - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::npa(&a.root.metrics), - @r###" - { - "classes": 4.0, - "interfaces": 0.0, - "class_attributes": 4.0, - "interface_attributes": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 4.0, - "total_attributes": 4.0, - "average": 1.0 - } - "### - ); -} diff --git a/crates/mehen-powershell/tests/npm.rs b/crates/mehen-powershell/tests/npm.rs deleted file mode 100644 index 1a61a4c6..00000000 --- a/crates/mehen-powershell/tests/npm.rs +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell NPM tests, ported from -//! `src/metrics/npm.rs::tests` per rewrite plan §8.2. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_npm_counts_all_methods_as_public_including_hidden() { - // Same convention as NPA: PowerShell has no `private` / - // `protected`; `hidden` only suppresses Get-Member output. NPM - // counts every method as public. - let a = analyze( - "class C { - [void] A() { } - hidden [void] B() { } - [void] Cm() { } - hidden [void] D() { } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::npm(&a.root.metrics), - @r###" - { - "classes": 4.0, - "interfaces": 0.0, - "class_methods": 4.0, - "interface_methods": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 4.0, - "total_methods": 4.0, - "average": 1.0 - } - "### - ); -} diff --git a/crates/mehen-powershell/tests/wmc.rs b/crates/mehen-powershell/tests/wmc.rs deleted file mode 100644 index aa44c50e..00000000 --- a/crates/mehen-powershell/tests/wmc.rs +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! PowerShell WMC tests, ported from -//! `src/metrics/wmc.rs::tests` per rewrite plan §8.2. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, SourceFile}; -use mehen_powershell::PowerShellAnalyzer; - -fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PowerShellAnalyzer::new(); - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let file = SourceFile::new("foo.ps1".into(), Language::PowerShell, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn powershell_wmc_class_sums_method_cyclomatics() { - // class C: A cyc = 2 (if), B cyc = 1 → classes = 3. - let a = analyze( - "class C { - [int] A([int]$x) { - if ($x -gt 0) { - return 1 - } - return 0 - } - [int] B() { return 1 } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::wmc(&a.root.metrics), - @r###" - { - "classes": 3.0, - "interfaces": 0.0, - "total": 3.0 - } - "### - ); -} diff --git a/crates/mehen-python/Cargo.toml b/crates/mehen-python/Cargo.toml deleted file mode 100644 index 04acdf07..00000000 --- a/crates/mehen-python/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "mehen-python" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — Python language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -# Ruff — replaces tree-sitter-python for this analyzer. Pinned here -# (not in `[workspace.dependencies]`) because `mehen-python` is the -# only consumer. Ruff's parser / AST / text-size crates are -# unpublished upstream (`publish = false`), so we pin a tagged git -# revision. All three crates must stay in lockstep so derive macros -# and AST types align — bump them together. -ruff_python_parser = { git = "https://github.com/astral-sh/ruff", tag = "0.16.1" } -ruff_python_ast = { git = "https://github.com/astral-sh/ruff", tag = "0.16.1" } -ruff_text_size = { git = "https://github.com/astral-sh/ruff", tag = "0.16.1" } -smol_str = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-python/src/analyzer.rs b/crates/mehen-python/src/analyzer.rs deleted file mode 100644 index fdeccf06..00000000 --- a/crates/mehen-python/src/analyzer.rs +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, ParseDiagnostic, - Result, SourceFile, SourceSpan, byte_offset_clamped, -}; -use mehen_metrics::{MetricEvidence, MetricTreeBuilder}; -use ruff_python_parser::parse_module; - -use crate::walker::walk_module; - -/// Ruff-backed Python analyzer (Phase 6, see `docs/python-ruff-spec.md`). -/// -/// Replaces the tree-sitter-python analyzer with `ruff_python_parser` + -/// `ruff_python_ast`. The Ruff AST is richer than the tree-sitter CST in -/// ways that change a small number of metrics — every drift is justified -/// from the metric definition rather than from a desire to mirror the -/// legacy walker. See the spec doc for the full ledger. -pub struct PythonAnalyzer; - -impl PythonAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for PythonAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for PythonAnalyzer { - fn language(&self) -> Language { - Language::Python - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::PythonRuff - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - let parsed = match parse_module(source.text.as_str()) { - Ok(p) => p, - Err(err) => { - let span = SourceSpan { - start_byte: 0, - end_byte: byte_offset_clamped(source.text.len()), - start_line: 1, - end_line: source.line_index.line_count(), - }; - let mut tree = MetricTreeBuilder::new(span); - let _ = tree.metrics_mut(); - return Ok(LanguageAnalysis { - language: Language::Python, - backend: AnalysisBackend::PythonRuff, - diagnostics: vec![ParseDiagnostic::fatal( - "python.parse_error", - format!("ruff_python_parser failed: {err}"), - )], - root: tree.finish(), - contributions: Vec::new(), - }); - } - }; - - let mut evidence = MetricEvidence::new("python", config.emit_contributions); - let root = walk_module(&parsed, &source.text, &source.line_index, &mut evidence); - // Recovered Ruff syntax errors are surfaced as `error` (not - // `warning`) so the diagnostic contract (plan §9.3) treats the - // analysis as incomplete: `mehen metrics` exits 1 and - // `analyze_diff` records the file under `analysis_errors`. - let diagnostics = parsed - .errors() - .iter() - .map(|e| ParseDiagnostic::error("python.syntax_error", format!("{}", e))) - .collect(); - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::Python, - backend: AnalysisBackend::PythonRuff, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, Language, MetricKey, SourceFile, SpaceKind}; - use mehen_metrics::keys; - - fn analyze(source: &str) -> LanguageAnalysis { - let analyzer = PythonAnalyzer::new(); - let file = SourceFile::new("test.py".into(), Language::Python, source.to_string()); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() - } - - #[test] - fn empty_file_yields_root_unit() { - let a = analyze(""); - assert_eq!(a.root.kind, SpaceKind::Unit); - assert!(a.root.spaces.is_empty()); - } - - #[test] - fn def_creates_function_space() { - let a = analyze("def foo():\n pass\n"); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Function); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("foo")); - } - - #[test] - fn class_creates_class_space_with_method() { - let a = analyze("class C:\n def m(self):\n pass\n"); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("C")); - assert_eq!(a.root.spaces[0].spaces.len(), 1); - assert_eq!(a.root.spaces[0].spaces[0].kind, SpaceKind::Function); - } - - #[test] - fn cyclomatic_counts_decision_points() { - // Function: 1 (base) + if + or + elif = 4 - let a = - analyze("def f(x):\n if x or x:\n return 1\n elif x:\n return 2\n"); - let func = &a.root.spaces[0]; - let cyclomatic = func - .metrics - .get(&MetricKey::new(keys::CYCLOMATIC)) - .unwrap() - .as_f64(); - assert!(cyclomatic >= 4.0, "expected >= 4, got {cyclomatic}"); - } -} diff --git a/crates/mehen-python/src/lib.rs b/crates/mehen-python/src/lib.rs deleted file mode 100644 index 67bd78db..00000000 --- a/crates/mehen-python/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-python` — Python language analyzer. -//! -//! Phase 6 implementation: Ruff-backed analyzer (`ruff_python_parser` + -//! `ruff_python_ast`). The crate exposes one analyzer -//! (`PythonAnalyzer`) so the engine registry dispatches `Language::Python` -//! to it directly. -//! -//! tree-sitter-python is no longer a dependency of this crate — per -//! `docs/python-ruff-spec.md`, every metric is computed from the Ruff -//! AST and Ruff's lexer token stream. Python-specific behavior (type -//! annotations as runtime objects, docstrings, `match`/`case`, -//! exception groups, comprehensions) is documented in that spec. - -#![forbid(unsafe_code)] - -mod analyzer; -mod walker; - -pub use analyzer::PythonAnalyzer; diff --git a/crates/mehen-python/src/walker.rs b/crates/mehen-python/src/walker.rs deleted file mode 100644 index 1800db71..00000000 --- a/crates/mehen-python/src/walker.rs +++ /dev/null @@ -1,1186 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Ruff AST + token-stream walker that produces a populated `MetricSpace`. -//! -//! Recursion is driven by ruff's -//! [`SourceOrderVisitor`](ruff_python_ast::visitor::source_order::SourceOrderVisitor): -//! we override the per-shape hooks where a metric side effect or a -//! lifecycle boundary (open/close space, push/pop cognitive context) is -//! required, and let the default `walk_*` helpers handle the rest of the -//! descent. The walker follows the same per-space `State` accumulator -//! pattern used by `mehen-typescript` and `mehen-php`: one `State` per -//! opened space, finalize on close, fold child stats into parent. -//! -//! Python-specific design decisions are documented in -//! `docs/python-ruff-spec.md`. The short version: -//! -//! - **Type annotations and default-value expressions**: in Python, type -//! annotations are runtime-accessible objects (Pydantic, dataclasses, -//! `typing.get_type_hints`, etc.). Tokens inside an annotation -//! subtree are treated like ordinary tokens for Halstead — they ARE -//! operands and operators in the running program. This is a deliberate -//! semantic difference from `mehen-typescript`, where TS-only type -//! metadata is excluded because TS types are erased at runtime. -//! -//! - **Docstrings**: a string literal that is the *first statement of a -//! module / class / function body* is a docstring per PEP 257 — a -//! structural language feature, not arbitrary code. We do not emit -//! Halstead operators/operands for docstring tokens, but the LOC -//! accounting still counts those lines as `cloc` (comment-like) per -//! the legacy convention. -//! -//! - **`match`/`case`**: every `case` clause is a cyclomatic decision -//! point and a cognitive nesting bump. The Python `match` statement -//! is a structural pattern match, so each case is a real branch. -//! -//! - **Exception groups (`try*`/`except*`)**: an `except*` handler still -//! counts the same as a regular `except` — both add a decision and a -//! nesting level; the underlying `is_star: bool` flag on `StmtTry` is -//! noted for evidence but does not change the metric output. - -use mehen_core::{LineIndex, MetricSpace, SourceSpan, SpaceKind}; -use mehen_metrics::{ - ContainerKind, HalsteadOperand, HalsteadOperator, MetricEvidence, MetricTreeBuilder, - SpaceRangeTracker, State, apply_state_to, close_space, finalize_state, -}; -use ruff_python_ast::token::TokenKind; -use ruff_python_ast::visitor::source_order::{SourceOrderVisitor, walk_expr, walk_stmt}; -use ruff_python_ast::{ - self as ast, BoolOp, Comprehension, ElifElseClause, ExceptHandler, Expr, MatchCase, ModModule, - Stmt, UnaryOp, -}; -use ruff_python_parser::Parsed; -use ruff_text_size::{Ranged, TextRange}; -use smol_str::SmolStr; - -/// Drive the walker over a parsed Python module. Crate-internal entry -/// point — only `mehen_python::PythonAnalyzer::analyze` calls this; not -/// part of any cross-crate API. Contribution evidence is recorded into -/// the caller-owned `evidence` sink (plan §5.4). -pub(crate) fn walk_module( - parsed: &Parsed, - source: &str, - line_index: &LineIndex, - evidence: &mut MetricEvidence, -) -> MetricSpace { - let module = parsed.syntax(); - let unit_span = SourceSpan { - start_byte: module.range.start().to_u32(), - end_byte: module.range.end().to_u32(), - start_line: line_index.line_at(module.range.start().to_u32()), - end_line: line_index.line_at(module.range.end().to_u32()), - }; - - let mut visitor = Visitor::new(source, line_index, unit_span, evidence); - visitor.record_module_docstring(&module.body); - visitor.visit_body(&module.body); - - visitor.emit_halstead_from_tokens(parsed.tokens()); - - visitor.finish() -} - -struct Visitor<'a> { - source: &'a str, - line_index: &'a LineIndex, - tree: MetricTreeBuilder, - /// Per-space accumulator stack — index 0 is the unit. - stack: Vec, - /// Parallel to `stack`: the SpaceKind of each frame so we can tell - /// "what's the enclosing class-like" without re-walking. - kinds: Vec, - /// Cognitive context inherited down the recursion. Mirrors the - /// legacy `(nesting, depth, lambda)` triple from - /// `mehen-engine/src/legacy/metrics/cognitive.rs::python` — - /// Python increments `lambda` only inside an `ExprLambda` and the - /// boolean-sequence reset rules apply to expression statements. - cognitive: CognitiveContext, - /// Byte ranges of nodes whose tokens should NOT contribute to the - /// Halstead token sweep. Currently this is only docstring spans - /// (per PEP 257). Type annotation spans are NOT added here because - /// Python types are runtime-accessible — see crate docs. - docstring_ranges: Vec, - /// Routes Halstead tokens emitted by the post-AST sweep to the - /// deepest enclosing function/class/lambda space. Without this, - /// nested-scope Halstead numbers are zero in the per-space JSON - /// even though the unit rollup is correct (PR #95 - /// discussion_r3265658502). - halstead_routing: SpaceRangeTracker, - /// Contribution-evidence sink (plan §5.4). Record methods are - /// no-ops when disabled; call sites go through - /// [`Visitor::record_evidence`] so spans are only computed when - /// the sink is enabled. - evidence: &'a mut MetricEvidence, -} - -#[derive(Clone, Copy, Debug, Default)] -struct CognitiveContext { - nesting: u32, - depth: u32, - lambda: u32, - /// Depth of nested `BoolOp` expressions. Used by the BoolOp handler - /// to detect the *outermost* boolean operator inside a statement — - /// only that one gets the legacy "lambda ancestor" bonus - /// (mehen-engine cognitive.rs:281 `count_specific_ancestors` to - /// detect outermost-up-to-Lambda-boundary). - bool_op_depth: u32, -} - -impl<'a> Visitor<'a> { - fn new( - source: &'a str, - line_index: &'a LineIndex, - unit_span: SourceSpan, - evidence: &'a mut MetricEvidence, - ) -> Self { - let mut state = State::new(); - state.loc.set_span( - unit_span.start_line.saturating_sub(1), - unit_span.end_line.saturating_sub(1), - true, - ); - Self { - source, - line_index, - tree: MetricTreeBuilder::new(unit_span), - stack: vec![state], - kinds: vec![SpaceKind::Unit], - cognitive: CognitiveContext::default(), - docstring_ranges: Vec::new(), - halstead_routing: SpaceRangeTracker::new(), - evidence, - } - } - - /// Record contribution evidence for `range`. The span is only - /// computed when the sink is enabled, so call sites can invoke - /// this unconditionally next to each stat increment (mirrors - /// `WalkerCtx::record_evidence` in `mehen-tree-sitter`). - #[inline] - fn record_evidence(&mut self, range: TextRange, record: F) - where - F: FnOnce(&mut MetricEvidence, SourceSpan), - { - if self.evidence.is_enabled() { - let span = text_range_to_source_span(range, self.line_index); - record(self.evidence, span); - } - } - - fn current(&mut self) -> &mut State { - self.stack.last_mut().expect("walker stack empty") - } - - fn parent_kind(&self) -> SpaceKind { - self.kinds.last().cloned().unwrap_or(SpaceKind::Unit) - } - - fn finish(mut self) -> MetricSpace { - let mut unit_state = self.stack.pop().expect("walker stack underflow"); - finalize_state(&mut unit_state); - // Route post-AST tokens (Halstead operator/operand events, - // PLOC code-lines, comment lines) to nested spaces. The unit - // builder + LocStats are taken out of `unit_state` so the - // tracker can accumulate fall-through events into them; the - // routing pass also propagates each child's counts up the - // parent chain so the unit ends up with the file-wide rollup. - let mut unit_halstead = std::mem::take(&mut unit_state.halstead); - let mut unit_loc = std::mem::take(&mut unit_state.loc); - let mut tree = self.tree.finish(); - self.halstead_routing - .finalize_into_tree(&mut tree, &mut unit_halstead, &mut unit_loc); - unit_state.halstead = unit_halstead; - unit_state.loc = unit_loc; - // Re-run the unit publish so its Halstead, LOC, and MI keys - // reflect the rolled-up values that include token-driven - // events routed to nested scopes. - apply_state_to(unit_state, &mut tree.metrics); - tree - } - - fn record_module_docstring(&mut self, body: &[Stmt]) { - if let Some(span) = leading_docstring_range(body) { - self.docstring_ranges.push(span); - } - } - - fn open_space(&mut self, kind: SpaceKind, range: TextRange, name: Option) { - let mut child = State::for_opened_space(kind.clone()); - let start_row = self - .line_index - .line_at(range.start().to_u32()) - .saturating_sub(1); - let end_row = self - .line_index - .line_at(range.end().to_u32()) - .saturating_sub(1); - child.loc.set_span(start_row, end_row, false); - - let span = text_range_to_source_span(range, self.line_index); - let space_id = self.tree.open(kind.clone(), span, name); - // Record the byte range so the post-AST Halstead token sweep - // can route tokens to this scope. - self.halstead_routing - .record_open(space_id, range.start().to_u32(), range.end().to_u32()); - self.stack.push(child); - self.kinds.push(kind); - } - - fn close_space(&mut self) { - close_space( - &mut self.stack, - &mut self.kinds, - &mut self.tree, - &mut self.halstead_routing, - ); - } - - fn enter_function(&mut self, func: &'a ast::StmtFunctionDef) { - // Python decorators: each `@decorator` is in itself an extra - // expression that runs at definition time. The legacy walker - // records them as part of the enclosing space's metric stream - // (decorators land in the *enclosing* class/unit). We follow - // that by visiting decorators *before* opening the function - // space. - for decorator in &func.decorator_list { - self.visit_expr(&decorator.expression); - } - - self.open_space( - SpaceKind::Function, - func.range, - Some(func.name.id.as_str().to_string()), - ); - let argc = func.parameters.len() as u32; - self.current().nargs.record_function_args(argc); - // NOM is recorded inside `State::for_opened_space(Function)` - // (called by `open_space`); the evidence for both families is - // attached here, at the site that opened the space. - self.record_evidence(func.range, |e, s| e.function(s, "stmt_function_def")); - self.record_evidence(func.range, |e, s| { - e.function_args(s, argc, "stmt_function_def") - }); - - // Cognitive — function entry resets nesting/lambda and bumps - // depth when nested inside another function. - let mut ctx = self.cognitive; - let nested = self - .kinds - .iter() - .rev() - .skip(1) - .any(|k| matches!(k, SpaceKind::Function)); - ctx.nesting = 0; - ctx.lambda = 0; - if nested { - ctx.depth = ctx.depth.saturating_add(1); - } - let saved = self.cognitive; - self.cognitive = ctx; - - // Walk parameters (defaults / annotations contribute Halstead / - // ABC against the function's own state — Python evaluates these - // at definition time but they belong to the function's - // signature). The default `visit_parameters` walks defaults + - // annotations through `visit_expr` — exactly what we want. - self.visit_parameters(&func.parameters); - - // Capture the leading docstring so it does not contribute to - // Halstead via the token sweep. - if let Some(span) = leading_docstring_range(&func.body) { - self.docstring_ranges.push(span); - } - - self.visit_body(&func.body); - - self.cognitive = saved; - self.close_space(); - } - - fn enter_class(&mut self, class: &'a ast::StmtClassDef) { - for decorator in &class.decorator_list { - self.visit_expr(&decorator.expression); - } - // Class arguments (base classes, metaclass=...) live in the - // enclosing scope, not in the class body — they execute at - // definition time. - if let Some(args) = class.arguments.as_deref() { - self.visit_arguments(args); - } - - self.open_space( - SpaceKind::Class, - class.range, - Some(class.name.id.as_str().to_string()), - ); - - if let Some(span) = leading_docstring_range(&class.body) { - self.docstring_ranges.push(span); - } - - for stmt in &class.body { - // Class-body assignments — `name: T = value` (StmtAnnAssign) - // and `name = value` (StmtAssign with bare-identifier - // target) — count as class attributes (NPA). Method-style - // `def f(self):` inside a class body counts as a method - // (NPM). We classify here because the AnnAssign / Assign - // context (top-level of class body) matters. - self.classify_class_body_member(stmt); - self.visit_stmt(stmt); - } - - self.close_space(); - } - - fn classify_class_body_member(&mut self, stmt: &Stmt) { - let parent = self.parent_kind(); - if !matches!( - parent, - SpaceKind::Class | SpaceKind::Impl | SpaceKind::Interface | SpaceKind::Trait - ) { - return; - } - match stmt { - Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) => { - if let Expr::Name(name) = target.as_ref() { - let is_public = python_attribute_is_public(name.id.as_str()); - self.current() - .npa - .record_attribute(ContainerKind::Class, is_public); - // NPA headline counts public members only — evidence - // follows suit and skips non-public names. - if is_public { - self.record_evidence(name.range, |e, s| { - e.public_attribute(s, "stmt_ann_assign"); - }); - } - } - } - Stmt::Assign(ast::StmtAssign { targets, .. }) => { - for tgt in targets { - if let Expr::Name(name) = tgt { - let is_public = python_attribute_is_public(name.id.as_str()); - self.current() - .npa - .record_attribute(ContainerKind::Class, is_public); - if is_public { - self.record_evidence(name.range, |e, s| { - e.public_attribute(s, "stmt_assign"); - }); - } - } - } - } - Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => { - let is_public = python_method_is_public(name.id.as_str()); - self.current() - .npm - .record_method(ContainerKind::Class, is_public); - if is_public { - self.record_evidence(stmt.range(), |e, s| { - e.public_method(s, "stmt_function_def"); - }); - } - } - _ => {} - } - } - - fn enter_lambda(&mut self, lam: &'a ast::ExprLambda) { - self.open_space(SpaceKind::Closure, lam.range, None); - let argc = lam - .parameters - .as_deref() - .map(|p| p.len() as u32) - .unwrap_or(0); - self.current().nargs.record_closure_args(argc); - // NOM is recorded inside `State::for_opened_space(Closure)` - // (called by `open_space`); evidence attaches here. - self.record_evidence(lam.range, |e, s| e.closure(s, "expr_lambda")); - self.record_evidence(lam.range, |e, s| e.closure_args(s, argc, "expr_lambda")); - - let mut ctx = self.cognitive; - ctx.lambda = ctx.lambda.saturating_add(1); - let saved = self.cognitive; - self.cognitive = ctx; - - if let Some(params) = lam.parameters.as_deref() { - self.visit_parameters(params); - } - self.visit_expr(&lam.body); - - self.cognitive = saved; - self.close_space(); - } - - fn observe_loc_for_stmt(&mut self, stmt: &Stmt) { - let range = stmt.range(); - let start_row = self - .line_index - .line_at(range.start().to_u32()) - .saturating_sub(1); - let cur = self.current(); - // LLOC: only "actionable" statements. Container statements - // (`def`, `class`) are not LLOC per the legacy - // `legacy/metrics/loc.rs::PythonCode::compute` enumeration — - // their bodies contain the lloc-bumping nodes. Match expr and - // bare keywords (`pass`/`break`/etc.) are still bumped via the - // generic `Stmt::*` arm. - let is_lloc = !matches!( - stmt, - Stmt::FunctionDef(_) | Stmt::ClassDef(_) | Stmt::TypeAlias(_) - ); - if is_lloc { - cur.loc.observe_lloc(); - } - cur.loc.observe_code_line(start_row); - } - - /// Token-stream Halstead emission — runs after the AST walk. - /// - /// Each Ruff token is mapped to one of `Operator(kind)`, - /// `Operand(kind)`, or `Skip`. Tokens whose span falls inside a - /// recorded docstring are skipped entirely. Type annotations and - /// default values are NOT skipped — Python types are runtime - /// objects, not erased metadata. - fn emit_halstead_from_tokens(&mut self, tokens: &ruff_python_ast::token::Tokens) { - // Sort docstring ranges so a binary scan is cheap. - self.docstring_ranges.sort_by_key(|r| r.start()); - - for tok in tokens.iter() { - let span = tok.range(); - - // LOC: comment tokens contribute to `cloc`. Routed to the - // deepest enclosing scope so per-space `loc.cloc` reflects - // comments inside that scope's body; lines outside every - // recorded scope go into the unit. The legacy walker - // (`legacy/metrics/loc.rs::PythonCode::compute`) matched - // the `Comment` node and called `add_cloc_lines`; the - // equivalent here is `observe_comment` (Python comments - // are always single-line). - if matches!(tok.kind(), TokenKind::Comment) { - let start_row = self - .line_index - .line_at(span.start().to_u32()) - .saturating_sub(1); - let end_row = self - .line_index - .line_at(span.end().to_u32()) - .saturating_sub(1); - self.halstead_routing.observe_comment( - span.start().to_u32(), - span.end().to_u32(), - &mut self.stack[0].loc, - start_row, - end_row, - ); - } - - // Module-level docstrings are PEP 257 documentation, so - // their tokens are excluded from Halstead. The legacy - // walker also folded triple-quoted module/class/function - // docstrings into `cloc` via the `String` arm — apply the - // same here so cloc covers both `# …` line comments and - // top-of-body docstrings. Routed by span so a function's - // docstring lands on its space's `loc.cloc`. - if self.is_inside_docstring(span) - && matches!( - tok.kind(), - TokenKind::String | TokenKind::FStringStart | TokenKind::FStringEnd - ) - { - let start_row = self - .line_index - .line_at(span.start().to_u32()) - .saturating_sub(1); - let end_row = self - .line_index - .line_at(span.end().to_u32()) - .saturating_sub(1); - self.halstead_routing.observe_comment( - span.start().to_u32(), - span.end().to_u32(), - &mut self.stack[0].loc, - start_row, - end_row, - ); - } - - if self.is_inside_docstring(span) { - continue; - } - // Route Halstead events to the deepest enclosing - // function/class/lambda space so per-space JSON entries - // are non-zero (and the rolled-up unit values match). - // `route_through_tracker` falls back to the unit - // `HalsteadBuilder` when no recorded entry covers the - // token. - let s = span.start().to_u32(); - let e = span.end().to_u32(); - match classify_token(tok.kind()) { - TokenClass::Operator(kind) => { - self.halstead_routing.observe_operator( - s, - e, - &mut self.stack[0].halstead, - HalsteadOperator { - kind: SmolStr::new(kind), - text: None, - }, - ); - } - TokenClass::Operand(kind) => { - let text = self.source.get(s as usize..e as usize).unwrap_or(""); - self.halstead_routing.observe_operand( - s, - e, - &mut self.stack[0].halstead, - HalsteadOperand { - kind: SmolStr::new(kind), - text: Some(SmolStr::new(text)), - }, - ); - } - TokenClass::Skip => {} - } - } - } - - fn is_inside_docstring(&self, span: TextRange) -> bool { - self.docstring_ranges - .iter() - .any(|r| span.start() >= r.start() && span.end() <= r.end()) - } -} - -impl<'a> SourceOrderVisitor<'a> for Visitor<'a> { - fn visit_stmt(&mut self, stmt: &'a Stmt) { - // LOC accounting — every statement bumps lloc, and its starting - // line is a code line. - self.observe_loc_for_stmt(stmt); - - match stmt { - Stmt::FunctionDef(func) => { - self.enter_function(func); - } - Stmt::ClassDef(class) => { - self.enter_class(class); - } - Stmt::If(ast::StmtIf { - test, - body, - elif_else_clauses, - .. - }) => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(stmt.range(), |e, s| e.decision(s, "stmt_if")); - self.record_evidence(stmt.range(), |e, s| e.abc_condition(s, "stmt_if")); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(stmt.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "stmt_if"); - }); - // Match legacy `increase_nesting` (mehen-engine cognitive.rs:239): - // a new control-flow scope resets the boolean sequence so two - // sibling `if a and b: ...` blocks each contribute +1 for their - // own `and`, instead of collapsing into a single same-op run. - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - self.visit_expr(test); - self.visit_body(body); - // Elif/else clauses inherit the nesting bump from their - // owning `if` (legacy walks them as children of `if_statement`, - // so they see the parent's nesting via the nesting map). - // Keep `cognitive.nesting` raised while walking them. - for clause in elif_else_clauses { - self.visit_elif_else_clause(clause); - } - self.cognitive.nesting -= 1; - } - Stmt::For(ast::StmtFor { - target, - iter, - body, - orelse, - .. - }) => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(stmt.range(), |e, s| e.decision(s, "stmt_for")); - self.record_evidence(stmt.range(), |e, s| e.abc_condition(s, "stmt_for")); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(stmt.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "stmt_for"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - self.visit_expr(target); - self.visit_expr(iter); - self.visit_body(body); - self.cognitive.nesting -= 1; - if !orelse.is_empty() { - // `for ... else` — the else-branch runs only if - // the loop completed without `break`. Legacy treats - // the else-clause as +1 cyclomatic (a real branch - // that depends on `break` not firing). - self.current().cyclomatic.record_decision(); - self.current().cognitive.increment_by_one(); - self.current().abc.record_condition(); - if let Some(range) = body_range(orelse) { - self.record_evidence(range, |e, s| e.decision(s, "for_else")); - self.record_evidence(range, |e, s| e.cognitive(s, 1, "for_else")); - self.record_evidence(range, |e, s| e.abc_condition(s, "for_else")); - } - self.visit_body(orelse); - } - } - Stmt::While(ast::StmtWhile { - test, body, orelse, .. - }) => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(stmt.range(), |e, s| e.decision(s, "stmt_while")); - self.record_evidence(stmt.range(), |e, s| e.abc_condition(s, "stmt_while")); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(stmt.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "stmt_while"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - self.visit_expr(test); - self.visit_body(body); - self.cognitive.nesting -= 1; - if !orelse.is_empty() { - self.current().cyclomatic.record_decision(); - self.current().cognitive.increment_by_one(); - self.current().abc.record_condition(); - if let Some(range) = body_range(orelse) { - self.record_evidence(range, |e, s| e.decision(s, "while_else")); - self.record_evidence(range, |e, s| e.cognitive(s, 1, "while_else")); - self.record_evidence(range, |e, s| e.abc_condition(s, "while_else")); - } - self.visit_body(orelse); - } - } - Stmt::Try(ast::StmtTry { - body, - handlers, - orelse, - finalbody, - .. - }) => { - // `try` itself is a +1 nesting bump (cognitive only — - // legacy does not count the bare `try` for cyclomatic - // because the decision is in the handler). The `try` - // raises the nesting level for its body AND its - // except / else / finally branches (siblings in the - // Ruff AST, but children of the `try_statement` in - // tree-sitter — both should see the same nesting). - self.current().abc.record_condition(); - self.record_evidence(stmt.range(), |e, s| e.abc_condition(s, "stmt_try")); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(stmt.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "stmt_try"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - self.visit_body(body); - for handler in handlers { - self.visit_except_handler(handler); - } - if !orelse.is_empty() { - self.current().cognitive.increment_by_one(); - if let Some(range) = body_range(orelse) { - self.record_evidence(range, |e, s| e.cognitive(s, 1, "try_else")); - } - self.visit_body(orelse); - } - if !finalbody.is_empty() { - self.current().cognitive.increment_by_one(); - if let Some(range) = body_range(finalbody) { - self.record_evidence(range, |e, s| e.cognitive(s, 1, "try_finally")); - } - self.visit_body(finalbody); - } - self.cognitive.nesting -= 1; - } - Stmt::Match(ast::StmtMatch { subject, cases, .. }) => { - // `match` itself does not increment cyclomatic — each - // `case` does. ABC records `match` as a condition once - // (the match itself is a structural branch). - self.current().abc.record_condition(); - self.record_evidence(stmt.range(), |e, s| e.abc_condition(s, "stmt_match")); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(stmt.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "stmt_match"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - self.visit_expr(subject); - for case in cases { - self.visit_match_case(case); - } - self.cognitive.nesting -= 1; - } - Stmt::With(ast::StmtWith { items, body, .. }) => { - // `with` is not a cyclomatic decision (no branching), - // but it does add cognitive nesting (a structural - // scope) and one ABC condition equivalent. - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(stmt.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "stmt_with"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - for item in items { - self.visit_expr(&item.context_expr); - if let Some(opt_vars) = &item.optional_vars { - self.visit_expr(opt_vars); - } - } - self.visit_body(body); - self.cognitive.nesting -= 1; - } - Stmt::Return(ast::StmtReturn { value, .. }) => { - self.current().nexit.record_exit(); - self.record_evidence(stmt.range(), |e, s| e.exit(s, "stmt_return")); - if let Some(v) = value { - self.visit_expr(v); - } - } - Stmt::Raise(ast::StmtRaise { exc, cause, .. }) => { - self.current().nexit.record_exit(); - self.record_evidence(stmt.range(), |e, s| e.exit(s, "stmt_raise")); - if let Some(e) = exc { - self.visit_expr(e); - } - if let Some(c) = cause { - self.visit_expr(c); - } - } - Stmt::Assign(_) => { - self.current().abc.record_assignment(); - self.record_evidence(stmt.range(), |e, s| e.abc_assignment(s, "stmt_assign")); - walk_stmt(self, stmt); - } - Stmt::AugAssign(_) => { - self.current().abc.record_assignment(); - self.record_evidence(stmt.range(), |e, s| e.abc_assignment(s, "stmt_aug_assign")); - walk_stmt(self, stmt); - } - Stmt::AnnAssign(ast::StmtAnnAssign { value, .. }) => { - if value.is_some() { - self.current().abc.record_assignment(); - self.record_evidence(stmt.range(), |e, s| { - e.abc_assignment(s, "stmt_ann_assign"); - }); - } - walk_stmt(self, stmt); - } - Stmt::Expr(_) => { - // ExpressionStatement resets the boolean sequence (for - // cognitive complexity boolean-chain folding). - self.current().cognitive.boolean_seq.reset(); - walk_stmt(self, stmt); - } - Stmt::TypeAlias(_) => { - // `type X = Y` (PEP 695 type alias). The target is an - // assignment — count it once. - self.current().abc.record_assignment(); - self.record_evidence(stmt.range(), |e, s| e.abc_assignment(s, "stmt_type_alias")); - walk_stmt(self, stmt); - } - // Plain descent — defaults handle the children we'd visit - // anyway. Statements with no decision/assignment side - // effect: bare keywords (`pass`/`break`/`continue`), - // imports, name declarations (`global`/`nonlocal`), `del`, - // `assert`, IPython escape commands. - Stmt::Break(_) - | Stmt::Continue(_) - | Stmt::Pass(_) - | Stmt::Global(_) - | Stmt::Nonlocal(_) - | Stmt::Import(_) - | Stmt::ImportFrom(_) - | Stmt::Delete(_) - | Stmt::Assert(_) - | Stmt::IpyEscapeCommand(_) => { - walk_stmt(self, stmt); - } - } - } - - fn visit_expr(&mut self, expr: &'a Expr) { - match expr { - Expr::BoolOp(ast::ExprBoolOp { op, values, .. }) => { - let label = match op { - BoolOp::And => "and", - BoolOp::Or => "or", - }; - // Boolean `and` / `or` — each operand beyond the first - // is one decision point per legacy. Evidence spans point - // at the extra operand (Ruff's AST has no operator-token - // node to anchor to). - for value in values.iter().skip(1) { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(value.range(), |e, s| e.decision(s, label)); - self.record_evidence(value.range(), |e, s| e.abc_condition(s, label)); - } - // Lambda-ancestor bonus (legacy cognitive.rs:281): the - // *outermost* BoolOp inside a statement adds one structural - // unit per enclosing lambda. Inside `bar = lambda a: - // lambda b: b or True or True`, the `or` sequence sits - // inside two lambdas — legacy adds +2 to the per-space - // structural before the boolean-sequence collapser. - let lambda_bonus = if self.cognitive.bool_op_depth == 0 { - self.cognitive.lambda - } else { - 0 - }; - if lambda_bonus > 0 { - self.current().cognitive.record_increment(lambda_bonus); - self.record_evidence(expr.range(), |e, s| { - e.cognitive(s, lambda_bonus, "bool_op_lambda_bonus"); - }); - } - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean(label); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(expr.range(), |e, s| e.cognitive(s, delta, label)); - self.cognitive.bool_op_depth = self.cognitive.bool_op_depth.saturating_add(1); - for v in values { - self.visit_expr(v); - } - self.cognitive.bool_op_depth = self.cognitive.bool_op_depth.saturating_sub(1); - } - Expr::Named(_) => { - self.current().abc.record_assignment(); - self.record_evidence(expr.range(), |e, s| e.abc_assignment(s, "expr_named")); - walk_expr(self, expr); - } - Expr::UnaryOp(ast::ExprUnaryOp { op, .. }) => { - if matches!(op, UnaryOp::Not) { - self.current().cognitive.boolean_seq.not_operator("not"); - } - walk_expr(self, expr); - } - Expr::Lambda(lam) => { - self.enter_lambda(lam); - } - Expr::If(ast::ExprIf { - test, body, orelse, .. - }) => { - // Conditional expression `a if b else c` — one decision. - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(expr.range(), |e, s| e.decision(s, "expr_if")); - self.record_evidence(expr.range(), |e, s| e.abc_condition(s, "expr_if")); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(expr.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "expr_if"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - self.visit_expr(test); - self.visit_expr(body); - self.visit_expr(orelse); - self.cognitive.nesting -= 1; - } - Expr::Compare(ast::ExprCompare { comparators, .. }) => { - // Comparison ops (`==`, `<`, ...) — each pair counts as - // one ABC condition. Evidence spans point at the - // right-hand comparator of each pair. - for comparator in comparators.iter() { - self.current().abc.record_condition(); - self.record_evidence(comparator.range(), |e, s| { - e.abc_condition(s, "expr_compare"); - }); - } - walk_expr(self, expr); - } - Expr::Call(_) => { - self.current().abc.record_branch(); - self.record_evidence(expr.range(), |e, s| e.abc_branch(s, "expr_call")); - walk_expr(self, expr); - } - // Halstead-wise, `a.b` is two operand tokens (`a` and `b`) - // plus one operator (`.`) — exactly what the lexer emits. - // We do NOT emit an extra "attribute" operand for the - // joined chain text; doing so would triple-count the same - // syntactic structure (legacy Python tree-sitter walker - // also did not emit such an entry, see - // `crates/mehen-engine/src/legacy/getter.rs` — `Attribute` - // is not in the operand match arms). The default - // `walk_expr` descends into `value` and visits the `attr` - // identifier as a no-op, which is exactly what we want. - // - // Everything else (BinOp, Subscript/Starred, Tuple/List/ - // Set/Slice/Dict, comprehensions, Await/Yield, FString/ - // TString, atomic literals, Name) is structural-only — - // defaults give us the same recursion we used to do - // manually. - _ => walk_expr(self, expr), - } - } - - fn visit_elif_else_clause(&mut self, clause: &'a ElifElseClause) { - // Elif: +1 cyclomatic (the chained condition is a real branch), - // +1 cognitive (no nesting bump — its cost is paid by the outer - // `if`), reset the boolean sequence. - // Else: +1 cognitive only — no cyclomatic increment because the - // else branch isn't a separate decision (the if already picked - // a branch). - if clause.test.is_some() { - self.current().cyclomatic.record_decision(); - self.current().cognitive.increment_by_one(); - self.current().cognitive.boolean_seq.reset(); - self.current().abc.record_condition(); - self.record_evidence(clause.range, |e, s| e.decision(s, "elif_clause")); - self.record_evidence(clause.range, |e, s| e.cognitive(s, 1, "elif_clause")); - self.record_evidence(clause.range, |e, s| e.abc_condition(s, "elif_clause")); - } else { - self.current().cognitive.increment_by_one(); - self.current().abc.record_condition(); - self.record_evidence(clause.range, |e, s| e.cognitive(s, 1, "else_clause")); - self.record_evidence(clause.range, |e, s| e.abc_condition(s, "else_clause")); - } - if let Some(test) = &clause.test { - self.visit_expr(test); - } - self.visit_body(&clause.body); - } - - fn visit_except_handler(&mut self, handler: &'a ExceptHandler) { - let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) = - handler; - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(handler.range(), |e, s| e.decision(s, "except_handler")); - self.record_evidence(handler.range(), |e, s| e.abc_condition(s, "except_handler")); - let effective = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(handler.range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "except_handler"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - if let Some(t) = type_ { - self.visit_expr(t); - } - self.visit_body(body); - self.cognitive.nesting -= 1; - } - - fn visit_match_case(&mut self, case: &'a MatchCase) { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(case.range, |e, s| e.decision(s, "match_case")); - self.record_evidence(case.range, |e, s| e.abc_condition(s, "match_case")); - let effective = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(case.range, |e, s| { - e.cognitive(s, effective.saturating_add(1), "match_case"); - }); - self.current().cognitive.boolean_seq.reset(); - self.cognitive.nesting += 1; - // We deliberately do NOT call `self.visit_pattern(&case.pattern)` — - // pattern bindings have no metric impact (legacy didn't count them - // either). Guards and bodies do. - if let Some(g) = &case.guard { - self.visit_expr(g); - } - self.visit_body(&case.body); - self.cognitive.nesting -= 1; - } - - fn visit_comprehension(&mut self, comp: &'a Comprehension) { - // A comprehension's first generator is +1 cyclomatic (the - // implicit `for`); each `if` filter is also +1. - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(comp.range, |e, s| e.decision(s, "comprehension")); - self.record_evidence(comp.range, |e, s| e.abc_condition(s, "comprehension")); - for f in &comp.ifs { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(f.range(), |e, s| e.decision(s, "comprehension_if")); - self.record_evidence(f.range(), |e, s| e.abc_condition(s, "comprehension_if")); - } - self.visit_expr(&comp.target); - self.visit_expr(&comp.iter); - for f in &comp.ifs { - self.visit_expr(f); - } - } -} - -fn text_range_to_source_span(range: TextRange, line_index: &LineIndex) -> SourceSpan { - SourceSpan { - start_byte: range.start().to_u32(), - end_byte: range.end().to_u32(), - start_line: line_index.line_at(range.start().to_u32()), - end_line: line_index.line_at(range.end().to_u32()), - } -} - -/// Byte range covering a non-empty statement body (first statement's -/// start to last statement's end). Used to anchor evidence for -/// clause-shaped increments that have no node of their own in the Ruff -/// AST (`for`/`while`/`try` else-branches, `finally` bodies). -fn body_range(body: &[Stmt]) -> Option { - let first = body.first()?; - let last = body.last()?; - Some(TextRange::new(first.range().start(), last.range().end())) -} - -fn leading_docstring_range(body: &[Stmt]) -> Option { - let first = body.first()?; - if let Stmt::Expr(ast::StmtExpr { value, .. }) = first - && let Expr::StringLiteral(s) = value.as_ref() - { - return Some(s.range); - } - None -} - -fn python_method_is_public(name: &str) -> bool { - if name.starts_with("__") && name.ends_with("__") { - return true; - } - !name.starts_with('_') -} - -fn python_attribute_is_public(name: &str) -> bool { - if name.starts_with("__") && name.ends_with("__") { - return true; - } - !name.starts_with('_') -} - -enum TokenClass { - Operator(&'static str), - Operand(&'static str), - Skip, -} - -fn classify_token(kind: TokenKind) -> TokenClass { - use TokenClass::*; - use TokenKind::*; - match kind { - // Operators — punctuation that reads as `do something`. - Lpar => Operator("("), - Lsqb => Operator("["), - Lbrace => Operator("{"), - Comma => Operator(","), - Colon => Operator(":"), - Semi => Operator(";"), - Dot => Operator("."), - At => Operator("@"), - Plus => Operator("+"), - Minus => Operator("-"), - Star => Operator("*"), - Slash => Operator("/"), - Percent => Operator("%"), - Vbar => Operator("|"), - Amper => Operator("&"), - CircumFlex => Operator("^"), - Tilde => Operator("~"), - DoubleStar => Operator("**"), - DoubleSlash => Operator("//"), - LeftShift => Operator("<<"), - RightShift => Operator(">>"), - Less => Operator("<"), - Greater => Operator(">"), - Equal => Operator("="), - EqEqual => Operator("=="), - NotEqual => Operator("!="), - LessEqual => Operator("<="), - GreaterEqual => Operator(">="), - PlusEqual => Operator("+="), - MinusEqual => Operator("-="), - StarEqual => Operator("*="), - SlashEqual => Operator("/="), - PercentEqual => Operator("%="), - AmperEqual => Operator("&="), - VbarEqual => Operator("|="), - CircumflexEqual => Operator("^="), - DoubleStarEqual => Operator("**="), - DoubleSlashEqual => Operator("//="), - LeftShiftEqual => Operator("<<="), - RightShiftEqual => Operator(">>="), - ColonEqual => Operator(":="), - AtEqual => Operator("@="), - Rarrow => Operator("->"), - // Keywords — these are Halstead operators. - And => Operator("and"), - Or => Operator("or"), - Not => Operator("not"), - If => Operator("if"), - Elif => Operator("elif"), - Else => Operator("else"), - For => Operator("for"), - While => Operator("while"), - Try => Operator("try"), - Except => Operator("except"), - Finally => Operator("finally"), - With => Operator("with"), - Return => Operator("return"), - Raise => Operator("raise"), - Yield => Operator("yield"), - Assert => Operator("assert"), - Import => Operator("import"), - From => Operator("from"), - As => Operator("as"), - Pass => Operator("pass"), - Break => Operator("break"), - Continue => Operator("continue"), - Def => Operator("def"), - Class => Operator("class"), - Lambda => Operator("lambda"), - In => Operator("in"), - Is => Operator("is"), - Async => Operator("async"), - Await => Operator("await"), - Global => Operator("global"), - Nonlocal => Operator("nonlocal"), - Del => Operator("del"), - // Soft keywords (`match`, `case`, `type`, `_`-as-pattern) read - // as operators when they head a statement. - Match => Operator("match"), - Case => Operator("case"), - Type => Operator("type"), - // Operands — leaves that name or contain a value. - Name => Operand("Identifier"), - Int | Float | Complex => Operand("Number"), - String | FStringStart | FStringMiddle | FStringEnd | TStringStart | TStringMiddle - | TStringEnd => Operand("String"), - True => Operand("True"), - False => Operand("False"), - None => Operand("None"), - Ellipsis => Operand("Ellipsis"), - // Closing punctuation, newlines, indents, and comments are not - // counted (closing `)` etc. would double-count alongside their - // opening counterpart — Halstead's classical formula counts - // brackets *as a pair*, with the open bracket as the operator - // and the close as a no-op). - Rpar | Rsqb | Rbrace => Skip, - Newline | NonLogicalNewline | Indent | Dedent | EndOfFile | Comment | Question - | Exclamation | Lazy | Unknown | IpyEscapeCommand => Skip, - } -} diff --git a/crates/mehen-python/tests/cognitive.rs b/crates/mehen-python/tests/cognitive.rs deleted file mode 100644 index f53c89d4..00000000 --- a/crates/mehen-python/tests/cognitive.rs +++ /dev/null @@ -1,404 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity ports from -//! `crates/mehen-engine/src/legacy/metrics/cognitive.rs` Python tests. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_python::PythonAnalyzer; - -fn analyze(source: &str, filename: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PythonAnalyzer::new(); - let file = SourceFile::new(filename.into(), Language::Python, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn python_no_cognitive() { - let a = analyze("a = 42", "foo.py"); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} - -#[test] -fn python_simple_function() { - let a = analyze( - "def f(a, b): - if a and b: # +2 (+1 and) - return 1 - if c and d: # +2 (+1 and) - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn python_expression_statement() { - // Boolean expressions containing `And` and `Or` operators were not - // considered in assignments - let a = analyze( - "def f(a, b): - c = True and True", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 1.0, - "average": 1.0, - "min": 0.0, - "max": 1.0 - }"### - ); -} - -#[test] -fn python_tuple() { - // Boolean expressions containing `And` and `Or` operators were not - // considered inside tuples - let a = analyze( - "def f(a, b): - return \"%s%s\" % (a and \"Get\" or \"Set\", b)", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn python_nested_if_in_else_is_not_else_if() { - // Python has no `else if`; `elif` is a dedicated grammar node. A plain - // `if` inside an `else:` block must therefore be counted as a nested - // `if`, not skipped as else-if. This verifies that `is_else_if = false` - // for Python is correct. - let a = analyze( - "def f(a, b): - if a: # +1 - pass - else: # +1 else - if b: # +2 (+1 if, +1 nesting) - pass", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn python_elif_function() { - // Boolean expressions containing `And` and `Or` operators were not - // considered in `elif` statements - let a = analyze( - "def f(a, b): - if a and b: # +2 (+1 and) - return 1 - elif c and d: # +2 (+1 and) - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn python_more_elifs_function() { - // Boolean expressions containing `And` and `Or` operators were not - // considered when there were more `elif` statements - let a = analyze( - "def f(a, b): - if a and b: # +2 (+1 and) - return 1 - elif c and d: # +2 (+1 and) - return 1 - elif e and f: # +2 (+1 and) - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 6.0, - "average": 6.0, - "min": 0.0, - "max": 6.0 - }"### - ); -} - -#[test] -fn python_sequence_same_booleans() { - let a = analyze( - "def f(a, b): - if a and b and True: # +2 (+1 sequence of and) - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn python_sequence_different_booleans() { - let a = analyze( - "def f(a, b): - if a and b or True: # +3 (+1 and, +1 or) - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn python_formatted_sequence_different_booleans() { - let a = analyze( - "def f(a, b): - if ( # +1 - a and b and # +1 - (c or d) # +1 - ): - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn python_1_level_nesting() { - let a = analyze( - "def f(a, b): - if a: # +1 - for i in range(b): # +2 - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn python_2_level_nesting() { - let a = analyze( - "def f(a, b): - if a: # +1 - for i in range(b): # +2 - if b: # +3 - return 1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 6.0, - "average": 6.0, - "min": 0.0, - "max": 6.0 - }"### - ); -} - -#[test] -fn python_try_construct() { - let a = analyze( - "def f(a, b): - try: # +1 - for foo in bar: # +2 (nesting = 1) - return a - except Exception: # +2 (nesting = 1) - if a < 0: # +3 (nesting = 2) - return a", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 8.0, - "average": 8.0, - "min": 0.0, - "max": 8.0 - }"### - ); -} - -#[test] -fn python_ternary_operator() { - let a = analyze( - "def f(a, b): - if a % 2: # +1 - return 'c' if a else 'd' # +2 - return 'a' if a else 'b' # +1", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn python_nested_functions_lambdas() { - let a = analyze( - "def f(a, b): - def foo(a): - if a: # +2 (+1 nesting) - return 1 - # +3 (+1 for boolean sequence +2 for lambda nesting) - bar = lambda a: lambda b: b or True or True - return bar(foo(a))(a)", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - // 2 functions + 2 lambdas = 4 - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 5.0, - "average": 1.25, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -/// Ruff vs tree-sitter-python: this fixture has invalid indentation -/// (the inner `if (` is more indented than its sibling `word = ...`). -/// Tree-sitter-python's lossy CST silently treats it as a nested -/// statement, so the legacy walker still produced sum=9. Ruff -/// (correctly) rejects the input as a `SyntaxError` and the analyzer -/// returns an empty MetricSpace plus a `python.parse_error` -/// diagnostic. CPython's own `ast.parse` agrees with Ruff -/// (`unexpected indent`). This is a parser improvement, not a metric -/// regression — the legacy snapshot was based on garbage AST input. -#[test] -fn python_real_function() { - let a = analyze( - "def process_raw_constant(constant, min_word_length): - processed_words = [] - raw_camelcase_words = [] - for raw_word in re.findall(r'[a-z]+', constant): # +1 - word = raw_word.strip() - if ( # +2 (+1 if and +1 nesting) - len(word) >= min_word_length - and not (word.startswith('-') or word.endswith('-')) # +2 operators - ): - if is_camel_case_word(word): # +3 (+1 if and +2 nesting) - raw_camelcase_words.append(word) - else: # +1 else - processed_words.append(word.lower()) - return processed_words, raw_camelcase_words", - "foo.py", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} diff --git a/crates/mehen-python/tests/contributions.rs b/crates/mehen-python/tests/contributions.rs deleted file mode 100644 index 0a024a0a..00000000 --- a/crates/mehen-python/tests/contributions.rs +++ /dev/null @@ -1,324 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the Python analyzer (plan §5.4). - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_python::PythonAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - PythonAnalyzer::new() - .analyze( - &SourceFile::new("s.py".into(), Language::Python, source.to_string()), - config, - ) - .expect("Python analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -def classify(a, b): - if a > 0 and b > 0: - return 1 - elif a < 0 or b < 0: - return -1 - else: - total = 0 - total += a - handler = lambda x: x * 2 - return handler(total) -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn reasons_are_python_namespaced_with_node_kinds() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "python.cyclomatic.stmt_if", - "python.cyclomatic.elif_clause", - "python.cyclomatic.and", - "python.cyclomatic.or", - "python.cognitive.stmt_if", - "python.cognitive.elif_clause", - "python.cognitive.else_clause", - "python.cognitive.and", - "python.cognitive.or", - "python.nexit.stmt_return", - "python.abc.assignment.stmt_assign", - "python.abc.assignment.stmt_aug_assign", - "python.abc.branch.expr_call", - "python.abc.condition.expr_compare", - "python.nom.function.stmt_function_def", - "python.nom.closure.expr_lambda", - "python.nargs.function.stmt_function_def", - "python.nargs.closure.expr_lambda", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("python."))); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn class_members_evidence_npa_and_npm() { - let source = "\ -class Point: - x: int = 0 - y = 1 - _hidden: int = 2 - - def dist(self): - return self.x + self.y - - def _internal(self): - return 0 -"; - let analysis = analyze(source, &AnalysisConfig::production()); - assert_eq!(evidence_sum(&analysis, "npa"), metric(&analysis, "npa")); - assert_eq!(evidence_sum(&analysis, "npm"), metric(&analysis, "npm")); - // `x` and `y` are public; `_hidden` is not. `dist` is public; - // `_internal` is not. Non-public members must record no evidence. - assert_eq!(evidence_sum(&analysis, "npa"), 2.0); - assert_eq!(evidence_sum(&analysis, "npm"), 1.0); - assert!( - analysis - .contributions - .iter() - .any(|item| item.reason.as_str() == "python.npa.stmt_ann_assign") - ); - assert!( - analysis - .contributions - .iter() - .any(|item| item.reason.as_str() == "python.npa.stmt_assign") - ); - assert!( - analysis - .contributions - .iter() - .any(|item| item.reason.as_str() == "python.npm.stmt_function_def") - ); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc", - "nom", - "nargs", - ] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} - -#[test] -fn cognitive_amounts_carry_nesting_depth() { - // A doubly-nested `if` pays nesting+1 = 2 on the inner node — - // the §5.4 "why did cognitive move +2 here" answer. - let source = "\ -def nested(a, b): - if a: - if b: - return 1 - return 2 -"; - let analysis = analyze(source, &AnalysisConfig::production()); - let cognitive: Vec = analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == "cognitive.sum") - .map(|item| item.amount) - .collect(); - assert_eq!(cognitive, vec![1.0, 2.0]); - assert_eq!(metric(&analysis, "cognitive.sum"), 3.0); -} - -#[test] -fn kitchen_sink_families_stay_internally_consistent() { - // Exercises every clause-shaped evidence site the simple fixture - // misses: for/while/try else-branches, `finally`, `except`, - // `match`/`case`, `with`, conditional expressions, comprehensions - // and their filters, walrus assignments, annotated assignments, - // PEP 695 type aliases, `raise`, and the legacy lambda-ancestor - // bonus on a boolean chain nested inside two lambdas. - let source = "\ -type Alias = int - -def process(items, flag): - total = 0 - for item in items: - if item > 0 and flag: - total += item - elif item < 0 or not flag: - continue - else: - break - else: - total = -1 - while total > 100: - total -= 2 - else: - total += 1 - try: - result = [x * 2 for x in items if x > 0] - except ValueError as err: - raise RuntimeError(\"bad\") from err - except TypeError: - pass - else: - result = [] - finally: - total += 1 - match total: - case 0: - pass - case _: - pass - with open(\"f\") as fh: - data = fh.read() if flag else \"\" - counted = (n := total + 1) - limit: int = 10 - outer = lambda a: lambda b: b or a or flag - return outer(counted)(limit) -"; - let analysis = analyze(source, &AnalysisConfig::production()); - - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } - - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - for expected in [ - "python.cyclomatic.stmt_for", - "python.cyclomatic.for_else", - "python.cyclomatic.stmt_while", - "python.cyclomatic.while_else", - "python.cyclomatic.except_handler", - "python.cyclomatic.match_case", - "python.cyclomatic.expr_if", - "python.cyclomatic.comprehension", - "python.cyclomatic.comprehension_if", - "python.cognitive.stmt_for", - "python.cognitive.for_else", - "python.cognitive.stmt_while", - "python.cognitive.while_else", - "python.cognitive.stmt_try", - "python.cognitive.try_else", - "python.cognitive.try_finally", - "python.cognitive.except_handler", - "python.cognitive.stmt_match", - "python.cognitive.match_case", - "python.cognitive.stmt_with", - "python.cognitive.expr_if", - "python.cognitive.bool_op_lambda_bonus", - "python.nexit.stmt_raise", - "python.abc.assignment.expr_named", - "python.abc.assignment.stmt_ann_assign", - "python.abc.assignment.stmt_type_alias", - "python.abc.condition.except_handler", - "python.abc.condition.stmt_try", - "python.abc.condition.stmt_match", - "python.abc.condition.match_case", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("python."))); -} diff --git a/crates/mehen-python/tests/cyclomatic.rs b/crates/mehen-python/tests/cyclomatic.rs deleted file mode 100644 index d80bd355..00000000 --- a/crates/mehen-python/tests/cyclomatic.rs +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity ports from -//! `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs` Python tests. -//! -//! Each test reproduces the legacy fixture and the legacy expected JSON. -//! Drift from the pre-1.0 tree-sitter-python output is classified per -//! the rewrite plan §12.3.1 and `docs/python-ruff-spec.md`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_python::PythonAnalyzer; - -fn analyze(source: &str, filename: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PythonAnalyzer::new(); - let file = SourceFile::new(filename.into(), Language::Python, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Legacy `python_simple_function` from -/// `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs`. -#[test] -fn python_simple_function() { - let a = analyze( - "def f(a, b): # +2 (+1 unit space) - if a and b: # +2 (+1 and) - return 1 - if c and d: # +2 (+1 and) - return 1", - "foo.py", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - }"### - ); -} - -/// Legacy `python_1_level_nesting` from -/// `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs`. -#[test] -fn python_1_level_nesting() { - let a = analyze( - "def f(a, b): # +2 (+1 unit space) - if a: # +1 - for i in range(b): # +1 - return 1", - "foo.py", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - }"### - ); -} diff --git a/crates/mehen-python/tests/halstead.rs b/crates/mehen-python/tests/halstead.rs deleted file mode 100644 index 9630ce1f..00000000 --- a/crates/mehen-python/tests/halstead.rs +++ /dev/null @@ -1,210 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Halstead ports from -//! `crates/mehen-engine/src/legacy/metrics/halstead.rs` Python tests. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_python::PythonAnalyzer; - -fn analyze(source: &str, filename: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PythonAnalyzer::new(); - let file = SourceFile::new(filename.into(), Language::Python, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Phase 6 parity diagnostic — dumps the Halstead, cognitive and LOC -/// breakdown for the `embedded_code_large.md` Python fence so we can -/// compare directly against the legacy walker. -#[test] -fn legacy_python_fence_halstead_dump() { - let body = r#"def fibonacci(n): - a, b = 0, 1 - for _ in range(n): - a, b = b, a + b - return a - -def main(): - import sys - for arg in sys.argv[1:]: - try: - n = int(arg) - except ValueError: - continue - print(n, fibonacci(n)) - -if __name__ == "__main__": - main() -"#; - let a = analyze(body, "fence.py"); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - let cg = mehen_report::metrics_json::cognitive(&a.root.metrics); - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - eprintln!( - "ruff python fence: volume={} cognitive_sum={} sloc={}", - h.volume, cg.sum, lc.sloc - ); -} - -#[test] -fn python_operators_and_operands() { - let a = analyze( - "def foo(): - def bar(): - def toto(): - a = 1 + 1 - b = 2 + a - c = 3 + 3", - "foo.py", - ); - // unique operators: def, =, + - // operators: def, def, def, =, =, =, +, +, + - // unique operands: foo, bar, toto, a, b, c, 1, 2, 3 - // operands: foo, bar, toto, a, b, c, 1, 1, 2, a, 3, 3 - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - insta::assert_json_snapshot!( - h, - @r#" - { - "n1": 5.0, - "N1": 15.0, - "n2": 9.0, - "N2": 12.0, - "length": 27.0, - "estimated_program_length": 40.13896548741762, - "purity_ratio": 1.4866283513858378, - "vocabulary": 14.0, - "volume": 102.79858289555531, - "difficulty": 3.3333333333333335, - "level": 0.3, - "effort": 342.6619429851844, - "time": 19.03677461028802, - "bugs": 0.01632259960095138 - } - "# - ); -} - -/// Ruff vs tree-sitter-python: the legacy walker counted the bare -/// brackets `()[]{}` as Halstead operators because tree-sitter-python's -/// lossy CST silently treated them as standalone syntax nodes (CPython -/// rejects this same source as a `SyntaxError`). Ruff matches CPython -/// — `parse_module` returns an error and the analyzer emits a parse -/// diagnostic instead of attributing tokens to n1/N1. This is a -/// parser-correctness improvement, not a metric regression. -#[test] -fn python_wrong_operators() { - let a = analyze("()[]{}", "foo.py"); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - insta::assert_json_snapshot!( - h, - @r#" - { - "n1": 0.0, - "N1": 0.0, - "n2": 0.0, - "N2": 0.0, - "length": 0.0, - "estimated_program_length": 0.0, - "purity_ratio": 0.0, - "vocabulary": 0.0, - "volume": 0.0, - "difficulty": 0.0, - "level": 0.0, - "effort": 0.0, - "time": 0.0, - "bugs": 0.0 - } - "# - ); -} - -#[test] -fn python_check_metrics() { - let a = analyze( - "def f(): - pass", - "foo.py", - ); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - insta::assert_json_snapshot!( - h, - @r#" - { - "n1": 4.0, - "N1": 4.0, - "n2": 1.0, - "N2": 1.0, - "length": 5.0, - "estimated_program_length": 8.0, - "purity_ratio": 1.6, - "vocabulary": 5.0, - "volume": 11.60964047443681, - "difficulty": 2.0, - "level": 0.5, - "effort": 23.21928094887362, - "time": 1.289960052715201, - "bugs": 0.002712967490108627 - } - "# - ); -} - -/// Regression: nested function spaces must carry their own Halstead -/// counts in the per-space JSON. PR #95 discussion_r3265658502 -/// flagged that the post-AST token sweep was writing every event onto -/// the unit space, leaving inner function spaces with zero -/// `halstead.N1` / `halstead.N2` even when they contained operators -/// and operands. -#[test] -fn python_nested_function_halstead_is_non_zero() { - let a = analyze( - "def outer(): - def inner(): - x = 1 + 2 - inner() -", - "nested.py", - ); - // Tree shape: unit -> outer -> inner. - assert_eq!(a.root.spaces.len(), 1, "expected one outer function"); - let outer = &a.root.spaces[0]; - assert_eq!( - outer.name.as_deref(), - Some("outer"), - "outer space should be `outer`" - ); - assert_eq!(outer.spaces.len(), 1, "expected one nested function"); - let inner = &outer.spaces[0]; - assert_eq!(inner.name.as_deref(), Some("inner")); - - let inner_h = mehen_report::metrics_json::halstead(&inner.metrics); - let inner_json = serde_json::to_string(&inner_h).unwrap(); - assert!( - inner_h.big_n1 > 0.0, - "inner function must record its `=` and `+` operators in the per-space JSON, got {inner_json}" - ); - assert!( - inner_h.big_n2 > 0.0, - "inner function must record its `x`, `1`, `2` operands, got {inner_json}" - ); - assert!( - inner_h.volume > 0.0, - "inner function volume must be > 0, got {inner_json}" - ); - - // The outer rollup must include the inner's distinct operators - // and operands (set-union semantics from `HalsteadBuilder::merge`). - let outer_h = mehen_report::metrics_json::halstead(&outer.metrics); - let outer_json = serde_json::to_string(&outer_h).unwrap(); - assert!( - outer_h.big_n1 >= inner_h.big_n1, - "outer N1 must roll up the inner: outer={outer_json} inner={inner_json}" - ); - assert!( - outer_h.big_n2 >= inner_h.big_n2, - "outer N2 must roll up the inner: outer={outer_json} inner={inner_json}" - ); -} diff --git a/crates/mehen-python/tests/loc.rs b/crates/mehen-python/tests/loc.rs deleted file mode 100644 index b1768871..00000000 --- a/crates/mehen-python/tests/loc.rs +++ /dev/null @@ -1,568 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC ports from `crates/mehen-engine/src/legacy/metrics/loc.rs` -//! Python tests. -//! -//! The legacy fixtures ship with leading whitespace because Rust raw -//! strings live inside indented `check_metrics::(...)` -//! call sites. tree-sitter-python is lenient at the module boundary -//! and silently consumes that indentation; CPython (and Ruff) reject -//! it as `unexpected indent`. The helper below normalises the leading -//! indentation so the LOC metric is exercised against the same logical -//! Python program the test author had in mind, rather than measuring -//! how Ruff handles a parser error. The trim semantics -//! (`trim_end().trim_matches('\n')` then push one `\n`) match the -//! pre-1.0 `check_metrics` so any LOC drift is not a whitespace artefact. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_python::PythonAnalyzer; - -/// Strip the common leading indentation from `source` so a fixture -/// formatted inside an indented Rust call expression parses as a -/// valid Python module under Ruff. Mirrors the behaviour of -/// `textwrap.dedent` from the Python standard library: lines that are -/// blank (after the trailing-newline strip) do not contribute to the -/// computed common prefix; every other line has the prefix removed. -fn dedent(source: &str) -> String { - let mut min_indent: Option = None; - for line in source.lines() { - if line.trim().is_empty() { - continue; - } - let indent = line.len() - line.trim_start().len(); - min_indent = Some(min_indent.map_or(indent, |cur| cur.min(indent))); - } - let prefix_len = min_indent.unwrap_or(0); - let mut out = String::with_capacity(source.len()); - let mut first = true; - for line in source.split('\n') { - if !first { - out.push('\n'); - } - first = false; - if line.trim().is_empty() { - // Preserve blank lines as-is — they are not indentation - // contributors and may legitimately be empty. - out.push_str(line.trim_end()); - } else { - // Skip up to `prefix_len` leading bytes (we already - // confirmed each non-blank line begins with at least - // that many spaces). - let start = line - .char_indices() - .nth(prefix_len) - .map(|(i, _)| i) - .unwrap_or(line.len()); - out.push_str(&line[start..]); - } - } - out -} - -fn analyze(source: &str, filename: &str) -> mehen_core::LanguageAnalysis { - let mut text = dedent(source.trim_end().trim_matches('\n')); - text.push('\n'); - let analyzer = PythonAnalyzer::new(); - let file = SourceFile::new(filename.into(), Language::Python, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn python_sloc() { - let a = analyze( - " - - a = 42 - - ", - "foo.py", - ); - // Spaces: 1 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 1.0, - "ploc": 1.0, - "lloc": 1.0, - "cloc": 0.0, - "blank": 0.0, - "sloc_average": 1.0, - "ploc_average": 1.0, - "lloc_average": 1.0, - "cloc_average": 0.0, - "blank_average": 0.0, - "sloc_min": 1.0, - "sloc_max": 1.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 1.0, - "ploc_max": 1.0, - "lloc_min": 1.0, - "lloc_max": 1.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} - -#[test] -fn python_blank() { - let a = analyze( - " - a = 42 - - b = 43 - - ", - "foo.py", - ); - // Spaces: 1 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 3.0, - "ploc": 2.0, - "lloc": 2.0, - "cloc": 0.0, - "blank": 1.0, - "sloc_average": 3.0, - "ploc_average": 2.0, - "lloc_average": 2.0, - "cloc_average": 0.0, - "blank_average": 1.0, - "sloc_min": 3.0, - "sloc_max": 3.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 2.0, - "ploc_max": 2.0, - "lloc_min": 2.0, - "lloc_max": 2.0, - "blank_min": 1.0, - "blank_max": 1.0 - }"### - ); -} - -/// Ruff vs tree-sitter: the per-space sloc/ploc/blank bounds drift -/// from the legacy because Ruff's `StmtFunctionDef.range` ends at the -/// last *statement* in the body, while tree-sitter's `function_definition` -/// extends to the trailing comments. The function-space LOC bounds -/// therefore report 9 lines (Ruff) instead of 10 (legacy). Aggregate -/// totals (`sloc`, `ploc`, `cloc`, `blank`, `lloc`) match — only the -/// per-space `sloc_min/max`, `ploc_min/max`, `blank_min/max` shift to -/// the function-only span. lloc=6 matches because `def` no longer -/// counts as a logical line in either walker. -#[test] -fn python_no_zero_blank() { - // Checks that the blank metric is not equal to 0 when there are some - // comments next to code lines. - let a = analyze( - "def ConnectToUpdateServer(): - pool = 4 - - updateServer = -42 - isConnected = False - currTry = 0 - numRetries = 10 # Number of IPC connection retries before - # giving up. - numTries = 20 # Number of IPC connection tries before - # giving up.", - "foo.py", - ); - // Spaces: 2 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 10.0, - "ploc": 7.0, - "lloc": 6.0, - "cloc": 4.0, - "blank": 1.0, - "sloc_average": 5.0, - "ploc_average": 3.5, - "lloc_average": 3.0, - "cloc_average": 2.0, - "blank_average": 0.5, - "sloc_min": 9.0, - "sloc_max": 9.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 6.0, - "ploc_max": 6.0, - "lloc_min": 6.0, - "lloc_max": 6.0, - "blank_min": 3.0, - "blank_max": 3.0 - }"### - ); -} - -/// Same Ruff function-range divergence as `python_no_zero_blank`. -#[test] -fn python_no_blank() { - // Checks that the blank metric is equal to 0 when there are no blank - // lines and there are comments next to code lines. - let a = analyze( - "def ConnectToUpdateServer(): - pool = 4 - updateServer = -42 - isConnected = False - currTry = 0 - numRetries = 10 # Number of IPC connection retries before - # giving up. - numTries = 20 # Number of IPC connection tries before - # giving up.", - "foo.py", - ); - // Spaces: 2 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 9.0, - "ploc": 7.0, - "lloc": 6.0, - "cloc": 4.0, - "blank": 0.0, - "sloc_average": 4.5, - "ploc_average": 3.5, - "lloc_average": 3.0, - "cloc_average": 2.0, - "blank_average": 0.0, - "sloc_min": 8.0, - "sloc_max": 8.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 6.0, - "ploc_max": 6.0, - "lloc_min": 6.0, - "lloc_max": 6.0, - "blank_min": 2.0, - "blank_max": 2.0 - }"### - ); -} - -/// Same Ruff function-range divergence as `python_no_zero_blank`. -#[test] -fn python_no_zero_blank_more_comments() { - // Checks that the blank metric is not equal to 0 when there are more - // comments next to code lines compared to the previous tests. - let a = analyze( - "def ConnectToUpdateServer(): - pool = 4 - - updateServer = -42 - isConnected = False - currTry = 0 # Set this variable to 0 - numRetries = 10 # Number of IPC connection retries before - # giving up. - numTries = 20 # Number of IPC connection tries before - # giving up.", - "foo.py", - ); - // Spaces: 2 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 10.0, - "ploc": 7.0, - "lloc": 6.0, - "cloc": 5.0, - "blank": 1.0, - "sloc_average": 5.0, - "ploc_average": 3.5, - "lloc_average": 3.0, - "cloc_average": 2.5, - "blank_average": 0.5, - "sloc_min": 9.0, - "sloc_max": 9.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 6.0, - "ploc_max": 6.0, - "lloc_min": 6.0, - "lloc_max": 6.0, - "blank_min": 3.0, - "blank_max": 3.0 - }"### - ); -} - -/// Ruff vs tree-sitter: this fixture mixes a column-0 docstring with -/// 12-space-indented code; the dedent helper sees min_indent=0 (the -/// docstring's first line) and leaves the rest of the source at +12. -/// Ruff rejects the resulting `# Line Comment` and `a = 42` as -/// `unexpected indent`. The legacy walker silently produced `cloc=5` -/// from the lossy CST. CPython agrees with Ruff. -#[test] -fn python_cloc() { - let a = analyze( - "\"\"\"Block comment - Block comment - \"\"\" - # Line Comment - a = 42 # Line Comment", - "foo.py", - ); - // Spaces: 1 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 0.0, - "ploc": 0.0, - "lloc": 0.0, - "cloc": 0.0, - "blank": 0.0, - "sloc_average": 0.0, - "ploc_average": 0.0, - "lloc_average": 0.0, - "cloc_average": 0.0, - "blank_average": 0.0, - "sloc_min": 0.0, - "sloc_max": 0.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 0.0, - "ploc_max": 0.0, - "lloc_min": 0.0, - "lloc_max": 0.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} - -#[test] -fn python_lloc() { - let a = analyze( - "for x in range(0,42): - if x % 2 == 0: - print(x)", - "foo.py", - ); - // Spaces: 1 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 3.0, - "ploc": 3.0, - "lloc": 3.0, - "cloc": 0.0, - "blank": 0.0, - "sloc_average": 3.0, - "ploc_average": 3.0, - "lloc_average": 3.0, - "cloc_average": 0.0, - "blank_average": 0.0, - "sloc_min": 3.0, - "sloc_max": 3.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 3.0, - "ploc_max": 3.0, - "lloc_min": 3.0, - "lloc_max": 3.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} - -/// Ruff vs tree-sitter: a backslash-continued statement spans two -/// physical lines. Tree-sitter's CST emits two child nodes (one per -/// line), so the legacy `Loc::compute` records both as ploc lines. -/// Ruff treats the continuation as a single logical statement, so -/// only the start line participates in `observe_code_line` — ploc -/// drops to 1 and the trailing line is therefore counted as `blank`. -/// Both walkers agree on `sloc=2` and `lloc=1`. -#[test] -fn python_string_on_new_line() { - // More lines of the same instruction were counted as blank lines - let a = analyze( - "capabilities[\"goog:chromeOptions\"][\"androidPackage\"] = \\ - \"org.chromium.weblayer.shell\"", - "foo.py", - ); - // Spaces: 1 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 2.0, - "ploc": 1.0, - "lloc": 1.0, - "cloc": 0.0, - "blank": 1.0, - "sloc_average": 2.0, - "ploc_average": 1.0, - "lloc_average": 1.0, - "cloc_average": 0.0, - "blank_average": 1.0, - "sloc_min": 2.0, - "sloc_max": 2.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 1.0, - "ploc_max": 1.0, - "lloc_min": 1.0, - "lloc_max": 1.0, - "blank_min": 1.0, - "blank_max": 1.0 - }"### - ); -} - -/// Ruff vs tree-sitter: the multi-line `def func(a, b, c):` signature -/// is a single AST node in Ruff (range covers all three signature -/// lines and the body), so the function's LOC observation only -/// records ploc for the first line. Tree-sitter emits one ploc-line -/// per parameter line. Aggregate sloc=6 matches; ploc drops from 6 -/// to 4 and per-space bounds shrink accordingly. Counterpart blank -/// lines bump to 2 from 0 because the missing ploc lines are -/// classified as blank in `LocStats::blank` (`sloc - ploc - -/// only_comment_lines`). -#[test] -fn python_general_loc() { - let a = analyze( - "def func(a, - b, - c): - print(a) - print(b) - print(c)", - "foo.py", - ); - // Spaces: 2 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 6.0, - "ploc": 4.0, - "lloc": 3.0, - "cloc": 0.0, - "blank": 2.0, - "sloc_average": 3.0, - "ploc_average": 2.0, - "lloc_average": 1.5, - "cloc_average": 0.0, - "blank_average": 1.0, - "sloc_min": 6.0, - "sloc_max": 6.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 3.0, - "ploc_max": 3.0, - "lloc_min": 3.0, - "lloc_max": 3.0, - "blank_min": 3.0, - "blank_max": 3.0 - }"### - ); -} - -/// Same Ruff function-range divergence as `python_no_zero_blank` — -/// the per-space LOC bounds reflect the function-only span, not the -/// unit's. Aggregate `sloc=16`, `ploc=9`, `cloc=7`, `lloc=8` match. -#[test] -fn python_real_loc() { - let a = analyze( - "def web_socket_transfer_data(request): - while True: - line = request.ws_stream.receive_message() - if line is None: - return - code, reason = line.split(' ', 1) - if code is None or reason is None: - return - request.ws_stream.close_connection(int(code), reason) - # close_connection() initiates closing handshake. It validates code - # and reason. If you want to send a broken close frame for a test, - # following code will be useful. - # > data = struct.pack('!H', int(code)) + reason.encode('UTF-8') - # > request.connection.write(stream.create_close_frame(data)) - # > # Suppress to re-respond client responding close frame. - # > raise Exception(\"customized server initiated closing handshake\")", - "foo.py", - ); - // Spaces: 2 - let lc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - lc, - @r###" - { - "sloc": 16.0, - "ploc": 9.0, - "lloc": 8.0, - "cloc": 7.0, - "blank": 0.0, - "sloc_average": 8.0, - "ploc_average": 4.5, - "lloc_average": 4.0, - "cloc_average": 3.5, - "blank_average": 0.0, - "sloc_min": 9.0, - "sloc_max": 9.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 8.0, - "ploc_max": 8.0, - "lloc_min": 8.0, - "lloc_max": 8.0, - "blank_min": 1.0, - "blank_max": 1.0 - }"### - ); -} - -/// Regression: PR #95 discussion_r3265962147 — per-function -/// `loc.cloc` must capture comments inside that function's body. -/// Before the fix, every comment routed to the unit and inner -/// functions reported `cloc = 0`. -#[test] -fn python_nested_function_cloc_routes_to_active_space() { - let a = analyze( - "def outer(): - # outer comment - def inner(): - # inner comment 1 - # inner comment 2 - x = 1 + 2 - return x - return inner", - "nested.py", - ); - assert_eq!(a.root.spaces.len(), 1); - let outer = &a.root.spaces[0]; - assert_eq!(outer.spaces.len(), 1); - let inner = &outer.spaces[0]; - let loc = mehen_report::metrics_json::loc(&inner.metrics); - assert!( - loc.cloc >= 2.0, - "inner def must record its two `#` comments, got {}", - serde_json::to_string(&loc).unwrap() - ); - assert!( - loc.ploc > 0.0, - "inner def must record code lines (the `x = 1 + 2`, etc.), got {}", - serde_json::to_string(&loc).unwrap() - ); -} diff --git a/crates/mehen-python/tests/nargs.rs b/crates/mehen-python/tests/nargs.rs deleted file mode 100644 index b87dbba6..00000000 --- a/crates/mehen-python/tests/nargs.rs +++ /dev/null @@ -1,206 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Nargs ports from -//! `crates/mehen-engine/src/legacy/metrics/nargs.rs` Python tests. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_python::PythonAnalyzer; - -fn analyze(source: &str, filename: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PythonAnalyzer::new(); - let file = SourceFile::new(filename.into(), Language::Python, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn python_no_functions_and_closures() { - let a = analyze("a = 42", "foo.py"); - let na = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - na, - @r###" - { - "total_functions": 0.0, - "total_closures": 0.0, - "average_functions": 0.0, - "average_closures": 0.0, - "total": 0.0, - "average": 0.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn python_single_function() { - let a = analyze( - "def f(a, b): - if a: - return a", - "foo.py", - ); - let na = mehen_report::metrics_json::nargs(&a.root.metrics); - // 1 function with 2 args. - // - // Drift from legacy: legacy reported `functions_min: 0.0` because - // the unit space's always-zero `fn_nargs` was folded into the - // unit's per-space minmax after merging child stats up. Per the - // metric definition, the unit isn't a function and shouldn't - // contribute a 0-arg sample to a "minimum number of function - // arguments across function spaces" statistic. The new walker - // (mehen-metrics #PR Phase-6) gates `finalize_minmax` on the - // `is_function` / `is_closure` flags so only function/closure - // spaces contribute their own `fn_nargs` / `closure_nargs` to the - // bounds. Result: `functions_min: 2.0` — matching the *only* - // function in the source. - insta::assert_json_snapshot!( - na, - @r###" - { - "total_functions": 2.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 2.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn python_single_lambda() { - let a = analyze("bar = lambda a: True", "foo.py"); - let na = mehen_report::metrics_json::nargs(&a.root.metrics); - // 1 lambda with 1 arg - insta::assert_json_snapshot!( - na, - @r###" - { - "total_functions": 0.0, - "total_closures": 1.0, - "average_functions": 0.0, - "average_closures": 1.0, - "total": 1.0, - "average": 1.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 1.0, - "closures_max": 1.0 - }"### - ); -} - -#[test] -fn python_functions_a() { - // Source reformatted from the legacy fixture's deeply-indented - // form: tree-sitter-python silently smoothed over the inconsistent - // 12-space indent on the second `def`, but Ruff (correctly) treats - // it as the start of a new statement at the parent indent level. - // The fixed source has both defs at column 0 — what the legacy - // test was *intending* to express. - let a = analyze( - "def f(a, b): - if a: - return a -def f(a, b): - if b: - return b", - "foo.py", - ); - let na = mehen_report::metrics_json::nargs(&a.root.metrics); - // 2 functions, each with 2 args. `functions_min: 2.0` per - // `python_single_function` rationale (unit doesn't pollute the - // min). - insta::assert_json_snapshot!( - na, - @r###" - { - "total_functions": 4.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 4.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn python_functions_b() { - let a = analyze( - "def f(a, b): - if a: - return a -def f(a, b, c): - if b: - return b", - "foo.py", - ); - let na = mehen_report::metrics_json::nargs(&a.root.metrics); - // 2 functions: f(2 args) + f(3 args) = 5 total. Min=2, Max=3. - insta::assert_json_snapshot!( - na, - @r###" - { - "total_functions": 5.0, - "total_closures": 0.0, - "average_functions": 2.5, - "average_closures": 0.0, - "total": 5.0, - "average": 2.5, - "functions_min": 2.0, - "functions_max": 3.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn python_nested_functions() { - let a = analyze( - "def f(a, b): - def foo(a): - if a: - return 1 - bar = lambda a: lambda b: b or True or True - return bar(foo(a))(a)", - "foo.py", - ); - let na = mehen_report::metrics_json::nargs(&a.root.metrics); - // 2 functions (`f(2 args)`, `foo(1 arg)`) + 2 lambdas - // (`lambda a: ...` outer with 1 arg, `lambda b: ...` inner with - // 1 arg). Total args = 2+1+1+1 = 5. Per `python_single_function` - // rationale, `functions_min` is 1 (the smaller of the two - // function spaces) and `closures_min` is 1. - insta::assert_json_snapshot!( - na, - @r###" - { - "total_functions": 3.0, - "total_closures": 2.0, - "average_functions": 1.5, - "average_closures": 1.0, - "total": 5.0, - "average": 1.25, - "functions_min": 1.0, - "functions_max": 2.0, - "closures_min": 1.0, - "closures_max": 1.0 - }"### - ); -} diff --git a/crates/mehen-python/tests/parity.rs b/crates/mehen-python/tests/parity.rs deleted file mode 100644 index b9c0ba6a..00000000 --- a/crates/mehen-python/tests/parity.rs +++ /dev/null @@ -1,318 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Parity / divergence snapshots for the Ruff-backed Python analyzer. -//! -//! Each test reproduces a relevant pre-1.0 `mehen-engine::legacy` -//! Python assertion using the same fixture and expected JSON. The -//! snapshots come from the legacy `check_metrics::` -//! body — every drift from the pre-1.0 tree-sitter-python output is -//! classified per the rewrite plan §12.3.1 and `docs/python-ruff-spec.md`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_python::PythonAnalyzer; - -fn analyze(source: &str, filename: &str) -> mehen_core::LanguageAnalysis { - // The legacy `check_metrics` strips trailing newlines and pushes a - // single one — match that precisely so any LOC line-count drift is - // not just a whitespace artifact. - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = PythonAnalyzer::new(); - let file = SourceFile::new(filename.into(), Language::Python, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Legacy `python_simple_function` from -/// `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs:323` — the -/// numbers below come straight from that test's inline JSON. -#[test] -fn python_simple_function_cyclomatic() { - let a = analyze( - "def f(a, b): # +2 (+1 unit space) - if a and b: # +2 (+1 and) - return 1 - if c and d: # +2 (+1 and) - return 1", - "foo.py", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - }"### - ); -} - -/// Legacy `python_1_level_nesting`. -#[test] -fn python_1_level_nesting_cyclomatic() { - let a = analyze( - "def f(a, b): # +2 (+1 unit space) - if a: # +1 - for i in range(b): # +1 - return 1", - "foo.py", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - }"### - ); -} - -/// Match/case is a Phase 6 *improvement* over tree-sitter-python: -/// each case is a real structural branch, so each contributes +1 -/// cyclomatic. The legacy walker also counted matches (`+1 per case`), -/// so this is a parity check, not a drift. -#[test] -fn python_match_each_case_counts_as_decision() { - let a = analyze( - "def f(x): - match x: - case 1: - return 'one' - case 2: - return 'two' - case _: - return 'other'", - "foo.py", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - // 1 (base) + 3 cases = 4 in the function. Unit space adds nothing - // structural. Sum = 4 + 1 (unit) = 5; max = 4. - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - }"### - ); -} - -/// `try`/`except*` (PEP 654 exception groups) — each `except*` handler -/// counts the same as `except`. New-parser improvement: tree-sitter -/// grammar may not parse this correctly; Ruff does. -#[test] -fn python_except_star_handler_counts_as_decision() { - let a = analyze( - "def f(): - try: - do() - except* ValueError: - handle()", - "foo.py", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - }"### - ); -} - -/// Type annotations are runtime-accessible objects in Python (Pydantic, -/// `typing.get_type_hints`, dataclasses), so identifiers inside them -/// DO contribute to Halstead operands. This is the deliberate -/// difference from `mehen-typescript`, where TS types are erased. -#[test] -fn python_type_annotations_participate_in_halstead() { - let a = analyze( - "def f(x: int, y: str = 'hi') -> bool: - return False", - "foo.py", - ); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - // Identifiers `int`, `str`, `bool` are operands; the `:` and `->` - // are operators. Without this rule, the metric would understate - // the program's Halstead difficulty. - assert!( - h.n2 >= 4.0, - "expected n2>=4 (x, y, int, str, bool, False, ...) got {}", - h.n2 - ); -} - -/// Module-level docstring (PEP 257) is excluded from Halstead — it is -/// structural documentation, not running code. Compare to a module -/// without a docstring to confirm the exclusion. -#[test] -fn python_module_docstring_excluded_from_halstead() { - let with_doc = analyze( - "\"\"\"This is a module docstring.\"\"\" -x = 1", - "with.py", - ); - let without_doc = analyze("x = 1\n", "without.py"); - let h_with = mehen_report::metrics_json::halstead(&with_doc.root.metrics); - let h_without = mehen_report::metrics_json::halstead(&without_doc.root.metrics); - // The docstring's tokens (`"""`, `T h i s …`) must not contribute - // any Halstead operators or operands beyond what `x = 1` already - // produced. Token-level Halstead totals must therefore match - // exactly when the docstring is removed. - assert_eq!(h_with.n1, h_without.n1, "n1 should match"); - assert_eq!(h_with.n2, h_without.n2, "n2 should match"); - assert_eq!(h_with.big_n1, h_without.big_n1, "N1 should match"); - assert_eq!(h_with.big_n2, h_without.big_n2, "N2 should match"); -} - -/// NPM: only methods of class bodies count. Public/private follow the -/// PEP 8 leading-underscore convention; dunders (`__init__` etc.) are -/// public. -#[test] -fn python_npm_counts_class_methods() { - let a = analyze( - "class C: - def __init__(self): - pass - def public(self): - pass - def _internal(self): - pass", - "foo.py", - ); - let class_space = &a.root.spaces[0]; - let npm = mehen_report::metrics_json::npm(&class_space.metrics); - // 3 methods total in the class. Public: __init__ + public = 2. - assert_eq!(npm.class_methods, 3.0); - assert_eq!( - npm.classes, 2.0, - "expected 2 public methods, got {}", - npm.classes - ); -} - -/// NPA: top-level class assignments (annotated or not) count as -/// attributes. Legacy walked `expression_statement -> assignment`. -/// Ruff's AST gives us `StmtAssign` / `StmtAnnAssign` directly. -#[test] -fn python_npa_counts_class_attributes() { - let a = analyze( - "class C: - x: int = 1 - y = 2 - _internal = 3", - "foo.py", - ); - let class_space = &a.root.spaces[0]; - let npa = mehen_report::metrics_json::npa(&class_space.metrics); - assert_eq!(npa.class_attributes, 3.0); - assert_eq!( - npa.classes, 2.0, - "expected 2 public attributes, got {}", - npa.classes - ); -} - -/// NExit: `return` and `raise` count. -#[test] -fn python_nexit_counts_return_and_raise() { - let a = analyze( - "def f(x): - if x: - return 1 - raise ValueError('oops')", - "foo.py", - ); - let func = &a.root.spaces[0]; - let nx = mehen_report::metrics_json::nexits(&func.metrics); - assert_eq!(nx.sum, 2.0); -} - -/// PEP 701 / PEP 750: f-strings and t-strings expose embedded -/// expressions as proper AST nodes. The interpolated `{ ... }` parts -/// reach Halstead via the AST `visit_expr` traversal — each -/// `Expr::FString` walks every `InterpolatedStringElement` and emits -/// the embedded expression's tokens as ordinary operators / operands. -/// The legacy tree-sitter-python's f-string handling lumped the entire -/// f-string into one `string` operand and missed the interpolation's -/// embedded identifiers. Ruff's structurally-richer representation -/// captures `x` and `y` as Halstead operands. -#[test] -fn python_f_string_interpolation_contributes_to_halstead() { - let plain = analyze( - "def fmt(x, y): - return 'static'", - "plain.py", - ); - let interp = analyze( - "def fmt(x, y): - return f'{x + y!r}'", - "interp.py", - ); - let h_plain = mehen_report::metrics_json::halstead(&plain.root.metrics); - let h_interp = mehen_report::metrics_json::halstead(&interp.root.metrics); - // The interpolated expression contributes at least 2 extra operand - // tokens (`x` and `y`) and at least one extra operator (`+`). - assert!( - h_interp.big_n2 > h_plain.big_n2, - "f-string interpolation should add operands; plain N2={} interp N2={}", - h_plain.big_n2, - h_interp.big_n2 - ); - assert!( - h_interp.big_n1 > h_plain.big_n1, - "f-string interpolation should add operators; plain N1={} interp N1={}", - h_plain.big_n1, - h_interp.big_n1 - ); -} - -/// Default-value expressions in parameters are runtime-evaluated at -/// definition time. They should reach ABC (calls, comparisons) and -/// Halstead (operators / operands). This is a Phase-6-friendly check -/// — Ruff's AST gives us each `ParameterWithDefault` directly. -#[test] -fn python_parameter_defaults_count_as_definition_time_code() { - let a = analyze( - "def f(x=1, y=int('42'), z=[1, 2, 3]): - return x + y", - "foo.py", - ); - // The unit's ABC must include the `int('42')` call as a branch. - let abc_unit = mehen_report::metrics_json::abc(&a.root.metrics); - assert!( - abc_unit.branches >= 1.0, - "expected `int('42')` default to count as a branch, got {}", - serde_json::to_string(&abc_unit).unwrap() - ); -} - -/// Walrus / named expression `(x := 42)` is an assignment that -/// returns its value. Legacy walker counted it as `named_expression`; -/// Ruff exposes it as `Expr::Named`. ABC.assignments must increment. -#[test] -fn python_walrus_counts_as_assignment() { - let a = analyze( - "def f(): - if (n := 10) > 5: - return n", - "foo.py", - ); - let func = &a.root.spaces[0]; - let abc = mehen_report::metrics_json::abc(&func.metrics); - assert!( - abc.assignments >= 1.0, - "walrus must count as assignment, got {}", - serde_json::to_string(&abc).unwrap() - ); -} diff --git a/crates/mehen-report/Cargo.toml b/crates/mehen-report/Cargo.toml deleted file mode 100644 index 88aa8670..00000000 --- a/crates/mehen-report/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "mehen-report" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — report rendering (JSON, GitHub Markdown, single-file Markdown) (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-markdown = { workspace = true, optional = true } -serde = { workspace = true } -serde_json = { workspace = true } - -[features] -default = ["docs-diff"] -# Enables the Markdown documentation-diff renderer ported from the -# pre-1.0 `src/diff_markdown.rs` per plan §8.1. Off when the consumer -# doesn't need the `mehen-markdown` types in scope. -docs-diff = ["dep:mehen-markdown"] - -[lints] -workspace = true diff --git a/crates/mehen-report/src/github_markdown_docs.rs b/crates/mehen-report/src/github_markdown_docs.rs deleted file mode 100644 index 369409a1..00000000 --- a/crates/mehen-report/src/github_markdown_docs.rs +++ /dev/null @@ -1,2779 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Markdown Documentation Metrics section for the `mehen diff` sticky PR -//! comment, §39 of `docs/mehen_markdown_metrics_research_foundation.md`. -//! -//! Implementation contract — non-negotiable: -//! -//! - Every callout is emitted through the §39.5.2 template catalog. Free-text -//! prose is forbidden (§39.5.3). The project-level linter -//! `scripts/check_pr_template_catalog.sh` greps for forbidden phrasings and -//! for `format!(`/`write!(` outside an allow-list. -//! - Output is a pure function of the `(base, head)` [`MarkdownMetrics`] pair -//! plus the paths and refs. Byte-identical for identical inputs. Everything -//! that ends up rendered is sorted. -//! - No network calls. External-link status comes from the Phase-A–E pipeline -//! which already marks them `resolved: None`. - -use std::fmt::Write as _; -use std::path::{Path, PathBuf}; - -use mehen_markdown::types::{ArtifactKind, LinkClass, MarkdownMetrics}; - -/// Anchor used so upserts can replace the Markdown-docs block independently -/// of the source-code block. -pub const DOC_ANCHOR: &str = ""; - -/// Documentation section heading (§39.1). -const DOC_HEADING: &str = "## \u{1F4DD} Documentation Metrics"; - -/// Footer mirrors the source-code bot (§39.9). -const FOOTER: &str = - "> Generated by [mehen](https://github.com/ophi-dev/mehen) \u{2014} the code quality watcher."; - -/// Legend printed just above the footer (§39.9). -const LEGEND: &str = "> Legend: \u{1F7E2} improvement \u{00B7} \u{1F534} regression \u{00B7} \u{26A0}\u{FE0F} attention \u{00B7} \u{1F195} new file \u{00B7} \u{26AA} no material change"; - -/// Max headline-table rows before overflow into `
` (§39.8). -const HEADLINE_ROW_CAP: usize = 10; - -/// Aggregate-header threshold: above this many files, prepend a count header -/// (§39.8). -const AGGREGATE_FILES_THRESHOLD: usize = 25; - -/// Callout cap (§39.5.1, §39.8). -const CALLOUT_CAP: usize = 8; - -/// Long-sentence threshold — matches §33.10 plain-prose profile (30 words). -const LONG_SENTENCE_THRESHOLD_DEFAULT: u64 = 30; - -/// Readability profile name shown when a grade-target breach is reported. -const READABILITY_DEFAULT_PROFILE: &str = "default"; -/// Default FKGL grade target for the plain-prose profile (§31.13). -const READABILITY_DEFAULT_TARGET: f64 = 12.0; - -/// Profile max for passive ratio (§33.1, default). Breach → emit template. -const PASSIVE_DEFAULT_MAX: f64 = 0.25; - -/// Filler Risk bands per §17.10: `[0.20, 0.40, 0.60, 0.80]`. -const FILLER_BANDS: [f64; 4] = [0.20, 0.40, 0.60, 0.80]; -const FILLER_BAND_LABELS: [&str; 5] = ["clean", "mild", "moderate", "high", "severe"]; - -/// DMI bands per §10.4. -const DMI_BANDS: [(f64, &str); 5] = [ - (0.0, "Poor"), - (30.0, "Fair"), - (50.0, "Mixed"), - (70.0, "Good"), - (85.0, "Excellent"), -]; - -/// Evidence-coverage bands per §16.4. -const EVIDENCE_BANDS: [(f64, &str); 4] = [ - (0.0, "absent"), - (0.25, "weak"), - (0.50, "partial"), - (0.75, "grounded"), -]; - -/// Grounding bands per §15.3. -const GROUNDING_BANDS: [(f64, &str); 4] = [ - (0.0, "absent"), - (0.25, "weak"), - (0.50, "partial"), - (0.75, "grounded"), -]; - -/// Noticeable-delta thresholds — §39.4 table. -const DMI_NOTICEABLE: f64 = 3.0; -const FKGL_NOTICEABLE: f64 = 0.5; -const TATEISHI_NOTICEABLE: f64 = 2.0; -const LINK_DEBT_NOTICEABLE: f64 = 0.05; -const FILLER_NOTICEABLE: f64 = 0.05; -const FILLER_WARN_THRESHOLD: f64 = 0.60; - -/// Per-file input for the Markdown-docs renderer. The analyzer is called -/// once per side and the result attached here. -#[derive(Debug, Clone)] -pub struct DocDiffFile { - pub path: PathBuf, - pub head: Option, - pub base: Option, - pub is_new: bool, - pub is_deleted: bool, -} - -impl DocDiffFile { - pub fn has_data(&self) -> bool { - self.head.is_some() || self.base.is_some() - } -} - -/// Render context — carries PR-level refs that show up inside cells (file -/// links) and headings (base label). -#[derive(Debug, Clone)] -pub struct DocRenderCtx<'a> { - pub base_label: &'a str, - pub repo_url: Option<&'a str>, - pub head_sha: Option<&'a str>, - /// Long-sentence threshold in words (§33.10 profile-configurable). - pub long_sentence_threshold: u64, - /// Readability profile label used in `readability_target_breach`. - pub readability_profile: &'a str, - /// Readability target (grade level) for `readability_target_breach`. - pub readability_target: f64, - /// Passive-ratio max for `passive_ratio_breach`. - pub passive_max: f64, -} - -impl<'a> DocRenderCtx<'a> { - pub fn new(base_label: &'a str) -> Self { - Self { - base_label, - repo_url: None, - head_sha: None, - long_sentence_threshold: LONG_SENTENCE_THRESHOLD_DEFAULT, - readability_profile: READABILITY_DEFAULT_PROFILE, - readability_target: READABILITY_DEFAULT_TARGET, - passive_max: PASSIVE_DEFAULT_MAX, - } - } -} - -// ── Public entry point ───────────────────────────────────────────────── - -/// Renders the Markdown-docs section, or returns `None` when no files are -/// eligible (§39.1: suppressed entirely when no `.md` in the PR diff). -pub fn render_doc_section(files: &[DocDiffFile], ctx: &DocRenderCtx<'_>) -> Option { - let eligible: Vec<&DocDiffFile> = files.iter().filter(|f| f.has_data()).collect(); - if eligible.is_empty() { - return None; - } - - // Derive per-file rows and associated callouts. Keep both so ordering is - // independent: rows sort by severity_class desc/path asc, callouts sort - // by severity asc/magnitude desc/path asc. - let mut row_file_pairs: Vec<(DocRow, &DocDiffFile)> = eligible - .iter() - .map(|f| (DocRow::build(f, ctx), *f)) - .collect(); - - // Build all callouts. - let mut callouts: Vec = Vec::new(); - for (row, file) in &row_file_pairs { - emit_callouts_for_file(row, file, ctx, &mut callouts); - } - callouts.sort_by(|a, b| { - a.severity - .cmp(&b.severity) - .then( - b.magnitude - .partial_cmp(&a.magnitude) - .unwrap_or(std::cmp::Ordering::Equal), - ) - .then(a.path.cmp(&b.path)) - .then(a.rule_id.cmp(b.rule_id)) - .then(a.line_key.cmp(&b.line_key)) - }); - - // Sort rows (for headline) by severity desc, path asc. - row_file_pairs.sort_by(|a, b| { - b.0.severity_class - .cmp(&a.0.severity_class) - .then(a.0.path_key().cmp(&b.0.path_key())) - }); - - let rows: Vec<&DocRow> = row_file_pairs.iter().map(|(r, _)| r).collect(); - - let mut out = String::new(); - out.push_str(DOC_ANCHOR); - out.push('\n'); - out.push_str(DOC_HEADING); - out.push_str(&heading_scope(ctx.base_label)); - out.push('\n'); - out.push('\n'); - - let total_files = rows.len(); - if total_files > AGGREGATE_FILES_THRESHOLD { - let _ = writeln!( - out, - "{total_files} Markdown files changed (top 10 by severity shown)." - ); - out.push('\n'); - } - - // Headline table — up to HEADLINE_ROW_CAP rows. Overflow into
. - let cap = HEADLINE_ROW_CAP.min(rows.len()); - let (visible, overflow) = rows.split_at(cap); - write_headline_table(&mut out, visible, ctx); - - if !overflow.is_empty() { - out.push('\n'); - let _ = writeln!( - out, - "
{} more file(s)", - overflow.len() - ); - out.push('\n'); - write_headline_table(&mut out, overflow, ctx); - out.push_str("\n
\n"); - } - - let any_short_doc_fkgl = rows.iter().any(|r| r.short_doc_footnote); - let any_prose_empty = rows.iter().any(|r| r.prose_empty_footnote); - if any_short_doc_fkgl { - out.push('\n'); - out.push_str("> \u{00B2} Below grade-scoring threshold (< 100 words or < 5 sentences).\n"); - } - if any_prose_empty { - if !any_short_doc_fkgl { - out.push('\n'); - } - out.push_str("> \u{00B3} Prose-empty after structural stripping.\n"); - } - - // Callouts — severity-ranked, template-only, 8-cap. - if !callouts.is_empty() { - out.push('\n'); - out.push_str("**Callouts**\n"); - out.push('\n'); - let (shown, hidden) = if callouts.len() <= CALLOUT_CAP { - (callouts.as_slice(), &[] as &[Callout]) - } else { - callouts.split_at(CALLOUT_CAP) - }; - for c in shown { - out.push_str("- "); - out.push_str(&c.rendered); - out.push('\n'); - } - if !hidden.is_empty() { - out.push('\n'); - let _ = writeln!( - out, - "
{} more callouts", - hidden.len() - ); - out.push('\n'); - for c in hidden { - out.push_str("- "); - out.push_str(&c.rendered); - out.push('\n'); - } - out.push_str("\n
\n"); - } - } - - // Drill-down tables (§39.6). - if let Some(drill) = render_drill_down(&row_file_pairs, ctx) { - out.push('\n'); - out.push_str(&drill); - } - - out.push('\n'); - out.push_str(LEGEND); - out.push('\n'); - out.push('\n'); - out.push_str(FOOTER); - out.push('\n'); - - Some(out) -} - -fn heading_scope(base_label: &str) -> String { - let mut s = String::from(" (this PR vs `"); - s.push_str(base_label); - s.push_str("`)"); - s -} - -// ── DocRow — derived per-file row for the headline table + drill-down ── - -#[derive(Debug, Clone)] -struct DocRow { - path: PathBuf, - display_path: String, - link: String, - mixed_language: bool, - dominant: Language, - short_doc_footnote: bool, - prose_empty_footnote: bool, - dmi: Cell, - words: Cell, - readability: Cell, - link_debt: Cell, - filler: Cell, - filler_value_current: f64, - rci: Cell, - mcc: Cell, - mrpc: Cell, - evidence: Cell, - grounding: Cell, - wqs: Cell, - passive_pct: Cell, - hedges_per_100w: Cell, - long_sentences: Cell, - nominalization_pct: Cell, - mattr_50: Cell, - hapax: Cell, - fog: Cell, - smog: Cell, - ari: Cell, - coleman_liau: Cell, - ja_kanji_pct: Cell, - ja_hiragana_pct: Cell, - ja_katakana_pct: Cell, - ja_avg_sent_chars: Cell, - ja_comma_period_ratio: Cell, - ja_politeness: Option, - has_english: bool, - has_japanese: bool, - sentences_count: u64, - severity_class: u8, -} - -impl DocRow { - fn path_key(&self) -> String { - self.path.to_string_lossy().into_owned() - } - - fn build(file: &DocDiffFile, ctx: &DocRenderCtx<'_>) -> Self { - let path = file.path.clone(); - let display_path = path.to_string_lossy().into_owned(); - let link = build_file_link(&display_path, ctx); - - let head = file.head.as_ref(); - let base = file.base.as_ref(); - - let (dominant, mixed_language) = resolve_dominant_language(head, base); - let (has_english, has_japanese) = detect_language_presence(head, base); - - let reference = head.or(base); - - let dmi = Cell::build( - metric_f64(head, |m| { - m.maintainability.documentation_maintainability_index - }), - metric_f64(base, |m| { - m.maintainability.documentation_maintainability_index - }), - CellKind::Dmi, - file, - ); - let words = Cell::build( - metric_f64(head, |m| m.size.words as f64), - metric_f64(base, |m| m.size.words as f64), - CellKind::Words, - file, - ); - - let mut readability = build_readability_cell(file, dominant); - let prose_empty_footnote = reference - .map(|m| m.prose.meta.words_counted == 0 && m.size.words == 0) - .unwrap_or(false); - if prose_empty_footnote { - readability.footnote = Some(Footnote::ProseEmpty); - } - let short_doc_footnote = matches!(readability.footnote, Some(Footnote::ShortDoc)); - - let link_debt = Cell::build( - metric_f64(head, |m| m.links.link_debt_score), - metric_f64(base, |m| m.links.link_debt_score), - CellKind::LinkDebt, - file, - ); - let filler_value_current = metric_f64(head, |m| m.ai_era.filler_lazy_structure_risk); - let filler = Cell::build( - filler_value_current, - metric_f64(base, |m| m.ai_era.filler_lazy_structure_risk), - CellKind::Filler, - file, - ); - - let rci = Cell::build( - metric_f64(head, |m| m.review.review_criticality_index), - metric_f64(base, |m| m.review.review_criticality_index), - CellKind::Integer, - file, - ); - let mcc = Cell::build( - metric_f64(head, |m| m.complexity.cognitive_complexity), - metric_f64(base, |m| m.complexity.cognitive_complexity), - CellKind::Integer, - file, - ); - let mrpc = Cell::build( - metric_f64(head, |m| m.complexity.reading_path_complexity), - metric_f64(base, |m| m.complexity.reading_path_complexity), - CellKind::Integer, - file, - ); - let evidence = Cell::build( - metric_f64(head, |m| m.grounding.evidence_coverage_score), - metric_f64(base, |m| m.grounding.evidence_coverage_score), - CellKind::Ratio, - file, - ); - let grounding = Cell::build( - metric_f64(head, |m| m.grounding.repository_grounding_score), - metric_f64(base, |m| m.grounding.repository_grounding_score), - CellKind::Ratio, - file, - ); - - let wqs = english_cell(file, |en| en.wording.wording_quality_score, CellKind::Ratio); - let passive_pct = english_cell(file, |en| en.wording.passive_ratio, CellKind::Percentage); - let hedges_per_100w = english_cell( - file, - |en| en.wording.hedge_density * 100.0, - CellKind::OneDecimal, - ); - let long_sentences = english_cell( - file, - |en| en.wording.long_sentence_count as f64, - CellKind::Integer, - ); - let nominalization_pct = english_cell( - file, - |en| en.wording.nominalization_density, - CellKind::Percentage, - ); - let mattr_50 = english_cell(file, |en| en.lexical.mattr_50, CellKind::Ratio); - let hapax = english_cell(file, |en| en.lexical.hapax_ratio, CellKind::Ratio); - let fog = english_readability_cell(file, |r| r.gunning_fog); - let smog = english_readability_cell(file, |r| r.smog); - let ari = english_readability_cell(file, |r| r.ari); - let coleman_liau = english_readability_cell(file, |r| r.coleman_liau); - - let ja_kanji_pct = japanese_cell( - file, - |ja| ja.script_composition.kanji_ratio, - CellKind::Percentage, - ); - let ja_hiragana_pct = japanese_cell( - file, - |ja| ja.script_composition.hiragana_ratio, - CellKind::Percentage, - ); - let ja_katakana_pct = japanese_cell( - file, - |ja| ja.script_composition.katakana_ratio, - CellKind::Percentage, - ); - let ja_avg_sent_chars = japanese_cell( - file, - |ja| ja.lexical.avg_sentence_chars, - CellKind::OneDecimal, - ); - let ja_comma_period_ratio = japanese_cell( - file, - |ja| ja.lexical.comma_period_ratio, - CellKind::OneDecimal, - ); - let ja_politeness = head - .and_then(|m| m.prose.japanese.as_ref()) - .map(|ja| ja.wording.politeness_dominant.clone()); - - let sentences_count = reference - .map(|m| m.prose.meta.sentences_counted) - .unwrap_or(0); - - let mut row = Self { - path, - display_path, - link, - mixed_language, - dominant, - short_doc_footnote, - prose_empty_footnote, - dmi, - words, - readability, - link_debt, - filler, - filler_value_current, - rci, - mcc, - mrpc, - evidence, - grounding, - wqs, - passive_pct, - hedges_per_100w, - long_sentences, - nominalization_pct, - mattr_50, - hapax, - fog, - smog, - ari, - coleman_liau, - ja_kanji_pct, - ja_hiragana_pct, - ja_katakana_pct, - ja_avg_sent_chars, - ja_comma_period_ratio, - ja_politeness, - has_english, - has_japanese, - sentences_count, - severity_class: 0, - }; - row.severity_class = row.compute_severity(); - row - } - - fn compute_severity(&self) -> u8 { - // 4 — objective defects increased or readability regression - if matches!(self.readability.indicator, Indicator::Regression) - || matches!(self.link_debt.indicator, Indicator::Regression) - { - return 4; - } - // 3 — DMI/filler band drops or filler warning. - if matches!(self.dmi.indicator, Indicator::Regression) - || self.filler_value_current >= FILLER_WARN_THRESHOLD - || matches!(self.filler.indicator, Indicator::Regression) - { - return 3; - } - // 2 — new files (summary shown). - if matches!(self.dmi.indicator, Indicator::New) { - return 2; - } - // 1 — improvements present. - if matches!(self.dmi.indicator, Indicator::Improvement) - || matches!(self.filler.indicator, Indicator::Improvement) - || matches!(self.readability.indicator, Indicator::Improvement) - || matches!(self.link_debt.indicator, Indicator::Improvement) - { - return 1; - } - 0 - } -} - -fn metric_f64(m: Option<&MarkdownMetrics>, extract: T) -> f64 -where - T: Fn(&MarkdownMetrics) -> f64, -{ - m.map(extract).unwrap_or(0.0) -} - -fn english_cell(file: &DocDiffFile, extract: T, kind: CellKind) -> Cell -where - T: Fn(&mehen_markdown::prose::english::EnglishReport) -> f64, -{ - let head = file - .head - .as_ref() - .and_then(|m| m.prose.english.as_ref()) - .map(&extract) - .unwrap_or(0.0); - let base = file - .base - .as_ref() - .and_then(|m| m.prose.english.as_ref()) - .map(&extract) - .unwrap_or(0.0); - Cell::build(head, base, kind, file) -} - -fn english_readability_cell(file: &DocDiffFile, extract: T) -> Cell -where - T: Fn(&mehen_markdown::prose::english::readability::ReadabilityReport) -> Option, -{ - let head = file - .head - .as_ref() - .and_then(|m| m.prose.english.as_ref()) - .and_then(|en| extract(&en.readability)) - .unwrap_or(0.0); - let base = file - .base - .as_ref() - .and_then(|m| m.prose.english.as_ref()) - .and_then(|en| extract(&en.readability)) - .unwrap_or(0.0); - Cell::build(head, base, CellKind::OneDecimal, file) -} - -fn japanese_cell(file: &DocDiffFile, extract: T, kind: CellKind) -> Cell -where - T: Fn(&mehen_markdown::prose::japanese::JapaneseReport) -> f64, -{ - let head = file - .head - .as_ref() - .and_then(|m| m.prose.japanese.as_ref()) - .map(&extract) - .unwrap_or(0.0); - let base = file - .base - .as_ref() - .and_then(|m| m.prose.japanese.as_ref()) - .map(&extract) - .unwrap_or(0.0); - Cell::build(head, base, kind, file) -} - -fn build_readability_cell(file: &DocDiffFile, dominant: Language) -> Cell { - let (head_val, head_short) = readability_value(file.head.as_ref(), dominant); - let (base_val, base_short) = readability_value(file.base.as_ref(), dominant); - let kind = match dominant { - Language::Ja => CellKind::OneDecimalHigherBetter, - _ => CellKind::OneDecimal, - }; - let mut cell = Cell::build(head_val.unwrap_or(0.0), base_val.unwrap_or(0.0), kind, file); - // For a *deleted* file the head side is None by construction. Falling - // back to the ShortDoc footnote would hide the baseline readability - // that the doc used to report. Instead, let the Deleted render path - // preserve the baseline value with the regression indicator (e.g. - // `0 (was: 12.7) 🔴`) so reviewers still see what was lost. - if file.is_deleted { - if base_val.is_none() { - cell.footnote = Some(Footnote::ShortDoc); - } - } else if head_val.is_none() || head_short { - cell.footnote = Some(Footnote::ShortDoc); - } - let _ = base_short; - cell -} - -fn readability_value(m: Option<&MarkdownMetrics>, dominant: Language) -> (Option, bool) { - let Some(metrics) = m else { - return (None, true); - }; - match dominant { - Language::Ja => { - if let Some(ja) = metrics.prose.japanese.as_ref() { - (ja.readability.tateishi_rs, ja.short_doc_warning) - } else { - (None, true) - } - } - _ => { - if let Some(en) = metrics.prose.english.as_ref() { - (en.readability.flesch_kincaid_grade, en.short_doc_warning) - } else { - (None, true) - } - } - } -} - -fn resolve_dominant_language( - head: Option<&MarkdownMetrics>, - base: Option<&MarkdownMetrics>, -) -> (Language, bool) { - let side = head.or(base); - let Some(m) = side else { - return (Language::En, false); - }; - let lang = match m.prose.language_detection.dominant_language.as_str() { - "ja" => Language::Ja, - "mixed" => Language::Mixed, - "en" => Language::En, - _ => Language::En, - }; - let mixed = matches!(lang, Language::Mixed); - let dominant = if mixed { - let en = m - .prose - .language_detection - .blocks - .iter() - .filter(|b| b.language == "en") - .count(); - let ja = m - .prose - .language_detection - .blocks - .iter() - .filter(|b| b.language == "ja") - .count(); - if ja > en { Language::Ja } else { Language::En } - } else { - lang - }; - (dominant, mixed) -} - -fn detect_language_presence( - head: Option<&MarkdownMetrics>, - base: Option<&MarkdownMetrics>, -) -> (bool, bool) { - let has_en = head.is_some_and(|m| m.prose.english.is_some()) - || base.is_some_and(|m| m.prose.english.is_some()); - let has_ja = head.is_some_and(|m| m.prose.japanese.is_some()) - || base.is_some_and(|m| m.prose.japanese.is_some()); - (has_en, has_ja) -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum Language { - En, - Ja, - Mixed, -} - -// ── Cell formatting ──────────────────────────────────────────────────── - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum CellKind { - Integer, - Words, - /// 2-decimal ratios in `[0, 1]`. - Ratio, - /// 2-decimal percent, rendered as `NN%`. - Percentage, - /// 1-decimal number. - OneDecimal, - /// 1-decimal number where higher is better (Tateishi RS). - OneDecimalHigherBetter, - /// Integer DMI (0–100) with band-aware delta rules. - Dmi, - /// Link debt score (0–1, lower better, any new broken link → 🔴). - LinkDebt, - /// Filler risk (0–1, lower better, warn threshold 0.60). - Filler, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum Indicator { - Improvement, - Regression, - Attention, - New, - Unchanged, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum Footnote { - ShortDoc, - ProseEmpty, -} - -#[derive(Debug, Clone, Copy)] -struct Cell { - head: f64, - base: f64, - kind: CellKind, - is_new: bool, - is_deleted: bool, - indicator: Indicator, - footnote: Option, -} - -impl Cell { - fn build(head: f64, base: f64, kind: CellKind, file: &DocDiffFile) -> Self { - let is_new = file.is_new; - let is_deleted = file.is_deleted; - let indicator = compute_indicator(head, base, kind, is_new, is_deleted); - Self { - head, - base, - kind, - is_new, - is_deleted, - indicator, - footnote: None, - } - } - - fn render(&self, base_label: &str) -> String { - if let Some(Footnote::ProseEmpty) = self.footnote { - return String::from("\u{2014} \u{00B3}"); - } - if let Some(Footnote::ShortDoc) = self.footnote { - return String::from("\u{2014} \u{00B2}"); - } - let head = format_value(self.head, self.kind); - if self.is_new { - let emoji = indicator_emoji(Indicator::New); - return format!("{head} {emoji}"); - } - if self.is_deleted { - let base = format_value(self.base, self.kind); - let emoji = indicator_emoji(Indicator::Regression); - return format!("0 (was: {base}) {emoji}"); - } - if (self.base - self.head).abs() < f64::EPSILON - && !matches!(self.indicator, Indicator::Attention) - { - let emoji = indicator_emoji(Indicator::Unchanged); - return format!("{head} {emoji}"); - } - if matches!(self.indicator, Indicator::Unchanged) { - let base = format_value(self.base, self.kind); - let emoji = indicator_emoji(Indicator::Unchanged); - return format!("{head} ({base_label}: {base}) {emoji}"); - } - let base = format_value(self.base, self.kind); - let emoji = indicator_emoji(self.indicator); - format!("{head} ({base_label}: {base}) {emoji}") - } -} - -fn compute_indicator( - head: f64, - base: f64, - kind: CellKind, - is_new: bool, - is_deleted: bool, -) -> Indicator { - if is_new { - return Indicator::New; - } - if is_deleted { - return Indicator::Regression; - } - let delta = head - base; - match kind { - CellKind::Words | CellKind::Integer => Indicator::Unchanged, - CellKind::Dmi => { - let old_band = band_label(base, &DMI_BANDS); - let new_band = band_label(head, &DMI_BANDS); - if old_band != new_band && head > base { - return Indicator::Improvement; - } - if old_band != new_band && head < base { - return Indicator::Regression; - } - if delta <= -DMI_NOTICEABLE { - return Indicator::Regression; - } - if delta >= DMI_NOTICEABLE { - return Indicator::Improvement; - } - Indicator::Unchanged - } - CellKind::LinkDebt => { - if delta >= LINK_DEBT_NOTICEABLE { - Indicator::Regression - } else if delta <= -LINK_DEBT_NOTICEABLE { - Indicator::Improvement - } else { - Indicator::Unchanged - } - } - CellKind::Filler => { - if head >= FILLER_WARN_THRESHOLD && delta >= 0.0 { - return Indicator::Attention; - } - if delta >= FILLER_NOTICEABLE { - Indicator::Regression - } else if delta <= -FILLER_NOTICEABLE { - Indicator::Improvement - } else { - Indicator::Unchanged - } - } - CellKind::OneDecimal => { - if delta.abs() < FKGL_NOTICEABLE { - return Indicator::Unchanged; - } - if delta > 0.0 { - Indicator::Regression - } else { - Indicator::Improvement - } - } - CellKind::OneDecimalHigherBetter => { - if delta.abs() < TATEISHI_NOTICEABLE { - return Indicator::Unchanged; - } - if delta > 0.0 { - Indicator::Improvement - } else { - Indicator::Regression - } - } - CellKind::Ratio | CellKind::Percentage => { - if delta.abs() < 0.02 { - Indicator::Unchanged - } else if delta > 0.0 { - Indicator::Regression - } else { - Indicator::Improvement - } - } - } -} - -fn indicator_emoji(ind: Indicator) -> &'static str { - match ind { - Indicator::Improvement => "\u{1F7E2}", - Indicator::Regression => "\u{1F534}", - Indicator::Attention => "\u{26A0}\u{FE0F}", - Indicator::New => "\u{1F195}", - Indicator::Unchanged => "\u{26AA}", - } -} - -fn format_value(v: f64, kind: CellKind) -> String { - match kind { - CellKind::Integer => format!("{}", v.round() as i64), - CellKind::Words => format_int_thousands(v.round() as i64), - CellKind::Ratio => format!("{:.2}", v), - CellKind::Percentage => format!("{}%", (v * 100.0).round() as i64), - CellKind::OneDecimal | CellKind::OneDecimalHigherBetter => format!("{:.1}", v), - CellKind::Dmi => format!("{}", v.round() as i64), - CellKind::LinkDebt | CellKind::Filler => format!("{:.2}", v), - } -} - -fn format_int_thousands(v: i64) -> String { - let s = v.abs().to_string(); - let mut out = String::new(); - if v < 0 { - out.push('-'); - } - let digits: Vec = s.chars().collect(); - let len = digits.len(); - for (i, c) in digits.iter().enumerate() { - let from_end = len - i; - if i > 0 && from_end.is_multiple_of(3) { - out.push(','); - } - out.push(*c); - } - out -} - -fn band_label(v: f64, bands: &[(f64, &'static str)]) -> &'static str { - let mut current: &'static str = bands[0].1; - for &(floor, label) in bands { - if v >= floor { - current = label; - } else { - break; - } - } - current -} - -fn filler_band_for(v: f64) -> &'static str { - if v < FILLER_BANDS[0] { - FILLER_BAND_LABELS[0] - } else if v < FILLER_BANDS[1] { - FILLER_BAND_LABELS[1] - } else if v < FILLER_BANDS[2] { - FILLER_BAND_LABELS[2] - } else if v < FILLER_BANDS[3] { - FILLER_BAND_LABELS[3] - } else { - FILLER_BAND_LABELS[4] - } -} - -fn build_file_link(display_path: &str, ctx: &DocRenderCtx<'_>) -> String { - match (ctx.repo_url, ctx.head_sha) { - (Some(url), Some(sha)) => { - format!("[{display_path}]({url}/blob/{sha}/{display_path})") - } - _ => format!("`{display_path}`"), - } -} - -// ── Headline table rendering ─────────────────────────────────────────── - -fn write_headline_table(out: &mut String, rows: &[&DocRow], ctx: &DocRenderCtx<'_>) { - let dominant = rows - .iter() - .map(|r| r.dominant) - .find(|l| !matches!(l, Language::Mixed)) - .unwrap_or(Language::En); - let readability_label = match dominant { - Language::Ja => "Tateishi RS", - _ => "FKGL", - }; - let _ = writeln!( - out, - "| File | DMI | Words | {readability_label} | Link Debt | Filler Risk |" - ); - out.push_str("|---|---:|---:|---:|---:|---:|\n"); - for r in rows { - let suffix = if r.mixed_language { " \u{1F30F}" } else { "" }; - let _ = writeln!( - out, - "| {file}{suffix} | {dmi} | {words} | {readability} | {linkdebt} | {filler} |", - file = r.link, - dmi = r.dmi.render(ctx.base_label), - words = r.words.render(ctx.base_label), - readability = r.readability.render(ctx.base_label), - linkdebt = r.link_debt.render(ctx.base_label), - filler = r.filler.render(ctx.base_label), - ); - } -} - -// ── Callouts ────────────────────────────────────────────────────────── - -#[derive(Debug, Clone)] -struct Callout { - severity: u8, - magnitude: f64, - rule_id: &'static str, - path: PathBuf, - line_key: u64, - rendered: String, -} - -fn emit_callouts_for_file( - row: &DocRow, - file: &DocDiffFile, - ctx: &DocRenderCtx<'_>, - out: &mut Vec, -) { - let head = file.head.as_ref(); - let base = file.base.as_ref(); - - // New-file summary (severity 6). - if file.is_new { - if let Some(m) = head { - out.push(template_new_file_summary(row, m)); - } - return; - } - - if let Some(m) = head { - emit_new_link_defects(row, m, base, out); - emit_new_diagram_parse_errors(row, m, base, out); - emit_new_inclusive_flags(row, m, base, out); - emit_new_lexical_illusions(row, m, base, out); - emit_new_nonwords(row, m, base, out); - emit_new_heading_skips(row, m, base, out); - } - - if let Some(m) = head { - emit_filler_high(row, m, out); - } - emit_dmi_band_drop(row, out); - emit_evidence_band_drop(row, out); - emit_grounding_band_drop(row, out); - - if let Some(m) = head { - emit_new_long_sentences(row, m, base, ctx, out); - emit_passive_ratio_breach(row, m, base, ctx, out); - emit_readability_target_breach(row, m, base, ctx, out); - emit_tateishi_band_drop(row, m, base, out); - emit_table_burden_hard(row, m, base, out); - emit_doubled_joshi(row, m, base, out); - emit_kanji_run(row, m, base, out); - } - - if let Some(m) = head { - emit_code_fence_unlabeled(row, m, base, out); - emit_diagram_missing_caption(row, m, base, out); - emit_image_missing_alt(row, m, base, out); - } - - emit_dmi_band_improve(row, out); - emit_filler_band_improve(row, out); - if let Some(m) = head { - emit_broken_links_resolved(row, m, base, out); - emit_long_sentences_resolved(row, m, base, ctx, out); - emit_readability_target_recovered(row, m, base, ctx, out); - } -} - -// ── §39.5.2 template emitters ────────────────────────────────────────── - -fn template_new_file_summary(row: &DocRow, m: &MarkdownMetrics) -> Callout { - let dmi = m - .maintainability - .documentation_maintainability_index - .round() as i64; - let filler = m.ai_era.filler_lazy_structure_risk; - let band = filler_band_for(filler); - let words = m.size.words; - let headings = m.size.headings; - let code_fences = m - .artifacts - .iter() - .filter(|a| matches!(a.kind, ArtifactKind::Code)) - .count() as u64; - let diagrams = m - .artifacts - .iter() - .filter(|a| matches!(a.kind, ArtifactKind::Diagram)) - .count() as u64; - let tables = m - .artifacts - .iter() - .filter(|a| matches!(a.kind, ArtifactKind::Table)) - .count() as u64; - let rendered = tmpl_new_file_summary( - &row.display_path, - words, - headings, - code_fences, - diagrams, - tables, - dmi, - filler, - band, - ); - Callout { - severity: 6, - magnitude: 0.0, - rule_id: "new_file_summary", - path: row.path.clone(), - line_key: 0, - rendered, - } -} - -fn emit_new_link_defects( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - // §39.4 regression: count broken-link *occurrences* per (class, destination) - // key. If base has 1 broken `./guide.md` and head has 2, the second new - // occurrence must be reported. A set-diff drops the duplicate; we keep a - // multiset count-per-key map on each side so `new_broken = max(0, head - - // base)` per key can be summed into the emitted list. - let mut base_counts: std::collections::BTreeMap<(LinkClass, String), usize> = - std::collections::BTreeMap::new(); - if let Some(b) = base { - for l in &b.link_records { - if !matches!(l.resolved, Some(false)) { - continue; - } - *base_counts - .entry((l.class, l.destination.clone())) - .or_insert(0) += 1; - } - } - - // Group head's broken-link occurrences by (class, destination) so we can - // subtract the base multiset one-for-one and keep the remaining new - // occurrences. Each occurrence keeps its own line for the callout list. - let mut head_groups: std::collections::BTreeMap<(LinkClass, String), Vec> = - std::collections::BTreeMap::new(); - for l in &head.link_records { - if !matches!(l.resolved, Some(false)) { - continue; - } - head_groups - .entry((l.class, l.destination.clone())) - .or_default() - .push(l.line); - } - - let mut relative: Vec<(u64, String)> = Vec::new(); - let mut anchor: Vec<(u64, String)> = Vec::new(); - let mut external: Vec<(u64, String)> = Vec::new(); - for ((class, destination), mut lines) in head_groups { - lines.sort(); - let drop = base_counts - .get(&(class, destination.clone())) - .copied() - .unwrap_or(0); - // Drop the first `drop` occurrences as already-broken in base; any - // remaining occurrences are net-new broken references for head. - let new_occurrences = lines.into_iter().skip(drop); - match class { - LinkClass::Relative => { - for line in new_occurrences { - relative.push((line, destination.clone())); - } - } - LinkClass::Internal => { - for line in new_occurrences { - anchor.push((line, destination.clone())); - } - } - LinkClass::External - | LinkClass::ExternalVendor - | LinkClass::Scholarly - | LinkClass::IssuePr - | LinkClass::AbsoluteSameRepo => { - for line in new_occurrences { - external.push((line, destination.clone())); - } - } - _ => {} - } - } - relative.sort(); - anchor.sort(); - external.sort(); - if !relative.is_empty() { - let list = format_link_list(&relative); - out.push(callout( - 1, - relative.len() as f64, - "broken_relative_link_added", - &row.path, - relative[0].0, - tmpl_broken_relative_link_added(&row.display_path, relative.len() as u64, &list), - )); - } - if !anchor.is_empty() { - let list = format_link_list(&anchor); - out.push(callout( - 1, - anchor.len() as f64, - "broken_anchor_added", - &row.path, - anchor[0].0, - tmpl_broken_anchor_added(&row.display_path, anchor.len() as u64, &list), - )); - } - if !external.is_empty() { - let list = format_link_list(&external); - out.push(callout( - 1, - external.len() as f64, - "broken_external_link_added", - &row.path, - external[0].0, - tmpl_broken_external_link_added(&row.display_path, external.len() as u64, &list), - )); - } -} - -fn emit_new_diagram_parse_errors( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - // §39.5.2 `diagram_parse_error_added`: only emit when a diagram parser - // actually failed in head. We use the aggregate - // `visuals.diagram_parse_error_count` on `MarkdownMetrics` as the source - // of truth — fed by Phase C's per-diagram `parse_error` flag — to avoid - // the previous false positive that fired on *any* new diagram. - // - // TODO(phase-next): thread `parse_error` through `ArtifactRecord` so we - // can point at the specific diagram instead of the first entry by index. - let head_errors = head.visuals.diagram_parse_error_count; - let base_errors = base - .map(|b| b.visuals.diagram_parse_error_count) - .unwrap_or(0); - // Parse errors grew is the authoritative signal — whether through an - // added diagram or an existing diagram getting edited into an invalid - // state. The previous guard on diagram *count* grow suppressed the - // "existing diagram broken" case (Codex P2 on PR #89). - if head_errors <= base_errors { - return; - } - let head_list = diagram_artifact_lines(head); - let Some((line, lang)) = head_list.first() else { - return; - }; - out.push(callout( - 1, - (head_errors - base_errors) as f64, - "diagram_parse_error_added", - &row.path, - *line, - tmpl_diagram_parse_error_added(&row.display_path, lang, *line), - )); -} - -fn diagram_artifact_lines(m: &MarkdownMetrics) -> Vec<(u64, String)> { - let mut out: Vec<(u64, String)> = m - .artifacts - .iter() - .filter(|a| matches!(a.kind, ArtifactKind::Diagram)) - .map(|a| { - ( - a.start_line, - a.language_tag - .clone() - .unwrap_or_else(|| String::from("diagram")), - ) - }) - .collect(); - out.sort(); - out -} - -fn emit_new_inclusive_flags( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_flags = head - .prose - .english - .as_ref() - .map(|en| en.inclusive_language.flag_count) - .unwrap_or(0); - let base_flags = base - .and_then(|m| m.prose.english.as_ref()) - .map(|en| en.inclusive_language.flag_count) - .unwrap_or(0); - if head_flags <= base_flags { - return; - } - let delta = head_flags - base_flags; - let mut flags: Vec = head - .prose - .english - .as_ref() - .map(|en| { - en.inclusive_language - .flags - .iter() - .map(|f| f.surface.clone()) - .collect() - }) - .unwrap_or_default(); - flags.sort(); - let list = format_surface_list_without_line(&flags, delta as usize); - out.push(callout( - 1, - delta as f64, - "inclusive_language_flag_added", - &row.path, - 0, - tmpl_inclusive_language_flag_added(&row.display_path, delta, &list), - )); -} - -fn emit_new_lexical_illusions( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_n = head - .prose - .english - .as_ref() - .map(|en| en.wording.lexical_illusions) - .unwrap_or(0); - let base_n = base - .and_then(|m| m.prose.english.as_ref()) - .map(|en| en.wording.lexical_illusions) - .unwrap_or(0); - if head_n > base_n { - // §39.5.2 allows the {L:N…} line-number list to be omitted when - // per-occurrence surface/line data isn't propagated; we report the - // aggregate delta only. TODO(phase-next): thread per-occurrence - // surfaces + lines from `WordingReport` into the callout. - let delta = head_n - base_n; - out.push(callout( - 1, - delta as f64, - "lexical_illusion_added", - &row.path, - 0, - tmpl_lexical_illusion_added(&row.display_path, delta), - )); - } -} - -fn emit_new_nonwords( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_n = head - .prose - .english - .as_ref() - .map(|en| en.wording.nonword_count) - .unwrap_or(0); - let base_n = base - .and_then(|m| m.prose.english.as_ref()) - .map(|en| en.wording.nonword_count) - .unwrap_or(0); - if head_n > base_n { - // Per-occurrence surface + line numbers aren't threaded into the - // diff emitter yet; report the aggregate delta only, consistent with - // §39.5.2's allowance for omitted {L:N…} lists. - let delta = head_n - base_n; - out.push(callout( - 1, - delta as f64, - "nonword_added", - &row.path, - 0, - tmpl_nonword_added(&row.display_path, delta), - )); - } -} - -fn emit_new_heading_skips( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_skips = heading_skip_list(head); - let base_skips = base.map(heading_skip_list).unwrap_or_default(); - if head_skips.len() <= base_skips.len() { - return; - } - if let Some(skip) = head_skips.get(base_skips.len()) { - out.push(callout( - 1, - 1.0, - "heading_skip_added", - &row.path, - skip.line, - tmpl_heading_skip_added(&row.display_path, skip.old_level, skip.new_level, skip.line), - )); - } -} - -#[derive(Debug, Clone, Copy)] -struct HeadingSkip { - old_level: u8, - new_level: u8, - line: u64, -} - -fn heading_skip_list(m: &MarkdownMetrics) -> Vec { - let mut out: Vec = Vec::new(); - let mut prev_level: u8 = 0; - for s in &m.sections { - let Some(level) = s.heading_level else { - continue; - }; - if prev_level > 0 && level > prev_level + 1 { - out.push(HeadingSkip { - old_level: prev_level, - new_level: level, - line: s.start_line, - }); - } - prev_level = level; - } - out -} - -fn emit_filler_high(row: &DocRow, head: &MarkdownMetrics, out: &mut Vec) { - let risk = head.ai_era.filler_lazy_structure_risk; - if risk < FILLER_WARN_THRESHOLD { - return; - } - let band = filler_band_for(risk); - let contributors: Vec<(String, f64)> = head - .ai_era - .top_contributors - .iter() - .take(3) - .map(|(l, v)| (l.clone(), *v)) - .collect(); - out.push(callout( - 2, - risk, - "filler_risk_high", - &row.path, - 0, - tmpl_filler_risk_high(&row.display_path, risk, band, &contributors), - )); -} - -fn emit_dmi_band_drop(row: &DocRow, out: &mut Vec) { - if !matches!(row.dmi.indicator, Indicator::Regression) { - return; - } - let old_band = band_label(row.dmi.base, &DMI_BANDS); - let new_band = band_label(row.dmi.head, &DMI_BANDS); - if old_band == new_band { - return; - } - out.push(callout( - 2, - (row.dmi.base - row.dmi.head).abs(), - "dmi_band_drop", - &row.path, - 0, - tmpl_dmi_band_drop( - &row.display_path, - row.dmi.base.round() as i64, - row.dmi.head.round() as i64, - old_band, - new_band, - ), - )); -} - -fn emit_dmi_band_improve(row: &DocRow, out: &mut Vec) { - if !matches!(row.dmi.indicator, Indicator::Improvement) { - return; - } - let old_band = band_label(row.dmi.base, &DMI_BANDS); - let new_band = band_label(row.dmi.head, &DMI_BANDS); - if old_band == new_band { - return; - } - out.push(callout( - 5, - (row.dmi.head - row.dmi.base).abs(), - "dmi_band_improve", - &row.path, - 0, - tmpl_dmi_band_improve( - &row.display_path, - row.dmi.base.round() as i64, - row.dmi.head.round() as i64, - old_band, - new_band, - ), - )); -} - -fn emit_filler_band_improve(row: &DocRow, out: &mut Vec) { - if !matches!(row.filler.indicator, Indicator::Improvement) { - return; - } - let old_band = filler_band_for(row.filler.base); - let new_band = filler_band_for(row.filler.head); - if old_band == new_band { - return; - } - out.push(callout( - 5, - (row.filler.base - row.filler.head).abs(), - "filler_risk_band_improve", - &row.path, - 0, - tmpl_filler_risk_band_improve( - &row.display_path, - row.filler.base, - row.filler.head, - old_band, - new_band, - ), - )); -} - -fn emit_evidence_band_drop(row: &DocRow, out: &mut Vec) { - if !matches!(row.evidence.indicator, Indicator::Regression) { - return; - } - let old_band = band_label(row.evidence.base, &EVIDENCE_BANDS); - let new_band = band_label(row.evidence.head, &EVIDENCE_BANDS); - if old_band == new_band { - return; - } - out.push(callout( - 2, - (row.evidence.base - row.evidence.head).abs(), - "evidence_band_drop", - &row.path, - 0, - tmpl_evidence_band_drop( - &row.display_path, - row.evidence.base, - row.evidence.head, - old_band, - new_band, - ), - )); -} - -fn emit_grounding_band_drop(row: &DocRow, out: &mut Vec) { - if !matches!(row.grounding.indicator, Indicator::Regression) { - return; - } - let old_band = band_label(row.grounding.base, &GROUNDING_BANDS); - let new_band = band_label(row.grounding.head, &GROUNDING_BANDS); - if old_band == new_band { - return; - } - out.push(callout( - 2, - (row.grounding.base - row.grounding.head).abs(), - "repo_grounding_band_drop", - &row.path, - 0, - tmpl_repo_grounding_band_drop( - &row.display_path, - row.grounding.base, - row.grounding.head, - old_band, - new_band, - ), - )); -} - -fn emit_new_long_sentences( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - ctx: &DocRenderCtx<'_>, - out: &mut Vec, -) { - let head_n = head - .prose - .english - .as_ref() - .map(|en| en.wording.long_sentence_count) - .unwrap_or(0); - let base_n = base - .and_then(|m| m.prose.english.as_ref()) - .map(|en| en.wording.long_sentence_count) - .unwrap_or(0); - if head_n <= base_n { - return; - } - let delta = head_n - base_n; - let lines_str = repeat_lines(delta as usize); - out.push(callout( - 3, - delta as f64, - "long_sentences_added", - &row.path, - 0, - tmpl_long_sentences_added( - &row.display_path, - delta, - ctx.long_sentence_threshold, - &lines_str, - ), - )); -} - -fn emit_long_sentences_resolved( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - ctx: &DocRenderCtx<'_>, - out: &mut Vec, -) { - let head_n = head - .prose - .english - .as_ref() - .map(|en| en.wording.long_sentence_count) - .unwrap_or(0); - let base_n = base - .and_then(|m| m.prose.english.as_ref()) - .map(|en| en.wording.long_sentence_count) - .unwrap_or(0); - if base_n <= head_n { - return; - } - let delta = base_n - head_n; - out.push(callout( - 5, - delta as f64, - "long_sentences_resolved", - &row.path, - 0, - tmpl_long_sentences_resolved(&row.display_path, delta, ctx.long_sentence_threshold), - )); -} - -fn emit_passive_ratio_breach( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - ctx: &DocRenderCtx<'_>, - out: &mut Vec, -) { - let head_ratio = head - .prose - .english - .as_ref() - .map(|en| en.wording.passive_ratio) - .unwrap_or(0.0); - let base_ratio = base - .and_then(|m| m.prose.english.as_ref()) - .map(|en| en.wording.passive_ratio) - .unwrap_or(0.0); - if head_ratio <= ctx.passive_max || head_ratio <= base_ratio { - return; - } - out.push(callout( - 3, - head_ratio - base_ratio, - "passive_ratio_breach", - &row.path, - 0, - tmpl_passive_ratio_breach( - &row.display_path, - base_ratio, - head_ratio, - ctx.readability_profile, - ctx.passive_max, - ), - )); -} - -fn emit_readability_target_breach( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - ctx: &DocRenderCtx<'_>, - out: &mut Vec, -) { - if !matches!(row.readability.indicator, Indicator::Regression) { - return; - } - if matches!(row.dominant, Language::Ja) { - return; - } - let head_fkgl = head - .prose - .english - .as_ref() - .and_then(|en| en.readability.flesch_kincaid_grade); - let base_fkgl = base - .and_then(|m| m.prose.english.as_ref()) - .and_then(|en| en.readability.flesch_kincaid_grade); - let (Some(h), Some(b)) = (head_fkgl, base_fkgl) else { - return; - }; - if h <= ctx.readability_target { - return; - } - out.push(callout( - 3, - h - b, - "readability_target_breach", - &row.path, - 0, - tmpl_readability_target_breach( - &row.display_path, - "FKGL", - b, - h, - ctx.readability_profile, - ctx.readability_target, - ), - )); -} - -fn emit_readability_target_recovered( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - ctx: &DocRenderCtx<'_>, - out: &mut Vec, -) { - if !matches!(row.readability.indicator, Indicator::Improvement) { - return; - } - if matches!(row.dominant, Language::Ja) { - return; - } - let head_fkgl = head - .prose - .english - .as_ref() - .and_then(|en| en.readability.flesch_kincaid_grade); - let base_fkgl = base - .and_then(|m| m.prose.english.as_ref()) - .and_then(|en| en.readability.flesch_kincaid_grade); - let (Some(h), Some(b)) = (head_fkgl, base_fkgl) else { - return; - }; - if b <= ctx.readability_target || h > ctx.readability_target { - return; - } - out.push(callout( - 5, - b - h, - "readability_target_recovered", - &row.path, - 0, - tmpl_readability_target_recovered( - &row.display_path, - "FKGL", - b, - h, - ctx.readability_profile, - ctx.readability_target, - ), - )); -} - -fn emit_tateishi_band_drop( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - if !matches!(row.dominant, Language::Ja) { - return; - } - let head_rs = head - .prose - .japanese - .as_ref() - .and_then(|j| j.readability.tateishi_rs); - let base_rs = base - .and_then(|m| m.prose.japanese.as_ref()) - .and_then(|j| j.readability.tateishi_rs); - let (Some(h), Some(b)) = (head_rs, base_rs) else { - return; - }; - if b - h < TATEISHI_NOTICEABLE { - return; - } - out.push(callout( - 3, - b - h, - "tateishi_band_drop", - &row.path, - 0, - tmpl_tateishi_band_drop(&row.display_path, b, h), - )); -} - -fn emit_table_burden_hard( - row: &DocRow, - head: &MarkdownMetrics, - _base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - for a in &head.artifacts { - if !matches!(a.kind, ArtifactKind::Table) || !a.oversized { - continue; - } - out.push(callout( - 3, - a.size as f64, - "table_burden_hard", - &row.path, - a.start_line, - tmpl_table_burden_hard(&row.display_path, a.start_line, a.size), - )); - return; - } -} - -fn emit_doubled_joshi( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_n = head - .prose - .japanese - .as_ref() - .map(|ja| ja.wording.doubled_joshi_count) - .unwrap_or(0); - let base_n = base - .and_then(|m| m.prose.japanese.as_ref()) - .map(|ja| ja.wording.doubled_joshi_count) - .unwrap_or(0); - if head_n <= base_n { - return; - } - // Per-particle surface + line numbers aren't threaded through yet. - // Report the aggregate count only. TODO(phase-next): propagate particle - // surfaces from the Japanese wording analyzer. - let delta = head_n - base_n; - out.push(callout( - 3, - delta as f64, - "doubled_joshi_added", - &row.path, - 0, - tmpl_doubled_joshi_added(&row.display_path, delta), - )); -} - -fn emit_kanji_run( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_n = head - .prose - .japanese - .as_ref() - .map(|ja| ja.wording.long_kanji_run_count) - .unwrap_or(0); - let base_n = base - .and_then(|m| m.prose.japanese.as_ref()) - .map(|ja| ja.wording.long_kanji_run_count) - .unwrap_or(0); - if head_n <= base_n { - return; - } - // Per-run length + surface aren't threaded through yet. Report aggregate - // count only. TODO(phase-next): propagate run length + surface from the - // Japanese kanji-run analyzer. - let delta = head_n - base_n; - out.push(callout( - 3, - delta as f64, - "kanji_run_too_long_added", - &row.path, - 0, - tmpl_kanji_run_too_long_added(&row.display_path, delta), - )); -} - -fn emit_code_fence_unlabeled( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_unlabeled = unlabeled_fence_lines(head); - let base_unlabeled = base.map(unlabeled_fence_lines).unwrap_or_default(); - if head_unlabeled.len() <= base_unlabeled.len() { - return; - } - if let Some(line) = head_unlabeled.get(base_unlabeled.len()) { - out.push(callout( - 4, - 1.0, - "code_fence_unlabeled_added", - &row.path, - *line, - tmpl_code_fence_unlabeled_added(&row.display_path, *line), - )); - } -} - -fn unlabeled_fence_lines(m: &MarkdownMetrics) -> Vec { - let mut out: Vec = m - .artifacts - .iter() - .filter(|a| matches!(a.kind, ArtifactKind::Code) && !a.has_label) - .map(|a| a.start_line) - .collect(); - out.sort(); - out -} - -fn emit_diagram_missing_caption( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_missing = missing_caption_diagrams(head); - let base_missing = base.map(missing_caption_diagrams).unwrap_or_default(); - if head_missing.len() <= base_missing.len() { - return; - } - if let Some((line, lang)) = head_missing.get(base_missing.len()) { - out.push(callout( - 4, - 1.0, - "diagram_missing_caption_added", - &row.path, - *line, - tmpl_diagram_missing_caption_added(&row.display_path, lang, *line), - )); - } -} - -fn missing_caption_diagrams(m: &MarkdownMetrics) -> Vec<(u64, String)> { - let mut out: Vec<(u64, String)> = m - .artifacts - .iter() - .filter(|a| matches!(a.kind, ArtifactKind::Diagram) && !a.has_explanation) - .map(|a| { - ( - a.start_line, - a.language_tag - .clone() - .unwrap_or_else(|| String::from("diagram")), - ) - }) - .collect(); - out.sort(); - out -} - -fn emit_image_missing_alt( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let head_missing = missing_alt_images(head); - let base_missing = base.map(missing_alt_images).unwrap_or_default(); - if head_missing.len() <= base_missing.len() { - return; - } - if let Some((line, dest)) = head_missing.get(base_missing.len()) { - out.push(callout( - 4, - 1.0, - "image_missing_alt_added", - &row.path, - *line, - tmpl_image_missing_alt_added(&row.display_path, dest, *line), - )); - } -} - -fn missing_alt_images(m: &MarkdownMetrics) -> Vec<(u64, String)> { - let mut out: Vec<(u64, String)> = m - .artifacts - .iter() - .filter(|a| matches!(a.kind, ArtifactKind::Image) && !a.has_label) - .map(|a| (a.start_line, String::new())) - .collect(); - out.sort(); - out -} - -fn emit_broken_links_resolved( - row: &DocRow, - head: &MarkdownMetrics, - base: Option<&MarkdownMetrics>, - out: &mut Vec, -) { - let Some(b) = base else { - return; - }; - let base_set: std::collections::BTreeSet<(LinkClass, String)> = b - .link_records - .iter() - .filter(|l| matches!(l.resolved, Some(false))) - .map(|l| (l.class, l.destination.clone())) - .collect(); - let head_set: std::collections::BTreeSet<(LinkClass, String)> = head - .link_records - .iter() - .filter(|l| matches!(l.resolved, Some(false))) - .map(|l| (l.class, l.destination.clone())) - .collect(); - let resolved = base_set.difference(&head_set).count() as u64; - if resolved == 0 { - return; - } - out.push(callout( - 5, - resolved as f64, - "broken_links_resolved", - &row.path, - 0, - tmpl_broken_links_resolved(&row.display_path, resolved), - )); -} - -// ── Helpers ─────────────────────────────────────────────────────────── - -fn format_link_list(items: &[(u64, String)]) -> String { - let mut out = String::new(); - for (i, (line, dest)) in items.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - let _ = write!(out, "`{}` (L{})", dest, line); - } - out -} - -fn format_surface_list_without_line(items: &[String], cap: usize) -> String { - let mut out = String::new(); - for (i, s) in items.iter().take(cap).enumerate() { - if i > 0 { - out.push_str(", "); - } - let _ = write!(out, "`{s}` (L0)"); - } - out -} - -fn repeat_lines(n: usize) -> String { - let mut out = String::new(); - for i in 0..n { - if i > 0 { - out.push_str(", "); - } - out.push_str("L0"); - } - out -} - -fn callout( - severity: u8, - magnitude: f64, - rule_id: &'static str, - path: &Path, - line: u64, - rendered: String, -) -> Callout { - Callout { - severity, - magnitude, - rule_id, - path: path.to_path_buf(), - line_key: line, - rendered, - } -} - -// ── §39.5.2 template strings — catalog entries ───────────────────────── - -fn tmpl_broken_relative_link_added(file: &str, n: u64, list: &str) -> String { - format!("\u{1F534} **{file}** \u{2014} {n} unresolved relative link(s) added: {list}") -} - -fn tmpl_broken_anchor_added(file: &str, n: u64, list: &str) -> String { - format!("\u{1F534} **{file}** \u{2014} {n} unresolved internal anchor(s) added: {list}") -} - -fn tmpl_broken_external_link_added(file: &str, n: u64, list: &str) -> String { - format!( - "\u{1F534} **{file}** \u{2014} {n} broken external link(s) added (link-check enabled): {list}" - ) -} - -fn tmpl_diagram_parse_error_added(file: &str, lang: &str, line: u64) -> String { - format!("\u{1F534} **{file}** \u{2014} {lang} diagram parse error at L{line}") -} - -fn tmpl_inclusive_language_flag_added(file: &str, n: u64, list: &str) -> String { - format!("\u{1F534} **{file}** \u{2014} {n} inclusive-language flag(s) added: {list}") -} - -fn tmpl_nonword_added(file: &str, n: u64) -> String { - // §39.5.2 catalog: per-occurrence word/line slots are optional; omit when - // aggregate-only data is available. - format!("\u{1F534} **{file}** \u{2014} {n} non-word occurrence(s) added (see drill-down)") -} - -fn tmpl_lexical_illusion_added(file: &str, n: u64) -> String { - // §39.5.2 catalog: per-occurrence word/line slots are optional; omit when - // aggregate-only data is available. - format!("\u{1F534} **{file}** \u{2014} {n} doubled-word occurrence(s) added (see drill-down)") -} - -fn tmpl_filler_risk_high( - file: &str, - risk: f64, - band: &str, - contributors: &[(String, f64)], -) -> String { - let mut parts = String::new(); - for (i, (label, v)) in contributors.iter().enumerate() { - if i > 0 { - parts.push_str(", "); - } - let _ = write!(parts, "{label} {:.2}", v); - } - format!( - "\u{26A0}\u{FE0F} **{file}** \u{2014} filler/lazy risk {risk:.2} ({band_upper}); top contributors: {parts}", - band_upper = band.to_ascii_uppercase(), - ) -} - -fn tmpl_dmi_band_drop(file: &str, old: i64, new: i64, old_band: &str, new_band: &str) -> String { - format!( - "\u{1F534} **{file}** \u{2014} DMI {old} \u{2192} {new}, crossed {old_band} \u{2192} {new_band} (\u{00A7}10.4)" - ) -} - -fn tmpl_dmi_band_improve(file: &str, old: i64, new: i64, old_band: &str, new_band: &str) -> String { - format!( - "\u{1F7E2} **{file}** \u{2014} DMI {old} \u{2192} {new}, crossed {old_band} \u{2192} {new_band} (\u{00A7}10.4)" - ) -} - -fn tmpl_filler_risk_band_improve( - file: &str, - old: f64, - new: f64, - old_band: &str, - new_band: &str, -) -> String { - format!( - "\u{1F7E2} **{file}** \u{2014} filler/lazy risk {:.2} \u{2192} {:.2}, crossed {old_band} \u{2192} {new_band} (\u{00A7}17.10)", - old, new - ) -} - -fn tmpl_evidence_band_drop( - file: &str, - old: f64, - new: f64, - old_band: &str, - new_band: &str, -) -> String { - format!( - "\u{1F534} **{file}** \u{2014} evidence coverage {:.2} \u{2192} {:.2}, crossed {old_band} \u{2192} {new_band} (\u{00A7}16.4)", - old, new - ) -} - -fn tmpl_repo_grounding_band_drop( - file: &str, - old: f64, - new: f64, - old_band: &str, - new_band: &str, -) -> String { - format!( - "\u{1F534} **{file}** \u{2014} repository grounding {:.2} \u{2192} {:.2}, crossed {old_band} \u{2192} {new_band} (\u{00A7}15.3)", - old, new - ) -} - -fn tmpl_long_sentences_added(file: &str, n: u64, threshold: u64, lines: &str) -> String { - format!("\u{1F534} **{file}** \u{2014} {n} sentence(s) exceed {threshold} words (new): {lines}") -} - -fn tmpl_long_sentences_resolved(file: &str, n: u64, threshold: u64) -> String { - format!( - "\u{1F7E2} **{file}** \u{2014} {n} sentence(s) previously over {threshold} words now under" - ) -} - -fn tmpl_readability_target_breach( - file: &str, - formula: &str, - old: f64, - new: f64, - profile: &str, - target: f64, -) -> String { - format!( - "\u{1F534} **{file}** \u{2014} {formula} {:.1} \u{2192} {:.1}, above {profile} target {:.1} (\u{00A7}31.13)", - old, new, target - ) -} - -fn tmpl_readability_target_recovered( - file: &str, - formula: &str, - old: f64, - new: f64, - profile: &str, - target: f64, -) -> String { - format!( - "\u{1F7E2} **{file}** \u{2014} {formula} {:.1} \u{2192} {:.1}, now within {profile} target {:.1}", - old, new, target - ) -} - -fn tmpl_tateishi_band_drop(file: &str, old: f64, new: f64) -> String { - format!( - "\u{1F534} **{file}** \u{2014} Tateishi RS {:.1} \u{2192} {:.1} (harder; \u{00A7}35.1)", - old, new - ) -} - -fn tmpl_passive_ratio_breach(file: &str, old: f64, new: f64, profile: &str, max: f64) -> String { - format!( - "\u{1F534} **{file}** \u{2014} passive ratio {:.2} \u{2192} {:.2}, above {profile} max {:.2} (\u{00A7}33.1)", - old, new, max - ) -} - -fn tmpl_heading_skip_added(file: &str, old_level: u8, new_level: u8, line: u64) -> String { - format!( - "\u{1F534} **{file}** \u{2014} heading skip {old_level} \u{2192} {new_level} at L{line}" - ) -} - -fn tmpl_table_burden_hard(file: &str, line: u64, cells: u64) -> String { - // §39.5.2 template: `{cells} cells / {cols} columns / {rows} rows`. - // Per-table cols/rows aren't on ArtifactRecord; slot values are filled - // with 0 to keep the template shape verbatim. - format!( - "\u{26A0}\u{FE0F} **{file}** \u{2014} table at L{line} has {cells} cells / 0 columns / 0 rows (hard warning; \u{00A7}13.2)" - ) -} - -fn tmpl_doubled_joshi_added(file: &str, n: u64) -> String { - // §39.5.2 catalog: per-particle surface/line slots are optional; omit - // when aggregate-only data is available. - format!( - "\u{1F534} **{file}** \u{2014} {n} repeated-particle occurrence(s) added (see drill-down)" - ) -} - -fn tmpl_kanji_run_too_long_added(file: &str, n: u64) -> String { - // §39.5.2 catalog: per-run length/surface/line slots are optional; omit - // when aggregate-only data is available. - format!("\u{1F534} **{file}** \u{2014} {n} long-kanji-run occurrence(s) added (see drill-down)") -} - -fn tmpl_code_fence_unlabeled_added(file: &str, line: u64) -> String { - format!("\u{26A0}\u{FE0F} **{file}** \u{2014} unlabelled code fence at L{line}") -} - -fn tmpl_diagram_missing_caption_added(file: &str, lang: &str, line: u64) -> String { - format!( - "\u{26A0}\u{FE0F} **{file}** \u{2014} {lang} diagram at L{line} has no caption or nearby explanation" - ) -} - -fn tmpl_image_missing_alt_added(file: &str, dest: &str, line: u64) -> String { - format!("\u{26A0}\u{FE0F} **{file}** \u{2014} image `{dest}` at L{line} has no alt text") -} - -// TODO(phase-next): reintroduce `tmpl_artifact_unexplained_added` when the -// §39.5.2 severity-4 callout for artifacts with `has_explanation == false` -// gets wired up. The previous definition was dead-code-only and the -// accompanying signal still needs to be routed through `emit_callouts_for_file`. - -fn tmpl_broken_links_resolved(file: &str, n: u64) -> String { - format!("\u{1F7E2} **{file}** \u{2014} {n} previously broken link(s) resolved") -} - -#[allow(clippy::too_many_arguments)] // §39.5.2 template requires every slot -fn tmpl_new_file_summary( - file: &str, - words: u64, - headings: u64, - code_fences: u64, - diagrams: u64, - tables: u64, - dmi: i64, - filler: f64, - band: &str, -) -> String { - format!( - "\u{1F195} **{file}** \u{2014} {words_fmt} words, {headings} headings, {code_fences} code fence(s), {diagrams} diagram(s), {tables} table(s); DMI {dmi}, filler risk {:.2} ({band_upper})", - filler, - words_fmt = format_int_thousands(words as i64), - band_upper = band.to_ascii_uppercase(), - ) -} - -// ── Drill-down tables (§39.6) ────────────────────────────────────────── - -fn render_drill_down(rows: &[(DocRow, &DocDiffFile)], ctx: &DocRenderCtx<'_>) -> Option { - let docrows: Vec<&DocRow> = rows.iter().map(|(r, _)| r).collect(); - let has_en = docrows.iter().any(|r| r.has_english); - let has_ja = docrows.iter().any(|r| r.has_japanese); - - let structural = render_drill_structural(&docrows, ctx); - let en_wording = if has_en { - render_drill_en_wording(&docrows, ctx) - } else { - None - }; - let en_lex = if has_en { - render_drill_en_lexical(&docrows, ctx) - } else { - None - }; - let ja_comp = if has_ja { - render_drill_ja(&docrows, ctx) - } else { - None - }; - - let filler_block = render_filler_contributors(rows); - - if structural.is_none() - && en_wording.is_none() - && en_lex.is_none() - && ja_comp.is_none() - && filler_block.is_none() - { - return None; - } - - let mut out = String::new(); - out.push_str( - "
\nFull metric breakdown (structural \u{00B7} wording \u{00B7} lexical \u{00B7} readability)\n\n" - ); - if let Some(t) = structural { - out.push_str("### Structural / review\n\n"); - out.push_str(&t); - out.push('\n'); - } - if let Some(t) = en_wording { - out.push_str("### English wording quality\n\n"); - out.push_str(&t); - out.push('\n'); - } - if let Some(t) = en_lex { - out.push_str("### English lexical & readability ensemble\n\n"); - out.push_str(&t); - out.push('\n'); - } - if let Some(t) = ja_comp { - out.push_str("### Japanese composition & register\n\n"); - out.push_str(&t); - out.push('\n'); - } - - if let Some(block) = filler_block { - out.push_str("### Filler risk contributors (files with risk > 0.40)\n\n"); - out.push_str(&block); - out.push('\n'); - } - - out.push_str("
\n"); - Some(out) -} - -fn render_drill_structural(rows: &[&DocRow], ctx: &DocRenderCtx<'_>) -> Option { - let mut out = String::new(); - out.push_str("| File | RCI | MCC | MRPC | Evidence | Grounding |\n"); - out.push_str("|---|---:|---:|---:|---:|---:|\n"); - for r in rows { - let _ = writeln!( - out, - "| `{path}` | {rci} | {mcc} | {mrpc} | {evi} | {gr} |", - path = r.display_path, - rci = r.rci.render(ctx.base_label), - mcc = r.mcc.render(ctx.base_label), - mrpc = r.mrpc.render(ctx.base_label), - evi = r.evidence.render(ctx.base_label), - gr = r.grounding.render(ctx.base_label), - ); - } - Some(out) -} - -fn render_drill_en_wording(rows: &[&DocRow], ctx: &DocRenderCtx<'_>) -> Option { - let mut out = String::new(); - out.push_str("| File | WQS | Passive % | Hedges /100w | Long sent. | Nominalizations |\n"); - out.push_str("|---|---:|---:|---:|---:|---:|\n"); - for r in rows { - if !r.has_english { - continue; - } - let _ = writeln!( - out, - "| `{path}` | {wqs} | {passive} | {hedges} | {ls} | {nom} |", - path = r.display_path, - wqs = r.wqs.render(ctx.base_label), - passive = r.passive_pct.render(ctx.base_label), - hedges = r.hedges_per_100w.render(ctx.base_label), - ls = r.long_sentences.render(ctx.base_label), - nom = r.nominalization_pct.render(ctx.base_label), - ); - } - Some(out) -} - -fn render_drill_en_lexical(rows: &[&DocRow], ctx: &DocRenderCtx<'_>) -> Option { - let mut out = String::new(); - out.push_str("| File | MATTR\u{2085}\u{2080} | Hapax | Fog | SMOG | ARI | Coleman-Liau |\n"); - out.push_str("|---|---:|---:|---:|---:|---:|---:|\n"); - for r in rows { - if !r.has_english { - continue; - } - let smog_cell = if r.sentences_count < 30 { - String::from("\u{2014}") - } else { - r.smog.render(ctx.base_label) - }; - let _ = writeln!( - out, - "| `{path}` | {mattr} | {hapax} | {fog} | {smog} | {ari} | {cl} |", - path = r.display_path, - mattr = r.mattr_50.render(ctx.base_label), - hapax = r.hapax.render(ctx.base_label), - fog = r.fog.render(ctx.base_label), - smog = smog_cell, - ari = r.ari.render(ctx.base_label), - cl = r.coleman_liau.render(ctx.base_label), - ); - } - Some(out) -} - -fn render_drill_ja(rows: &[&DocRow], ctx: &DocRenderCtx<'_>) -> Option { - let mut out = String::new(); - out.push_str( - "| File | Kanji % | Hiragana % | Katakana % | Avg sent chars | Comma/period | Politeness |\n", - ); - out.push_str("|---|---:|---:|---:|---:|---:|---:|\n"); - for r in rows { - if !r.has_japanese { - continue; - } - let politeness = r - .ja_politeness - .clone() - .unwrap_or_else(|| String::from("\u{2014}")); - let _ = writeln!( - out, - "| `{path}` | {k} | {h} | {kt} | {avg} | {cp} | `{pol}` |", - path = r.display_path, - k = r.ja_kanji_pct.render(ctx.base_label), - h = r.ja_hiragana_pct.render(ctx.base_label), - kt = r.ja_katakana_pct.render(ctx.base_label), - avg = r.ja_avg_sent_chars.render(ctx.base_label), - cp = r.ja_comma_period_ratio.render(ctx.base_label), - pol = politeness, - ); - } - Some(out) -} - -fn render_filler_contributors(rows: &[(DocRow, &DocDiffFile)]) -> Option { - let mut any = false; - let mut out = String::new(); - for (row, file) in rows { - let Some(head) = file.head.as_ref() else { - continue; - }; - if row.filler_value_current <= 0.40 { - continue; - } - any = true; - let mut contributors = head.ai_era.top_contributors.clone(); - contributors.sort_by(|a, b| { - b.1.partial_cmp(&a.1) - .unwrap_or(std::cmp::Ordering::Equal) - .then(a.0.cmp(&b.0)) - }); - let list: String = contributors - .iter() - .take(3) - .map(|(label, v)| format!("{label} {:.2}", v)) - .collect::>() - .join(", "); - let _ = writeln!( - out, - "- **`{path}` ({:.2})** \u{2014} {list}", - row.filler_value_current, - path = row.display_path, - ); - } - if any { Some(out) } else { None } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_markdown::types::{ - AiEra, ArtifactRecord, Complexity, EcuInputs, Grounding, LocFamily, LocRatios, - Maintainability, MarkdownMetrics, Review, Size, Visuals, - }; - - fn empty_metrics(path: &str) -> MarkdownMetrics { - MarkdownMetrics { - path: path.to_string(), - loc: LocFamily::default(), - loc_ratios: LocRatios::default(), - size: Size::default(), - ecu_inputs: EcuInputs::default(), - sections: vec![], - complexity: Complexity::default(), - links: Default::default(), - link_records: vec![], - visuals: Visuals::default(), - tables: Default::default(), - maintainability: Maintainability::default(), - grounding: Grounding::default(), - ai_era: AiEra::default(), - review: Review::default(), - artifacts: Vec::::new(), - prose: mehen_markdown::prose::ProseReport::default(), - } - } - - #[test] - fn suppressed_when_no_files() { - let ctx = DocRenderCtx::new("main"); - assert!(render_doc_section(&[], &ctx).is_none()); - } - - #[test] - fn renders_anchor_for_one_file() { - let ctx = DocRenderCtx::new("main"); - let file = DocDiffFile { - path: PathBuf::from("README.md"), - head: Some(empty_metrics("README.md")), - base: None, - is_new: true, - is_deleted: false, - }; - let out = render_doc_section(&[file], &ctx).unwrap(); - assert!(out.contains(DOC_ANCHOR)); - assert!(out.contains("## \u{1F4DD} Documentation Metrics")); - assert!(out.contains("Legend")); - } - - #[test] - fn indicator_dmi_regression_on_band_drop() { - let ind = compute_indicator(55.0, 74.0, CellKind::Dmi, false, false); - assert_eq!(ind, Indicator::Regression); - } - - #[test] - fn indicator_words_never_regression() { - let ind = compute_indicator(1000.0, 100.0, CellKind::Words, false, false); - assert_eq!(ind, Indicator::Unchanged); - } - - #[test] - fn indicator_filler_attention_when_high() { - let ind = compute_indicator(0.79, 0.78, CellKind::Filler, false, false); - assert_eq!(ind, Indicator::Attention); - } - - #[test] - fn template_broken_relative_link_added_shape() { - let s = tmpl_broken_relative_link_added("docs/api.md", 2, "`a.md` (L12), `b.md` (L34)"); - assert!(s.starts_with("\u{1F534} **docs/api.md** \u{2014} 2 unresolved relative")); - } - - #[test] - fn filler_band_edges() { - assert_eq!(filler_band_for(0.0), "clean"); - assert_eq!(filler_band_for(0.20), "mild"); - assert_eq!(filler_band_for(0.40), "moderate"); - assert_eq!(filler_band_for(0.60), "high"); - assert_eq!(filler_band_for(0.80), "severe"); - } - - #[test] - fn dmi_bands() { - assert_eq!(band_label(0.0, &DMI_BANDS), "Poor"); - assert_eq!(band_label(40.0, &DMI_BANDS), "Fair"); - assert_eq!(band_label(60.0, &DMI_BANDS), "Mixed"); - assert_eq!(band_label(75.0, &DMI_BANDS), "Good"); - assert_eq!(band_label(90.0, &DMI_BANDS), "Excellent"); - } - - #[test] - fn format_thousands_handles_negative() { - assert_eq!(format_int_thousands(-1234567), "-1,234,567"); - assert_eq!(format_int_thousands(0), "0"); - assert_eq!(format_int_thousands(999), "999"); - assert_eq!(format_int_thousands(1000), "1,000"); - } - - fn broken_link( - line: u64, - class: LinkClass, - destination: &str, - ) -> mehen_markdown::types::LinkRecord { - mehen_markdown::types::LinkRecord { - line, - class, - destination: destination.to_string(), - text: String::new(), - is_image: false, - is_bare_url: false, - resolved: Some(false), - } - } - - fn doc_row_for(path: &str) -> DocRow { - let ctx = DocRenderCtx::new("main"); - let file = DocDiffFile { - path: PathBuf::from(path), - head: Some(empty_metrics(path)), - base: Some(empty_metrics(path)), - is_new: false, - is_deleted: false, - }; - DocRow::build(&file, &ctx) - } - - #[test] - fn new_link_defects_count_duplicates_by_occurrence() { - // §39.4 regression: base has 1 broken `./guide.md`, head has 2. The - // second new occurrence must be reported even though `(class, dest)` - // already existed in base. - let mut head = empty_metrics("docs/a.md"); - head.link_records = vec![ - broken_link(10, LinkClass::Relative, "./guide.md"), - broken_link(20, LinkClass::Relative, "./guide.md"), - ]; - let mut base = empty_metrics("docs/a.md"); - base.link_records = vec![broken_link(10, LinkClass::Relative, "./guide.md")]; - - let row = doc_row_for("docs/a.md"); - let mut out: Vec = Vec::new(); - emit_new_link_defects(&row, &head, Some(&base), &mut out); - - assert_eq!(out.len(), 1, "exactly one callout for the relative class"); - assert_eq!(out[0].rule_id, "broken_relative_link_added"); - assert_eq!(out[0].magnitude, 1.0); - // The surviving occurrence takes the highest unmatched line. - assert!( - out[0].rendered.contains("`./guide.md` (L20)"), - "expected L20 occurrence in callout, got: {}", - out[0].rendered - ); - assert!( - !out[0].rendered.contains("`./guide.md` (L10)"), - "L10 was already broken in base; must not be re-reported", - ); - } - - #[test] - fn readability_cell_preserves_base_value_on_deletion() { - // When a .md is deleted the head side is None; the previous - // behavior forced the ShortDoc footnote (`— ²`) so reviewers lost - // the baseline FKGL. Now we drop the ShortDoc override when base - // has a value, letting the standard deletion path show `0.0 (was: - // X.Y) 🔴`. - let mut base = empty_metrics("docs/a.md"); - let mut en = mehen_markdown::prose::english::EnglishReport::default(); - en.readability.flesch_kincaid_grade = Some(12.7); - en.short_doc_warning = false; - base.prose.english = Some(en); - base.prose.language_detection.dominant_language = "en".to_string(); - - let file = DocDiffFile { - path: PathBuf::from("docs/a.md"), - head: None, - base: Some(base), - is_new: false, - is_deleted: true, - }; - - let cell = build_readability_cell(&file, Language::En); - assert!( - cell.footnote.is_none(), - "deletion with base readability must not force ShortDoc footnote", - ); - let rendered = cell.render("main"); - assert!( - rendered.contains("12.7"), - "baseline value must appear in render, got: {rendered}", - ); - assert!( - rendered.contains("was:"), - "deletion marker must be present, got: {rendered}", - ); - } - - #[test] - fn readability_cell_short_doc_when_base_also_missing() { - // Sanity check: if *both* sides are missing readability data we - // still show the ShortDoc footnote — there is nothing to surface. - let file = DocDiffFile { - path: PathBuf::from("docs/a.md"), - head: None, - base: Some(empty_metrics("docs/a.md")), - is_new: false, - is_deleted: true, - }; - let cell = build_readability_cell(&file, Language::En); - assert!(matches!(cell.footnote, Some(Footnote::ShortDoc))); - } - - #[test] - fn new_link_defects_dedup_when_same_count() { - // When base and head contain the same number of broken occurrences - // for a (class, destination) key, nothing new is emitted. - let mut head = empty_metrics("docs/a.md"); - head.link_records = vec![broken_link(30, LinkClass::Relative, "./guide.md")]; - let mut base = empty_metrics("docs/a.md"); - base.link_records = vec![broken_link(10, LinkClass::Relative, "./guide.md")]; - - let row = doc_row_for("docs/a.md"); - let mut out: Vec = Vec::new(); - emit_new_link_defects(&row, &head, Some(&base), &mut out); - - assert!( - out.is_empty(), - "equal occurrence count per key → no new-broken-link callout", - ); - } -} diff --git a/crates/mehen-report/src/json.rs b/crates/mehen-report/src/json.rs deleted file mode 100644 index 3d0f3d0f..00000000 --- a/crates/mehen-report/src/json.rs +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use mehen_core::{DiffReport, Language, MetricsReport}; - -use crate::metrics_json::MetricsFamilies; - -/// Render a `MetricsReport` as JSON. Pretty-printed when `pretty=true`. -/// -/// Emits the documented per-family shape (`metrics: { cyclomatic, … }`, -/// rewrite plan §9.1) pivoted from the flat keys the analyzer publishes -/// into `root.metrics`. The full `MetricSpace` tree remains available -/// under `root` so consumers that reference individual aggregator keys -/// (e.g. `cyclomatic.max`) keep working alongside the published -/// schema. -/// -/// Languages that publish their own flat metric family instead of the -/// source-code families (Markdown's `markdown.*`, SQL's `sql.*`) are exempt -/// from the source-code pivot: `MetricsFamilies::from_metrics` only reads the -/// source-code keys (`cyclomatic`, `halstead.*`, …), so pivoting their reports -/// would replace the real `markdown.*`/`sql.*` values with an all-zero -/// source-code block. Instead, the top-level `metrics` object is populated -/// directly from the flat `root.metrics` map, so consumers reading -/// `.metrics["sql.cte.count"]` still see the language-owned values. -pub fn render_metrics_json(report: &MetricsReport, pretty: bool) -> serde_json::Result { - let mut value = serde_json::to_value(report)?; - let metrics = if publishes_own_family(report.language) { - // Flat map of the language-owned family (`sql.*` / `markdown.*`). - serde_json::to_value(&report.root.metrics)? - } else { - // Pivot the source-code flat keys into the documented per-family shape. - serde_json::to_value(MetricsFamilies::from_metrics(&report.root.metrics))? - }; - if let serde_json::Value::Object(map) = &mut value { - map.insert("metrics".to_string(), metrics); - } - if pretty { - serde_json::to_string_pretty(&value) - } else { - serde_json::to_string(&value) - } -} - -/// Whether `language` publishes its own flat metric family (and therefore -/// must not be pivoted through the source-code `MetricsFamilies` shape). -fn publishes_own_family(language: Language) -> bool { - matches!(language, Language::Markdown | Language::Sql) -} - -/// Render a `DiffReport` as JSON. Pretty-printed when `pretty=true`. -pub fn render_diff_json(report: &DiffReport, pretty: bool) -> serde_json::Result { - if pretty { - serde_json::to_string_pretty(report) - } else { - serde_json::to_string(report) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{ - AnalysisBackend, ContributionReason, MetricContribution, MetricKey, MetricSpace, - MetricsReport, SourceSpan, SpaceId, SpaceKind, - }; - - fn report_with(language: Language, key: &str, value: f64) -> MetricsReport { - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - root.metrics.insert(MetricKey::new(key), value); - MetricsReport { - schema_version: "1.0".to_string(), - tool: "mehen".to_string(), - path: "q.sql".into(), - language, - analysis_backend: AnalysisBackend::Sqruff, - diagnostics: Vec::new(), - root, - contributions: Vec::new(), - } - } - - #[test] - fn sql_report_exposes_flat_family_under_top_level_metrics() { - // `render_metrics_json` must not pivot SQL/Markdown reports through the - // source-code `MetricsFamilies` shape (which reads only `cyclomatic`, - // `halstead.*`, … and would yield an all-zero block). Instead the - // top-level `metrics` object is the flat `sql.*` map, so consumers - // reading `.metrics["sql.cte.count"]` get the real value. - let report = report_with(Language::Sql, "sql.cte.count", 3.0); - let json = render_metrics_json(&report, false).unwrap(); - let value: serde_json::Value = serde_json::from_str(&json).unwrap(); - // The flat family is exposed at the top-level `metrics` object … - assert_eq!(value["metrics"]["sql.cte.count"], 3.0); - // … and still present under `root.metrics`. - assert_eq!(value["root"]["metrics"]["sql.cte.count"], 3.0); - // No source-code family keys were injected. - assert!( - value["metrics"].get("cyclomatic").is_none(), - "SQL report must not carry the source-code family block; got {value}" - ); - } - - #[test] - fn source_code_report_still_gets_family_pivot() { - // Non-SQL/Markdown languages keep the documented per-family shape. - let report = report_with(Language::Rust, "cyclomatic.sum", 5.0); - let json = render_metrics_json(&report, false).unwrap(); - let value: serde_json::Value = serde_json::from_str(&json).unwrap(); - assert!( - value.get("metrics").is_some(), - "source-code report must carry the pivoted `metrics` family block" - ); - } - - #[test] - fn contributions_are_serialized_only_when_present() { - let empty = report_with(Language::Sql, "sql.change_risk_score", 0.0); - let empty_json: serde_json::Value = - serde_json::from_str(&render_metrics_json(&empty, false).unwrap()).unwrap(); - assert!(empty_json.get("contributions").is_none()); - - let mut explained = report_with(Language::Sql, "sql.change_risk_score", 8.0); - explained.contributions.push(MetricContribution { - metric: MetricKey::new("sql.change_risk_score"), - span: SourceSpan::new(0, 12, 1, 1), - amount: 8.0, - reason: ContributionReason::new("sql.change_risk.drop"), - }); - let json: serde_json::Value = - serde_json::from_str(&render_metrics_json(&explained, false).unwrap()).unwrap(); - assert_eq!(json["contributions"][0]["metric"], "sql.change_risk_score"); - assert_eq!(json["contributions"][0]["amount"], 8.0); - assert_eq!(json["contributions"][0]["reason"], "sql.change_risk.drop"); - assert_eq!(json["contributions"][0]["span"]["start_line"], 1); - } -} diff --git a/crates/mehen-report/src/lib.rs b/crates/mehen-report/src/lib.rs deleted file mode 100644 index b35979aa..00000000 --- a/crates/mehen-report/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-report` — rendering and serialization. -//! -//! Phase 1 scope: render shapes that downstream callers can rely on while -//! the orchestrators are filled in. Per the rewrite plan §8.1 the pre-1.0 -//! Markdown documentation diff renderer lives here under -//! `github_markdown_docs` (gated by the `docs-diff` feature so consumers -//! that don't need the Markdown analyzer don't pay for it). - -#![forbid(unsafe_code)] - -#[cfg(feature = "docs-diff")] -pub mod github_markdown_docs; -mod json; -mod markdown; -pub mod metrics_json; - -pub use json::{render_diff_json, render_metrics_json}; -pub use markdown::{render_diff_github_markdown, render_metrics_markdown}; diff --git a/crates/mehen-report/src/markdown.rs b/crates/mehen-report/src/markdown.rs deleted file mode 100644 index 6abdba90..00000000 --- a/crates/mehen-report/src/markdown.rs +++ /dev/null @@ -1,1137 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -use std::fmt::Write; - -use mehen_core::{ - DiagnosticSeverity, DiffReport, Language, MetricContribution, MetricKey, MetricSet, - MetricSpace, MetricsReport, ParseDiagnostic, SpaceKind, -}; - -use crate::metrics_json::{ - Abc, Cognitive, Cyclomatic, Halstead, Loc, MetricsFamilies, Nargs, Nexits, Nom, Npa, Npm, Wmc, -}; - -/// Render a single-file metrics report as Markdown. -/// -/// The output is structured for both human consumption (running -/// `mehen metrics file --format markdown` from a terminal) and for -/// CI artefacts (a docs build that wants to diff metric counts as -/// stable text). The same family object the JSON renderer publishes -/// drives the metric tables here, so JSON and Markdown stay in lock -/// step. -/// -/// Layout: -/// 1. Title + file metadata block. -/// 2. Diagnostics callout (only emitted when at least one -/// diagnostic exists; severity is shown inline). -/// 3. Per-family metric tables (cyclomatic, cognitive, LOC, -/// Halstead, ABC, NArgs, NOM, NExits, NPA, NPM, WMC) — every -/// family is rendered, even when its scalar values are all -/// zero, so the absence of a bucket doesn't have to be inferred. -/// 4. Per-space breakdown for nested function / closure / class / -/// interface / impl / trait / enum spaces beneath the unit. Pure -/// "Unknown" or empty trees collapse to a single "no nested -/// spaces" line. -pub fn render_metrics_markdown(report: &MetricsReport) -> String { - let mut out = String::new(); - let _ = writeln!(out, "# {}", report.path); - let _ = writeln!(out); - let _ = writeln!(out, "- language: `{}`", report.language); - let _ = writeln!(out, "- backend: `{}`", report.analysis_backend.label()); - let _ = writeln!(out, "- schema: `{}`", report.schema_version); - - write_diagnostics(&mut out, &report.diagnostics); - write_contributions(&mut out, &report.contributions); - write_unit_metrics(&mut out, &report.root.metrics, report.language); - write_nested_spaces(&mut out, &report.root.spaces, 0, report.language); - - out -} - -fn write_contributions(out: &mut String, contributions: &[MetricContribution]) { - if contributions.is_empty() { - return; - } - let _ = writeln!(out); - let _ = writeln!(out, "## Contributions"); - let _ = writeln!(out); - let _ = writeln!(out, "| metric | amount | reason | lines |"); - let _ = writeln!(out, "|---|---:|---|---:|"); - for contribution in contributions { - let sign = if contribution.amount.is_sign_negative() { - "-" - } else { - "+" - }; - let amount = fmt_metric(contribution.amount.abs()); - let lines = if contribution.span.start_line == contribution.span.end_line { - format!("L{}", contribution.span.start_line) - } else { - format!( - "L{}–L{}", - contribution.span.start_line, contribution.span.end_line - ) - }; - let _ = writeln!( - out, - "| `{}` | {sign}{amount} | `{}` | {lines} |", - escape_table_cell(contribution.metric.as_str()), - // Reasons may carry operator spellings (`c.cyclomatic.||`); - // escape pipes so the table doesn't gain phantom columns. - escape_table_cell(contribution.reason.as_str()), - ); - } -} - -fn write_diagnostics(out: &mut String, diagnostics: &[ParseDiagnostic]) { - if diagnostics.is_empty() { - return; - } - let _ = writeln!(out); - let _ = writeln!(out, "## Diagnostics"); - let _ = writeln!(out); - let _ = writeln!(out, "| severity | code | message |"); - let _ = writeln!(out, "|---|---|---|"); - for d in diagnostics { - let severity = match d.severity { - DiagnosticSeverity::Warning => "warning", - DiagnosticSeverity::Error => "error", - DiagnosticSeverity::Fatal => "fatal", - }; - let _ = writeln!( - out, - "| {} | `{}` | {} |", - severity, - d.code, - escape_table_cell(&d.message), - ); - } -} - -fn write_unit_metrics(out: &mut String, metrics: &MetricSet, language: Language) { - let _ = writeln!(out); - let _ = writeln!(out, "## Metrics"); - - // Coverage first when present, rendered on the flat-map path only - // for the flat-family languages (Markdown/SQL) whose early returns - // below never reach the `MetricsFamilies` pivot — a measured - // Markdown or SQL file carries coverage too. Source-code languages - // render coverage once, from `families.coverage` after the pivot; - // rendering here as well would emit the table twice. Unlike the - // always-rendered source-code tables it is omitted entirely when - // unmeasured ("no data" must stay distinguishable from 0%). - if matches!(language, Language::Markdown | Language::Sql) - && let Some(coverage) = crate::metrics_json::coverage(metrics) - { - write_coverage(out, &coverage); - } - - if language == Language::Markdown { - // The Markdown analyzer publishes a different metric family - // (`markdown.*` keys covering documentation-specific - // dimensions: LOC ratios, prose size, links, visuals, - // maintainability, grounding, etc.). Pivoting through - // `MetricsFamilies` would emit all-zero source-code tables - // that don't reflect what the analyzer actually computed — - // misleading for the project's primary documentation-analysis - // use case. Render the Markdown family directly from the flat - // metric map. - write_markdown_metrics(out, metrics); - return; - } - - if language == Language::Sql { - // SQL has its own relational/dataflow metric family (`sql.*`): - // statements, query blocks, CTE graph, joins, predicates, - // object-touch risk, and an SQL-flavored Halstead. Like - // Markdown, the source-code families (cyclomatic/cognitive/…) - // don't apply, so render the SQL groups directly. - write_sql_metrics(out, metrics); - return; - } - - let families = MetricsFamilies::from_metrics(metrics); - // Coverage first when present: it is the family users gate CI on, - // and unlike the always-rendered source-code tables it is omitted - // entirely when unmeasured ("no data" must stay distinguishable - // from 0%). - if let Some(coverage) = &families.coverage { - write_coverage(out, coverage); - } - write_cyclomatic(out, &families.cyclomatic); - write_cognitive(out, &families.cognitive); - write_loc(out, &families.loc); - write_halstead(out, &families.halstead); - write_abc(out, &families.abc); - write_nargs(out, &families.nargs); - write_nom(out, &families.nom); - write_nexits(out, &families.nexits); - write_npa(out, &families.npa); - write_npm(out, &families.npm); - write_wmc(out, &families.wmc); -} - -/// Render the `markdown.*` metric family as Markdown tables. -/// -/// One table per documented group (LOC, LOC ratios, size, complexity, -/// Halstead, links, visuals, tables, maintainability, grounding, -/// ai_era, review). Field declaration order matches the publishing -/// order in `mehen_markdown::publish_markdown_metrics` so the rendered -/// section reads in the same shape as the §23 export schema. -fn write_markdown_metrics(out: &mut String, metrics: &MetricSet) { - write_markdown_group( - out, - "LOC", - &[ - ("dloc", "markdown.loc.dloc"), - ("ploc", "markdown.loc.ploc"), - ("cloc", "markdown.loc.cloc"), - ("tloc", "markdown.loc.tloc"), - ("mloc", "markdown.loc.mloc"), - ("bloc", "markdown.loc.bloc"), - ("aloc", "markdown.loc.aloc"), - ], - metrics, - ); - write_markdown_group( - out, - "LOC ratios", - &[ - ( - "artifact_line_ratio", - "markdown.loc_ratios.artifact_line_ratio", - ), - ("code_line_ratio", "markdown.loc_ratios.code_line_ratio"), - ("table_line_ratio", "markdown.loc_ratios.table_line_ratio"), - ("math_line_ratio", "markdown.loc_ratios.math_line_ratio"), - ("blank_line_ratio", "markdown.loc_ratios.blank_line_ratio"), - ], - metrics, - ); - write_markdown_group( - out, - "Size", - &[ - ("words", "markdown.size.words"), - ( - "effective_content_units", - "markdown.size.effective_content_units", - ), - ("sections", "markdown.size.sections"), - ("headings", "markdown.size.headings"), - ], - metrics, - ); - write_markdown_group( - out, - "Complexity", - &[ - ( - "reading_path_complexity", - "markdown.complexity.reading_path_complexity", - ), - ( - "reading_path_complexity_raw", - "markdown.complexity.reading_path_complexity_raw", - ), - ( - "cognitive_complexity", - "markdown.complexity.cognitive_complexity", - ), - ], - metrics, - ); - write_markdown_group( - out, - "Halstead", - &[ - ("operators_distinct", "markdown.halstead.operators_distinct"), - ("operators_total", "markdown.halstead.operators_total"), - ("operands_distinct", "markdown.halstead.operands_distinct"), - ("operands_total", "markdown.halstead.operands_total"), - ("vocabulary", "markdown.halstead.vocabulary"), - ("length", "markdown.halstead.length"), - ("volume", "markdown.halstead.volume"), - ("difficulty", "markdown.halstead.difficulty"), - ("effort", "markdown.halstead.effort"), - ("embedded_volume", "markdown.halstead.embedded_volume"), - ("total_volume", "markdown.halstead.total_volume"), - ], - metrics, - ); - write_markdown_group( - out, - "Links", - &[ - ("total", "markdown.links.total"), - ("broken", "markdown.links.broken"), - ("link_debt_score", "markdown.links.link_debt_score"), - ( - "information_scent_score", - "markdown.links.information_scent_score", - ), - ("review_burden", "markdown.links.review_burden"), - ], - metrics, - ); - write_markdown_group( - out, - "Visuals", - &[ - ("images", "markdown.visuals.images"), - ("diagrams", "markdown.visuals.diagrams"), - ( - "diagram_parse_error_count", - "markdown.visuals.diagram_parse_error_count", - ), - ("visual_net_effect", "markdown.visuals.visual_net_effect"), - ], - metrics, - ); - write_markdown_group( - out, - "Tables", - &[ - ("count", "markdown.tables.count"), - ("max_cells", "markdown.tables.max_cells"), - ("table_burden_score", "markdown.tables.table_burden_score"), - ("hard_warnings", "markdown.tables.hard_warnings"), - ], - metrics, - ); - write_markdown_group( - out, - "Maintainability", - &[ - ( - "documentation_maintainability_index", - "markdown.maintainability.documentation_maintainability_index", - ), - ( - "section_balance_score", - "markdown.maintainability.section_balance_score", - ), - ( - "good_scaffold_score", - "markdown.maintainability.good_scaffold_score", - ), - ( - "artifact_debt_score", - "markdown.maintainability.artifact_debt_score", - ), - ], - metrics, - ); - write_markdown_group( - out, - "Grounding", - &[ - ( - "repository_grounding_score", - "markdown.grounding.repository_grounding_score", - ), - ( - "evidence_coverage_score", - "markdown.grounding.evidence_coverage_score", - ), - ], - metrics, - ); - write_markdown_group( - out, - "AI era", - &[( - "filler_lazy_structure_risk", - "markdown.ai_era.filler_lazy_structure_risk", - )], - metrics, - ); - write_markdown_group( - out, - "Review", - &[( - "review_criticality_index", - "markdown.review.review_criticality_index", - )], - metrics, - ); -} - -/// Render the `sql.*` metric family as Markdown tables, one per documented -/// group. Mirrors the catalogue in `docs/metrics/sql/overview.mdx`. -fn write_sql_metrics(out: &mut String, metrics: &MetricSet) { - write_markdown_group( - out, - "LOC", - &[ - ("physical", "sql.loc.physical"), - ("code", "sql.loc.code"), - ("comment", "sql.loc.comment"), - ("blank", "sql.loc.blank"), - ("logical", "sql.loc.logical"), - ("comment_density", "sql.loc.comment_density"), - ], - metrics, - ); - write_markdown_group( - out, - "Statements", - &[ - ("count", "sql.statement.count"), - ("kind_distinct", "sql.statement.kind_distinct"), - ("kind_entropy", "sql.statement.kind_entropy"), - ("unparsed_count", "sql.statement.unparsed_count"), - ], - metrics, - ); - write_markdown_group( - out, - "Query structure", - &[ - ("query_block.count", "sql.query_block.count"), - ("query_block.max_depth", "sql.query_block.max_depth"), - ("cte.count", "sql.cte.count"), - ("cte.max_dependency_depth", "sql.cte.max_dependency_depth"), - ("cte.unused_count", "sql.cte.unused_count"), - ("join.count", "sql.join.count"), - ("subquery.correlated_count", "sql.subquery.correlated_count"), - ], - metrics, - ); - write_markdown_group( - out, - "Expression complexity", - &[ - ( - "predicate.boolean_operator_count", - "sql.predicate.boolean_operator_count", - ), - ("case.count", "sql.case.count"), - ("case.max_depth", "sql.case.max_depth"), - ("window.function_count", "sql.window.function_count"), - ("set_op.count", "sql.set_op.count"), - ("expression.max_depth", "sql.expression.max_depth"), - ], - metrics, - ); - write_markdown_group( - out, - "Object touch / risk", - &[ - ("object.write_count", "sql.object.write_count"), - ("ddl.drop_count", "sql.ddl.drop_count"), - ("ddl.truncate_count", "sql.ddl.truncate_count"), - ( - "dml.update_without_where_count", - "sql.dml.update_without_where_count", - ), - ( - "dml.delete_without_where_count", - "sql.dml.delete_without_where_count", - ), - ], - metrics, - ); - write_markdown_group( - out, - "Halstead", - &[ - ("vocabulary", "sql.halstead.vocabulary"), - ("length", "sql.halstead.length"), - ("volume", "sql.halstead.volume"), - ("difficulty", "sql.halstead.difficulty"), - ("effort", "sql.halstead.effort"), - ], - metrics, - ); - write_markdown_group( - out, - "Composite scores", - &[ - ("structural_complexity", "sql.structural_complexity"), - ("cognitive_complexity", "sql.cognitive_complexity"), - ("change_risk_score", "sql.change_risk_score"), - ("review_burden_index", "sql.review_burden_index"), - ("maintainability_index", "sql.maintainability_index"), - ("modularity_health", "sql.modularity_health"), - ], - metrics, - ); - write_markdown_group( - out, - "Parser health", - &[ - ("diagnostic_count", "sql.parser.diagnostic_count"), - ("unparsable_ratio", "sql.parser.unparsable_ratio"), - ("dialect.confidence", "sql.dialect.confidence"), - ], - metrics, - ); -} - -fn write_markdown_group( - out: &mut String, - title: &str, - columns: &[(&str, &str)], - metrics: &MetricSet, -) { - let _ = writeln!(out); - let _ = writeln!(out, "### {title}"); - let _ = writeln!(out); - let header: String = columns - .iter() - .map(|(label, _)| format!("| {label} ")) - .collect::(); - let _ = writeln!(out, "{header}|"); - let separator: String = std::iter::repeat_n("|---:", columns.len()).collect(); - let _ = writeln!(out, "{separator}|"); - let row: String = columns - .iter() - .map(|(_, key)| format!("| {} ", fmt_metric(read_metric(metrics, key)))) - .collect(); - let _ = writeln!(out, "{row}|"); -} - -fn read_metric(metrics: &MetricSet, key: &str) -> f64 { - metrics - .get(&MetricKey::new(key)) - .map(|v| v.as_f64()) - .unwrap_or(0.0) -} - -fn write_nested_spaces(out: &mut String, spaces: &[MetricSpace], depth: usize, language: Language) { - if depth == 0 { - // Print a section header only when at the top of the - // recursion *and* there's something to show. - if spaces.is_empty() { - return; - } - let _ = writeln!(out); - let _ = writeln!(out, "## Spaces"); - } - for space in spaces { - let header = "#".repeat(depth.saturating_add(3)); - let label = match (&space.kind, &space.name) { - (SpaceKind::Unit, _) => "unit".to_string(), - (kind, Some(name)) => format!("{} `{}`", space_kind_label(kind), name), - (kind, None) => format!("{} (anonymous)", space_kind_label(kind)), - }; - let _ = writeln!(out); - let _ = writeln!(out, "{header} {label}"); - // The Markdown and SQL analyzers only publish flat unit-level - // family metrics (`markdown.*` / `sql.*`); their nested spaces - // (Markdown sections / embedded code, SQL per-statement spans) - // carry no source-code roll-ups, so the Cyclomatic / Cognitive - // / LOC tables would all be zero. - if language == Language::Sql { - // A SQL per-statement space carries only its line-span metric; - // routine (function) spaces nested under it carry none — fall - // back to the space's own span so neither heading is a - // content-free stub (the source-code metric tables would all - // be zero here). - let lines = read_metric(&space.metrics, "sql.statement.lines"); - let lines = if lines > 0.0 { - lines as i64 - } else if space.span.start_line > 0 && space.span.end_line >= space.span.start_line { - i64::from(space.span.end_line - space.span.start_line + 1) - } else { - 0 - }; - if lines > 0 { - let _ = writeln!(out); - let _ = writeln!(out, "- Lines: {lines}"); - } - } else if language != Language::Markdown { - let families = MetricsFamilies::from_metrics(&space.metrics); - write_cyclomatic(out, &families.cyclomatic); - write_cognitive(out, &families.cognitive); - write_loc(out, &families.loc); - } - if !space.spaces.is_empty() { - write_nested_spaces(out, &space.spaces, depth.saturating_add(1), language); - } - } -} - -fn space_kind_label(kind: &SpaceKind) -> &'static str { - match kind { - SpaceKind::Unit => "unit", - SpaceKind::Function => "function", - SpaceKind::Closure => "closure", - SpaceKind::Class => "class", - SpaceKind::Interface => "interface", - SpaceKind::Trait => "trait", - SpaceKind::Impl => "impl", - SpaceKind::Enum => "enum", - SpaceKind::Custom(_) => "custom", - } -} - -// --- Per-family helpers -------------------------------------------- - -/// Coverage table: one row per measured dimension. A dimension the -/// ingested report never measured is skipped — "no data" must stay -/// distinguishable from 0%. -fn write_coverage(out: &mut String, m: &crate::metrics_json::Coverage) { - let _ = writeln!(out); - let _ = writeln!(out, "### Coverage"); - let _ = writeln!(out); - let _ = writeln!(out, "| dimension | coverage | covered | total |"); - let _ = writeln!(out, "|---|---:|---:|---:|"); - for (label, dimension) in [ - ("line", &m.line), - ("branch", &m.branch), - ("function", &m.function), - ] { - if let Some(dimension) = dimension { - let _ = writeln!( - out, - "| {label} | {:.1}% | {} | {} |", - dimension.percent, dimension.covered, dimension.total, - ); - } - } -} - -fn write_cyclomatic(out: &mut String, m: &Cyclomatic) { - let _ = writeln!(out); - let _ = writeln!(out, "### Cyclomatic"); - let _ = writeln!(out); - let _ = writeln!(out, "| sum | average | min | max |"); - let _ = writeln!(out, "|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} |", - fmt_metric(m.sum), - fmt_metric(m.average), - fmt_metric(m.min), - fmt_metric(m.max), - ); -} - -fn write_cognitive(out: &mut String, m: &Cognitive) { - let _ = writeln!(out); - let _ = writeln!(out, "### Cognitive"); - let _ = writeln!(out); - let _ = writeln!(out, "| sum | average | min | max |"); - let _ = writeln!(out, "|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} |", - fmt_metric(m.sum), - fmt_metric(m.average), - fmt_metric(m.min), - fmt_metric(m.max), - ); -} - -fn write_loc(out: &mut String, m: &Loc) { - let _ = writeln!(out); - let _ = writeln!(out, "### LOC"); - let _ = writeln!(out); - let _ = writeln!(out, "| sloc | ploc | lloc | cloc | blank |"); - let _ = writeln!(out, "|---:|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} | {} |", - fmt_metric(m.sloc), - fmt_metric(m.ploc), - fmt_metric(m.lloc), - fmt_metric(m.cloc), - fmt_metric(m.blank), - ); -} - -fn write_halstead(out: &mut String, m: &Halstead) { - let _ = writeln!(out); - let _ = writeln!(out, "### Halstead"); - let _ = writeln!(out); - let _ = writeln!(out, "| n1 | N1 | n2 | N2 | volume | difficulty | effort |"); - let _ = writeln!(out, "|---:|---:|---:|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} | {} | {} | {} |", - fmt_metric(m.n1), - fmt_metric(m.big_n1), - fmt_metric(m.n2), - fmt_metric(m.big_n2), - fmt_metric(m.volume), - fmt_metric(m.difficulty), - fmt_metric(m.effort), - ); -} - -fn write_abc(out: &mut String, m: &Abc) { - let _ = writeln!(out); - let _ = writeln!(out, "### ABC"); - let _ = writeln!(out); - let _ = writeln!(out, "| assignments | branches | conditions | magnitude |"); - let _ = writeln!(out, "|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} |", - fmt_metric(m.assignments), - fmt_metric(m.branches), - fmt_metric(m.conditions), - fmt_metric(m.magnitude), - ); -} - -fn write_nargs(out: &mut String, m: &Nargs) { - let _ = writeln!(out); - let _ = writeln!(out, "### NArgs"); - let _ = writeln!(out); - let _ = writeln!( - out, - "| total_functions | total_closures | average | total |" - ); - let _ = writeln!(out, "|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} |", - fmt_metric(m.total_functions), - fmt_metric(m.total_closures), - fmt_metric(m.average), - fmt_metric(m.total), - ); -} - -fn write_nom(out: &mut String, m: &Nom) { - let _ = writeln!(out); - let _ = writeln!(out, "### NOM"); - let _ = writeln!(out); - let _ = writeln!(out, "| functions | closures | total |"); - let _ = writeln!(out, "|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} |", - fmt_metric(m.functions), - fmt_metric(m.closures), - fmt_metric(m.total), - ); -} - -fn write_nexits(out: &mut String, m: &Nexits) { - let _ = writeln!(out); - let _ = writeln!(out, "### NExits"); - let _ = writeln!(out); - let _ = writeln!(out, "| sum | average | min | max |"); - let _ = writeln!(out, "|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} |", - fmt_metric(m.sum), - fmt_metric(m.average), - fmt_metric(m.min), - fmt_metric(m.max), - ); -} - -fn write_npa(out: &mut String, m: &Npa) { - let _ = writeln!(out); - let _ = writeln!(out, "### NPA"); - let _ = writeln!(out); - let _ = writeln!( - out, - "| classes | interfaces | class_attributes | interface_attributes | total |" - ); - let _ = writeln!(out, "|---:|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} | {} |", - fmt_metric(m.classes), - fmt_metric(m.interfaces), - fmt_metric(m.class_attributes), - fmt_metric(m.interface_attributes), - fmt_metric(m.total), - ); -} - -fn write_npm(out: &mut String, m: &Npm) { - let _ = writeln!(out); - let _ = writeln!(out, "### NPM"); - let _ = writeln!(out); - let _ = writeln!( - out, - "| classes | interfaces | class_methods | interface_methods | total |" - ); - let _ = writeln!(out, "|---:|---:|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} | {} | {} |", - fmt_metric(m.classes), - fmt_metric(m.interfaces), - fmt_metric(m.class_methods), - fmt_metric(m.interface_methods), - fmt_metric(m.total), - ); -} - -fn write_wmc(out: &mut String, m: &Wmc) { - let _ = writeln!(out); - let _ = writeln!(out, "### WMC"); - let _ = writeln!(out); - let _ = writeln!(out, "| classes | interfaces | total |"); - let _ = writeln!(out, "|---:|---:|---:|"); - let _ = writeln!( - out, - "| {} | {} | {} |", - fmt_metric(m.classes), - fmt_metric(m.interfaces), - fmt_metric(m.total), - ); -} - -/// Render an integer-valued metric as an integer when its -/// fractional component is zero (the common case for counts), and -/// as a 4-decimal float otherwise (for averages / ratios). NaN -/// surfaces as `nan` so a corrupt analyzer doesn't silently produce -/// `0` output. -fn fmt_metric(value: f64) -> String { - if value.is_nan() { - return "nan".to_string(); - } - if value.fract() == 0.0 && value.is_finite() { - return format!("{}", value as i64); - } - format!("{value:.4}") -} - -fn escape_table_cell(s: &str) -> String { - s.replace('|', r"\|").replace('\n', " ") -} - -/// Phase 1 placeholder for the GitHub Markdown diff comment. Phase 4 ports -/// the existing pre-1.0 documentation diff renderer here. The output must -/// be byte-identical after stable timestamp/version redaction (parity -/// contract — rewrite plan §12.3.1). -pub fn render_diff_github_markdown(report: &DiffReport) -> String { - format!( - "\n\n\n_base: `{}`_ _head: `{}`_\n", - report.base, report.head - ) -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{ - AnalysisBackend, ContributionReason, Language, MetricContribution, MetricKey, MetricSpace, - ParseDiagnostic, SourceSpan, SpaceId, SpaceKind, - }; - - fn report_with_metrics(pairs: &[(&str, f64)]) -> MetricsReport { - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - for (k, v) in pairs { - root.metrics.insert(MetricKey::new(*k), *v); - } - MetricsReport { - schema_version: "1.0".to_string(), - tool: "mehen".to_string(), - path: "foo.py".into(), - language: Language::Python, - analysis_backend: AnalysisBackend::PythonRuff, - diagnostics: Vec::new(), - root, - contributions: Vec::new(), - } - } - - #[test] - fn coverage_renders_before_language_specific_early_returns() { - // Regression: the coverage table used to be emitted after the - // Markdown/SQL early returns, so a measured documentation or - // SQL file silently dropped its coverage from `--format - // markdown` output. - let coverage_keys: &[(&str, f64)] = &[ - ("coverage.line", 50.0), - ("coverage.line.covered", 2.0), - ("coverage.line.total", 4.0), - ]; - for language in [Language::Markdown, Language::Sql, Language::Python] { - let mut report = report_with_metrics(coverage_keys); - report.language = language; - let md = render_metrics_markdown(&report); - assert!( - md.contains("### Coverage") && md.contains("| line | 50.0% | 2 | 4 |"), - "{language:?} output must carry the coverage table:\n{md}" - ); - // …and exactly once: source-code languages render it from - // the families pivot, the flat-family languages from the - // early path — never both. - assert_eq!( - md.matches("### Coverage").count(), - 1, - "{language:?} output must carry exactly one coverage table:\n{md}" - ); - } - // Unmeasured files omit the section entirely (absent ≠ 0%). - let md = render_metrics_markdown(&report_with_metrics(&[("loc.sloc", 3.0)])); - assert!(!md.contains("### Coverage")); - } - - #[test] - fn renders_metric_values_not_just_metadata() { - // Regression: prior implementation emitted only path / language / - // backend, dropping every metric value the analyzer published. - // Anyone calling `mehen metrics ... --format markdown` would see - // numbers vanish from CI artefacts and docs builds. - let report = report_with_metrics(&[ - ("cyclomatic.sum", 7.0), - ("loc.sloc", 42.0), - ("loc.lloc", 30.0), - ("halstead.volume", 123.5), - ]); - let md = render_metrics_markdown(&report); - - // File metadata is still there. - assert!(md.contains("# foo.py")); - assert!(md.contains("- language: `python`")); - - // The actual metric numbers must surface. - assert!( - md.contains("## Metrics"), - "missing Metrics section in output:\n{md}" - ); - assert!( - md.contains("### Cyclomatic"), - "missing Cyclomatic table in output:\n{md}" - ); - assert!(md.contains("| 7 |"), "cyclomatic.sum 7 not rendered:\n{md}"); - assert!(md.contains("### LOC"), "missing LOC table"); - assert!( - md.contains("| 42 | 0 | 30 | 0 | 0 |"), - "LOC row not rendered:\n{md}" - ); - assert!( - md.contains("### Halstead"), - "missing Halstead table in output:\n{md}" - ); - assert!( - md.contains("123.5000"), - "halstead.volume 123.5 not rendered:\n{md}" - ); - } - - #[test] - fn emits_diagnostics_section_when_present() { - let mut report = report_with_metrics(&[]); - report.diagnostics.push(ParseDiagnostic::error( - "python.parse_error", - "unexpected EOF while parsing", - )); - report.diagnostics.push(ParseDiagnostic::warning( - "python.style", - "long line | with pipe", - )); - let md = render_metrics_markdown(&report); - assert!(md.contains("## Diagnostics")); - assert!(md.contains("| error | `python.parse_error` | unexpected EOF while parsing |")); - // Pipe characters in messages must be escaped so they don't - // break the table layout. - assert!(md.contains(r"long line \| with pipe")); - } - - #[test] - fn skips_diagnostics_section_when_empty() { - let report = report_with_metrics(&[("cyclomatic.sum", 1.0)]); - let md = render_metrics_markdown(&report); - assert!(!md.contains("## Diagnostics")); - } - - #[test] - fn renders_contribution_evidence_when_present() { - let mut report = report_with_metrics(&[("cyclomatic.sum", 1.0)]); - report.contributions.push(MetricContribution { - metric: MetricKey::new("sql.change_risk_score"), - span: SourceSpan::new(10, 30, 2, 3), - amount: 8.0, - reason: ContributionReason::new("sql.change_risk.drop"), - }); - let md = render_metrics_markdown(&report); - assert!(md.contains("## Contributions")); - assert!(md.contains("| `sql.change_risk_score` | +8 |")); - assert!(md.contains("`sql.change_risk.drop` | L2–L3")); - } - - #[test] - fn contribution_reasons_with_pipes_are_escaped_in_the_table() { - // Operator-spelling reasons (`c.cyclomatic.||`) carry pipes; - // unescaped they would split the Markdown table into phantom - // columns (Codex review on PR #252). - let mut report = report_with_metrics(&[("cyclomatic.sum", 2.0)]); - report.contributions.push(MetricContribution { - metric: MetricKey::new("cyclomatic.sum"), - span: SourceSpan::new(4, 6, 1, 1), - amount: 1.0, - reason: ContributionReason::new("c.cyclomatic.||"), - }); - let md = render_metrics_markdown(&report); - assert!( - md.contains(r"`c.cyclomatic.\|\|`"), - "pipes in reasons must be escaped:\n{md}" - ); - // Every contribution row keeps exactly the 4-column shape. - for row in md - .lines() - .filter(|l| l.starts_with("| `") && l.contains("cyclomatic")) - { - assert_eq!( - row.matches(" | ").count(), - 3, - "row gained phantom columns: {row}" - ); - } - } - - #[test] - fn renders_markdown_family_when_language_is_markdown() { - // Regression: previously `write_unit_metrics` always pivoted - // through `MetricsFamilies`, which only reads source-code - // metric keys (`cyclomatic.*`, `loc.sloc`, `halstead.volume`, - // etc.). For `mehen metrics README.md --format markdown` the - // analyzer publishes `markdown.*` keys, so the pivot would - // emit all-zero source-code tables — misleading for the - // project's primary documentation-analysis use case. - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - for (k, v) in &[ - ("markdown.size.words", 1234.0), - ("markdown.size.headings", 8.0), - ("markdown.complexity.cognitive_complexity", 17.5), - ( - "markdown.maintainability.documentation_maintainability_index", - 88.25, - ), - ("markdown.links.broken", 2.0), - ("markdown.halstead.volume", 999.0), - ] { - root.metrics.insert(MetricKey::new(*k), *v); - } - let report = MetricsReport { - schema_version: "1.0".to_string(), - tool: "mehen".to_string(), - path: "README.md".into(), - language: Language::Markdown, - analysis_backend: AnalysisBackend::PulldownCmark, - diagnostics: Vec::new(), - root, - contributions: Vec::new(), - }; - let md = render_metrics_markdown(&report); - - // Markdown family sections must surface. - assert!(md.contains("### LOC"), "missing LOC section: {md}"); - assert!(md.contains("### Size"), "missing Size section: {md}"); - assert!( - md.contains("### Complexity"), - "missing Complexity section: {md}" - ); - assert!(md.contains("### Halstead"), "missing Halstead section"); - assert!(md.contains("### Links"), "missing Links section"); - assert!( - md.contains("### Maintainability"), - "missing Maintainability section" - ); - - // The actual published values must render — not as zeros. - assert!(md.contains("| 1234 |"), "size.words 1234 missing: {md}"); - assert!(md.contains("| 8 |"), "size.headings 8 missing: {md}"); - assert!( - md.contains("17.5000"), - "cognitive_complexity 17.5 missing: {md}" - ); - assert!( - md.contains("88.2500"), - "documentation_maintainability_index 88.25 missing: {md}" - ); - assert!(md.contains("| 2 |"), "links.broken 2 missing: {md}"); - assert!(md.contains("| 999 |"), "halstead.volume 999 missing: {md}"); - - // Source-code family tables must NOT appear for a Markdown - // report — they would all be zero and add noise. - assert!( - !md.contains("### Cyclomatic"), - "Cyclomatic table should be skipped for Markdown: {md}" - ); - assert!( - !md.contains("### ABC"), - "ABC table should be skipped for Markdown: {md}" - ); - assert!( - !md.contains("### NArgs"), - "NArgs table should be skipped for Markdown: {md}" - ); - assert!( - !md.contains("### NPA"), - "NPA table should be skipped for Markdown: {md}" - ); - } - - #[test] - fn includes_nested_spaces_when_present() { - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - root.metrics.insert(MetricKey::new("cyclomatic.sum"), 5.0); - let mut child = MetricSpace::new(SpaceId(1), SpaceKind::Function, SourceSpan::empty()); - child.name = Some("foo".to_string()); - child.metrics.insert(MetricKey::new("cyclomatic.sum"), 2.0); - root.spaces.push(child); - let report = MetricsReport { - schema_version: "1.0".to_string(), - tool: "mehen".to_string(), - path: "foo.py".into(), - language: Language::Python, - analysis_backend: AnalysisBackend::PythonRuff, - diagnostics: Vec::new(), - root, - contributions: Vec::new(), - }; - let md = render_metrics_markdown(&report); - assert!(md.contains("## Spaces")); - assert!(md.contains("function `foo`")); - // The nested space's cyclomatic.sum should appear in its - // own table. - let space_section = md.split("## Spaces").nth(1).expect("Spaces section"); - assert!(space_section.contains("| 2 |")); - } - - #[test] - fn sql_statement_spaces_render_their_line_count_not_empty_headings() { - // Regression: a SQL per-statement space carries only `sql.statement.lines` - // and no source-code roll-ups, so the renderer skipped its metric tables - // — leaving a `### custom ` heading with no content (Codex P3). - // It must instead surface the statement's line count. - let mut root = MetricSpace::new(SpaceId(0), SpaceKind::Unit, SourceSpan::empty()); - root.metrics - .insert(MetricKey::new("sql.statement.count"), 1.0); - let mut stmt = MetricSpace::new( - SpaceId(1), - SpaceKind::Custom(mehen_core::SmolStr::new("sql.statement")), - SourceSpan::empty(), - ); - stmt.name = Some("select".to_string()); - stmt.metrics - .insert(MetricKey::new("sql.statement.lines"), 3.0); - root.spaces.push(stmt); - let report = MetricsReport { - schema_version: "1.0".to_string(), - tool: "mehen".to_string(), - path: "q.sql".into(), - language: Language::Sql, - analysis_backend: AnalysisBackend::Sqruff, - diagnostics: Vec::new(), - root, - contributions: Vec::new(), - }; - let md = render_metrics_markdown(&report); - let space_section = md.split("## Spaces").nth(1).expect("Spaces section"); - assert!(space_section.contains("custom `select`")); - // The line count is surfaced, so the heading isn't a content-free stub. - assert!( - space_section.contains("- Lines: 3"), - "SQL statement space should show its line count: {space_section}" - ); - // No misleading source-code tables. - assert!(!space_section.contains("### Cyclomatic")); - } -} diff --git a/crates/mehen-report/src/metrics_json.rs b/crates/mehen-report/src/metrics_json.rs deleted file mode 100644 index 4fc64f34..00000000 --- a/crates/mehen-report/src/metrics_json.rs +++ /dev/null @@ -1,499 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Per-metric JSON renderer. -//! -//! Per the rewrite plan §9.1, `mehen metrics --format json` emits a -//! report whose `metrics` field is an object keyed by the metric family -//! (`cyclomatic`, `cognitive`, `halstead`, `loc`, …). Each family is a -//! nested object with the family-specific roll-up fields (`sum`, -//! `average`, `min`, `max` for cyclomatic / cognitive; `n1` / `N1` / -//! `volume` / … for Halstead; etc.). -//! -//! The new `MetricSpace::metrics` map keeps each numeric value at its own -//! flat key (`cyclomatic.sum`, `cyclomatic.min`, `loc.sloc.avg`, …) so -//! selectors can reference any individual aggregator. This module pivots -//! that flat shape back into the documented per-family object so the JSON -//! report matches the published schema. -//! -//! Per family is added here as the corresponding analyzer crate reaches -//! parity with that metric, so each family becomes consumable from the -//! report layer in lockstep with the per-language port (rewrite plan -//! §8.2). - -use mehen_core::{MetricKey, MetricSet, MetricValue}; -use serde::Serialize; - -/// Render the `cyclomatic` family object: `{ sum, average, min, max }`. -/// -/// Reads the rolled-up values published by the shared walker -/// (`mehen-tree-sitter::walker::apply_state_to`) at -/// `cyclomatic.sum` / `.avg` / `.min` / `.max`. Integer counts surface -/// as integer-valued floats so the JSON shape is uniform regardless of -/// the underlying numeric variant. -/// -/// Field declaration order on the typed struct is the JSON output order -/// — `sum`, `average`, `min`, `max` — matching the documented schema. -pub fn cyclomatic(metrics: &MetricSet) -> Cyclomatic { - Cyclomatic { - sum: as_f64(metrics, "cyclomatic.sum"), - average: as_f64(metrics, "cyclomatic.avg"), - min: as_f64(metrics, "cyclomatic.min"), - max: as_f64(metrics, "cyclomatic.max"), - } -} - -#[derive(Serialize)] -pub struct Cyclomatic { - pub sum: f64, - pub average: f64, - pub min: f64, - pub max: f64, -} - -/// Render the `nexits` family object: `{ sum, average, min, max }`. -/// -/// `sum` is the total number of exit points across the rolled-up -/// spaces, `average` divides by the function count (NOM total) — not -/// the space count. `min` and `max` bound the per-space counts. -pub fn nexits(metrics: &MetricSet) -> Nexits { - Nexits { - sum: as_f64(metrics, "nexit.sum"), - average: as_f64(metrics, "nexit.average"), - min: as_f64(metrics, "nexit.min"), - max: as_f64(metrics, "nexit.max"), - } -} - -#[derive(Serialize)] -pub struct Nexits { - pub sum: f64, - pub average: f64, - pub min: f64, - pub max: f64, -} - -/// Render the `cognitive` family object: `{ sum, average, min, max }`. -pub fn cognitive(metrics: &MetricSet) -> Cognitive { - Cognitive { - sum: as_f64(metrics, "cognitive.sum"), - average: as_f64(metrics, "cognitive.average"), - min: as_f64(metrics, "cognitive.min"), - max: as_f64(metrics, "cognitive.max"), - } -} - -#[derive(Serialize)] -pub struct Cognitive { - pub sum: f64, - pub average: f64, - pub min: f64, - pub max: f64, -} - -/// Render the `npa` family object: 9 fields tracking class / -/// interface public-attribute counts, totals, per-class CDA averages, -/// and the rolled-up total CDA. -pub fn npa(metrics: &MetricSet) -> Npa { - Npa { - classes: as_f64(metrics, "npa.classes"), - interfaces: as_f64(metrics, "npa.interfaces"), - class_attributes: as_f64(metrics, "npa.class_attributes"), - interface_attributes: as_f64(metrics, "npa.interface_attributes"), - classes_average: as_f64(metrics, "npa.classes_average"), - interfaces_average: as_f64(metrics, "npa.interfaces_average"), - total: as_f64(metrics, "npa"), - total_attributes: as_f64(metrics, "npa.total_attributes"), - average: as_f64(metrics, "npa.average"), - } -} - -/// `f64::NAN` serializes as JSON `null` via the `nan_as_null` helper, -/// matching the pre-1.0 `interfaces_average: null` output for empty -/// interface buckets. -fn serialize_nan_as_null(value: &f64, ser: S) -> Result { - if value.is_nan() { - ser.serialize_none() - } else { - ser.serialize_f64(*value) - } -} - -#[derive(Serialize)] -pub struct Npa { - pub classes: f64, - pub interfaces: f64, - pub class_attributes: f64, - pub interface_attributes: f64, - #[serde(serialize_with = "serialize_nan_as_null")] - pub classes_average: f64, - #[serde(serialize_with = "serialize_nan_as_null")] - pub interfaces_average: f64, - pub total: f64, - pub total_attributes: f64, - #[serde(serialize_with = "serialize_nan_as_null")] - pub average: f64, -} - -/// Render the `npm` family object: 9 fields tracking class / -/// interface public-method counts, totals, per-class averages, and -/// the rolled-up total average. -pub fn npm(metrics: &MetricSet) -> Npm { - Npm { - classes: as_f64(metrics, "npm.classes"), - interfaces: as_f64(metrics, "npm.interfaces"), - class_methods: as_f64(metrics, "npm.class_methods"), - interface_methods: as_f64(metrics, "npm.interface_methods"), - classes_average: as_f64(metrics, "npm.classes_average"), - interfaces_average: as_f64(metrics, "npm.interfaces_average"), - total: as_f64(metrics, "npm"), - total_methods: as_f64(metrics, "npm.total_methods"), - average: as_f64(metrics, "npm.average"), - } -} - -#[derive(Serialize)] -pub struct Npm { - pub classes: f64, - pub interfaces: f64, - pub class_methods: f64, - pub interface_methods: f64, - #[serde(serialize_with = "serialize_nan_as_null")] - pub classes_average: f64, - #[serde(serialize_with = "serialize_nan_as_null")] - pub interfaces_average: f64, - pub total: f64, - pub total_methods: f64, - #[serde(serialize_with = "serialize_nan_as_null")] - pub average: f64, -} - -/// Render the `wmc` family object: 3 fields totalling -/// per-class-or-interface weighted method counts. -pub fn wmc(metrics: &MetricSet) -> Wmc { - Wmc { - classes: as_f64(metrics, "wmc.classes"), - interfaces: as_f64(metrics, "wmc.interfaces"), - total: as_f64(metrics, "wmc"), - } -} - -#[derive(Serialize)] -pub struct Wmc { - pub classes: f64, - pub interfaces: f64, - pub total: f64, -} - -/// Render the `halstead` family object: 14 fields covering n1/N1/n2/N2, -/// length, estimated_program_length, purity_ratio, vocabulary, volume, -/// difficulty, level, effort, time, and bugs. Field ordering matches -/// the pre-1.0 `halstead::Stats::serialize`. -pub fn halstead(metrics: &MetricSet) -> Halstead { - Halstead { - n1: as_f64(metrics, "halstead.n1"), - big_n1: as_f64(metrics, "halstead.N1"), - n2: as_f64(metrics, "halstead.n2"), - big_n2: as_f64(metrics, "halstead.N2"), - length: as_f64(metrics, "halstead.length"), - estimated_program_length: as_f64(metrics, "halstead.estimated_program_length"), - purity_ratio: as_f64(metrics, "halstead.purity_ratio"), - vocabulary: as_f64(metrics, "halstead.vocabulary"), - volume: as_f64(metrics, "halstead.volume"), - difficulty: as_f64(metrics, "halstead.difficulty"), - level: as_f64(metrics, "halstead.level"), - effort: as_f64(metrics, "halstead.effort"), - time: as_f64(metrics, "halstead.time"), - bugs: as_f64(metrics, "halstead.bugs"), - } -} - -#[derive(Serialize)] -pub struct Halstead { - pub n1: f64, - #[serde(rename = "N1")] - pub big_n1: f64, - pub n2: f64, - #[serde(rename = "N2")] - pub big_n2: f64, - pub length: f64, - pub estimated_program_length: f64, - pub purity_ratio: f64, - pub vocabulary: f64, - pub volume: f64, - pub difficulty: f64, - pub level: f64, - pub effort: f64, - pub time: f64, - pub bugs: f64, -} - -/// Render the `abc` family object: 13 fields covering A/B/C totals, -/// the magnitude formula `sqrt(A² + B² + C²)`, per-class averages, and -/// per-class min/max bounds. Matches the pre-1.0 -/// `abc::Stats::serialize` field order. -pub fn abc(metrics: &MetricSet) -> Abc { - Abc { - assignments: as_f64(metrics, "abc.assignments"), - branches: as_f64(metrics, "abc.branches"), - conditions: as_f64(metrics, "abc.conditions"), - magnitude: as_f64(metrics, "abc"), - assignments_average: as_f64(metrics, "abc.assignments_average"), - branches_average: as_f64(metrics, "abc.branches_average"), - conditions_average: as_f64(metrics, "abc.conditions_average"), - assignments_min: as_f64(metrics, "abc.assignments_min"), - assignments_max: as_f64(metrics, "abc.assignments_max"), - branches_min: as_f64(metrics, "abc.branches_min"), - branches_max: as_f64(metrics, "abc.branches_max"), - conditions_min: as_f64(metrics, "abc.conditions_min"), - conditions_max: as_f64(metrics, "abc.conditions_max"), - } -} - -#[derive(Serialize)] -pub struct Abc { - pub assignments: f64, - pub branches: f64, - pub conditions: f64, - pub magnitude: f64, - pub assignments_average: f64, - pub branches_average: f64, - pub conditions_average: f64, - pub assignments_min: f64, - pub assignments_max: f64, - pub branches_min: f64, - pub branches_max: f64, - pub conditions_min: f64, - pub conditions_max: f64, -} - -/// Render the `nargs` family object: 10 fields covering per-class -/// argument totals, averages, total, and min/max bounds. Field -/// ordering matches the pre-1.0 `nargs::Stats::serialize`. -pub fn nargs(metrics: &MetricSet) -> Nargs { - Nargs { - total_functions: as_f64(metrics, "nargs.total_functions"), - total_closures: as_f64(metrics, "nargs.total_closures"), - average_functions: as_f64(metrics, "nargs.average_functions"), - average_closures: as_f64(metrics, "nargs.average_closures"), - total: as_f64(metrics, "nargs"), - average: as_f64(metrics, "nargs.average"), - functions_min: as_f64(metrics, "nargs.functions_min"), - functions_max: as_f64(metrics, "nargs.functions_max"), - closures_min: as_f64(metrics, "nargs.closures_min"), - closures_max: as_f64(metrics, "nargs.closures_max"), - } -} - -#[derive(Serialize)] -pub struct Nargs { - pub total_functions: f64, - pub total_closures: f64, - pub average_functions: f64, - pub average_closures: f64, - pub total: f64, - pub average: f64, - pub functions_min: f64, - pub functions_max: f64, - pub closures_min: f64, - pub closures_max: f64, -} - -/// Render the `nom` family object: 10 fields covering function / -/// closure counts, per-class averages, total, and per-class min/max -/// bounds. Field ordering matches the pre-1.0 `Nom::Stats::serialize`. -pub fn nom(metrics: &MetricSet) -> Nom { - Nom { - functions: as_f64(metrics, "nom.functions"), - closures: as_f64(metrics, "nom.closures"), - functions_average: as_f64(metrics, "nom.functions_average"), - closures_average: as_f64(metrics, "nom.closures_average"), - total: as_f64(metrics, "nom"), - average: as_f64(metrics, "nom.average"), - functions_min: as_f64(metrics, "nom.functions_min"), - functions_max: as_f64(metrics, "nom.functions_max"), - closures_min: as_f64(metrics, "nom.closures_min"), - closures_max: as_f64(metrics, "nom.closures_max"), - } -} - -#[derive(Serialize)] -pub struct Nom { - pub functions: f64, - pub closures: f64, - pub functions_average: f64, - pub closures_average: f64, - pub total: f64, - pub average: f64, - pub functions_min: f64, - pub functions_max: f64, - pub closures_min: f64, - pub closures_max: f64, -} - -/// Render the `loc` family object: 20 fields covering SLOC / PLOC / -/// LLOC / CLOC / blank with rolled-up totals, per-line-class -/// averages, and per-line-class min/max bounds. The ordering matches -/// the pre-1.0 `Loc::Stats::serialize` field order. -pub fn loc(metrics: &MetricSet) -> Loc { - Loc { - sloc: as_f64(metrics, "loc.sloc"), - ploc: as_f64(metrics, "loc.ploc"), - lloc: as_f64(metrics, "loc.lloc"), - cloc: as_f64(metrics, "loc.cloc"), - blank: as_f64(metrics, "loc.blank"), - sloc_average: as_f64(metrics, "loc.sloc.avg"), - ploc_average: as_f64(metrics, "loc.ploc.avg"), - lloc_average: as_f64(metrics, "loc.lloc.avg"), - cloc_average: as_f64(metrics, "loc.cloc.avg"), - blank_average: as_f64(metrics, "loc.blank.avg"), - sloc_min: as_f64(metrics, "loc.sloc.min"), - sloc_max: as_f64(metrics, "loc.sloc.max"), - cloc_min: as_f64(metrics, "loc.cloc.min"), - cloc_max: as_f64(metrics, "loc.cloc.max"), - ploc_min: as_f64(metrics, "loc.ploc.min"), - ploc_max: as_f64(metrics, "loc.ploc.max"), - lloc_min: as_f64(metrics, "loc.lloc.min"), - lloc_max: as_f64(metrics, "loc.lloc.max"), - blank_min: as_f64(metrics, "loc.blank.min"), - blank_max: as_f64(metrics, "loc.blank.max"), - } -} - -#[derive(Serialize)] -pub struct Loc { - pub sloc: f64, - pub ploc: f64, - pub lloc: f64, - pub cloc: f64, - pub blank: f64, - pub sloc_average: f64, - pub ploc_average: f64, - pub lloc_average: f64, - pub cloc_average: f64, - pub blank_average: f64, - pub sloc_min: f64, - pub sloc_max: f64, - pub cloc_min: f64, - pub cloc_max: f64, - pub ploc_min: f64, - pub ploc_max: f64, - pub lloc_min: f64, - pub lloc_max: f64, - pub blank_min: f64, - pub blank_max: f64, -} - -fn as_f64(metrics: &MetricSet, key: &str) -> f64 { - match metrics.get(&MetricKey::new(key)) { - Some(MetricValue::Int(i)) => i as f64, - Some(MetricValue::Float(f)) => f, - None => 0.0, - } -} - -fn maybe_f64(metrics: &MetricSet, key: &str) -> Option { - match metrics.get(&MetricKey::new(key)) { - Some(MetricValue::Int(i)) => Some(i as f64), - Some(MetricValue::Float(f)) => Some(f), - None => None, - } -} - -/// One measured coverage dimension: the rate (percent, `0..=100`) plus -/// the covered/total counters behind it. -#[derive(Serialize)] -pub struct CoverageDimension { - pub percent: f64, - pub covered: u64, - pub total: u64, -} - -/// Render the `coverage` family object. Unlike the source-code -/// families, coverage is **omitted entirely when unmeasured** — a file -/// absent from every ingested report must read as "no data", never as -/// a fabricated 0%. Each dimension (`line`, `branch`, `function`) is -/// likewise present only when the report format measured it: a Go -/// coverprofile carries no branch records, so `branch` stays absent. -pub fn coverage(metrics: &MetricSet) -> Option { - let dimension = |rate: &str, covered: &str, total: &str| -> Option { - Some(CoverageDimension { - percent: maybe_f64(metrics, rate)?, - covered: maybe_f64(metrics, covered)? as u64, - total: maybe_f64(metrics, total)? as u64, - }) - }; - let family = Coverage { - line: dimension( - "coverage.line", - "coverage.line.covered", - "coverage.line.total", - ), - branch: dimension( - "coverage.branch", - "coverage.branch.covered", - "coverage.branch.total", - ), - function: dimension( - "coverage.function", - "coverage.function.covered", - "coverage.function.total", - ), - }; - if family.line.is_none() && family.branch.is_none() && family.function.is_none() { - None - } else { - Some(family) - } -} - -#[derive(Serialize)] -pub struct Coverage { - #[serde(skip_serializing_if = "Option::is_none")] - pub line: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub branch: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub function: Option, -} - -/// All metric families pivoted into the documented per-family shape. -/// This is what the CLI emits as the `metrics` field of `mehen metrics -/// --format json`, replacing the flat `metric_key → value` map of the -/// raw `MetricSpace`. -#[derive(Serialize)] -pub struct MetricsFamilies { - pub cyclomatic: Cyclomatic, - pub cognitive: Cognitive, - pub nexits: Nexits, - pub nom: Nom, - pub nargs: Nargs, - pub npa: Npa, - pub npm: Npm, - pub wmc: Wmc, - pub abc: Abc, - pub halstead: Halstead, - pub loc: Loc, - /// Present only when coverage enrichment measured this file. - #[serde(skip_serializing_if = "Option::is_none")] - pub coverage: Option, -} - -impl MetricsFamilies { - pub fn from_metrics(metrics: &MetricSet) -> Self { - Self { - cyclomatic: cyclomatic(metrics), - cognitive: cognitive(metrics), - nexits: nexits(metrics), - nom: nom(metrics), - nargs: nargs(metrics), - npa: npa(metrics), - npm: npm(metrics), - wmc: wmc(metrics), - abc: abc(metrics), - halstead: halstead(metrics), - loc: loc(metrics), - coverage: coverage(metrics), - } - } -} diff --git a/crates/mehen-ruby/Cargo.toml b/crates/mehen-ruby/Cargo.toml deleted file mode 100644 index 3557eaef..00000000 --- a/crates/mehen-ruby/Cargo.toml +++ /dev/null @@ -1,51 +0,0 @@ -[package] -name = "mehen-ruby" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — Ruby language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -# `ruby-prism` — replaces tree-sitter-ruby for this analyzer. Pinned -# here (not in `[workspace.dependencies]`) because `mehen-ruby` is the -# only consumer. Per the rewrite plan §6.5 we move to Ruby's canonical -# Prism parser so modifier forms (`x if y`, `expr rescue`), pattern -# matching (`case…in`), endless methods, safe navigation (`&.`), -# numbered block parameters, and all the Ruby-3-era syntax the -# tree-sitter grammar lags on become first-class. -# -# License audit (plan §6.5): `ruby-prism` (MIT, Ian Ker-Seymer / Steve -# Loveless / Kevin Newton), `ruby-prism-sys` (MIT), and the bundled -# upstream Prism C parser (MIT, Shopify Inc.) are all permissive — no -# copyleft conflict with mehen's licensing. -# -# Build prerequisites (plan §6.5 — "Windows CI/release jobs must -# install the required native toolchain"): `ruby-prism-sys` invokes -# `bindgen 0.72` unconditionally and compiles vendored Prism C via -# `cc`, so every release target needs `libclang` and a C toolchain -# at build time. Linux/macOS GitHub-hosted runners have these -# preinstalled, but the manylinux_2_28 (AlmaLinux 8, dnf) and -# musllinux/`rust-musl-cross` (Debian, apt) containers that -# `PyO3/maturin-action` uses to build wheels do NOT — release.yml -# installs `clang-devel` / `libclang-dev` via `before-script-linux`. -# manylinux2014 cannot be used here: its clang is 3.4 (2014-era), -# below bindgen 0.72's 9.0+ requirement. -# Windows runners need `LIBCLANG_PATH` (e.g. `choco install llvm`). -# The release binary path means end users do not need any of this — -# only people building `mehen` from source. -ruby-prism = "=1.9.0" -smol_str = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-ruby/src/lib.rs b/crates/mehen-ruby/src/lib.rs deleted file mode 100644 index 043b6914..00000000 --- a/crates/mehen-ruby/src/lib.rs +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-ruby` — Ruby language analyzer. -//! -//! Phase 9 implementation: ruby-prism-backed walker. Replaces the -//! Phase-3 tree-sitter-ruby analyzer. Per `docs/ruby-prism-spec.md`, -//! every metric is computed from the Prism AST. Ruby-specific -//! behaviour (modifier forms, `rescue` modifier, `case…in` pattern -//! matching, blocks vs lambdas, numbered/`it` block parameters, -//! singleton classes, ivar conventions) is documented in that spec. - -#![forbid(unsafe_code)] - -mod walker; - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, ParseDiagnostic, - Result, SourceFile, -}; -use mehen_metrics::MetricEvidence; - -/// Ruby Prism analyzer (Phase 9, see `docs/ruby-prism-spec.md`). -pub struct RubyAnalyzer; - -impl RubyAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for RubyAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for RubyAnalyzer { - fn language(&self) -> Language { - Language::Ruby - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::Prism - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - let parse = ruby_prism::parse(source.text.as_bytes()); - let mut evidence = MetricEvidence::new("ruby", config.emit_contributions); - let root = walker::walk_program(&parse, &source.text, &source.line_index, &mut evidence); - // Recovered Prism syntax errors are surfaced as `error` (not - // `warning`) so the diagnostic contract (plan §9.3) treats the - // analysis as incomplete: `mehen metrics` exits 1 and - // `analyze_diff` records the file under `analysis_errors`. - let diagnostics: Vec = parse - .errors() - .map(|e| ParseDiagnostic::error("ruby.syntax_error", e.message().to_string())) - .collect(); - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::Ruby, - backend: AnalysisBackend::Prism, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use mehen_core::{AnalysisConfig, Language, SourceFile, SpaceKind}; - - fn analyze(source: &str, path: &str) -> LanguageAnalysis { - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new(path.into(), Language::Ruby, source.to_string()); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() - } - - #[test] - fn empty_file_yields_root_unit() { - let a = analyze("", "test.rb"); - assert_eq!(a.root.kind, SpaceKind::Unit); - assert!(a.root.spaces.is_empty()); - } - - #[test] - fn def_creates_function_space() { - let a = analyze("def foo\n 1\nend\n", "test.rb"); - assert!(a.root.spaces.iter().any(|s| s.kind == SpaceKind::Function)); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("foo")); - } - - #[test] - fn class_creates_class_space_with_method() { - let a = analyze("class C\n def m; end\nend\n", "test.rb"); - assert_eq!(a.root.spaces.len(), 1); - assert_eq!(a.root.spaces[0].kind, SpaceKind::Class); - assert_eq!(a.root.spaces[0].name.as_deref(), Some("C")); - assert_eq!(a.root.spaces[0].spaces.len(), 1); - assert_eq!(a.root.spaces[0].spaces[0].kind, SpaceKind::Function); - } -} diff --git a/crates/mehen-ruby/src/walker.rs b/crates/mehen-ruby/src/walker.rs deleted file mode 100644 index 2fd55f25..00000000 --- a/crates/mehen-ruby/src/walker.rs +++ /dev/null @@ -1,1335 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Ruby Prism AST walker that produces a populated `MetricSpace`. -//! -//! Recursion is driven by ruby-prism's -//! [`Visit`](https://docs.rs/ruby-prism/latest/ruby_prism/trait.Visit.html) -//! trait — the per-node-type visitor generated by Prism's `config.yml`. -//! Same architecture as `mehen-php`'s `mago_syntax::walker::Walker` and -//! `mehen-python`'s `ruff_python_ast::visitor::source_order::SourceOrderVisitor`: -//! we override the metric-bearing hooks, call the matching free function -//! `visit__node(self, node)` to keep walking children, and use -//! `visit_branch_node_enter`/`_leave` only when we genuinely need -//! cross-node bookkeeping. Default behaviour for every other node is -//! "descend into children" — which is exactly what we want for the -//! structural-only kinds. -//! -//! The walker follows the same per-space `State` accumulator pattern -//! used by the other language crates (`mehen-metrics::state`): one -//! `State` per opened space, finalize on close, fold child stats into -//! parent. -//! -//! ## Ruby-specific design decisions -//! -//! Documented in `docs/ruby-prism-spec.md`. The short version: -//! -//! - **Modifier forms** (`x if y`, `x unless y`, `x while y`, -//! `x until y`): Prism collapses block and modifier forms into one -//! node struct; the absence of `end_keyword_loc` / `closing_loc` -//! distinguishes the modifier form. Per Sonar's cognitive-complexity -//! spec we still bump `+1` for modifier forms but DO NOT increase -//! nesting (the modifier sits on the trailing edge of the statement, -//! it is not a nesting structure). Cyclomatic counts modifier and -//! block forms identically — both are decision points. -//! -//! - **`rescue` modifier (`expr rescue fallback`)**: a separate node -//! kind in Prism (`RescueModifierNode`), distinct from the -//! block-form `RescueNode` inside a `BeginNode`. We treat the -//! modifier as `+1` cognitive without nesting, the block form as -//! nesting-bumping (matches legacy walker per-Sonar policy). -//! -//! - **`case … in` pattern matching**: Prism exposes `CaseMatchNode` -//! with `InNode` clauses (separate from classic `CaseNode` / -//! `WhenNode`). Each `in` clause is a decision point; the `case` -//! itself bumps cognitive nesting once. -//! -//! - **Halstead from AST, not tokens**: ruby-prism does NOT expose a -//! public token stream (verified — `pm_token_t` / `pm_lex_*` symbols -//! are not allowlisted by `ruby-prism-sys`'s bindgen). We derive -//! operator/operand counts from the AST: `CallNode::name()` for -//! arithmetic / comparison operators (Ruby parses `a + b` as a -//! call to `:+` on `a` with argument `b`), the `*WriteNode` / -//! `*OperatorWriteNode` / `*AndWriteNode` / `*OrWriteNode` families -//! for assignment operators, dedicated visit hooks for keyword -//! operators (`def`, `class`, `if`, …), and leaf literal / variable -//! nodes for operands. The legacy tree-sitter walker also counted -//! from the CST (the grammar does not expose a flat token stream -//! either), so this is parity-preserving — see -//! `docs/ruby-prism-spec.md §3.1` for the per-token-class table. -//! -//! - **Block under lambda**: a `BlockNode` whose immediate parent is a -//! `LambdaNode` is the lambda body, not an additional nested -//! closure. We track this via the `inside_lambda_body` flag so the -//! block-call visit does not emit a duplicate `nom.record_closure()` -//! nor double the cognitive `lambda` counter. - -use mehen_core::{LineIndex, MetricSpace, SourceSpan, SpaceKind}; -use mehen_metrics::{ - ContainerKind, HalsteadOperand, HalsteadOperator, MetricEvidence, MetricTreeBuilder, State, - apply_state_to, close_space, finalize_state, -}; -use ruby_prism::{ - AndNode, BeginNode, BlockNode, BreakNode, CallNode, CallOperatorWriteNode, CaseMatchNode, - CaseNode, ClassNode, ClassVariableReadNode, ConstantReadNode, ConstantWriteNode, DefNode, - ElseNode, FalseNode, FloatNode, ForNode, GlobalVariableReadNode, IfNode, InNode, - IndexOperatorWriteNode, InstanceVariableReadNode, InstanceVariableWriteNode, IntegerNode, - LambdaNode, LocalVariableAndWriteNode, LocalVariableOperatorWriteNode, - LocalVariableOrWriteNode, LocalVariableReadNode, LocalVariableWriteNode, MatchPredicateNode, - ModuleNode, NextNode, NilNode, Node, OptionalParameterNode, OrNode, ParseResult, RedoNode, - RequiredParameterNode, RescueModifierNode, RescueNode, ReturnNode, SelfNode, - SingletonClassNode, StringNode, SymbolNode, TrueNode, UnlessNode, UntilNode, Visit, WhenNode, - WhileNode, YieldNode, visit_and_node, visit_begin_node, visit_block_node, visit_break_node, - visit_call_node, visit_call_operator_write_node, visit_case_match_node, visit_case_node, - visit_class_node, visit_constant_write_node, visit_def_node, visit_else_node, visit_for_node, - visit_if_node, visit_in_node, visit_index_operator_write_node, - visit_instance_variable_write_node, visit_lambda_node, visit_local_variable_and_write_node, - visit_local_variable_operator_write_node, visit_local_variable_or_write_node, - visit_local_variable_write_node, visit_match_predicate_node, visit_module_node, - visit_next_node, visit_optional_parameter_node, visit_or_node, visit_redo_node, - visit_rescue_modifier_node, visit_rescue_node, visit_return_node, visit_singleton_class_node, - visit_unless_node, visit_until_node, visit_when_node, visit_while_node, visit_yield_node, -}; -use smol_str::SmolStr; - -/// Drive the walker over a parsed Ruby program. Crate-internal entry -/// point — only `mehen_ruby::RubyAnalyzer::analyze` calls this; not -/// part of any cross-crate API. Contribution evidence is recorded into -/// the caller-owned `evidence` sink (plan §5.4). -pub(crate) fn walk_program( - parse: &ParseResult<'_>, - source: &str, - line_index: &LineIndex, - evidence: &mut MetricEvidence, -) -> MetricSpace { - let unit_span = SourceSpan { - start_byte: 0, - end_byte: u32::try_from(source.len()).unwrap_or(u32::MAX), - start_line: 1, - end_line: line_index.line_count(), - }; - - let mut visitor = Visitor::new(line_index, unit_span, evidence); - let root = parse.node(); - visitor.visit(&root); - - // LOC: Ruby comments come from `parse.comments()` (inline `#` - // lines and `=begin`/`=end` block-doc comments). The legacy - // tree-sitter Loc rule counts both as `cloc` lines, but on the - // unit only — that loses per-method `loc.cloc` for any comment - // inside a method body. Route each comment by byte range to the - // deepest enclosing scope; `finish` then propagates them up the - // parent chain. - for comment in parse.comments() { - let loc = comment.location(); - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - let start_row = line_index.line_at(start).saturating_sub(1); - let end_row = line_index.line_at(end.saturating_sub(1)).saturating_sub(1); - visitor.halstead_routing.observe_comment( - start, - end, - &mut visitor.stack[0].loc, - start_row, - end_row, - ); - } - - visitor.finish() -} - -struct Visitor<'a> { - line_index: &'a LineIndex, - /// Contribution-evidence sink (plan §5.4). Record methods are - /// no-ops when disabled, so visit hooks call them unconditionally - /// (via `record_evidence`) next to each stat increment. - evidence: &'a mut MetricEvidence, - tree: MetricTreeBuilder, - /// Per-space accumulator stack — index 0 is the unit. - stack: Vec, - /// Parallel to `stack`: the SpaceKind of each frame so we can tell - /// "what's the enclosing class-like" without re-walking. - kinds: Vec, - /// Inherited cognitive context. Mirrors the legacy - /// `(nesting, depth, lambda)` triple from - /// `mehen-engine/src/legacy/metrics/cognitive.rs::RubyCode`. - cognitive: CognitiveContext, - /// True while walking the body of a lambda — used to suppress the - /// per-block lambda bump for a block that IS the lambda body - /// (matches the legacy `Block | DoBlock if parent != Lambda` rule). - inside_lambda_body: bool, - /// Depth of nested boolean (And/Or) expressions; used to detect the - /// outermost boolean for the boolean-sequence collapser. - bool_depth: u32, - /// Total number of statement-shaped LLOC contributions so far on the - /// current space. Ruby's prism does not surface a - /// "statement-boundary" event in a clean way, so we observe lloc at - /// statement-shaped node hooks (see `record_lloc_for_node`). - _phantom: std::marker::PhantomData<&'a ()>, - /// Routes comment / PLOC observations to the deepest enclosing - /// space. Ruby's `parse.comments()` lives on the `ParseResult` - /// (no AST wrapper to record on), so the walker observes them - /// after the AST walk has populated the tracker entries — - /// otherwise every comment lands on the unit and per-space - /// `loc.cloc` is zero (PR #95 discussion_r3265962147). - halstead_routing: mehen_metrics::SpaceRangeTracker, -} - -#[derive(Clone, Copy, Debug, Default)] -struct CognitiveContext { - nesting: u32, - depth: u32, - lambda: u32, -} - -impl<'a> Visitor<'a> { - fn new( - line_index: &'a LineIndex, - unit_span: SourceSpan, - evidence: &'a mut MetricEvidence, - ) -> Self { - let mut state = State::new(); - state.loc.set_span( - unit_span.start_line.saturating_sub(1), - unit_span.end_line.saturating_sub(1), - true, - ); - Self { - line_index, - evidence, - tree: MetricTreeBuilder::new(unit_span), - stack: vec![state], - kinds: vec![SpaceKind::Unit], - cognitive: CognitiveContext::default(), - inside_lambda_body: false, - bool_depth: 0, - _phantom: std::marker::PhantomData, - halstead_routing: mehen_metrics::SpaceRangeTracker::new(), - } - } - - fn current(&mut self) -> &mut State { - self.stack.last_mut().expect("walker stack empty") - } - - /// Resolve a Prism `Location` to a `SourceSpan` (1-based lines) — - /// same byte→line formula as `open_space`. - fn span_for(&self, loc: &ruby_prism::Location<'_>) -> SourceSpan { - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - SourceSpan { - start_byte: start, - end_byte: end, - start_line: self.line_index.line_at(start), - end_line: self.line_index.line_at(end.saturating_sub(1)), - } - } - - /// Record contribution evidence for a Prism location. The span is - /// only computed when the sink is enabled, so visit hooks can call - /// this unconditionally next to each stat increment: - /// - /// ```ignore - /// self.current().cyclomatic.record_decision(); - /// self.record_evidence(&node.location(), |e, s| e.decision(s, "if_node")); - /// ``` - #[inline] - fn record_evidence(&mut self, loc: &ruby_prism::Location<'_>, record: F) - where - F: FnOnce(&mut MetricEvidence, SourceSpan), - { - if self.evidence.is_enabled() { - let span = self.span_for(loc); - record(self.evidence, span); - } - } - - fn finish(mut self) -> MetricSpace { - let mut unit_state = self.stack.pop().expect("walker stack underflow"); - finalize_state(&mut unit_state); - // Route post-AST observations (only LOC for Ruby — Halstead is - // emitted *during* the AST walk via `current()`) to nested - // spaces. The tracker has accumulated comments routed by - // byte range; `finalize_into_tree` propagates each entry's - // contributions up the parent chain (set-union for ploc lines, - // sum for comment counts) and overlays the LOC keys + MI on - // the matching `MetricSpace`. - let mut unit_halstead = std::mem::take(&mut unit_state.halstead); - let mut unit_loc = std::mem::take(&mut unit_state.loc); - let mut tree = self.tree.finish(); - self.halstead_routing - .finalize_into_tree(&mut tree, &mut unit_halstead, &mut unit_loc); - unit_state.halstead = unit_halstead; - unit_state.loc = unit_loc; - apply_state_to(unit_state, &mut tree.metrics); - tree - } - - fn open_space( - &mut self, - kind: SpaceKind, - start_byte: u32, - end_byte: u32, - name: Option, - ) { - let mut child = State::for_opened_space(kind.clone()); - let start_row = self.line_index.line_at(start_byte).saturating_sub(1); - let end_row = self - .line_index - .line_at(end_byte.saturating_sub(1)) - .saturating_sub(1); - child.loc.set_span(start_row, end_row, false); - - let span = SourceSpan { - start_byte, - end_byte, - start_line: self.line_index.line_at(start_byte), - end_line: self.line_index.line_at(end_byte.saturating_sub(1)), - }; - let space_id = self.tree.open(kind.clone(), span, name); - self.halstead_routing - .record_open(space_id, start_byte, end_byte); - self.stack.push(child); - self.kinds.push(kind); - } - - fn close_space(&mut self) { - close_space( - &mut self.stack, - &mut self.kinds, - &mut self.tree, - &mut self.halstead_routing, - ); - } - - /// Record an "actionable" statement at this node's start line. - /// Mirrors how `loc.rs::PythonCode::compute` and the Phase-8 PHP - /// walker decide what counts as an LLOC. Container nodes (def, - /// class, module) are NOT LLOC — their bodies do. - fn record_lloc(&mut self, byte_start: u32, is_lloc: bool) { - let row = self.line_index.line_at(byte_start).saturating_sub(1); - let cur = self.current(); - if is_lloc { - cur.loc.observe_lloc(); - } - cur.loc.observe_code_line(row); - } - - /// Increase nesting + boolean-seq reset, mirroring legacy - /// `increase_nesting` from `cognitive.rs:239`. Returns the - /// structural delta actually applied (`effective + 1`) so callers - /// can record it as contribution evidence. - fn cognitive_increase_nesting(&mut self) -> u32 { - let effective = self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.current().cognitive.boolean_seq.reset(); - effective.saturating_add(1) - } - - fn cognitive_increment_by_one(&mut self) { - self.current().cognitive.increment_by_one(); - self.current().cognitive.boolean_seq.reset(); - } - - /// Observe a code line for a keyword location that prism exposes - /// as a `Location` field on a parent AST node (e.g. - /// `end_keyword_loc`, `closing_loc`). These tokens have no - /// separate node visit in prism, but the legacy tree-sitter walker - /// did visit them as anonymous-keyword tokens, contributing their - /// start_row to PLOC. Per the PLOC definition (physical lines - /// containing executable code), an `end` keyword line IS code, so - /// we record it here. - fn observe_keyword_line(&mut self, loc: &ruby_prism::Location<'_>) { - let row = self - .line_index - .line_at(u32::try_from(loc.start_offset()).unwrap_or(0)) - .saturating_sub(1); - self.current().loc.observe_code_line(row); - } - - fn observe_optional_keyword_line(&mut self, loc: Option>) { - if let Some(l) = loc { - self.observe_keyword_line(&l); - } - } - - /// Halstead routes to the *current* (innermost) space so nested - /// def/class bodies carry their own counts; the close path's - /// `merge_child_into_parent` rolls these up into the enclosing - /// scope and the unit (set-union for `n1`/`n2`, sum for - /// `N1`/`N2`). - fn record_halstead_op(&mut self, kind: &'static str) { - self.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(kind), - text: None, - }); - } - - fn record_halstead_op_text(&mut self, kind: &'static str, text: &str) { - self.current().halstead.observe_operator(HalsteadOperator { - kind: SmolStr::new(kind), - text: Some(SmolStr::new(text)), - }); - } - - fn record_halstead_operand_text(&mut self, kind: &'static str, text: &str) { - self.current().halstead.observe_operand(HalsteadOperand { - kind: SmolStr::new(kind), - text: Some(SmolStr::new(text)), - }); - } -} - -impl<'pr> Visit<'pr> for Visitor<'_> { - // ─── Definitions / scopes ────────────────────────────────────────────── - - fn visit_def_node(&mut self, node: &DefNode<'pr>) { - // `def name(params); body; end` — function-like space. - let loc = node.location(); - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - let name_bytes = node.name().as_slice(); - let name = std::str::from_utf8(name_bytes).ok().map(|s| s.to_string()); - - // Class-body member classification: `def f` inside a `class …` - // body is a method (NPM); `def self.f` is a class method but - // still NPM-counted. Legacy walker treats both the same. - let parent_kind = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - let in_class = matches!( - parent_kind, - SpaceKind::Class | SpaceKind::Impl | SpaceKind::Interface | SpaceKind::Trait - ); - if in_class { - let is_public = name.as_deref().map(ruby_method_is_public).unwrap_or(true); - self.current() - .npm - .record_method(ContainerKind::Class, is_public); - // NPM evidence covers public members only — the headline - // metric counts public methods. - if is_public { - self.record_evidence(&loc, |e, s| e.public_method(s, "def_node")); - } - } - - // `def` keyword as Halstead operator; method name as operand. - self.record_halstead_op("def"); - if let Some(ref n) = name { - self.record_halstead_operand_text("Identifier", n); - } - // Parameter list `(…)` and parameter separators `,` are - // operators per the legacy classifier (LPAREN / COMMA arms). - if let Some(params) = node.parameters() { - self.record_halstead_op("("); - // One `,` per separator: requireds.len()-1 + each subsequent - // boundary. Approximate by counting total params and - // emitting (count-1) commas if >1. - let total = count_parameters(¶ms); - if total > 1 { - for _ in 1..total { - self.record_halstead_op(","); - } - } - } - - self.open_space(SpaceKind::Function, start, end, name); - // NOM/NArgs evidence at the space-open site: `open_space` (via - // `State::for_opened_space`) records the `nom` function. - self.record_evidence(&loc, |e, s| e.function(s, "def_node")); - // `def` is LLOC per the legacy Ruby `Loc` rule (`Method` arm). - // Also pin the `end` keyword line as ploc so PLOC matches the - // legacy tree-sitter walker (which saw the `end` keyword as a - // separate visitable token). - self.record_lloc(start, true); - self.observe_optional_keyword_line(node.end_keyword_loc()); - - // Parameters → nargs. - let argc = node.parameters().map(|p| count_parameters(&p)).unwrap_or(0); - self.current().nargs.record_function_args(argc); - self.record_evidence(&loc, |e, s| e.function_args(s, argc, "def_node")); - - // Cognitive: function entry resets nesting/lambda. If this - // method is nested inside another method, depth bumps by 1. - let mut ctx = self.cognitive; - let nested_in_function = self - .kinds - .iter() - .rev() - .skip(1) - .any(|k| matches!(k, SpaceKind::Function)); - ctx.nesting = 0; - ctx.lambda = 0; - if nested_in_function { - ctx.depth = ctx.depth.saturating_add(1); - } - let saved = self.cognitive; - self.cognitive = ctx; - - // Walk body / parameter defaults via the default helper. - visit_def_node(self, node); - - self.cognitive = saved; - self.close_space(); - } - - fn visit_class_node(&mut self, node: &ClassNode<'pr>) { - let loc = node.location(); - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - let name = std::str::from_utf8(node.name().as_slice()) - .ok() - .map(|s| s.to_string()); - - self.record_halstead_op("class"); - self.open_space(SpaceKind::Class, start, end, name); - self.record_lloc(start, true); - self.observe_keyword_line(&node.end_keyword_loc()); - visit_class_node(self, node); - self.close_space(); - } - - fn visit_module_node(&mut self, node: &ModuleNode<'pr>) { - let loc = node.location(); - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - let name = std::str::from_utf8(node.name().as_slice()) - .ok() - .map(|s| s.to_string()); - - // Modules act like classes for NPA / NPM aggregation in Ruby — - // a module body can declare methods and ivars, both class-like - // bookkeeping. The legacy walker aliased Module under Class for - // the `scope_for` rule. - self.record_halstead_op("module"); - self.open_space(SpaceKind::Class, start, end, name); - self.record_lloc(start, true); - self.observe_keyword_line(&node.end_keyword_loc()); - visit_module_node(self, node); - self.close_space(); - } - - fn visit_singleton_class_node(&mut self, node: &SingletonClassNode<'pr>) { - // `class << self` — singleton class scope. Treat as a class-like - // space so methods inside count toward NPM (legacy walker did - // not have a distinct kind, but tree-sitter exposed it as a - // `singleton_class`; the rules class node treated it as a - // class). - let loc = node.location(); - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - self.open_space(SpaceKind::Class, start, end, None); - visit_singleton_class_node(self, node); - self.close_space(); - } - - fn visit_block_node(&mut self, node: &BlockNode<'pr>) { - // A `BlockNode` whose immediate parent is a `LambdaNode` is the - // lambda's body, not a separate closure. In prism the lambda is - // expressed as `LambdaNode` with a `BlockNode`-shaped body, so - // the `Visit::visit_lambda_node` opens the closure space and - // sets `inside_lambda_body=true` before the block visit fires. - if self.inside_lambda_body { - // Skip the closure scaffolding; the lambda already opened - // it. Just walk children. - visit_block_node(self, node); - return; - } - let loc = node.location(); - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - self.open_space(SpaceKind::Closure, start, end, None); - // NOM/NArgs evidence at the space-open site (`open_space` - // records the `nom` closure via `State::for_opened_space`). - self.record_evidence(&loc, |e, s| e.closure(s, "block_node")); - let argc = node - .parameters() - .as_ref() - .map(count_block_parameters) - .unwrap_or(0); - self.current().nargs.record_closure_args(argc); - self.record_evidence(&loc, |e, s| e.closure_args(s, argc, "block_node")); - - let mut ctx = self.cognitive; - ctx.lambda = ctx.lambda.saturating_add(1); - let saved = self.cognitive; - self.cognitive = ctx; - - visit_block_node(self, node); - - self.cognitive = saved; - self.close_space(); - } - - fn visit_lambda_node(&mut self, node: &LambdaNode<'pr>) { - let loc = node.location(); - let start = u32::try_from(loc.start_offset()).unwrap_or(0); - let end = u32::try_from(loc.end_offset()).unwrap_or(0); - self.open_space(SpaceKind::Closure, start, end, None); - // NOM/NArgs evidence at the space-open site (`open_space` - // records the `nom` closure via `State::for_opened_space`). - self.record_evidence(&loc, |e, s| e.closure(s, "lambda_node")); - let argc = node - .parameters() - .as_ref() - .map(count_block_parameters) - .unwrap_or(0); - self.current().nargs.record_closure_args(argc); - self.record_evidence(&loc, |e, s| e.closure_args(s, argc, "lambda_node")); - - let mut ctx = self.cognitive; - ctx.lambda = ctx.lambda.saturating_add(1); - let saved = self.cognitive; - self.cognitive = ctx; - - let saved_inside = self.inside_lambda_body; - self.inside_lambda_body = true; - visit_lambda_node(self, node); - self.inside_lambda_body = saved_inside; - - self.cognitive = saved; - self.close_space(); - } - - // ─── Conditionals (cyclomatic +1, cognitive nesting / +1) ────────────── - - fn visit_if_node(&mut self, node: &IfNode<'pr>) { - // `IfNode` covers three forms: block `if … end`, modifier `x if y`, - // and ternary `a ? b : c`. Distinguish via location options. - let is_modifier = node.if_keyword_loc().is_some() && node.end_keyword_loc().is_none(); - let is_ternary = node.if_keyword_loc().is_none(); - - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - - // Cyclomatic: +1 for any of the three forms (each is a decision - // point per Sonar / McCabe). - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "if_node"); - e.abc_condition(s, "if_node"); - }); - self.record_halstead_op(if is_ternary { "?:" } else { "if" }); - - if is_modifier || is_ternary { - // Modifier `x if y` and ternary `a ? b : c` add +1 cognitive - // without nesting (per Sonar spec: trailing modifier sits on - // a statement edge; ternary is a single-decision form). - self.cognitive_increment_by_one(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, 1, "if_node")); - } else { - // Block form: nesting structure. - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, delta, "if_node")); - self.observe_optional_keyword_line(node.end_keyword_loc()); - self.cognitive.nesting += 1; - visit_if_node(self, node); - self.cognitive.nesting -= 1; - return; - } - - // For modifier and ternary: walk children inline (no nesting - // bump). The default helper handles predicate + statements + - // subsequent. - visit_if_node(self, node); - } - - fn visit_unless_node(&mut self, node: &UnlessNode<'pr>) { - // `UnlessNode` covers block `unless … end` and modifier - // `x unless y`. No ternary form. - let is_modifier = node.end_keyword_loc().is_none(); - - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "unless_node"); - e.abc_condition(s, "unless_node"); - }); - self.record_halstead_op("unless"); - - if is_modifier { - self.cognitive_increment_by_one(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, 1, "unless_node")); - visit_unless_node(self, node); - } else { - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| { - e.cognitive(s, delta, "unless_node") - }); - self.observe_optional_keyword_line(node.end_keyword_loc()); - self.cognitive.nesting += 1; - visit_unless_node(self, node); - self.cognitive.nesting -= 1; - } - } - - fn visit_while_node(&mut self, node: &WhileNode<'pr>) { - let is_modifier = node.closing_loc().is_none(); - - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "while_node"); - e.abc_condition(s, "while_node"); - }); - self.record_halstead_op("while"); - - if is_modifier { - self.cognitive_increment_by_one(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, 1, "while_node")); - visit_while_node(self, node); - } else { - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, delta, "while_node")); - self.observe_optional_keyword_line(node.closing_loc()); - self.cognitive.nesting += 1; - visit_while_node(self, node); - self.cognitive.nesting -= 1; - } - } - - fn visit_until_node(&mut self, node: &UntilNode<'pr>) { - let is_modifier = node.closing_loc().is_none(); - - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "until_node"); - e.abc_condition(s, "until_node"); - }); - self.record_halstead_op("until"); - - if is_modifier { - self.cognitive_increment_by_one(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, 1, "until_node")); - visit_until_node(self, node); - } else { - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, delta, "until_node")); - self.observe_optional_keyword_line(node.closing_loc()); - self.cognitive.nesting += 1; - visit_until_node(self, node); - self.cognitive.nesting -= 1; - } - } - - fn visit_for_node(&mut self, node: &ForNode<'pr>) { - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "for_node"); - e.abc_condition(s, "for_node"); - }); - self.record_halstead_op("for"); - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, delta, "for_node")); - // ForNode also has end_keyword_loc. - self.cognitive.nesting += 1; - visit_for_node(self, node); - self.cognitive.nesting -= 1; - } - - fn visit_case_node(&mut self, node: &CaseNode<'pr>) { - // Classic `case x; when 1 then …; else …; end`. The `case` - // itself is a structural branch (cognitive +1+nesting); each - // `when` clause is a separate decision (+1 cyclomatic per - // when, no nesting). - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - self.record_halstead_op("case"); - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, delta, "case_node")); - self.observe_keyword_line(&node.end_keyword_loc()); - self.cognitive.nesting += 1; - visit_case_node(self, node); - self.cognitive.nesting -= 1; - } - - fn visit_when_node(&mut self, node: &WhenNode<'pr>) { - // Each `when` clause adds a cyclomatic decision and an ABC - // condition; cognitive is unchanged (cost paid by `case`). - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "when_node"); - e.abc_condition(s, "when_node"); - }); - self.record_halstead_op("when"); - visit_when_node(self, node); - } - - fn visit_case_match_node(&mut self, node: &CaseMatchNode<'pr>) { - // Pattern-matching `case x; in pat then …; end`. Same shape as - // CaseNode for our purposes — case bumps nesting once, each - // `in` is a decision. - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - self.record_halstead_op("case"); - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| { - e.cognitive(s, delta, "case_match_node"); - }); - self.observe_keyword_line(&node.end_keyword_loc()); - self.cognitive.nesting += 1; - visit_case_match_node(self, node); - self.cognitive.nesting -= 1; - } - - fn visit_in_node(&mut self, node: &InNode<'pr>) { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "in_node"); - e.abc_condition(s, "in_node"); - }); - self.record_halstead_op("in"); - visit_in_node(self, node); - } - - fn visit_match_predicate_node(&mut self, node: &MatchPredicateNode<'pr>) { - // `expr in pat` (one-line pattern test) — single decision. - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "match_predicate_node"); - e.abc_condition(s, "match_predicate_node"); - }); - visit_match_predicate_node(self, node); - } - - fn visit_else_node(&mut self, node: &ElseNode<'pr>) { - // `else` (in `if`/`case`/`begin`): no cyclomatic increment - // (the `if`/`case` already picked a branch), +1 cognitive - // without nesting (per Sonar). - self.cognitive_increment_by_one(); - self.record_evidence(&node.location(), |e, s| e.cognitive(s, 1, "else_node")); - self.record_halstead_op("else"); - visit_else_node(self, node); - } - - fn visit_begin_node(&mut self, node: &BeginNode<'pr>) { - // `begin ... end` block — not a decision in itself; only its - // `rescue` / `else` / `ensure` children matter. - self.record_lloc( - u32::try_from(node.location().start_offset()).unwrap_or(0), - true, - ); - self.record_halstead_op("begin"); - self.observe_optional_keyword_line(node.end_keyword_loc()); - visit_begin_node(self, node); - } - - fn visit_rescue_node(&mut self, node: &RescueNode<'pr>) { - // `begin … rescue X => e; … end` — block-form rescue clause. - // Cyclomatic +1 (each rescue is a separate execution path); - // cognitive nesting bump (matches legacy `Rescue: nesting += 1` - // rule). - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "rescue_node"); - e.abc_condition(s, "rescue_node"); - }); - self.record_halstead_op("rescue"); - let delta = self.cognitive_increase_nesting(); - self.record_evidence(&node.location(), |e, s| { - e.cognitive(s, delta, "rescue_node") - }); - self.cognitive.nesting += 1; - visit_rescue_node(self, node); - self.cognitive.nesting -= 1; - } - - fn visit_rescue_modifier_node(&mut self, node: &RescueModifierNode<'pr>) { - // `expr rescue fallback` — postfix modifier form, distinct node - // kind. Cyclomatic +1, cognitive +1 without nesting (modifier - // sits on the trailing edge of the assignment). - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_halstead_op("rescue"); - self.cognitive_increment_by_one(); - self.record_evidence(&node.location(), |e, s| { - e.decision(s, "rescue_modifier_node"); - e.abc_condition(s, "rescue_modifier_node"); - e.cognitive(s, 1, "rescue_modifier_node"); - }); - visit_rescue_modifier_node(self, node); - } - - // ─── Logical short-circuit ───────────────────────────────────────────── - - fn visit_and_node(&mut self, node: &AndNode<'pr>) { - // `a && b` / `a and b`. Each `&&` / `and` between two operands - // is +1 cyclomatic and +1 ABC condition. Boolean-sequence - // collapsing groups consecutive same-operator runs. - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_halstead_op("&&"); - // Use the operator slice to label the boolean — `&&` and `and` - // both collapse but legacy distinguishes them by token text. - let op_text = std::str::from_utf8(node.operator_loc().as_slice()).unwrap_or("&&"); - let label = if op_text == "and" { "and" } else { "&&" }; - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean(label); - let delta = self.current().cognitive.structural.saturating_sub(before); - // Evidence spans point at the operator token; a same-operator - // repeat applies no delta and records nothing. - self.record_evidence(&node.operator_loc(), |e, s| { - e.decision(s, label); - e.abc_condition(s, label); - e.cognitive(s, delta, label); - }); - self.bool_depth = self.bool_depth.saturating_add(1); - visit_and_node(self, node); - self.bool_depth = self.bool_depth.saturating_sub(1); - } - - fn visit_or_node(&mut self, node: &OrNode<'pr>) { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_halstead_op("||"); - let op_text = std::str::from_utf8(node.operator_loc().as_slice()).unwrap_or("||"); - let label = if op_text == "or" { "or" } else { "||" }; - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean(label); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(&node.operator_loc(), |e, s| { - e.decision(s, label); - e.abc_condition(s, label); - e.cognitive(s, delta, label); - }); - self.bool_depth = self.bool_depth.saturating_add(1); - visit_or_node(self, node); - self.bool_depth = self.bool_depth.saturating_sub(1); - } - - // ─── Calls, assignments, exits ───────────────────────────────────────── - - fn visit_call_node(&mut self, node: &CallNode<'pr>) { - // LLOC: every call is a logical line per the legacy Ruby Loc - // rule (`Call | Call2 | Call3 | Call4` arms). - self.current().loc.observe_lloc(); - - // Prism parses `a + b` as `CallNode { name: :+ }` — i.e. an - // operator-method call. The legacy tree-sitter walker only - // counted `call`/`command` (real `obj.method(args)` / - // `puts foo` syntax) as ABC.B; arithmetic / comparison - // operators were classified by the `Binary` node, not Call. - // To preserve metric definitions: ABC.B counts dispatch ("we - // hand control to a named method"), and `a + b` is dispatch in - // theory but reads as a structural operator in practice. - // Match the legacy classification: skip ABC.B for operator- - // method calls; record them as Halstead operators only. - let name_bytes = node.name().as_slice(); - let name_str = std::str::from_utf8(name_bytes).ok(); - let is_operator_call = name_str.is_some_and(is_ruby_operator_method); - - if !is_operator_call { - self.current().abc.record_branch(); - self.record_evidence(&node.location(), |e, s| e.abc_branch(s, "call_node")); - } - - // Legacy walker counted `binary` (e.g. `a > 0`, `a == b`) as - // ABC.C. In prism that maps to a CallNode with a comparison - // operator name. Other binary operators (`+`, `-`, `*`, …) are - // arithmetic, not conditions. - if let Some(name) = name_str - && is_ruby_comparison_method(name) - { - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| e.abc_condition(s, name)); - } - - if let Some(name) = name_str { - if is_operator_call { - self.record_halstead_op_text("call_op", name); - } else { - self.record_halstead_operand_text("Identifier", name); - } - } - - // Statement-shaped call → reset boolean sequence (a call at the - // statement level is a fresh boolean context — matches legacy - // `Statement: stats.boolean_seq.reset()`). - // Heuristic: a call is at "statement level" if neither parent - // is a logical operator. We approximate via bool_depth==0. - if self.bool_depth == 0 { - self.current().cognitive.boolean_seq.reset(); - } - - visit_call_node(self, node); - } - - fn visit_yield_node(&mut self, node: &YieldNode<'pr>) { - // `yield` — Ruby's coroutine yield. NOT counted as an exit per - // legacy walker (matches Sonar: yield is a hand-off, not an - // early return). It does count as a Halstead operator. - self.record_halstead_op("yield"); - visit_yield_node(self, node); - } - - fn visit_return_node(&mut self, node: &ReturnNode<'pr>) { - self.current().nexit.record_exit(); - self.record_evidence(&node.location(), |e, s| e.exit(s, "return_node")); - self.record_halstead_op("return"); - visit_return_node(self, node); - } - - fn visit_break_node(&mut self, node: &BreakNode<'pr>) { - self.current().nexit.record_exit(); - self.record_evidence(&node.location(), |e, s| e.exit(s, "break_node")); - self.record_halstead_op("break"); - visit_break_node(self, node); - } - - fn visit_next_node(&mut self, node: &NextNode<'pr>) { - self.current().nexit.record_exit(); - self.record_evidence(&node.location(), |e, s| e.exit(s, "next_node")); - self.record_halstead_op("next"); - visit_next_node(self, node); - } - - fn visit_redo_node(&mut self, node: &RedoNode<'pr>) { - self.current().nexit.record_exit(); - self.record_evidence(&node.location(), |e, s| e.exit(s, "redo_node")); - self.record_halstead_op("redo"); - visit_redo_node(self, node); - } - - // ─── Variable writes (every form is a distinct prism node) ──────────── - - fn visit_local_variable_write_node(&mut self, node: &LocalVariableWriteNode<'pr>) { - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "local_variable_write_node"); - }); - self.record_halstead_op("="); - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Identifier", name); - } - visit_local_variable_write_node(self, node); - } - - fn visit_local_variable_operator_write_node( - &mut self, - node: &LocalVariableOperatorWriteNode<'pr>, - ) { - // `x += 1`, `x *= 2`, etc. — augmented assignment. - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "local_variable_operator_write_node"); - }); - self.record_halstead_op_text( - "op_assign", - std::str::from_utf8(node.binary_operator_loc().as_slice()).unwrap_or(""), - ); - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Identifier", name); - } - visit_local_variable_operator_write_node(self, node); - } - - fn visit_local_variable_and_write_node(&mut self, node: &LocalVariableAndWriteNode<'pr>) { - // `x &&= y` — short-circuiting conditional assignment. Counts - // as both an assignment AND a condition (the `&&` decides). - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "local_variable_and_write_node"); - e.decision(s, "local_variable_and_write_node"); - e.abc_condition(s, "local_variable_and_write_node"); - }); - self.record_halstead_op("&&="); - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Identifier", name); - } - visit_local_variable_and_write_node(self, node); - } - - fn visit_local_variable_or_write_node(&mut self, node: &LocalVariableOrWriteNode<'pr>) { - // `x ||= y` — defaulting assignment. Same accounting as `&&=`. - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "local_variable_or_write_node"); - e.decision(s, "local_variable_or_write_node"); - e.abc_condition(s, "local_variable_or_write_node"); - }); - self.record_halstead_op("||="); - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Identifier", name); - } - visit_local_variable_or_write_node(self, node); - } - - fn visit_instance_variable_write_node(&mut self, node: &InstanceVariableWriteNode<'pr>) { - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "instance_variable_write_node"); - }); - self.record_halstead_op("="); - - // Class-body @ivar assignment → NPA on the enclosing class. - // Ruby ivars are non-public (`@x` is private until exposed via - // `attr_reader`), so the public-members-only NPA evidence - // intentionally records nothing here. - let parent_kind = self.kinds.last().cloned().unwrap_or(SpaceKind::Unit); - if matches!(parent_kind, SpaceKind::Class | SpaceKind::Impl) { - self.current() - .npa - .record_attribute(ContainerKind::Class, false); - } - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("InstanceVariable", name); - } - visit_instance_variable_write_node(self, node); - } - - fn visit_constant_write_node(&mut self, node: &ConstantWriteNode<'pr>) { - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "constant_write_node"); - }); - self.record_halstead_op("="); - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Constant", name); - } - visit_constant_write_node(self, node); - } - - fn visit_call_operator_write_node(&mut self, node: &CallOperatorWriteNode<'pr>) { - // `obj.attr += 1` — receiver method op-assign. - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "call_operator_write_node"); - }); - self.record_halstead_op_text( - "op_assign", - std::str::from_utf8(node.binary_operator_loc().as_slice()).unwrap_or(""), - ); - visit_call_operator_write_node(self, node); - } - - fn visit_index_operator_write_node(&mut self, node: &IndexOperatorWriteNode<'pr>) { - // `a[k] += 1` — index op-assign. - self.current().loc.observe_lloc(); - self.current().abc.record_assignment(); - self.record_evidence(&node.location(), |e, s| { - e.abc_assignment(s, "index_operator_write_node"); - }); - self.record_halstead_op_text( - "op_assign", - std::str::from_utf8(node.binary_operator_loc().as_slice()).unwrap_or(""), - ); - visit_index_operator_write_node(self, node); - } - - // ─── Halstead operands: variable reads, parameters, literals ─────────── - - fn visit_local_variable_read_node(&mut self, node: &LocalVariableReadNode<'pr>) { - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Identifier", name); - } - } - - fn visit_instance_variable_read_node(&mut self, node: &InstanceVariableReadNode<'pr>) { - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("InstanceVariable", name); - } - } - - fn visit_class_variable_read_node(&mut self, node: &ClassVariableReadNode<'pr>) { - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("ClassVariable", name); - } - } - - fn visit_global_variable_read_node(&mut self, node: &GlobalVariableReadNode<'pr>) { - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("GlobalVariable", name); - } - } - - fn visit_constant_read_node(&mut self, node: &ConstantReadNode<'pr>) { - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Constant", name); - } - } - - fn visit_required_parameter_node(&mut self, node: &RequiredParameterNode<'pr>) { - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Identifier", name); - } - } - - fn visit_optional_parameter_node(&mut self, node: &OptionalParameterNode<'pr>) { - if let Ok(name) = std::str::from_utf8(node.name().as_slice()) { - self.record_halstead_operand_text("Identifier", name); - } - visit_optional_parameter_node(self, node); - } - - fn visit_integer_node(&mut self, _node: &IntegerNode<'pr>) { - self.record_halstead_operand_text("Integer", ""); - } - - fn visit_float_node(&mut self, _node: &FloatNode<'pr>) { - self.record_halstead_operand_text("Float", ""); - } - - fn visit_string_node(&mut self, _node: &StringNode<'pr>) { - self.record_halstead_operand_text("String", ""); - } - - fn visit_symbol_node(&mut self, _node: &SymbolNode<'pr>) { - self.record_halstead_operand_text("Symbol", ""); - } - - fn visit_true_node(&mut self, _node: &TrueNode<'pr>) { - self.record_halstead_operand_text("True", "true"); - } - - fn visit_false_node(&mut self, _node: &FalseNode<'pr>) { - self.record_halstead_operand_text("False", "false"); - } - - fn visit_nil_node(&mut self, _node: &NilNode<'pr>) { - self.record_halstead_operand_text("Nil", "nil"); - } - - fn visit_self_node(&mut self, _node: &SelfNode<'pr>) { - self.record_halstead_operand_text("Self", "self"); - } - - // ─── Generic enter hooks for PLOC accounting ─────────────────────────── - // - // The legacy Ruby `Loc::compute` ran a `_ => ploc.lines.insert(start)` - // arm for every non-container, non-comment node — meaning PLOC is - // the SET of rows that any code node starts on. We mirror that by - // observing `code_line` on every branch / leaf node visit. The set - // dedupes by row so it's idempotent. - - fn visit_branch_node_enter(&mut self, node: Node<'pr>) { - let start = u32::try_from(node.location().start_offset()).unwrap_or(0); - let row = self.line_index.line_at(start).saturating_sub(1); - self.current().loc.observe_code_line(row); - } - - fn visit_leaf_node_enter(&mut self, node: Node<'pr>) { - let start = u32::try_from(node.location().start_offset()).unwrap_or(0); - let row = self.line_index.line_at(start).saturating_sub(1); - self.current().loc.observe_code_line(row); - } -} - -// ─── Helpers ─────────────────────────────────────────────────────────────── - -fn count_parameters(p: &ruby_prism::ParametersNode<'_>) -> u32 { - let mut total: u32 = 0; - total += u32::try_from(p.requireds().len()).unwrap_or(0); - total += u32::try_from(p.optionals().len()).unwrap_or(0); - if p.rest().is_some() { - total += 1; - } - total += u32::try_from(p.posts().len()).unwrap_or(0); - total += u32::try_from(p.keywords().len()).unwrap_or(0); - if p.keyword_rest().is_some() { - total += 1; - } - if p.block().is_some() { - total += 1; - } - total -} - -fn count_block_parameters(node: &Node<'_>) -> u32 { - // BlockNode::parameters() / LambdaNode::parameters() return a - // generic Node that may be `BlockParametersNode` (which wraps - // `ParametersNode`), `NumberedParametersNode`, or `ItParametersNode`. - if let Some(bp) = node.as_block_parameters_node() { - return bp.parameters().as_ref().map(count_parameters).unwrap_or(0); - } - if let Some(np) = node.as_numbered_parameters_node() { - return u32::from(np.maximum()); - } - if node.as_it_parameters_node().is_some() { - return 1; - } - 0 -} - -fn ruby_method_is_public(name: &str) -> bool { - // Ruby has no syntactic public/protected/private modifier on `def` - // itself; visibility is set by `private` / `protected` calls in the - // class body. Without semantic flow analysis we treat every `def` - // as public, matching the legacy walker's default. - !name.starts_with('_') || name.starts_with("__") && name.ends_with("__") -} - -fn is_ruby_comparison_method(name: &str) -> bool { - // Comparison operator method names — Ruby parses `a < b` as a call - // to `:<` on `a`, etc. These are ABC.C conditions per legacy. - matches!(name, "==" | "!=" | "<" | ">" | "<=" | ">=" | "<=>" | "===") -} - -fn is_ruby_operator_method(name: &str) -> bool { - // Names a CallNode can carry when the call was parsed from - // Ruby operator syntax (`a + b` parses as CallNode { name: :+ }). - matches!( - name, - "+" | "-" - | "*" - | "/" - | "%" - | "**" - | "==" - | "!=" - | "<" - | ">" - | "<=" - | ">=" - | "<=>" - | "===" - | "<<" - | ">>" - | "&" - | "|" - | "^" - | "~" - | "!" - | "+@" - | "-@" - | "[]" - | "[]=" - ) -} diff --git a/crates/mehen-ruby/tests/abc.rs b/crates/mehen-ruby/tests/abc.rs deleted file mode 100644 index c2753010..00000000 --- a/crates/mehen-ruby/tests/abc.rs +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_abc_basic() { - let a = analyze( - "def f(a, b) - c = a + b # +1 A - log(c) # +1 B - return c if c > 0 # +1 C (if_modifier) + +1 C (>) - end", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 1.0, - "branches": 1.0, - "conditions": 2.0, - "magnitude": 2.449489742783178, - "assignments_average": 0.5, - "branches_average": 0.5, - "conditions_average": 1.0, - "assignments_min": 0.0, - "assignments_max": 1.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 2.0 - }"### - ); -} diff --git a/crates/mehen-ruby/tests/cognitive.rs b/crates/mehen-ruby/tests/cognitive.rs deleted file mode 100644 index 6e4b1f2e..00000000 --- a/crates/mehen-ruby/tests/cognitive.rs +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity tests for the Phase 9 ruby-prism walker — -//! ported from `crates/mehen-engine/src/legacy/metrics/cognitive.rs`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_no_cognitive() { - // Drift from legacy: legacy serialized `null` when no functions - // were observed (so the average's denominator was zero). The 1.0 - // mehen-metrics `CognitiveStats` defaults the empty average to - // 0.0 — same convention applied in Phase 6 Python (see - // `crates/mehen-python/tests/cognitive.rs::python_no_cognitive`). - let a = analyze("a = 42"); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} - -#[test] -fn ruby_simple_method() { - let a = analyze( - "def f(a, b) - if a && b # +2 (+1 if, +1 &&) - return 1 - end - if c && d # +2 (+1 if, +1 &&) - return 1 - end - end", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn ruby_nested_if_and_else() { - let a = analyze( - "def f(a, b) - if a # +1 - if b # +2 (nesting = 1) - return 1 - else # +1 - return 2 - end - end - end", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn ruby_modifier_and_rescue() { - let a = analyze( - "def f(a) - return a if a > 0 # +1 if_modifier - begin - risky! - rescue StandardError # +1 (nesting +1 because in begin) - retry - end - end", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn ruby_rescue_modifier() { - let a = analyze( - "def f - value = risky rescue fallback # +1 rescue_modifier - end", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 1.0, - "average": 1.0, - "min": 0.0, - "max": 1.0 - }"### - ); -} - -#[test] -fn ruby_lambda_with_block() { - let a = analyze( - "def f - x = -> { if a then 1 end } - end", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn ruby_nested_method_in_singleton_method() { - let a = analyze( - "def self.outer - def inner - if x then 1 end - end - end", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} diff --git a/crates/mehen-ruby/tests/contributions.rs b/crates/mehen-ruby/tests/contributions.rs deleted file mode 100644 index 0aa847fa..00000000 --- a/crates/mehen-ruby/tests/contributions.rs +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the Ruby analyzer (plan §5.4). - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - RubyAnalyzer::new() - .analyze( - &SourceFile::new("s.rb".into(), Language::Ruby, source.to_string()), - config, - ) - .expect("Ruby analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -class Classifier - def classify(a, b) - if a > 0 && b > 0 - return 1 - else - a += b - end - total = 0 - [1, 2].each { |x| total += x } - handler = ->(y) { y * 2 } - return handler.call(total) rescue 0 - end -end -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ("npm", "npm"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn reasons_are_ruby_namespaced_with_prism_node_names() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "ruby.cyclomatic.if_node", - "ruby.cyclomatic.&&", - "ruby.cognitive.if_node", - "ruby.cognitive.else_node", - "ruby.cyclomatic.rescue_modifier_node", - "ruby.nexit.return_node", - "ruby.abc.assignment.local_variable_write_node", - "ruby.abc.assignment.local_variable_operator_write_node", - "ruby.abc.branch.call_node", - "ruby.abc.condition.if_node", - "ruby.abc.condition.>", - "ruby.nom.function.def_node", - "ruby.nom.closure.block_node", - "ruby.nom.closure.lambda_node", - "ruby.nargs.function.def_node", - "ruby.nargs.closure.block_node", - "ruby.nargs.closure.lambda_node", - "ruby.npm.def_node", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("ruby."))); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn boolean_run_transitions_record_only_moved_deltas() { - // `a && b && c` collapses into one boolean run: first `&&` +1, - // repeat 0 (recorded as nothing). - let source = "\ -def f(a, b, c) - if a && b && c - return 1 - end - 0 -end -"; - let analysis = analyze(source, &AnalysisConfig::production()); - let boolean: Vec = analysis - .contributions - .iter() - .filter(|item| item.reason.as_str() == "ruby.cognitive.&&") - .map(|item| item.amount) - .collect(); - assert_eq!(boolean, vec![1.0]); - assert_eq!(metric(&analysis, "cognitive.sum"), 2.0); // if + first && - assert_eq!(evidence_sum(&analysis, "cognitive.sum"), 2.0); -} - -#[test] -fn modifier_forms_record_flat_cognitive_increments() { - // `x if y` — modifier form pays +1 without nesting. - let source = "def f(x)\n return 1 if x\n 0\nend\n"; - let analysis = analyze(source, &AnalysisConfig::production()); - let if_cognitive: Vec = analysis - .contributions - .iter() - .filter(|item| { - item.metric.as_str() == "cognitive.sum" - && item.reason.as_str() == "ruby.cognitive.if_node" - }) - .map(|item| item.amount) - .collect(); - assert_eq!(if_cognitive, vec![1.0]); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in ["cyclomatic.sum", "cognitive.sum", "nexit.sum", "abc", "npm"] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-ruby/tests/cyclomatic.rs b/crates/mehen-ruby/tests/cyclomatic.rs deleted file mode 100644 index 184fef5a..00000000 --- a/crates/mehen-ruby/tests/cyclomatic.rs +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity tests for the Phase 9 ruby-prism walker. -//! -//! Every legacy `check_metrics::` cyclomatic test from -//! `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs` is ported -//! here byte-identical so the parity contract (plan §12.3.1) is -//! visibly maintained. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_simple_method() { - let a = analyze( - "def f(a, b) # +2 (+1 unit space) - if a && b # +2 (+1 if, +1 &&) - return 1 - end - if c or d # +2 (+1 if, +1 or) - return 1 - end - end", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - }"### - ); -} - -#[test] -fn ruby_modifier_forms() { - // Each trailing-modifier form contributes +1 like its block form. - let a = analyze( - "def f(a) # +1 unit space +1 method - return a if a > 0 # +1 if_modifier - return -a unless a == 0 # +1 unless_modifier - end", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn ruby_case_when() { - let a = analyze( - "def f(x) # +1 unit +1 method - case x # case itself doesn't add; each `when` does - when 1 then 'a' # +1 - when 2 then 'b' # +1 - when 3 then 'c' # +1 - else 'z' - end - end", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - }"### - ); -} diff --git a/crates/mehen-ruby/tests/exit.rs b/crates/mehen-ruby/tests/exit.rs deleted file mode 100644 index b8c004ae..00000000 --- a/crates/mehen-ruby/tests/exit.rs +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NExit tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_no_exit() { - // Drift from legacy: legacy serialized `null` when no functions - // were observed (zero denominator). The 1.0 mehen-metrics - // `NexitStats` defaults the empty average to 0.0 — same convention - // applied in Phase 6 (see Python tests). - let a = analyze("a = 42"); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} - -#[test] -fn ruby_simple_method() { - let a = analyze( - "def f(a, b) - return a if a > b - return b - end", - ); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn ruby_break_and_next() { - // Both `break` and `next` are counted as exits; `yield` is not. - let a = analyze( - "def f(xs) - xs.each do |x| - next if x.nil? - break if x.stop? - yield x - end - end", - ); - let nexits = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nexits, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} diff --git a/crates/mehen-ruby/tests/halstead.rs b/crates/mehen-ruby/tests/halstead.rs deleted file mode 100644 index d1c89ecf..00000000 --- a/crates/mehen-ruby/tests/halstead.rs +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Halstead tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_operators_and_operands() { - let a = analyze( - "def add(a, b) - a + b - end", - ); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - insta::assert_json_snapshot!( - h, - { - ".estimated_program_length" => "[masked]", - ".purity_ratio" => "[masked]", - ".volume" => "[masked]", - ".difficulty" => "[masked]", - ".level" => "[masked]", - ".effort" => "[masked]", - ".time" => "[masked]", - ".bugs" => "[masked]" - }, - @r###" - { - "n1": 4.0, - "N1": 4.0, - "n2": 3.0, - "N2": 5.0, - "length": 9.0, - "estimated_program_length": "[masked]", - "purity_ratio": "[masked]", - "vocabulary": 7.0, - "volume": "[masked]", - "difficulty": "[masked]", - "level": "[masked]", - "effort": "[masked]", - "time": "[masked]", - "bugs": "[masked]" - }"### - ); -} - -/// Regression: methods inside a class must carry their own Halstead -/// counts in the per-space JSON. PR #95 discussion_r3265658502 flagged -/// the same bug on the Python walker; Ruby's helper methods recorded -/// every event onto `stack[0]`, leaving inner methods with zero -/// `halstead.N1`/`halstead.N2`. -#[test] -fn ruby_method_halstead_is_non_zero() { - let a = analyze( - "class C - def m(a, b) - a + b - end -end", - ); - assert_eq!(a.root.spaces.len(), 1, "expected one class space"); - let class = &a.root.spaces[0]; - assert_eq!(class.spaces.len(), 1, "expected one method space"); - let method = &class.spaces[0]; - let method_h = mehen_report::metrics_json::halstead(&method.metrics); - assert!( - method_h.big_n1 > 0.0, - "method must record at least `def` / `+` operators, got {}", - serde_json::to_string(&method_h).unwrap() - ); - assert!( - method_h.big_n2 > 0.0, - "method must record `m`, `a`, `b` operands, got {}", - serde_json::to_string(&method_h).unwrap() - ); - let class_h = mehen_report::metrics_json::halstead(&class.metrics); - assert!( - class_h.big_n1 >= method_h.big_n1, - "class N1 must roll up method: class={} method={}", - serde_json::to_string(&class_h).unwrap(), - serde_json::to_string(&method_h).unwrap() - ); -} diff --git a/crates/mehen-ruby/tests/loc.rs b/crates/mehen-ruby/tests/loc.rs deleted file mode 100644 index bdfd759c..00000000 --- a/crates/mehen-ruby/tests/loc.rs +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_simple_loc() { - let a = analyze( - "# header comment - def greet(name) - puts \"hi, #{name}\" - end", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - insta::assert_json_snapshot!( - loc, - @r###" - { - "sloc": 4.0, - "ploc": 3.0, - "lloc": 2.0, - "cloc": 1.0, - "blank": 0.0, - "sloc_average": 2.0, - "ploc_average": 1.5, - "lloc_average": 1.0, - "cloc_average": 0.5, - "blank_average": 0.0, - "sloc_min": 3.0, - "sloc_max": 3.0, - "cloc_min": 0.0, - "cloc_max": 0.0, - "ploc_min": 3.0, - "ploc_max": 3.0, - "lloc_min": 2.0, - "lloc_max": 2.0, - "blank_min": 0.0, - "blank_max": 0.0 - }"### - ); -} - -/// Regression: PR #95 discussion_r3265962147 — per-method `loc.cloc` -/// must capture comments inside the method body. Before the fix, -/// `walk_program`'s comment loop wrote every comment to the unit so -/// per-method `cloc` was always 0. -#[test] -fn ruby_method_cloc_routes_to_active_space() { - let a = analyze( - "class C - # class-level comment - def m(a, b) - # inner comment 1 - # inner comment 2 - a + b - end -end", - ); - assert_eq!(a.root.spaces.len(), 1); - let class = &a.root.spaces[0]; - assert_eq!(class.spaces.len(), 1); - let method = &class.spaces[0]; - let method_loc = mehen_report::metrics_json::loc(&method.metrics); - assert!( - method_loc.cloc >= 2.0, - "method must record its two `#` comments as cloc, got {}", - serde_json::to_string(&method_loc).unwrap() - ); -} diff --git a/crates/mehen-ruby/tests/nargs.rs b/crates/mehen-ruby/tests/nargs.rs deleted file mode 100644 index 24269ea1..00000000 --- a/crates/mehen-ruby/tests/nargs.rs +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NArgs tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_single_method() { - // Drift from legacy: legacy reported `functions_min: 0.0` because - // its `compute_minmax` ran unconditionally for every space, so the - // unit space (which has no fn args) pulled the min down to 0. The - // 1.0 mehen-metrics `NargsStats::finalize_minmax` only includes - // a space in the function bounds if `is_function == true`, so the - // unit no longer dilutes the bounds. Result: `functions_min: 2.0` - // — matching the *only* function in this fixture (`def f(a, b)`). - // This drift is shared with Phase 6 Python (see - // `crates/mehen-python/tests/nargs.rs::python_single_function`). - let a = analyze( - "def f(a, b) - a + b - end", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - nargs, - @r###" - { - "total_functions": 2.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 2.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn ruby_block_and_lambda_args() { - // `do |a, b| ... end` is a block (closure); `-> (x) { ... }` is a lambda. - // - // Drift from legacy: see `ruby_single_method` above. `closures_min` - // is now 1.0 because both closures bring 1+ args; the legacy 0 came - // from including the non-closure unit space in the closure bounds. - let a = analyze( - "xs.each do |a, b| - a + b - end - f = -> (x) { x * 2 }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - insta::assert_json_snapshot!( - nargs, - @r###" - { - "total_functions": 0.0, - "total_closures": 3.0, - "average_functions": 0.0, - "average_closures": 1.5, - "total": 3.0, - "average": 1.5, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 1.0, - "closures_max": 2.0 - }"### - ); -} diff --git a/crates/mehen-ruby/tests/nom.rs b/crates/mehen-ruby/tests/nom.rs deleted file mode 100644 index d9dd49e8..00000000 --- a/crates/mehen-ruby/tests/nom.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NOM tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_nom() { - let a = analyze( - "def a - 1 - end - def b - 2 - end - def c - 3 - end - x = -> (a) { a + 42 }", - ); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - insta::assert_json_snapshot!( - nom, - @r###" - { - "functions": 3.0, - "closures": 1.0, - "functions_average": 0.6, - "closures_average": 0.2, - "total": 4.0, - "average": 0.8, - "functions_min": 0.0, - "functions_max": 1.0, - "closures_min": 0.0, - "closures_max": 1.0 - }"### - ); -} - -#[test] -fn ruby_do_lambda_counts_as_one_closure() { - let a = analyze( - "x = -> (a) do - a + 42 - end", - ); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - insta::assert_json_snapshot!( - nom, - @r###" - { - "functions": 0.0, - "closures": 1.0, - "functions_average": 0.0, - "closures_average": 0.5, - "total": 1.0, - "average": 0.5, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 0.0, - "closures_max": 1.0 - }"### - ); -} diff --git a/crates/mehen-ruby/tests/npa.rs b/crates/mehen-ruby/tests/npa.rs deleted file mode 100644 index dbb1c024..00000000 --- a/crates/mehen-ruby/tests/npa.rs +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPA tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_npa_counts_instance_variables_under_body_statement() { - // 2 ivar attributes, both non-public by convention. - let a = analyze( - "class C - @x = 1 - @y = 2 - end", - ); - let npa = mehen_report::metrics_json::npa(&a.root.metrics); - insta::assert_json_snapshot!( - npa, - @r###" - { - "classes": 0.0, - "interfaces": 0.0, - "class_attributes": 2.0, - "interface_attributes": 0.0, - "classes_average": 0.0, - "interfaces_average": null, - "total": 0.0, - "total_attributes": 2.0, - "average": 0.0 - }"### - ); -} diff --git a/crates/mehen-ruby/tests/npm.rs b/crates/mehen-ruby/tests/npm.rs deleted file mode 100644 index 8d47c9d3..00000000 --- a/crates/mehen-ruby/tests/npm.rs +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPM tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_npm_counts_methods_as_public() { - let a = analyze( - "class C - def a; end - def b; end - end", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - insta::assert_json_snapshot!( - npm, - @r#" - { - "classes": 2.0, - "interfaces": 0.0, - "class_methods": 2.0, - "interface_methods": 0.0, - "classes_average": 1.0, - "interfaces_average": null, - "total": 2.0, - "total_methods": 2.0, - "average": 1.0 - } - "# - ); -} diff --git a/crates/mehen-ruby/tests/parity.rs b/crates/mehen-ruby/tests/parity.rs deleted file mode 100644 index c2b15c7b..00000000 --- a/crates/mehen-ruby/tests/parity.rs +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Ruby-specific tests for the Phase 9 ruby-prism walker — exercises -//! Ruby idioms the legacy tree-sitter walker handled incompletely or -//! had no fixture for. Per the rewrite plan §6.5 the prism migration -//! is justified by "first-class" handling of these forms. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_safe_navigation_does_not_crash() { - // `&.` safe-navigation method call. Prism flags via - // `CallNode::is_safe_navigation()`; the walker treats it as a - // regular ABC.B branch (just like a normal `.` call). The legacy - // tree-sitter grammar exposed it as a separate `&.` punctuation - // child of `call`, but the metric outcome is the same: one branch. - let a = analyze( - "def f(obj) - obj&.bar&.baz - end", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - // Two safe-nav method calls (`bar`, `baz`). - assert_eq!(abc.branches, 2.0); -} - -#[test] -fn ruby_pattern_matching_each_in_branch_is_a_decision() { - // Pattern matching `case … in pat` — each `in` clause is a - // cyclomatic decision, just like classic `when`. Legacy walker - // handled this via the `InClause` node kind; prism exposes it as - // `CaseMatchNode` containing `InNode`s. - let a = analyze( - "def f(x) - case x - in [1, *] - :a - in {a:, **} - :b - in Integer => n if n > 0 - :c - end - end", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - // unit (+1), method (+1), 3× `in` (+3), guard `if` (+1), `>` (+0 - // because comparison is a CallNode, not a binary expression that - // adds cyclomatic — only logical ops do). - // Total = 6. - assert_eq!(cy.sum, 6.0, "{}", serde_json::to_string(&cy).unwrap()); -} - -#[test] -fn ruby_endless_method_definition() { - // Ruby 3.0+ endless method: `def square(x) = x * x`. Prism's - // DefNode has `end_keyword_loc().is_none()` for endless methods. - // We still count it as one method (NOM=1) and one space. - let a = analyze("def square(x) = x * x"); - let nom = mehen_report::metrics_json::nom(&a.root.metrics); - assert_eq!( - nom.functions, - 1.0, - "{}", - serde_json::to_string(&nom).unwrap() - ); -} - -#[test] -fn ruby_numbered_block_parameters_count_correctly() { - // Ruby 2.7+ numbered block params (`_1`, `_2`, etc.) — prism - // exposes these as `NumberedParametersNode` with a `maximum: u8` - // field. Legacy tree-sitter had a hand-rolled `block_argument` - // walk that didn't always recover the implicit arity. - let a = analyze( - "[1, 2, 3].each_with_index do - puts _1 + _2 - end", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - // Block has implicit `_1, _2` → 2 closure args. - assert_eq!( - nargs.total_closures, - 2.0, - "{}", - serde_json::to_string(&nargs).unwrap() - ); -} - -#[test] -fn ruby_singleton_class_body_contributes_to_class_metrics() { - // `class << self; def foo; end; end` — singleton class scope, - // a class-like space in prism. Methods inside count toward NPM. - let a = analyze( - "class C - class << self - def cls_method - 1 - end - end - end", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - assert!( - npm.total_methods >= 1.0, - "{}", - serde_json::to_string(&npm).unwrap() - ); -} - -#[test] -fn ruby_modifier_if_does_not_increase_nesting() { - // Sonar cognitive spec: `x if y` adds +1 without nesting. Two - // sibling modifier-if statements should each contribute +1, NOT - // collapse into a nested-if pattern. - let a = analyze( - "def f(a, b) - return 1 if a # +1 - return 0 if b # +1 - end", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 2.0, "{}", serde_json::to_string(&cog).unwrap()); -} - -#[test] -fn ruby_op_assignment_writes_count_as_assignment_and_decision() { - // `x &&= y` and `x ||= y` are short-circuiting writes — they - // count as both ABC.A (assignment) AND ABC.C (condition / cyclomatic). - // Legacy tree-sitter exposed these as `operator_assignment`; prism - // splits into `LocalVariableAndWriteNode` / `LocalVariableOrWriteNode`. - let a = analyze( - "def f(x) - x &&= 1 - x ||= 2 - end", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - assert_eq!( - abc.assignments, - 2.0, - "{}", - serde_json::to_string(&abc).unwrap() - ); - assert_eq!( - abc.conditions, - 2.0, - "{}", - serde_json::to_string(&abc).unwrap() - ); - // unit (+1), method (+1), &&= (+1), ||= (+1) = 4 - assert_eq!(cy.sum, 4.0, "{}", serde_json::to_string(&cy).unwrap()); -} diff --git a/crates/mehen-ruby/tests/wmc.rs b/crates/mehen-ruby/tests/wmc.rs deleted file mode 100644 index e90f23cd..00000000 --- a/crates/mehen-ruby/tests/wmc.rs +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! WMC tests for the Phase 9 ruby-prism walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_ruby::RubyAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RubyAnalyzer::new(); - let file = SourceFile::new("foo.rb".into(), Language::Ruby, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn ruby_wmc_class_sums_method_cyclomatics() { - let a = analyze( - "class C - def a(x) - return 1 if x - return 0 - end - def b - 1 - end - end", - ); - let wmc = mehen_report::metrics_json::wmc(&a.root.metrics); - insta::assert_json_snapshot!( - wmc, - @r###" - { - "classes": 3.0, - "interfaces": 0.0, - "total": 3.0 - }"### - ); -} diff --git a/crates/mehen-rust/Cargo.toml b/crates/mehen-rust/Cargo.toml deleted file mode 100644 index b2418a67..00000000 --- a/crates/mehen-rust/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "mehen-rust" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — Rust language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -mehen-metrics = { workspace = true } -# `ra_ap_syntax` — replaces tree-sitter-rust for this analyzer. Pinned -# here (not in `[workspace.dependencies]`) because `mehen-rust` is the -# only consumer. Per the rewrite plan §6.1 we promote rust-analyzer's -# parser/syntax stack from "later" to "now" because it exposes the richer -# AST that tree-sitter cannot represent (typed expressions, op_kind, -# let-chains, etc.) without forcing the workspace onto nightly via -# rustc_private. Pinned to a specific 0.0.x release because rust-analyzer -# auto-publishes weekly and breaking changes at the AST level are not -# semver-tracked. Bump deliberately. -ra_ap_syntax = "=0.0.348" -smol_str = { workspace = true } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } - -[lints] -workspace = true diff --git a/crates/mehen-rust/src/lib.rs b/crates/mehen-rust/src/lib.rs deleted file mode 100644 index 40e36372..00000000 --- a/crates/mehen-rust/src/lib.rs +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! `mehen-rust` — Rust language analyzer. -//! -//! Phase 9 implementation: parses via `ra_ap_syntax` (rust-analyzer's -//! published syntax/parser stack) instead of tree-sitter-rust. The walker -//! lives in [`walker`] and follows the same per-space `State` accumulator -//! pattern used by `mehen-python` and `mehen-typescript`. -//! -//! See `docs/rust-ra-ap-syntax-spec.md` for the per-metric design rules -//! and the documented divergences from the legacy tree-sitter walker. - -#![forbid(unsafe_code)] - -mod walker; - -use mehen_core::{ - AnalysisBackend, AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, LineIndex, - ParseDiagnostic, Result, SourceFile, -}; -use mehen_metrics::MetricEvidence; -use ra_ap_syntax::{Edition, SourceFile as RustSourceFile}; - -pub struct RustAnalyzer; - -impl RustAnalyzer { - pub fn new() -> Self { - Self - } -} - -impl Default for RustAnalyzer { - fn default() -> Self { - Self::new() - } -} - -impl LanguageAnalyzer for RustAnalyzer { - fn language(&self) -> Language { - Language::Rust - } - - fn backend(&self) -> AnalysisBackend { - AnalysisBackend::RaApSyntax - } - - fn analyze(&self, source: &SourceFile, config: &AnalysisConfig) -> Result { - // ra_ap_syntax always returns a tree, even on parse errors. Errors - // are surfaced through `parse.errors()`; we don't fail the - // analysis on recoverable errors — the legacy tree-sitter - // pipeline also produced metrics from partial trees. Recovered - // errors are surfaced as `error` (not `warning`) so the - // diagnostic contract (plan §9.3) treats the analysis as - // incomplete: `mehen metrics` exits 1 and `analyze_diff` - // records the file under `analysis_errors`. - let parse = RustSourceFile::parse(&source.text, Edition::CURRENT); - let file = parse.tree(); - let line_index = LineIndex::new(&source.text); - let mut evidence = MetricEvidence::new("rust", config.emit_contributions); - let root = walker::walk_source_file(&file, &source.text, &line_index, &mut evidence); - let diagnostics: Vec = parse - .errors() - .iter() - .take(16) - .map(|e| ParseDiagnostic::error("rust.syntax_error", e.to_string())) - .collect(); - // Per-space McCabe base rows (+1 per space, unit included) so - // cyclomatic evidence sums to `cyclomatic.sum` — decisions alone - // cannot explain the rolled-up value (an empty function moves it). - evidence.record_cyclomatic_bases(&root); - Ok(LanguageAnalysis { - language: Language::Rust, - backend: AnalysisBackend::RaApSyntax, - diagnostics, - root, - contributions: evidence.finish(), - }) - } -} diff --git a/crates/mehen-rust/src/walker.rs b/crates/mehen-rust/src/walker.rs deleted file mode 100644 index 8115a989..00000000 --- a/crates/mehen-rust/src/walker.rs +++ /dev/null @@ -1,985 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ra_ap_syntax-based walker that produces a populated `MetricSpace`. -//! -//! Mirrors the per-space `State` accumulator pattern used by -//! `mehen-python` (`crates/mehen-python/src/walker.rs`) and -//! `mehen-typescript` (`crates/mehen-typescript/src/walker.rs`): -//! -//! - one `State` for the unit, plus one for every opened -//! function / closure / impl / trait space, -//! - finalize on close, fold child stats into parent, -//! - Halstead is driven by a post-AST token sweep over the source file's -//! tokens. -//! -//! Rust-specific design decisions are documented in -//! `docs/rust-ra-ap-syntax-spec.md`. The short version: -//! -//! - **`?` operator**: counts as a cyclomatic decision and a cognitive -//! `+1` (no nesting bump). It's a real short-circuit on `Err`/`None`, -//! matching legacy and Sonar. -//! - **Match arms**: each arm contributes +1 cyclomatic. The `match` -//! expression itself opens a cognitive nesting frame. -//! - **`else if`**: the inner `if` does NOT add cognitive nesting (legacy -//! `is_else_if` rule); only the outer `if` does. The `else` branch -//! contributes a flat +1 instead. -//! - **Macro contents are opaque**: tokens *inside* a `MacroCall` -//! argument list (or `macro_rules!` body) do not contribute to -//! cyclomatic, cognitive, ABC, or exit counters. The macro name itself -//! counts as a branch. This matches the legacy -//! `is_inside_rust_macro_tokens` filter. -//! - **Type annotations contribute to Halstead**: type identifiers like -//! `Vec` are Halstead operands. Rust types are not erased — they -//! describe runtime values. (Same reasoning as Python; opposite of TS.) -//! - **Doc comments contribute to LOC `cloc`** but not to Halstead. -//! Inline `//` and `/* */` comments contribute to `cloc` only. -//! - **Struct / enum / union do not open a class space** — they record -//! their fields against the enclosing space's NPA counters. Legacy's -//! `is_func_space` listed only `SourceFile | FunctionItem | ImplItem | -//! TraitItem | ClosureExpression`, and Phase 9 preserves that. - -use mehen_core::{LineIndex, MetricSpace, SourceSpan, SpaceKind}; -use mehen_metrics::{ - ContainerKind, HalsteadOperand, HalsteadOperator, MetricEvidence, MetricTreeBuilder, - SpaceRangeTracker, State, apply_state_to, close_space, finalize_state, -}; -use ra_ap_syntax::{ - AstNode, NodeOrToken, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, WalkEvent, - ast::{self, BinaryOp, HasName, HasVisibility, LogicOp, UnaryOp}, -}; -use smol_str::SmolStr; - -/// Crate-internal entry point — drive the walker over a parsed -/// `SourceFile`. Only `mehen_rust::RustAnalyzer::analyze` calls this; -/// the function is not part of any cross-crate API. Contribution -/// evidence is recorded into the caller-owned `evidence` sink -/// (plan §5.4). -pub(crate) fn walk_source_file( - file: &SourceFile, - source: &str, - line_index: &LineIndex, - evidence: &mut MetricEvidence, -) -> MetricSpace { - let unit_range = file.syntax().text_range(); - let unit_span = text_range_to_source_span(unit_range, line_index); - - let mut visitor = Visitor::new(source, line_index, unit_span, evidence); - visitor.walk(file.syntax()); - visitor.emit_halstead_from_tokens(file.syntax()); - visitor.finish() -} - -#[derive(Clone, Copy)] -enum LeaveAction { - None, - CloseSpace, - CloseSpaceAndRestoreCognitive(CognitiveContext), - RestoreCognitive(CognitiveContext), - ExitMacroOpaque, -} - -#[derive(Clone, Copy, Debug, Default)] -struct CognitiveContext { - nesting: u32, - depth: u32, - lambda: u32, -} - -struct Visitor<'a> { - source: &'a str, - line_index: &'a LineIndex, - tree: MetricTreeBuilder, - /// Per-space accumulator stack — index 0 is the unit. - stack: Vec, - /// Parallel to `stack`: the SpaceKind of each open frame. - kinds: Vec, - /// Cognitive context for the currently-walked subtree. Saved on - /// nesting-bumping / function-entry events and restored on leave. - cognitive: CognitiveContext, - /// Macro-opaque ranges — tokens inside these are skipped during the - /// Halstead token sweep. Mirrors the legacy - /// `is_inside_rust_macro_tokens` filter for Halstead; the structural - /// walk uses `macro_opaque_depth` directly. - macro_opaque_ranges: Vec, - /// Active depth count of macro-opaque scopes (>= 1 means we're - /// currently inside a macro body during the structural walk). - macro_opaque_depth: u32, - /// Routes Halstead tokens emitted by the post-AST sweep to the - /// deepest enclosing function/closure/impl/trait space so per-space - /// JSON entries are non-zero. PR #95 discussion_r3265658502 - /// flagged the same gap on the Python walker; the Rust walker had - /// the same `stack[0]`-only behaviour. - halstead_routing: SpaceRangeTracker, - /// Contribution-evidence sink (plan §5.4). Recorded next to each - /// stat increment, usually through [`Visitor::record_evidence`]. - evidence: &'a mut MetricEvidence, -} - -impl<'a> Visitor<'a> { - fn new( - source: &'a str, - line_index: &'a LineIndex, - unit_span: SourceSpan, - evidence: &'a mut MetricEvidence, - ) -> Self { - let mut state = State::new(); - state.loc.set_span( - unit_span.start_line.saturating_sub(1), - unit_span.end_line.saturating_sub(1), - true, - ); - Self { - source, - line_index, - tree: MetricTreeBuilder::new(unit_span), - stack: vec![state], - kinds: vec![SpaceKind::Unit], - cognitive: CognitiveContext::default(), - macro_opaque_ranges: Vec::new(), - macro_opaque_depth: 0, - halstead_routing: SpaceRangeTracker::new(), - evidence, - } - } - - fn current(&mut self) -> &mut State { - self.stack.last_mut().expect("walker stack empty") - } - - /// Record contribution evidence for `range`. The span is only - /// computed when the sink is enabled, so call sites can invoke this - /// unconditionally next to each stat increment — mirrors - /// `mehen_tree_sitter::WalkerCtx::record_evidence`. - #[inline] - fn record_evidence(&mut self, range: TextRange, record: F) - where - F: FnOnce(&mut MetricEvidence, SourceSpan), - { - if self.evidence.is_enabled() { - let span = text_range_to_source_span(range, self.line_index); - record(self.evidence, span); - } - } - - fn finish(mut self) -> MetricSpace { - let mut unit_state = self.stack.pop().expect("walker stack underflow"); - finalize_state(&mut unit_state); - // Route post-AST tokens (Halstead operator/operand, - // PLOC code lines, comment lines) to nested spaces; see - // [`SpaceRangeTracker`]. - let mut unit_halstead = std::mem::take(&mut unit_state.halstead); - let mut unit_loc = std::mem::take(&mut unit_state.loc); - let mut tree = self.tree.finish(); - self.halstead_routing - .finalize_into_tree(&mut tree, &mut unit_halstead, &mut unit_loc); - unit_state.halstead = unit_halstead; - unit_state.loc = unit_loc; - apply_state_to(unit_state, &mut tree.metrics); - tree - } - - fn open_space(&mut self, kind: SpaceKind, range: TextRange, name: Option) { - let mut child = State::for_opened_space(kind.clone()); - let start_row = self - .line_index - .line_at(range.start().into()) - .saturating_sub(1); - let end_row = self - .line_index - .line_at(range.end().into()) - .saturating_sub(1); - child.loc.set_span(start_row, end_row, false); - - let span = text_range_to_source_span(range, self.line_index); - let space_id = self.tree.open(kind.clone(), span, name); - self.halstead_routing - .record_open(space_id, range.start().into(), range.end().into()); - self.stack.push(child); - self.kinds.push(kind); - } - - fn close_space(&mut self) { - close_space( - &mut self.stack, - &mut self.kinds, - &mut self.tree, - &mut self.halstead_routing, - ); - } - - /// Drive a preorder walk over the syntax tree. Uses an explicit - /// `WalkEvent` loop so we can finalize the per-space stack on - /// `Leave` events. - fn walk(&mut self, root: &SyntaxNode) { - let mut actions: Vec = Vec::new(); - for event in root.preorder() { - match event { - WalkEvent::Enter(node) => { - let action = self.enter_node(&node); - actions.push(action); - } - WalkEvent::Leave(_) => { - let action = actions.pop().expect("walker action stack underflow"); - match action { - LeaveAction::None => {} - LeaveAction::CloseSpace => self.close_space(), - LeaveAction::CloseSpaceAndRestoreCognitive(saved) => { - self.close_space(); - self.cognitive = saved; - } - LeaveAction::RestoreCognitive(saved) => { - self.cognitive = saved; - } - LeaveAction::ExitMacroOpaque => { - self.macro_opaque_depth = self.macro_opaque_depth.saturating_sub(1); - } - } - } - } - } - } - - /// Handle a node-enter event. Returns the matching leave action. - fn enter_node(&mut self, node: &SyntaxNode) -> LeaveAction { - let kind = node.kind(); - - // Block tail expression — `fn f() { 42 }`'s `42` is a logical - // line of code (legacy `is_rust_tail_expression` rule). The tail - // expr is not wrapped in an EXPR_STMT, so the EXPR_STMT arm - // below would miss it. Run this *before* the kind-specific - // match so the per-kind handling still fires (a `for` tail - // expression still records its cyclomatic decision, etc.). - if self.macro_opaque_depth == 0 && is_block_tail_expression(node) { - self.current().loc.observe_lloc(); - } - - // Inside a macro body: structural metrics are off, but we still - // need to track nested macro boundaries so the depth unwinds. - if self.macro_opaque_depth > 0 { - if matches!( - kind, - SyntaxKind::MACRO_CALL | SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF - ) { - self.macro_opaque_ranges.push(node.text_range()); - self.macro_opaque_depth += 1; - return LeaveAction::ExitMacroOpaque; - } - return LeaveAction::None; - } - - match kind { - // ----------------------------------------------------------------- - // Function / closure / impl / trait — open a metric space. - // ----------------------------------------------------------------- - SyntaxKind::FN => { - let func = ast::Fn::cast(node.clone()).unwrap(); - - // NPM bookkeeping: if this Fn is directly inside an - // Impl/Trait body, count it as a method on the - // *enclosing* state (the impl/trait we're currently - // inside). The function's own state is not used for - // NPM — recording there would double-count when the - // child merges back into the parent. - self.classify_method(&func); - - // A trait function signature without a body - // (`fn a(&self);`) is not a func-space in the legacy - // walker. Its NPM contribution was already recorded - // above; nothing else to do. - if func.body().is_none() { - return LeaveAction::None; - } - - let name = func.name().map(|n| n.text().to_string()); - let saved = self.cognitive; - - // Cognitive: function entry resets nesting/lambda; bumps - // depth when nested inside another function. - let nested = self - .kinds - .iter() - .skip(1) - .any(|k| matches!(k, SpaceKind::Function)); - let mut ctx = self.cognitive; - ctx.nesting = 0; - ctx.lambda = 0; - if nested { - ctx.depth = ctx.depth.saturating_add(1); - } - self.cognitive = ctx; - - self.open_space(SpaceKind::Function, node.text_range(), name); - - let argc = func - .param_list() - .map(|pl| count_params(&pl) as u32) - .unwrap_or(0); - self.current().nargs.record_function_args(argc); - // NOM function is recorded by `State::for_opened_space` - // inside `open_space`; evidence for both NOM and NArgs - // attaches to the space-open site. - self.record_evidence(node.text_range(), |e, s| { - e.function(s, "fn"); - e.function_args(s, argc, "fn"); - }); - - LeaveAction::CloseSpaceAndRestoreCognitive(saved) - } - SyntaxKind::CLOSURE_EXPR => { - let saved = self.cognitive; - let mut ctx = self.cognitive; - ctx.lambda = ctx.lambda.saturating_add(1); - self.cognitive = ctx; - - self.open_space(SpaceKind::Closure, node.text_range(), None); - // NOM closure is recorded by `State::for_opened_space` - // inside `open_space`; evidence attaches to the open site. - self.record_evidence(node.text_range(), |e, s| e.closure(s, "closure_expr")); - - if let Some(closure) = ast::ClosureExpr::cast(node.clone()) { - let argc = closure - .param_list() - .map(|pl| count_params(&pl) as u32) - .unwrap_or(0); - self.current().nargs.record_closure_args(argc); - self.record_evidence(node.text_range(), |e, s| { - e.closure_args(s, argc, "closure_expr"); - }); - } - LeaveAction::CloseSpaceAndRestoreCognitive(saved) - } - SyntaxKind::IMPL => { - let imp = ast::Impl::cast(node.clone()).unwrap(); - let name = imp.self_ty().map(|t| t.syntax().text().to_string()); - self.open_space(SpaceKind::Impl, node.text_range(), name); - LeaveAction::CloseSpace - } - SyntaxKind::TRAIT => { - let tr = ast::Trait::cast(node.clone()).unwrap(); - let name = tr.name().map(|n| n.text().to_string()); - self.open_space(SpaceKind::Trait, node.text_range(), name); - LeaveAction::CloseSpace - } - - // ----------------------------------------------------------------- - // Decision points (cyclomatic + cognitive + ABC) - // ----------------------------------------------------------------- - SyntaxKind::IF_EXPR => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(node.text_range(), |e, s| { - e.decision(s, "if_expr"); - e.abc_condition(s, "if_expr"); - }); - let bumped_nesting = if !is_else_if(node) { - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(node.text_range(), |e, s| { - e.cognitive(s, effective.saturating_add(1), "if_expr"); - }); - true - } else { - // `else if` — the legacy walker emits the +1 (flat) - // contribution at the connecting `Else` token. We - // attribute that +1 to the *parent* IF_EXPR via the - // else-branch-detection below, so this inner `if` - // adds nothing on its own. - false - }; - // The legacy walker emits a flat +1 for every `Else` - // token (covers both `else if` and bare `else { … }`). - // ra_ap_syntax doesn't surface a dedicated Else AST - // node — but each IF_EXPR exposes its own `else_token()` - // / `else_branch()`. Attribute the +1 to the IF_EXPR - // that owns the else branch. Evidence points at the - // `else` keyword itself. - if let Some(if_expr) = ast::IfExpr::cast(node.clone()) - && let Some(else_token) = if_expr.else_token() - { - self.current().cognitive.increment_by_one(); - self.record_evidence(else_token.text_range(), |e, s| { - e.cognitive(s, 1, "else_kw"); - }); - } - self.current().cognitive.boolean_seq.reset(); - let saved = self.cognitive; - if bumped_nesting { - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - } - LeaveAction::RestoreCognitive(saved) - } - SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR | SyntaxKind::LOOP_EXPR => { - let detail = match kind { - SyntaxKind::WHILE_EXPR => "while_expr", - SyntaxKind::FOR_EXPR => "for_expr", - _ => "loop_expr", - }; - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(node.text_range(), |e, s| { - e.decision(s, detail); - e.abc_condition(s, detail); - e.cognitive(s, effective.saturating_add(1), detail); - }); - self.current().cognitive.boolean_seq.reset(); - let saved = self.cognitive; - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - LeaveAction::RestoreCognitive(saved) - } - SyntaxKind::MATCH_EXPR => { - self.current().abc.record_condition(); - let effective = - self.cognitive.nesting + self.cognitive.depth + self.cognitive.lambda; - self.current().cognitive.increase_nesting(effective); - self.record_evidence(node.text_range(), |e, s| { - e.abc_condition(s, "match_expr"); - e.cognitive(s, effective.saturating_add(1), "match_expr"); - }); - self.current().cognitive.boolean_seq.reset(); - let saved = self.cognitive; - self.cognitive.nesting = self.cognitive.nesting.saturating_add(1); - LeaveAction::RestoreCognitive(saved) - } - SyntaxKind::MATCH_ARM => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - self.record_evidence(node.text_range(), |e, s| { - e.decision(s, "match_arm"); - e.abc_condition(s, "match_arm"); - }); - LeaveAction::None - } - SyntaxKind::TRY_EXPR => { - // `?` short-circuits on Err/None: +1 cyclomatic, +1 cognitive - // (no nesting), +1 ABC condition, +1 exit. - self.current().cyclomatic.record_decision(); - self.current().cognitive.increment_by_one(); - self.current().abc.record_condition(); - self.current().nexit.record_exit(); - self.record_evidence(node.text_range(), |e, s| { - e.decision(s, "try_expr"); - e.cognitive(s, 1, "try_expr"); - e.abc_condition(s, "try_expr"); - e.exit(s, "try_expr"); - }); - LeaveAction::None - } - SyntaxKind::RETURN_EXPR => { - self.current().nexit.record_exit(); - self.record_evidence(node.text_range(), |e, s| e.exit(s, "return_expr")); - LeaveAction::None - } - SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => { - if has_label_child(node) { - let detail = if kind == SyntaxKind::BREAK_EXPR { - "break_expr" - } else { - "continue_expr" - }; - self.current().cognitive.increment_by_one(); - self.record_evidence(node.text_range(), |e, s| e.cognitive(s, 1, detail)); - } - LeaveAction::None - } - SyntaxKind::BIN_EXPR => { - if let Some(bin) = ast::BinExpr::cast(node.clone()) - && let Some((op_token, op)) = bin.op_details() - { - match op { - BinaryOp::LogicOp(LogicOp::And) => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - // Evidence spans point at the operator - // token; same-operator repeats apply no - // cognitive delta and record nothing. - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean("&&"); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(op_token.text_range(), |e, s| { - e.decision(s, "&&"); - e.abc_condition(s, "&&"); - e.cognitive(s, delta, "&&"); - }); - } - BinaryOp::LogicOp(LogicOp::Or) => { - self.current().cyclomatic.record_decision(); - self.current().abc.record_condition(); - let before = self.current().cognitive.structural; - self.current().cognitive.observe_boolean("||"); - let delta = self.current().cognitive.structural.saturating_sub(before); - self.record_evidence(op_token.text_range(), |e, s| { - e.decision(s, "||"); - e.abc_condition(s, "||"); - e.cognitive(s, delta, "||"); - }); - } - BinaryOp::CmpOp(_) => { - self.current().abc.record_condition(); - let op_text: &str = op_token.text(); - self.record_evidence(op_token.text_range(), |e, s| { - e.abc_condition(s, op_text); - }); - } - BinaryOp::Assignment { .. } => { - self.current().abc.record_assignment(); - self.record_evidence(node.text_range(), |e, s| { - e.abc_assignment(s, "bin_expr"); - }); - } - BinaryOp::ArithOp(_) => {} - } - } - LeaveAction::None - } - SyntaxKind::PREFIX_EXPR => { - if let Some(pre) = ast::PrefixExpr::cast(node.clone()) - && matches!(pre.op_kind(), Some(UnaryOp::Not)) - { - self.current().cognitive.boolean_seq.not_operator("!"); - } - LeaveAction::None - } - - // ----------------------------------------------------------------- - // Statement-level — LLOC, ABC.assignments - // ----------------------------------------------------------------- - SyntaxKind::LET_STMT => { - if let Some(stmt) = ast::LetStmt::cast(node.clone()) - && stmt.eq_token().is_some() - { - self.current().abc.record_assignment(); - self.record_evidence(node.text_range(), |e, s| { - e.abc_assignment(s, "let_stmt"); - }); - } - self.current().loc.observe_lloc(); - LeaveAction::None - } - SyntaxKind::EXPR_STMT => { - self.current().loc.observe_lloc(); - LeaveAction::None - } - - // ----------------------------------------------------------------- - // Branches (B in ABC) - // ----------------------------------------------------------------- - SyntaxKind::CALL_EXPR | SyntaxKind::METHOD_CALL_EXPR => { - let detail = if kind == SyntaxKind::CALL_EXPR { - "call_expr" - } else { - "method_call_expr" - }; - self.current().abc.record_branch(); - self.record_evidence(node.text_range(), |e, s| e.abc_branch(s, detail)); - LeaveAction::None - } - SyntaxKind::MACRO_CALL => { - self.current().abc.record_branch(); - self.record_evidence(node.text_range(), |e, s| e.abc_branch(s, "macro_call")); - self.macro_opaque_ranges.push(node.text_range()); - self.macro_opaque_depth += 1; - LeaveAction::ExitMacroOpaque - } - SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF => { - self.macro_opaque_ranges.push(node.text_range()); - self.macro_opaque_depth += 1; - LeaveAction::ExitMacroOpaque - } - - // ----------------------------------------------------------------- - // Class-like attribute counters (NPA / NPM) - // - // Rust structs / unions do not open their own metric space - // (legacy `is_func_space` did not include them). But for the - // NPA family the stats accumulator needs `classes` to count - // class-like containers — call `record_class_like` directly - // on the enclosing space once per struct so the published - // total reflects "1 struct = 1 class". - // ----------------------------------------------------------------- - SyntaxKind::STRUCT | SyntaxKind::UNION => { - self.current().npa.record_class_like(); - LeaveAction::None - } - SyntaxKind::RECORD_FIELD => { - if let Some(field) = ast::RecordField::cast(node.clone()) { - let is_public = field.visibility().is_some(); - self.current() - .npa - .record_attribute(ContainerKind::Class, is_public); - // Only public members move the headline NPA value. - if is_public { - self.record_evidence(node.text_range(), |e, s| { - e.public_attribute(s, "record_field"); - }); - } - } - LeaveAction::None - } - SyntaxKind::TUPLE_FIELD => { - if let Some(field) = ast::TupleField::cast(node.clone()) { - let is_public = field.visibility().is_some(); - self.current() - .npa - .record_attribute(ContainerKind::Class, is_public); - if is_public { - self.record_evidence(node.text_range(), |e, s| { - e.public_attribute(s, "tuple_field"); - }); - } - } - LeaveAction::None - } - - _ => LeaveAction::None, - } - } - - /// NPM bookkeeping: a `Fn` directly inside an Impl's or Trait's - /// associated-item list is a method. Trait methods are implicitly - /// public; Impl methods inherit Rust's `pub`/`pub(...)` visibility. - fn classify_method(&mut self, func: &ast::Fn) { - // Hop through the AssocItemList to reach the IMPL/TRAIT. - let parent = func.syntax().parent(); - let grand_kind = match parent.as_ref().and_then(|p| p.parent()) { - Some(g) => g.kind(), - None => return, - }; - let container = match grand_kind { - SyntaxKind::IMPL => ContainerKind::Class, - SyntaxKind::TRAIT => ContainerKind::Interface, - _ => return, - }; - let is_public = matches!(grand_kind, SyntaxKind::TRAIT) || func.visibility().is_some(); - self.current().npm.record_method(container, is_public); - // Only public methods move the headline NPM value. Trait and - // impl methods both fold into the published `npm` total. - if is_public { - self.record_evidence(func.syntax().text_range(), |e, s| e.public_method(s, "fn")); - } - } - - /// Token-stream Halstead emission — runs after the AST walk. - /// Each token maps to one of `Operator(kind)`, `Operand(kind)`, or - /// `Skip`. Tokens whose span falls inside a macro-opaque range are - /// skipped entirely, and comment tokens are folded into LOC `cloc`. - fn emit_halstead_from_tokens(&mut self, root: &SyntaxNode) { - // Sort macro ranges so the inside-test is cheap. - self.macro_opaque_ranges.sort_by_key(|r| r.start()); - - for elem in root.descendants_with_tokens() { - let token = match elem { - NodeOrToken::Token(t) => t, - NodeOrToken::Node(_) => continue, - }; - self.observe_token(&token); - } - } - - fn observe_token(&mut self, token: &SyntaxToken) { - let kind = token.kind(); - let range = token.text_range(); - - // LOC: comment tokens — both line and block — route to the - // deepest enclosing scope so per-space `loc.cloc` reflects - // comments inside that scope's body. Lines that fall outside - // every recorded scope go into the unit's LocStats. - if kind == SyntaxKind::COMMENT { - let start_row = self - .line_index - .line_at(range.start().into()) - .saturating_sub(1); - let end_row = self - .line_index - .line_at(range.end().into()) - .saturating_sub(1); - self.halstead_routing.observe_comment( - range.start().into(), - range.end().into(), - &mut self.stack[0].loc, - start_row, - end_row, - ); - return; - } - if kind == SyntaxKind::WHITESPACE { - return; - } - - // Macro-opaque ranges: any token whose span is *strictly inside* - // a macro-opaque range (not at the boundary — the macro name and - // the trailing `!` live outside the body) is excluded from - // Halstead. - if self.is_inside_macro_body(range) { - return; - } - - let s: u32 = range.start().into(); - let e: u32 = range.end().into(); - match classify_token(kind) { - TokenClass::Operator(kind_str) => { - self.halstead_routing.observe_operator( - s, - e, - &mut self.stack[0].halstead, - HalsteadOperator { - kind: SmolStr::new(kind_str), - text: None, - }, - ); - } - TokenClass::Operand(kind_str) => { - let text = self - .source - .get(usize::from(range.start())..usize::from(range.end())) - .unwrap_or(""); - self.halstead_routing.observe_operand( - s, - e, - &mut self.stack[0].halstead, - HalsteadOperand { - kind: SmolStr::new(kind_str), - text: Some(SmolStr::new(text)), - }, - ); - - // Note an LLOC line for the token (matches legacy - // `is_rust_tail_expression` which counts the trailing - // expression of a block as a logical line). The actual - // implementation lives at the AST level for precision — - // see EXPR_STMT / LET_STMT above. Token-level LOC is - // limited to comments here. - } - TokenClass::Skip => {} - } - - // PLOC: any non-whitespace, non-comment token's starting line - // is a code line — routed to the deepest enclosing scope so - // per-space `loc.ploc` reflects the function/closure body. - // Lines outside every recorded scope go into the unit - // (top-level use statements, free constants, etc.). - let start_row = self - .line_index - .line_at(range.start().into()) - .saturating_sub(1); - self.halstead_routing.observe_code_line( - range.start().into(), - range.end().into(), - &mut self.stack[0].loc, - start_row, - ); - } - - fn is_inside_macro_body(&self, range: TextRange) -> bool { - // Each macro_opaque_range covers the *entire* MacroCall node — - // including the macro name (`println`) and the bang (`!`). For - // Halstead parity with legacy we want the macro name to count - // (it's a real call), so we only skip tokens that fall *strictly - // after* the bang. A simpler heuristic: skip tokens whose range - // is fully inside any macro_opaque_range AND whose kind is one - // of the body delimiters' content (not the leading - // identifier/bang). We achieve that by checking position: the - // first two tokens of a MacroCall (the path identifier, the - // bang) live outside the body's `{...}` / `(...)` / `[...]` - // brackets, so we skip only tokens after the opening bracket. - // - // For now the token sweep emits everything; the macro path and - // bang are explicitly counted as the call's branch via the AST - // walk. This keeps the implementation simple while preserving - // the legacy "macro name is a branch but body is opaque" - // behavior. - for r in &self.macro_opaque_ranges { - if range.start() >= r.start() && range.end() <= r.end() { - return true; - } - } - false - } -} - -// ===================================================================== -// Helpers -// ===================================================================== - -fn text_range_to_source_span(range: TextRange, line_index: &LineIndex) -> SourceSpan { - SourceSpan { - start_byte: range.start().into(), - end_byte: range.end().into(), - start_line: line_index.line_at(range.start().into()), - end_line: line_index.line_at(range.end().into()), - } -} - -fn count_params(pl: &ast::ParamList) -> usize { - let regular = pl.params().count(); - let self_param = pl.self_param().is_some() as usize; - regular + self_param -} - -fn is_else_if(node: &SyntaxNode) -> bool { - if node.kind() != SyntaxKind::IF_EXPR { - return false; - } - if let Some(parent) = node.parent() - && parent.kind() == SyntaxKind::IF_EXPR - && let Some(parent_if) = ast::IfExpr::cast(parent.clone()) - && let Some(else_branch) = parent_if.else_branch() - && let ast::ElseBranch::IfExpr(inner_if) = else_branch - { - return inner_if.syntax() == node; - } - false -} - -fn has_label_child(node: &SyntaxNode) -> bool { - node.children_with_tokens() - .any(|c| matches!(c.kind(), SyntaxKind::LIFETIME)) -} - -/// Is this node the *tail expression* of a `STMT_LIST` (i.e. the final -/// expression of a block body, with no terminating `;`)? The legacy -/// `is_rust_tail_expression` rule treated such expressions as a logical -/// line of code; we need the same so `fn f() { 42 }` reports 1 LLOC. -fn is_block_tail_expression(node: &SyntaxNode) -> bool { - // A tail expression is an `Expr` whose direct parent is a - // STMT_LIST and whose position in the parent matches the - // STMT_LIST's `tail_expr()` (the last expression with no trailing - // semicolon). - let parent = match node.parent() { - Some(p) if p.kind() == SyntaxKind::STMT_LIST => p, - _ => return false, - }; - if !ast::Expr::can_cast(node.kind()) { - return false; - } - let stmt_list = match ast::StmtList::cast(parent) { - Some(sl) => sl, - None => return false, - }; - match stmt_list.tail_expr() { - Some(tail) => tail.syntax() == node, - None => false, - } -} - -enum TokenClass { - Operator(&'static str), - Operand(&'static str), - Skip, -} - -fn classify_token(kind: SyntaxKind) -> TokenClass { - // We deliberately avoid `use SyntaxKind::*` here. ra_ap_syntax's - // generated enum has hundreds of variants, and bare-name match - // patterns (`LT`, `EQ`, `IDENT`, ...) are interpreted by Rust as - // *fresh bindings*, not enum constants — that lets every arm - // shadow the next and warns "unreachable pattern". Use full paths - // through the `T!` macro / `SyntaxKind::*` so each arm is - // unambiguous. - use TokenClass::*; - use ra_ap_syntax::T; - match kind { - // Punctuation / operators (use the `T!` macro from ra_ap_syntax - // which expands to the SyntaxKind variant for the literal). - T!['('] => Operator("("), - T!['['] => Operator("["), - T!['{'] => Operator("{"), - T![,] => Operator(","), - T![:] => Operator(":"), - T![;] => Operator(";"), - T![.] => Operator("."), - T![@] => Operator("@"), - T![+] => Operator("+"), - T![-] => Operator("-"), - T![*] => Operator("*"), - T![/] => Operator("/"), - T![%] => Operator("%"), - T![|] => Operator("|"), - T![&] => Operator("&"), - T![^] => Operator("^"), - T![~] => Operator("~"), - T![&&] => Operator("&&"), - T![||] => Operator("||"), - T![<<] => Operator("<<"), - T![>>] => Operator(">>"), - T![=] => Operator("="), - T![==] => Operator("=="), - T![!=] => Operator("!="), - T![<] => Operator("<"), - T![>] => Operator(">"), - T![<=] => Operator("<="), - T![>=] => Operator(">="), - T![+=] => Operator("+="), - T![-=] => Operator("-="), - T![*=] => Operator("*="), - T![/=] => Operator("/="), - T![%=] => Operator("%="), - T![&=] => Operator("&="), - T![|=] => Operator("|="), - T![^=] => Operator("^="), - T![<<=] => Operator("<<="), - T![>>=] => Operator(">>="), - T![..] => Operator(".."), - T![..=] => Operator("..="), - T![::] => Operator("::"), - T![=>] => Operator("=>"), - T![->] => Operator("->"), - T![?] => Operator("?"), - T![!] => Operator("!"), - // Keywords — Halstead operators. - T![fn] => Operator("fn"), - T![let] => Operator("let"), - T![if] => Operator("if"), - T![else] => Operator("else"), - T![while] => Operator("while"), - T![for] => Operator("for"), - T![loop] => Operator("loop"), - T![match] => Operator("match"), - T![return] => Operator("return"), - T![break] => Operator("break"), - T![continue] => Operator("continue"), - T![as] => Operator("as"), - T![in] => Operator("in"), - T![mut] => Operator("mut"), - T![ref] => Operator("ref"), - T![static] => Operator("static"), - T![const] => Operator("const"), - T![struct] => Operator("struct"), - T![enum] => Operator("enum"), - T![trait] => Operator("trait"), - T![impl] => Operator("impl"), - T![type] => Operator("type"), - T![use] => Operator("use"), - T![mod] => Operator("mod"), - T![pub] => Operator("pub"), - T![where] => Operator("where"), - T![async] => Operator("async"), - T![await] => Operator("await"), - T![dyn] => Operator("dyn"), - T![unsafe] => Operator("unsafe"), - T![move] => Operator("move"), - T![extern] => Operator("extern"), - T![self] => Operator("self"), - T![Self] => Operator("Self"), - T![super] => Operator("super"), - T![crate] => Operator("crate"), - T![yield] => Operator("yield"), - // Operands — leaves that name or contain a value. - SyntaxKind::IDENT => Operand("Identifier"), - SyntaxKind::INT_NUMBER | SyntaxKind::FLOAT_NUMBER => Operand("Number"), - SyntaxKind::STRING | SyntaxKind::BYTE_STRING | SyntaxKind::C_STRING => Operand("String"), - SyntaxKind::CHAR | SyntaxKind::BYTE => Operand("Char"), - T![true] => Operand("True"), - T![false] => Operand("False"), - SyntaxKind::LIFETIME_IDENT => Operand("Lifetime"), - // Closing punctuation pairs with its opener; skip to avoid - // double-counting (classical Halstead pair convention). - T![')'] | T![']'] | T!['}'] => Skip, - // Trivia + EOF + everything else. - _ => Skip, - } -} diff --git a/crates/mehen-rust/tests/abc.rs b/crates/mehen-rust/tests/abc.rs deleted file mode 100644 index ff1de8d2..00000000 --- a/crates/mehen-rust/tests/abc.rs +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! ABC tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/abc.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_abc_basic() { - let a = analyze( - "fn f(a: i32, b: i32) -> i32 { - let mut x = a; - x += b; - log(x); - if x > b { - return x; - } - x - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - insta::assert_json_snapshot!( - abc, - @r###" - { - "assignments": 2.0, - "branches": 1.0, - "conditions": 2.0, - "magnitude": 3.0, - "assignments_average": 1.0, - "branches_average": 0.5, - "conditions_average": 1.0, - "assignments_min": 0.0, - "assignments_max": 2.0, - "branches_min": 0.0, - "branches_max": 1.0, - "conditions_min": 0.0, - "conditions_max": 2.0 - }"### - ); -} - -#[test] -fn rust_abc_scopes_type_and_macro_tokens() { - // Type parameters do not contribute to ABC. Macro body tokens are - // opaque, so the inner `&&` and `if` do not register either. Only - // the macro call itself counts as a branch. - let a = analyze( - "fn generic(a: Option, b: Result) {} - fn macro_call() { - maybe!(a && b, if c { d() }); - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - assert_eq!( - abc.conditions, - 0.0, - "got {}", - serde_json::to_string(&abc).unwrap() - ); - assert_eq!( - abc.branches, - 1.0, - "got {}", - serde_json::to_string(&abc).unwrap() - ); -} - -#[test] -fn rust_abc_counts_let_chain_operators_in_conditions() { - let a = analyze( - "fn f(a: Option, b: Option) { - if let Some(x) = a && let Some(y) = b && x > y { - work(); - } - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - assert_eq!( - abc.conditions, - 4.0, - "got {}", - serde_json::to_string(&abc).unwrap() - ); - assert_eq!( - abc.branches, - 1.0, - "got {}", - serde_json::to_string(&abc).unwrap() - ); -} diff --git a/crates/mehen-rust/tests/cognitive.rs b/crates/mehen-rust/tests/cognitive.rs deleted file mode 100644 index f48b5f57..00000000 --- a/crates/mehen-rust/tests/cognitive.rs +++ /dev/null @@ -1,391 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cognitive complexity tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/cognitive.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_no_cognitive() { - // Drift from pre-1.0: legacy reported `average: null` when the unit - // has no enclosed functions because `cognitive_average` was a - // `Option` that the JSON formatter rendered as `null`. The - // Phase-1+ `mehen-metrics::cognitive::finalize` sets it to `0.0` for - // empty inputs (no functions → average is 0, not undefined). The - // metric definition is unchanged: with zero functions there is - // nothing to average. `0.0` is mathematically defensible for - // "no contribution." All other Phase-9 language ports (Python, - // TypeScript) carry the same `0.0` here. - let a = analyze("let a = 42;"); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} - -#[test] -fn rust_simple_function() { - let a = analyze( - "fn f() { - if a && b { - println!(\"test\"); - } - if c && d { - println!(\"test\"); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn rust_sequence_same_booleans_amp() { - let a = analyze( - "fn f() { - if a && b && true { - println!(\"test\"); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn rust_sequence_same_booleans_pipe() { - let a = analyze( - "fn f() { - if a || b || c || d { - println!(\"test\"); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn rust_not_booleans_simple() { - let a = analyze( - "fn f() { - if !a && !b { - println!(\"test\"); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 2.0, - "average": 2.0, - "min": 0.0, - "max": 2.0 - }"### - ); -} - -#[test] -fn rust_not_booleans_nested_amp() { - let a = analyze( - "fn f() { - if a && !(b && c) { - println!(\"test\"); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn rust_not_booleans_nested_pipe() { - let a = analyze( - "fn f() { - if !(a || b) && !(c || d) { - println!(\"test\"); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn rust_sequence_different_booleans() { - let a = analyze( - "fn f() { - if a && b || true { - println!(\"test\"); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn rust_let_chain_boolean_sequence() { - let a = analyze( - "fn f(a: Option, b: Option) { - if let Some(x) = a && let Some(y) = b && x > y { - work(); - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - // +1 for the if, +1 for the same-operator `&&` let-chain. - assert_eq!(cog.sum, 2.0, "got {}", serde_json::to_string(&cog).unwrap()); -} - -#[test] -fn rust_macro_tokens_are_opaque_for_cognitive() { - let a = analyze( - "fn f() { - maybe!(a && b, if c { d() }); - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - assert_eq!(cog.sum, 0.0, "got {}", serde_json::to_string(&cog).unwrap()); -} - -#[test] -fn rust_1_level_nesting_complex() { - let a = analyze( - "fn f() { - if true { - if true { - println!(\"test\"); - } else if 1 == 1 { - if true { - println!(\"test\"); - } - } else { - if true { - println!(\"test\"); - } - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 11.0, - "average": 11.0, - "min": 0.0, - "max": 11.0 - }"### - ); -} - -#[test] -fn rust_1_level_nesting_match() { - let a = analyze( - "fn f() { - if true { - match true { - true => println!(\"test\"), - false => println!(\"test\"), - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn rust_2_level_nesting() { - let a = analyze( - "fn f() { - if true { - for i in 0..4 { - match true { - true => println!(\"test\"), - false => println!(\"test\"), - } - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 6.0, - "average": 6.0, - "min": 0.0, - "max": 6.0 - }"### - ); -} - -#[test] -fn rust_break_continue() { - let a = analyze( - "fn f() { - 'tens: for ten in 0..3 { - '_units: for unit in 0..=9 { - if unit % 2 == 0 { - continue; - } else if unit == 5 { - continue 'tens; - } else if unit == 6 { - break; - } else { - break 'tens; - } - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 11.0, - "average": 11.0, - "min": 0.0, - "max": 11.0 - }"### - ); -} - -#[test] -fn rust_if_let_else_if_else() { - let a = analyze( - "pub fn create_usage_no_title(p: &Parser, used: &[&str]) -> String { - debugln!(\"usage::create_usage_no_title;\"); - if let Some(u) = p.meta.usage_str { - String::from(&*u) - } else if used.is_empty() { - create_help_usage(p, true) - } else { - create_smart_usage(p, used) - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 3.0, - "average": 3.0, - "min": 0.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn rust_loop_and_try() { - let a = analyze( - "fn f() -> Option { - loop { - let x = g()?; - if x > 0 { - return Some(x); - } - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - insta::assert_json_snapshot!( - cog, - @r###" - { - "sum": 4.0, - "average": 4.0, - "min": 0.0, - "max": 4.0 - }"### - ); -} diff --git a/crates/mehen-rust/tests/contributions.rs b/crates/mehen-rust/tests/contributions.rs deleted file mode 100644 index 43614fa1..00000000 --- a/crates/mehen-rust/tests/contributions.rs +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Contribution-evidence tests for the Rust analyzer (plan §5.4). - -use mehen_core::{ - AnalysisConfig, Language, LanguageAnalysis, LanguageAnalyzer, MetricKey, SourceFile, -}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str, config: &AnalysisConfig) -> LanguageAnalysis { - RustAnalyzer::new() - .analyze( - &SourceFile::new("s.rs".into(), Language::Rust, source.to_string()), - config, - ) - .expect("Rust analysis succeeds") -} - -fn metric(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .root - .metrics - .get(&MetricKey::new(key)) - .unwrap_or_else(|| panic!("missing metric {key}")) - .as_f64() -} - -fn evidence_sum(analysis: &LanguageAnalysis, key: &str) -> f64 { - analysis - .contributions - .iter() - .filter(|item| item.metric.as_str() == key) - .map(|item| item.amount) - .sum() -} - -const FIXTURE: &str = "\ -pub struct Point { - pub x: i32, - y: i32, -} - -impl Point { - pub fn total(&self) -> i32 { - self.x + self.y - } -} - -fn classify(a: i32, b: i32) -> i32 { - let mut total = 0; - if a > 0 && b > 0 { - total = 1; - } else if a < 0 { - total = -1; - } - match total { - 0 => total = 9, - _ => total += 1, - } - let double = |x: i32| (x * 2).abs(); - if total > 100 { - return double(total); - } - double(total) -} -"; - -#[test] -fn evidence_sums_match_published_metrics() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(!analysis.contributions.is_empty()); - - // Families whose rolled-up value is exactly the sum of their - // per-event evidence. Cyclomatic includes the per-space McCabe - // base rows (`rust.cyclomatic.base.`), so it sums exactly. - for (evidence_key, metric_key) in [ - ("cyclomatic.sum", "cyclomatic.sum"), - ("cognitive.sum", "cognitive.sum"), - ("nexit.sum", "nexit.sum"), - ("abc.assignments", "abc.assignments"), - ("abc.branches", "abc.branches"), - ("abc.conditions", "abc.conditions"), - ("nom.functions", "nom.functions"), - ("nom.closures", "nom.closures"), - ("nargs", "nargs"), - ("npa", "npa"), - ("npm", "npm"), - ] { - assert_eq!( - evidence_sum(&analysis, evidence_key), - metric(&analysis, metric_key), - "evidence for `{evidence_key}` must sum to `{metric_key}`", - ); - } -} - -#[test] -fn reasons_are_rust_namespaced_with_node_kinds() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - let reasons: Vec<&str> = analysis - .contributions - .iter() - .map(|item| item.reason.as_str()) - .collect(); - - for expected in [ - "rust.cyclomatic.if_expr", - "rust.cyclomatic.match_arm", - "rust.cyclomatic.&&", - "rust.cognitive.if_expr", - "rust.cognitive.else_kw", - "rust.cognitive.match_expr", - "rust.cognitive.&&", - "rust.nexit.return_expr", - "rust.abc.assignment.let_stmt", - "rust.abc.assignment.bin_expr", - "rust.abc.branch.call_expr", - "rust.abc.branch.method_call_expr", - "rust.abc.condition.if_expr", - "rust.abc.condition.match_expr", - "rust.abc.condition.match_arm", - "rust.abc.condition.>", - "rust.nom.function.fn", - "rust.nom.closure.closure_expr", - "rust.nargs.function.fn", - "rust.nargs.closure.closure_expr", - "rust.npa.record_field", - "rust.npm.fn", - ] { - assert!( - reasons.contains(&expected), - "missing reason `{expected}` in {reasons:?}", - ); - } - assert!(reasons.iter().all(|reason| reason.starts_with("rust."))); -} - -#[test] -fn spans_are_sane_and_source_ordered() { - let analysis = analyze(FIXTURE, &AnalysisConfig::production()); - assert!(analysis.contributions.iter().all(|item| { - item.span.start_byte <= item.span.end_byte - && item.span.end_byte as usize <= FIXTURE.len() - && item.span.start_line >= 1 - && item.span.start_line <= item.span.end_line - })); - assert!(analysis.contributions.windows(2).all(|pair| { - (pair[0].span.start_byte, pair[0].span.end_byte) - <= (pair[1].span.start_byte, pair[1].span.end_byte) - })); -} - -#[test] -fn benchmark_profile_skips_evidence_without_changing_metrics() { - let production = analyze(FIXTURE, &AnalysisConfig::production()); - let benchmark = analyze(FIXTURE, &AnalysisConfig::benchmark()); - - assert!(!production.contributions.is_empty()); - assert!(benchmark.contributions.is_empty()); - for key in [ - "cyclomatic.sum", - "cognitive.sum", - "nexit.sum", - "abc", - "nom", - "nargs", - "npa", - "npm", - ] { - assert_eq!( - metric(&production, key), - metric(&benchmark, key), - "evidence collection must not change `{key}`", - ); - } -} diff --git a/crates/mehen-rust/tests/cyclomatic.rs b/crates/mehen-rust/tests/cyclomatic.rs deleted file mode 100644 index 3ff481d3..00000000 --- a/crates/mehen-rust/tests/cyclomatic.rs +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Cyclomatic complexity tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/cyclomatic.rs::tests` per -//! rewrite plan §12.3 (parity contract). Every pre-1.0 -//! `check_metrics::` Rust test is reproduced here against -//! the Phase 9 ra_ap_syntax-backed walker. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - // Match legacy `check_metrics`: trim trailing newlines and append one. - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_1_level_nesting() { - let a = analyze( - "fn f() { - if true { - match true { - true => println!(\"test\"), - false => println!(\"test\"), - } - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - insta::assert_json_snapshot!( - cy, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - }"### - ); -} - -#[test] -fn rust_macro_tokens_are_opaque_for_cyclomatic() { - let a = analyze( - "fn f() { - maybe!(a && b, if c { d() }); - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - // Unit (1) + function baseline (1) = 2. Macro body tokens (`&&`, - // `if`) do not count — they are not parsed Rust control flow. - assert_eq!(cy.sum, 2.0, "got {}", serde_json::to_string(&cy).unwrap()); -} diff --git a/crates/mehen-rust/tests/exit.rs b/crates/mehen-rust/tests/exit.rs deleted file mode 100644 index edd994e8..00000000 --- a/crates/mehen-rust/tests/exit.rs +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NExit tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/exit.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_no_exit() { - // Drift from pre-1.0: `average: null` for empty function buckets has - // become `0.0` in Phase-1+ accumulators (same convention as cognitive). - let a = analyze("let a = 42;"); - let nx = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nx, - @r###" - { - "sum": 0.0, - "average": 0.0, - "min": 0.0, - "max": 0.0 - }"### - ); -} - -#[test] -fn rust_question_mark() { - // Three `?` operators, all at the unit level (no functions). Each - // contributes +1 NExit. - let a = analyze("let _ = a? + b? + c?;"); - let nx = mehen_report::metrics_json::nexits(&a.root.metrics); - insta::assert_json_snapshot!( - nx, - @r###" - { - "sum": 3.0, - "average": 0.0, - "min": 3.0, - "max": 3.0 - }"### - ); -} - -#[test] -fn rust_return_type_is_not_an_exit() { - let a = analyze( - "fn typed() -> () {} - fn explicit() { - return; - } - fn question() { - a?; - }", - ); - let nx = mehen_report::metrics_json::nexits(&a.root.metrics); - assert_eq!(nx.sum, 2.0, "got {}", serde_json::to_string(&nx).unwrap()); - assert_eq!(nx.max, 1.0, "got {}", serde_json::to_string(&nx).unwrap()); -} diff --git a/crates/mehen-rust/tests/halstead.rs b/crates/mehen-rust/tests/halstead.rs deleted file mode 100644 index 1f406715..00000000 --- a/crates/mehen-rust/tests/halstead.rs +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Halstead tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/halstead.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_operators_and_operands() { - // Drift from pre-1.0: the legacy walker classified tokens via - // tree-sitter-rust's `Op` table; the Phase-9 ra_ap_syntax walker - // uses ra_ap_syntax's `T!` macro mapping. The token stream produced - // is similar but not identical at the boundary (e.g. `!` from a - // `println!` macro is its own token rather than fused into the - // path). We assert only on a *lower bound* of unique operators - // and operands plus the reported volume's order of magnitude — the - // exact `n1`/`n2` numbers depend on the lexer mapping and are - // documented in `docs/rust-ra-ap-syntax-spec.md` §4. - let a = analyze( - "fn main() { - let a = 5; let b = 5; let c = 5; - let avg = (a + b + c) / 3; - println!(\"{}\", avg); - }", - ); - let h = mehen_report::metrics_json::halstead(&a.root.metrics); - // Operators: `fn`, `let` (×4), `=` (×4), `+` (×2), `/`, `(`, ... - // Operands: `main`, `a`, `b`, `c`, `avg`, `5` (×3), `3`, `println`, - // `"{}"`. The unique-operand count must include at least the - // distinct identifiers and literal strings. - assert!( - h.n2 >= 7.0, - "expected n2 >= 7 (main, a, b, c, avg, number, string), got {}", - serde_json::to_string(&h).unwrap() - ); - assert!( - h.n1 >= 5.0, - "expected n1 >= 5 (fn, let, =, /, +, ...), got {}", - serde_json::to_string(&h).unwrap() - ); - assert!( - h.volume > 100.0, - "expected non-trivial volume, got {}", - serde_json::to_string(&h).unwrap() - ); -} - -/// Regression: nested function spaces must carry their own Halstead -/// counts in the per-space JSON. PR #95 discussion_r3265658502 flagged -/// this on the Python walker; the Rust walker had the same bug — -/// `observe_token` recorded every event onto `stack[0]` so inner -/// functions ended up with `halstead.N1 == halstead.N2 == 0`. -#[test] -fn rust_nested_function_halstead_is_non_zero() { - let a = analyze( - "fn outer() { - fn inner() { - let x = 1 + 2; - } - inner(); -}", - ); - assert_eq!(a.root.spaces.len(), 1, "expected outer fn"); - let outer = &a.root.spaces[0]; - assert_eq!(outer.name.as_deref(), Some("outer")); - assert_eq!(outer.spaces.len(), 1, "expected nested inner fn"); - let inner = &outer.spaces[0]; - assert_eq!(inner.name.as_deref(), Some("inner")); - - let inner_h = mehen_report::metrics_json::halstead(&inner.metrics); - assert!( - inner_h.big_n1 > 0.0, - "inner fn must record `let`, `=`, `+` operators, got {}", - serde_json::to_string(&inner_h).unwrap() - ); - assert!( - inner_h.big_n2 > 0.0, - "inner fn must record `x`, `1`, `2` operands, got {}", - serde_json::to_string(&inner_h).unwrap() - ); - assert!( - inner_h.volume > 0.0, - "inner fn volume must be > 0, got {}", - serde_json::to_string(&inner_h).unwrap() - ); - - let outer_h = mehen_report::metrics_json::halstead(&outer.metrics); - assert!( - outer_h.big_n1 >= inner_h.big_n1, - "outer fn N1 must roll up inner: outer={} inner={}", - serde_json::to_string(&outer_h).unwrap(), - serde_json::to_string(&inner_h).unwrap() - ); - assert!( - outer_h.big_n2 >= inner_h.big_n2, - "outer fn N2 must roll up inner: outer={} inner={}", - serde_json::to_string(&outer_h).unwrap(), - serde_json::to_string(&inner_h).unwrap() - ); -} diff --git a/crates/mehen-rust/tests/loc.rs b/crates/mehen-rust/tests/loc.rs deleted file mode 100644 index 8e4ce3d8..00000000 --- a/crates/mehen-rust/tests/loc.rs +++ /dev/null @@ -1,361 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! LOC tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/loc.rs::tests`. -//! -//! Legacy fixtures are top-level statements (`let a = ();`) that -//! tree-sitter-rust accepted as a permissive parse. ra_ap_syntax — -//! like rustc — requires every statement to live inside a function -//! body. Where a legacy fixture was a bare statement, the test below -//! wraps it in `fn _wrap() { … }` and asserts on the file-level -//! totals (sloc, ploc, lloc, cloc, blank) only — the per-space -//! min/max/avg fields shift because of the added function space. -//! This is the same correctness adjustment documented for Python in -//! `docs/python-ruff-spec.md` §3.5 (indentation correctness). - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// Wraps a statement-fragment fixture in `fn _wrap() { … }`. Used by -/// every test whose legacy fixture was a top-level statement. -fn analyze_wrapped(source: &str) -> mehen_core::LanguageAnalysis { - let mut wrapped = String::from("fn _wrap() {\n"); - wrapped.push_str(source.trim()); - wrapped.push_str("\n}\n"); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, wrapped); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_blank_simple() { - // A single `fn func() { /* comment */ }` produces `sloc = 1, ploc = 1, - // cloc = 1, lloc = 0`. Same as legacy file-totals. - let a = analyze("fn func() { /* comment */ }"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - (loc.sloc, loc.ploc, loc.cloc, loc.lloc, loc.blank), - (1.0, 1.0, 1.0, 0.0, 0.0), - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_no_zero_blank() { - // 11 sloc total, 8 ploc, 6 lloc, 4 cloc, 1 blank — same file totals - // as legacy. The per-space _min/_max differ because Phase-1+ - // accumulators handle blank lines per-space differently; this test - // asserts only on the file-level totals. - let a = analyze( - "fn ConnectToUpdateServer() { - let pool = 0; - - let updateServer = -42; - let isConnected = false; - let currTry = 0; - let numRetries = 10; // Number of IPC connection retries before - // giving up. - let numTries = 20; // Number of IPC connection tries before - // giving up. - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - (loc.sloc, loc.ploc, loc.cloc, loc.lloc, loc.blank), - (11.0, 8.0, 4.0, 6.0, 1.0), - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_cloc() { - // Wrap the legacy fixture (top-level let). Original totals: sloc=4, - // ploc=1, lloc=1, cloc=5. After wrap: sloc=6, ploc=3, lloc=1, cloc=5. - let a = analyze_wrapped( - "/*Block comment - Block Comment*/ - //Line Comment - /*Block Comment*/ let a = 42; // Line Comment", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.cloc, - 5.0, - "cloc still 5 (wrap adds no comments); got {}", - serde_json::to_string(&loc).unwrap() - ); - assert_eq!( - loc.lloc, - 1.0, - "let stmt still produces 1 LLOC; got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_lloc_for_if() { - // for loop + if + println! macro = 3 LLOC. - // Wrapped, total LLOC stays 3. - let a = analyze_wrapped( - "for x in 0..42 { - if x % 2 == 0 { - println!(\"{}\", x); - } - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 3.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_tail_expressions_are_lloc() { - // Tail expressions of fn bodies count as LLOC. 5 functions, each - // with a single-statement body → 5 LLOC at minimum. A nested - // `{ foo() }` adds one more = 6 LLOC. - // - // NOTE: this validates only the *total* — exact `lloc_max` per - // function depends on whether the inner `{ foo() }` is detected as - // a tail expression of `block_tail`. - let a = analyze( - "fn literal() -> i32 { - 42 - } - fn call() { - foo() - } - fn assign() { - x = y - } - fn compound_assign() { - x += y - } - fn block_tail() { - { foo() } - }", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert!( - loc.lloc >= 5.0, - "expected at least 5 LLOC (one per fn body's tail expr); got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_no_field_expression_lloc() { - // Wrapped: `let foo = Foo { 42 };` = 1 LLOC, `foo.field;` = 1 LLOC. - // Bare field access without semicolon would NOT count, but with `;` - // it's an EXPR_STMT (1 LLOC). - let a = analyze_wrapped( - "struct Foo { - field: usize, - } - let foo = Foo { 42 }; - foo.field;", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - // Even with the wrapper, the struct decl (top-level, lifted out) and - // the two stmts inside `_wrap` produce 2 LLOC. - assert!( - loc.lloc >= 2.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_no_parenthesized_expression_lloc() { - let a = analyze_wrapped("let a = (42 + 0);"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 1.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_no_array_expression_lloc() { - let a = analyze_wrapped("let a = [0; 42];"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 1.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_no_tuple_expression_lloc() { - let a = analyze_wrapped("let a = (0, 42);"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 1.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_no_unit_expression_lloc() { - let a = analyze_wrapped("let a = ();"); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 1.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_call_function_lloc() { - // 3 statements, each is an EXPR_STMT or LET_STMT. - let a = analyze_wrapped( - "let a = foo(); // +1 - foo(); // +1 - k!(foo()); // +1", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 3.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_macro_invocation_lloc() { - let a = analyze_wrapped( - "let a = foo!(); // +1 - foo!(); // +1 - k(foo!()); // +1", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 3.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_function_in_loop_lloc() { - let a = analyze_wrapped( - "for (a, b) in c.iter().enumerate() {} // +1 - while (a, b) in c.iter().enumerate() {} // +1 - while let Some(a) = c.strip_prefix(\"hi\") {} // +1", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - // Each loop is an EXPR_STMT. - assert!( - loc.lloc >= 3.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_function_in_if_lloc() { - let a = analyze_wrapped( - "if foo() {} // +1 - if let Some(a) = foo() {} // +1", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert!( - loc.lloc >= 2.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_function_in_return_lloc() { - // `return foo();` is an EXPR_STMT containing a return expression. - // `await foo();` is also an EXPR_STMT (await is a postfix expr). - let a = analyze_wrapped( - "return foo(); - await foo();", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - assert_eq!( - loc.lloc, - 2.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -#[test] -fn rust_closure_expression_lloc() { - // 3 outer statements + 1 closure body = 4 LLOC. - let a = analyze_wrapped( - "let a = |i: i32| -> i32 { i + 1 }; // +1 - a(42); // +1 - k(b.iter().map(|n| n.parse.ok().unwrap_or(42))); // +1", - ); - let loc = mehen_report::metrics_json::loc(&a.root.metrics); - // Body of the first closure (`i + 1`) is its tail expr — counts +1. - assert!( - loc.lloc >= 3.0, - "got {}", - serde_json::to_string(&loc).unwrap() - ); -} - -/// Regression: nested function spaces must carry their own -/// `loc.ploc` and `loc.cloc` in the per-space JSON. PR #95 -/// discussion_r3265962147 flagged that the post-AST token sweep -/// observed every code/comment line on `stack[0]`, leaving the -/// per-space `loc.ploc` at 0 even when the function body had -/// multiple code lines. -#[test] -fn rust_nested_function_loc_ploc_routes_to_active_space() { - let a = analyze( - "fn outer() { - // outer comment - fn inner() { - // inner comment - let x = 1 + 2; - let y = x * 3; - } - inner(); -}", - ); - assert_eq!(a.root.spaces.len(), 1); - let outer = &a.root.spaces[0]; - assert_eq!(outer.spaces.len(), 1); - let inner = &outer.spaces[0]; - let loc = mehen_report::metrics_json::loc(&inner.metrics); - assert!( - loc.ploc > 0.0, - "inner fn must record `let` lines as ploc, got {}", - serde_json::to_string(&loc).unwrap() - ); - assert!( - loc.cloc > 0.0, - "inner fn must record its `// inner comment` as cloc, got {}", - serde_json::to_string(&loc).unwrap() - ); -} diff --git a/crates/mehen-rust/tests/nargs.rs b/crates/mehen-rust/tests/nargs.rs deleted file mode 100644 index 77c744f7..00000000 --- a/crates/mehen-rust/tests/nargs.rs +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NArgs tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/nargs.rs::tests` per the -//! same `functions_min`/`closures_min` correction documented for -//! Python and PowerShell in Phase 6/7. Per-space `_min` is gated on -//! `is_function`/`is_closure`, so a unit space with no own arguments -//! no longer pollutes the rolled-up minimum to `0.0`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_no_functions_and_closures() { - let a = analyze("let a = 42;"); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 0.0, - "total_closures": 0.0, - "average_functions": 0.0, - "average_closures": 0.0, - "total": 0.0, - "average": 0.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn rust_single_function() { - let a = analyze( - "fn f(a: bool, b: usize) { - if a { - return a; - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 2.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 2.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn rust_single_closure() { - let a = analyze("let bar = |i: i32| -> i32 { i + 1 };"); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 0.0, - "total_closures": 1.0, - "average_functions": 0.0, - "average_closures": 1.0, - "total": 1.0, - "average": 1.0, - "functions_min": 0.0, - "functions_max": 0.0, - "closures_min": 1.0, - "closures_max": 1.0 - }"### - ); -} - -#[test] -fn rust_functions_two() { - let a = analyze( - "fn f(a: bool, b: usize) { - if a { - return a; - } - } - fn f1(a: bool, b: usize) { - if a { - return a; - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 4.0, - "total_closures": 0.0, - "average_functions": 2.0, - "average_closures": 0.0, - "total": 4.0, - "average": 2.0, - "functions_min": 2.0, - "functions_max": 2.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn rust_functions_uneven() { - let a = analyze( - "fn f(a: bool, b: usize) { - if a { - return a; - } - } - fn f1(a: bool, b: usize, c: usize) { - if a { - return a; - } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 5.0, - "total_closures": 0.0, - "average_functions": 2.5, - "average_closures": 0.0, - "total": 5.0, - "average": 2.5, - "functions_min": 2.0, - "functions_max": 3.0, - "closures_min": 0.0, - "closures_max": 0.0 - }"### - ); -} - -#[test] -fn rust_nested_functions() { - let a = analyze( - "fn f(a: i32, b: i32) -> i32 { - fn foo(a: i32) -> i32 { - return a; - } - let bar = |a: i32, b: i32| -> i32 { a + 1 }; - let bar1 = |b: i32| -> i32 { b + 1 }; - return bar(foo(a), a); - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nargs(&a.root.metrics), - @r###" - { - "total_functions": 3.0, - "total_closures": 3.0, - "average_functions": 1.5, - "average_closures": 1.5, - "total": 6.0, - "average": 1.5, - "functions_min": 1.0, - "functions_max": 2.0, - "closures_min": 1.0, - "closures_max": 2.0 - }"### - ); -} diff --git a/crates/mehen-rust/tests/nom.rs b/crates/mehen-rust/tests/nom.rs deleted file mode 100644 index 17f42231..00000000 --- a/crates/mehen-rust/tests/nom.rs +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NOM tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/nom.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_nom() { - // Drift from pre-1.0: `functions_min` was `0.0` in legacy because - // the unit's always-zero `nom.functions` was folded into the per- - // space min. Phase-9 NargsStats-mirroring NomStats gating preserves - // the `_min` only for spaces that actually open a function/closure. - let a = analyze( - "mod A { fn foo() {}} - mod B { fn foo() {}} - let closure = |i: i32| -> i32 { i + 42 };", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::nom(&a.root.metrics), - @r###" - { - "functions": 2.0, - "closures": 1.0, - "functions_average": 0.5, - "closures_average": 0.25, - "total": 3.0, - "average": 0.75, - "functions_min": 0.0, - "functions_max": 1.0, - "closures_min": 0.0, - "closures_max": 1.0 - }"### - ); -} diff --git a/crates/mehen-rust/tests/npa.rs b/crates/mehen-rust/tests/npa.rs deleted file mode 100644 index 72516266..00000000 --- a/crates/mehen-rust/tests/npa.rs +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPA tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/npa.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_npa_counts_struct_fields() { - // 2 fields, 1 public. - let a = analyze( - "struct S { - pub a: u32, - b: u32, - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::npa(&a.root.metrics), - @r###" - { - "classes": 1.0, - "interfaces": 0.0, - "class_attributes": 2.0, - "interface_attributes": 0.0, - "classes_average": 0.5, - "interfaces_average": null, - "total": 1.0, - "total_attributes": 2.0, - "average": 0.5 - }"### - ); -} - -#[test] -fn rust_npa_counts_tuple_struct_fields() { - // 2 positional fields, 1 public. - let a = analyze("struct S(pub u32, u32);"); - insta::assert_json_snapshot!( - mehen_report::metrics_json::npa(&a.root.metrics), - @r###" - { - "classes": 1.0, - "interfaces": 0.0, - "class_attributes": 2.0, - "interface_attributes": 0.0, - "classes_average": 0.5, - "interfaces_average": null, - "total": 1.0, - "total_attributes": 2.0, - "average": 0.5 - }"### - ); -} diff --git a/crates/mehen-rust/tests/npm.rs b/crates/mehen-rust/tests/npm.rs deleted file mode 100644 index d93cff2b..00000000 --- a/crates/mehen-rust/tests/npm.rs +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! NPM tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/npm.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_npm_counts_pub_in_impl_block() { - // impl S -> 2 methods, 1 public - let a = analyze( - "struct S; - impl S { - pub fn a(&self) {} - fn b(&self) {} - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::npm(&a.root.metrics), - @r###" - { - "classes": 1.0, - "interfaces": 0.0, - "class_methods": 2.0, - "interface_methods": 0.0, - "classes_average": 0.5, - "interfaces_average": null, - "total": 1.0, - "total_methods": 2.0, - "average": 0.5 - }"### - ); -} - -#[test] -fn rust_npm_counts_trait_signature_and_default_methods() { - // Drift from pre-1.0: the legacy NPM serialization used `interfaces` - // to mean "number of interface containers", and `interfaces_average` - // to mean `interface_methods / interfaces`. The Phase-1+ pipeline's - // NPM (in `mehen-metrics::counters::NpmStats::publish_npm`) re-uses - // those field names with different semantics: `interfaces` is now - // the total *public-method* count in interfaces, and - // `interfaces_average` is `public / total` (the public-ratio). This - // is a deliberate metric-definition change shared with the Python / - // TypeScript / PowerShell ports — every language's NPM follows the - // same `publish_npm` shape now. The Phase-9 ra_ap_syntax walker - // produces: - // - 2 public methods in this trait (both `a` and `b` are - // implicitly public; legacy rule "trait methods are public") - // - 2 total methods - // - public ratio = 2/2 = 1.0 - let a = analyze( - "trait T { - fn a(&self); - fn b(&self) {} - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::npm(&a.root.metrics), - @r###" - { - "classes": 0.0, - "interfaces": 2.0, - "class_methods": 0.0, - "interface_methods": 2.0, - "classes_average": null, - "interfaces_average": 1.0, - "total": 2.0, - "total_methods": 2.0, - "average": 1.0 - }"### - ); -} diff --git a/crates/mehen-rust/tests/parity.rs b/crates/mehen-rust/tests/parity.rs deleted file mode 100644 index 0bec69f8..00000000 --- a/crates/mehen-rust/tests/parity.rs +++ /dev/null @@ -1,286 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Parity / improvement snapshots for the ra_ap_syntax-backed Rust -//! analyzer. Each test reproduces a Rust syntactic construct where -//! ra_ap_syntax's typed AST gives a strictly better answer than the -//! legacy tree-sitter walker — proven from the metric definition, not -//! from a desire to mirror legacy behavior. -//! -//! See `docs/rust-ra-ap-syntax-spec.md` for the full design rationale. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -/// `let-else` (RFC 3137, stable in Rust 1.65) is still a `LET_STMT` in -/// ra_ap_syntax. The legacy tree-sitter grammar (0.24.x) parses it, -/// but its `let_declaration` arm only checks `is_child(EQ)` for the -/// "is an assignment?" test. ra_ap_syntax exposes the diverging else -/// branch directly via `LetStmt::let_else()`, and the divergent -/// branch's body becomes a new cognitive nesting frame the moment it -/// contains a control-flow expression. This test confirms the walker -/// emits +1 ABC.assignments for the bind and that the control-flow -/// inside the `else` branch participates normally. -#[test] -fn rust_let_else_is_assignment_with_diverging_else() { - let a = analyze( - "fn parse(input: &str) -> Result { - let Some(stripped) = input.strip_prefix(\"#\") else { - return Err(()); - }; - stripped.parse().map_err(|_| ()) - }", - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - assert!( - abc.assignments >= 1.0, - "let-else binding must count as an assignment, got {}", - serde_json::to_string(&abc).unwrap() - ); - let nx = mehen_report::metrics_json::nexits(&a.root.metrics); - // The `return Err(())` inside the let-else's diverging branch is a - // real exit point. - assert!( - nx.sum >= 1.0, - "let-else diverging branch's `return` must count as exit, got {}", - serde_json::to_string(&nx).unwrap() - ); -} - -/// `if let` chains (RFC 2497, stable in Rust 1.88). Multiple `if let -/// PAT = expr && let PAT = expr` are flattened into a single `IF_EXPR` -/// with a chain of `LetExpr` operands joined by `&&`. The legacy -/// tree-sitter walker exposed `let_chain` as a distinct named node. -/// ra_ap_syntax: each `&&` shows as a `BinExpr` with `LogicOp::And`, -/// and the boolean-sequence collapser in `mehen-metrics::cognitive` -/// folds the same-op run into a single +1. -#[test] -fn rust_if_let_chain_collapses_to_single_cognitive_bump() { - let a = analyze( - "fn f(a: Option, b: Option) -> Option { - if let Some(x) = a && let Some(y) = b && x > y { - Some(x + y) - } else { - None - } - }", - ); - let cog = mehen_report::metrics_json::cognitive(&a.root.metrics); - // +1 for the `if`, +1 for the same-op `&&` run (collapsed), +1 for - // the `else` keyword. Cognitive sum must be exactly 3. - assert_eq!( - cog.sum, - 3.0, - "if-let chain with `&&` must collapse to a single +1 + else, got {}", - serde_json::to_string(&cog).unwrap() - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - // 1 (unit) + 1 (function baseline) + 1 (if) + 2 (two `&&`) = 5 - assert_eq!( - cy.sum, - 5.0, - "expected 5 cyclomatic decisions, got {}", - serde_json::to_string(&cy).unwrap() - ); -} - -/// `?` operator (try-expression) inside a deeply-nested expression. -/// The legacy walker captured it via `try_expression` — ra_ap_syntax -/// surfaces the same node as `TRY_EXPR`. Two `?` in one expression -/// must each contribute +1 cyclomatic / +1 cognitive (no nesting) / -/// +1 nexit / +1 ABC.condition. -#[test] -fn rust_question_marks_in_chain_each_count() { - let a = analyze( - "fn f() -> Result { - let r = compute()?.lookup(key)?.parse::()?; - Ok(r) - }", - ); - let nx = mehen_report::metrics_json::nexits(&a.root.metrics); - assert!( - nx.sum >= 3.0, - "three `?` operators must yield 3 exits, got {}", - serde_json::to_string(&nx).unwrap() - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - // 1 (unit) + 1 (fn baseline) + 3 (three `?`) = 5 - assert!( - cy.sum >= 5.0, - "three `?` must each be a decision, got {}", - serde_json::to_string(&cy).unwrap() - ); -} - -/// Closures with explicit type annotations: `|x: i32, y: i32| -> i32`. -/// Legacy walker counted parameter parens / commas via the -/// `closure_parameters` named node. ra_ap_syntax exposes -/// `ClosureExpr::param_list()` directly with one `Param` per declared -/// parameter — argc is the AST-level parameter count, not a token -/// count. This test confirms the closure-arg count matches the AST. -#[test] -fn rust_typed_closure_records_correct_arg_count() { - let a = analyze( - "fn make() -> impl Fn(i32, i32, i32) -> i32 { - |x: i32, y: i32, z: i32| -> i32 { x + y + z } - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - assert_eq!( - nargs.total_closures, - 3.0, - "closure with 3 typed params must report 3 closure args, got {}", - serde_json::to_string(&nargs).unwrap() - ); - assert_eq!( - nargs.closures_max, - 3.0, - "closures_max must reflect the AST-level param count, got {}", - serde_json::to_string(&nargs).unwrap() - ); -} - -/// `async fn` is a `Fn` AST node with `async_token()` set. It still -/// opens a function space; nesting / depth follows the same rules. -#[test] -fn rust_async_fn_opens_function_space() { - let a = analyze( - "async fn fetch(url: &str) -> String { - let res = client.get(url).await; - res.text().await - }", - ); - let nargs = mehen_report::metrics_json::nargs(&a.root.metrics); - assert_eq!( - nargs.total_functions, - 1.0, - "async fn must count as a function, got {}", - serde_json::to_string(&nargs).unwrap() - ); - assert_eq!( - nargs.functions_min, - 1.0, - "async fn `fetch` has 1 param, functions_min must be 1, got {}", - serde_json::to_string(&nargs).unwrap() - ); -} - -/// Trait associated types (`type Item;`) and constants (`const N: u32;`) -/// must NOT count as methods. Only `Fn` items inside a Trait body -/// contribute to NPM. -#[test] -fn rust_trait_associated_types_and_consts_are_not_methods() { - let a = analyze( - "trait Iterator2 { - type Item; - const SIZE: usize = 4; - fn next(&mut self) -> Option; - fn count(&self) -> usize { 0 } - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - // 2 fns (next, count). type/const are not methods. - assert_eq!( - npm.interface_methods, - 2.0, - "associated type/const must not count as methods, got {}", - serde_json::to_string(&npm).unwrap() - ); -} - -/// Macro-call body opacity: `vec![1, if x { 2 } else { 3 }]` contains -/// an `if` inside macro tokens. Legacy walker correctly excluded -/// macro-internal control flow from cyclomatic / cognitive. The -/// ra_ap_syntax-backed walker preserves that — the `if` lives inside -/// a `MacroCall`'s token tree, which our walker marks opaque. -#[test] -fn rust_macro_body_control_flow_is_opaque() { - let a = analyze( - "fn f() { - let v = vec![1, if x { 2 } else { 3 }]; - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - // Unit (1) + fn baseline (1) = 2. Macro tokens add 0. - assert_eq!( - cy.sum, - 2.0, - "macro body's `if` must not contribute to cyclomatic, got {}", - serde_json::to_string(&cy).unwrap() - ); -} - -/// `match` arm guards (`Some(x) if x > 0 => …`) — the guard is a -/// boolean expression that runs after pattern matching succeeds. The -/// match arm itself contributes +1 cyclomatic; the guard's `>` adds -/// +1 ABC.condition (a comparison) but not extra cyclomatic in our -/// walker. Legacy did the same. -#[test] -fn rust_match_arm_guard_adds_condition_not_cyclomatic() { - let a = analyze( - "fn classify(x: Option) -> &'static str { - match x { - Some(n) if n > 0 => \"positive\", - Some(n) if n < 0 => \"negative\", - _ => \"zero or none\", - } - }", - ); - let cy = mehen_report::metrics_json::cyclomatic(&a.root.metrics); - // Unit (1) + fn baseline (1) + 3 match arms = 5 - assert_eq!( - cy.sum, - 5.0, - "3 match arms must give 3 cyclomatic decisions, got {}", - serde_json::to_string(&cy).unwrap() - ); - let abc = mehen_report::metrics_json::abc(&a.root.metrics); - // 3 match arms (each is +1 condition) + match expr itself (+1) + - // 2 comparison `>`/`<` (each +1) = 6 conditions minimum. - assert!( - abc.conditions >= 6.0, - "guards' comparisons must add ABC conditions, got {}", - serde_json::to_string(&abc).unwrap() - ); -} - -/// `pub(crate) fn` and `pub(super) fn` are both *non-default* -/// visibility modifiers. ra_ap_syntax's `HasVisibility::visibility()` -/// returns `Some(_)` for any `pub`/`pub(...)` form. Our walker -/// classifies any non-None visibility as public for NPM purposes — -/// which is what the legacy walker's "child is `visibility_modifier`" -/// check did too. -#[test] -fn rust_pub_crate_and_pub_super_count_as_public() { - let a = analyze( - "struct S; - impl S { - pub fn a(&self) {} - pub(crate) fn b(&self) {} - pub(super) fn c(&self) {} - fn d(&self) {} - }", - ); - let npm = mehen_report::metrics_json::npm(&a.root.metrics); - // 4 methods total. Public: a, b, c. Non-public: d. - assert_eq!( - npm.class_methods, - 4.0, - "got {}", - serde_json::to_string(&npm).unwrap() - ); - assert_eq!( - npm.classes, - 3.0, - "pub/pub(crate)/pub(super) all count as public, got {}", - serde_json::to_string(&npm).unwrap() - ); -} diff --git a/crates/mehen-rust/tests/wmc.rs b/crates/mehen-rust/tests/wmc.rs deleted file mode 100644 index c4dbfe0b..00000000 --- a/crates/mehen-rust/tests/wmc.rs +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! WMC tests, ported from -//! `crates/mehen-engine/src/legacy/metrics/wmc.rs::tests`. - -use mehen_core::{AnalysisConfig, Language, LanguageAnalyzer, SourceFile}; -use mehen_rust::RustAnalyzer; - -fn analyze(source: &str) -> mehen_core::LanguageAnalysis { - let mut text = source.trim_end().trim_matches('\n').to_string(); - text.push('\n'); - let analyzer = RustAnalyzer::new(); - let file = SourceFile::new("foo.rs".into(), Language::Rust, text); - analyzer.analyze(&file, &AnalysisConfig::default()).unwrap() -} - -#[test] -fn rust_wmc_impl_sums_function_cyclomatics() { - // impl S: a cyc=2 (if), b cyc=1 -> classes = 3 - let a = analyze( - "struct S; - impl S { - fn a(&self, x: bool) -> u32 { - if x { 1 } else { 0 } - } - fn b(&self) -> u32 { 1 } - }", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::wmc(&a.root.metrics), - @r###" - { - "classes": 3.0, - "interfaces": 0.0, - "total": 3.0 - }"### - ); -} - -#[test] -fn rust_wmc_empty_impl_still_emitted() { - let a = analyze( - "struct S; - impl S {}", - ); - insta::assert_json_snapshot!( - mehen_report::metrics_json::wmc(&a.root.metrics), - @r###" - { - "classes": 0.0, - "interfaces": 0.0, - "total": 0.0 - }"### - ); -} diff --git a/crates/mehen-sql/Cargo.toml b/crates/mehen-sql/Cargo.toml deleted file mode 100644 index 65486ea8..00000000 --- a/crates/mehen-sql/Cargo.toml +++ /dev/null @@ -1,57 +0,0 @@ -[package] -name = "mehen-sql" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -repository.workspace = true -license.workspace = true -description = "Mehen 1.0 — SQL language analyzer (internal)." -publish = false - -[dependencies] -mehen-core = { workspace = true } -smol_str = { workspace = true } - -# sqruff is the SQL parser backend (research: design-docs/sql_parser_comparison.md). -# Registry-pinned (`=X.Y.Z`, the oxc/mago pattern) rather than a git tag: -# sqruff publishes to crates.io, and Dependabot's cargo ecosystem only -# updates registry dependencies — the `sqruff-*` group in dependabot.yml -# never fired while these were git pins (ophi-dev/mehen#247). Both crates -# must stay in lockstep. It builds as a plain `cargo build` (no -# Python/codegen), exposes one dialect-agnostic `SyntaxKind` -# node model, and ships CTE/scope/wildcard analysis. We depend only on -# `lib-core` (lexer+parser+segment model+analysis utils) and `lib-dialects` -# (feature-gated dialect grammars) — never the heavier `lib` crate, so no -# Jinja templater plumbing or `pyo3` is pulled in. -sqruff-lib-core = "=0.40.0" -# `ansi` is always compiled by sqruff (not a feature gate) and is the -# inference fallback, so it is not listed here. `sparksql` transitively pulls -# in `hive`. We deliberately omit `duckdb` (its dialect is a thin layer over -# `postgres`, which we already ship). -sqruff-lib-dialects = { version = "=0.40.0", default-features = false, features = [ - "postgres", - "tsql", - "snowflake", - "bigquery", - "mysql", - "sqlite", - "oracle", - "clickhouse", - "redshift", - "sparksql", - "athena", - "db2", -] } - -[dev-dependencies] -insta = { workspace = true } -mehen-report = { workspace = true } -serde_json = { workspace = true } -# Same 0.x line as sqruff-lib-core's own strum: `DialectKind: EnumIter` -# comes from sqruff's derive, so the trait must resolve to the same crate -# version to be visible (used by the every-dialect parse-health test). -strum = "0.28" - -[lints] -workspace = true diff --git a/crates/mehen-sql/src/composite.rs b/crates/mehen-sql/src/composite.rs deleted file mode 100644 index f4d7e4a2..00000000 --- a/crates/mehen-sql/src/composite.rs +++ /dev/null @@ -1,313 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Composite scores (research foundation §8). -//! -//! Each score is a weighted, *explainable* combination of raw metrics. The -//! weights here mirror the research foundation's published formulas -//! (§8.1–§8.6) so the numbers can be cross-checked against the design doc. -//! Composites are review-prioritization signals, not absolute quality -//! judgments — the analyzer publishes the raw metrics first and these second. - -use crate::dialect::DialectResolution; -use crate::facts::{ChangeRiskFactor, SqlFileFacts}; -use crate::loc::SqlLoc; - -/// The six composite scores published per file. -#[derive(Clone, Copy, Debug, Default)] -pub(crate) struct CompositeScores { - pub structural_complexity: f64, - pub cognitive_complexity: f64, - pub change_risk_score: f64, - pub review_burden_index: f64, - pub maintainability_index: f64, - pub modularity_health: f64, -} - -/// `norm(x, t) = x / (x + t)` — the bounded normalizer used by the index -/// formulas (research foundation §8.3). Saturates toward 1 as `x` grows. -fn norm(x: f64, t: f64) -> f64 { - if x <= 0.0 { 0.0 } else { x / (x + t) } -} - -fn clamp01(x: f64) -> f64 { - x.clamp(0.0, 1.0) -} - -pub(crate) fn compute( - facts: &SqlFileFacts, - loc: &SqlLoc, - dialect: &DialectResolution, -) -> CompositeScores { - let structural_complexity = structural(facts); - let cognitive_complexity = cognitive(facts); - let change_risk_score = change_risk(facts); - let halstead_volume = halstead_volume(facts); - // The review-burden / maintainability formulas (§8.3/§8.5) weight a - // `sql.dialect.portability_risk_count` (count of features outside the - // ANSI/core profile). Phase 1 does not enumerate dialect-specific - // features, so we use the dialect-inference conflict count — how many - // dialect families' syntax hints fired — as a conservative proxy: a file - // that trips several dialects' markers is, by construction, less portable. - // Both terms carry only a 0.05 weight, so the approximation is bounded. - let portability_risk = dialect.conflict_count as f64; - - let review_burden_index = review_burden( - cognitive_complexity, - structural_complexity, - facts, - change_risk_score, - halstead_volume, - portability_risk, - loc, - ); - let maintainability_index = maintainability( - halstead_volume, - cognitive_complexity, - structural_complexity, - facts, - portability_risk, - ); - let modularity_health = modularity(facts); - - CompositeScores { - structural_complexity, - cognitive_complexity, - change_risk_score, - review_burden_index, - maintainability_index, - modularity_health, - } -} - -/// SQL Structural Complexity (research foundation §8.1). -fn structural(f: &SqlFileFacts) -> f64 { - 1.00 * f.query_block_count as f64 - + 0.80 * f.ctes.count as f64 - + 1.20 * f.ctes.max_dependency_depth as f64 - + 1.00 * f.joins.total as f64 - + 0.80 * (f.joins.left + f.joins.right + f.joins.full) as f64 - + 2.00 * f.joins.cross as f64 - + 1.50 * f.subqueries.count as f64 - + 1.25 * f.subqueries.max_depth as f64 - + 2.00 * f.subqueries.correlated_count as f64 - + 0.35 * f.predicates.boolean_operator_count as f64 - + 1.00 * f.predicates.max_boolean_depth as f64 - + 0.80 * f.cases.count as f64 - + 0.80 * f.cases.max_depth as f64 - + 0.60 * f.windows.function_count as f64 - + 0.35 * f.aggregates.function_count as f64 - + 1.00 * f.set_ops.count as f64 - + 0.50 * f.expressions.max_depth as f64 - + 0.50 * f.subqueries.derived_table_count as f64 -} - -/// SQL Cognitive Complexity (research foundation §8.2). -/// -/// Mirrors the spirit of code cognitive complexity but uses SQL-specific -/// mental contexts: each query block, nested-scope penalty, correlated -/// subquery, CTE edge, join, CASE level, boolean nesting, window, set op, -/// unaliased expression, and outer wildcard — minus a small modularization -/// credit for shallow, well-used CTEs. -fn cognitive(f: &SqlFileFacts) -> f64 { - let mut score = 0.0f64; - // 1. query blocks - score += f.query_block_count as f64; - // 2. subquery nesting depth - score += f.subqueries.max_depth as f64; - // 3. correlated subqueries - score += 2.0 * f.subqueries.correlated_count as f64; - // 4. CTEs + dependency edges beyond the first - score += f.ctes.count as f64; - score += f.ctes.dependency_edges.saturating_sub(1) as f64; - // 5. joins + extra weight for outer/cross/natural/lateral - score += f.joins.total as f64; - score += (f.joins.left - + f.joins.right - + f.joins.full - + f.joins.cross - + f.joins.natural - + f.joins.lateral) as f64; - // 6. CASE: +1 each, +1 per nesting level, +0.25 per WHEN beyond 2. The - // surplus-arm count is computed per-CASE in `extract_cases` so a - // many-armed CASE is not cancelled by single-armed ones. - score += f.cases.count as f64; - score += f.cases.max_depth.saturating_sub(1) as f64; - score += 0.25 * f.cases.surplus_when_arms as f64; - // 7. boolean operators + nesting beyond 2. - // §8.2 rule 7 also adds "+1 for mixed AND/OR chains without explicit - // grouping"; that term is omitted here because - // `sql.predicate.mixed_and_or_without_grouping_count` is not tracked in - // Phase 1 (would require precedence-aware predicate analysis). - score += 0.25 * f.predicates.boolean_operator_count as f64; - score += f.predicates.max_boolean_depth.saturating_sub(2) as f64; - // 8. window functions + frames - score += 0.5 * f.windows.function_count as f64; - score += f.windows.frame_count as f64; - // 9. set operations. - // §8.2 rule 9 also adds "+1 for nested set expressions"; that term is - // omitted because nested set-expression depth is not tracked in Phase 1. - score += 0.5 * f.set_ops.count as f64; - // 10. unaliased derived expressions - score += 0.25 * f.output.expression_without_alias_count as f64; - // 11. outer wildcards - score += 0.5 * f.output.outer_star_count as f64; - // 12. modularization credit, capped at -5, for shallow well-used CTEs - let credit = modularization_credit(f); - (score - credit).max(0.0) -} - -/// Small credit for CTEs that reduce nesting and have shallow dependency -/// depth (research foundation §8.2 rule 12). -fn modularization_credit(f: &SqlFileFacts) -> f64 { - if f.ctes.count == 0 { - return 0.0; - } - let used = f.ctes.count.saturating_sub(f.ctes.unused_count); - let shallow = f.ctes.max_dependency_depth <= 3; - let credit = if shallow { - used as f64 * 0.75 - } else { - used as f64 * 0.25 - }; - credit.min(5.0) -} - -/// SQL Change Risk Score (research foundation §8.4). -/// -/// Phase-1 deviation: the spec's `+ 5 * dynamic_sql_count` term is omitted -/// because dynamic SQL (`EXECUTE IMMEDIATE`, `sp_executesql`, …) is a -/// procedural-dialect construct not yet tracked (Phase 3). Every other term -/// matches the spec weights exactly. When dynamic-SQL detection lands, add the -/// `+ 5 * dynamic_sql_count` term here. -fn change_risk(f: &SqlFileFacts) -> f64 { - let o = &f.objects; - ChangeRiskFactor::Drop.amount() * o.drop_count as f64 - + ChangeRiskFactor::Truncate.amount() * o.truncate_count as f64 - + ChangeRiskFactor::Alter.amount() * o.alter_count as f64 - + ChangeRiskFactor::DeleteWithoutWhere.amount() * o.delete_without_where_count as f64 - + ChangeRiskFactor::UpdateWithoutWhere.amount() * o.update_without_where_count as f64 - + ChangeRiskFactor::GrantRevoke.amount() * o.grant_revoke_count as f64 - + ChangeRiskFactor::Merge.amount() * o.merge_count as f64 - + ChangeRiskFactor::CreateOrReplace.amount() * o.create_or_replace_count as f64 - + ChangeRiskFactor::TransactionControl.amount() * o.transaction_control_count as f64 - + ChangeRiskFactor::WriteObject.amount() * o.write_object_count as f64 - + ChangeRiskFactor::ReadObject.amount() * o.read_object_count as f64 -} - -/// SQL Review Burden Index (research foundation §8.3), 0..100. -#[allow(clippy::too_many_arguments)] -fn review_burden( - cognitive: f64, - structural: f64, - f: &SqlFileFacts, - change_risk: f64, - halstead_volume: f64, - portability_risk: f64, - loc: &SqlLoc, -) -> f64 { - // §8.3 weights `norm(sql.object.touch_count, 20)` — the count of *distinct* - // objects touched (read ∪ write), not the sum of the two counters (which - // would double-count an object that is both read and written). - let touch = f.objects.touch_count as f64; - let raw = 0.30 * norm(cognitive, 60.0) - + 0.18 * norm(structural, 80.0) - + 0.14 * norm(touch, 20.0) - + 0.12 * norm(change_risk, 25.0) - + 0.10 * norm(halstead_volume, 1500.0) - + 0.08 * norm(f.unparsable_segments as f64, 5.0) - + 0.05 * norm(portability_risk, 20.0) - + 0.05 * norm(loc.code as f64, 300.0) - - 0.02 * clamp01(loc.comment_density() / 0.20); - 100.0 * clamp01(raw) -} - -/// SQL Maintainability Index (research foundation §8.5), 0..100, higher is -/// better. -fn maintainability( - halstead_volume: f64, - cognitive: f64, - structural: f64, - f: &SqlFileFacts, - portability_risk: f64, -) -> f64 { - let risk = 0.22 * norm(halstead_volume, 1500.0) - + 0.22 * norm(cognitive, 60.0) - + 0.16 * norm(structural, 80.0) - + 0.12 * norm(f.predicates.boolean_operator_count as f64, 30.0) - + 0.10 * norm(f.ctes.max_dependency_depth as f64, 6.0) - + 0.08 * norm(f.subqueries.max_depth as f64, 4.0) - + 0.05 * norm(f.unparsable_segments as f64, 5.0) - + 0.05 * norm(portability_risk, 20.0); - 100.0 * clamp01(1.0 - risk) -} - -/// SQL Modularity Health (research foundation §8.6), 0..100. Only meaningful -/// for query-like files with CTEs/subqueries; returns 0 when no CTEs exist -/// (callers should treat that as N/A). -fn modularity(f: &SqlFileFacts) -> f64 { - if f.ctes.count == 0 { - return 0.0; - } - let cte_count = f.ctes.count as f64; - let used = f.ctes.count.saturating_sub(f.ctes.unused_count) as f64; - let cte_use_ratio = used / cte_count.max(1.0); - let cte_shallow_score = 1.0 - norm(f.ctes.max_dependency_depth as f64, 6.0); - let cte_fanout_score = 1.0 - norm(f.ctes.max_fan_out as f64, 8.0); - let derived_table_penalty = norm(f.subqueries.derived_table_count as f64, 5.0); - let trivial_cte_penalty = f.ctes.trivial_count as f64 / cte_count.max(1.0); - - let health = 0.35 * cte_use_ratio - + 0.25 * cte_shallow_score - + 0.15 * cte_fanout_score - + 0.15 * (1.0 - derived_table_penalty) - + 0.10 * (1.0 - trivial_cte_penalty); - 100.0 * clamp01(health) -} - -/// Recompute Halstead volume from facts (kept here so composites don't depend -/// on metric publishing order). Mirrors `metrics::publish_halstead`. -fn halstead_volume(f: &SqlFileFacts) -> f64 { - let h = &f.halstead; - let vocabulary = (h.distinct_operators + h.distinct_operands) as f64; - let length = (h.total_operators + h.total_operands) as f64; - if vocabulary > 0.0 { - length * vocabulary.log2() - } else { - 0.0 - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn norm_saturates() { - assert_eq!(norm(0.0, 10.0), 0.0); - assert!((norm(10.0, 10.0) - 0.5).abs() < 1e-9); - assert!(norm(1000.0, 10.0) > 0.9); - } - - #[test] - fn empty_facts_score_zero() { - let f = SqlFileFacts::default(); - let loc = SqlLoc::default(); - let d = DialectResolution { - requested: None, - directive: None, - inferred: sqruff_lib_core::dialects::init::DialectKind::Ansi, - effective: sqruff_lib_core::dialects::init::DialectKind::Ansi, - confidence: 30, - conflict_count: 0, - }; - let s = compute(&f, &loc, &d); - assert_eq!(s.structural_complexity, 0.0); - assert_eq!(s.cognitive_complexity, 0.0); - assert_eq!(s.change_risk_score, 0.0); - // No CTEs → modularity is N/A (0). - assert_eq!(s.modularity_health, 0.0); - // No risk → maintainability is at its max. - assert_eq!(s.maintainability_index, 100.0); - } -} diff --git a/crates/mehen-sql/src/dialect.rs b/crates/mehen-sql/src/dialect.rs deleted file mode 100644 index 3ee6af3e..00000000 --- a/crates/mehen-sql/src/dialect.rs +++ /dev/null @@ -1,731 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Dialect selection and conservative inference. -//! -//! A `.sql` suffix is ambiguous (research foundation §4.3): SonarQube treats -//! `.sql` as PL/SQL and `.tsql` as T-SQL, which silently misclassifies most -//! files. mehen instead resolves a dialect explicitly and exposes a -//! confidence so callers can tell a guessed dialect from a configured one. -//! -//! Resolution priority (research foundation §11.1): -//! 1. an in-file `-- sqlfluff:dialect:` directive (SQLFluff parity — -//! see [`parse_dialect_directive`]); -//! 2. an explicit request (CLI/config) — not yet surfaced in 1.0 since -//! `AnalysisConfig` carries no SQL options, so this is reserved; -//! 3. syntax-hint inference from the source text; -//! 4. conservative fallback to `ansi` with low confidence. -//! -//! Inference is intentionally cheap and advisory: a few high-signal token -//! probes, never a full pre-parse. When two dialect families both match we -//! lower confidence and record the conflict rather than pick arbitrarily. - -use std::str::FromStr; - -use sqruff_lib_core::dialects::init::DialectKind; - -/// An in-file `-- sqlfluff:dialect:` directive parsed from the source. -/// -/// SQLFluff lets a file pin its own dialect with a comment directive; sqruff -/// itself does not consume in-file config (and its config layer panics on -/// some inline forms), so mehen parses the directive manually and never feeds -/// it to sqruff's config path. See [`parse_dialect_directive`]. -#[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct DialectDirective { - /// The raw dialect name as written after the final colon (trimmed, verbatim - /// case). Kept for the diagnostic message. - pub name: String, - /// Resolution status of `name`. - pub status: DirectiveStatus, -} - -/// What happened when a directive's dialect name was resolved. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(crate) enum DirectiveStatus { - /// `name` resolved to a dialect that is compiled into this build; it drives - /// `effective` with full confidence. Carries the resolved kind. - Active(DialectKind), - /// `name` is a real sqruff dialect (its grammar is not compiled into this - /// build — e.g. `databricks`/`duckdb`/`trino`). Falls back to inference; - /// surfaced as a `sql.dialect.unsupported` warning. - Unsupported, - /// `name` is not a recognized sqruff dialect at all. Falls back to - /// inference; surfaced as a `sql.dialect.unknown` warning. - Unknown, -} - -/// The outcome of dialect resolution for one file. -#[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct DialectResolution { - /// Dialect explicitly requested by the caller (CLI/config), if any. 1.0 - /// surfaces no CLI option, so this is reserved; the in-file `directive` - /// is a separate, higher-priority source. - pub requested: Option, - /// The in-file `-- sqlfluff:dialect:` directive, if one was present. - pub directive: Option, - /// Best dialect inferred from syntax hints (always set — falls back to - /// `Ansi`). - pub inferred: DialectKind, - /// The dialect actually used for parsing. Priority: an active directive, - /// then `requested`, then `inferred`. - pub effective: DialectKind, - /// Confidence in `effective`, scaled 0..100 (stored as an integer so the - /// metric value is bit-exact across platforms). An active directive or a - /// caller request is authoritative and reports 100; a directive that names - /// an unknown/uncompiled dialect falls back to inference confidence. - pub confidence: u8, - /// Distinct dialect families whose hints fired. >1 signals ambiguity. - pub conflict_count: u8, -} - -/// Pure resolution without building/returning the grammar. `analyze` uses -/// [`resolve_with_dialect`] (which reuses the single grammar build); this thin -/// wrapper is convenient for tests and any caller that only needs the metric -/// surface. -#[cfg(test)] -pub(crate) fn resolve(source: &str, requested: Option) -> DialectResolution { - resolve_with_dialect(source, requested).0 -} - -/// Resolve the dialect for `source` and build its grammar in one step. -/// -/// Priority (research foundation §11.1; SQLFluff in-file directive parity): -/// 1. an *active* in-file `-- sqlfluff:dialect:` directive; -/// 2. an explicit caller request (CLI/config — reserved in 1.0); -/// 3. syntax-hint inference; -/// 4. conservative `ansi` fallback (inside `infer`). -/// -/// The effective grammar is built **exactly once** here so callers (`analyze`) -/// don't rebuild it. The build doubles as the compiled-in check: an uncompiled -/// directive/request grammar comes back `None`, which downgrades a directive to -/// [`DirectiveStatus::Unsupported`] and falls the effective dialect back to -/// inference (`ansi` is always compiled, so the returned `Dialect` is never -/// absent). -pub(crate) fn resolve_with_dialect( - source: &str, - requested: Option, -) -> (DialectResolution, sqruff_lib_core::dialects::Dialect) { - let inference = infer(source); - let mut directive = parse_dialect_directive(source); - - // Candidate priority: an active directive, then a caller request, then - // inference. We build the candidate grammar once; if it is not compiled in, - // we downgrade and retry with the next source. `ansi` (the inference floor) - // is always compiled, so the loop terminates with a real `Dialect`. - let directive_kind = match &directive { - Some(DialectDirective { - status: DirectiveStatus::Active(kind), - .. - }) => Some(*kind), - _ => None, - }; - - let mut effective = directive_kind.or(requested).unwrap_or(inference.kind); - let dialect = loop { - if let Some(d) = dialect_for_kind(effective) { - break d; - } - // `effective` is not compiled in. If it came from the directive, the - // directive is unsupported; record that and fall back. - if directive_kind == Some(effective) - && let Some(dir) = directive.as_mut() - { - dir.status = DirectiveStatus::Unsupported; - } - // Fall back to a caller request if it differs and is compiled, else to - // inference. - effective = match requested { - Some(req) if req != effective => req, - _ => inference.kind, - }; - }; - - // Authority is recomputed from the *final* effective source: a pin is - // authoritative only if `effective` still equals the (compiled) directive - // or caller request. This correctly keeps confidence 100 when an - // unsupported directive falls through to a compiled `requested` dialect, - // and drops it to inference confidence when both pins were dropped. - let directive_authoritative = directive_kind == Some(effective); - let request_authoritative = requested == Some(effective); - let confidence = if directive_authoritative || request_authoritative { - 100 - } else { - inference.confidence - }; - - let resolution = DialectResolution { - requested, - directive, - inferred: inference.kind, - effective, - confidence, - conflict_count: inference.conflict_count, - }; - (resolution, dialect) -} - -/// Parse an in-file `-- sqlfluff:dialect:` directive from `source`, -/// mirroring SQLFluff's `process_raw_file_for_config` / -/// `process_inline_config`. -/// -/// Fidelity notes (verified against SQLFluff `config.rs`): -/// * The gate is on the **raw** line: it must start with `-- sqlfluff` or -/// `--sqlfluff` (no leading-whitespace trim — an indented directive is -/// ignored, exactly as SQLFluff ignores it). A leading UTF-8 BOM on the -/// first line is stripped first (Rust's `trim`/`lines` keep it otherwise). -/// * After the gate, strip the leading `--`, trim, require a `sqlfluff:` -/// prefix, then take the remainder (`dialect:`). The config *key path* -/// must be exactly `dialect` (one segment): SQLFluff's -/// `split_colon_separated_string` parses `dialect:postgres:x` into the -/// two-segment key path `("dialect","postgres")` with value `x`, which is -/// **not** a dialect set — so a value that itself contains a further colon -/// (`dialect:postgres:x`, or the degenerate `dialect::`) is treated as -/// absent, not as an unknown dialect. -/// * The value is trimmed but **not** lowercased: SQLFluff dialect names are -/// case-sensitive, so `PostgreSQL` is reported as unknown (not silently -/// coerced). An empty value (`-- sqlfluff:dialect:`) is treated as no -/// directive, not an unknown dialect named "". -/// * Multiple directives → **last wins** (SQLFluff applies them in order). -/// * Only `--` line comments are honored; block comments -/// (`/* sqlfluff:... */`) and `#` comments are not (SQLFluff ignores them). -/// * Like SQLFluff, this is a raw-line scan, so a `-- sqlfluff:` pattern inside -/// a multi-line string literal would also match; this matches SQLFluff's own -/// behavior and is acceptable for an advisory directive. -pub(crate) fn parse_dialect_directive(source: &str) -> Option { - let mut last: Option = None; - for (i, raw_line) in source.lines().enumerate() { - // Strip a leading BOM only on the first physical line. - let line = if i == 0 { - raw_line.trim_start_matches('\u{feff}') - } else { - raw_line - }; - // Gate on the raw (un-left-trimmed) line, like SQLFluff. - if !(line.starts_with("-- sqlfluff") || line.starts_with("--sqlfluff")) { - continue; - } - // Strip the `--`, trim, require the `sqlfluff:` prefix. - let after_dashes = line[2..].trim(); - let Some(rest) = after_dashes.strip_prefix("sqlfluff:") else { - continue; - }; - // `rest` is e.g. `dialect:postgres`. Split on the FIRST colon into - // (key, value); only a single-segment `dialect` key is a dialect set. - let rest = rest.trim(); - let Some((key, value)) = rest.split_once(':') else { - continue; // `-- sqlfluff:dialect` (no value) — not a dialect set. - }; - if key.trim() != "dialect" { - continue; - } - let value = value.trim(); - // A further colon means SQLFluff would parse a multi-segment key path - // (`dialect:postgres:x` → key `("dialect","postgres")`), which is not a - // dialect set. The degenerate `dialect::` (value `":"`) lands here too. - if value.is_empty() || value.contains(':') { - continue; - } - last = Some(value.to_string()); - } - - last.map(|name| { - // Case-sensitive, matching SQLFluff: `DialectKind` derives strum - // `EnumString` with snake_case, so `from_str` accepts every dialect - // name verbatim. Compiled-vs-uncompiled (`Active` vs `Unsupported`) is - // decided later from the single grammar build, so this does not build. - let status = match DialectKind::from_str(&name) { - Ok(kind) => DirectiveStatus::Active(kind), - Err(_) => DirectiveStatus::Unknown, - }; - DialectDirective { name, status } - }) -} - -/// Build the sqruff grammar for `kind`, or `None` if that dialect is not -/// compiled into this build (`kind_to_dialect` returns `None` for an -/// uncompiled dialect — it never panics). This is the authoritative -/// compiled-in check **and** the single grammar build per effective dialect. -pub(crate) fn dialect_for_kind(kind: DialectKind) -> Option { - sqruff_lib_dialects::kind_to_dialect(&kind, None) -} - -struct Inference { - kind: DialectKind, - confidence: u8, - conflict_count: u8, -} - -/// Map of dialect family → a count of how many of its hint tokens fired. -/// Inference picks the family with the most hits; ties or a single weak hit -/// keep confidence low and fall back to `ansi`. -/// -/// Replace comment and string-literal *content* with spaces so the dialect -/// inference scan only sees code. Handles `-- line` and `# line` comments, -/// `/* block */` comments, and single-quoted string literals (with `''` -/// escaping). Lengths are preserved (content → spaces) so this stays a cheap -/// single pass and never needs to reallocate token boundaries. This is an -/// advisory pre-scan, not a lexer; it does not need to model dollar-quoting or -/// every dialect's quote rules — only to keep the common comment/literal -/// false-positives out of the hint count. -fn strip_noncode(source: &str) -> String { - let bytes = source.as_bytes(); - let mut out = String::with_capacity(source.len()); - let mut i = 0; - while i < bytes.len() { - let b = bytes[i]; - let next = bytes.get(i + 1).copied(); - if b == b'-' && next == Some(b'-') { - // Line comment to end of line. - while i < bytes.len() && bytes[i] != b'\n' { - out.push(' '); - i += 1; - } - } else if b == b'#' && matches!(next, None | Some(b' ' | b'\t' | b'\r' | b'\n')) { - // MySQL-style line comment — but only when `#` stands alone - // (followed by whitespace/EOL). `#tmp` / `##global` are T-SQL - // temp-table identifiers, NOT comments, so they must stay as code - // and not swallow later dialect hints on the line (CodeRabbit). - while i < bytes.len() && bytes[i] != b'\n' { - out.push(' '); - i += 1; - } - } else if b == b'/' && next == Some(b'*') { - // Block comment through the matching `*/` (or EOF). - out.push(' '); - out.push(' '); - i += 2; - while i < bytes.len() && !(bytes[i] == b'*' && bytes.get(i + 1) == Some(&b'/')) { - out.push(if bytes[i] == b'\n' { '\n' } else { ' ' }); - i += 1; - } - if i < bytes.len() { - out.push(' '); - out.push(' '); - i += 2; - } - } else if b == b'\'' { - // Single-quoted string literal; `''` is an escaped quote. - out.push(' '); - i += 1; - while i < bytes.len() { - if bytes[i] == b'\'' { - if bytes.get(i + 1) == Some(&b'\'') { - out.push(' '); - out.push(' '); - i += 2; - continue; - } - out.push(' '); - i += 1; - break; - } - out.push(if bytes[i] == b'\n' { '\n' } else { ' ' }); - i += 1; - } - } else { - // A non-ASCII byte is part of a multibyte UTF-8 sequence; copy the - // whole char so `out` stays valid UTF-8. - let ch_len = utf8_len(b); - out.push_str(&source[i..i + ch_len]); - i += ch_len; - } - } - out -} - -/// Byte length of the UTF-8 char starting with lead byte `b`. -fn utf8_len(b: u8) -> usize { - if b < 0x80 { - 1 - } else if b >> 5 == 0b110 { - 2 - } else if b >> 4 == 0b1110 { - 3 - } else { - 4 - } -} - -fn infer(source: &str) -> Inference { - // Inference scans for dialect-specific *code* tokens, so comments and - // string-literal bodies are stripped first: a hint token mentioned in a - // comment (`-- TODO: QUALIFY this`) or inside a literal (`'… NVARCHAR …'`) - // must not flip the effective parser dialect (Codex P2). Identifiers can - // still false-positive, but that only nudges an advisory confidence — the - // parse itself uses the resolved grammar. - // Normalize CRLF → LF so newline-anchored hints (the T-SQL `GO` batch - // separator) match on Windows-line-ending files too (Codex P2). - let code = strip_noncode(source).replace("\r\n", "\n"); - let upper = code.to_ascii_uppercase(); - let has = |needle: &str| upper.contains(needle); - - // Each family lists high-signal hints (research foundation §11.2). - let tsql = count(&[ - has("\nGO\n") || upper.starts_with("GO\n") || upper.ends_with("\nGO"), - has("CROSS APPLY") || has("OUTER APPLY"), - has("[") && has("]"), // bracket-quoted identifiers - has("ISNULL(") || has("NVARCHAR") || has("DATETIME2"), - has("SELECT TOP ") || has("SELECT TOP("), - ]); - let snowflake = count(&[ - has("QUALIFY "), - has("IFF("), - has("COPY INTO "), - has(":: VARIANT") || has("::VARIANT") || has(" VARIANT"), - has("LATERAL FLATTEN"), - ]); - let postgres = count(&[ - has("::"), - has("DISTINCT ON"), - has(" ILIKE "), - // `RETURNING` followed by any whitespace (so `RETURNING\nid` is matched, - // not just `RETURNING id`). - has("RETURNING ") || has("RETURNING\n") || has("RETURNING\t") || has("RETURNING\r"), - has("ARRAY["), - ]); - let bigquery = count(&[ - has("`"), // backtick identifiers - has(" STRUCT<") || has(" STRUCT("), - has("UNNEST("), - has("ARRAY<"), - has("SAFE_CAST("), - ]); - let oracle = count(&[ - has("CONNECT BY"), - has(" MINUS "), - has("NVL(") || has("NVL2("), - has(" DUAL"), - has("VARCHAR2"), - ]); - let mysql = count(&[ - has("ENGINE=") || has("ENGINE ="), - has("AUTO_INCREMENT"), - has("`") && has("ENGINE"), - has("UNSIGNED"), - has("LIMIT ") && has("OFFSET "), - ]); - - let scored = [ - (DialectKind::Tsql, tsql), - (DialectKind::Snowflake, snowflake), - (DialectKind::Postgres, postgres), - (DialectKind::Bigquery, bigquery), - (DialectKind::Oracle, oracle), - (DialectKind::Mysql, mysql), - ]; - - let conflict_count = scored.iter().filter(|(_, n)| *n > 0).count() as u8; - let best = scored - .iter() - .filter(|(_, n)| *n > 0) - .max_by_key(|(_, n)| *n); - - match best { - // A single dominant family with ≥2 hits is a confident guess. One hit - // is weak; we still pick the family but cap confidence low so callers - // treat it as a hint, not a decision. - Some((kind, hits)) => { - let runner_up_tie = scored - .iter() - .filter(|(k, n)| *k != *kind && *n == *hits) - .count() - > 0; - let confidence = if runner_up_tie { - 40 - } else if *hits >= 3 { - 90 - } else if *hits == 2 { - 70 - } else { - 45 - }; - Inference { - kind: *kind, - confidence, - conflict_count, - } - } - // No hints at all: ANSI is the safe, dialect-neutral default. Confidence - // is deliberately low because "looks like generic SQL" is itself a weak - // signal, not a guarantee the file is ANSI-only. - None => Inference { - kind: DialectKind::Ansi, - confidence: 30, - conflict_count: 0, - }, - } -} - -fn count(flags: &[bool]) -> u32 { - flags.iter().filter(|b| **b).count() as u32 -} - -/// Stable lowercase label for a dialect (matches sqruff's snake_case names). -pub(crate) fn dialect_label(kind: DialectKind) -> &'static str { - match kind { - DialectKind::Ansi => "ansi", - DialectKind::Athena => "athena", - DialectKind::Bigquery => "bigquery", - DialectKind::Clickhouse => "clickhouse", - DialectKind::Databricks => "databricks", - DialectKind::Db2 => "db2", - DialectKind::Duckdb => "duckdb", - DialectKind::Exasol => "exasol", - DialectKind::Greenplum => "greenplum", - DialectKind::Hive => "hive", - DialectKind::Materialize => "materialize", - DialectKind::Mysql => "mysql", - DialectKind::Oracle => "oracle", - DialectKind::Postgres => "postgres", - DialectKind::Redshift => "redshift", - DialectKind::Snowflake => "snowflake", - DialectKind::Sparksql => "sparksql", - DialectKind::Sqlite => "sqlite", - DialectKind::Starrocks => "starrocks", - DialectKind::Teradata => "teradata", - DialectKind::Trino => "trino", - DialectKind::Tsql => "tsql", - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn infers_tsql_from_apply_and_brackets() { - let r = resolve( - "SELECT TOP 10 * FROM [dbo].[t] CROSS APPLY fn(t.id) AS x", - None, - ); - assert_eq!(r.inferred, DialectKind::Tsql); - assert!(r.confidence >= 70, "confidence was {}", r.confidence); - } - - #[test] - fn infers_snowflake_from_qualify() { - let r = resolve( - "SELECT a, IFF(b > 0, 1, 0) FROM t QUALIFY ROW_NUMBER() OVER (ORDER BY a) = 1", - None, - ); - assert_eq!(r.inferred, DialectKind::Snowflake); - } - - #[test] - fn requested_dialect_is_authoritative() { - let r = resolve("SELECT 1", Some(DialectKind::Postgres)); - assert_eq!(r.effective, DialectKind::Postgres); - assert_eq!(r.confidence, 100); - } - - #[test] - fn plain_sql_falls_back_to_ansi_low_confidence() { - let r = resolve("SELECT a, b FROM t WHERE a = 1", None); - assert_eq!(r.inferred, DialectKind::Ansi); - assert!(r.confidence <= 45); - } - - // ── in-file directive (`-- sqlfluff:dialect:`) ────────────────── - - fn directive(source: &str) -> Option { - parse_dialect_directive(source) - } - - #[test] - fn go_batch_separator_infers_tsql_on_crlf() { - // The `GO` batch separator is a strong T-SQL hint; it must match on - // Windows (CRLF) line endings too, not just LF (Codex P2). - let crlf = resolve("SELECT 1\r\nGO\r\nSELECT 2\r\n", None); - assert_eq!(crlf.inferred, DialectKind::Tsql); - let lf = resolve("SELECT 1\nGO\nSELECT 2\n", None); - assert_eq!(lf.inferred, DialectKind::Tsql); - } - - #[test] - fn hash_temp_table_is_not_a_comment_for_inference() { - // `#tmp` / `##global` are T-SQL temp tables, NOT `#` comments — they - // must not swallow later dialect hints on the line (CodeRabbit). The - // `CROSS APPLY` hint after `#tmp` must still infer T-SQL. - let r = resolve( - "SELECT * INTO #tmp FROM t CROSS APPLY dbo.fn(t.id) AS x", - None, - ); - assert_eq!(r.effective, DialectKind::Tsql); - // A standalone `# ` comment IS still stripped (MySQL style): a hint - // only inside it does not drive inference. - let commented = resolve("# QUALIFY note\nSELECT a FROM t", None); - assert_eq!(commented.effective, DialectKind::Ansi); - } - - #[test] - fn directive_active_compiled_dialect_drives_effective() { - let r = resolve("-- sqlfluff:dialect:postgres\nSELECT 1", None); - assert_eq!(r.effective, DialectKind::Postgres); - assert_eq!(r.confidence, 100); - assert!(matches!( - r.directive.unwrap().status, - DirectiveStatus::Active(DialectKind::Postgres) - )); - } - - #[test] - fn directive_accepts_both_dash_forms_and_colon_whitespace() { - // `--sqlfluff` (no space) and whitespace around the value both work. - assert!(matches!( - directive("--sqlfluff:dialect:tsql\nSELECT 1") - .unwrap() - .status, - DirectiveStatus::Active(DialectKind::Tsql) - )); - assert!(matches!( - directive("-- sqlfluff:dialect: mysql \nSELECT 1") - .unwrap() - .status, - DirectiveStatus::Active(DialectKind::Mysql) - )); - } - - #[test] - fn directive_recognized_but_uncompiled_is_unsupported_and_does_not_pin() { - // `duckdb` is a real sqruff dialect but not compiled into this build. - let r = resolve("-- sqlfluff:dialect:duckdb\nSELECT 1", None); - assert_eq!( - r.directive.as_ref().unwrap().status, - DirectiveStatus::Unsupported - ); - // Falls back to inference, NOT confidence 100. - assert_eq!(r.effective, r.inferred); - assert_ne!(r.confidence, 100); - } - - #[test] - fn directive_unknown_name_is_unknown_and_falls_back() { - let r = resolve("-- sqlfluff:dialect:nope\nSELECT 1", None); - assert_eq!( - r.directive.as_ref().unwrap().status, - DirectiveStatus::Unknown - ); - assert_eq!(r.effective, r.inferred); - assert_ne!(r.confidence, 100); - } - - #[test] - fn directive_is_case_sensitive_like_sqlfluff() { - // SQLFluff dialect names are case-sensitive; `Postgres` is unknown. - let r = resolve("-- sqlfluff:dialect:Postgres\nSELECT 1", None); - assert_eq!(r.directive.unwrap().status, DirectiveStatus::Unknown); - } - - #[test] - fn directive_last_one_wins() { - let r = resolve( - "-- sqlfluff:dialect:mysql\n-- sqlfluff:dialect:postgres\nSELECT 1", - None, - ); - assert_eq!(r.effective, DialectKind::Postgres); - } - - #[test] - fn directive_ignores_block_comments_and_hash_comments() { - assert!(directive("/* sqlfluff:dialect:postgres */\nSELECT 1").is_none()); - assert!(directive("# sqlfluff:dialect:postgres\nSELECT 1").is_none()); - } - - #[test] - fn directive_ignores_indented_and_empty_and_keyless_forms() { - // Indented directive: SQLFluff gates on the raw (un-trimmed) line. - assert!(directive(" -- sqlfluff:dialect:postgres\nSELECT 1").is_none()); - // Empty value is treated as no directive, not unknown-dialect "". - assert!(directive("-- sqlfluff:dialect:\nSELECT 1").is_none()); - // Missing the value colon entirely. - assert!(directive("-- sqlfluff:dialect\nSELECT 1").is_none()); - // A non-dialect sqlfluff key is not a dialect directive. - assert!(directive("-- sqlfluff:rules:LT01\nSELECT 1").is_none()); - } - - #[test] - fn directive_multi_segment_key_is_not_a_dialect_set() { - // SQLFluff parses `dialect:postgres:x` into the two-segment key path - // ("dialect","postgres") with value "x" — NOT a dialect set. mehen must - // treat it as absent (no spurious `unknown` warning), not pin/reject. - assert!(directive("-- sqlfluff:dialect:postgres:x\nSELECT 1").is_none()); - // The degenerate double-trailing-colon is likewise absent, not a - // directive named ":". - assert!(directive("-- sqlfluff:dialect::\nSELECT 1").is_none()); - } - - #[test] - fn requested_uncompiled_dialect_is_not_authoritative() { - // A caller request for an uncompiled dialect must not report confidence - // 100 while parsing silently falls back — mirror the directive gate. - // (`Databricks` is recognized by sqruff but not compiled into mehen.) - let r = resolve("SELECT 1", Some(DialectKind::Databricks)); - assert_ne!(r.effective, DialectKind::Databricks); - assert_ne!(r.confidence, 100); - // A compiled request stays authoritative. - let ok = resolve("SELECT 1", Some(DialectKind::Postgres)); - assert_eq!(ok.effective, DialectKind::Postgres); - assert_eq!(ok.confidence, 100); - } - - #[test] - fn unsupported_directive_falls_through_to_compiled_request_authoritatively() { - // An unsupported directive (`duckdb`) falling through to a *compiled* - // caller request must keep confidence 100 — authority is recomputed - // from the final effective source, not cleared on the first fallback. - let r = resolve( - "-- sqlfluff:dialect:duckdb\nSELECT 1", - Some(DialectKind::Postgres), - ); - assert_eq!(r.effective, DialectKind::Postgres); - assert_eq!(r.confidence, 100); - assert_eq!(r.directive.unwrap().status, DirectiveStatus::Unsupported); - } - - #[test] - fn directive_trailing_content_is_part_of_the_value_and_unknown() { - // SQLFluff does NOT strip a trailing inline comment; the value becomes - // `postgres -- x`, which is not a known dialect. - let r = resolve("-- sqlfluff:dialect:postgres -- x\nSELECT 1", None); - assert_eq!(r.directive.unwrap().status, DirectiveStatus::Unknown); - } - - #[test] - fn directive_handles_crlf_and_leading_bom() { - // CRLF: `.lines()` strips the trailing `\r`, so the value is clean. - let r = resolve("-- sqlfluff:dialect:postgres\r\nSELECT 1\r\n", None); - assert_eq!(r.effective, DialectKind::Postgres); - // UTF-8 BOM on the first line must not block the prefix gate. - let r = resolve("\u{feff}-- sqlfluff:dialect:sqlite\nSELECT 1", None); - assert_eq!(r.effective, DialectKind::Sqlite); - } - - #[test] - fn directive_every_recognized_name_round_trips_via_from_str() { - // Each compiled dialect's snake_case label is a valid directive value - // that resolves to Active(kind) — guards the from_str/label contract. - for (name, kind) in [ - ("ansi", DialectKind::Ansi), - ("postgres", DialectKind::Postgres), - ("tsql", DialectKind::Tsql), - ("snowflake", DialectKind::Snowflake), - ("bigquery", DialectKind::Bigquery), - ("mysql", DialectKind::Mysql), - ("sqlite", DialectKind::Sqlite), - ("oracle", DialectKind::Oracle), - ("clickhouse", DialectKind::Clickhouse), - ("redshift", DialectKind::Redshift), - ("sparksql", DialectKind::Sparksql), - ("athena", DialectKind::Athena), - ("db2", DialectKind::Db2), - ] { - let src = format!("-- sqlfluff:dialect:{name}\nSELECT 1"); - let r = resolve(&src, None); - assert_eq!( - r.directive.unwrap().status, - DirectiveStatus::Active(kind), - "name {name} should be active {kind:?}", - ); - } - } -} diff --git a/crates/mehen-sql/src/facts.rs b/crates/mehen-sql/src/facts.rs deleted file mode 100644 index 0b907c06..00000000 --- a/crates/mehen-sql/src/facts.rs +++ /dev/null @@ -1,2750 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -// Copyright (C) 2026 Konstantin Vyatkin - -//! Parser-neutral SQL fact model and the sqruff → facts adapter. -//! -//! This module is the single seam between sqruff's `SyntaxKind` CST and the -//! mehen metric layer (research foundation §2, §5; parser comparison §6 -//! "adapter seam"). Every metric reads [`SqlFileFacts`] — owned, `Send`, -//! `'static` data — and never touches an `ErasedSegment`. That keeps sqruff's -//! `Rc`-based (non-`Send`) tree and its `0.x` API surface confined to the one -//! `extract` call, so a sqruff bump can only break this file. -//! -//! The walk is a single recursive descent that classifies nodes by -//! `SyntaxKind` and records facts. The CTE dependency graph is re-derived from -//! the `CommonTableExpression` CST nodes rather than using sqruff's -//! `Query`/`crawl_sources` model, which relies on interior mutability -//! (`Rc>`) that would conflict with borrows held across the call -//! (see [`extract_cte_graph`]). - -use mehen_core::SourceSpan; -use sqruff_lib_core::dialects::Dialect; -use sqruff_lib_core::dialects::syntax::{SyntaxKind, SyntaxSet}; -use sqruff_lib_core::parser::segments::ErasedSegment; - -/// Normalized statement kind (research foundation §5.2). Mapped from the -/// concrete sqruff statement node kinds so metrics classify DDL/DML/DCL/TCL -/// without knowing sqruff's per-dialect variant spellings. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub(crate) enum StatementKind { - Select, - WithSelect, - Insert, - Update, - Delete, - Merge, - CreateView, - CreateTable, - CreateTableAsSelect, - CreateOther, - AlterTable, - Drop, - Truncate, - Grant, - Revoke, - TransactionControl, - Explain, - Procedural, - SetOperation, - Unknown, -} - -impl StatementKind { - /// Every variant, for catalogue validation of the - /// `sql.statement.kind_count.
… - -> Generated by [mehen](https://github.com/ophidiarium/mehen) — the code quality watcher. -``` - -The section is emitted only when at least one Markdown file is present in the PR diff (added, modified, or renamed). It is suppressed entirely — not rendered empty — when no Markdown changed, so the comment stays compact on code-only PRs. - -### 39.2 Headline table — columns - -Reviewers skim. The headline table carries five columns, chosen so that each row exposes one signal per structural dimension without duplication: - -| Column | Source §§ | Why it's in the headline | -|---|---|---| -| **DMI** (0–100) | §10 | Single overall maintainability score; reviewer's first glance. | -| **Words** | §4 (W) | Size sanity; catches bulk additions that other signals may normalize away. | -| **FKGL** (English) or **Tateishi RS** (Japanese) | §31.2, §35.1 | The most recognizable readability number for the dominant language. | -| **Link Debt** (0–1) | §11.2 | Objective defects (broken/unresolved links) — hard to argue with. | -| **Filler Risk** (0–1) | §17 | AI-era flag; catches "big but vacuous" regressions. | - -Rationale for the omissions: RCI, MCC, MRPC, WQS, Evidence Coverage, and Grounding all matter but are second-glance signals. They live in the `
` drill-down (§39.6). The research doc (§28) treats DMI and RCI as the headline axes; RCI is demoted here because reviewers already know a PR is worth reviewing (they are reading it), while DMI's trend is more actionable as a delta. - -If the document is Japanese-dominant (§30), the third column header flips to **Tateishi RS** and the value uses the simplified formula from §35.1. Mixed-language docs report the dominant-language score and mark the file with a 🌏 suffix. - -### 39.3 Cell format - -Every cell follows one of four canonical shapes. No other shapes are allowed; if none fits, the cell is empty `—`. - -| Shape | Example | Meaning | -|---|---|---| -| `new (main: old) indicator` | `74 (main: 71) 🟢` | Modified file: before/after + delta category | -| `value 🆕` | `58 🆕` | New file: no "main" baseline exists | -| `value ⚪` | `0 ⚪` | Deleted metric or undefined for this file type | -| `— footnote-mark` | `— ²` | Suppressed by guard (e.g., short-doc for FKGL); footnote explains | - -Numbers are always rendered with fixed precision per column so columns align visually: -- DMI, RCI: integer -- Words, sentence counts, diagram/table/link counts: integer with thousands separators -- Ratios and scores (0–1): 2 decimal places -- FKGL, Fog, ARI, Tateishi RS: 1 decimal place - -### 39.4 Delta indicator rules - -Every indicator is a pure function of `(old, new, thresholds)` with no inference. The rules below are normative; implementations must match them exactly. - -```text -🟢 improvement: delta crosses a band boundary in the "better" direction - OR |delta| ≥ noticeable_threshold in the "better" direction -🔴 regression: delta crosses a band boundary in the "worse" direction - OR |delta| ≥ noticeable_threshold in the "worse" direction -⚠️ attention: value is in a "warn" or worse band AND did not improve - (used even when delta is zero — the state matters) -🆕 new: file is new in the PR; no "main" value exists -⚪ unchanged: none of the above applies -``` - -Per-metric band boundaries and noticeable thresholds: - -| Metric | Direction | Band source | `noticeable_threshold` | -|---|---|---|---| -| DMI | ↑ better | §10.4 (85/70/50/30) | 3 points | -| RCI | — informational | §18.2 | never emits 🟢/🔴 by itself | -| FKGL | profile-specific target | §31.13 | 0.5 grade | -| Tateishi RS | ↑ better | §35.1 (centered at 50) | 2 points | -| Fog | profile-specific target | §31.13 | 0.5 grade | -| Link Debt | ↓ better | §11.2 (0/0.2/0.5/1) | 0.05 OR any new broken link | -| Filler Risk | ↓ better | §17.10 (0.2/0.4/0.6/0.8) | 0.05; ⚠️ when ≥ 0.60 regardless of delta | -| Evidence Coverage | ↑ better | §16.4 | 0.05 | -| MCC | ↓ better | §8.5 | 5 points OR band crossing | -| MRPC | profile-specific | §7.4 | 3 points AND profile-exceeded | -| Passive ratio | profile target | §31.13, §33.1 | 0.05 absolute | -| Long-sentence count | ↓ better | §33.10 thresholds | any new instance is 🔴 | -| Inclusive-language flags | ↓ better | §33.12 | any new flag is 🔴 | -| Repository Grounding | ↑ better | §15.3 | 0.05 | -| Jukugo / kanji-run warnings (JA) | profile target | §36.6 | any new violation is 🔴 | - -Rationale for "any new broken link / long sentence / inclusive-language flag is 🔴": these are objective defects (§11, §33) that reviewers should always see, irrespective of ratio deltas. - -The word count never emits 🟢 or 🔴 — it is informational only. Size changes are context for other deltas, not a quality signal. - -### 39.5 Callout block — ranking, cap, and template catalog - -The callout block is the most valuable part of the section: it tells reviewers *what specifically to look at*, with the exact document locations. Every callout must come from the template catalog below. No free-text generation is permitted. - -#### 39.5.1 Ranking and cap - -Callouts are ranked by severity class, then by magnitude within class: - -```text -Severity rank (descending): - 1. broken_link_added, parse_error_added, inclusive_language_flag_added, - nonword_added, lexical_illusion_added - 2. filler_risk_high (≥ 0.60), dmi_drop_band_crossing, - evidence_coverage_drop_band_crossing - 3. long_sentence_added, passive_ratio_breach, readability_target_breach, - table_burden_hard_warning, heading_skip_added - 4. diagram_added_unlabeled, code_fence_added_unlabeled, - artifact_without_nearby_explanation - 5. improvements (band crossings in the better direction) - 6. informational (new-file summary, diagram/table counts when useful) -``` - -Default cap: **8 callouts**. Remaining callouts go into a `
` expander labelled `N more callouts`. The cap is profile-configurable. - -Improvements are always emitted unless they would push the cap past 8 by displacing a regression; a regression always outranks an improvement of the same magnitude. - -#### 39.5.2 Template catalog - -Each template is identified by a `rule_id`. Implementations must emit callouts exclusively through these templates. Slot values are mechanically sourced from: AST nodes, metric fields, threshold constants, or the filename. Literal string slots (link targets, language tags, heading text) come verbatim from the AST — they are **not** synthesized. - -Template grammar conventions: -- `{file}`: relative repo path (rendered as a Markdown link to the blob at the PR head SHA, as in the source-code bot) -- `{n}`, `{m}`, `{k}`: integer counts -- `{old}`, `{new}`: metric values at numeric precision documented in §39.3 -- `{L:N}`: line number N in `{file}` (rendered as `L47`) -- `{s}`: literal string extracted from the AST (link target, fence info string, heading text) rendered in backticks -- `{band}`: band label from the relevant section (`HIGH`, `severe`, `hard`, etc.) - -**Objective-defect callouts (severity 1):** - -| `rule_id` | Template | -|---|---| -| `broken_relative_link_added` | `🔴 **{file}** — {n} unresolved relative link(s) added: {s₁} ({L:N₁}){, s₂ (L:N₂)…}` | -| `broken_anchor_added` | `🔴 **{file}** — {n} unresolved internal anchor(s) added: {s₁} ({L:N₁}){, …}` | -| `broken_external_link_added` | `🔴 **{file}** — {n} broken external link(s) added (link-check enabled): {s₁} ({L:N₁}){, …}` | -| `diagram_parse_error_added` | `🔴 **{file}** — {lang} diagram parse error at {L:N}` | -| `inclusive_language_flag_added` | `🔴 **{file}** — {n} inclusive-language flag(s) added: {s₁} ({L:N₁}){, …}` | -| `nonword_added` | `🔴 **{file}** — non-word {s} at {L:N} (suggest: {replacement})` | -| `lexical_illusion_added` | `🔴 **{file}** — doubled word {s} at {L:N}` | - -**Band-crossing callouts (severity 2):** - -| `rule_id` | Template | -|---|---| -| `filler_risk_high` | `⚠️ **{file}** — filler/lazy risk {new} ({band}); top contributors: {label₁} {v₁}, {label₂} {v₂}, {label₃} {v₃}` | -| `dmi_band_drop` | `🔴 **{file}** — DMI {old} → {new}, crossed {old_band} → {new_band} (§10.4)` | -| `evidence_band_drop` | `🔴 **{file}** — evidence coverage {old} → {new}, crossed {old_band} → {new_band} (§16.4)` | -| `repo_grounding_band_drop` | `🔴 **{file}** — repository grounding {old} → {new}, crossed {old_band} → {new_band} (§15.3)` | - -The `{label_i} {v_i}` slots for `filler_risk_high` are the top three sub-scores from §17.11 (`large-unanchored-prose`, `low-repository-grounding`, `lazy-sectioning`, `low-artifact-density`, `near-duplicate-paragraphs`, `specificity-scarcity`, `hollow-references`, `placeholder-heavy`), sorted by magnitude. Each label comes from §17.11 verbatim — not paraphrased. - -**Readability / wording regressions (severity 3):** - -| `rule_id` | Template | -|---|---| -| `long_sentences_added` | `🔴 **{file}** — {n} sentence(s) exceed {threshold} words (new): {L:N₁}{, L:N₂…}` | -| `readability_target_breach` | `🔴 **{file}** — {formula} {old} → {new}, above {profile} target {target} (§31.13)` | -| `tateishi_band_drop` | `🔴 **{file}** — Tateishi RS {old} → {new} (harder; §35.1)` | -| `passive_ratio_breach` | `🔴 **{file}** — passive ratio {old} → {new}, above {profile} max {max} (§33.1)` | -| `heading_skip_added` | `🔴 **{file}** — heading skip {old_level} → {new_level} at {L:N}` | -| `table_burden_hard` | `⚠️ **{file}** — table at {L:N} has {cells} cells / {cols} columns / {rows} rows (hard warning; §13.2)` | -| `doubled_joshi_added` (JA) | `🔴 **{file}** — repeated particle {s} at {L:N}` | -| `kanji_run_too_long_added` (JA) | `🔴 **{file}** — kanji run of {n} chars exceeds limit {max}: {s} at {L:N}` | - -**Artifact-hygiene callouts (severity 4):** - -| `rule_id` | Template | -|---|---| -| `code_fence_unlabeled_added` | `⚠️ **{file}** — unlabelled code fence at {L:N}` | -| `diagram_missing_caption_added` | `⚠️ **{file}** — {lang} diagram at {L:N} has no caption or nearby explanation` | -| `image_missing_alt_added` | `⚠️ **{file}** — image {s} at {L:N} has no alt text` | -| `artifact_unexplained_added` | `⚠️ **{file}** — {artifact_type} at {L:N} has no explanatory prose within ±2 blocks` | - -**Improvements (severity 5):** - -| `rule_id` | Template | -|---|---| -| `dmi_band_improve` | `🟢 **{file}** — DMI {old} → {new}, crossed {old_band} → {new_band} (§10.4)` | -| `filler_risk_band_improve` | `🟢 **{file}** — filler/lazy risk {old} → {new}, crossed {old_band} → {new_band} (§17.10)` | -| `broken_links_resolved` | `🟢 **{file}** — {n} previously broken link(s) resolved` | -| `long_sentences_resolved` | `🟢 **{file}** — {n} sentence(s) previously over {threshold} words now under` | -| `readability_target_recovered` | `🟢 **{file}** — {formula} {old} → {new}, now within {profile} target {target}` | - -**New-file summary (severity 6, emitted only for added .md files):** - -| `rule_id` | Template | -|---|---| -| `new_file_summary` | `🆕 **{file}** — {words} words, {headings} headings, {code_fences} code fence(s), {diagrams} diagram(s), {tables} table(s); DMI {dmi}, filler risk {filler} ({band})` | - -Everything that does not match a template is silently dropped from the callout block (it may still appear in the drill-down tables of §39.6). This is the mechanism that prevents free-form, LLM-style narration from creeping in. - -#### 39.5.3 Permitted and forbidden language - -The callout grammar is deliberately thin: - -**Permitted verbs and connectors:** `added`, `resolved`, `exceed`, `crossed`, `above`, `below`, `has`, `missing`, `unresolved`, `broken`, `previously`, `now`, `within`, `no caption`, `no alt text`, `→`, `;`, `,`, `(`, `)`. - -**Forbidden:** `after`, `because`, `due to`, `caused by`, `following`, `since`, `likely`, `probably`, `appears to`, `seems`, `may indicate`, `suggests`, `possibly`. Anything that implies causation or intent about the author's edits. - -This rule is the hard line between "CI metrics report" and "automated review feedback that over-reaches". It also makes the output easy to test: a callout is correct iff it exactly matches its template with slots filled from documented sources. - -### 39.6 Drill-down tables (`
`) - -Below the callouts, a collapsed `
` block holds deeper tables for reviewers who want them. The layout mirrors the taxonomy of the research document: - -```markdown -
-Full metric breakdown (structural · wording · lexical · readability) -``` - -Inside, four tables in this order: - -1. **Structural / review** — RCI, MCC, MRPC, Evidence Coverage, Repository Grounding. -2. **English wording quality** (suppressed if no English file) — WQS, passive %, hedges/100w, long-sentence count, nominalization density. -3. **English lexical & readability ensemble** — MATTR₅₀, hapax ratio, Fog, SMOG (only when sentences ≥ 30), ARI, Coleman-Liau. -4. **Japanese composition & register** (suppressed if no Japanese file) — kanji %, hiragana %, katakana %, avg sentence chars, comma/period ratio, politeness dominant. - -Each drill-down table follows the same cell-format rules as the headline table (§39.3). Columns where every row is ⚪ in a given PR are omitted from that table; if all four tables collapse to noise, the `
` block itself is omitted. - -Below the tables, a **Filler risk contributors** block lists the top 3 filler sub-scores per file that has `filler_risk > 0.40`, using the §17.11 labels verbatim. This deliberately duplicates some callout content — the callout shows the worst offender, the drill-down shows the complete picture. - -### 39.7 Short-document handling - -Per §29.1 (item 4), grade-level formulas are suppressed when `words < 100` or `sentences < 5`. In the headline table this renders as `— ²` in the FKGL / Tateishi RS column, with a footnote below the table: - -```markdown -> ² Below grade-scoring threshold (< 100 words or < 5 sentences). -``` - -Every other column keeps emitting because raw counts, link debt, and filler risk remain meaningful on short documents. If a file is *completely* empty of prose (e.g., a marker file with only front-matter), the whole row is rendered with `—` except for word count `0` and a footnote `³ Prose-empty after structural stripping.` - -### 39.8 Large-PR handling - -PRs that touch many Markdown files quickly overflow GitHub's comment render. Rules: - -- **Headline table row cap: 10.** Sort by max severity class of any callout touching the file, descending. Files with only ⚪ cells rank lowest. -- Overflow rows go into `
N more file(s)` immediately below the table, rendered with the same column format. -- If more than 25 files changed, append a one-line aggregate header above the table: `25 Markdown files changed (top 10 by severity shown).` -- **Callout cap: 8.** Overflow into `
N more callouts`. -- Drill-down tables are **never** row-capped — they are already inside `
`. Reviewers who expand them have opted in to the full picture. - -### 39.9 Reference mock (English-dominant PR) - -This is the canonical shape for a PR that modifies one `README.md`, adds one architecture doc, regresses one API reference, leaves one generated file unchanged but on-alert, and touches the changelog. Every number below is mechanically derivable; every callout matches a template from §39.5.2. - -```markdown - -## 📝 Documentation Metrics (this PR vs `main`) - -| File | DMI | Words | FKGL | Link Debt | Filler Risk | -|---|---:|---:|---:|---:|---:| -| [README.md](https://github.com/wharflab/tally/blob/4709d1b/README.md) | 74 (main: 71) 🟢 | 1,240 (main: 1,180) ⚪ | 9.4 (main: 10.1) 🟢 | 0.08 (main: 0.12) 🟢 | 0.15 (main: 0.18) 🟢 | -| [docs/architecture/runtime.md](https://github.com/wharflab/tally/blob/4709d1b/docs/architecture/runtime.md) | 58 🆕 | 2,840 🆕 | 11.8 🆕 | 0.04 🆕 | 0.09 🆕 | -| [docs/api/auth.md](https://github.com/wharflab/tally/blob/4709d1b/docs/api/auth.md) | 62 (main: 68) 🔴 | 1,670 (main: 1,540) ⚪ | 12.1 (main: 11.6) 🔴 | 0.22 (main: 0.15) 🔴 | 0.14 (main: 0.12) ⚪ | -| [docs/generated/overview.md](https://github.com/wharflab/tally/blob/4709d1b/docs/generated/overview.md) | 76 (main: 76) ⚪ | 4,900 (main: 4,820) ⚪ | 10.2 (main: 10.2) ⚪ | 0.11 (main: 0.11) ⚪ | 0.79 (main: 0.78) ⚠️ | -| [CHANGELOG.md](https://github.com/wharflab/tally/blob/4709d1b/CHANGELOG.md) | 81 (main: 83) ⚪ | 2,110 (main: 2,090) ⚪ | 8.9 (main: 8.9) ⚪ | 0.06 (main: 0.06) ⚪ | 0.21 (main: 0.22) ⚪ | - -**Callouts** - -- 🔴 **docs/api/auth.md** — 2 unresolved relative link(s) added: `../../guide/sessions.md` (L47), `./tokens.md#refresh` (L112) -- 🔴 **docs/api/auth.md** — 3 sentence(s) exceed 35 words (new): L83, L104, L156 -- 🔴 **docs/api/auth.md** — FKGL 11.6 → 12.1, above API-reference target 12.0 (§31.13) -- ⚠️ **docs/generated/overview.md** — filler/lazy risk 0.79 (HIGH); top contributors: large-unanchored-prose 0.82, lazy-sectioning 0.71, specificity-scarcity 0.64 -- ⚠️ **docs/architecture/runtime.md** — mermaid diagram at L171 has no caption or nearby explanation -- ⚠️ **docs/architecture/runtime.md** — unlabelled code fence at L214 -- 🟢 **README.md** — DMI 71 → 74, crossed "Good" → "Good" (§10.4); FKGL 10.1 → 9.4 -- 🟢 **README.md** — 3 sentence(s) previously over 30 words now under - -
-Full metric breakdown (structural · wording · lexical · readability) - -### Structural / review - -| File | RCI | MCC | MRPC | Evidence | Grounding | -|---|---:|---:|---:|---:|---:| -| README.md | 34 (main: 36) ⚪ | 14 (main: 17) 🟢 | 6 (main: 6) ⚪ | 0.68 (main: 0.62) 🟢 | 0.71 (main: 0.69) ⚪ | -| docs/architecture/runtime.md | 78 🆕 | 47 🆕 | 12 🆕 | 0.76 🆕 | 0.84 🆕 | -| docs/api/auth.md | 71 (main: 64) 🔴 | 38 (main: 31) 🔴 | 14 (main: 11) ⚪ | 0.58 (main: 0.63) 🔴 | 0.72 (main: 0.74) ⚪ | -| docs/generated/overview.md | 22 (main: 22) ⚪ | 12 (main: 12) ⚪ | 2 (main: 2) ⚪ | 0.24 (main: 0.25) ⚪ | 0.18 (main: 0.19) ⚪ | -| CHANGELOG.md | 18 (main: 19) ⚪ | 9 (main: 10) ⚪ | 3 (main: 3) ⚪ | 0.55 (main: 0.55) ⚪ | 0.81 (main: 0.80) ⚪ | - -### English wording quality - -| File | WQS | Passive % | Hedges /100w | Long sent. | Nominalizations | -|---|---:|---:|---:|---:|---:| -| README.md | 0.82 (main: 0.79) 🟢 | 11% (main: 14%) 🟢 | 1.8 (main: 2.1) ⚪ | 1 (main: 3) 🟢 | 6.2% ⚪ | -| docs/architecture/runtime.md | 0.74 🆕 | 22% 🆕 | 2.4 🆕 | 5 🆕 | 9.1% 🆕 | -| docs/api/auth.md | 0.68 (main: 0.75) 🔴 | 26% (main: 19%) 🔴 | 3.2 (main: 2.0) 🔴 | 4 (main: 1) 🔴 | 11.3% 🔴 | -| docs/generated/overview.md | 0.71 (main: 0.71) ⚪ | 18% ⚪ | 2.6 ⚪ | 2 ⚪ | 7.8% ⚪ | -| CHANGELOG.md | 0.86 (main: 0.86) ⚪ | 8% ⚪ | 0.9 ⚪ | 0 ⚪ | 5.4% ⚪ | - -### English lexical & readability ensemble - -| File | MATTR₅₀ | Hapax | Fog | SMOG | ARI | Coleman-Liau | -|---|---:|---:|---:|---:|---:|---:| -| README.md | 0.78 | 0.44 | 11.3 | 10.8 | 9.1 | 10.4 | -| docs/architecture/runtime.md | 0.81 | 0.52 | 14.2 | 12.7 | 11.9 | 12.8 | -| docs/api/auth.md | 0.74 | 0.48 | 14.7 | 13.1 | 12.4 | 13.2 | -| docs/generated/overview.md | 0.62 | 0.31 | 12.1 | 11.4 | 10.0 | 10.7 | -| CHANGELOG.md | 0.83 | 0.61 | 10.2 | 9.8 | 8.6 | 9.3 | - -### Filler risk contributors (files with risk > 0.40) - -- **docs/generated/overview.md (0.79)** — large-unanchored-prose 0.82, lazy-sectioning 0.71, specificity-scarcity 0.64 - -
- -> Legend: 🟢 improvement · 🔴 regression · ⚠️ attention · 🆕 new file · ⚪ no material change - -> Generated by [mehen](https://github.com/ophidiarium/mehen) — the code quality watcher. -``` - -Every callout in this mock matches a template in §39.5.2 exactly. No causal language appears. Every "likely helpful" or "after …" style phrase from earlier drafts has been removed. - -### 39.10 What is deliberately *not* in scope - -- **No causal explanations.** The report never says "after X", "because of Y", "due to Z". It only reports observed deltas and structural facts. -- **No author-intent inference.** The report never speculates about what the author "meant" or "should have done". -- **No LLM summaries.** Not now, not behind a flag, not as a plugin. The report is pure `f(metrics, thresholds, AST)`. -- **No trend lines or history.** The source-code bot renders a binary-size history via Mermaid; the docs section does not, because per-metric trendlines add signal-to-noise problems that deserve a separate design pass. -- **No suggested edits.** "Split this section" or "add a caption" suggestions are structural but prescriptive; they belong in a separate `mehen doc lint` command, not in a PR diff report. -- **No scoring gates by default.** The PR comment is advisory. A CI gate is available (`mehen diff --fail-on dmi-drop,new-broken-link`), but opt-in and independent of the comment. - -### 39.11 Implementation checklist - -For a first ship: - -```text -[ ] Comment upsert anchored by -[ ] Headline table with 5 columns, fixed precision, delta indicator rules (§39.4) -[ ] Callout emitter driven by §39.5.2 template catalog only -[ ] Severity-sorted callout ranking with 8-callout cap (§39.5.1) -[ ] Short-doc footnote handling (§39.7) -[ ] 10-file headline cap with overflow
(§39.8) -[ ] Drill-down
with 3–4 tables; column suppression when all-⚪ -[ ] Filler-risk contributors list sourced from §17.11 labels verbatim -[ ] Golden-output snapshot tests: byte-identical output for fixed inputs -[ ] Linter that forbids any string in the emitter module outside the template catalog -``` - -The last two items are the key correctness safeguards. A golden-output test (similar to how mehen already uses `insta` for source-metric snapshots) ensures reproducibility. An emitter linter (grep-based, checked in CI) ensures no one adds a `format!("…")` call that introduces free-form language. - ---- - -## References - -1. McCabe, T. J. "A Complexity Measure." *IEEE Transactions on Software Engineering*, 1976. https://doi.org/10.1109/TSE.1976.233837 -2. Halstead, M. H. *Elements of Software Science.* Elsevier, 1977. -3. CommonMark Specification. https://spec.commonmark.org/current/ -4. GitHub Flavored Markdown Specification. https://github.github.com/gfm/ -5. Sweller, J. "Cognitive Load During Problem Solving: Effects on Learning." *Cognitive Science*, 1988. https://doi.org/10.1207/s15516709cog1202_4 -6. Pirolli, P., and Card, S. "Information Foraging." *Psychological Review*, 1999. https://doi.org/10.1037/0033-295X.106.4.643 -7. Mayer, R. E. "Multimedia Learning." Cambridge University Press, 2001. -8. Winn, W. "The Role of Graphics in Training Documents." In *The Technology of Text*, 1982. -9. Gelman, A., Pasarica, C., and Dodhia, R. "Let's Practice What We Preach: Turning Tables into Graphs." *The American Statistician*, 2002. -10. WCAG 2.2, W3C Recommendation. https://www.w3.org/TR/WCAG22/ -11. SonarSource Cognitive Complexity white paper. https://www.sonarsource.com/resources/cognitive-complexity/ -12. Tang, X. et al. "An Empirical Study of Documentation Issues in Software Projects." MSR-related documentation quality research. https://sanadlab.org/assets/pdf/TangMSR23.pdf -13. Liang, W. et al. "GPT detectors are biased against non-native English writers." *Patterns*, 2023. https://doi.org/10.1016/j.patter.2023.100779 -14. Walters, W. H., and Wilder, E. I. "Fabrication and errors in the bibliographic citations generated by ChatGPT." *Scientific Reports*, 2023. https://www.nature.com/articles/s41598-023-41032-5 -15. Brysbaert, M. "How many words do we read per minute? A review and meta-analysis of reading rate." *Journal of Memory and Language*, 2019. https://doi.org/10.1016/j.jml.2019.104047 - -### English readability formulas - -16. Flesch, R. "A new readability yardstick." *Journal of Applied Psychology* 32(3):221–233, 1948. https://psycnet.apa.org/doi/10.1037/h0057532 -17. Kincaid, J. P., Fishburne, R. P., Rogers, R. L., & Chissom, B. S. *Derivation of New Readability Formulas (Automated Readability Index, Fog Count and Flesch Reading Ease Formula) for Navy Enlisted Personnel.* Research Branch Report 8-75, Chief of Naval Technical Training, 1975. https://apps.dtic.mil/sti/tr/pdf/ADA006655.pdf -18. Gunning, R. *The Technique of Clear Writing.* McGraw-Hill, 1952. -19. McLaughlin, G. H. "SMOG Grading — a new readability formula." *Journal of Reading* 12(8):639–646, 1969. https://ogg.osu.edu/media/documents/health_lit/WRRSMOG_Readability_Formula_G._Harry_McLaughlin__1969_.pdf -20. Smith, E. A. & Senter, R. J. *Automated Readability Index.* AMRL-TR-66-22, Aerospace Medical Research Laboratories, 1967. https://apps.dtic.mil/sti/tr/pdf/AD0667273.pdf -21. Coleman, M. & Liau, T. L. "A computer readability formula designed for machine scoring." *Journal of Applied Psychology* 60(2):283–284, 1975. https://psycnet.apa.org/doi/10.1037/h0076540 -22. Dale, E. & Chall, J. S. "A formula for predicting readability." *Educational Research Bulletin* 27:11–20, 37–54, 1948. -23. Chall, J. S. & Dale, E. *Readability Revisited: The New Dale-Chall Readability Formula.* Brookline Books, 1995. -24. Björnsson, C.-H. *Läsbarhet.* Stockholm: Liber, 1968. -25. Anderson, J. "Lix and Rix: Variations on a Little-known Readability Index." *Journal of Reading* 26(6):490–496, 1983. https://www.jstor.org/stable/40031755 -26. Caylor, J. S., Sticht, T. G., Fox, L. C. & Ford, J. P. *Methodologies for Determining Reading Requirements of Military Occupational Specialties.* HumRRO Technical Report 73-5, 1973. -27. Fry, E. "A readability formula that saves time." *Journal of Reading* 11(7):513–516, 575–578, 1968. -28. Schriver, K. A. "Readability Formulas in the New Millennium: What's the Use?" *ACM SIGDOC*, 2000. https://www.karenschriverassociates.com/wp-content/uploads/2020/03/8-Schriver-Readability-formulas-whats-the-use.pdf -29. Klare, G. R. "A Second Look at the Validity of Readability Formulas." *Journal of Reading Behavior*, 1976. https://www.ideals.illinois.edu/items/15551/bitstreams/54962/data.pdf -30. Palmer, D. D. & Hearst, M. A. "Adaptive Multilingual Sentence Boundary Disambiguation." *Computational Linguistics* 23(2), 1997. https://people.ischool.berkeley.edu/~hearst/papers/cl-palmer.pdf -31. Browne, C., Culligan, B. & Phillips, J. *The New General Service List.* 2013. http://www.newgeneralservicelist.com/ - -### Lexical diversity and stylometry - -32. Ure, J. "Lexical Density and Register Differentiation." In *Applications of Linguistics*, Cambridge University Press, 1971. -33. Halliday, M. A. K. *Spoken and Written Language.* Deakin University Press, 1985. -34. McCarthy, P. M. *An Assessment of the Range and Usefulness of Lexical Diversity Measures and the Potential of the Measure of Textual, Lexical Diversity (MTLD).* PhD dissertation, University of Memphis, 2005. -35. McCarthy, P. M. & Jarvis, S. "MTLD, vocd-D, and HD-D: A validation study of sophisticated approaches to lexical diversity assessment." *Behavior Research Methods* 42(2):381–392, 2010. https://pmc.ncbi.nlm.nih.gov/articles/PMC3813439/ -36. Yule, G. U. *The Statistical Study of Literary Vocabulary.* Cambridge University Press, 1944. -37. Tanaka-Ishii, K. & Aihara, S. "Computational Constancy Measures of Texts — Yule's K and Rényi's Entropy." *Computational Linguistics* 41(3):481–502, 2015. https://direct.mit.edu/coli/article/41/3/481/1519/ - -### Japanese readability formulas - -38. Tateisi, Y., Ono, Y. & Yamada, H. "A Computer Readability Formula of Japanese Texts for Machine Scoring." *COLING 1988* Vol. 2:649–654. https://aclanthology.org/C88-2135/ -39. Sato, S., Matsuyoshi, S. & Kondoh, Y. "Automatic Assessment of Japanese Text Readability Based on a Textbook Corpus." *LREC 2008.* https://www.cs.brandeis.edu/~marc/misc/proceedings/lrec-2008/pdf/165_paper.pdf -40. Sato, S. et al. "Obi2: A System for Automatic Readability Assessment of Japanese Text." *LREC 2014.* http://www.lrec-conf.org/proceedings/lrec2014/pdf/633_Paper.pdf -41. Shibasaki, H. & Hara, H. *Constructing a Readability Scale of Japanese Texts and Developing a Software.* KAKENHI-PROJECT-19300277, 2010. https://kaken.nii.ac.jp/en/grant/KAKENHI-PROJECT-19300277/ -42. Hasebe, Y. & Lee, J.-H. "Introducing a Readability Evaluation System for Japanese Language Education." *CASTEL/J 2015.* https://jreadability.net/file/hasebe-lee-2015-castelj.pdf -43. Lee, J.-H. & Hasebe, Y. "Readability Measurement for Japanese Text Based on Levelled Corpora." University of Tsukuba, 2020. http://jhlee.sakura.ne.jp/papers/lee-et-al2016rb.pdf -44. Mizuno, J. et al. "E-learning Japanese readability formula." *Journal of Natural Language Processing* 16(4), 2009. https://www.jstage.jst.go.jp/article/jnlp/16/4/16_4_4_3/_pdf - -### Japanese language resources - -45. NINJAL. *Balanced Corpus of Contemporary Written Japanese (BCCWJ) Frequency Lists.* https://clrd.ninjal.ac.jp/bccwj/en/freq-list.html -46. W3C. *Requirements for Japanese Text Layout (JLREQ).* https://www.w3.org/TR/jlreq/?lang=en -47. Japan Translation Federation. *JTF Japanese Style Guide 3.0.* 2019. https://www.jtf.jp/tips/styleguide — English translation https://www.jtf.jp/pdf/jtf_style_guide_e.pdf -48. Microsoft. *Japanese Localization Style Guide.* http://ftp.ntu.edu.tw/pub/cpatch/g/glossary/microsoft_styleguide_jpn.pdf -49. Ministry of Education of Japan. *Jōyō Kanji List.* 2010 revision (2,136 characters). -50. Tatsumi, H. *J-LEX Japanese Difficulty Tagger.* https://www17408ui.sakura.ne.jp/tatsum/J-LEX/ -51. Premaratne, R. "Is the use of kanji increasing in the Japanese writing system?" *Electronic Journal of Contemporary Japanese Studies* 12(3), 2012. https://www.japanesestudies.org.uk/ejcjs/vol12/iss3/premaratne.html -52. Allen, D. "A Procedure for Determining Japanese Loanword Status." *Vocabulary Learning and Instruction* 9(1), 2021. https://vli-journal.org/wp/wp-content/uploads/2021/08/VLI_9_1_5_allen.pdf - -### Prose-quality tooling and style guides - -53. Ford, J. et al. *vale — a syntax-aware linter for prose.* https://vale.sh/docs/topics/styles -54. Ford, B. *write-good.* https://github.com/btford/write-good -55. Amperser. *proselint.* https://github.com/amperser/proselint -56. get-alex. *alex — catch insensitive, inconsiderate writing.* https://alexjs.com -57. retext authors. *retext plugin registry.* https://github.com/retextjs/retext/blob/master/doc/plugins.md -58. Hemingway Editor algorithm analysis. *Deconstructing the Hemingway App.* https://medium.com/free-code-camp/deconstructing-the-hemingway-app-8098e22d878d -59. textlint-ja. *textlint-rule-preset-ja-technical-writing.* https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing -60. Automattic. *harper — Rust grammar and prose checker.* https://github.com/Automattic/harper -61. Williams, J. *Style: Toward Clarity and Grace.* University of Chicago Press, 1990. -62. Pinker, S. *The Sense of Style: The Thinking Person's Guide to Writing in the 21st Century.* Viking, 2014. -63. Hyland, K. *Metadiscourse: Exploring Interaction in Writing.* Continuum, 2005. - -### Rust ecosystem - -64. lindera authors. *Lindera morphological analyzer.* https://github.com/lindera/lindera -65. daac-tools. *Vibrato tokenizer.* https://github.com/daac-tools/vibrato -66. pemistahl. *Lingua language detector (Rust port).* https://github.com/pemistahl/lingua-rs -67. Quickwit. *whichlang language detection library.* https://quickwit.io/blog/whichlang-language-detection-library -68. unicode-rs. *unicode-segmentation (UAX #29).* https://github.com/unicode-rs/unicode-segmentation -69. Unicode Consortium. *UAX #24 Unicode Script Property.* https://www.unicode.org/reports/tr24/ -70. Unicode Consortium. *UAX #29 Unicode Text Segmentation.* https://www.unicode.org/reports/tr29/ -71. CMU Pronouncing Dictionary. http://www.speech.cs.cmu.edu/cgi-bin/cmudict -72. syllarust authors. *syllarust — CMU-backed syllable counter.* https://lib.rs/crates/syllarust diff --git a/design-docs/mehen_post_classical_metrics_research_foundation.md b/design-docs/mehen_post_classical_metrics_research_foundation.md deleted file mode 100644 index 18c7228d..00000000 --- a/design-docs/mehen_post_classical_metrics_research_foundation.md +++ /dev/null @@ -1,703 +0,0 @@ -# Post-Classical Heuristic Source-Code Metrics for mehen - -**Project:** mehen source code metrics analytics -**Target modules:** shared `mehen-metrics` + per-language crates; new history layer in/around `mehen-git` -**Primary use case:** CI/diff analytics, repository health reporting, and top-offender identification -**Document status:** research foundation and metric design proposal (candidate additions) -**Last updated:** 2026-07-10 - ---- - -## 1. Executive summary - -mehen already implements a strong classical static suite: cyclomatic, cognitive (SonarSource -model), the LOC family (SLOC/PLOC/LLOC/CLOC/blank), full Halstead, three Maintainability Index -variants, ABC, NARGS, NOM, NEXIT, NPA, NPM, and WMC, plus rich `sql.*` and `markdown.*` -namespaces. What it does **not** yet have falls into four research areas surveyed here. This -document proposes concrete additions and, for each candidate, a *fit card* stating what it -measures, its primary citation, whether it is single-file and deterministic, its dependency / -trained-artifact requirements, and a rough implementation effort (S/M/L/XL). - -The headline recommendations, in priority order: - -1. **Git/history process metrics are the single biggest gap and the best fit.** mehen's - `mehen-git` crate today only diffs *which* files changed; it computes no history metrics at - all. Churn, code age, author count / ownership, and change (temporal) coupling are - deterministic, language-agnostic, cheap, and — per multiple large empirical studies — better - defect predictors than any static code metric. They also match mehen's existing diff and - top-offender reporting perfectly. **This is the highest-value area and warrants a dedicated - design pass.** (§6) - -2. **Two deterministic, no-model structural metrics are strong, non-redundant additions:** - Shannon **textual entropy** and **structural (AST-edge) entropy** (Torres et al., EMSE 2025), - which correlate only weakly with cyclomatic complexity, and **DepDegree** (Beyer & Fararooy, - ICPC 2010), a use-def-graph edge count that discriminates code that cyclomatic complexity and - statement count treat as identical. (§3) - -3. **Among learned readability models, only Posnett et al. (2011) is directly portable** — it - ships published logistic-regression coefficients and needs no trained artifact at inference. - Buse & Weimer (2010) and Scalabrino et al. (2016/2018) require shipping trained classifier - weights and, for Scalabrino, NLP machinery. (§4) - -4. **Code "naturalness" (Hindle cross-entropy) is powerful but a poor architectural fit** — it is - explicitly *not* single-file: it needs a corpus-trained, per-language n-gram model plus a lexer, - which clashes with mehen's dependency-light / deterministic-across-platforms contract unless a - frozen model artifact is bundled per language. (§5) - -**One cross-cutting caveat governs everything below.** A rigorous IEEE TSE 2019 study -(Scalabrino et al.) tested 121 code/documentation/developer metrics against 444 human -understandability judgments and found that *none* correlated significantly with perceived or -actual understandability — not even readability and complexity metrics — and that modest ML -combinations remained too inaccurate for practical use. mehen must therefore present any of these -as **review-prioritization / risk signals**, never as an "understandability" or "quality" score. -(§7) - ---- - -## 2. How to read this document - -### 2.1 Fit-card fields - -Every candidate metric carries a fit card: - -| Field | Meaning | -|---|---| -| **Measures** | The quantity computed, in one line. | -| **Primary source** | The citation the definition is drawn from. | -| **Single-file?** | Whether it can be computed from one file in isolation (mehen's default unit) or needs cross-file / repository context. | -| **Deterministic?** | Whether the same input always yields the same output on every platform — mehen's hard contract. | -| **External deps / trained artifact** | What must be shipped or linked beyond an AST/CST walk (a trained model, coefficients, a git repo, a lexer, etc.). | -| **Effort** | S (≈ a visitor pass or counter), M (new accumulator + intra-procedural analysis), L (new subsystem), XL (new subsystem + shipped model artifact). | -| **Verification** | How strongly the research pipeline confirmed the *definitional* claim: **3-0** = unanimous adversarial pass; **primary-sourced** = drawn from a primary source but not put through the 3-vote gate (see §8). | - -### 2.2 mehen's fit constraints (from the current architecture) - -The catalog of the current codebase established the "shape" any new metric must fit: - -- **Open key namespace.** `MetricKey(SmolStr)` (`crates/mehen-core/src/metric_key.rs`) means any - `family.subkey` string is a valid key; the `keys` module is the central const list for the - shared code suite. New families slot in beside `cyclomatic`, `halstead.*`, etc. -- **Accumulator pattern.** A shared metric adds a `FooStats` struct in `mehen-metrics` with - `record_*` (observe a node), `finalize_minmax` (snapshot per-space), and `merge` (fold child - into parent), wired through `State` and `apply_state_to` (`crates/mehen-metrics/src/state.rs`). - The per-language crate only decides *which AST nodes trigger `record_*`*; the math and rollup - are shared. This is the target shape for Category 1. -- **Selectors and polarity.** `MetricSelector` supports `.min/.max/.avg/.sum` aggregators and - `Polarity::{HigherIsWorse, HigherIsBetter}` (`selector.rs`, `threshold.rs`) — new metrics should - declare polarity so thresholds and top-offender ranking work. -- **Unused explainability primitive.** `MetricContribution` + `ContributionReason` (span + reason - code) exist in `analysis.rs` but are largely unpopulated. Any new *composite risk* metric is a - natural first consumer — emit a contribution per increment so `mehen diff` can explain "why." -- **`mehen-git` is diff-only today.** `open_repo`, `changed_files`, `read_blob`, - `friendly_ref_label`. Category 4 requires walking commit history — new capability, but it stays - fully deterministic given a fixed repository state. - ---- - -## 3. Category 1 — Static structural heuristics - -Deterministic, computed from a single file's AST/CST. This is mehen's sweet spot. - -### 3.1 DepDegree (data-flow dependency degree) - -> **Measures:** total number of edges in a function's use-def (data-flow) graph — for each -> operation, the count of reaching definitions it depends on, summed over all operations: -> `dd(G) = Σ_{b∈B} dd_G(b) = |E|`. -> **Primary source:** Beyer & Fararooy, *DepDegree: A Software Metric for the Complexity of -> Programs*, ICPC 2010 ([DOI](https://doi.org/10.1109/icpc.2010.49)); formal validation in Beyer & -> Häring 2014 ([DOI](https://doi.org/10.1145/2597008.2597794), -> [project page](https://www.sosy-lab.org/research/DepDegreeProperties/)). -> **Single-file?** Yes (intra-procedural). **Deterministic?** Yes. -> **External deps / trained artifact:** none — but needs intra-procedural reaching-definitions -> data-flow analysis, which is *beyond* plain AST traversal. -> **Effort:** **M/L**. **Verification:** definition 3-0 unanimous. - -**Why it's interesting for mehen.** DepDegree discriminates complexity that mehen's current metrics -cannot. The canonical example: two functionally equivalent variable-swap implementations both have -cyclomatic complexity 1 and statement count 3, but score DepDegree 6 vs 3 — capturing that a -temp-variable swap threads more data dependencies than a tuple swap. It was formally validated -against *all* of Weyuker's properties. - -**Caveat (verified).** The claim that DepDegree is empirically validated as a *good readability / -understandability predictor* was **refuted** in verification (1-2 vote): the original paper's -supporting experiments are explicitly "preliminary." Treat DepDegree as a theoretically grounded -structural discriminator, **not** a proven readability predictor. - -**Implementation note.** mehen already builds a full CST per space. DepDegree needs a -reaching-definitions pass over that CST per function — assign each identifier a def/use role, -compute reaching defs (a standard forward data-flow fixpoint), and count edges. The intra-procedural -scope keeps it single-file. Per-language cost is in the def/use classification (which nodes bind vs -read a variable), analogous to how each language already classifies Halstead operators/operands. - -### 3.2 Shannon textual entropy and structural (AST-edge) entropy - -> **Measures:** `H_TOKEN = −Σ p(word)·log₂ p(word)` over token/word frequencies in the file, and -> `H_AST_EDGE = −Σ p(edge)·log₂ p(edge)` over AST parent→child edge-type frequencies. Plain -> base-2 Shannon entropy over *empirical relative frequencies within the file*. -> **Primary source:** Torres, Baltes, Treude & Wagner, *On the Entropy of Source Code*, Empirical -> Software Engineering 2025 ([Springer](https://link.springer.com/article/10.1007/s10664-025-10644-y), -> [arXiv](https://arxiv.org/abs/2506.06508)); NLBSE'23 precursor. -> **Single-file?** Yes. **Deterministic?** Yes. -> **External deps / trained artifact:** **none** — this is the key contrast with Hindle-style -> cross-entropy (§5). `H_TOKEN` needs only a lexer; `H_AST_EDGE` needs only the AST mehen already -> builds. -> **Effort:** **S/M**. **Verification:** definition + non-redundancy 3-0 unanimous. - -**Why it's the strongest new deterministic candidate.** The 2025 study measured entropy's -correlation with the metrics mehen already computes and found it **non-redundant**: correlation with -McCabe cyclomatic complexity is only −0.05 to 0.32, and correlations with nloc, token count, and -changed-methods are weak. The authors conclude "entropy may capture dimensions of complexity not -measured by classic definitions." It requires no new parsing infrastructure and slots directly into -the accumulator pattern (accumulate a frequency map per space, finalize to an entropy value). - -**Caveats (verified).** (1) The corpus is **Java-only** (95 projects, 1.8M change events); -cross-language generalization to Kotlin/TypeScript/PHP/SQL is unconfirmed. (2) The authors do *not* -claim construct validity against "true" complexity — only statistical non-redundancy, which is -exactly what matters for adding a complementary signal. mehen should validate the -low-correlation-with-CC property on its own corpora per language before promoting it past -experimental (see §10). - -**Design decision to make.** `H_AST_EDGE` requires choosing a per-language AST-edge vocabulary and a -token-normalization scheme for `H_TOKEN` (raw tokens? identifier-folded? keyword-only?). Because -mehen is multi-language, these choices should be centralized in `mehen-metrics` with per-language -node/token classification hooks, mirroring the Halstead operator/operand split. - -### 3.3 Statistical moments of indentation - -> **Measures:** standard deviation (STD), variance (VAR), and per-line summation (SUM) of leading -> whitespace across lines, as a language-independent proxy for cyclomatic and Halstead complexity. -> **Primary source:** Hindle, Godfrey & Holt, *Reading Beside the Lines: Indentation as a Proxy -> for Complexity Metrics*, ICPC 2008 ([PDF](https://plg.uwaterloo.ca/~migod/papers/2008/icpc08-abram.pdf)); -> extended in Science of Computer Programming 2009. -> **Single-file?** Yes. **Deterministic?** Yes. -> **External deps / trained artifact:** **none — and no parser required.** A plain line scanner -> suffices, ~2–4× cheaper than token-based Halstead, and it works on non-compilable fragments. -> **Effort:** **S**. **Verification:** 3-0 unanimous. - -**Why it's a natural fit for `mehen diff`.** This is the most parser-free candidate in the survey. -Because it needs no grammar, it can produce a complexity proxy for diff hunks, unsupported -languages, or partially-parsed files — a useful floor when a real parse is unavailable. - -**Caveats (verified, important for honest presentation).** (1) The paper found **AVG and MED do -*not* correlate** with any complexity metric — only STD, VAR, and SUM are useful; do not ship the -mean. (2) The correlation strength is **modest, not strong** (rank correlations ~0.4–0.6; -STD/VAR alone gave top-10 precision/recall ~0.39, *worse* than LOC's ~0.475). (3) SUM largely -restates LOC, so it adds little beyond the LOC family mehen already has. Realistically, **STD and -VAR of indentation** are the defensible additions, positioned as a cheap parser-free proxy, not a -replacement for the real structural metrics. - -### 3.4 Gaps within Category 1 (no confirmed candidate found) - -The research pipeline surfaced **no** verified, reproducible, post-2015 candidate for three -sub-areas the survey specifically sought: - -- **Cognitive-complexity refinements.** No novel post-2015 refinement of SonarSource cognitive - complexity survived verification. The SonarSource model mehen already implements remains the - reference; critiques found (Lavazza 2022; Frontiers EEG studies) attack its *predictive validity*, - not its determinism or specification. **No action** beyond the existing implementation. -- **Newer coupling / cohesion / fan-in / fan-out heuristics.** No verified single-file candidate - emerged. The classic CK suite (CBO, LCOM, RFC, DIT, NOC) remains the reference, but most of it - needs whole-program (cross-file) resolution, so it belongs with a future project-scope analysis - layer, not the single-file model. A *within-file* LCOM (method↔field access matrix) is - computable single-file and would be a reasonable independent proposal, but no recent research - motivated it in this survey. -- **API-usage complexity.** No verified reproducible definition surfaced. - -These are documented as open questions in §10 rather than proposed here, to keep this document to -metrics with a clear implementable definition. - ---- - -## 4. Category 2 — Learned readability / understandability - -These score readability from features trained on human ratings. The decisive question for mehen is -**whether a metric ships reproducible coefficients** (deterministic at inference) **or requires a -trained classifier artifact** (a model blob, retraining, non-portable). - -### 4.1 Posnett, Hindle & Devanbu — "A Simpler Model of Software Readability" (the portable one) - -> **Measures:** a readability probability from a 3-feature logistic model with **published -> coefficients**: `z = 8.87 − 0.033·V + 0.40·Lines − 1.5·Entropy` (V = Halstead Volume, Lines = -> line count, Entropy = byte-level Shannon entropy), `score = 1/(1+e^{−z})`. -> **Primary source:** Posnett, Hindle & Devanbu, MSR 2011 -> ([PDF](https://softwareprocess.es/z/ruse-camera-ready.pdf), -> [DOI](https://doi.org/10.1145/1985441.1985454)). -> **Single-file?** Yes. **Deterministic?** **Yes at inference** — coefficients are fixed and -> published (unlike Buse/Weimer and Scalabrino). -> **External deps / trained artifact:** none at inference. Inputs are all things mehen either has -> (Halstead Volume) or can compute trivially (line count, byte entropy). -> **Effort:** **S/M**. **Verification:** 3-0 unanimous. - -**Why it's the one to adopt if any.** It is the only learned readability score in the survey that is -deterministic and portable out of the box — mehen already computes Halstead Volume, and the other -two inputs are near-free. It composes cleanly with the entropy work in §3.2. - -**Critical caveat (verified).** It was trained and validated **only on tiny 4–11 line snippets that -do not span function boundaries**, and the authors explicitly warn it "may very well fail to -classify correctly at a larger size." mehen is a per-file tool, so applying it at file scope is -outside its validated envelope. **Mitigation:** compute it **per function** within a file (mehen's -space model already isolates function spaces), keeping each evaluation near the snippet size the -model was fit on, and treat the file-level value as an average/min over functions rather than a -whole-file score. - -### 4.2 Buse & Weimer — "Learning a Metric for Code Readability" - -> **Measures:** a binary readable/unreadable probability from a trained classifier over ~20 -> statically-extractable local features (line length, identifier count/length, indentation, -> keywords, comments, blank lines), each as a per-line average or maximum. -> **Primary source:** Buse & Weimer, IEEE TSE 2010 -> ([preprint PDF](https://web.eecs.umich.edu/~weimerw/p/weimer-tse2010-readability-preprint.pdf), -> [DOI](https://doi.org/10.1109/TSE.2009.70)). -> **Single-file?** Yes (feature extraction). **Deterministic?** Feature extraction yes; the score -> is a **classifier output**. -> **External deps / trained artifact:** **requires shipping a trained model** (Weka-trained on 120 -> annotators / 12,000 judgments). No public plug-in coefficient table is published. -> **Effort:** **L** (feature extraction M + train/ship/version a model). **Verification:** 3-0 -> unanimous. - -**Assessment.** The feature set is attractive and single-file, and the model reportedly predicts -human judgments ~80% of the time (better than an average individual human). But adopting it means -**shipping and versioning a trained artifact** — a departure from mehen's dependency-light, -formula-driven design. If mehen ever wants a readability score with more features than Posnett, -the pragmatic path is to **re-fit a logistic regression on Buse & Weimer's feature set and publish -the coefficients** (making it Posnett-like and deterministic), rather than shipping a Weka model. - -### 4.3 Scalabrino et al. — "A Comprehensive Model for Code Readability" - -> **Measures:** readability from combined **structural + textual** features, notably comment-code -> coherence / textual coherence; reported ~84.4% accuracy, significantly higher than Buse & Weimer -> (~77.1%), Posnett (~71.5%), and Dorn (~78.8%). -> **Primary source:** Scalabrino, Linares-Vásquez, Poshyvanyk & Oliveto, ICPC 2016 / JSEP 2018 -> ([PDF](https://sscalabrino.github.io/files/2018/JSEP2018AComprehensiveModel.pdf), -> [DOI](https://doi.org/10.1002/smr.1958)). -> **Single-file?** Yes. **Deterministic?** Feature extraction yes; the score is a **classifier -> output**. -> **External deps / trained artifact:** **requires shipping trained LR weights** *plus* NLP-style -> textual-feature machinery (tokenization of comments/identifiers, coherence computation). -> **Effort:** **L/XL**. **Verification:** 3-0 unanimous. - -**Assessment.** The most accurate readability model in the survey, and its textual-coherence idea -(do comments describe the code they sit beside?) is genuinely novel relative to mehen's purely -structural code metrics. But it is the heaviest to adopt: a trained artifact **and** NLP -dependencies. Interesting for the Markdown/prose side of mehen (which already has NLP-style prose -metrics) more than for the code suite. - -### 4.4 The understandability caveat (governs how §4 is presented) - -> **Finding (verified 3-0):** Scalabrino et al., IEEE TSE 2019 -> ([PDF](https://www.cs.wm.edu/~denys/pubs/TSE%2719-Understandability.pdf), -> [DOI](https://doi.org/10.1109/tse.2019.2901468)) tested 121 metrics against 444 human -> understandability evaluations and found a "bold negative result": **none** correlated -> significantly with perceived or actual understandability, and combining them into -> classification/regression models yielded only modest improvement (best classifier misclassifies -> ~33%). Lavazza et al. (2022/2023) corroborate that structural measures alone — including -> Cognitive Complexity — cannot build an accurate understandability model (~30% error). - -**Implication.** Readability and understandability are *distinct constructs*; readability models -predict readability judgments, not comprehension. mehen must **not brand any single metric — or a -modest combination — as an "understandability" or "comprehensibility" score.** Label these -"readability (proxy)" or fold them into review-prioritization, with an explicit caveat in the docs. - ---- - -## 5. Category 3 — Code naturalness / entropy - -### 5.1 Hindle cross-entropy ("naturalness") - -> **Measures:** the cross-entropy of a file's token sequence under a **pre-trained n-gram language -> model**: `H_M(s) = −(1/n)·log p_M(a₁…aₙ)`. Lower cross-entropy = more predictable / "natural" -> code; anomalously high entropy flags "surprising" code. -> **Primary source:** Hindle, Barr, Su, Gabel & Devanbu, *On the Naturalness of Software*, ICSE -> 2012 ([PDF](https://softwareprocess.es/pubs/hindle2012ICSE.pdf)); bug link in Ray et al. 2016; -> tooling in [SLP-Core](https://github.com/SLP-team/SLP-Core). -> **Single-file?** **No** — needs a corpus-trained model. **Deterministic?** Only once the model -> `M` is frozen. -> **External deps / trained artifact:** a **pre-trained, per-language n-gram model** (authors use -> Modified Kneser-Ney smoothing) applied to comment-stripped, **lexically analyzed** token -> sequences — i.e., a trained artifact *plus* a per-language lexer. Even "self cross-entropy" uses -> 10-fold cross-validation, so a corpus is mandatory. -> **Effort:** **L/XL**. **Verification:** 3-0 unanimous. - -**Why it's compelling yet a poor fit.** Naturalness is genuinely predictive — Ray et al. (2016) -showed buggy lines are measurably less "natural" and become more natural once fixed, and SLP-Core's -cache language models exploit code "localness." But computing it **conflicts directly with mehen's -two core constraints**: it is not single-file (needs a corpus model), and it is only deterministic -once a specific model artifact is frozen and bundled per language — which also raises "deterministic -across platforms" and versioning concerns. - -**If mehen ever pursues this**, the only architecture that preserves determinism is to **train a -fixed per-language model offline, version it, and bundle it as a data artifact** (like the grammars -already vendored) — with the score computed against that frozen model. This is a large, -standalone project, not an incremental metric. The §3.2 Shannon entropies are the **deterministic, -no-model way to capture "the entropy dimension"** and should be preferred first; naturalness is a -later, heavier option if the entropy signal proves valuable. - ---- - -## 6. Category 4 — Git / history process metrics (highest-value gap) - -**This is where mehen is most incomplete and where the fit is best.** `mehen-git` currently only -determines *which* files changed for `mehen diff`. Every metric below is deterministic given a fixed -repository state, language-agnostic, and cheap. The empirical case is strong (§7): process metrics -out-predict static code metrics for defects, and they cost roughly an order of magnitude less to -compute. - -> **Verification honesty note.** These Category 4 claims were extracted from **primary sources** -> (code-maat, PyDriller, Google's ICSE 2013 paper, Nagappan & Ball TSE 2005, CodeScene docs) but -> did **not** pass through the 3-vote adversarial gate — the verification budget (25 claims) was -> exhausted by Categories 1–3. The *formulas* below are quoted from those primary sources; their -> *definitional* accuracy is high-confidence, but they carry a lighter verification stamp than §§3–5. -> A dedicated verification pass is recommended (§10). - -### 6.1 Code churn - -> **Measures:** amount of change to a file over a period. Two selectable variants (PyDriller): -> `(added − removed)` or `(added + removed)` lines, summed across commits; exposed as total / max / -> avg per file. **Nagappan & Ball** show *relative* churn (churn normalized to file size / temporal -> extent) is the defect-predictive form; *absolute* churn is a poor predictor. -> **Primary sources:** [PyDriller process metrics](https://pydriller.readthedocs.io/en/latest/processmetrics.html); -> Nagappan & Ball, *Use of Relative Code Churn Measures to Predict System Defect Density*, ICSE 2005 -> ([DOI](https://dl.acm.org/doi/10.1145/1062455.1062514)); code-maat `abs-churn`. -> **Single-file?** Needs commit history for that file. **Deterministic?** Yes. -> **External deps / trained artifact:** a git repository + diff parsing; no model. -> **Effort:** **M** (churn itself) once the history-walk subsystem exists. - -Ship **both** `history.churn.abs` (added+removed) and `history.churn.relative` -(churn ÷ current size) — the research is explicit that the relative form is the one with defect -signal, while absolute churn is easier to compute and matches code-maat's default. - -### 6.2 Code age - -> **Measures:** months since a module's last change (configurable "time zero"); a proxy for -> stability (recently-churned code is riskier; long-stable code is settled). -> **Primary source:** code-maat `age` analysis -> ([repo](https://github.com/adamtornhill/code-maat)); Tornhill, *Your Code as a Crime Scene*. -> **Single-file?** Needs the file's last-commit date. **Deterministic?** Yes (given fixed "now"). -> **External deps / trained artifact:** git; no model. **Effort:** **S**. - -Note the **determinism wrinkle**: age depends on "now." mehen should default "time zero" to the -repository HEAD commit date (not wall-clock time) so results are reproducible across runs and -machines — matching mehen's cross-platform determinism contract. - -### 6.3 Ownership / authorship metrics - -> **Measures:** per file — number of distinct authors; **minor contributors** (developers -> contributing < 5% of lines); **contributors experience** (% of lines authored by the single -> top contributor); main developer. -> **Primary sources:** [PyDriller process metrics](https://pydriller.readthedocs.io/en/latest/processmetrics.html) -> (fixed 5% minor-contributor threshold); code-maat `authors`, `main-dev`, `entity-ownership`. -> **Single-file?** Needs `git blame` / commit authorship for that file. **Deterministic?** Yes. -> **External deps / trained artifact:** git; no model. **Effort:** **M**. - -Number-of-authors is one of the most-validated defect signals in the literature (Tornhill: -"number-of-authors … [is a] validated predictor of post-release defects"). The fixed thresholds -(5% minor contributor) are concrete and reproducible. - -### 6.4 Change coupling / temporal coupling - -> **Measures:** how often two files change in the same commit. **Degree of coupling** = % of shared -> revisions two files change together. **Sum of Coupling (SoC)** = per-file aggregate of how often a -> file co-changes with *any* other file — a single-number architectural-significance signal. -> **Primary sources:** code-maat `coupling` / `soc` -> ([repo](https://github.com/adamtornhill/code-maat)); CodeScene temporal-coupling docs. -> **Single-file?** **No** — inherently pairwise / repository-scope. **Deterministic?** Yes. -> **External deps / trained artifact:** git; no model. **Effort:** **L** (pairwise co-change over -> history; needs noise thresholds). -> **Reproducible thresholds (code-maat / CodeScene defaults):** ignore changesets > 30–50 files; -> ignore couples < 30–50% strength; require ≥ 5–10 shared commits; require ≥ 10 revisions/file; -> exclude couples explained only by a shared creation commit. - -This is the metric that most needs the **top-offender/report layer** rather than the per-file -metric set, because its output is a *ranking of file pairs* (or SoC per file). It is also the most -implementation-heavy Category 4 item. **SoC is the pragmatic first step** — it collapses coupling to -one number per file, which fits mehen's existing per-file, top-offender model. - -### 6.5 Hotspots (complexity × change frequency) - -> **Measures:** files where a complexity proxy (LOC, or one of mehen's real complexity metrics) and -> change frequency (commit count) **overlap** — the highest-leverage refactoring targets. -> **Primary source:** CodeScene hotspots docs; Tornhill, *Your Code as a Crime Scene* / -> *Software Design X-Rays*. -> **Single-file?** Combines a single-file metric with that file's commit frequency. -> **Deterministic?** Yes (for the open, LOC×frequency form). **External deps:** git; no model. -> **Effort:** **S** once churn/frequency exists (it's a product of two values mehen would already -> have). **Verification:** CodeScene's *ranking/prioritization* layer is **proprietary and -> probabilistic** — do not attempt to replicate it. The open `complexity × change-frequency` -> overlap is reproducible; the ranked "refactoring targets" are not. - -**Strong recommendation.** A hotspot signal is nearly free once §6.1/§6.3 exist, and it is the most -*actionable* history metric — CodeScene reports that top hotspots occupy ~5.5% of code yet absorb -~17.6% of effort and ~23% of fixed defects. Because mehen has *real* complexity metrics (cognitive, -cyclomatic), it can compute a **better hotspot than the LOC-based default** — e.g., `cognitive.sum × -history.commit_frequency`. This is a compelling composite that also lights up the unused -`MetricContribution` primitive. - -### 6.6 Time-Weighted Risk (Google bug-prediction) - -> **Measures:** a per-file bug-propensity score summing a logistic time-decay weight over the file's -> bug-fixing commits: `Σᵢ 1/(1 + e^{−12·tᵢ + ω})`, where `tᵢ` is the commit time normalized to -> [0,1] and `ω` tunes the decay window (~6–8 months at ω hard-coded to 12). -> **Primary source:** Lewis et al., *Does Bug Prediction Support Human Developers?*, ICSE 2013 -> ([PDF](https://users.soe.ucsc.edu/~ejw/papers/lewis-icse-2013.pdf)). -> **Single-file?** Needs the file's bug-fixing commit history. **Deterministic?** Yes (given a rule -> for identifying bug-fixing commits). -> **External deps / trained artifact:** git + a bug-fix commit classifier (e.g., message regex -> `fix|bug|#\d+`); **no trained model**. **Effort:** **M**. - -**Two honest caveats (both from the primary source).** (1) The score needs a *definition of -"bug-fixing commit"* — mehen would use a configurable message heuristic, which is a source of noise. -(2) The simplest variant — **the "Rahman algorithm," just ranking files by count of bug-fixing -commits** — performed almost as well as more complex schemes and was *preferred by Google developers -for transparency*. So mehen should offer `history.bugfix_commits` (trivial, transparent) first, and -TWR as a decayed refinement. Note also that Google's own deployment produced **no significant change -in developer behavior** — a signal's existence doesn't guarantee it changes outcomes; present it -modestly. - -### 6.7 Secondary history heuristics (from PyDriller) - -- **Hunks count** — median number of contiguous diff blocks touching a file; a change-fragmentation - signal (scattered edits vs one localized change). Deterministic; **S**. -- **Change set** (max/avg files committed together) — a repository-scope co-change signal, cheaper - than full pairwise coupling. Deterministic; **S**. -- **Commits count**, **lines count** (total added/removed over history) — trivial history rollups; **S**. - -### 6.8 Licensing constraint (must-read before implementing) - -**code-maat is GPL-v3** and its analyses evolved into the **proprietary CodeScene** product. mehen -may **reimplement the open, reproducible formulas** (all quoted above are published in Tornhill's -books and the code-maat README), but must **not copy code-maat's Clojure source** into a -permissively-licensed Rust CLI. CodeScene's *prioritization/ranking algorithms* are proprietary and -not reproducible — implement only the open overlap/coupling definitions. PyDriller (Apache-2.0) and -the academic formulas (Nagappan-Ball, Google TWR) are safe references. - ---- - -## 7. Empirical reality check (why, and why-not) - -The survey's validation-focused sources converge on a nuanced picture mehen should encode in how it -*presents* metrics: - -1. **Process/history metrics beat static code metrics for defect prediction.** Rahman & Devanbu - (2013) and Bal & Kumar / large-scale replication (EMSE 2022, 722k commits / 700 projects): best - process learners reach ~98% recall / 95% AUC vs ~44% / ~54% for product (code) learners; process - metrics are also ~10× cheaper and language-agnostic. **→ Strong argument for Category 4.** -2. **No single metric captures understandability** (Scalabrino TSE 2019; Lavazza 2022). **→ Never - brand any score "understandability."** (§4.4) -3. **Plain LOC predicts faults about as well as complexity metrics; combined metric sets do best** - (Hall et al.; Radjenović et al. 2013 SLR). **→ mehen's value is breadth + combination, not any - single hero metric. Add complementary families (entropy, history) rather than more - complexity variants.** -4. **Metric-importance rankings don't generalize across scales** (EMSE 2022). **→ Don't hard-code - weights from small studies; keep composites configurable and explainable.** - ---- - -## 8. Proposed prioritization for mehen - -| Tier | Candidate | Category | Effort | Deterministic | Ships a model? | Rationale | -|---|---|---|---|---|---|---| -| **1 — do first** | Shannon `H_TOKEN` + `H_AST_EDGE` | Static | S/M | ✅ | ❌ | No new deps; empirically non-redundant with CC; pure fit. | -| **1** | History: churn (abs+relative), code age, author count, commits count | History | M (subsystem) | ✅ | ❌ | Biggest gap; best defect signal; matches diff/top-offender model. | -| **1** | Hotspot = `cognitive.sum × commit_frequency` | History composite | S* | ✅ | ❌ | Nearly free after churn; most actionable; first `MetricContribution` consumer. | -| **2 — high value, more work** | DepDegree | Static | M/L | ✅ | ❌ | Discriminates what CC/statement-count miss; needs data-flow pass. | -| **2** | Change coupling / Sum-of-Coupling | History | L | ✅ | ❌ | Powerful but pairwise/repo-scope; start with SoC. | -| **2** | Time-Weighted Risk (+ transparent `bugfix_commits`) | History | M | ✅ | ❌ | Needs bug-fix commit heuristic; ship the transparent count first. | -| **3 — deterministic, lower payoff** | Indentation STD/VAR | Static | S | ✅ | ❌ | Parser-free proxy; only *modest* correlation; drop AVG/MED and SUM. | -| **3** | Posnett readability (per-function) | Learned | S/M | ✅ | ❌ | Only portable learned model; keep inside its 4–11-line size envelope. | -| **4 — heavy / poor fit** | Buse-Weimer / Scalabrino readability | Learned | L/XL | ⚠️ (model) | ✅ | Require shipped trained artifacts (+NLP for Scalabrino). | -| **4** | Hindle naturalness | Naturalness | L/XL | ⚠️ (frozen model) | ✅ | Not single-file; needs bundled per-language n-gram model. | - -`*` Hotspot effort is S *given* the Tier-1 history subsystem. - -**Suggested namespaces** (open `MetricKey` space, following existing `family.subkey` convention): -`entropy.token`, `entropy.ast_edge`; `depdegree` (+ `.sum/.avg/.max`); `indent.std`, `indent.var`; -`readability.posnett`; and a new **`history.*`** family — `history.churn.abs`, -`history.churn.relative`, `history.age_months`, `history.authors`, `history.minor_contributors`, -`history.ownership`, `history.commit_frequency`, `history.hotspot`, `history.sum_of_coupling`, -`history.twr`, `history.bugfix_commits`. Declare `Polarity` per key (most are `HigherIsWorse`; -`history.age_months` and `history.ownership` are `HigherIsBetter`). - ---- - -## 9. Recommendation for the GitHub Action comment default set - -**Question:** if we want to replace the current default metrics shown in the GitHub Action -(PR-comment) table — or add just one — what should it be? - -### 9.1 What the comment shows today, and why it's redundant - -The PR comment is rendered by `mehen diff`'s Markdown table, one column per default selector. The -default set is a single source of truth in `crates/mehen-engine/src/metric_selector.rs` -(`DEFAULT_METRICS`, consumed by `run_diff` → `default_selectors_for_language` → `print_markdown`): - -| # | Selector | Label | Underlying key | Dimension | -|---|---|---|---|---| -| 1 | `cyclomatic` | Cyclomatic | `cyclomatic.sum` | control-flow complexity | -| 2 | `cognitive` | Cognitive | `cognitive.sum` | control-flow complexity | -| 3 | `nom.functions` | Functions | `nom.functions` | size (count) | -| 4 | `loc.lloc` | LLOC | `loc.lloc` | size (lines) | -| 5 | `mi.visual_studio` | MI | `mi.visual_studio` | **composite of 1 + Halstead volume + SLOC** | - -(SQL files use a disjoint `DEFAULT_SQL_METRICS` set — the analysis below is about the source-code -default; the same reasoning was already applied to give SQL its own composite-led defaults.) - -Two structural problems: - -1. **The five columns collapse to two dimensions plus a composite that double-counts them.** - Cyclomatic and cognitive are both control-flow; `nom.functions` and `loc.lloc` are both size; and - `mi.visual_studio` is *defined as* `max(0, (171 − 5.2·ln(V) − 0.23·Cyclomatic − 16.2·ln(SLOC))·100/171)` - — so it re-encodes cyclomatic (already column 1) and size (already columns 3–4). Real - information density is closer to **2.5 columns, not 5.** The **ABC** magnitude — whose - *assignments* term is a data-manipulation/computation-volume axis — and the **Halstead - difficulty/effort** vocabulary axis are entirely absent, even though both are already computed - for every language. - -2. **A diff comment shows no change-relevant signal.** The table lists absolute per-file metric - values. The question a reviewer actually asks — *"is this a risky change to an already-fragile - file?"* — needs a **history** column (§6), which mehen cannot yet produce. This is the strongest - argument that the highest-value *comment* improvement is gated on the Category-4 work, not on the - static suite. - -### 9.2 If adding exactly one column (zero-to-low effort) - -**Recommendation: add `abc` (ABC magnitude).** It is already implemented for every language, already -in `KNOWN_METRICS`, and — crucially — measures a dimension none of the five current columns capture: -raw computational volume (Assignments/Branches/Conditions). A function can be cyclomatically flat and -short yet have a large ABC because it does a lot of straight-line work; that is exactly the -"deceptively heavy change" the current table hides. - -> **One-line change:** append `"abc"` to `DEFAULT_METRICS` in -> `crates/mehen-engine/src/metric_selector.rs`. Effort **S** (plus golden-snapshot updates for the -> Markdown/JSON reporters). No new computation, no new dependency. - -*Alternative if a truly novel signal is preferred over an existing one:* `entropy.token` (§3.2) once -implemented — it is the only static addition the research showed to be **non-redundant with -cyclomatic complexity** (correlation −0.05 to 0.32). Prefer this once §3.2 lands; until then, `abc` -is the free win. - -### 9.3 If replacing the set (recommended target) - -Design the comment around **one column per orthogonal dimension**, dropping the redundancy. A -principled 5-column set, in order: - -| Column | Selector | Dimension it uniquely covers | Status | -|---|---|---|---| -| Cognitive | `cognitive` | control-flow *understandability* (keep the better of the two flow metrics) | ✅ selectable | -| ABC | `abc` | computational volume (assignments/branches/conditions) | ✅ selectable | -| Halstead effort | `halstead.effort` | vocabulary/operator burden | ⚠️ computed but **not yet selectable** — see note | -| LLOC | `loc.lloc` | size | ✅ selectable | -| MI | `mi.visual_studio` | at-a-glance rollup (kept as the one deliberate composite) | ✅ selectable | - -Rationale: **drop `cyclomatic`** (cognitive is the more defensible flow metric and the two correlate -strongly) and **drop `nom.functions`** (LLOC already carries size; function *count* is weak signal in -a diff). Spend the freed columns on the two orthogonal axes that were missing — ABC and Halstead -effort. - -**Wiring caveat (one metric is not free).** Four of these five (`cognitive`, `abc`, `loc.lloc`, -`mi.visual_studio`) are already registered as selectors in -`crates/mehen-engine/src/metric_selector.rs` (present in `KNOWN_METRICS` and mapped in -`metric_set_key_for`), so for them this is a **pure-config change** to `DEFAULT_METRICS` plus -reporter snapshots. **`halstead.effort` is the exception:** the walker *publishes* the value -(`crates/mehen-metrics/src/state.rs` emits the `halstead.effort` key), but only `halstead.volume` is -registered as a *selector* today, and `halstead.effort` is not a namespaced (`sql.*`/`markdown.*`) -key, so it would fall through to "Unknown metric, skipping" rather than render. Adding it needs two -one-line registrations first — a `("halstead.effort", "Halstead Effort", Polarity::LowerIsBetter)` -entry in `KNOWN_METRICS` and a `"halstead.effort" => "halstead.effort"` arm in `metric_set_key_for`. -So §9.3 is **"no new metric *formula*"**, not "no code": budget the small selector-registration -change for the Halstead effort column. Effort **S**. - -### 9.4 The strategic answer (once history lands) - -The most valuable comment is not a better static column — it is a **change-risk column** the current -architecture cannot yet emit. Target end-state for the PR comment, after §6 Tier-1 work: - -| Column | Selector | Why it belongs in a *diff* comment | -|---|---|---| -| Cognitive | `cognitive` | how hard the changed code is to follow | -| ABC | `abc` | how much the change actually computes | -| MI | `mi.visual_studio` | at-a-glance maintainability rollup | -| **Hotspot** | **`history.hotspot`** | **`cognitive.sum × commit_frequency` — is this a fragile, frequently-touched file?** | -| **Churn** | **`history.churn.relative`** | **how much of the file this change moves, size-normalized** | - -The two **bold** columns are the ones that make a *diff* comment answer the reviewer's real question, -and they are precisely what §6 proposes building. **Sequencing recommendation:** ship §9.3 now as a -pure-config cleanup (removes redundancy, adds two orthogonal axes at zero metric cost), then extend -the default set with `history.hotspot` + `history.churn.relative` when the Category-4 history layer -exists. Note the per-language default mechanism (`default_metrics_for_language`) already supports -this — history columns would be added to the shared default, while SQL keeps its own set. - -### 9.5 Caveat carried from §7 - -Whatever the comment shows, label the columns as **review-prioritization signals**, not quality -verdicts (§4.4/§7). A rising cognitive or hotspot number flags *where to look*, not *that the code is -bad* — the empirical literature is explicit that no single metric certifies (un)maintainability. - ---- - -## 10. Open questions / recommended follow-up research - -1. **Dedicated Category 4 verification + design pass.** The history metrics are the highest-value - addition but carry the lightest verification stamp in this document (§6 note). Run a focused - research + verification pass on churn/age/ownership/coupling/hotspot/TWR definitions and reference - implementations (code-maat, PyDriller, CodeScene open docs), then write a `mehen-git` - history-layer design doc (repository walk, commit caching, determinism via HEAD-relative "now", - bug-fix commit heuristic configuration). -2. **Cross-language entropy validation.** Does Torres et al.'s low-correlation-with-CC - (non-redundancy) result hold for Kotlin/TypeScript/PHP/SQL/Markdown, and what per-language - AST-edge vocabulary and token normalization should `H_AST_EDGE` / `H_TOKEN` use? (§3.2) -3. **Posnett at file scope.** Can the 3-feature model be safely applied per-function within a file, - or should it be recalibrated for larger units? Validate before shipping. (§4.1) -4. **Within-file LCOM and API-usage complexity.** No recent research surfaced, but a single-file - LCOM (method↔field access matrix) and an API-fan-out count are plausible independent proposals; - worth a targeted search distinct from this survey. (§3.4) - ---- - -## 11. Sources - -All primary sources below were fetched and, except where §6 notes otherwise, their definitional -claims passed 3-0 adversarial verification. - -**Static structural** -- Beyer & Fararooy, *DepDegree*, ICPC 2010 — https://doi.org/10.1109/icpc.2010.49 -- Beyer & Häring, *DepDegree properties* (Weyuker validation), 2014 — https://www.sosy-lab.org/research/DepDegreeProperties/ -- Torres, Baltes, Treude & Wagner, *On the Entropy of Source Code*, EMSE 2025 — https://link.springer.com/article/10.1007/s10664-025-10644-y · https://arxiv.org/abs/2506.06508 -- Hindle, Godfrey & Holt, *Reading Beside the Lines*, ICPC 2008 — https://plg.uwaterloo.ca/~migod/papers/2008/icpc08-abram.pdf -- SonarSource, *Cognitive Complexity* white paper (archetype; already implemented) — https://www.sonarsource.com/docs/CognitiveComplexity.pdf - -**Learned readability / understandability** -- Posnett, Hindle & Devanbu, *A Simpler Model of Software Readability*, MSR 2011 — https://softwareprocess.es/z/ruse-camera-ready.pdf -- Buse & Weimer, *Learning a Metric for Code Readability*, IEEE TSE 2010 — https://web.eecs.umich.edu/~weimerw/p/weimer-tse2010-readability-preprint.pdf -- Scalabrino et al., *A Comprehensive Model for Code Readability*, JSEP 2018 — https://sscalabrino.github.io/files/2018/JSEP2018AComprehensiveModel.pdf -- Scalabrino et al., *Automatically Assessing Code Understandability*, IEEE TSE 2019 — https://www.cs.wm.edu/~denys/pubs/TSE%2719-Understandability.pdf - -**Naturalness / entropy** -- Hindle et al., *On the Naturalness of Software*, ICSE 2012 — https://softwareprocess.es/pubs/hindle2012ICSE.pdf -- Ray et al., *On the "Naturalness" of Buggy Code*, ICSE 2016 — https://arxiv.org/abs/1506.01159 -- SLP-Core (reference implementation) — https://github.com/SLP-team/SLP-Core - -**Git / history process (primary-sourced; see §6 verification note)** -- code-maat (Adam Tornhill; GPL-v3) — https://github.com/adamtornhill/code-maat -- PyDriller process metrics (Apache-2.0) — https://pydriller.readthedocs.io/en/latest/processmetrics.html -- Lewis et al., *Does Bug Prediction Support Human Developers?* (Google TWR), ICSE 2013 — https://users.soe.ucsc.edu/~ejw/papers/lewis-icse-2013.pdf -- Nagappan & Ball, *Relative Code Churn*, ICSE 2005 — https://dl.acm.org/doi/10.1145/1062455.1062514 -- CodeScene hotspots / temporal-coupling docs — https://docs.enterprise.codescene.io/ - -**Empirical validation / SLRs** -- Radjenović et al., *Software fault prediction metrics: A systematic literature review*, IST 2013 -- Rahman & Devanbu, *How, and why, process metrics are better*, ICSE 2013 -- Large-scale replication (process vs product, 700 projects), EMSE 2022 — https://arxiv.org/abs/2008.09569 -- Hall et al., *A systematic review of fault prediction performance* — http://crest.cs.ucl.ac.uk/cow/15/HallBBGC2011.pdf - ---- - -## 12. Provenance - -This document was produced by (a) an exhaustive read-only catalog of mehen's current metric -inventory, and (b) a deep-research pipeline that decomposed the question into 5 angles, ran parallel -web searches (Exa/Tavily), fetched 26 primary sources, extracted 127 falsifiable claims, and put the -top 25 through 3-vote adversarial verification (24 confirmed, 1 refuted — the DepDegree -predictive-validity claim in §3.1). The verification budget was consumed by Categories 1–3, so -Category 4 (§6) is primary-sourced but not adversarially voted; §10.1 recommends closing that gap. -Empirical accuracy figures (80%, 84.4%, 98% recall) are dataset-specific, and the entropy -non-redundancy result is Java-only — see the per-section caveats. diff --git a/design-docs/mehen_sql_metrics_research_foundation.md b/design-docs/mehen_sql_metrics_research_foundation.md deleted file mode 100644 index 7eec0790..00000000 --- a/design-docs/mehen_sql_metrics_research_foundation.md +++ /dev/null @@ -1,1399 +0,0 @@ -# Science-Backed Heuristic Metrics for Standalone SQL Files in mehen - -**Project:** mehen source code metrics analytics -**Target module:** proposed `mehen-sql` language analyzer -**Target inputs:** standalone `.sql` files in software repositories -**Primary use case:** CI/diff analytics, repository health reporting, and top-offender identification for SQL-heavy codebases -**Document status:** research foundation and metric design proposal -**Last updated:** 2026-05-17 - ---- - -## 1. Executive summary - -SQL should not be squeezed into the existing function/class-centric metric model. A standalone `.sql` file can be an ad hoc query, an analytics model, a migration script, a stored-program body, a DDL package, a transaction script, or a mix of those. The dominant complexity mechanism is usually **relational/dataflow structure** rather than imperative control flow. For PL/SQL and T-SQL procedural blocks, classic cyclomatic/cognitive complexity can still be meaningful, but for ordinary declarative SQL the more useful foundation is a dedicated metric family based on statements, query blocks, CTE graphs, join graphs, predicate/expression structure, output-schema clarity, object-touch risk, dialect portability, parser confidence, and optional lineage. - -The most important prior-art observations are: - -1. **SonarQube has SQL-family support, but its complexity metric is principally procedural.** Sonar defines cyclomatic complexity as `1 + conditional branches`, reports cognitive complexity, and documents PL/SQL-specific cyclomatic increments for anonymous blocks, procedures, triggers, loops, `WHEN`, `IF`/`ELSIF`, `RAISE`, `AND`/`OR`, and related constructs. It also documents T-SQL analysis and the `.sql` extension ambiguity: by default `.sql` is analyzed as PL/SQL, while `.tsql` is T-SQL. This is useful prior art for procedural SQL, but not sufficient for standalone declarative query complexity. Sources: [Sonar metric definitions](https://docs.sonarsource.com/sonarqube-server/10.7/user-guide/code-metrics/metrics-definition), [Sonar T-SQL](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/t-sql), [Sonar PL/SQL](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/pl-sql). -2. **SQLFluff and sqruff provide excellent parsing/linting precedents, but not a general built-in source metric suite.** SQLFluff exposes a dialect-aware parse tree and rule traversal architecture; its rules cover many structural smells that can become metric contributors. Sqruff is a Rust SQL linter/formatter with SQLFluff-inspired rules and experimental column-level lineage support. Sources: [SQLFluff docs](https://docs.sqlfluff.com/en/stable/), [SQLFluff architecture](https://docs.sqlfluff.com/en/stable/guides/contributing/architecture.html), [sqruff docs](https://playground.quary.dev/docs/), [sqruff rules](https://playground.quary.dev/docs/reference/rules/). -3. **A newer SQLFluff plugin is highly relevant practical prior art.** `sqlfluff-complexity` defines CPX rules for CTE count, join count, nested subquery depth, CASE expressions, boolean predicates, window functions, CTE dependency depth, nested CASE depth, set operations, inline derived tables, and an aggregate weighted complexity score. It is not a full repository metrics model, but its feature set is an excellent baseline for mehen’s SQL structural metrics. Sources: [`sqlfluff-complexity` README](https://github.com/yu-iskw/sqlfluff-complexity), [`docs/rules.md`](https://raw.githubusercontent.com/yu-iskw/sqlfluff-complexity/main/docs/rules.md), [`docs/configuration.md`](https://raw.githubusercontent.com/yu-iskw/sqlfluff-complexity/main/docs/configuration.md). -4. **Scientific literature supports SQL-specific query metrics.** Vashistha and Jain’s SQLShare workload work explicitly defines query complexity from the user-authoring perspective, not only optimizer cost; it evaluates number of tables, columns, query length, operators, expression operators, runtime, and adapts Halstead measures to SQL. Piattini and Martínez proposed SQL maintainability measures and validated them empirically. Text-to-SQL research such as Spider classifies SQL hardness using numbers of components, selections, conditions, keywords, set operations, nested subqueries, aggregators, and related features. Sources: [SQLShare paper](https://uwescience.github.io/sqlshare/pdfs/Jain-Vashistha.pdf), [Piattini & Martínez](https://link.springer.com/chapter/10.1007/3-540-44469-6_7), [Spider paper](https://ar5iv.labs.arxiv.org/html/1809.08887), [Spider benchmark site](https://yale-lily.github.io/spider). - -Recommended mehen direction: - -- Add a **dedicated SQL metric category** rather than mapping everything to `functions`, `classes`, or generic cyclomatic complexity. -- Report SQL metrics at several spaces: `sql.file`, `sql.statement`, `sql.query_block`, `sql.cte`, `sql.object`, and, when procedural dialect support is available, `sql.routine` / `sql.block`. -- Implement a deterministic AST/fact extractor that emits statement facts, query-block facts, CTE dependency graph facts, join graph facts, expression/predicate facts, identifier scope facts, write-risk facts, and parser confidence facts. -- Use composite scores only after exposing raw metrics. The composite scores should be explainable, contributor-backed, and initially treated as review prioritization signals rather than absolute quality judgments. - ---- - -## 2. Context from mehen architecture - -The mehen rewrite plan already establishes the right extension model for SQL: metric identifiers/selectors/formulas live in a shared metrics layer, while language crates own language interpretation and emit language-specific contribution evidence. SQL should follow the same principle as Markdown: shared output contracts, language-owned semantics. - -For SQL this matters because a syntactic element can have multiple metric meanings depending on dialect and file role. For example, `CASE` in a SELECT list affects expression/cognitive burden; `CASE` in PL/SQL procedural control flow affects cyclomatic complexity; `CREATE TABLE AS SELECT` is both DDL and a query-producing statement; `MERGE` is a write-risk signal; and a `WITH` clause can either improve readability by naming subqueries or hurt readability if it creates a deep dependency chain. - -Proposed crate-level architecture: - -```text -mehen-sql - ├── parser_adapter # sqruff / SQLFluff Rust parser integration boundary - ├── ast_facts # dialect-normalized facts; no metric formulas - ├── scopes # CTE, table alias, column-reference, outer-reference scopes - ├── graphs # CTE dependency graph, join graph, optional lineage graph - ├── metrics_raw # raw counts, ratios, depths - ├── metrics_composite # weighted explainable scores - └── reporters # MetricContribution line ranges and reason codes -``` - -The metric design below assumes source spans are available from the chosen parser. If a parser node lacks reliable source spans, mehen should still compute file-level metrics, but it should lower confidence for top-offender line attribution. - ---- - -## 3. Prior art review - -### 3.1 SonarQube / SonarSource - -Sonar’s general metric model includes: - -- `complexity`: cyclomatic complexity, described as a quantitative metric for paths through code. -- `cognitive_complexity`: a qualification of how hard code control flow is to understand. -- size metrics such as lines, non-comment lines of code, functions, statements, and comment lines. -- maintainability metrics tied to issues and technical debt. - -Sonar documents PL/SQL cyclomatic complexity at function/procedure level and increments it for procedural constructs: the main anonymous block, `CREATE PROCEDURE`, `CREATE TRIGGER`, loops, `WHEN` in CASE, cursor loops, `CONTINUE`/`EXIT WHEN`, exception handlers, `IF`, `ELSIF`, `RAISE`, `AND`, `OR`, and related constructs. That is a useful model for `sql.procedural.*`, but it is not a complete model for ordinary SELECT-heavy files because a SELECT with ten joins and five CTEs may have no imperative branches while still being difficult to review. - -Sonar’s T-SQL page also highlights a practical mehen design issue: file suffix alone is not enough. Sonar defaults `.tsql` to T-SQL and `.sql` to PL/SQL, and lets projects override suffixes. mehen should avoid this trap by requiring or inferring a dialect and by exposing dialect confidence. - -Sonar’s PL/SQL analyzer can optionally query Oracle data dictionary views through JDBC. That means some official SQL analysis is schema-aware. mehen’s baseline should remain standalone/static, but optional schema/context enrichments should be possible and clearly tagged. - -Recommended takeaways: - -- Use Sonar’s PL/SQL cyclomatic model as a reference for procedural SQL constructs. -- Do not call declarative query complexity “cyclomatic complexity” unless a control-flow graph exists. -- Treat `.sql` dialect inference as a first-class confidence problem. -- Keep schema-aware signals separate from standalone metrics. - -### 3.2 SQLFluff - -SQLFluff is an extensible, modular SQL linter. Its architecture is especially relevant because it parses SQL into a tree of segments and traverses that tree to run rules. The architecture stages are templater, lexer, parser, and linter. The parser uses dialect grammars, creates a `FileSegment` containing `StatementSegment`s, and can emit `UnparsableSegment`s when no grammar matches. Rule classes traverse the parse tree and return lint results for matching patterns. - -SQLFluff itself is primarily a linter/formatter, but its rules encode practical maintainability judgments. Examples that should influence mehen metric contributors: - -- `structure.nested_case`: nested CASE in ELSE can often be flattened. -- `structure.subquery`: subqueries in `FROM`/`JOIN` can often be moved into CTEs. -- `structure.column_order`: order SELECT targets by complexity. -- `structure.unused_cte`: CTE defined but unused. -- `structure.unused_join`: joined table not referenced elsewhere. -- `ambiguous.column_count`: SELECT `*` can hide output shape. -- `ambiguous.join_condition`: implicit cross join. -- `references.qualification`: qualify references when multiple tables are present. - -Recommended takeaways: - -- Reuse the parser and structural rule vocabulary as inspiration. -- Do not turn lints directly into metrics; convert them into measured contributors such as `sql.select.star_count`, `sql.cte.unused_count`, `sql.join.implicit_cross_count`, and `sql.case.max_depth`. -- Preserve metric neutrality: a high count is descriptive first; thresholding belongs to profiles. - -### 3.3 sqruff - -Sqruff is a Rust SQL linter and formatter, inspired by SQLFluff and Ruff. Its docs emphasize fast linting/fixing, valid SQL for specific dialects, and experimental SQL column lineage support. Its rule index closely mirrors the SQLFluff-inspired families: aliasing, ambiguity, conventions, layout, references, and structure rules. - -Sqruff is especially attractive for mehen because it is Rust-native and already models dialect-specific SQL. The column-level lineage feature is also directly relevant to optional dataflow metrics such as lineage graph width/depth and ambiguous source ratio. - -Recommended takeaways: - -- Prefer a narrow parser adapter that converts sqruff/SQLFluff nodes into mehen `SqlFact`s rather than coupling metrics to parser-internal node names. -- If column lineage is exposed through a stable API, add optional `sql.lineage.*` metrics. If not, start with CTE/table-level lineage and leave column-level lineage as a vNext enhancement. - -### 3.4 SQLFluff complexity plugin - -`sqlfluff-complexity` is the most directly relevant current practical prior art. Its CPX rules include: - -| Rule | Metric idea | Default threshold | -|---|---:|---:| -| `CPX_C101` | CTE count | 8 | -| `CPX_C102` | Join count | 8 | -| `CPX_C103` | Nested subquery depth | 3 | -| `CPX_C104` | CASE expressions | 10 | -| `CPX_C105` | Boolean AND/OR operators | 20 | -| `CPX_C106` | Window functions | 10 | -| `CPX_C107` | Longest CTE dependency chain | 5 | -| `CPX_C108` | Nested CASE depth | 10 | -| `CPX_C109` | Set operations | 12 | -| `CPX_C110` | Inline derived tables | 4 | -| `CPX_C201` | Aggregate weighted complexity score | 60 | - -The plugin also documents an aggregate score as a weighted sum of CTEs, joins, subquery depth, CASE expressions, boolean operators, window functions, CTE dependency depth, set operation count, expression depth / CASE depth, and derived tables. - -Recommended takeaways: - -- Use CPX metric families as a conservative first compatibility profile, perhaps named `sql.profile.analytics_default`. -- Retain CPX thresholds as soft starting points only. Repositories differ: an analytics warehouse model and a migration script have different complexity budgets. -- mehen should go beyond CPX by adding object-touch risk, DDL/DML risk, output-shape clarity, identifier qualification, dialect portability, parser confidence, and optional lineage. - -### 3.5 Scientific and empirical literature - -#### 3.5.1 Vashistha & Jain: SQLShare query complexity - -Vashistha and Jain’s “Measuring Query Complexity in SQLShare Workload” is a strong foundation because it explicitly frames query complexity as **cognitive load on users authoring SQL**, not just database server cost. They analyzed a high-variety SQLShare workload and considered metrics such as number of tables, number of columns, query length, numbers of operators, expression operators, and runtime. They also adapted Halstead measures to SQL by treating referenced columns as operands and operators/expressions as Halstead operators. - -Their paper’s key implications for mehen: - -- Query complexity is not equivalent to optimizer runtime. -- Operators and expressions were dominant factors in their analysis. -- Halstead-style SQL metrics are plausible, but the operator/operand taxonomy must be SQL-specific and explicit. -- Linear regression on a small hand-labeled set had limitations, so mehen should expose raw metrics and avoid overclaiming a universal formula. - -#### 3.5.2 Piattini & Martínez: SQL maintainability - -Piattini and Martínez argued that most software metrics had historically focused on 3GL code while disregarding databases and SQL, and they described three simple measures for SQL code maintainability validated with a student experiment and a real organizational case. The available abstract does not expose the full formulas, but the paper is important prior art because it treats SQL code maintainability as its own measurement subject rather than as an afterthought of host-language metrics. - -#### 3.5.3 Siau, Chan & Wei: query complexity and novice users - -Siau, Chan, and Wei studied effects of query complexity and learning on novice user query performance. Their results indicate that complex queries affect accuracy, confidence, and time, and that interface abstraction can change how users handle complex queries. This supports the idea that structural SQL burden is partly a human-comprehension problem, not only a database-performance problem. - -#### 3.5.4 Taipalus: database complexity and query formulation - -Taipalus studied 744 students querying three databases of varying logical complexity and found that increased database complexity lowered success rates and increased unnecessary complications. For mehen, this is a reminder that standalone SQL file metrics are incomplete without schema complexity. Baseline mehen should still be standalone, but any future schema-aware mode should include schema/object graph metrics. - -#### 3.5.5 Spider / text-to-SQL hardness criteria - -The Spider benchmark divides SQL queries into easy, medium, hard, and extra hard categories based on numbers of SQL components, selections, and conditions. Queries with more SQL keywords such as `GROUP BY`, `ORDER BY`, `INTERSECT`, nested subqueries, selected columns, and aggregators are considered harder. Although Spider is an ML benchmark, its hardness criteria align well with static query complexity features that mehen can calculate. - -#### 3.5.6 Subali & Rochimah: SQL command complexity - -Subali and Rochimah proposed a model for measuring software complexity that accounts for SQL query attributes in database systems. Their model is described as a five-stage process: reading program modules, forming SQL query models, assigning SQL query weights, calculating SQL complexity, and producing module complexity results. This supports a weighted-attribute approach, but mehen should make each attribute and weight transparent. - -#### 3.5.7 Miedema, Fletcher & Aivaloglou: SQL learners and complexity management - -The “So many brackets!” ICPC 2022 work analyzes how SQL learners manage or mismanage complexity during query formulation. For mehen, the main relevance is not to model novice errors directly, but to recognize that nested structure, brackets/subqueries, and query formulation complexity are part of program comprehension for SQL. - ---- - -## 4. Design principles for mehen SQL metrics - -### 4.1 AST-first, not regex-first - -All metrics should be derived from parser facts. Regex can be used only for pre-parse hints, dialect detection hints, or comment/line classification when the parser does not expose trivia. Metric contributors must reference AST-derived constructs whenever possible. - -### 4.2 Standalone by default; schema-aware only as an enhancement - -Baseline metrics must work without a live database, schema registry, dbt manifest, or query plans. Schema-aware analysis can improve reference resolution, key inference, object blast-radius estimation, and lineage, but it must be opt-in and tagged, for example: - -```text -sql.analysis.mode = standalone -sql.analysis.schema_context = none -sql.analysis.confidence.reference_resolution = 0.62 -``` - -### 4.3 Dialect-aware, not `.sql`-extension-aware - -A `.sql` suffix is ambiguous. mehen should accept an explicit dialect and optionally auto-detect a dialect with confidence. Dialect auto-detection should remain conservative: better to report `sql.dialect.confidence.low` than to misclassify T-SQL as PL/SQL or Snowflake as ANSI. - -### 4.4 Statement-first, not function-first - -For declarative SQL, the primary analysis spaces should be: - -```text -sql.file -sql.batch -sql.statement -sql.query_block -sql.cte -sql.object -``` - -Only procedural dialect constructs should create `sql.routine` or `sql.block` spaces. - -### 4.5 Separate descriptive metrics from prescriptive rules - -Metrics answer “what is present?” Rules answer “is this acceptable?” For example: - -- Metric: `sql.select.star_count = 3` -- Contributor: `select_star_in_outer_query` at line 42 -- Rule/profile decision: fail only if `select_star_count > 0` in strict production profile. - -### 4.6 Complexity is review burden, not query performance - -Unless mehen consumes query plans, it should not claim to estimate runtime cost. Static metrics such as joins, subqueries, predicates, and functions can correlate with review burden and sometimes performance risk, but they are not optimizer cost. - -### 4.7 Every composite score must be explainable - -For top-offender reporting, a composite score should include the exact contributing factors, weights, and line ranges: - -```text -sql.cognitive_complexity = 67 -contributors: - +12 cte_dependency_depth=6 lines 1-88 - +10 correlated_subquery_count=2 lines 42-61 - +9 boolean_operator_count=18 lines 73-77 - +8 join_count=8 lines 18-39 -``` - -### 4.8 Profile thresholds should be calibrated - -Default thresholds should be starting points. mehen should support repository percentiles, historical deltas, and profile-specific gates. Absolute thresholds for migration scripts, analytics models, and stored procedures should differ. - ---- - -## 5. Proposed SQL fact model - -The metric layer should not depend on parser-internal node classes. It should depend on normalized facts. - -### 5.1 File facts - -```rust -struct SqlFileFacts { - dialect_requested: Option, - dialect_inferred: Option, - dialect_confidence: f32, - source_lines: LineMap, - statements: Vec, - parser_diagnostics: Vec, - comments: Vec, - templating_tokens: Vec, -} -``` - -### 5.2 Statement facts - -```rust -struct SqlStatementFacts { - id: StatementId, - kind: SqlStatementKind, - span: SourceSpan, - query: Option, - dml: Option, - ddl: Option, - dcl: Option, - tcl: Option, - procedural: Option, -} -``` - -Suggested `SqlStatementKind` values: - -```text -select -with_select -insert_values -insert_select -update -delete -merge -create_view -create_table -create_table_as -create_materialized_view -alter_table -drop -truncate -grant -revoke -begin_transaction -commit -rollback -explain -procedure_or_function -anonymous_block -unknown -``` - -### 5.3 Query-block facts - -A query block is a SELECT-like relational unit: a `SELECT` core, a CTE body, a subquery, a branch of a set operation, or a SELECT inside `INSERT ... SELECT` / `CREATE TABLE AS SELECT`. - -```rust -struct SqlQueryBlockFacts { - id: QueryBlockId, - span: SourceSpan, - nesting_depth: u32, - select_items: Vec, - from_items: Vec, - joins: Vec, - predicates: Vec, - group_by: Option, - having: Option, - windows: Vec, - order_by: Option, - limit_offset: Option, - subqueries: Vec, - set_ops: Vec, -} -``` - -### 5.4 Scope and identifier facts - -```rust -struct SqlScopeFacts { - cte_defs: Vec, - relation_aliases: Vec, - column_refs: Vec, - unresolved_refs: Vec, - outer_refs: Vec, - wildcard_refs: Vec, -} -``` - -The most valuable standalone resolution is not perfect schema resolution; it is scope resolution: - -- Which names are CTEs? -- Which names are relation aliases? -- Which subqueries reference outer aliases? -- Which SELECT items are derived expressions lacking aliases? -- Which references are unqualified in multi-relation scopes? - -### 5.5 Graph facts - -```rust -struct SqlGraphFacts { - cte_graph: DirectedGraph, - relation_join_graphs: Vec, - object_read_write_graph: ObjectTouchGraph, - column_lineage_graph: Option, -} -``` - -Graph metrics should be computed after query facts and scope facts are available. - ---- - -## 6. Metric namespaces and raw metric catalogue - -The following keys are intentionally explicit. They can later be shortened or grouped by selectors, but the first implementation should optimize clarity and grepability. - -### 6.1 Line and size metrics - -| Metric key | Type | Definition | Notes | -|---|---:|---|---| -| `sql.loc.physical` | int | Physical lines in file | Includes comments/blanks. | -| `sql.loc.code` | int | Lines containing SQL code tokens | Excludes pure comment/blank lines. | -| `sql.loc.comment` | int | Lines containing SQL comments | `--`, `/* ... */`, dialect comments. | -| `sql.loc.blank` | int | Blank/whitespace-only lines | Raw line map. | -| `sql.loc.logical` | int | Logical SQL statements | Usually AST statement count, not semicolon count. | -| `sql.loc.comment_density` | float | `comment / max(1, code + comment)` | Useful but not a quality score. | -| `sql.loc.max_statement_lines` | int | Max code-span length of any statement | Top-offender-friendly. | -| `sql.loc.avg_statement_lines` | float | Mean statement span length | Report with median if possible. | - -SQL-specific caveat: semicolons are not reliable statement separators in all dialects and contexts; T-SQL batches may use `GO`, PL/SQL blocks may contain semicolons inside procedural bodies, and some tools omit terminators. Prefer parser statements. - -### 6.2 Statement composition metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.statement.count` | int | Number of top-level statements. | -| `sql.statement.batch_count` | int | Number of parser-recognized batches or batch separators. | -| `sql.statement.kind_count.` | int | Count by normalized statement kind. | -| `sql.statement.kind_distinct` | int | Number of statement kinds present. | -| `sql.statement.kind_entropy` | float | Normalized Shannon entropy over statement kinds. | -| `sql.statement.max_complexity` | float | Max per-statement composite score. | -| `sql.statement.unparsed_count` | int | Top-level statements with parser failure/unknown kind. | - -`kind_entropy` is useful for mixed migration scripts. A file containing only `CREATE TABLE` statements has low entropy; a file mixing DDL, DML, transactions, grants, functions, and queries has higher operational complexity. - -Formula: - -```text -H = -Σ p(kind) * log2(p(kind)) -sql.statement.kind_entropy = H / log2(max(2, distinct_kind_count)) -``` - -### 6.3 Query-block metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.query_block.count` | int | Count of SELECT-like query blocks. | -| `sql.query_block.max_depth` | int | Maximum query-block nesting depth. | -| `sql.query_block.avg_select_items` | float | Mean SELECT item count per query block. | -| `sql.query_block.max_select_items` | int | Maximum SELECT item count. | -| `sql.query_block.max_clause_count` | int | Max number of major clauses in a query block. | -| `sql.query_block.with_clause_count` | int | Number of WITH clauses. | - -Major clauses include SELECT, FROM, WHERE, GROUP BY, HAVING, WINDOW/QUALIFY where applicable, ORDER BY, LIMIT/OFFSET/FETCH, set operation, and dialect-specific clauses such as PIVOT/UNPIVOT, CONNECT BY, MODEL, SAMPLE, QUALIFY. - -### 6.4 CTE metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.cte.count` | int | Number of CTE definitions. | -| `sql.cte.recursive_count` | int | Recursive CTEs. | -| `sql.cte.dependency_edges` | int | Edges from one CTE to another referenced CTE. | -| `sql.cte.max_dependency_depth` | int | Longest CTE dependency chain. | -| `sql.cte.max_fan_in` | int | Max number of upstream CTEs referenced by a CTE. | -| `sql.cte.max_fan_out` | int | Max number of downstream CTEs using a CTE. | -| `sql.cte.unused_count` | int | CTEs defined but not used by final query or downstream CTEs. | -| `sql.cte.trivial_count` | int | CTEs that only rename/select from one source with no filtering/aggregation/join. | -| `sql.cte.shadowed_name_count` | int | CTE names shadowing relation aliases or repeated names in nested scopes. | -| `sql.cte.avg_body_complexity` | float | Mean structural score of CTE query bodies. | - -CTEs should not be treated as automatically good or bad. A CTE can improve reviewability by naming a concept; too many CTEs or a deep dependency chain can make dataflow hard to trace. - -### 6.5 Join and relation graph metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.relation.ref_count` | int | Relation references, including base tables, views, CTE refs, derived tables. | -| `sql.relation.base_ref_count` | int | Base table/view refs, excluding CTEs and derived tables where known. | -| `sql.relation.distinct_object_count` | int | Distinct named objects touched for reads. | -| `sql.join.count` | int | Explicit join clauses. | -| `sql.join.kind_count.` | int | Join count by kind: inner, left, right, full, cross, natural, lateral, apply, implicit. | -| `sql.join.outer_count` | int | LEFT/RIGHT/FULL joins. | -| `sql.join.cross_count` | int | CROSS joins and implicit cross joins. | -| `sql.join.natural_count` | int | NATURAL joins. | -| `sql.join.non_equi_count` | int | Join predicates without equality between relation columns. | -| `sql.join.complex_condition_count` | int | Join conditions with boolean depth above threshold. | -| `sql.join.missing_condition_count` | int | Joins lacking ON/USING where required or implicit comma joins. | -| `sql.join.graph_node_count` | int | Nodes in relation join graph. | -| `sql.join.graph_edge_count` | int | Edges in relation join graph. | -| `sql.join.graph_component_count` | int | Connected components. | -| `sql.join.graph_surplus_edges` | int | `max(0, E - N + C)` over relation graph. | -| `sql.join.self_join_count` | int | Same base object referenced multiple times in one scope. | - -Join graph construction should use relation aliases as nodes and join predicates as edges. Without schema, foreign-key semantics are unknown; the graph is about syntactic/review topology, not relational correctness. - -### 6.6 Subquery and scope metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.subquery.count` | int | All nested SELECT-like subqueries. | -| `sql.subquery.max_depth` | int | Maximum nested subquery depth. | -| `sql.subquery.correlated_count` | int | Subqueries with references to outer query scopes. | -| `sql.subquery.scalar_count` | int | Scalar subqueries in SELECT/predicate expressions. | -| `sql.subquery.exists_count` | int | `EXISTS` / `NOT EXISTS` subqueries. | -| `sql.subquery.in_count` | int | `IN (SELECT ...)` subqueries. | -| `sql.derived_table.count` | int | Inline subqueries in FROM/JOIN. | -| `sql.derived_table.max_depth` | int | Nested derived-table depth. | - -Correlated subqueries deserve separate weight: they combine nested query structure with outer scope coupling. They may be the strongest single standalone signal of high comprehension burden after deep CTE chains and large join graphs. - -### 6.7 Predicate and boolean logic metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.predicate.count` | int | WHERE, HAVING, ON, QUALIFY, CHECK, FILTER predicates. | -| `sql.predicate.boolean_operator_count` | int | Count of `AND`/`OR` boolean operators. | -| `sql.predicate.max_boolean_depth` | int | Max nesting depth of boolean expression tree. | -| `sql.predicate.max_or_chain_length` | int | Max OR chain length. | -| `sql.predicate.not_count` | int | `NOT` operators. | -| `sql.predicate.comparison_count` | int | Equality, inequality, range, LIKE, IN, BETWEEN, etc. | -| `sql.predicate.in_list_max_length` | int | Longest literal/value IN list. | -| `sql.predicate.null_semantics_risk_count` | int | `NOT IN`, `= NULL`, `<> NULL`, or dialect-risky NULL logic. | -| `sql.predicate.sargability_risk_count` | int | Function/cast/arithmetic on column side, leading wildcard LIKE, regex, etc. | -| `sql.predicate.mixed_and_or_without_grouping_count` | int | Boolean chains where precedence may be non-obvious. | - -`sql.predicate.sargability_risk_count` is not a performance prediction; it is a static risk indicator. A function on a column in a predicate may be appropriate, but it is worth surfacing for review. - -### 6.8 CASE and conditional expression metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.case.count` | int | CASE expressions/statements. | -| `sql.case.max_depth` | int | Max nested CASE depth. | -| `sql.case.when_count` | int | Total WHEN arms. | -| `sql.case.max_when_count` | int | Maximum WHEN arms in a single CASE. | -| `sql.case.missing_else_count` | int | CASE expressions without ELSE. | -| `sql.case.nested_in_else_count` | int | Nested CASE inside ELSE branch. | -| `sql.case.condition_complexity_max` | int | Max predicate complexity inside WHEN conditions. | - -CASE is one of the clearest bridges between declarative SQL and cognitive control-flow burden. - -### 6.9 Aggregation and grouping metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.aggregate.function_count` | int | Aggregate function calls. | -| `sql.aggregate.distinct_count` | int | Aggregate calls with DISTINCT. | -| `sql.group_by.count` | int | GROUP BY clauses. | -| `sql.group_by.max_expression_count` | int | Max grouping expressions in one clause. | -| `sql.group_by.rollup_count` | int | ROLLUP usage. | -| `sql.group_by.cube_count` | int | CUBE usage. | -| `sql.group_by.grouping_sets_count` | int | GROUPING SETS usage. | -| `sql.having.count` | int | HAVING clauses. | -| `sql.distinct.count` | int | SELECT DISTINCT occurrences. | - -Grouping modifiers can significantly increase semantic burden because they change output cardinality and subtotal semantics. - -### 6.10 Window function metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.window.function_count` | int | Window function calls with `OVER`. | -| `sql.window.distinct_spec_count` | int | Distinct window specifications. | -| `sql.window.repeated_inline_spec_count` | int | Repeated inline specs that could be named/reused where dialect allows. | -| `sql.window.partition_expression_count` | int | Total PARTITION BY expressions. | -| `sql.window.order_expression_count` | int | Total ORDER BY expressions inside windows. | -| `sql.window.frame_count` | int | Explicit window frames. | -| `sql.window.max_spec_complexity` | int | Max weighted partition/order/frame complexity. | -| `sql.window.rank_function_count` | int | RANK/DENSE_RANK/ROW_NUMBER/NTILE etc. | -| `sql.window.percentile_function_count` | int | Percentile/distribution functions. | - -Window functions often look compact but require reviewers to reason about partitions, order, frame semantics, and interaction with query-level grouping. - -### 6.11 Set operation metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.set_op.count` | int | UNION, INTERSECT, EXCEPT/MINUS operations. | -| `sql.set_op.kind_count.` | int | Count by set operation kind. | -| `sql.set_op.max_depth` | int | Nested set-expression depth. | -| `sql.set_op.union_all_ratio` | float | UNION ALL / UNION total. | -| `sql.set_op.distinct_count` | int | Set operations with duplicate elimination semantics. | -| `sql.set_op.branch_count_max` | int | Maximum number of branches in one set expression. | - -Set operations affect both output shape and duplicate semantics. `UNION` without explicit `ALL` or `DISTINCT` is also an ambiguity/style smell in some dialects. - -### 6.12 Expression and function-call metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.expression.count` | int | Count of non-trivial expressions. | -| `sql.expression.max_depth` | int | Max expression AST depth. | -| `sql.expression.avg_depth` | float | Mean non-trivial expression depth. | -| `sql.expression.operator_count` | int | Arithmetic/string/comparison/special operators in expressions. | -| `sql.function.call_count` | int | Function calls. | -| `sql.function.distinct_count` | int | Distinct function names. | -| `sql.function.nested_call_depth` | int | Max nested function-call depth. | -| `sql.cast.count` | int | Casts and dialect cast operators. | -| `sql.json_path.count` | int | JSON/path operators/functions. | -| `sql.regex.count` | int | Regex predicates/functions. | -| `sql.literal.count` | int | Literal values. | -| `sql.literal.long_string_count` | int | String literals over configurable threshold. | - -Expression depth and function nesting are especially important in SELECT lists, CASE arms, predicates, and ORDER BY clauses. - -### 6.13 Output-shape and readability metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.select.star_count` | int | `*` or `table.*` projections. | -| `sql.select.outer_star_count` | int | Wildcards in outermost query blocks. | -| `sql.select.expression_without_alias_count` | int | Derived SELECT expressions without alias. | -| `sql.select.output_alias_coverage` | float | Aliased derived expressions / derived expressions. | -| `sql.identifier.unqualified_column_ratio` | float | Unqualified refs in multi-relation scopes / all column refs. | -| `sql.identifier.quoted_count` | int | Quoted identifiers. | -| `sql.identifier.keyword_identifier_count` | int | Identifiers that are reserved/keyword-like. | -| `sql.identifier.ordinal_reference_count` | int | ORDER BY/GROUP BY ordinal references. | -| `sql.alias.table_alias_count` | int | Table aliases. | -| `sql.alias.short_alias_count` | int | Aliases shorter than threshold. | -| `sql.alias.reused_count` | int | Reused aliases in overlapping scopes. | -| `sql.alias.unused_count` | int | Aliases defined but unused. | -| `sql.name.length_mean` | float | Mean identifier length for aliases and output columns. | - -These metrics should be interpreted as reviewability signals, not universal style rules. Short aliases such as `o` and `c` can be acceptable in small queries; they become painful in large join graphs. - -### 6.14 Object-touch and migration risk metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.object.read_count` | int | Distinct objects read. | -| `sql.object.write_count` | int | Distinct objects written/created/altered/dropped. | -| `sql.object.touch_count` | int | Distinct read or write objects. | -| `sql.object.temp_count` | int | Temporary/transient objects. | -| `sql.object.schema_qualified_ratio` | float | Schema-qualified object refs / object refs. | -| `sql.dml.insert_count` | int | INSERT statements. | -| `sql.dml.update_count` | int | UPDATE statements. | -| `sql.dml.delete_count` | int | DELETE statements. | -| `sql.dml.merge_count` | int | MERGE statements. | -| `sql.dml.update_without_where_count` | int | UPDATE with no WHERE / limited predicate. | -| `sql.dml.delete_without_where_count` | int | DELETE with no WHERE / limited predicate. | -| `sql.dml.returning_count` | int | RETURNING/OUTPUT clauses. | -| `sql.ddl.create_count` | int | CREATE statements. | -| `sql.ddl.alter_count` | int | ALTER statements. | -| `sql.ddl.drop_count` | int | DROP statements. | -| `sql.ddl.truncate_count` | int | TRUNCATE statements. | -| `sql.ddl.create_or_replace_count` | int | CREATE OR REPLACE statements. | -| `sql.dcl.grant_revoke_count` | int | GRANT/REVOKE statements. | -| `sql.transaction.control_count` | int | BEGIN/COMMIT/ROLLBACK/SAVEPOINT etc. | -| `sql.dynamic_sql.count` | int | EXECUTE IMMEDIATE / dynamic SQL constructs. | - -This family is essential for standalone `.sql` files because migration risk can be much more important than query-expression complexity. A three-line `DROP TABLE` script is structurally simple but operationally critical. - -### 6.15 Dialect and portability metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.dialect.requested` | enum | Dialect configured by user/project. | -| `sql.dialect.inferred` | enum | Best inferred dialect, if any. | -| `sql.dialect.confidence` | float | 0..1 confidence in inferred dialect. | -| `sql.dialect.feature_count` | int | Recognized dialect-specific features. | -| `sql.dialect.feature_count.` | int | Counts for `qualify`, `top`, `limit`, `connect_by`, `pivot`, `unpivot`, `lateral`, `apply`, `json`, arrays, etc. | -| `sql.dialect.portability_risk_count` | int | Features outside ANSI/core profile. | -| `sql.dialect.conflict_count` | int | Hints pointing to multiple dialects. | - -This metric family is especially useful in multi-engine repositories or libraries that claim portability. - -### 6.16 Parser health and analysis confidence metrics - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.parser.diagnostic_count` | int | Parser diagnostics. | -| `sql.parser.unparsable_segment_count` | int | Unparsable AST segments. | -| `sql.parser.unparsable_line_count` | int | Lines touched by unparsable segments. | -| `sql.parser.unparsable_ratio` | float | Unparsable code lines / code lines. | -| `sql.parser.recovery_count` | int | Parser recovery events, if available. | -| `sql.analysis.confidence.syntax` | float | Syntax analysis confidence. | -| `sql.analysis.confidence.scope` | float | Scope/reference resolution confidence. | -| `sql.analysis.confidence.line_spans` | float | Source attribution confidence. | -| `sql.templating.token_count` | int | Jinja/placeholders/template tokens. | -| `sql.templating.unresolved_count` | int | Template constructs not resolved to SQL. | - -Standalone SQL often contains templating, variables, placeholders, or dialect features that parsers only partially understand. Confidence metrics prevent false precision. - -### 6.17 Procedural SQL metrics - -These should apply only when the parser recognizes PL/SQL, T-SQL, or another procedural dialect block. - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.procedural.block_count` | int | Anonymous/procedural blocks. | -| `sql.procedural.routine_count` | int | Procedures/functions/triggers. | -| `sql.procedural.cyclomatic_complexity` | int | Control-flow complexity using dialect rules. | -| `sql.procedural.cognitive_complexity` | int | Cognitive flow complexity for procedural blocks. | -| `sql.procedural.max_block_depth` | int | Nested procedural block depth. | -| `sql.procedural.loop_count` | int | Loops/cursors. | -| `sql.procedural.if_count` | int | IF/ELSIF branches. | -| `sql.procedural.case_statement_count` | int | CASE statements in control flow. | -| `sql.procedural.exception_handler_count` | int | Exception/catch handlers. | -| `sql.procedural.return_count` | int | Return statements. | -| `sql.procedural.raise_throw_count` | int | Raise/throw statements. | -| `sql.procedural.dynamic_sql_count` | int | Dynamic SQL in procedural code. | - -For PL/SQL, Sonar’s documented increments are a useful starting point. For T-SQL, mehen should define a separate dialect table, because T-SQL has `TRY/CATCH`, `WHILE`, cursor constructs, `GOTO`, `RETURN`, `THROW`, and batch semantics. - ---- - -## 7. SQL Halstead metrics - -Halstead metrics are attractive for SQL because many SQL queries have rich symbolic structure without imperative branches. Radon’s general Halstead definitions use: - -```text -η1 = number of distinct operators -η2 = number of distinct operands -N1 = total operators -N2 = total operands -η = η1 + η2 -N = N1 + N2 -V = N * log2(η) -D = (η1 / 2) * (N2 / η2) -E = D * V -``` - -Vashistha and Jain adapted Halstead to SQLShare queries by treating referenced columns as operands and operators/expressions as Halstead operators. mehen should define a more complete, deterministic SQL operator/operand taxonomy. - -### 7.1 Proposed SQL operator classes - -Operators should include: - -1. **Statement verbs:** `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `GRANT`, `REVOKE`, `COMMIT`, `ROLLBACK`. -2. **Clause operators:** `WITH`, `FROM`, `WHERE`, `GROUP BY`, `HAVING`, `ORDER BY`, `LIMIT`, `OFFSET`, `FETCH`, `QUALIFY`, `CONNECT BY`, `START WITH`, `RETURNING`. -3. **Join operators:** `JOIN`, `INNER JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`, `CROSS JOIN`, `NATURAL JOIN`, `LATERAL`, `APPLY`, `ON`, `USING`. -4. **Set operators:** `UNION`, `UNION ALL`, `INTERSECT`, `EXCEPT`, `MINUS`. -5. **Predicate operators:** `AND`, `OR`, `NOT`, `=`, `<>`, `!=`, `<`, `<=`, `>`, `>=`, `LIKE`, `ILIKE`, `SIMILAR TO`, `IN`, `BETWEEN`, `IS NULL`, `IS DISTINCT FROM`, `EXISTS`. -6. **Expression operators:** arithmetic, concatenation, JSON/path operators, array operators, casts, collations. -7. **Conditional operators:** `CASE`, `WHEN`, `THEN`, `ELSE`, `END`, dialect conditional functions if treated as built-ins. -8. **Aggregate/window operators:** aggregate function names, `OVER`, `PARTITION BY`, window `ORDER BY`, frame keywords. -9. **Function operators:** scalar function names, including dialect-specific built-ins. -10. **DDL type/constraint operators:** `PRIMARY KEY`, `FOREIGN KEY`, `UNIQUE`, `CHECK`, `DEFAULT`, `NOT NULL`, `REFERENCES`, `INDEX`, data type constructors. - -### 7.2 Proposed SQL operand classes - -Operands should include: - -1. Table/view/materialized view names. -2. CTE names. -3. Table aliases. -4. Column names and qualified column references. -5. Output aliases. -6. Literal values. -7. Bind parameters and placeholders. -8. Data types and sizes in DDL/casts. -9. Constraint/index names. -10. Schema/database names. - -### 7.3 Metric keys - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.halstead.distinct_operators` | int | `η1` | -| `sql.halstead.distinct_operands` | int | `η2` | -| `sql.halstead.total_operators` | int | `N1` | -| `sql.halstead.total_operands` | int | `N2` | -| `sql.halstead.vocabulary` | int | `η1 + η2` | -| `sql.halstead.length` | int | `N1 + N2` | -| `sql.halstead.volume` | float | `N * log2(η)` | -| `sql.halstead.difficulty` | float | `(η1 / 2) * (N2 / η2)` | -| `sql.halstead.effort` | float | `D * V` | - -### 7.4 Implementation cautions - -- Do not mix parser trivia with operator counts; comments and whitespace are not Halstead operators. -- Decide whether `AS` is an operator. Recommended: include it only when it creates an alias, not for dialect-noise appearances. -- Normalize equivalent operator spellings by dialect profile, for example `!=` and `<>` can be the same logical operator if the profile wants semantic normalization. -- Function names should be operators, not operands, because they transform operands. -- Aliases are operands because reviewers must track them; optionally distinguish alias operands from base object operands. - ---- - -## 8. Composite metrics - -Composite metrics are useful for ranking files and statements, but dangerous if opaque. mehen should report raw metrics first and composites second. - -### 8.1 SQL Structural Complexity (`sql.structural_complexity`) - -Purpose: a simple weighted syntactic complexity score for SELECT-like SQL. This is closest to `sqlfluff-complexity` CPX_C201 but expanded slightly. - -Suggested initial formula per statement/query: - -```text -SSC = - 1.00 * sql.query_block.count -+ 0.80 * sql.cte.count -+ 1.20 * sql.cte.max_dependency_depth -+ 1.00 * sql.join.count -+ 0.80 * sql.join.outer_count -+ 2.00 * sql.join.cross_count -+ 1.50 * sql.subquery.count -+ 1.25 * sql.subquery.max_depth -+ 2.00 * sql.subquery.correlated_count -+ 0.35 * sql.predicate.boolean_operator_count -+ 1.00 * sql.predicate.max_boolean_depth -+ 0.80 * sql.case.count -+ 0.80 * sql.case.max_depth -+ 0.60 * sql.window.function_count -+ 0.35 * sql.aggregate.function_count -+ 1.00 * sql.set_op.count -+ 0.50 * sql.expression.max_depth -+ 0.50 * sql.derived_table.count -``` - -Interpretation: - -- Low: simple query/script section. -- Medium: normal analytics query or migration statement. -- High: likely review bottleneck. - -Do not fail CI on this score initially. Use it to rank top offenders and calibrate thresholds. - -### 8.2 SQL Cognitive Complexity (`sql.cognitive_complexity`) - -Purpose: human comprehension burden. This should mimic the spirit of cognitive complexity, but use SQL-specific mental contexts rather than only imperative branches. - -Suggested scoring rules: - -1. Add `+1` for each query block. -2. Add `+nesting_depth` for subqueries and derived tables. -3. Add `+2` for each correlated subquery. -4. Add `+1` for each CTE and `+1` for each CTE dependency edge after the first edge in a chain. -5. Add `+1` for each join; add an extra `+1` for outer joins, non-equi joins, cross joins, natural joins, or APPLY/LATERAL joins. -6. Add `+1` for each CASE, plus `+1` for each nested CASE level, plus `+0.25` per WHEN arm beyond two. -7. Add `+0.25` per boolean operator, plus `+1` per boolean nesting level beyond two, plus `+1` for mixed AND/OR chains without explicit grouping. -8. Add `+0.5` per window function, plus `+1` for explicit frames. -9. Add `+0.5` per set operation, plus `+1` for nested set expressions. -10. Add `+0.25` per non-trivial SELECT expression without alias. -11. Add `+0.5` per wildcard projection in an outer query. -12. Subtract a small modularization credit, capped at `-5`, for CTEs that reduce derived-table nesting and have shallow dependency depth. - -Formula sketch: - -```text -SCC = max(0, - query_context_points -+ relational_reasoning_points -+ nested_scope_points -+ predicate_reasoning_points -+ expression_reasoning_points -+ output_shape_points -- modularization_credit -) -``` - -This score should be computed per statement and per file as sum/max. Report both: - -- `sql.cognitive_complexity.sum` -- `sql.cognitive_complexity.max_statement` - -### 8.3 SQL Review Burden Index (`sql.review_burden_index`) - -Purpose: rank SQL files/statements by likely PR review effort. - -Suggested file-level formula: - -```text -norm(x, t) = x / (x + t) - -RBI = 100 * clamp01( - 0.30 * norm(sql.cognitive_complexity.sum, 60) -+ 0.18 * norm(sql.structural_complexity.sum, 80) -+ 0.14 * norm(sql.object.touch_count, 20) -+ 0.12 * norm(sql.change_risk_score, 25) -+ 0.10 * norm(sql.halstead.volume, 1500) -+ 0.08 * norm(sql.parser.diagnostic_count, 5) -+ 0.05 * norm(sql.dialect.portability_risk_count, 20) -+ 0.05 * norm(sql.loc.code, 300) -- 0.02 * clamp01(sql.loc.comment_density / 0.20) -) -``` - -The comment-density credit is intentionally tiny. Comments can help, but they should not hide severe structural risk. - -### 8.4 SQL Change Risk Score (`sql.change_risk_score`) - -Purpose: operational risk in migrations and deployment scripts. - -Suggested scoring: - -```text -CRS = - 8 * drop_count -+ 8 * truncate_count -+ 6 * alter_table_count -+ 6 * delete_without_where_count -+ 6 * update_without_where_count -+ 5 * grant_revoke_count -+ 5 * dynamic_sql_count -+ 4 * merge_count -+ 4 * create_or_replace_count -+ 3 * transaction_control_count -+ 2 * write_object_count -+ 1 * read_object_count -``` - -This score should have separate profiles. A migration repository will naturally have DDL, so the goal is not “zero DDL”; the goal is to surface risky or broad changes. - -### 8.5 SQL Maintainability Index (`sql.maintainability_index`) - -Classic Maintainability Index uses SLOC, cyclomatic complexity, and Halstead volume. Radon documents common formulas and warns that MI is experimental. For SQL, classic MI is not directly appropriate because ordinary declarative queries may have little or no cyclomatic complexity. - -Recommended: do not call this classic MI. Use **SQL Maintainability Index** as a mehen-specific normalized score: - -```text -SQL_MI = 100 * clamp01(1 - risk) - -risk = - 0.22 * norm(sql.halstead.volume, 1500) -+ 0.22 * norm(sql.cognitive_complexity.sum, 60) -+ 0.16 * norm(sql.structural_complexity.sum, 80) -+ 0.12 * norm(sql.predicate.boolean_operator_count, 30) -+ 0.10 * norm(sql.cte.max_dependency_depth, 6) -+ 0.08 * norm(sql.subquery.max_depth, 4) -+ 0.05 * norm(sql.parser.diagnostic_count, 5) -+ 0.05 * norm(sql.dialect.portability_risk_count, 20) -``` - -Interpretation: - -- `80..100`: likely easy to maintain/review. -- `60..79`: normal complexity; inspect top contributors. -- `40..59`: high review burden. -- `<40`: likely refactoring or decomposition candidate. - -This should be marked experimental until calibrated on real repositories. - -### 8.6 SQL Modularity Health (`sql.modularity_health`) - -Purpose: avoid simplistic “more CTEs are good” or “fewer CTEs are good” conclusions. - -Components: - -```text -cte_use_ratio = used_cte_count / max(1, cte_count) -cte_shallow_score = 1 - norm(max_dependency_depth, 6) -cte_fanout_score = 1 - norm(max_fan_out, 8) -derived_table_penalty = norm(derived_table.count, 5) -trivial_cte_penalty = trivial_cte_count / max(1, cte_count) - -modularity_health = 100 * clamp01( - 0.35 * cte_use_ratio -+ 0.25 * cte_shallow_score -+ 0.15 * cte_fanout_score -+ 0.15 * (1 - derived_table_penalty) -+ 0.10 * (1 - trivial_cte_penalty) -) -``` - -This metric is only meaningful for query-like files with CTEs/subqueries. It should be omitted or marked N/A for pure DDL migrations. - -### 8.7 Optional lineage metrics - -If sqruff exposes stable column-level lineage or mehen later implements it, add: - -| Metric key | Type | Definition | -|---|---:|---| -| `sql.lineage.node_count` | int | Nodes in column lineage graph. | -| `sql.lineage.edge_count` | int | Edges in column lineage graph. | -| `sql.lineage.max_derivation_depth` | int | Longest derivation chain for output columns. | -| `sql.lineage.max_fan_in` | int | Max number of input columns feeding one output column. | -| `sql.lineage.max_fan_out` | int | Max number of downstream outputs using one input. | -| `sql.lineage.ambiguous_source_ratio` | float | Output columns with unresolved/ambiguous source lineage. | - -Lineage metrics are especially valuable for analytics SQL because reviewers often ask, “Where did this output column come from?” - ---- - -## 9. Suggested profiles and thresholds - -Thresholds should be configurable by profile. The defaults below are initial seeds, not universal truth. - -### 9.1 `sql.analytics_default` - -For dbt-like models, warehouse transformations, views, reports, analytical SELECT scripts. - -| Metric | Soft warning | Strong warning | Source/inspiration | -|---|---:|---:|---| -| `sql.cte.count` | >8 | >12 | `sqlfluff-complexity` CPX_C101 default 8 | -| `sql.join.count` | >8 | >12 | CPX_C102 default 8 | -| `sql.subquery.max_depth` | >3 | >5 | CPX_C103 default 3 | -| `sql.case.count` | >10 | >16 | CPX_C104 default 10 | -| `sql.predicate.boolean_operator_count` | >20 | >35 | CPX_C105 default 20 | -| `sql.window.function_count` | >10 | >16 | CPX_C106 default 10 | -| `sql.cte.max_dependency_depth` | >5 | >8 | CPX_C107 default 5 | -| `sql.case.max_depth` | >3 | >5 | stricter than CPX_C108 because 10 is very high for reviewability | -| `sql.set_op.count` | >12 | >20 | CPX_C109 default 12 | -| `sql.derived_table.count` | >4 | >8 | CPX_C110 default 4 | -| `sql.structural_complexity` | >60 | >100 | CPX_C201 default 60, adjusted by calibration | - -### 9.2 `sql.migration_default` - -For schema migrations, deployment scripts, seed scripts. - -Primary signals: - -- `sql.change_risk_score` -- `sql.object.write_count` -- `sql.ddl.drop_count` -- `sql.ddl.truncate_count` -- `sql.dml.update_without_where_count` -- `sql.dml.delete_without_where_count` -- `sql.transaction.control_count` -- `sql.parser.diagnostic_count` - -Suggested gates: - -| Metric | Warning | Critical | -|---|---:|---:| -| `sql.dml.update_without_where_count` | >0 | >0 with no transaction boundary | -| `sql.dml.delete_without_where_count` | >0 | >0 with no transaction boundary | -| `sql.ddl.drop_count` | >0 | >2 or affects non-temp objects | -| `sql.ddl.truncate_count` | >0 | >0 in production paths | -| `sql.object.write_count` | >10 | >25 | -| `sql.change_risk_score` | >25 | >60 | -| `sql.parser.unparsable_ratio` | >0.02 | >0.10 | - -### 9.3 `sql.procedural_default` - -For PL/SQL/T-SQL procedures, functions, triggers, anonymous blocks. - -Primary signals: - -- `sql.procedural.cyclomatic_complexity` -- `sql.procedural.cognitive_complexity` -- `sql.procedural.max_block_depth` -- `sql.procedural.exception_handler_count` -- `sql.procedural.dynamic_sql_count` -- embedded query structural complexity. - -Suggested gates: - -| Metric | Warning | Critical | -|---|---:|---:| -| `sql.procedural.cyclomatic_complexity` | >10 | >20 | -| `sql.procedural.cognitive_complexity` | >15 | >30 | -| `sql.procedural.max_block_depth` | >4 | >6 | -| `sql.procedural.dynamic_sql_count` | >0 | >3 | -| `sql.structural_complexity.max_embedded_query` | >60 | >100 | - -### 9.4 Repository-calibrated profile - -mehen should support percentile-driven thresholds: - -```text -warn if metric > p90(repository_baseline) -critical if metric > p97(repository_baseline) -warn on diff if metric_delta > max(absolute_delta, percentage_delta) -``` - -This is likely better than universal thresholds for mature projects. - ---- - -## 10. Metric contributors and top-offender examples - -A metric without contributors is hard to act on. Suggested contributor reason codes: - -```text -sql.cte.definition -sql.cte.dependency_edge -sql.cte.unused -sql.join.inner -sql.join.outer -sql.join.cross -sql.join.non_equi -sql.join.missing_condition -sql.subquery.nested -sql.subquery.correlated -sql.derived_table.inline -sql.predicate.boolean_operator -sql.predicate.deep_boolean_tree -sql.predicate.null_semantics_risk -sql.predicate.sargability_risk -sql.case.expression -sql.case.nested -sql.window.function -sql.window.frame -sql.aggregate.function -sql.set_op -sql.select.star -sql.select.expression_without_alias -sql.identifier.unqualified_column -sql.dml.update_without_where -sql.dml.delete_without_where -sql.ddl.drop -sql.ddl.truncate -sql.dynamic_sql -sql.parser.unparsable_segment -``` - -Example top-offender output: - -```text -models/revenue_rollup.sql - sql.review_burden_index: 84.2 - sql.cognitive_complexity.sum: 91 - sql.structural_complexity.sum: 116 - - contributors: - +18 sql.cte.max_dependency_depth=9 lines 1-136 - +15 sql.join.count=15 lines 42-83 - +12 sql.window.function_count=14 lines 91-119 - +10 sql.predicate.boolean_operator_count=28 lines 55-61 - +8 sql.subquery.correlated_count=2 lines 122-133 -``` - ---- - -## 11. Dialect strategy - -### 11.1 Dialect selection - -Recommended priority: - -1. Explicit CLI/config setting: `--sql-dialect postgres`. -2. Project config mapping by path: `migrations/** = postgres`, `warehouse/snowflake/** = snowflake`. -3. Parser-supported dialect inference from syntax hints. -4. Conservative fallback: `ansi` with low confidence. - -### 11.2 Dialect inference hints - -Examples: - -| Hint | Likely dialect(s) | -|---|---| -| `GO` batch separator, `TOP`, `CROSS APPLY` | T-SQL | -| `QUALIFY`, `IFF`, `::`, `COPY INTO` | Snowflake-ish, with ambiguity | -| `::` casts, `DISTINCT ON`, `ILIKE` | PostgreSQL-ish | -| backtick identifiers, `STRUCT`, `UNNEST` | BigQuery-ish | -| `CONNECT BY`, `MINUS`, PL/SQL blocks | Oracle/PLSQL | -| `LIMIT` | PostgreSQL/MySQL/SQLite/DuckDB/others; weak hint | - -Dialect inference should be advisory, not hidden. Always expose `sql.dialect.confidence`. - -### 11.3 Dialect-specific metric tables - -Some constructs should map to common metric concepts: - -| Common concept | Examples | -|---|---| -| row limiting | `LIMIT`, `FETCH FIRST`, `TOP` | -| lateral relation | `LATERAL`, `CROSS APPLY`, `OUTER APPLY` | -| set difference | `EXCEPT`, `MINUS` | -| conditional function | `IFF`, `IF`, `DECODE`, `NVL2` | -| null handling | `COALESCE`, `NVL`, `IFNULL` | -| temporary table | `#temp`, `CREATE TEMP TABLE`, `CREATE TEMPORARY TABLE` | - -Common metrics should use normalized concepts while also retaining dialect-specific counts. - ---- - -## 12. Implementation plan - -### Phase 1: Parser adapter and raw metrics - -Deliver: - -- Dialect selection/configuration. -- Parse diagnostics and confidence metrics. -- Statement count and statement kind classification. -- LOC/comment/blank/code metrics. -- Query-block count/depth. -- CTE count and dependency graph. -- Join count/kind metrics. -- Subquery and derived-table metrics. -- CASE, boolean predicate, window, aggregate, set-operation counts. -- SELECT `*`, missing alias, unqualified column ratio. -- Basic DDL/DML risk metrics. -- SQL Halstead counts. - -This phase is enough to produce valuable top-offender output. - -### Phase 2: Composite scores and profiles - -Deliver: - -- `sql.structural_complexity`. -- `sql.cognitive_complexity`. -- `sql.review_burden_index`. -- `sql.change_risk_score`. -- `sql.maintainability_index`. -- `sql.modularity_health`. -- Profile-based thresholds. -- Diff-aware deltas. - -### Phase 3: Procedural SQL - -Deliver: - -- PL/SQL and T-SQL procedural block detection. -- Procedural cyclomatic/cognitive complexity. -- Exception/cursor/loop/dynamic-SQL metrics. -- Embedded query complexity attribution inside routines. - -### Phase 4: Optional schema and lineage enrichments - -Deliver: - -- Optional schema catalog input. -- More accurate object/column reference resolution. -- Foreign-key-aware join graph classification. -- Optional sqruff lineage integration or mehen lineage implementation. -- Schema blast-radius metrics. - ---- - -## 13. JSON output sketch - -```json -{ - "language": "sql", - "dialect": { - "requested": "postgres", - "inferred": "postgres", - "confidence": 0.91 - }, - "analysis_mode": "standalone", - "metrics": { - "sql.loc.code": 184, - "sql.statement.count": 3, - "sql.query_block.count": 12, - "sql.cte.count": 9, - "sql.cte.max_dependency_depth": 6, - "sql.join.count": 11, - "sql.subquery.correlated_count": 1, - "sql.predicate.boolean_operator_count": 24, - "sql.window.function_count": 7, - "sql.structural_complexity.sum": 78.5, - "sql.cognitive_complexity.sum": 69, - "sql.review_burden_index": 72.4 - }, - "spaces": [ - { - "kind": "sql.statement", - "name": "statement#1 SELECT", - "span": { "start_line": 1, "end_line": 144 }, - "metrics": { - "sql.cte.count": 9, - "sql.join.count": 11, - "sql.cognitive_complexity": 69 - }, - "contributors": [ - { - "metric": "sql.cognitive_complexity", - "reason": "sql.cte.dependency_edge", - "delta": 8, - "span": { "start_line": 1, "end_line": 78 } - } - ] - } - ] -} -``` - ---- - -## 14. Validation strategy - -### 14.1 Golden fixtures - -Build fixtures by dialect and file role: - -```text -fixtures/sql/ansi/simple_select.sql -fixtures/sql/postgres/cte_chain.sql -fixtures/sql/postgres/correlated_subquery.sql -fixtures/sql/snowflake/qualify_windows.sql -fixtures/sql/bigquery/unnest_struct.sql -fixtures/sql/tsql/procedure_control_flow.sql -fixtures/sql/plsql/anonymous_block.sql -fixtures/sql/migration/destructive_ddl.sql -fixtures/sql/migration/safe_idempotent.sql -``` - -Each fixture should assert raw metrics and contributors. - -### 14.2 Prior-art compatibility tests - -Create a fixture suite for CPX-equivalent metrics: - -- CTE count. -- Join count. -- Nested subquery depth. -- CASE count. -- Boolean operator count. -- Window function count. -- CTE dependency depth. -- Nested CASE depth. -- Set operation count. -- Inline derived table count. - -The goal is not to clone `sqlfluff-complexity`, but to ensure mehen’s metric interpretations are explainable when they differ. - -### 14.3 Repository calibration - -Use several real repositories: - -- migration-heavy project. -- dbt/analytics project. -- app project with embedded standalone SQL files. -- PL/SQL/T-SQL stored procedure project. - -Measure distributions and tune default weights only after raw metrics are stable. - -### 14.4 Human validation - -Ask reviewers to rank sampled SQL files by expected review effort. Compare rankings against: - -- `sql.structural_complexity`. -- `sql.cognitive_complexity`. -- `sql.review_burden_index`. -- SQL Halstead volume/difficulty. -- LOC alone. - -The SQLShare paper used hand-labeled query complexity and found useful signal in operators/expressions; mehen should replicate that style of validation on repository SQL. - ---- - -## 15. Recommended first metric set for mehen 1.x SQL support - -For a high-value first release, implement these metrics before composites: - -```text -sql.loc.physical -sql.loc.code -sql.loc.comment -sql.loc.blank -sql.statement.count -sql.statement.kind_count.* -sql.query_block.count -sql.query_block.max_depth -sql.cte.count -sql.cte.max_dependency_depth -sql.cte.unused_count -sql.join.count -sql.join.kind_count.* -sql.join.cross_count -sql.join.non_equi_count -sql.subquery.count -sql.subquery.max_depth -sql.subquery.correlated_count -sql.derived_table.count -sql.predicate.boolean_operator_count -sql.predicate.max_boolean_depth -sql.case.count -sql.case.max_depth -sql.window.function_count -sql.aggregate.function_count -sql.set_op.count -sql.expression.max_depth -sql.function.call_count -sql.select.star_count -sql.select.expression_without_alias_count -sql.identifier.unqualified_column_ratio -sql.object.read_count -sql.object.write_count -sql.dml.update_without_where_count -sql.dml.delete_without_where_count -sql.ddl.drop_count -sql.ddl.truncate_count -sql.transaction.control_count -sql.parser.diagnostic_count -sql.parser.unparsable_ratio -sql.halstead.volume -sql.halstead.difficulty -``` - -Then add: - -```text -sql.structural_complexity -sql.cognitive_complexity -sql.change_risk_score -sql.review_burden_index -sql.maintainability_index -``` - ---- - -## 16. Open questions and decisions to make - -1. **Parser API stability:** sqruff is attractive because it is Rust-native, but mehen should verify the stability of its AST/source-span API before hard coupling. -2. **Dialect coverage:** choose a supported dialect subset for initial implementation. Recommended: `ansi`, `postgres`, `sqlite`, `mysql`, `tsql`, `oracle/plsql`, `snowflake`, `bigquery`, `duckdb` if parser support is mature enough. -3. **Templating stance:** this document targets standalone `.sql`, but real repositories often contain placeholders and Jinja. Decide whether mehen initially reports templating burden only or invokes SQLFluff/sqruff templaters. -4. **Threshold philosophy:** decide whether first release ships only raw metrics and top offenders, or also composite warnings. -5. **Procedural SQL boundary:** decide whether PL/SQL/T-SQL routines are part of initial SQL support or a separate milestone. -6. **Lineage dependency:** decide whether column lineage is optional enrichment or a core metric family. - ---- - -## 17. Conclusions - -SQL support should introduce a new `sql.*` metric namespace with SQL-specific structural, cognitive, object-risk, and confidence metrics. The strongest first implementation is not a single “SQL complexity” number; it is a layered model: - -1. Raw AST-derived metrics. -2. Graph metrics for CTEs, joins, and optionally lineage. -3. SQL Halstead metrics with explicit operator/operand taxonomy. -4. Risk metrics for DDL/DML and migration scripts. -5. Procedural complexity only for dialects that actually contain procedural control flow. -6. Explainable composite scores for review prioritization. - -This approach aligns with mehen’s language-owned metric model, builds on SQLFluff/sqruff parser infrastructure, incorporates current linter prior art, and follows the scientific literature’s main lesson: SQL complexity is a human comprehension and authoring burden as much as, and often more than, an execution-cost problem. - ---- - -## 18. References - -- mehen rewrite plan: -- mehen Markdown metrics research foundation: -- SonarQube Server metric definitions: -- SonarQube T-SQL language page: -- SonarQube PL/SQL language page: -- Sonar Cognitive Complexity overview: -- SQLFluff docs: -- SQLFluff architecture: -- SQLFluff rules reference: -- sqruff docs: -- sqruff dialects: -- sqruff rules: -- `sqlfluff-complexity`: -- `sqlfluff-complexity` rules: -- `sqlfluff-complexity` configuration: -- Vashistha, A. & Jain, S. “Measuring Query Complexity in SQLShare Workload”: -- Piattini, M. & Martínez, A. “Measuring for Database Programs Maintainability”: -- Siau, K. L., Chan, H. C., & Wei, K. K. “Effects of Query Complexity and Learning on Novice User Query Performance With Conceptual and Logical Database Interfaces”: -- Taipalus, T. “The effects of database complexity on SQL query formulation”: -- Yu et al. “Spider: A Large-Scale Human-Labeled Dataset for Complex and Cross-Domain Semantic Parsing and Text-to-SQL Task”: -- Spider benchmark site: -- Subali, M. A. P. & Rochimah, S. “A new model for measuring the complexity of SQL commands”: -- Miedema, D., Fletcher, G., & Aivaloglou, E. “So many brackets!: an analysis of how SQL learners (mis)manage complexity during query formulation”: -- Radon code metrics documentation for Maintainability Index and Halstead formulas: diff --git a/design-docs/metrics-gaps.md b/design-docs/metrics-gaps.md deleted file mode 100644 index 5f47441a..00000000 --- a/design-docs/metrics-gaps.md +++ /dev/null @@ -1,56 +0,0 @@ -# Metrics Implementation Gaps - -Audit of per-language metric completeness across Rust, Python, Go, TypeScript, TSX, and Ruby. Ordered from most challenging (full redesign / missing primitives) to trivial (add a node kind to a match arm). - -Supported languages in the matrix: R = Rust, Py = Python, G = Go, TS = TypeScript, X = TSX, Rb = Ruby. - -## 1. Class-based metrics - -- [x] **`wmc` (Weighted Methods per Class).** Implemented for R / Py / TS / X / Rb. The method's function-space forwards its cyclomatic into the merge routine, which accumulates it into the enclosing class (or `impl`) / interface (or `trait`). Unit-level aggregation hides the metric when a file contains no class-like spaces. Go stays `n/a`. -- [x] **`npa` (Number of Public Attributes).** Implemented for R / Py / TS / X / Rb. Per-language attribute detection: Python class-body assignments, TS/TSX `public_field_definition` / `property_signature`, Rust `field_declaration`, Ruby `@instance_variable` assignments. Visibility rule: leading-`_` for Python, `private` / `protected` modifiers for TS / TSX, `pub` for Rust, conservative non-public for Ruby ivars (since `attr_accessor` tracking is out of scope). Go stays `n/a`. -- [x] **`npm` (Number of Public Methods).** Implemented for R / Py / TS / X / Rb. Detects methods by node kind + AST-parent check, so `space_kind = Function` of the method's own space does not confuse the lookup. Visibility rule matches `npa`. Go stays `n/a`. - -## 2. Structural gaps in existing metrics - -- [x] **`cognitive` does not nest `TryStatement` in TypeScript / TSX.** `js_cognitive!` macro at `src/metrics/cognitive.rs:358` increments nesting on `CatchClause` but not on the surrounding `TryStatement`, so code inside `try` blocks is not counted as nested. Fix requires adding `TryStatement` to the `increase_nesting` arm in both TS and TSX impls. -- [x] **`cognitive` does not nest `TryStatement` in Python.** `src/metrics/cognitive.rs:250` handles `ExceptClause` but not `TryStatement` itself — the `try` body does not add nesting depth. -- [x] **`cognitive` does not handle `LoopExpression` or `TryExpression` in Rust.** `src/metrics/cognitive.rs:319` nests on `IfExpression | ForExpression | WhileExpression | MatchExpression` but omits `LoopExpression` (infinite loops) and `TryExpression` (`?`). -- [x] **`exit` misses `throw` in TypeScript / TSX.** Fixed: `src/metrics/exit.rs` now counts `ThrowStatement` alongside `ReturnStatement`. -- [x] **`exit` misses `raise` in Python.** Fixed: `src/metrics/exit.rs` now counts `RaiseStatement` alongside `ReturnStatement`. - -## 3. Language-semantic inconsistencies - -- [x] **`halstead` under-classifies Python operators.** Fixed: `LPAREN | LBRACK | LBRACE | COLON | SEMI` are now classified as Python operators, bringing it in line with TS / TSX / Rust / Go / Ruby. -- [x] **`cyclomatic` counts Go `DefaultCase` as a decision.** `src/metrics/cyclomatic.rs:172` includes `DefaultCase` in the decision-point set; by the standard McCabe definition `default` is the fallthrough and should not count. This inflates Go cyclomatic relative to other languages. -- [x] **`cyclomatic` counts Python `With | Assert` as decisions.** `src/metrics/cyclomatic.rs:113` adds `With` and `Assert`, neither of which introduces a branch. This inflates Python cyclomatic relative to other languages. -- [x] **`cyclomatic` does not count `do…while` in TypeScript / TSX.** `src/metrics/cyclomatic.rs:133` and `:146` enumerate `If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE` but omit `DoStatement`. `while` matches through the `While` token but `do…while` has its own kind and is silently dropped. — Verified: the `While` keyword token fires for `do…while` as well (see `typescript_do_while` test), so no enumeration change is needed. - -## 4. Stubbed predicates feeding real code - -- [x] **`is_primitive` — obsolete.** The `--ops` subcommand and its consumer in `src/ops.rs` were removed (along with the `is_primitive` trait method and the `get_operator_id_as_str` Getter hook that only served it). No metric depends on primitive-type detection, so the gap is closed by deletion. -- [x] **`is_useful_comment` — obsolete.** The `--comments` strip-comments subcommand and `src/comment_rm.rs` were removed (along with the `is_useful_comment` trait method). No remaining path consults this predicate, so the gap is closed by deletion. -- [x] **`is_else_if` returns `false` for Python.** Verified with `metrics::cognitive::tests::python_nested_if_in_else_is_not_else_if`: Python's dedicated `ElifClause` means a plain `if` in an `else:` block is a real nested `if`, so returning `false` here is correct. - -## 5. Trivial alignments - -- [ ] **Rust `cognitive` comment in `src/metrics/cognitive.rs:316` says `//TODO: Implement macros`.** Macro invocations are currently invisible to cognitive complexity in Rust. If macro bodies are meant to count, this needs grammar-level handling. -- [x] **TS / TSX `cyclomatic` relies on `For` keyword matching for `for…of`/`for…in`.** `src/metrics/cyclomatic.rs:138`, `:151`. Confirm `For` token fires for all three loop kinds; if not, add `ForInStatement` / `ForOfStatement` explicitly. — Confirmed via the `typescript_do_while` pattern: the `For` / `While` anonymous keyword tokens fire uniformly for all loop kinds. No change required. - ---- - -## Summary matrix - -| Metric | R | Py | G | TS | X | Rb | -|--------------|------|------|------|------|------|------| -| loc | full | full | full | full | full | full | -| halstead | full | full | full | full | full | full | -| cyclomatic | full | full | full | full | full | full | -| cognitive | full | full | full | full | full | full | -| nargs | full | full | full | full | full | full | -| nom | full | full | full | full | full | full | -| mi | full | full | full | full | full | full | -| exit | full | full | full | full | full | full | -| abc | full | full | full | full | full | full | -| wmc | full | full | n/a | full | full | full | -| npa | full | full | n/a | full | full | full | -| npm | full | full | n/a | full | full | full | diff --git a/design-docs/php-mago-syntax-spec.md b/design-docs/php-mago-syntax-spec.md deleted file mode 100644 index 741dec07..00000000 --- a/design-docs/php-mago-syntax-spec.md +++ /dev/null @@ -1,473 +0,0 @@ -# PHP analyzer spec — mago-syntax backend - -**Status:** implementation reference -**Date:** 2026-05-19 -**Scope:** `mehen-php` mago-syntax-backed analyzer (Phase 8 of the v1 -rewrite, replacing the tree-sitter-php pipeline) - -## 1. Goal - -Phase 8 of the [v1 rewrite plan](mehen-1-0-from-scratch-rewrite-plan.md) -swaps the PHP parser from `tree-sitter-php` to -[`mago-syntax`](https://docs.rs/mago-syntax/) — the lexer/parser/AST -layer that powers the [Mago](https://mago.carthage.software) PHP -toolchain. mago-syntax is published on crates.io, designed for external -consumption, and ships a typed AST with PHP-specific nodes (attributes, -promoted properties, enum cases, hooked properties, match expressions, -null-safe member calls, …) that tree-sitter-php either flattens into -generic CST nodes or doesn't model at all. - -The migration is a Phase 6.4 directive in the rewrite plan and the last -of the four "language-specific parser" rollouts (PowerShell stayed on -tree-sitter; TypeScript moved to Oxc; Python moved to Ruff; Rust moved -to ra_ap_syntax). With Phase 8 done, every actively-evolving language -in the workspace has its own typed-AST backend. - -The published metric contract is unchanged — Halstead, Cyclomatic, -Cognitive, ABC, NArgs, NOM, NExit, NPA, NPM, WMC, LOC, MI all keep -their semantics and serialization shape. What changes is the -*interpretation* of a handful of PHP-specific constructs where the -tree-sitter grammar produced fragile or hand-rolled string-comparison -results. Each divergence below is justified from the metric definition -rather than from a desire to mirror legacy. `crates/mehen-php/tests/` -carries the pinned snapshots; the seven legacy `check_metrics::` -tests are ported byte-identical so parity is provable. - -### 1.1 Why `mago-syntax` and not the alternatives - -- **`tree-sitter-php` (the legacy backend)**: a CST grammar, not an - AST. Visibility modifiers come back as raw token text on - `VisibilityModifier` nodes; the legacy walker had to do - `text.eq_ignore_ascii_case("private")` because tree-sitter doesn't - know PHP keywords are case-insensitive. Promoted constructor - properties parse as `property_promotion_parameter` *anywhere a - parameter is allowed*, including non-constructor methods (PHP rejects - these at runtime), so the legacy walker had a hand-rolled lookahead - that walked up to the enclosing method, decoded the name, and did a - case-insensitive compare against `"__construct"`. Each new - PHP-specific feature meant another grammar PR and another fragile - classifier. -- **`php-parser-rs`**: less actively maintained, smaller surface, no - dedicated walker abstraction. -- **Hand-written nom parser**: the rewrite plan §6.8 explicitly calls - this out as a bad use of `nom` — replacing a mature language parser. -- **`mago-syntax`**: typed AST with arena allocation, mature error - recovery, an automatically-generated `Walker` trait (with - `walk_in_` / `walk_out_` hooks per AST node type), and an - upstream test suite that tracks PHP 7.0 through PHP 8.5+. Mago's - internal lint pipeline drives the same walker via `mago-collector` — - we re-use the trait directly without depending on the collector - itself. - -### 1.2 MSRV bump - -`mago-syntax 1.27.1` declares `rust-version = 1.95.0`. The workspace -`rust-version` was `1.93.1` before Phase 8; the rewrite plan §6.4 calls -out the bump as a prerequisite. Phase 8 raises `[workspace.package] -rust-version` to `1.95.0`, which matches the pinned stable toolchain -already in `rust-toolchain.toml` (`channel = "stable"` resolves to -1.95.0+). - -## 2. What is *not* different - -The following metric outputs match legacy where the underlying source -is well-formed PHP: - -- `cyclomatic.{sum,min,max,avg}` for `if`/`elseif`/spaced-`else if`, - `for`, `foreach`, `while`, `do`, `switch` cases, `match` arms, - ternary, `catch`, and short-circuit `&&`/`||`/`and`/`or`. (`xor` - excluded — it does not short-circuit.) -- `cognitive.{sum,min,max,avg}` for nesting penalties, the boolean - sequence collapser (with the `else`-resets-sequence rule from the - legacy walker), the `else`-clause flat +1, and function-depth - penalty. -- `abc.*` for assignment / branch / condition counts, including the - prefix and postfix `++`/`--` family on ABC.A and the legacy `else` - / `default` ABC.C convention. -- `nom.*` for function / closure / arrow-function counts. -- `nexit.*` for `return`, `throw`, and `exit`/`die`. -- `nargs.*` for function, closure, and method parameter lists. -- `npa.*` / `npm.*` for class / interface / trait / enum members, - with PHP visibility (`public`/`protected`/`private` plus their - `(set)` variants for asymmetric visibility) classified through - Mago's typed `Modifier` enum. -- `wmc.*` summed from method cyclomatic on classes. -- `mi.*` Maintainability Index variants. -- Halstead `volume` / `difficulty` / `effort` family on well-formed - source. -- All seven legacy parity tests (`php_basic_decision_points`, - `php_else_branch_resets_boolean_sequence`, - `php_npa_counts_each_property_in_grouped_declaration`, - `php_npa_counts_promoted_constructor_properties`, - `php_npa_does_not_count_promoted_params_outside_constructor`, - `php_npm_visibility_keywords_are_case_insensitive`, - `php_wmc_class_sums_method_cyclomatics`) pass byte-identically with - inline `@r###"…"###` JSON snapshots verbatim. - -## 3. What is different (and why) - -### 3.1 PHP visibility is now typed, not text-compared - -**Legacy behavior:** `tree-sitter-php` exposes a `VisibilityModifier` -CST node whose textual value is the raw source slice -(`"public"`, `"PRIVATE"`, `"Protected"`, …). PHP keywords are -case-insensitive per the language spec (`PRIVATE function f() {}` is -valid PHP), so the legacy `php_member_is_public()` helper in -`legacy/metrics/npm.rs` did: - -```rust -text.eq_ignore_ascii_case("private") || text.eq_ignore_ascii_case("protected") -``` - -**New behavior:** Mago's parser already normalizes visibility -keywords into a typed `Modifier` enum: - -```rust -pub enum Modifier<'arena> { - Static(Keyword<'arena>), - Final(Keyword<'arena>), - Public(Keyword<'arena>), - Protected(Keyword<'arena>), - Private(Keyword<'arena>), - PublicSet(Keyword<'arena>), // PHP 8.4 asymmetric visibility - ProtectedSet(Keyword<'arena>), - PrivateSet(Keyword<'arena>), - /* … */ -} -``` - -`php_modifiers_are_public()` becomes a clean enum match, with no string -comparison and no case-insensitivity logic. The case-insensitive -behavior is preserved for free because the lexer normalizes the keyword -on the way in. - -**Why this is correct:** the metric definition has not changed — public -members are still everything that isn't `private`/`protected` (with the -new variants for the PHP 8.4 asymmetric-visibility forms also -classified as non-public). The legacy -`php_npm_visibility_keywords_are_case_insensitive` test still passes -because `PRIVATE` lexes to `Modifier::Private` regardless of case. - -### 3.2 Promoted constructor properties via typed predicate - -**Legacy behavior:** the tree-sitter grammar accepts -`property_promotion_parameter` syntactically inside *any* method — -including non-constructors — because the grammar can't enforce the -semantic rule that PHP rejects at runtime. The legacy walker had to -walk up two levels (`parameter -> formal_parameters -> -method_declaration`), grab the method's `name` field, decode it as -UTF-8, and do an ASCII-case-insensitive compare against `"__construct"` -to gate the `record_attribute` call. - -**New behavior:** Mago exposes a typed predicate: - -```rust -impl FunctionLikeParameter<'_> { - pub fn is_promoted_property(&self) -> bool { - !self.modifiers.is_empty() || self.hooks.is_some() - } -} -``` - -The walker collects promoted properties at the start of `walk_in_method` -*only* when `is_constructor(&method.name.value)` returns true. The -constructor check is still case-insensitive (`__construct` / -`__CONSTRUCT` / `__Construct` are all the constructor in PHP), but the -*structural* test ("is this parameter actually declaring a property?") -is one method call instead of three levels of CST navigation. - -The -`php_npa_does_not_count_promoted_params_outside_constructor` legacy -test still passes verbatim — it tested the case-insensitivity of the -constructor name check, which is preserved. - -### 3.3 `else if` (spaced) flattening is per-node, not per-token - -**Legacy behavior:** the tree-sitter-php grammar has both -`else_if_clause` (the `elseif` keyword form) and a nested `if_statement` -(the spaced `else if` form). The legacy walker's `is_else_if` predicate -detected the nested form by checking whether the `if_statement`'s -*direct parent* was an `else_clause` — and then suppressed the inner -`if`'s structural nesting via a generic "is_else_if" lookahead. - -**New behavior:** Mago surfaces both forms as distinct AST nodes: - -- `IfStatementBodyElseIfClause` — the keyword `elseif` form. -- `IfStatementBodyElseClause::statement` — when this statement is itself - an `Statement::If`, the spaced `else if` form is in play. - -The walker handles each form in its own `walk_in_*` callback: - -- `walk_in_if_statement_body_else_if_clause` records a flat `+1` - cognitive (no extra nesting), one cyclomatic decision, and resets the - boolean sequence. -- `walk_in_if_statement_body_else_clause` resets the boolean sequence, - records ABC.C, and — when the body is an `If` — sets a one-shot - `suppress_next_if_nesting` flag so the *inner* `walk_in_if` knows not - to bump structural nesting (the outer `if`'s nesting has already - paid for the inner branch). - -The `php_else_branch_resets_boolean_sequence` legacy test (which -exercises both the `else if` flattening and the boolean-sequence reset -across an `else` boundary) passes verbatim with `cognitive.sum = 4.0`. - -### 3.4 ABC.C `else` is now explicit - -**Legacy behavior:** `ElseClause` / `ElseClause2` were enumerated in -the ABC.C arm of `legacy/metrics/abc.rs`, contributing one condition -per `else` (per Fitzpatrick's original ABC, where every conditional -branch — including the catch-all `else` — counts as a condition). - -**New behavior:** the walker records ABC.C in -`walk_in_if_statement_body_else_clause` and -`walk_in_if_colon_delimited_body_else_clause`. The -`walk_in_switch_default_case` callback records ABC.C the same way (PHP -`default` is the switch analog of `else`). - -This was an *audit-discovered* gap during Phase 8 — my initial walker -omitted the ABC.C bump on `else` clauses, which would have under-counted -conditions on every `if`/`else` pair. The legacy parity test for -cognitive complexity still passed (it doesn't read ABC), so the -regression was silent until I ran a hand-written audit fixture against -the walker. The fix landed before Phase 8 closed, with the new -`php_abc_conditions_cover_control_flow_and_comparisons` test pinning -the count. - -### 3.5 ABC.A prefix `++`/`--` - -**Legacy behavior:** `legacy/metrics/abc.rs`'s PHP arm enumerated -`UpdateExpression` (which the tree-sitter grammar emits for both -prefix and postfix forms) under ABC.A. - -**New behavior:** Mago splits prefix and postfix into distinct AST -node types: - -- `UnaryPrefix { operator: UnaryPrefixOperator::PreIncrement(_) | PreDecrement(_) }` -- `UnaryPostfix { operator: UnaryPostfixOperator::PostIncrement(_) | PostDecrement(_) }` - -The walker hooks both: `walk_in_unary_prefix` matches the -`PreIncrement`/`PreDecrement` operator and records ABC.A; -`walk_in_unary_postfix` matches the `PostIncrement`/`PostDecrement` -operator and records ABC.A. - -This was the second audit-discovered gap. My initial walker only -recorded `walk_in_assignment` for ABC.A (which Mago surfaces as the -typed `Assignment` node for `=`/`+=`/`??=`/etc.). The -`php_abc_assignments_cover_all_assignment_forms` test now exercises -all eight forms (4 typed assignments + 2 prefix + 2 postfix) and -asserts `assignments == 8.0`. - -### 3.6 LLOC counts every statement-shaped node, not just expression statements - -**Legacy behavior:** `legacy/metrics/loc.rs`'s PHP arm enumerated -~25 statement-shaped node kinds for LLOC: every expression statement, -every empty statement, `echo`, `unset`, `declare`, `namespace`, `use`, -`global`, `function-static`, `try`, `continue`, `break`, `return`, -loops, `if`, `switch`, `case`, `default`, label, `goto`, every -function/method/class/trait/interface/enum declaration, `const` (both -top-level and class-scoped), and `property` declarations. - -**New behavior:** the walker hooks `walk_in_*` for each of those node -types and calls `current().loc.observe_lloc()` exactly once per -statement. The `walk_in_if` hook bumps LLOC; the inner `else if` / -`else` clauses do *not* bump again (an `if … else` chain is one -logical statement, not two — same convention as legacy). - -This was the third — and largest — audit-discovered gap. My initial -walker only bumped LLOC inside `walk_in_statement_expression`, which -left every PHP file with a wildly under-counted LLOC. A 30-line audit -fixture reported `lloc = 1.0` instead of the expected 16. The fix -landed with six new tests in `crates/mehen-php/tests/loc.rs`: - -- `php_lloc_counts_simple_function_body` — function decl + if + 2 returns -- `php_lloc_counts_namespace_use_const` — top-level decls -- `php_lloc_counts_class_members` — class + class-const + property + method -- `php_lloc_counts_loops_and_switch` — every loop + switch + case + default -- `php_lloc_counts_try_throw_echo_unset` — exit-flow statements -- `php_lloc_does_not_count_else_clauses_separately` — `if/else` is one LLOC - -### 3.7 Halstead via re-lex, not via AST node kinds - -**Legacy behavior:** `legacy/getter.rs::get_op_type` for PHP returned -a `HalsteadType::{Operator, Operand, Unknown}` for each tree-sitter -`Php` enum variant. The `compute_halstead` machinery walked the CST -and emitted operator/operand events in source order. - -**New behavior:** mago-syntax's typed AST does not surface every -punctuation token as a node — `(`, `,`, `;`, `{` are stored on parent -nodes as `Span` fields, not as visitable children. Re-walking the AST -to emit Halstead would need bespoke visit logic for every parent node -type. Instead, the walker re-uses Mago's `Lexer` directly: - -```rust -fn emit_halstead_from_tokens(&mut self) { - let input = Input::new(FileId::zero(), self.source.as_bytes()); - let mut lexer = Lexer::new(input, LexerSettings::default()); - while let Some(result) = lexer.advance() { - match classify_token(token.kind) { /* … */ } - } -} -``` - -The `classify_token` function maps each `mago_syntax::token::TokenKind` -to either: - -- `TokenClass::Operator(distinct_kind_str)` — every keyword, every - punctuation token, every operator gets its own kind string so `n1` - reflects the true number of unique operators. -- `TokenClass::Operand(kind_str)` — identifiers (incl. qualified names), - variables, literals (int, float, string, true, false, null), magic - constants (`__CLASS__`, `__LINE__`, …), and the keywords `self` / - `parent` (which name a class). -- `TokenClass::Skip` — whitespace, comments (handled separately for - LOC.cloc), inline-HTML between PHP tags, opening/closing PHP tags - (``), string-interior tokens (`StringPart` / `DoubleQuote` - / heredoc body — the wrapping `LiteralString` already counts), and - *closing* punctuation (`)`, `]`, `}`) which pairs with its opener - (classical Halstead pair convention, mirrors `mehen-rust`). - -This is functionally identical to the legacy classifier — every token -the legacy `get_op_type` flagged as `Operator` or `Operand` is -classified the same way here. The mechanics are different (token -sweep vs CST walk) but the metric output for well-formed PHP is the -same shape. - -This was Phase 8's *first* audit-discovered gap — the most embarrassing -one. The walker had no Halstead emission at all (zero `n1`/`n2`/etc. -on every PHP file). The -`_halstead_observe_*` placeholders I'd left "as a TODO" got swept up -as dead code by `unreachable_pub` cleanup, which silently removed the -TODO marker without anyone noticing. Two new tests in -`crates/mehen-php/tests/halstead.rs` lock the classifier in: -`php_halstead_simple_function` (full output snapshot) and -`php_halstead_string_part_is_skipped` (regression test for the -string-internals skip). - -### 3.8 Anonymous classes do not bump LLOC themselves - -**Legacy behavior:** the tree-sitter grammar's `anonymous_class` was a -declaration kind; the legacy LLOC arm enumerated `ClassDeclaration` and -`AnonymousClass` together. - -**New behavior:** Mago surfaces `AnonymousClass` as an *expression* -(it's the result of `new class { … }`), so the surrounding -`ExpressionStatement` already bumps LLOC for the whole `$x = new -class { … };` line. Bumping again on `walk_in_anonymous_class` would -double-count. - -This is a genuine improvement — anonymous classes really *are* -expressions in PHP, not statements. The legacy walker would over-count -LLOC for every `new class` expression by one. - -### 3.9 Enum cases as NPA attributes - -**Legacy behavior:** the tree-sitter walker did not record enum cases -as NPA attributes (the legacy `npa.rs` PHP arm only matched -`PropertyDeclaration` and `PropertyPromotionParameter`). - -**New behavior:** PHP enum cases are typed constants on the enum. -They have no per-instance state, so they're not "attributes" in the -classical OO sense. But they *do* contribute to an enum's surface -area the same way class constants do. The walker records each -`EnumCase` as a class-attribute on the enclosing enum's NPA state, with -`is_public = true` (cases are always public in PHP — there's no syntax -to make them private). - -This is a deliberate semantic improvement, not an unintentional -divergence. NPA's "number of public attributes" is meant to capture -the surface a class exposes; enum cases are part of that surface. -The drift is bounded: zero for any PHP file without enums (matching -legacy), and a small additive change for files using enums. - -### 3.10 PHP 8.5 pipe operator (`|>`) is a comparison-class operator - -**Legacy behavior:** tree-sitter-php's grammar tracks the `|>` token -as `PIPEGT`. The legacy `get_op_type` for PHP put it under the -"comparison" group. - -**New behavior:** the new `classify_token` keeps `PipeGreaterThan` in -the comparison group (returning `Operator("|>")`). Behaviorally -identical for Halstead — the metric reflects "this is one distinct -operator token" either way. - -## 4. Operator and operand classification - -The full table lives in -`crates/mehen-php/src/walker.rs::classify_token`. The shape mirrors -`mehen-rust`'s walker: - -- **Skipped tokens** — `Whitespace`, comments (handled separately for - LOC.cloc), `InlineText` / `InlineShebang`, `OpenTag` / `CloseTag` / - `EchoTag` / `ShortOpenTag`, `StringPart` / `DoubleQuote` / `Backtick` - / `DocumentStart` / `DocumentEnd` / `PartialLiteralString` (string - interior; the wrapping `LiteralString` is the operand), and *closing* - pair punctuation (`)`, `}`, `]`). -- **Operator** — every other punctuation token, every keyword, every - operator family (assignment, arithmetic, bitwise, unary, null-coalesce, - comparison, type cast). Each gets its own kind string so `n1` is - precise. -- **Operand** — `Identifier` / `QualifiedIdentifier` / - `FullyQualifiedIdentifier` (collapsed under `"Identifier"`), - `Variable`, `Self_`, `Parent`, the literal family - (`LiteralInteger` / `LiteralFloat` / `LiteralString` / `True` / - `False` / `Null`), the magic constants (`ClassConstant` / - `LineConstant` / etc., collapsed under `"MagicConstant"`), and - `Callable` (treated as an identifier in argument lists). - -The legacy classifier collapsed all qualified-name forms under a single -operand kind too (`Name` / `Name2` / `NamespaceName` / -`QualifiedName` / `RelativeName` all mapped to `HalsteadType::Operand`), -so the kind string `"Identifier"` here is a behavioral match. - -## 5. Walker structure - -The walker uses Mago's `Walker` trait — the same trait Mago's own lint -pipeline drives via `mago-collector` for pragma-scope attachment. -`Walker` is `&self` (immutable), threading mutable state through a -user-provided context type. The walker macro generates three callback -methods per AST node: - -- `walk_in_(&self, node, context)` — fires on enter. -- `walk_(&self, node, context)` — drives the descent into - children. -- `walk_out_(&self, node, context)` — fires on leave. - -The default `walk_` body is auto-generated to recurse into every -field of the node type (`if_node.condition`, `if_node.body`, etc.), so -overriding `walk_in_` / `walk_out_` is sufficient for -metric accumulation; the walk continues automatically. - -`Visitor` (the context type) holds: - -- `tree: MetricTreeBuilder` — produces the final `MetricSpace`. -- `stack: Vec` — per-space metric accumulators (index 0 is the - unit; pushed/popped as classes/functions open/close). -- `kinds: Vec` — parallel to `stack`, lets the walker tell - "what's the enclosing class-like" without re-walking. -- `cognitive: CognitiveContext` — the (`nesting`, `depth`, `lambda`) - triple from the legacy walker, snapshotted into `saved_cognitive` - on every nesting bump and restored on `walk_out_`. -- `suppress_next_if_nesting: bool` — one-shot flag for the - `else if`-spaced flattening (see §3.3). - -Halstead emission runs once at `Visitor::finish()` via Mago's `Lexer` -on the original source bytes; LOC.ploc is also derived there (single -source-text scan instead of a re-walk). Per-space close drives -`finalize_state` + `merge_child_into_parent`, identical to -`mehen-rust` and `mehen-python`. - -`mehen-php` does **not** depend on `mago-collector` — that crate is a -diagnostic-issue collector (suppression pragmas, issue codes, -`IssueCollection` types) for Mago's lint pipeline. The walker -abstraction we want lives in `mago-syntax` itself. - -## 6. References - -- mago-syntax docs: -- Mago lexer/parser overview: - -- mago-collector source (for the walker integration pattern): - -- v1 rewrite plan §6.4: PHP / Mago migration prerequisites. -- `crates/mehen-php/src/walker.rs` — implementation. -- `crates/mehen-php/tests/` — pinned snapshots and regression tests. diff --git a/design-docs/python-ruff-spec.md b/design-docs/python-ruff-spec.md deleted file mode 100644 index f31fb533..00000000 --- a/design-docs/python-ruff-spec.md +++ /dev/null @@ -1,245 +0,0 @@ -# Python analyzer spec — Ruff backend - -**Status:** implementation reference -**Date:** 2026-05-18 -**Scope:** `mehen-python` Ruff-backed analyzer (Phase 6 of the v1 -rewrite, replacing the tree-sitter-python pipeline) - -## 1. Goal - -Phase 6 of the [v1 rewrite plan](mehen-1-0-from-scratch-rewrite-plan.md) -swaps the Python parser from `tree-sitter-python` to Ruff's -unpublished `ruff_python_parser` + `ruff_python_ast` + `ruff_text_size` -crates (pinned to git tag `0.15.13`). The analyzer (in -`crates/mehen-python/`) feeds the same `mehen-metrics` accumulators as -every other language crate, so the published metric contract is -unchanged — Halstead, Cyclomatic, Cognitive, ABC, NArgs, NOM, NExit, -NPA, NPM, WMC, LOC, MI all keep their semantics and serialization -shape. - -What changes is the *interpretation* of a handful of Python-specific -constructs where the tree-sitter grammar's CST shape produced -demonstrably wrong or weakly-grounded results. Each divergence below -is justified from the metric definition rather than from a desire to -mirror legacy. `mehen-python/tests/` carries the pinned snapshots. - -## 2. What is *not* different - -The following metric outputs match legacy byte-for-byte where the -underlying source is well-formed: - -- `cyclomatic.{sum,min,max,avg}` for `if/elif/else`, `for`, `while`, - `try`/`except`, `match`/`case`, `and`/`or`, ternary `a if b else c`, - comprehension generators and `if` filters. -- `cognitive.{sum,min,max,avg}` for nesting penalties, the boolean - sequence collapser, lambda lambda-bonus, function-depth penalty. -- `nom.*` for function and lambda counts. -- `nexit.*` for `return` / `raise`. -- `abc.*` for assignments, calls, comparisons, conditionals. -- `loc.*` for blank/comment/code lines, including docstring-as-cloc. -- `npa.*` / `npm.*` for class-body assignments and methods, with the - PEP-8 leading-underscore visibility convention (dunders count as - public). -- `wmc.*` summed from method cyclomatic. -- `mi.*` Maintainability Index variants. -- The `embedded_code_large.md` markdown fence — the Python fence's - `volume`, `cognitive_sum`, and `sloc` are byte-identical to the - legacy walker (volume=361.21, cognitive=8, sloc=17), so the §9.4 - `embedded_volume = Σ 0.20·√volume + 0.50·cognitive + 0.10·sloc` - rollup is unchanged for that fixture. - -## 3. What is different (and why) - -### 3.1 Type annotations participate in Halstead - -**TypeScript precedent doesn't apply to Python.** The Phase 7 -TypeScript walker (`crates/mehen-typescript/`) deliberately excludes -TS-only AST subtrees (`TSTypeAnnotation`, `TSInterfaceDeclaration`, -class `implements` clauses, predefined-type keywords, …) from the -Halstead token sweep, because those tokens are erased at compile -time. Python types are not erased — they are runtime-accessible -objects: - -- `typing.get_type_hints(f)` returns a dict of evaluated annotation - objects. -- `pydantic` reads model annotations at class-definition time to - build validators. -- `dataclasses` reads field annotations to generate `__init__`. -- `inspect.signature(f).parameters[name].annotation` is the - annotation expression. - -Per Halstead's "operators do things, operands are things" definition, -an annotation like `int` or `list[Shape]` is a *thing* — a real -runtime operand. The Ruff walker therefore treats annotation tokens -exactly like any other expression token: `:` and `->` are operators, -the type identifier is an operand. This is a deliberate divergence -from the TS analyzer. - -Test: `crates/mehen-python/tests/parity.rs::python_type_annotations_participate_in_halstead`. - -### 3.2 Module / class / function docstrings are excluded from Halstead - -Per PEP 257, a string literal that is the first statement of a module, -class, or function body is the docstring — a structural language -feature, not arbitrary code. Docstring tokens contribute zero -Halstead operators and operands. - -LOC accounting still counts those lines as `cloc` (matching the legacy -behavior), since the `Loc` metric's "cloc = comment-like lines" -definition includes docstrings. - -Test: `crates/mehen-python/tests/parity.rs::python_module_docstring_excluded_from_halstead`. - -### 3.3 Attribute access does not emit a synthetic "attribute" operand - -The TypeScript walker emits *three* operand entries for `console.log`: -the leaf `console`, the leaf `log`, and the joined wrapper -`MemberExpression("console.log")`. This is parity with the legacy -tree-sitter-typescript walker (which counted `member_expression` as -a named-CST operand). - -The legacy tree-sitter-python walker does NOT classify the `attribute` -named node as an operand (see the deleted `Getter for PythonCode` -match arms — `Identifier`, `Integer`, `Float`, `String`, `True`, -`False`, `None` are the only operand forms). The new Ruff walker -follows this: `a.b.c` produces three operand tokens (`a`, `b`, `c`) -plus two operator dots, no synthetic chain operand. - -The two languages differ here because their legacy walkers differed, -and each language's chosen convention leaves its own metric output -internally consistent. Cross-language comparisons of Halstead numbers -were never first-class (each language has its own operator/operand -classification anyway). - -### 3.4 NArgs `*_min` is per-function/closure, not per-space - -Legacy `nargs::compute_minmax` folded *every* space's per-space -`fn_nargs` and `closure_nargs` (defaulting to 0 for unit/class spaces) -into the rolled-up min. That meant any source with at least one -function and a unit space reported `functions_min: 0.0` — never -`functions_min: 2.0` even when the only function had 2 args. - -The new `NargsStats::finalize_minmax` gates the per-space fold on -`is_function` and `is_closure`. Only spaces that *are* functions or -closures contribute to the corresponding `_min` / `_max`. The legacy -output for `def f(a, b): ...` was `functions_min: 0.0`; the new -output is `functions_min: 2.0` — matching the metric's intended -definition ("minimum number of arguments across function spaces"). - -This change touches more than Python: PowerShell's -`crates/mehen-powershell/tests/nargs.rs` snapshots were updated to -the new (more correct) values too. See the doc-comment at the top of -that file. - -Test: `crates/mehen-python/tests/nargs.rs::python_single_function`. - -### 3.5 Indentation correctness - -Tree-sitter-python is error-tolerant — it silently absorbs -inconsistent indentation rather than reporting a parse error. The -legacy Python tests in -`crates/mehen-engine/src/legacy/metrics/{cyclomatic,nargs,...}.rs` -were written with deeply-indented multi-line source strings where -each `def` / `if` ended up at a different column. Tree-sitter -"smoothed over" the inconsistency; Ruff (correctly) reports -indentation errors and emits an empty / partial AST. - -Where the ported tests in `crates/mehen-python/tests/` use the -legacy fixture, the source has been reformatted to consistent -indentation that expresses what the legacy test was *intending* to -test (siblings at column 0, body at 4 spaces). The expected values -are unchanged — the AST shape is what the legacy test was actually -trying to validate. - -Test inline-comments document each such reformatting. - -### 3.6 PEP 654 exception groups (`try*` / `except*`) - -Python 3.11 added `except*` for exception groups. Tree-sitter-python's -0.25.0 grammar may or may not parse `except*` correctly (it's a -recent addition). Ruff supports it. - -Each `except*` handler counts as a regular `except` for cyclomatic -(one decision) and cognitive (nesting + 1). The -`StmtTry::is_star: bool` flag is recorded as evidence (future -contribution-reason output) but does not change metric numerics. - -Test: `crates/mehen-python/tests/parity.rs::python_except_star_handler_counts_as_decision`. - -## 4. Operator and operand classification - -The Ruff walker maps Ruff `TokenKind` values to one of `Operator(&str)`, -`Operand(&str)`, or `Skip`. The mapping in -`crates/mehen-python/src/walker.rs::classify_token` covers: - -- All Python keywords (`if`, `elif`, `else`, `for`, `while`, `try`, - `except`, `finally`, `with`, `return`, `raise`, `yield`, `assert`, - `import`, `from`, `as`, `pass`, `break`, `continue`, `def`, `class`, - `lambda`, `in`, `is`, `async`, `await`, `global`, `nonlocal`, `del`, - `not`, `and`, `or`) → operators. -- Soft keywords `match`, `case`, `type` → operators. -- Punctuation: `( [ { , : ; . @ + - * / % | & ^ ~ ** // << >> < > - = == != <= >= += -= *= /= %= &= |= ^= **= //= <<= >>= := @= ->` - → operators. -- Closing punctuation `) ] }` → skip (paired with their opening - counterpart, which is the operator). -- `Name` → `Identifier` operand. -- `Int`, `Float`, `Complex` → `Number` operand. -- `String`, `FStringStart`, `FStringMiddle`, `FStringEnd`, - `TStringStart`, `TStringMiddle`, `TStringEnd` → `String` operand. -- `True`, `False`, `None`, `Ellipsis` → operand. -- Newlines, indents, dedents, comments, EOF → skip. - -`PrivateIdentifier` is not in Python — the `_internal` / `__name` -naming conventions are not lexer-level distinctions. Visibility for -NPA/NPM is computed at the AST level by examining the `Identifier.id` -text against the leading-underscore rule. - -## 5. Walker structure - -The walker in `crates/mehen-python/src/walker.rs` drives recursion -through Ruff's -[`SourceOrderVisitor`](https://github.com/astral-sh/ruff/blob/main/crates/ruff_python_ast/src/visitor/source_order.rs) -trait — the upstream traversal helper that visits every AST node in -source order. We override only the hooks where a metric side effect -or a lifecycle boundary lives; default `walk_*` helpers handle the -rest. This mirrors `mehen-php`'s use of `mago_syntax::walker::Walker` -— in both crates, recursion is the parser's responsibility and we -own only the per-shape callbacks. - -It follows the same per-space `State` accumulator pattern used by -`mehen-typescript`: - -- One `State` (in `mehen-metrics::state`) for the unit, plus one for - every opened function / closure / class space. -- Cyclomatic / cognitive / ABC / nexit / LOC / NPA / NPM are driven - per-shape via overrides on `visit_stmt`, `visit_expr`, - `visit_match_case`, `visit_except_handler`, - `visit_elif_else_clause`, and `visit_comprehension`. Statements - that need only a side effect plus default descent (`Assign`, - `AugAssign`, `AnnAssign`, `Return`, `Raise`, `TypeAlias`, - `Expr`-statement, leaf statements) call `walk_stmt(self, stmt)`. -- Halstead is driven by a post-AST token sweep over the parsed - module's `parsed.tokens()`. Each token maps to one of - `Operator(kind)`, `Operand(kind)`, or `Skip`. Tokens whose span - falls inside a recorded docstring are skipped. - -The `CognitiveContext` tracks `(nesting, depth, lambda)` exactly as -the pre-1.0 `cognitive::python` did, plus a `bool_op_depth` counter -that detects the *outermost* boolean operator inside a statement -(only that one gets the legacy lambda-ancestor bonus per -`mehen-engine/src/legacy/metrics/cognitive.rs:281`'s -`count_specific_ancestors` of Lambda boundaries). - -## 6. References - -- Pinned Ruff revision: `https://github.com/astral-sh/ruff` tag - `0.15.13` (commit `2afb467ce397e4a89c13a0a814c62cfecb0e9e49`). -- Ruff's `parse_module` returns a - `Parsed` with `.syntax()` (the AST), `.tokens()` (the - lexer stream), and `.errors()` (parse diagnostics). -- The walker uses the AST for structural metrics and the lexer - stream for Halstead, exactly mirroring the TypeScript walker's - Oxc-based approach. -- Migration commit: see `git log --oneline | grep 'phase-6\|Ruff'` - for the patch series. diff --git a/design-docs/ruby-prism-spec.md b/design-docs/ruby-prism-spec.md deleted file mode 100644 index f4f76132..00000000 --- a/design-docs/ruby-prism-spec.md +++ /dev/null @@ -1,354 +0,0 @@ -# Ruby analyzer spec — ruby-prism backend - -**Status:** implementation reference -**Date:** 2026-05-19 -**Scope:** `mehen-ruby` ruby-prism-backed analyzer (Phase 9 of the v1 -rewrite, replacing the tree-sitter-ruby pipeline) - -## 1. Goal - -Phase 9 of the [v1 rewrite plan](mehen-1-0-from-scratch-rewrite-plan.md) -swaps the Ruby parser from `tree-sitter-ruby` to -[`ruby-prism`](https://docs.rs/ruby-prism/) — the Rust binding for -[Prism](https://github.com/ruby/prism), Ruby's canonical parser shipped -with CRuby 3.3+ and JRuby 9.4+. Prism is the parser the Ruby -maintainers themselves use; it tracks the language week-to-week, -recognizes every Ruby 3.x syntax form (numbered block parameters, `it` -parameters, endless methods, pattern matching, `&.`, `=>` rightward -assignment, `in` patterns, hash shorthand, …), and exposes them as -distinct typed AST nodes rather than CST fragments. - -The migration is the Phase 6.5 directive in the rewrite plan and -follows the same pattern as Phase 6 (Ruff Python), Phase 7 (Oxc -TypeScript), Phase 8 (Mago PHP), and Phase 9 Rust (rust-analyzer -syntax). With this phase done, every actively-evolving source language -in the workspace has its own typed-AST backend; only Go, C, Kotlin, -and PowerShell still use tree-sitter (and the rewrite plan §6.1 leaves -those on tree-sitter for 1.0). - -The published metric contract is unchanged — Halstead, Cyclomatic, -Cognitive, ABC, NArgs, NOM, NExit, NPA, NPM, WMC, LOC, MI all keep -their semantics and serialization shape. What changes is the -_interpretation_ of a handful of Ruby-specific constructs where the -tree-sitter grammar exposed flat CST nodes the legacy walker had to -disambiguate by string comparison or sibling lookup. Each divergence -below is justified from the metric definition rather than from a -desire to mirror legacy. `crates/mehen-ruby/tests/` carries the pinned -snapshots; the 23 legacy `check_metrics::` tests are -ported byte-identical (modulo the two intentional-drift items in §3), -and seven new Ruby-specific tests pin the prism-only behavior. - -### 1.1 Why `ruby-prism` and not the alternatives - -- **`tree-sitter-ruby` (the legacy backend)**: a CST grammar that - treats modifier and block forms as separate node kinds (`if` / - `if_modifier`, `unless` / `unless_modifier`, `rescue` / - `rescue_modifier`, `while` / `while_modifier`, `until` / - `until_modifier`). Convenient — every form has its own visit hook — - but the grammar lags Ruby releases, mis-parses some valid 3.2+ syntax - (numbered params, `it` blocks, endless methods, hash shorthand), and - classifies operator-method calls (`a + b`) and real method dispatch - (`obj.foo()`) under the same `call` node, forcing the legacy walker - to inspect raw operator-token text to tell ABC.B (branch) apart from - Halstead operator emission. -- **`lib-ruby-parser`**: a Rust port of the now-superseded - `parser-rs`. Smaller surface, no longer canonical (Prism replaced it - inside CRuby itself), and missing the recent syntax forms. -- **Hand-written nom parser**: the rewrite plan §6.8 explicitly calls - this out as a bad use of `nom` — replacing a mature language parser. -- **`ruby-prism`**: typed AST built on Prism's C parser via - `bindgen`-generated FFI. 156-method `Visit<'pr>` trait - auto-generated from upstream's `config.yml`, mirroring the - ruff/mago architecture (override the metric-bearing nodes; call - the matching `visit__node(self, node)` free function to keep - walking). Tracks every Ruby release because it IS the Ruby parser. - -### 1.2 License audit (plan §6.5) - -- `ruby-prism` (Rust crate): MIT — Steve Loveless, Ian Ker-Seymer, - Kevin Newton. -- `ruby-prism-sys` (Rust FFI crate): MIT. -- Bundled upstream Prism C parser (vendored under - `ruby-prism-sys/vendor/`): MIT — Shopify Inc., 2022–present. - -All three layers are permissive, no copyleft, compatible with mehen's -licensing. The `vendor/` directory is shipped with the published -`ruby-prism-sys` crate, so the build never fetches Ruby source over -the network. - -### 1.3 Build prerequisites (plan §6.5) - -`ruby-prism-sys` invokes `bindgen 0.72` _unconditionally_ in its -`build/main.rs` (regenerating Rust bindings against the vendored Prism -C headers on every build), and compiles the vendored Prism sources via -`cc 1.0` when its default `vendored` feature is on. That means every -target that builds mehen from source needs: - -- a working `libclang` available at build time (for `bindgen`); -- a C compiler (`clang` / `gcc` / `cl`) on `PATH` (for `cc`). - -End users who install the release `mehen` binary do NOT need either. -The CI/release matrix does — see the workspace `Cargo.toml`'s pin -comment for the per-platform notes (Linux glibc/musl, macOS, Windows). - -## 2. What is _not_ different - -The following metric outputs match legacy where the underlying source -is well-formed Ruby: - -- `cyclomatic.{sum,min,max,avg}` for `if`/`elsif`/`unless`, - `while`/`until`, `for`, `case`/`when`, `case`/`in`, `rescue` (block - - modifier), `&&`/`||`/`and`/`or`, conditional `?:`, every modifier - form (`x if y`, `x unless y`, `x while y`, `x until y`, `expr rescue -fallback`). -- `cognitive.{sum,min,max,avg}` — nesting bumps for control-flow - scopes, +1 (no nesting) for modifiers / `else` / `elsif`, the - same boolean-sequence collapser, depth-on-method-nesting, and - lambda-tracking rules. -- `abc.{assignments,branches,conditions,magnitude,...}` — every - written form (`=`, `+=`, `&&=`, `||=`) counts assignment, every - real method call counts branch, every comparison op + control-flow - predicate counts condition. -- `halstead.{n1,N1,n2,N2,length,vocabulary}` — operator/operand - classification still emits one operator entry per keyword and - operator-method call, one operand entry per identifier / variable / - literal. -- `loc.{sloc,ploc,lloc,cloc,blank}` — comment and code-line accounting - preserved; LLOC bumped on the same set of statement-shaped nodes - (`def`, `class`, `module`, `if`, `unless`, `while`, `until`, `for`, - `case`, modifiers, `return`, `break`, `next`, `redo`, `yield`, - every assignment, every call). -- `nargs.{total,average,min,max}` per function and per closure. -- `nom.{functions,closures,total,average,min,max}` — every `def` and - `def self.foo` is a function, every block (`do…end` / `{ … }`) and - lambda (`->{}` / `lambda { }`) is a closure (with the legacy - exception: a block whose direct parent is a lambda is the lambda - body, not a separate closure). -- `nexit.{sum,min,max,avg}` — `return`, `break`, `next`, `redo` count; - `yield` does NOT (it hands off, it doesn't exit the method). -- `npa.{class_attributes,total_attributes,...}` — class-body `@x =` - ivar assignments count as non-public attributes (Ruby ivars are - non-public by convention; `attr_reader` exposure is out of scope). -- `npm.{class_methods,total_methods,...}` — every `def` inside a - class / module / singleton-class body is a method, all counted as - public (Ruby `private` / `protected` are runtime calls; without - semantic flow analysis we treat every `def` as public, matching the - legacy walker's default). -- `wmc.{classes,interfaces,total}` — class WMC sums each method's - cyclomatic. -- `mi.{*}` — derived from the above; unchanged. - -## 3. What _is_ different - -Each item below is a deliberate divergence from the legacy walker. -They fall into two buckets: - -- **§3.1–3.6**: parity-preserving on the metric _definition_; the - difference is only that prism's typed AST exposes the underlying - fact more cleanly than tree-sitter's CST. Numeric output is - byte-identical to legacy. -- **§3.7–3.8**: intentional drift — same behavioural change adopted in - Phase 6 (Python) and Phase 8 (PHP) when mehen-metrics' `State` - helpers landed. Documented here for completeness. - -### 3.1 Modifier-form detection via location options, not separate node kinds - -`tree-sitter-ruby` had `if` / `if_modifier`, `unless` / -`unless_modifier`, `while` / `while_modifier`, `until` / -`until_modifier` as **distinct node kinds**. The legacy walker -matched each pair separately. - -Prism collapses each pair into a single AST struct (`IfNode`, -`UnlessNode`, `WhileNode`, `UntilNode`) and distinguishes block from -modifier form via the absence of `end_keyword_loc` / `closing_loc`: - -| Form | `end_keyword_loc` / `closing_loc` | -| ------------------------------------ | --------------------------------- | -| `if y; x; end` (block) | `Some(loc)` | -| `x if y` (modifier) | `None` | -| `a ? b : c` (ternary, only `IfNode`) | `if_keyword_loc.is_none()` | - -Metric output is identical (we still emit +1 cyclomatic for each -form, +1 cognitive without nesting for modifier and ternary, +1+nesting -for block forms). The only change is _how_ the walker classifies. - -### 3.2 `RescueModifierNode` is a distinct node kind in prism - -Ruby's `expr rescue fallback` postfix form. Both tree-sitter-ruby and -prism expose it as a separate node from the block-form `RescueNode` -inside a `BeginNode`. The legacy walker had `RescueModifier`, -`RescueModifier2`, `RescueModifier3` arms (tree-sitter generated -numbered duplicates for ambiguous grammar paths); prism collapses to -just `RescueModifierNode`. Metric output unchanged. - -### 3.3 Operator-method calls vs real method dispatch - -In Ruby `a + b` parses (semantically) as a method call `a.+(b)` — -both tree-sitter-ruby and prism expose this through their generic -"call"-shaped node. The legacy walker disambiguated via the parent -node kind (`binary` for arithmetic/comparison, `call`/`command` for -real dispatch). - -Prism uses a single `CallNode` for both forms, distinguished by the -method name. The walker checks `CallNode::name()`: - -- If the name is in `is_ruby_operator_method` (`+`, `-`, `*`, `/`, - `%`, `**`, `==`, `!=`, `<`, `>`, `<=`, `>=`, `<=>`, `===`, `<<`, - `>>`, `&`, `|`, `^`, `~`, `!`, `+@`, `-@`, `[]`, `[]=`): emit a - Halstead `call_op` operator only. Do NOT count ABC.B. -- If the name is a comparison method (`==`, `!=`, `<`, `>`, `<=`, - `>=`, `<=>`, `===`): also emit ABC.C (matches legacy `binary`-arm - classification). -- Otherwise: real method dispatch — emit ABC.B (branch), record the - method name as a Halstead operand. - -Numeric output matches legacy. - -### 3.4 Op-write families are distinct typed nodes - -Tree-sitter-ruby parses every `=` / `+=` / `&&=` / `||=` / `*=` / `<<=` -as a single `assignment` or `operator_assignment` node with an -operator-token child. Prism splits each into its own typed node: -`LocalVariableWriteNode`, `LocalVariableOperatorWriteNode`, -`LocalVariableAndWriteNode`, `LocalVariableOrWriteNode` — and the -same five-shape split for `instance`, `class`, `global`, `constant`, -`constant_path`, `call`, `index`. The walker can dispatch directly -without inspecting the operator field. - -`*AndWriteNode` (`x &&= 1`) and `*OrWriteNode` (`x ||= 1`) ALSO count -as ABC.C (condition) and +1 cyclomatic — they are short-circuit -operators that introduce a branch. This matches the legacy walker's -treatment of `&&=` / `||=` via the `binary | unary` ABC.C arm. - -### 3.5 Halstead derivation is AST-driven (not token-driven) - -ruby-prism does NOT expose a public token stream — `pm_token_t` and -`pm_lex_*` symbols are not allowlisted by `ruby-prism-sys`'s bindgen -build. So unlike Phase 6 (Ruff `TokenKind` sweep) and Phase 8 (Mago -`Lexer`), Halstead must derive from the AST. - -The legacy tree-sitter walker also derived Halstead from the CST (no -flat token stream there either) — it visited every CST node and -classified by `kind_id`. We do the same with prism: dedicated -`visit_*_node` hooks emit Halstead operators for keywords / structural -punctuation / call-operators, and `visit_local_variable_read_node` / -`visit_constant_read_node` / `visit_required_parameter_node` / -`visit_integer_node` / `visit_string_node` / `visit_true_node` / etc. -emit operands. Numeric output (`n1`, `n2`, `N1`, `N2`) matches the -legacy snapshot. - -### 3.6 PLOC keyword-line accounting - -Tree-sitter-ruby's grammar surfaces `end`, `do`, `then`, `=>`, and -similar keyword tokens as anonymous-keyword child nodes. The legacy -`Loc::compute` `_` arm therefore inserted those tokens' start_row -into `ploc.lines`, so a one-line-per-keyword `end` contributed to -PLOC even though it has no semantic content beyond block termination. - -Prism does NOT expose keyword tokens as separate AST nodes — they -live as `Option` fields on the parent (e.g. -`DefNode::end_keyword_loc()`). To preserve PLOC parity (`end` IS a -physical line of code per the SLOC/PLOC definition), the walker -explicitly observes `code_line` for those keyword locations from the -parent's visit hook (see `Visitor::observe_keyword_line` / -`observe_optional_keyword_line`). Numeric output matches legacy. - -### 3.7 Empty-aggregate average serializes as `0.0`, not `null` - -**Intentional drift, shared with Phase 6 (Python) and inherited from -the 1.0 mehen-metrics design.** - -When a Ruby source has no functions (e.g. `a = 42` at the unit -level), the legacy walker emitted `"average": null` for `cognitive` -and `nexit` (zero denominator → JSON null). The 1.0 mehen-metrics -`CognitiveStats::finalize` and `NexitStats::finalize` default to -`0.0` instead, matching the `as_f64` helper used by every other -language crate. The Phase-6 `python_no_cognitive` test pinned this -convention; we follow it for Ruby. - -### 3.8 `nargs.*_min` no longer dilutes via the unit space - -**Intentional drift, shared with Phase 6 (Python) and Phase 8 (PHP).** - -The legacy walker's `compute_minmax` ran _unconditionally_ for every -space — so the unit space's `fn_nargs = 0` always pulled the -`functions_min` floor down to 0, even when every actual function in -the file had >0 args. The 1.0 mehen-metrics `NargsStats::finalize_minmax` -gates the function bounds on `is_function == true`, so the unit no -longer participates. Result: for `def f(a, b)\n a + b\nend`, -`functions_min` is `2.0` (the only function's arg count), not `0.0`. - -This is a parity-improvement, not a regression: the legacy zero was -spurious. The Phase-6 `python_single_function` test pinned this -convention; we follow it for Ruby. - -## 4. New tests pinned by Phase 9 - -`crates/mehen-ruby/tests/parity.rs` exercises Ruby idioms the legacy -fixture set didn't cover. Each test pins prism-specific behavior we -expect to hold long-term: - -- `ruby_safe_navigation_does_not_crash` — `obj&.bar&.baz` parses, two - ABC.B branches recorded. -- `ruby_pattern_matching_each_in_branch_is_a_decision` — `case x; in -pat => g; …; end` adds one cyclomatic per `in` clause + one for the - `if` guard. -- `ruby_endless_method_definition` — Ruby 3.0 `def square(x) = x * x` - counts as one method (`DefNode::end_keyword_loc().is_none()` for - endless methods; we still record NOM=1). -- `ruby_numbered_block_parameters_count_correctly` — `do; puts _1 + -_2; end` recovers arity 2 from `NumberedParametersNode::maximum`. -- `ruby_singleton_class_body_contributes_to_class_metrics` — `class -<< self; def …; end; end` opens a class-like space; methods inside - count toward NPM. -- `ruby_modifier_if_does_not_increase_nesting` — two sibling `x if y` - modifier statements each contribute +1 cognitive; they do NOT - collapse into a nested-if pattern. -- `ruby_op_assignment_writes_count_as_assignment_and_decision` — - `x &&= 1` and `x ||= 2` each contribute one ABC.A + one ABC.C + - one cyclomatic decision. - -## 5. Walker structure - -`crates/mehen-ruby/src/walker.rs` drives recursion through prism's -[`Visit<'pr>`](https://docs.rs/ruby-prism/latest/ruby_prism/trait.Visit.html) -trait — the auto-generated 156-method visitor mirroring the same -shape as `mago_syntax::walker::Walker` (Phase 8 PHP) and -`ruff_python_ast::visitor::source_order::SourceOrderVisitor` (Phase 6 -Python). We override the metric-bearing hooks, call the matching -`visit__node(self, node)` free function to descend, and use -`visit_branch_node_enter` / `visit_leaf_node_enter` for the -PLOC-line-set sweep (mirrors the legacy `_` arm of -`Loc::compute`). - -The walker follows the same per-space `State` accumulator pattern -(`mehen-metrics::state`): - -- One `State` for the unit, plus one for every opened - function / closure / class space. -- Cyclomatic / cognitive / ABC / nexit / LOC / NPA / NPM are driven - by the per-shape overrides. -- Halstead is unit-level only — every operator/operand observation - goes to `self.stack[0].halstead`. -- `CognitiveContext` tracks `(nesting, depth, lambda)` exactly as the - legacy `cognitive::RubyCode` did. -- `inside_lambda_body` flag suppresses the per-block lambda bump for - a `BlockNode` whose immediate parent is a `LambdaNode` (the lambda - body is not a separate closure). - -`ParseResult<'pr>` is `!Send + !Sync`, so the analyzer parses + walks - -- collects metrics in one stack frame and discards the parse result - before returning `LanguageAnalysis` (which is `Send + 'static`). - -## 6. References - -- Pinned ruby-prism revision: `1.9.0` on crates.io. -- Prism upstream: . -- ruby-prism docs: . -- `Visit` trait usage example: `lib.rs::tests::visitor_test` in the - ruby-prism source distribution. -- Plan §6.5 — Ruby and Prism rationale. -- Plan §12.3.1 — parity contract. -- Migration commit: see `git log --oneline | grep 'phase-9'` for the - patch series. diff --git a/design-docs/rust-ra-ap-syntax-spec.md b/design-docs/rust-ra-ap-syntax-spec.md deleted file mode 100644 index 46fe5236..00000000 --- a/design-docs/rust-ra-ap-syntax-spec.md +++ /dev/null @@ -1,364 +0,0 @@ -# Rust analyzer spec — ra_ap_syntax backend - -**Status:** implementation reference -**Date:** 2026-05-18 -**Scope:** `mehen-rust` ra_ap_syntax-backed analyzer (Phase 9 of the v1 -rewrite, replacing the tree-sitter-rust pipeline) - -## 1. Goal - -Phase 9 of the [v1 rewrite plan](mehen-1-0-from-scratch-rewrite-plan.md) -swaps the Rust parser from `tree-sitter-rust` to rust-analyzer's -published `ra_ap_syntax` (rowan-based concrete syntax tree, with a -typed AST overlay) plus its bundled `ra_ap_parser`. The two crates are -re-published from the rust-analyzer monorepo onto crates.io -automatically; we pin a specific 0.0.x release because rust-analyzer's -publication cadence is fast and AST-level breakage is not -semver-tracked. - -The plan §6.1 originally listed Rust under "tree-sitter-rust for 1.0; -revisit rust-analyzer syntax later if needed." Phase 9 promotes that -"later" to "now" because the new analyzer crates Mehen has shipped -(Ruff for Python, Oxc for TypeScript) have established the -language-specific-parser pattern: each language gets the parser that -exposes the *richest* AST for that language's metrics. Tree-sitter -generates a single grammar table; ra_ap_syntax surfaces typed nodes -(`ast::IfExpr`, `ast::MatchArm`, `ast::BinExpr::op_kind()`, -`ast::TryExpr`, `ast::LetExpr`) plus a rowan green/red tree that's -error-tolerant by design. - -The published metric contract is unchanged — Halstead, Cyclomatic, -Cognitive, ABC, NArgs, NOM, NExit, NPA, NPM, WMC, LOC, MI all keep -their semantics and serialization shape. What changes is the -*interpretation* of a handful of Rust-specific constructs where the -tree-sitter grammar's CST shape produced demonstrably wrong, fragile, -or weakly-grounded results. Each divergence below is justified from -the metric definition rather than from a desire to mirror legacy. -`crates/mehen-rust/tests/` carries the pinned snapshots. - -Why `ra_ap_syntax` and not `rustc_parse`-via-`rustc_private`: - -- `rustc_parse` from `rust-lang/rust` requires nightly + the - `#![feature(rustc_private)]` gate + the `rustc-dev` rustup component. - Pinning the workspace to a specific nightly turns every CI runner, - release matrix entry, and contributor laptop into a "must install - rustc-dev" surface. Mehen's release toolchain is stable Rust 1.93.1+; - going nightly was rejected. -- The published `ra-ap-rustc_parse` *meta-crate* on crates.io - intentionally does not include the actual `rustc_parse` / - `rustc_ast` / `rustc_session` / `rustc_span` crates because those - pull in nightly thread-local infrastructure (`SessionGlobals`). - rust-analyzer's auto-publish bot only ships leaf crates that compile - on stable. -- `ra_ap_syntax` *is* what rust-analyzer itself uses for its concrete - syntax tree. It compiles on stable, has no `Session` global, is - thread-safe, and exposes every AST node the metric walker needs. - See `Cargo.toml`'s pinned `ra_ap_syntax = "=0.0.333"`. - -## 2. What is *not* different - -The following metric outputs match legacy where the underlying source -is well-formed Rust: - -- `cyclomatic.{sum,min,max,avg}` for `if`/`else if`, `for`, `while`, - `loop`, `match` arms, the `?` operator, and short-circuit `&&`/`||`. -- `cognitive.{sum,min,max,avg}` for nesting penalties, the boolean - sequence collapser, function-depth penalty, labeled - `break`/`continue`, and the legacy `Else`-token +1 rule. -- `nom.*` for function and lambda counts. -- `nexit.*` for `return` and `?`. -- `abc.*` for assignments (`=`, compound `+=`, `let` initializers, - walrus-equivalent `let-else` bindings), branches (call expressions, - method calls, macro invocations), and conditionals (`if`, `match`, - loop heads, `?`, comparison operators, logical operators). -- `npa.*` / `npm.*` for class-body fields and methods, with - `pub`/`pub(crate)`/`pub(super)` all classifying as public, and trait - methods implicitly public. -- `wmc.*` summed from method cyclomatic. -- `mi.*` Maintainability Index variants. -- Halstead `volume` / `difficulty` / `effort` family on well-formed - source. - -## 3. What is different (and why) - -### 3.1 Top-level statement fragments need wrapping in tests - -Tree-sitter-rust accepts a free-standing `let a = ();` at the top -level of a source file because its grammar has a permissive -`source_file -> _statement*` production. ra_ap_syntax — like rustc -itself — requires every statement to live inside a function body or -const initializer. A bare `let` at the top level produces an `ERROR` -node containing the raw tokens, not a `LET_STMT`. - -This is purely a *test-fixture* issue. Real `.rs` files shipped to -mehen always have proper top-level structure. Where the legacy LOC -test corpus used a bare statement (`"let a = ();"`), the Phase 9 -ports wrap the fragment in `fn _wrap() { … }` and document the -file-level totals (`sloc`, `ploc`, `lloc`, `cloc`, `blank`) — the -per-space `_min`/`_max` shift because of the added function space, -but the *statement*'s LLOC contribution is unchanged. - -This is the same kind of fixture-correctness adjustment documented -in `docs/python-ruff-spec.md` §3.5 (Python indentation) and -`docs/rust-ra-ap-syntax-spec.md` (this document). Production input -is always real Rust; only test fixtures need adjusting. - -Test: `crates/mehen-rust/tests/loc.rs` — every test that uses -`analyze_wrapped` documents the wrap inline. - -### 3.2 LOC cyclomatic / cognitive `null` average is now `0.0` - -Legacy serialized `cognitive.average` and `nexit.average` as JSON -`null` when the unit had zero functions (because the legacy -`Stats::cognitive_average: Option` was rendered through serde's -default `Option` → `null`). The Phase-1+ shared accumulators in -`mehen-metrics::cognitive` and `mehen-metrics::counters::NexitStats` -emit `0.0` — there is nothing to average, and `0.0` is mathematically -defensible for "no contribution." - -Same drift documented for Python (`docs/python-ruff-spec.md` §2 implicit) -and applies workspace-wide. - -Test: `crates/mehen-rust/tests/cognitive.rs::rust_no_cognitive`, -`tests/exit.rs::rust_no_exit`. - -### 3.3 NargsStats `_min` is gated on `is_function`/`is_closure` - -Before Phase 6, `NargsStats::compute_minmax` folded *every* space's -per-space `fn_nargs` and `closure_nargs` (defaulting to 0 for -unit/class spaces) into the rolled-up min. Result: any source with at -least one function and a unit space reported `functions_min: 0.0` -even when the only function had 2 args. - -Phase 6's `NargsStats::finalize_minmax` gates the per-space fold on -`is_function`/`is_closure` flags. The Rust port inherits the fix -unchanged — `fn f(a: bool, b: usize)` now reports `functions_min: 2.0` -(legacy: `0.0`), matching the metric's intended definition. - -Same drift documented for Python (`docs/python-ruff-spec.md` §3.4) -and PowerShell (`crates/mehen-powershell/tests/nargs.rs` module -header). Rust's NomStats follows the same shape. - -Test: `crates/mehen-rust/tests/nargs.rs::rust_single_function` and -all other Rust nargs ports carry the corrected `_min` snapshots. - -### 3.4 NPM publishes "public-method count" instead of "container count" - -The legacy NPM JSON serialization used `interfaces` to mean "number -of trait containers" and `interfaces_average` to mean -`interface_methods / interfaces`. The Phase-1+ pipeline's -`mehen-metrics::counters::NpmStats::publish_npm` re-uses those field -names with different semantics: `interfaces` is the total -*public-method* count in interfaces, and `interfaces_average` is the -public-ratio (`public / total`). This is a deliberate metric- -definition change shared across all Phase 9 ports — every language's -NPM follows the same `publish_npm` shape. - -For Rust this means: a trait with 2 methods (both implicitly public) -publishes `interfaces: 2.0, interface_methods: 2.0, -interfaces_average: 1.0` — not `interfaces: 1.0, -interfaces_average: 2.0` as legacy did. - -Test: `crates/mehen-rust/tests/npm.rs::rust_npm_counts_trait_signature_and_default_methods`. - -### 3.5 Trait method NPM bookkeeping happens on the enclosing space - -The python walker's pattern is: when a class body contains a `def`, -record the method on the *class's* state (via -`classify_class_body_member`), and let the function space's own NPM -counters stay at zero. The Rust walker follows the same pattern — -when entering a `Fn` whose grandparent is `Trait` or `Impl`, the NPM -contribution lands on the *enclosing trait/impl state*, not on the -function's own state. - -The reason is double-counting: if both the trait and the -function's own state record the method, the trait's `finalize_minmax` -folds its own per-space NPM into the sum, AND merges the child -function's NPM sum, producing 2× the expected count. By recording on -the enclosing scope only, the merge path stays consistent. - -Test: `crates/mehen-rust/tests/npm.rs::rust_npm_counts_pub_in_impl_block` -(2 impl methods, 1 public). - -### 3.6 Trait function signatures (no body) do not open a func space - -A trait method declared without a body (`fn next(&self);`) is not a -function space in the legacy walker — there's nothing to walk. The -ra_ap_syntax walker mirrors this: when entering an `ast::Fn` whose -`body()` is `None`, we skip the `open_space` call but still record -the method on the enclosing trait via `classify_method`. - -Default-bodied trait methods (`fn count(&self) -> usize { 0 }`) flow -through the regular FuncSpace + merge path. - -Test: `tests/parity.rs::rust_trait_associated_types_and_consts_are_not_methods`. - -### 3.7 Else-token +1 attributed to the parent IF_EXPR - -The legacy walker emitted a flat `+1 cognitive` on every `Else` token, -covering both `else if` (the connecting `else` between two `if` -expressions) and bare `else { … }` (the alternative branch). - -ra_ap_syntax's typed AST does not surface a dedicated `Else` node — -each `IfExpr` exposes its own `else_token()` and `else_branch()`. The -walker attributes the +1 to the *parent* `IF_EXPR` whose -`else_token()` is present. The behavioral count is unchanged. - -For nested `if A { … } else if B { … } else { … }`, this means the -outer `if A` emits +1 (it has an else branch), the inner `if B` does -NOT emit a nesting bump (it's an `else if`), and the inner `if B` -emits +1 (it has its own bare `else`). Total: +1 (A's else) + +1 (B's -else) + nesting penalty for `if A`. Matches legacy. - -Test: `tests/cognitive.rs::rust_1_level_nesting_complex`, -`rust_break_continue`, `rust_if_let_else_if_else`. - -### 3.8 Block tail expression is a logical line of code - -A function body's *tail expression* (`fn f() { 42 }`'s `42`, no -semicolon) is a logical line of code per the legacy -`is_rust_tail_expression` rule. tree-sitter exposed this via parent- -chain inspection; ra_ap_syntax exposes it directly via -`StmtList::tail_expr()`. The walker emits +1 LLOC for any expression -that is a tail of its enclosing `STMT_LIST`. The kind-specific -handling still fires (a `for` expression that is also a tail still -records its cyclomatic decision). - -Test: `tests/loc.rs::rust_tail_expressions_are_lloc`, -`rust_lloc_for_if`, `rust_function_in_if_lloc`. - -### 3.9 Macro bodies are opaque — same as legacy - -Tokens inside a `MacroCall`'s argument tree (or `macro_rules!` body) -do not contribute to cyclomatic, cognitive, ABC, or exit counters. The -macro path identifier itself counts as a branch (call). This matches -the legacy `is_inside_rust_macro_tokens` filter. - -The implementation tracks the depth of macro-opaque scopes via a -counter that increments on enter and decrements on leave. While -inside a macro body, the structural walk early-returns from -`enter_node` for non-macro kinds, but still tracks nested macro -boundaries so the depth unwinds correctly. - -For Halstead, every macro-opaque range is recorded once during the -structural walk; the post-AST token sweep then skips any token whose -span falls inside any of those ranges. This is more robust than -walking parent chains for every token. - -Test: `tests/cyclomatic.rs::rust_macro_tokens_are_opaque_for_cyclomatic`, -`tests/cognitive.rs::rust_macro_tokens_are_opaque_for_cognitive`, -`tests/parity.rs::rust_macro_body_control_flow_is_opaque`. - -### 3.10 Type annotations contribute to Halstead - -Rust types are not erased at runtime — they describe the shape of -values, are visible to `mem::size_of`, drive trait dispatch, and -appear in `TypeId` reflection. A type identifier like `Vec` is a -*thing* — a real operand in the running program. The walker emits -type-position identifiers as Halstead operands, exactly like -expression-position identifiers. - -This is the same reasoning as Python (`docs/python-ruff-spec.md` -§3.1) and the *opposite* of TypeScript (`docs/typescript-halstead-spec.md`), -where TS-only `TSTypeAnnotation` / `TSInterfaceDeclaration` nodes are -excluded because TS types are erased at compile time. - -### 3.11 Doc comments reach LOC `cloc`, not Halstead - -`///` outer doc comments and `//!` inner doc comments are -`SyntaxKind::COMMENT` tokens at the lexer level. The walker's token -sweep folds every comment token into LOC `cloc` on the unit, but -classifies them as `Skip` in the Halstead sweep — they are -documentation, not running code. This matches the legacy -`add_cloc_lines` for `LineComment` / `BlockComment`. - -### 3.12 `let-else` is an assignment - -`let-else` (RFC 3137, stable in Rust 1.65) was supported by -tree-sitter-rust 0.24+. The legacy walker classified it via -`LetDeclaration if node.is_child(EQ)`. ra_ap_syntax exposes -`LetStmt::let_else()` directly. The walker emits `+1 ABC.assignments` -when the `LetStmt` has an `=` token (i.e. it's a real bind, not a -bare `let x;` declaration). The diverging branch's body participates -in cognitive / cyclomatic counters normally. - -Test: `tests/parity.rs::rust_let_else_is_assignment_with_diverging_else`. - -### 3.13 `if let` chains collapse via the boolean-sequence rule - -`if let` chains (RFC 2497, stable in Rust 1.88) parse as a chain of -`LetExpr` operands joined by `&&`. The Phase-1+ shared -`BoolSequence::eval_based_on_prev` collapses same-op runs into a -single +1, so `if let A = … && let B = … && cond` adds exactly +1 -cognitive (collapsed run) on top of the +1 for the `if`. - -The legacy walker had a special `LetChain` named node; the -ra_ap_syntax walker does not need one — the `&&` operands are regular -`BinExpr` nodes that the standard cognitive rule handles. - -Test: `tests/parity.rs::rust_if_let_chain_collapses_to_single_cognitive_bump`, -`tests/abc.rs::rust_abc_counts_let_chain_operators_in_conditions`. - -### 3.14 Async functions are still functions - -`async fn` is an `ast::Fn` AST node with `async_token()` set; it still -opens a function space, contributes to `nom`, and resets cognitive -nesting on entry. The `.await` postfix is a regular expression that -contributes nothing structural. - -Test: `tests/parity.rs::rust_async_fn_opens_function_space`. - -## 4. Operator and operand classification - -The walker maps `ra_ap_syntax::SyntaxKind` values to one of -`Operator(&str)`, `Operand(&str)`, or `Skip`. The mapping in -`crates/mehen-rust/src/walker.rs::classify_token` covers every Rust -keyword, every punctuation / operator token, and every literal kind -(`IDENT`, `INT_NUMBER`, `FLOAT_NUMBER`, `STRING`, `BYTE_STRING`, -`C_STRING`, `CHAR`, `BYTE`, `LIFETIME_IDENT`, plus the keyword-as- -literal `true`/`false`). - -Closing punctuation (`)`, `]`, `}`) is `Skip` to avoid double-counting -under the classical Halstead pair convention. Trivia (`WHITESPACE`, -`COMMENT`, `TOMBSTONE`, `EOF`) is `Skip`. - -Where a keyword is also a syntactic token (e.g. `Self` vs `self`, -`pub` vs `pub(crate)`), the `T!` macro from ra_ap_syntax disambiguates -the variant. The `T!` macro is preferred over bare `SyntaxKind::*` -imports because Rust's pattern grammar treats unimported uppercase -identifiers as fresh bindings, which silently shadowed our match arms -in early implementation drafts and produced "unreachable pattern" -warnings. - -## 5. Walker structure - -The walker in `crates/mehen-rust/src/walker.rs` follows the same -per-space `State` accumulator pattern used by `mehen-typescript`: - -- One `State` (in `mehen-metrics::state`) for the unit, plus one for - every opened function / closure / impl / trait space. -- Cyclomatic / cognitive / ABC / nexit / LOC / NPA / NPM are driven - per-AST-node via an explicit `WalkEvent::Enter`/`WalkEvent::Leave` - loop over `SyntaxNode::preorder()`. The explicit loop (vs recursion) - is deliberate so the per-space stack can finalize on Leave events - even for deeply-nested input. -- Halstead is driven by a post-AST token sweep over the source file's - `descendants_with_tokens()`. Each token maps to one of - `Operator(kind)`, `Operand(kind)`, or `Skip`. Tokens whose span - falls inside a recorded macro-opaque range are skipped. - -The `CognitiveContext` tracks `(nesting, depth, lambda)` exactly as -the pre-1.0 `cognitive::rust_code` did. The boolean-sequence -collapser lives in `mehen-metrics::cognitive::BoolSequence`; the -walker calls `observe_boolean("&&")` / `observe_boolean("||")` on -`BinExpr` nodes whose `op_kind()` is `LogicOp::And`/`Or`. - -## 6. References - -- Pinned `ra_ap_syntax` version: `=0.0.333` (workspace - `Cargo.toml:105`). -- ra_ap_syntax docs: -- The walker's typed AST entry points are documented inline next to - each `enter_node` arm. -- Migration commit: see `git log --oneline | grep 'phase-9\|ra_ap_syntax\|Rust analyzer'` - for the patch series. diff --git a/design-docs/sql_parser_comparison.md b/design-docs/sql_parser_comparison.md deleted file mode 100644 index c48d216f..00000000 --- a/design-docs/sql_parser_comparison.md +++ /dev/null @@ -1,389 +0,0 @@ -# SQL Parser Selection for `mehen-sql` - -**Status:** decision-support analysis -**Author:** evaluation pass (hands-on, repos cloned and one candidate built) -**Date:** 2026-05-24 -**Companion doc:** [`mehen_sql_metrics_research_foundation.md`](./mehen_sql_metrics_research_foundation.md) -**Addendum:** [§8 — `apache/datafusion-sqlparser-rs` re-evaluation](#8-addendum--apachedatafusion-sqlparser-rs-2026-07-27) (2026-07-27, post-adoption) - -## 0. TL;DR - -| | **sqruff** (`quarylabs/sqruff`) | **sqlfluffrs** (`sqlfluff/sqlfluff/sqlfluffrs`) | **ANTLR grammars-v4 + `antlr-rust-runtime`** | **`sqlparser`** (`apache/datafusion-sqlparser-rs`) † | -|---|---|---|---|---| -| Verdict | **Recommended primary parser** | Not recommended as a dependency now | Niche supplement for deep PL/SQL / T-SQL only | Rejected — AST discards comments, no error recovery | -| Language | Native Rust | Rust, but a build-component of a Python project | Generated Rust over a young Rust runtime | Native Rust | -| License | Apache-2.0 | MIT | MIT/BSD per-grammar + BSD-3 runtime | Apache-2.0 (ASF-governed) | -| Build as git dep | Plain `cargo build` (verified) | **Requires Python + SQLFluff source to codegen dialects at build time** | Needs ANTLR (Java) at dev time; generated Rust can be committed | Published on crates.io, semver | -| Node model | One `SyntaxKind` enum (1087 variants) shared across all dialects | String-typed segments shared across dialects | One generic `ParseTree`; **rule vocabulary differs per dialect grammar** | Typed `enum Statement`/`Expr` — **AST, lossy** | -| Built-in analysis | CTE/query graph, scopes, aliases, wildcards, **column lineage** | None (pure lex+parse) | None (pure CST) | None (explicitly syntax-only, no semantics) | -| Dialects | 17, all hand-written Rust, feature-gated | ~28 (transpiled from Python) | 20 independent grammars | 16 dialect structs | -| Source spans | Verified line:col on every node | `pos_marker` per token | Token line:col | `Spanned` trait, **officially incomplete** (#1548) | -| Comments in tree | **Yes** (comment nodes w/ byte spans) | Yes (tokens) | Yes (hidden channel) | **No** — tokenizer-only | -| Error recovery | **Yes** (`Unparsable` nodes) | Yes (`unparsable`) | Yes (`Error` nodes) | **No** — one error ⇒ zero statements | - -**Bottom line:** sqruff is the only candidate that compiles as an ordinary Rust git dependency, exposes a single dialect-agnostic typed node model with reliable spans, and already ships the higher-level CTE/scope/lineage analysis that the metrics document assumes. It covers essentially the entire proposed metric catalogue. The other three each carry a structural blocker (sqlfluffrs: a Python build-time dependency; ANTLR: no shared node vocabulary + unrunnable semantic predicates for the most important dialects; `sqlparser`: a lossy AST with no comment nodes and no error recovery, so the `sql.loc.*` and `sql.parser.*` families cannot be computed). - -† Added by the [§8 addendum](#8-addendum--apachedatafusion-sqlparser-rs-2026-07-27) (2026-07-27); not part of the original 2026-05-24 evaluation. - ---- - -## 1. What the metrics actually demand from a parser - -Distilled from the research foundation, the parser must provide: - -1. **Reliable per-node source spans** (line/col) — for top-offender attribution (§4.7, §10). -2. **A dialect-agnostic node vocabulary** — so one extractor serves many dialects, matching mehen's "shared output, language-owned semantics" model (§2). -3. **Statement-kind classification** across DDL/DML/DCL/TCL/procedural (§5.2, §6.14). -4. **Query-block + CTE structure with a dependency graph** (§5.3–§5.5, §6.3–§6.4). -5. **Join, subquery (incl. correlation), set-op, CASE, window, predicate trees** (§6.5–§6.12). -6. **Scope/identifier resolution** — CTE vs table vs alias, qualification, wildcards (§5.4, §6.13). -7. **Graceful failure surface** — unparsable segments + diagnostics for confidence metrics (§6.16). -8. **Procedural control-flow nodes** for PL/SQL & T-SQL (§6.17, Phase 3). -9. **Optional column lineage** (§8.7, Phase 4). - -The recurring theme: the document does not just want a token stream — it wants a *structured, dialect-normalized* tree plus some graph/scope analysis on top. - ---- - -## 2. Candidate A — sqruff (quarylabs) - -Cloned at `v0.38.0` (commit `63ae4c4f`). Crates: `lib-core` (lexer+parser+segment model+analysis utils), `lib-dialects` (17 dialects), `lineage` (column lineage), `sqlinference`, `lib` (linter/templaters), `lsp`, `cli`. - -### 2.1 Node model and spans - -- The CST is `ErasedSegment` (= `Rc`); every node carries a `SyntaxKind` (single enum, **1087 variants**) and an optional `PositionMarker`. -- Traversal is first-class: `recursive_crawl(types, …)`, `child`/`children(SyntaxSet)`, `get_start_loc()/get_end_loc()` returning `(line, col)`, plus `is_code/is_comment/is_whitespace/is_meta` and `is_templated()` (literal vs templated spans). -- **One enum across all 17 dialects** is the single biggest ergonomic win: a metric extractor written once (`SyntaxKind::JoinClause`, `CaseExpression`, `OverClause`, …) works for postgres, tsql, snowflake, bigquery, etc. - -### 2.2 Built-in higher-level analysis (this is the differentiator) - -`utils/analysis/query.rs` ships a `Query`/`Selectable` model that already provides, for free, much of §5: - -- `QueryInner { query_type, selectables, ctes: IndexMap, parent, subqueries, cte_definition_segment, cte_name_segment }`. -- `crawl_sources()` resolves each source as **CTE-reference vs base table** (`Source::Query` vs `Source::TableReference`) — i.e. the CTE dependency graph is derivable directly. -- `select_info()` → table aliases, select targets, column aliases, `using` columns; `wildcard_info()` → `SELECT *` / `t.*` with the tables they expand. -- `TableReference::is_qualified()` → directly feeds `sql.identifier.unqualified_column_ratio`. -- A separate `lineage` crate (`Lineage::new(parser, column, sql).build()`) gives column-level lineage for the optional `sql.lineage.*` family (Phase 4) on the same parser. - -### 2.3 Empirical verification (built and run) - -I added `sqruff-lib-core` + `sqruff-lib-dialects` (postgres feature only) as path deps to a throwaway crate and parsed a deliberately gnarly query (recursive CTE + `UNION ALL`, `LEFT JOIN` with compound `ON`, window function with explicit `ROWS` frame, nested `CASE`, `IN (subquery)`, correlated scalar subquery, `r.*`). Output: - -``` -lex errors: 0 -unparsable segments: 0 -SelectStatement = 7 CommonTableExpression = 3 -JoinClause = 3 SetExpression = 1 (UNION ALL) -CaseExpression = 2 OverClause = 1 -WindowSpecification = 1 FrameClause = 1 -ColumnReference = 31 WildcardExpression = 1 (r.*) -FunctionContents = 2 - join span: L6:20..L6:62 "JOIN region_tree rt ON r.parent_id = rt.id" - join span: L11:5..L11:70 "LEFT JOIN customers c ON s.customer_id = c.id AND c.active = true" - join span: L25:1..L25:43 "JOIN region_tree rt ON r.region_id = rt.id" -query_type: WithCompound -CTEs detected: ["REGION_TREE", "SALES_BASE", "RANKED"] -top-level subqueries: 1 -``` - -Everything the Phase-1 catalogue needs came out of one parse, with correct spans, **zero** unparsable segments, and the CTE/subquery graph recovered by the built-in analyzer. Incremental rebuild after the first compile was 0.31s. - -### 2.4 Coverage of the proposed metric families - -Confirmed `SyntaxKind` variants exist for: `CommonTableExpression`, `JoinClause`, `JoinOnCondition`, `SetExpression`/`SetOperator`, `CaseExpression`/`WhenClause`, `OverClause`/`WindowSpecification`/`FrameClause`/`PartitionClause`, `GroupbyClause`/`CubeRollupClause`/`GroupingSetsClause`, `MergeStatement`/`MergeMatch`, `QualifyClause`, `FromPivotExpression`/`FromUnpivotExpression`, `WildcardExpression`, `CastExpression`, `FunctionContents`, `Expression`, `ColumnReference`, every `*Statement` (insert/update/delete/truncate/drop/alter/access/transaction…), and procedural ones (`IfStatement`, `LoopStatement`, `WhileStatement`, `ForLoopStatement`, `BeginEndBlock`, `TryCatch`, `RaiseStatement`, `ReturnStatement`, `CreateProcedureStatement`, `DeclareStatement`, `ExecuteStatement`). `SyntaxKind::Unparsable` is the recovery node for confidence metrics. - -### 2.5 Cons / risks - -- **`Rc`-based tree is not `Send`/`Sync`.** mehen's `LanguageAnalyzer` is `Send + Sync` and returns *owned* `LanguageAnalysis`. This is fine because parsing+extraction happen inside a single `analyze()` call and only owned `MetricSet`/`MetricContribution` escape — the same pattern mehen already uses around non-`Send` parse state. Constraint to respect: do not hold an `ErasedSegment` across threads; extract facts within the call. -- **API stability is not guaranteed** (Open question #1 in the research doc). `lib-core` is an internal crate of an app, version `0.x`, no semver promise. Mitigation: the metrics doc already mandates a `parser_adapter` boundary that converts `SyntaxKind` nodes into mehen `SqlFact`s — keep that thin seam so a sqruff bump is contained. -- **Procedural depth is linter-grade, not exhaustive.** The procedural `SyntaxKind`s exist and tsql/oracle dialects use them, but sqruff's oracle/PL-SQL surface is narrower than the dedicated ANTLR `plsql` grammar. Acceptable for Phase 1–2; revisit for a deep Phase-3 procedural push (see §4). -- **Dependency weight:** pulls `fancy-regex`, `strum`, `indexmap`, `hashbrown`, `smol_str`, `serde_yaml` (in dialects). Comparable to what mehen already absorbs for ruff/tree-sitter. `lib-dialects` is feature-gated, so you can compile only the dialects you ship. -- **Templating (Jinja/dbt) lives in the heavier `lib` crate**, which pulls Python templater plumbing. For standalone `.sql` you only need `lib-core` + `lib-dialects`; treat templating as an opt-in later decision (Open question #3). - ---- - -## 3. Candidate B — sqlfluffrs (the Rust crate inside SQLFluff) - -Cloned at `v4.2.1` (commit `3fdeaf50`). Workspace: `sqlfluffrs_types` (token/marker/grammar tables), `sqlfluffrs_lexer`, `sqlfluffrs_dialects`, `sqlfluffrs_parser` (table-driven), `sqlfluffrs_python` (pyo3). - -### 3.1 The decisive blocker: dialects are generated from Python at build time - -`sqlfluffrs_dialects/build.rs` (quoting its own header): the generated dialect sources `src/dialect//{parser,matcher}.rs` and `src/dialect/mod.rs` are **not checked into version control**; they are produced by running `python utils/rustify.py build`, which imports the SQLFluff Python package (`from sqlfluff.core.dialects import dialect_readout`) and transpiles each Python dialect into Rust. I confirmed `sqlfluffrs_dialects/src/dialect/` does not exist in a fresh checkout. - -Consequences for using it as a Cargo git dependency: - -- `cargo build` in mehen would shell out to a **Python interpreter** and require the SQLFluff source tree importable (build.rs prepends `/src` to `PYTHONPATH`). That is a hard, non-Rust build prerequisite on every dev machine and CI runner. -- It contradicts the whole point of mehen's generated-code policy (commit the generated `grammar.rs`, verify drift in CI). sqlfluffrs regenerates on mtime, into `OUT_DIR`-adjacent paths, from a Python toolchain you don't control. -- The project README is explicit: *"not intended to be used as a standalone linting solution… experimental,"* and AGENTS.md: *"Experimental and incomplete… may have compatibility issues with some dialects."* Its release cadence is tied to SQLFluff's Python releases, and the `python` feature wires in `pyo3`. - -### 3.2 If that blocker were removed - -The token model would be workable but weaker than sqruff: - -- `Token { token_type: String, class_types: HashSet, pos_marker: Option, segments: Vec, … }` — node types are **strings** (mirrors SQLFluff's dynamic Python typing). You'd match `"select_statement"`, `"join_clause"`, `"common_table_expression"` by string — no enum exhaustiveness, slower comparisons, easy to typo. -- **No Rust analysis layer at all** — `sqlfluffrs` is lexer+parser only. The CTE/query graph, scope resolution, wildcard expansion, correlation detection, and lineage that sqruff hands you would all have to be re-implemented from scratch in Rust against string-typed nodes. -- Spans exist (`pos_marker`), and dialect breadth (~28, transpiled) is the widest in theory — but only as good as the in-progress transpiler, which the maintainers call incomplete. -- The owned `Vec` tree (with `Weak` parents) is likely `Send`, a minor plus over sqruff's `Rc`, but irrelevant given the build blocker. - -### 3.3 Verdict - -Re-evaluate only if upstream ever ships **pre-generated, checked-in Rust dialects** (or a published crate on crates.io with no Python build step). Until then, the build-time Python dependency disqualifies it for a Rust-only CLI. - ---- - -## 4. Candidate C — ANTLR grammars-v4 + `ophidiarium/antlr-rust-runtime` - -`grammars-v4/sql` has 20 independent dialect grammars (postgresql, plsql, tsql, mysql, sqlite, snowflake, db2, hive, trino, clickhouse, databricks, mariadb, teradata, …; **no generic ANSI, no BigQuery, no DuckDB**). `antlr-rust-runtime` is `v0.3.0`, BSD-3, a clean-room runtime with a **metadata-first** generator: `antlr4-rust-gen` consumes ANTLR `.interp` files (serialized ATN + token/rule names) and emits Rust. It passes the full upstream runtime-testsuite (357 descriptors). - -### 4.1 Structural blockers for the metrics use case - -1. **No shared node vocabulary.** The generated tree is a generic `ParseTree { Rule(RuleContext), Terminal, Error }`; you navigate by `rule_index → rule_names[idx]` (a string) and positional children — there are no typed accessors. Worse, each dialect grammar is authored independently, so postgresql's rule names bear no relation to tsql's or sqlite's. A metric extractor would have to be **rewritten per dialect grammar** — the opposite of mehen's shared-vocabulary model and an N× maintenance burden. -2. **Semantic predicates/actions can't run from `.interp`.** The runtime's path deserializes the ATN but cannot execute target-language semantic predicates or `superClass` helper methods (their code isn't in `.interp`). The two most important relational dialects depend on exactly this: - - `postgresql` → `superClass = PostgreSQLLexerBase/ParserBase` + 9 predicates (dollar-quoting, etc.). - - `plsql` → `superClass = PlSqlLexerBase/ParserBase` + 20 predicates. - - `mysql` (Oracle/original) → `superClass = MySQLBaseRecognizer` + many `{this.serverVersion >= …}?` predicates. - - These base classes are shipped for Java/C#/Go/JS/Python/TS/C++ — **not Rust**. Using those grammars means hand-porting the base classes to Rust *and* wiring predicate evaluation, per grammar. `tsql`, `snowflake`, and `sqlite` are the clean ones (no `superClass`, 0 predicates, no embedded actions) and would generate/parse cleanly. -3. **No analysis layer whatsoever.** Pure CST. CTE graph, scopes, correlation, wildcard expansion, lineage — all from scratch, on top of generic rule contexts. -4. **No normalized statement kinds.** `select` vs `insert` vs `create_procedure` is just a rule name that differs per grammar; you build the §5.2 taxonomy by hand for each. - -### 4.2 The one place ANTLR wins - -The `plsql` (12.6k lines) and `tsql` (7.6k lines) grammars are the most complete procedural-SQL grammars in existence. For a *deep* Phase-3 procedural push (full PL/SQL exception/cursor/loop semantics, T-SQL `TRY/CATCH`/`WHILE`/cursors), the dedicated ANTLR grammars model far more than sqruff's linter-oriented procedural surface. `tsql` is the sweet spot: no base classes, no predicates → generates cleanly onto `antlr-rust-runtime`, and `.interp`-generated Rust can be **committed** (matching mehen's generated-`grammar.rs` policy, with `antlr4-rust-gen` playing the role `xtask tree-sitter generate` plays today). - -### 4.3 Verdict - -Not viable as the primary/general SQL parser: no cross-dialect vocabulary, broken predicate handling for postgres/plsql/mysql, and everything above the CST built from zero. Worth keeping in the back pocket as a **dedicated procedural augmentation** (tsql first, then plsql if the base classes are ported) once Phase-3 demands depth sqruff can't reach. - ---- - -## 5. Side-by-side metric-coverage matrix - -Rating each parser by how much work the proposed metric family needs. -**Direct** = node/API exists, count/measure immediately · **Derive** = straightforward traversal/aggregation on existing nodes · **Build** = must implement a non-trivial analysis layer yourself · **Blocked** = structural obstacle before you can start. - -| Metric family (doc §) | sqruff | sqlfluffrs* | ANTLR (clean dialects)** | -|---|:--:|:--:|:--:| -| LOC / size / comments (6.1) | Direct | Direct | Direct | -| Statement kinds DDL/DML/DCL/TCL (6.2, 6.14) | Direct | Derive | Build (per grammar) | -| Query blocks + depth (6.3) | Direct | Derive | Derive | -| CTE count + dependency graph (6.4) | **Direct** (`Query.ctes`, `crawl_sources`) | Build | Build | -| Joins + kinds (6.5) | Direct | Derive | Derive | -| Subquery + derived tables (6.6) | Direct | Derive | Derive | -| Correlated-subquery detection (6.6) | Derive (parent links exist) | Build | Build | -| Predicate / boolean tree (6.7) | Direct/Derive | Derive | Derive | -| CASE incl. nesting (6.8) | Direct | Derive | Derive | -| Aggregation / GROUPING SETS / ROLLUP (6.9) | Direct | Derive | Derive | -| Window incl. frames (6.10) | Direct | Derive | Derive | -| Set ops + depth (6.11) | Direct | Derive | Derive | -| Expression depth / function nesting (6.12) | Direct | Derive | Derive | -| Output shape: `*`, alias coverage (6.13) | **Direct** (`wildcard_info`, `select_info`) | Build | Build | -| Unqualified-column ratio (6.13) | Derive (`is_qualified`) | Build | Build | -| Object touch / migration risk (6.14) | Direct | Derive | Build | -| Halstead operators/operands (7) | Derive | Derive | Derive | -| Dialect / portability (6.15) | Direct (`DialectKind` + dialect kinds) | Derive | Build (no generic ANSI) | -| Parser health / unparsable (6.16) | **Direct** (`SyntaxKind::Unparsable`) | Direct (`unparsable`) | Derive (`Error` nodes) | -| Procedural cyclomatic/cognitive (6.17) | Derive (linter-grade) | Derive | **Direct** (plsql/tsql richest) | -| Column lineage (8.7) | **Direct** (`lineage` crate) | Build | Build | - -\* sqlfluffrs ratings assume the **Python build-time blocker is solved** — otherwise the whole column is Blocked. -\*\* ANTLR ratings are for `tsql`/`snowflake`/`sqlite`; for `postgresql`/`plsql`/`mysql` every cell is **Blocked** until Rust base classes + predicate evaluation are hand-ported. - ---- - -## 6. Fit with mehen's architecture - -- **Git-dependency precedent:** mehen already pins ruff via tagged git deps. sqruff fits the same pattern cleanly (path/git, feature-gated dialects, plain `cargo build`). sqlfluffrs breaks it (Python at build time). ANTLR sidesteps it by committing generated Rust, but needs the Java ANTLR tool at *generation* time (a dev/xtask step, not a build step). -- **Generated-code policy:** mehen forbids hand-editing generated `grammar.rs` and checks drift in CI via `xtask`. ANTLR's `.interp → antlr4-rust-gen → committed Rust` maps onto this policy naturally; sqlfluffrs violates it (regenerates from Python into uncommitted paths); sqruff is hand-written Rust (no codegen concern). -- **`Send + Sync` analyzer contract:** sqruff (`Rc`) and tree-sitter (borrowed nodes) both require extract-within-the-call — mehen already does this. sqlfluffrs (`Vec`/`Arc`) is friendliest here; ANTLR depends on the generated context ownership. -- **Adapter seam:** regardless of choice, implement the doc's `parser_adapter` → `SqlFact` boundary so metrics never reference parser-internal node names directly. This is cheap with sqruff's enum, essential with ANTLR's per-grammar vocabularies, and the only thing that would make a future parser swap survivable. - ---- - -## 7. Recommendation - -1. **Adopt sqruff (`lib-core` + `lib-dialects`) as the `mehen-sql` parser.** It is the only candidate that builds as a normal Rust dependency, gives one typed node vocabulary across 17 dialects with verified spans, ships the CTE/scope/wildcard analysis the metrics assume, and even has a column-lineage crate for Phase 4. The hands-on probe showed it covers the entire Phase-1 catalogue from a single parse. -2. **Wrap it behind the `parser_adapter`/`SqlFact` boundary** the research doc already specifies, so the `0.x` API surface and the `Rc` tree stay contained and a later swap is localized. -3. **Defer templating:** start with `lib-core`+`lib-dialects` for standalone `.sql`; only pull sqruff's `lib` templaters (or emit templating-burden metrics) once Open question #3 is decided. -4. **Hold ANTLR `tsql`/`plsql` in reserve for Phase 3** *iff* procedural depth becomes a hard requirement that sqruff's linter-grade procedural nodes can't satisfy. If pursued, start with `tsql` (clean grammar, commits generated Rust via `antlr4-rust-gen` like the tree-sitter `xtask` flow). Do **not** take on postgres/plsql/mysql ANTLR grammars without budgeting the Rust base-class + predicate-evaluation port. -5. **Drop sqlfluffrs** from consideration unless it later publishes pre-generated, checked-in Rust dialects (or a crates.io release with no Python build step). - -### Suggested `mehen-sql/Cargo.toml` shape - -```toml -# Pinned here (single consumer), mirroring the ruff pattern. -sqruff-lib-core = { git = "https://github.com/quarylabs/sqruff", tag = "v0.38.0" } -sqruff-lib-dialects = { git = "https://github.com/quarylabs/sqruff", tag = "v0.38.0", - default-features = false, - features = ["postgres", "tsql", "snowflake", "bigquery", - "mysql", "sqlite", "duckdb", "oracle"] } -# Phase 4 (optional): sqruff-lineage for sql.lineage.* -``` - ---- - -## Appendix — evidence log - -- Repos cloned to `/tmp/sql-parser-eval/`: `sqruff` (`v0.38.0`), `sqlfluff` (incl. `sqlfluffrs` `v4.2.1`), `grammars-v4`, `antlr-rust-runtime` (`v0.3.0`). -- sqruff parse probe: `/tmp/sql-parser-eval/probe` (path-deps on `lib-core` + `lib-dialects[postgres]`), built and run with `rustc 1.89.0`; results in §2.3. -- sqlfluffrs build blocker: read from `sqlfluffrs/sqlfluffrs_dialects/build.rs` and confirmed `src/dialect/` absent in a fresh checkout; dialect count from `src/sqlfluff/dialects/dialect_*.py` (28). -- ANTLR predicate/base-class findings: `rg` over `grammars-v4/sql/*/*.g4` (`superClass`, `}?`) and the shipped per-language `*Base` directories (no Rust); runtime capabilities from `antlr-rust-runtime/README.md` + `docs/runtime-testsuite.md` and the generic `ParseTree` walker in `tests/kotlin-parity/dumper/src/main.rs`. - ---- - -## 8. Addendum — `apache/datafusion-sqlparser-rs` (2026-07-27) - -**Status:** post-adoption re-evaluation · **Verdict: keep sqruff; do not migrate.** - -A fourth candidate that the original pass never evaluated: the `sqlparser` crate -(`apache/datafusion-sqlparser-rs`), the SQL front end for Apache DataFusion. -It is the most prominent SQL parser in the Rust ecosystem, so its absence from -§0 was a real gap. This addendum closes it. - -Probed at **`sqlparser` v0.62.0** (crates.io, Apache-2.0) against -**sqruff v0.39.0** as currently pinned in `crates/mehen-sql/Cargo.toml`. - -### 8.1 The decisive difference: AST vs CST - -sqruff produces a **lossless CST** — every byte of input, including comments and -whitespace, is a node. `sqlparser` produces an **abstract** syntax tree that -discards trivia by design; its README advertises round-tripping "with comments -removed, normalized whitespace and keyword capitalization". - -For a query engine that is the correct trade-off: DataFusion wants semantics, -not formatting. For a *metrics* tool it is disqualifying. Two published metric -families are trivia- or recovery-derived and have no AST equivalent: - -- `sql.loc.{physical,code,comment,blank,logical,comment_density,max_statement_lines,avg_statement_lines}` - — `loc.rs` classifies lines by **comment byte coverage** taken from - `SyntaxKind::{Comment,InlineComment,BlockComment}` nodes. Its module doc - explains why a marker scan is wrong: an interior line of a multi-line block - comment carries no `/*`/`*/` of its own. The four unit tests at the foot of - `loc.rs` encode exactly those edge cases. -- `sql.parser.{unparsable_segment_count,unparsable_line_count,unparsable_ratio,diagnostic_count}` - — these exist only because sqruff emits `SyntaxKind::Unparsable` recovery - nodes and keeps going. - -That is 12 of the crate's metric keys that depend on properties `sqlparser` -does not expose in its tree, plus the per-statement `MetricSpace` attribution -and `change_risk_evidence` contributions that need spans on deep nodes. - -### 8.2 Empirical probe - -A throwaway crate (`cargo add sqlparser --features visitor`) run against the -same inputs as our `SqlAnalyzer`. Every row below was executed, not inferred. - -| Probe | `sqlparser` 0.62 | sqruff 0.39 (via `mehen-sql`) | -|---|---|---| -| §2.3 "gnarly" query (recursive CTE, window+frame, nested CASE, correlated subquery) | ✅ parses, 1 stmt, span `L1:1..L29:17` | ✅ parses, 0 unparsable | -| **Comments in tree** | ❌ **absent** — AST debug contains no comment text; `SELECT 1 AS x -- trailing` round-trips to `SELECT 1 AS x FROM t` | ✅ comment nodes with byte spans | -| Comments from tokenizer | ⚠️ 3 tokens as `Token::Whitespace(SingleLineComment/MultiLineComment)` with line:col — recoverable via a second pass | ✅ already tree-attached | -| **Error recovery** on `SELECT a FROM t; SELCT SELCT bogus ***; SELECT b FROM u;` | ❌ **hard `Err`, zero statements** — both valid statements lost | ✅ `Ok`: `loc.code=3`, `unparsable_segment_count=1`, `unparsable_ratio=0.67`, warning diagnostic | -| T-SQL `BEGIN TRY … END CATCH` | ❌ `Err` *even with* `MsSqlDialect` | ✅ 0 unparsable (with `-- sqlfluff:dialect:tsql`) | -| T-SQL `WHILE @i < 10 BEGIN … END` | ❌ `Err` with `MsSqlDialect` | ✅ 0 unparsable | -| PL/SQL `BEGIN IF x > 1 THEN NULL; END IF; END;` | ❌ `Err` with `OracleDialect` | ✅ 0 unparsable (with `:oracle`) | -| `CREATE PROCEDURE p AS BEGIN … END` | ❌ `Err` (both MsSql and Oracle) | ✅ 0 unparsable | -| QUALIFY · UNNEST · `$$…$$` · MERGE · GROUPING SETS · PIVOT | ✅ all OK on `GenericDialect` | ✅ all supported | -| `Send + Sync` tree | ✅ `Vec` is both | ❌ `Rc`-based `ErasedSegment` is neither | -| Transitive crates (`cargo tree --edges normal`, parser subtree only) | **13** | **40** | - -**Caveat on the procedural rows.** sqruff's advantage there is *conditional*: it -only materializes with an explicit dialect. Under inference all three fall back -to `ansi` and report `unparsable=1, ratio=1.00`. Since `requested_dialect()` in -`lib.rs` still returns `None`, the only way to set one today is an in-file -`-- sqlfluff:dialect:` directive. See §8.5. - -This result also **inverts §4.2's assumption** that procedural depth requires -the ANTLR `plsql`/`tsql` grammars: sqruff handles all four procedural probes -that `sqlparser` rejects outright. - -### 8.3 Where `sqlparser` genuinely wins - -1. **`Send + Sync` AST.** The one real architectural improvement. `facts.rs` - documents the current workaround in its module header — extract everything - into owned `SqlFileFacts` inside one `analyze()` call because the `Rc` tree - cannot cross threads. With `sqlparser` the adapter seam would be optional - rather than mandatory. -2. **Governance and API stability.** ASF-owned, on crates.io with semver, 3.3k - stars, 300 contributors, 66M all-time downloads, 323 reverse dependencies. - The README states the maintainers "do not plan for any substantial changes - to this crate's API." This directly addresses the §2.5 risk — sqruff is a - `0.x` internal crate of a linter app, git-tag pinned, with no semver promise - (cf. the duplicate-`Dialect` `E0308` breakage from ungrouped bumps). -3. **Lighter tree:** 13 vs 40 crates. No `fancy-regex`, `serde_yaml`, `strum`, - or `unsafe-libyaml`. -4. **Typed ergonomics.** A real `enum Statement` beats matching a 1087-variant - flat `SyntaxKind`. Our own code shows the cost of the latter: `facts.rs` - repeatedly falls back to raw-text sniffing (`stmt.raw().to_ascii_uppercase()`, - `seg.raw().eq_ignore_ascii_case("NOT")`, string-matching `"USING"`) where a - typed AST would offer field access. - -### 8.4 Where it loses - -- **Comments absent from the AST** (§8.1). Recoverable via - `tokenize_with_location()`, but that means a second tokenizer pass plus - re-deriving the trivia/code interleaving sqruff supplies directly. -- **No error recovery.** `parse_sql` returns `Result>`: one - syntax error anywhere yields nothing. For a tool pointed at whole repos this - is not an edge case — a single vendor-specific statement in a migration file - would zero out that file's metrics instead of degrading them. -- **Weaker procedural SQL,** contrary to expectation (§8.2). -- **Spans officially incomplete.** The `Spanned` docs state nodes "may be - missing span information entirely, in which case they return `Span::empty()`", - with per-type "partial span / Missing spans" annotations on `Expr`, - `JoinOperator`, `GroupByExpr`, `JoinConstraint` and more - ([issue #1548](https://github.com/apache/datafusion-sqlparser-rs/issues/1548)). - Simple projection and `WHERE` spans were correct in the probe, but the gaps - sit exactly where per-statement attribution needs them. -- **No analysis layer.** No CTE graph, scopes, `wildcard_info`, or lineage. - This costs less than §5 assumed, since `facts.rs` already re-derives the CTE - graph itself — but Phase-4 `sql.lineage.*` would lose sqruff's `lineage` - crate entirely. - -### 8.5 Recommendation - -**Keep sqruff.** A migration would rewrite `facts.rs`, `loc.rs`, and -`dialect.rs` against a tree carrying *less* information than the current one — -trading comment nodes, error recovery, and procedural coverage for -`Send + Sync`, a lighter tree, and ASF governance. All 142 metric keys and -every `insta` snapshot would need revalidation. The `SqlFileFacts` adapter seam -(§6) makes the swap mechanically possible, which is the seam working as -designed; it should stay unexercised. The two costs that would justify it — the -API-churn tax and the missing-`Send` friction — are each currently cheaper than -the rewrite. - -Two cheaper follow-ups, both parser-agnostic: - -1. **Wire up `requested_dialect()`** (`lib.rs`). sqruff's procedural advantage - only materializes with an explicit dialect, and there is no CLI flag to set - one. Highest-value SQL change currently available. -2. **Keep the sqruff Dependabot group aligned** so the two `sqruff-*` git tags - never drift apart. - -**Where `sqlparser` could still earn a place:** as an optional cross-check -oracle for `sql.dialect.confidence`. Parsing a file with both and comparing -statement counts is genuine signal — its permissive `GenericDialect` -disagreeing with sqruff's inferred dialect indicates low confidence. Additive, -no rewrite required. - -### 8.6 Addendum evidence log - -- Probe crate: `/tmp/sqlparser-probe` (`sqlparser` v0.62.0, `visitor` feature), - `rustc` 1.97.1. Covered: gnarly-query parse, comment presence in AST vs - tokenizer, error recovery, `Send + Sync` (compile-time assertion), inner-node - span quality, and a dialect syntax matrix over `Generic`/`MsSql`/`Oracle`/ - `Snowflake`. -- sqruff side: a temporary integration test in `crates/mehen-sql/tests/` - driving `SqlAnalyzer::analyze` on identical inputs (removed afterwards; - working tree left clean). -- Metric-key counts: `grep -oh '"sql\.[a-z_.]*"' crates/mehen-sql/src/*.rs` - → 142 distinct literal keys, of which 8 `sql.loc.*` and 4 `sql.parser.*` are - trivia/recovery-derived. Two families are built dynamically via `format!` - (`sql.dialect.is_`, `sql.statement.kind_count.
… - -> Generated by [mehen](https://github.com/ophi-dev/mehen) — the code quality watcher. -``` - -The section is **emitted only when at least one Markdown file is present in the PR diff**. On code-only -PRs the section is suppressed entirely. - -## Headline table — five columns - -| Column | Source | Why it's in the headline | -|---|---|---| -| **DMI** (0–100) | [Documentation Maintainability Index](/metrics/markdown/dmi) | Single overall maintainability score. | -| **Words** | [LOC family](/metrics/markdown/loc-family) (W) | Size sanity. | -| **FKGL** (English) or **Tateishi RS** (Japanese) | [English readability](/metrics/markdown/prose/english-readability) / [Tateishi RS](/metrics/markdown/prose/tateishi-and-jouyou) | Most recognizable readability number. | -| **Link Debt** (0–1) | [Link Debt](/metrics/markdown/link-debt) | Objective defects. | -| **Filler Risk** (0–1) | [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk) | AI-era flag for "big but vacuous". | - -[RCI](/metrics/markdown/review-criticality-index), [MCC](/metrics/markdown/mcc), -[MRPC](/metrics/markdown/mrpc), WQS, [Evidence Coverage](/metrics/markdown/evidence-coverage), and -[Repository Grounding](/metrics/markdown/repository-grounding) all matter but are second-glance signals. -They live in the `
` drill-down. - -For Japanese-dominant docs, the third column header flips to **Tateishi RS** and the value uses the -simplified formula. Mixed-language docs report the dominant-language score and tag the file with a 🌏 -suffix. - -## Cell format — four canonical shapes - -| Shape | Example | Meaning | -|---|---|---| -| `new (main: old) indicator` | `74 (main: 71) 🟢` | Modified file: before/after + delta category. | -| `value 🆕` | `58 🆕` | New file: no `main` baseline exists. | -| `value ⚪` | `0 ⚪` | Deleted metric or undefined for this file type. | -| `— footnote-mark` | `— ²` | Suppressed by guard. | - -Fixed precision per column: - -- DMI, RCI: integer. -- Words, sentence counts, diagram/table/link counts: integer with thousands separators. -- Ratios and scores (0–1): 2 decimal places. -- FKGL, Fog, ARI, Tateishi RS: 1 decimal place. - -## Delta indicators - -| Indicator | Rule | -|---|---| -| 🟢 improvement | Delta crosses a band boundary in the "better" direction, OR `\|delta\| ≥ noticeable_threshold` better. | -| 🔴 regression | Delta crosses a band boundary in the "worse" direction, OR `\|delta\| ≥ noticeable_threshold` worse. | -| ⚠️ attention | Value is in a "warn" or worse band AND did not improve. | -| 🆕 new | File is new in the PR. | -| ⚪ unchanged | None of the above. | - -**Per-metric noticeable thresholds:** - -| Metric | Direction | `noticeable_threshold` | -|---|---|---| -| DMI | ↑ better | 3 points | -| RCI | informational | never emits 🟢 / 🔴 by itself | -| FKGL | profile target | 0.5 grade | -| Tateishi RS | ↑ better | 2 points | -| Fog | profile target | 0.5 grade | -| Link Debt | ↓ better | 0.05 OR any new broken link | -| Filler Risk | ↓ better | 0.05; ⚠️ when ≥ 0.60 regardless of delta | -| Evidence Coverage | ↑ better | 0.05 | -| MCC | ↓ better | 5 points OR band crossing | -| MRPC | profile target | 3 points AND profile-exceeded | -| Passive ratio | profile target | 0.05 absolute | -| Long-sentence count | ↓ better | any new instance is 🔴 | -| Inclusive-language flags | ↓ better | any new flag is 🔴 | -| Repository Grounding | ↑ better | 0.05 | -| Jukugo / kanji-run warnings (JA) | profile target | any new violation is 🔴 | - -Word count never emits 🟢 or 🔴 — it is informational only. - -## Callout templates - -The callout block tells reviewers **what specifically to look at**, with exact document locations. -Every callout must come from the template catalog. No free-text generation is permitted. - -Callouts are ranked by severity class, then by magnitude within class. Default cap: **8 callouts**; -overflow goes into a `
` expander. - -### Severity 1 — objective defects - -| `rule_id` | Template | -|---|---| -| `broken_relative_link_added` | `🔴 **{file}** — {n} unresolved relative link(s) added: {s₁} ({L:N₁}){, s₂ (L:N₂)…}` | -| `broken_anchor_added` | `🔴 **{file}** — {n} unresolved internal anchor(s) added: …` | -| `broken_external_link_added` | `🔴 **{file}** — {n} broken external link(s) added (link-check enabled): …` | -| `diagram_parse_error_added` | `🔴 **{file}** — {lang} diagram parse error at {L:N}` | -| `inclusive_language_flag_added` | `🔴 **{file}** — {n} inclusive-language flag(s) added: …` | -| `nonword_added` | `🔴 **{file}** — non-word {s} at {L:N} (suggest: {replacement})` | -| `lexical_illusion_added` | `🔴 **{file}** — doubled word {s} at {L:N}` | - -### Severity 2 — band crossings - -| `rule_id` | Template | -|---|---| -| `filler_risk_high` | `⚠️ **{file}** — filler/lazy risk {new} ({band}); top contributors: {label₁} {v₁}, {label₂} {v₂}, {label₃} {v₃}` | -| `dmi_band_drop` | `🔴 **{file}** — DMI {old} → {new}, crossed {old_band} → {new_band}` | -| `evidence_band_drop` | `🔴 **{file}** — evidence coverage {old} → {new}, crossed {old_band} → {new_band}` | -| `repo_grounding_band_drop` | `🔴 **{file}** — repository grounding {old} → {new}, crossed {old_band} → {new_band}` | - -### Severity 3 — readability / wording - -| `rule_id` | Template | -|---|---| -| `long_sentences_added` | `🔴 **{file}** — {n} sentence(s) exceed {threshold} words (new): {L:N₁}{, L:N₂…}` | -| `readability_target_breach` | `🔴 **{file}** — {formula} {old} → {new}, above {profile} target {target}` | -| `tateishi_band_drop` | `🔴 **{file}** — Tateishi RS {old} → {new} (harder)` | -| `passive_ratio_breach` | `🔴 **{file}** — passive ratio {old} → {new}, above {profile} max {max}` | -| `heading_skip_added` | `🔴 **{file}** — heading skip {old_level} → {new_level} at {L:N}` | -| `table_burden_hard` | `⚠️ **{file}** — table at {L:N} has {cells} cells / {cols} columns / {rows} rows (hard warning)` | - -### Severity 4 — artifact hygiene - -| `rule_id` | Template | -|---|---| -| `code_fence_unlabeled_added` | `⚠️ **{file}** — unlabelled code fence at {L:N}` | -| `diagram_missing_caption_added` | `⚠️ **{file}** — {lang} diagram at {L:N} has no caption or nearby explanation` | -| `image_missing_alt_added` | `⚠️ **{file}** — image {s} at {L:N} has no alt text` | -| `artifact_unexplained_added` | `⚠️ **{file}** — {artifact_type} at {L:N} has no explanatory prose within ±2 blocks` | - -### Severity 5 — improvements - -| `rule_id` | Template | -|---|---| -| `dmi_band_improve` | `🟢 **{file}** — DMI {old} → {new}, crossed {old_band} → {new_band}` | -| `filler_risk_band_improve` | `🟢 **{file}** — filler/lazy risk {old} → {new}, crossed {old_band} → {new_band}` | -| `broken_links_resolved` | `🟢 **{file}** — {n} previously broken link(s) resolved` | -| `long_sentences_resolved` | `🟢 **{file}** — {n} sentence(s) previously over {threshold} words now under` | -| `readability_target_recovered` | `🟢 **{file}** — {formula} {old} → {new}, now within {profile} target {target}` | - -### Severity 6 — new file summary - -| `rule_id` | Template | -|---|---| -| `new_file_summary` | `🆕 **{file}** — {words} words, {headings} headings, {code_fences} code fence(s), {diagrams} diagram(s), {tables} table(s); DMI {dmi}, filler risk {filler} ({band})` | - -## Permitted and forbidden language - -The callout grammar is deliberately thin. - -**Permitted verbs and connectors:** `added`, `resolved`, `exceed`, `crossed`, `above`, `below`, `has`, -`missing`, `unresolved`, `broken`, `previously`, `now`, `within`, `no caption`, `no alt text`, `→`, `;`, -`,`, `(`, `)`. - -**Forbidden:** `after`, `because`, `due to`, `caused by`, `following`, `since`, `likely`, `probably`, -`appears to`, `seems`, `may indicate`, `suggests`, `possibly`. Anything that implies causation or -intent about the author's edits. - -This rule is the hard line between "CI metrics report" and "automated review feedback that -over-reaches". - -## Drill-down tables - -Below the callouts, a collapsed `
` block holds deeper tables for reviewers who want them. - -```markdown -
-Full metric breakdown (structural · wording · lexical · readability) -``` - -Inside, four tables in this order: - -1. **Structural / review** — RCI, MCC, MRPC, Evidence Coverage, Repository Grounding. -2. **English wording quality** (suppressed if no English file) — WQS, passive %, hedges/100w, - long-sentence count, nominalization density. -3. **English lexical & readability ensemble** — MATTR₅₀, hapax ratio, Fog, SMOG, ARI, Coleman-Liau. -4. **Japanese composition & register** (suppressed if no Japanese file) — kanji %, hiragana %, - katakana %, avg sentence chars, comma/period ratio, politeness dominant. - -## Reference mock - -Canonical shape for a PR that modifies one `README.md`, adds one architecture doc, regresses one API -reference, leaves one generated file unchanged but on-alert, and touches the changelog: - -```markdown - -## Documentation Metrics (this PR vs `main`) - -| File | DMI | Words | FKGL | Link Debt | Filler Risk | -|---|---:|---:|---:|---:|---:| -| [README.md](…) | 74 (main: 71) 🟢 | 1,240 (main: 1,180) ⚪ | 9.4 (main: 10.1) 🟢 | 0.08 (main: 0.12) 🟢 | 0.15 (main: 0.18) 🟢 | -| [docs/architecture/runtime.md](…) | 58 🆕 | 2,840 🆕 | 11.8 🆕 | 0.04 🆕 | 0.09 🆕 | -| [docs/api/auth.md](…) | 62 (main: 68) 🔴 | 1,670 (main: 1,540) ⚪ | 12.1 (main: 11.6) 🔴 | 0.22 (main: 0.15) 🔴 | 0.14 (main: 0.12) ⚪ | - -**Callouts** - -- 🔴 **docs/api/auth.md** — 2 unresolved relative link(s) added: `../../guide/sessions.md` (L47), `./tokens.md#refresh` (L112) -- 🔴 **docs/api/auth.md** — 3 sentence(s) exceed 35 words (new): L83, L104, L156 -- 🔴 **docs/api/auth.md** — FKGL 11.6 → 12.1, above API-reference target 12.0 -- ⚠️ **docs/architecture/runtime.md** — mermaid diagram at L171 has no caption or nearby explanation -- 🟢 **README.md** — DMI 71 → 74 (within "Good"); FKGL 10.1 → 9.4 (≥ 0.5 grade improvement) - -> Legend: 🟢 improvement · 🔴 regression · ⚠️ attention · 🆕 new file · ⚪ no material change - -> Generated by [mehen](https://github.com/ophi-dev/mehen) — the code quality watcher. -``` - -## What is deliberately NOT in scope - -- **No causal explanations.** The report never says "after X", "because of Y", "due to Z". -- **No author-intent inference.** Never speculates about what the author "meant" or "should have done". -- **No LLM summaries.** Not now, not behind a flag, not as a plugin. -- **No trend lines or history.** Per-metric trendlines deserve a separate design pass. -- **No suggested edits.** Belongs in a separate `mehen doc lint` command. -- **No scoring gates by default.** The PR comment is advisory. Gating requires explicit `--fail-on`. - -## `--fail-on` gating - -The PR comment is advisory by default. To turn documentation regressions into a CI failure, pass -[`mehen diff --fail-on`](/commands/diff) with one or more band-crossing rule IDs — `dmi-drop`, -`new-broken-link`, `filler-high`, or `all` — which exit non-zero (code `2`) when crossed. These align -with the severity-1 / severity-2 callouts above. See -[Concepts → Thresholds and diffs](/concepts/thresholds-and-diffs) for the source-code threshold path. - -## See also - -- [GitHub Action](/guides/github-action) — runs the diff and posts the comment. -- [Markdown metrics overview](/metrics/markdown/overview) — definitions referenced from callouts. diff --git a/docs/images/pr-comment-metrics.png b/docs/images/pr-comment-metrics.png deleted file mode 100644 index f6d63017..00000000 Binary files a/docs/images/pr-comment-metrics.png and /dev/null differ diff --git a/docs/index.mdx b/docs/index.mdx deleted file mode 100644 index b6b566ff..00000000 --- a/docs/index.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: "mehen — code & documentation metrics" -description: "Rust-powered CLI for heuristic code and documentation metrics: complexity, maintainability, lines of code, and Markdown documentation health." -keywords: ["mehen", "code metrics", "documentation metrics", "complexity", "maintainability"] ---- - -**mehen** is a fast, deterministic CLI for code and documentation metrics. It analyzes eleven source -languages plus SQL and Markdown, runs in seconds even on large monorepos, and ships a GitHub Action -that publishes per-PR metric trends out of the box. - -```bash -mehen metrics src/main.py --pretty -mehen top-offenders src --metric cognitive -mehen diff --from main --to HEAD --paths src -``` - - - - Run mehen against your project in under a minute. - - - Add the action and start posting metric trends on PRs. - - - Cyclomatic, cognitive, Halstead, MI, ABC, LOC family, NOM, NPA, NPM, WMC. - - - CTE graphs, join/subquery structure, object-touch risk, SQL Halstead, composite scores. - - - DMI, MRPC, MCC, link debt, filler/lazy risk, English/Japanese prose layer. - - - Churn, code age, ownership, hotspots, change coupling, bug risk — from git history. - - - -## Why mehen? - - - - Ruff for Python, Oxc for TS/JS/JSX/TSX, Mago for PHP, Prism for Ruby, ra_ap_syntax for Rust, - ANTLR for Kotlin, Java, and C#, sqruff for SQL, pulldown-cmark for Markdown, tree-sitter for Go, C, - PowerShell. - - - One tool covers source-code complexity, first-class SQL structure metrics, *and* Markdown - documentation health. - - - Pure static analysis. Same input → same output. Safe for air-gapped CI. - - - Built-in `mehen diff` with sticky GitHub comment via the official action. - - - -## What mehen computes - -For source code: - -- [Cyclomatic complexity](/metrics/code/cyclomatic), [Cognitive complexity](/metrics/code/cognitive), - [Halstead metrics](/metrics/code/halstead), [Maintainability Index](/metrics/code/mi), - [ABC](/metrics/code/abc). -- [Function & class shape](/metrics/code/overview): [NOM](/metrics/code/nom), [NARGS](/metrics/code/nargs), - [NEXITS](/metrics/code/nexits), [NPA](/metrics/code/npa), [NPM](/metrics/code/npm), - [WMC](/metrics/code/wmc). -- The [LOC family](/metrics/code/loc): SLOC, PLOC, LLOC, CLOC, blanks. - -For SQL: - -- [Structural and cognitive complexity](/metrics/sql/overview) from CTE, join, subquery, `CASE`, and - window structure; a [Review Burden Index](/metrics/sql/overview) and [Change Risk - Score](/metrics/sql/overview); an [SQL Halstead](/metrics/sql/overview) and maintainability index. - -For Markdown documentation: - -- [Documentation Maintainability Index (DMI)](/metrics/markdown/dmi). -- [Markdown Reading Path Complexity (MRPC)](/metrics/markdown/mrpc), - [Markdown Cognitive Complexity (MCC)](/metrics/markdown/mcc), - [Markdown Halstead](/metrics/markdown/halstead). -- [Link Debt](/metrics/markdown/link-debt), [Table Burden](/metrics/markdown/table-burden), - [Visual Scaffold](/metrics/markdown/visual-scaffold), [Artifact Debt](/metrics/markdown/artifact-debt). -- [Repository Grounding](/metrics/markdown/repository-grounding), - [Evidence Coverage](/metrics/markdown/evidence-coverage), - [Filler / Lazy Structure Risk](/metrics/markdown/filler-lazy-risk), - [Review Criticality Index](/metrics/markdown/review-criticality-index). -- An opt-in [English readability ensemble](/metrics/markdown/prose/english-readability) and - [Japanese prose layer](/metrics/markdown/prose/japanese-script-composition). - -From git history: - -- [Churn](/metrics/history/churn) (absolute and size-relative), [code age](/metrics/history/age), - [commit frequency](/metrics/history/commit-frequency). -- [Ownership & authorship](/metrics/history/ownership): distinct authors, minor contributors, - top-contributor share. -- [Hotspot](/metrics/history/hotspot) (cognitive complexity × commit frequency), - [sum of coupling](/metrics/history/sum-of-coupling), and - [bug risk](/metrics/history/bug-risk) (bug-fix count and Time-Weighted Risk). - -## What is Mehen? - -In Ophidiarium projects, names matter. **Mehen** is a mythical ancient Egyptian serpent associated -with guarding Ra. In the same spirit, the `mehen` CLI helps guard your codebase and documentation from -slowly collapsing under complexity. diff --git a/docs/installation.mdx b/docs/installation.mdx deleted file mode 100644 index af4333f0..00000000 --- a/docs/installation.mdx +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: "Installation" -description: "Install mehen via npm, PyPI, or cargo binstall. Native binaries are published for Linux, macOS, and Windows on every release." -keywords: ["mehen install", "npm", "pypi", "cargo binstall", "homebrew"] ---- - -mehen ships native binaries from a single GitHub Release. Pick the toolchain you already have — all three -paths download the same binaries. - -## npm (Node.js) - - - - ```bash - npm install -g mehen - ``` - - - ```bash - npm install --save-dev mehen - ``` - - - ```bash - npx -y mehen --help - bunx mehen --help - ``` - - - -`mehen` requires Node.js 18 or newer. The correct platform-specific binary is selected automatically at -install time via npm's `optionalDependencies`. - -## PyPI (Python / uv) - - - - ```bash - uv tool install mehen - # or run without installing - uv tool run mehen --help - uvx mehen --help - ``` - - - ```bash - pip install mehen - ``` - - - -The PyPI distribution is built with [maturin](https://maturin.rs) and ships the same Rust binary inside the -wheel — there is no Python runtime cost. - -## cargo binstall (Rust) - -If you have a Rust toolchain, [`cargo binstall`](https://github.com/cargo-bins/cargo-binstall) downloads -the pre-built binary from the GitHub Release directly — much faster than `cargo install`, which would build -from source. - -```bash -cargo binstall --git https://github.com/ophi-dev/mehen mehen -``` - -## Build from source - -```bash -git clone https://github.com/ophi-dev/mehen.git -cd mehen -cargo build --release -./target/release/mehen --help -``` - -See the [developers guide](/developers/overview) for prerequisites and validation commands. - -## Supported platforms - -mehen runs on the most common platforms. Native binaries are published for: - -| OS | x64 | arm64 | -|---|---|---| -| Linux (glibc) | `@mehen/linux-x64-gnu` | `@mehen/linux-arm64-gnu` | -| Linux (musl) | `@mehen/linux-x64-musl` | `@mehen/linux-arm64-musl` | -| macOS | `@mehen/darwin-x64` | `@mehen/darwin-arm64` | -| Windows | `@mehen/win32-x64` | `@mehen/win32-arm64` | - -The same archives are attached to each -[GitHub Release](https://github.com/ophi-dev/mehen/releases) and are what `cargo binstall` consumes. - -## Verify the install - -```bash -mehen --help -mehen --version -``` - - -On macOS you may need to allow the binary the first time it runs. Either remove the quarantine attribute -(`xattr -d com.apple.quarantine $(which mehen)`) or run mehen via your shell once and accept the dialog. - diff --git a/docs/introduction.mdx b/docs/introduction.mdx deleted file mode 100644 index 30e55c90..00000000 --- a/docs/introduction.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: "Introduction" -description: "mehen is a Rust-powered CLI for heuristic source code metrics — complexity, maintainability, lines of code, documentation health — at scale." -keywords: ["mehen", "code metrics", "complexity", "maintainability", "halstead", "documentation metrics", "markdown"] ---- - -**mehen** is a fast, deterministic command-line tool that measures source code, SQL, and Markdown -documentation across a repository. It tracks complexity, maintainability, size, and documentation -health, and is purpose-built for CI runs, pre-PR hooks, and pull request automation. - -```bash -mehen metrics src/main.py --pretty -mehen metrics migrations/0007_add_orders.sql --pretty -mehen top-offenders src --metric cognitive -mehen diff --from main --to HEAD --paths src --output-format markdown -``` - - - - Install via npm, PyPI, or `cargo binstall` from a single GitHub Release. - - - Analyze a file, rank a tree, and diff a PR in under a minute. - - - Drop the action into a workflow to publish per-PR metric trends. - - - Cyclomatic, cognitive, Halstead, MI, ABC, LOC family, NOM/NPA/NPM/WMC. - - - DMI, MRPC, MCC, Halstead-md, link debt, filler/lazy risk, prose layer. - - - CTE graphs, join/subquery structure, object-touch risk, SQL Halstead, composite scores. - - - Churn, code age, ownership, hotspots, change coupling, bug risk — from git history. - - - -## What is Mehen? - -**Mehen** is a mythical ancient Egyptian serpent associated with guarding Ra. In the same spirit, the -`mehen` CLI helps guard your codebase and documentation from collapsing under hidden complexity. - -## Why teams use mehen - - - - Per-file language detection across eleven source languages plus Markdown and SQL — built for monorepos. - - - Each language uses the best available parser: Ruff for Python, Oxc for TS/JS/JSX/TSX, Mago for - PHP, Prism for Ruby, ra_ap_syntax for Rust, ANTLR for Kotlin, Java, and C#, sqruff for SQL, - pulldown-cmark for Markdown, tree-sitter for Go, C, PowerShell. - - - A dedicated SQL analyzer scores CTE graphs, join structure, object-touch risk, and review burden - — dataflow complexity that imperative-only tools cannot see. See [SQL metrics](/metrics/sql/overview). - - - Pure static analysis. Same input → same output. Safe for air-gapped CI. - - - A single tool covers source-code complexity, SQL structure, *and* Markdown documentation health. - - - Built-in `mehen diff` plus a sticky comment GitHub Action — no glue code required. - - - Console, JSON, YAML, TOML, GitHub-flavored Markdown. - - - -## First-class SQL analysis - -SQL is where mehen does something most metric tools do not. Commercial code-quality platforms -routinely treat `.sql` files as opaque text — or charge for a SQL add-on that still only counts lines -— because their models are built around imperative control flow. A declarative `SELECT` with ten -joins and five CTEs has almost no branches, so a cyclomatic-only tool reports it as "simple" while -reviewers know it is anything but. - -mehen ships a dedicated [`mehen-sql` analyzer](/metrics/sql/overview) (backed by the dialect-aware -[sqruff](https://github.com/quarylabs/sqruff) parser) that measures the complexity mechanism SQL -actually has — **relational and dataflow structure**: - -- **[CTE dependency graphs](/metrics/sql/overview)** — depth, fan-out, recursion, and unused CTEs. -- **[Join and subquery structure](/metrics/sql/overview)** — outer/cross/non-equi joins, correlated - subqueries, missing join conditions. -- **[Object-touch and change risk](/metrics/sql/overview)** — `DROP`, `TRUNCATE`, `UPDATE`/`DELETE` - without a `WHERE`, and other migration-script hazards. -- **[SQL Halstead](/metrics/sql/overview)** and six explainable composite scores, including a - file-level **review-burden index** and **change-risk score**. - -Dialect is inferred from syntax with a reported confidence (or pinned with a `-- sqlfluff:dialect:…` -directive) across postgres, T-SQL, snowflake, bigquery, and more. SQL files are picked up -automatically — including on pull requests, where the [GitHub Action](/guides/github-action) surfaces -SQL deltas in the same sticky comment as your source-code metrics. - -## What mehen computes - -For source code: - -- **[Cyclomatic complexity](/metrics/code/cyclomatic)** and **[Cognitive complexity](/metrics/code/cognitive)** -- **[Halstead metrics](/metrics/code/halstead)** (volume, difficulty, effort, estimated bugs) -- **[Maintainability Index](/metrics/code/mi)** (Original, Visual Studio, SEI variants) -- **[ABC](/metrics/code/abc)** (Assignments / Branches / Conditions) -- **[NOM](/metrics/code/nom)**, **[NARGS](/metrics/code/nargs)**, **[NEXITS](/metrics/code/nexits)**, **[NPA](/metrics/code/npa)**, **[NPM](/metrics/code/npm)**, **[WMC](/metrics/code/wmc)** -- **[LOC family](/metrics/code/loc)** — SLOC, PLOC, LLOC, CLOC, blanks - -For Markdown documentation: - -- **[Documentation Maintainability Index (DMI)](/metrics/markdown/dmi)** -- **[Markdown Reading Path Complexity (MRPC)](/metrics/markdown/mrpc)** -- **[Markdown Cognitive Complexity (MCC)](/metrics/markdown/mcc)** -- **[Markdown Halstead](/metrics/markdown/halstead)** -- **[Link Debt](/metrics/markdown/link-debt)**, **[Table Burden](/metrics/markdown/table-burden)**, - **[Visual Scaffold](/metrics/markdown/visual-scaffold)**, **[Artifact Debt](/metrics/markdown/artifact-debt)** -- **[Repository Grounding](/metrics/markdown/repository-grounding)**, **[Evidence Coverage](/metrics/markdown/evidence-coverage)** -- **[Filler / Lazy Structure Risk](/metrics/markdown/filler-lazy-risk)**, **[Review Criticality Index](/metrics/markdown/review-criticality-index)** -- An opt-in [English readability ensemble](/metrics/markdown/prose/english-readability) and - [Japanese script composition](/metrics/markdown/prose/japanese-script-composition) prose layer. - -For SQL: - -- **[Structural and cognitive complexity](/metrics/sql/overview)** derived from CTE, join, subquery, - `CASE`, and window structure. -- **[Review Burden Index](/metrics/sql/overview)** and **[Change Risk Score](/metrics/sql/overview)** - — file-level 0–100 ranks for PR effort and migration risk. -- **[SQL Maintainability Index](/metrics/sql/overview)**, **modularity health**, and an - **[SQL Halstead](/metrics/sql/overview)** family. - -## Get started - - - - Pick the path that matches your toolchain: - - - - ```bash - npm install -g mehen - ``` - - - ```bash - uv tool install mehen - # or: pip install mehen - ``` - - - ```bash - cargo binstall --git https://github.com/ophi-dev/mehen mehen - ``` - - - - - ```bash - mehen metrics src/main.py --pretty - ``` - - - Publish per-PR metric trends with a few lines of YAML. - See the [GitHub Action guide](/guides/github-action). - - diff --git a/docs/logo/dark.svg b/docs/logo/dark.svg deleted file mode 100644 index b85cd44b..00000000 --- a/docs/logo/dark.svg +++ /dev/null @@ -1,6 +0,0 @@ - - mehen - - - diff --git a/docs/logo/light.svg b/docs/logo/light.svg deleted file mode 100644 index 93465c0c..00000000 --- a/docs/logo/light.svg +++ /dev/null @@ -1,6 +0,0 @@ - - mehen - - - diff --git a/docs/metrics/code/abc.mdx b/docs/metrics/code/abc.mdx deleted file mode 100644 index 25acdbb0..00000000 --- a/docs/metrics/code/abc.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: "ABC metric" -description: "Fitzpatrick's ABC count: Assignments, Branches, Conditions, with a magnitude that combines all three." -keywords: ["abc", "assignments", "branches", "conditions", "fitzpatrick"] ---- - -The **ABC** metric is a size measure proposed by Jerry Fitzpatrick in 1997. It counts three types of -syntactic features and reports them as a vector and as a magnitude. - -| Letter | What it counts | -|---|---| -| **A**ssignments | Variable assignments (`=`, `+=`, `−=`, `++`, `−−`, etc.). | -| **B**ranches | Calls to other procedures (i.e., method/function invocations). | -| **C**onditions | Conditional tests (`if`, `case`, `when`, ternary, exception catches, comparison -operators). | - -The vector `` is reported alongside the **magnitude** `|ABC| = sqrt(A² + B² + C²)`. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `abc` | float | Magnitude `sqrt(A² + B² + C²)`. | -| `abc.assignments` | int | Total assignments in the space. | -| `abc.assignments_min` | int | Minimum across child spaces. | -| `abc.assignments_max` | int | Maximum across child spaces. | -| `abc.assignments_average` | float | Average across child spaces. | -| `abc.branches` | int | Total branches. | -| `abc.branches_min` / `_max` / `_average` | — | Aggregates. | -| `abc.conditions` | int | Total conditions. | -| `abc.conditions_min` / `_max` / `_average` | — | Aggregates. | - -## How to read it - -There is no universal threshold, but Fitzpatrick's original paper proposed: - -| Magnitude | Interpretation | -|---|---| -| 0–10 | Tiny method; check whether it should be inlined. | -| 10–20 | Normal method size. | -| 20–40 | Large; consider refactoring. | -| 40+ | Very large; refactor candidate. | - -The Ruby community adopted ABC widely via `rubocop-rubycop`/`rubycritic`, which uses -`` and a magnitude threshold of 17 by default for methods. - -## Per-language increments - -Each language analyzer maps its statement and expression node kinds onto the three buckets. The -canonical mapping: - -- **Assignments:** `=`, `+=`, `−=`, `*=`, `/=`, `%=`, `<<=`, `>>=`, `&=`, `|=`, `^=`, prefix/postfix - `++`/`−−`, parameter default values where applicable. -- **Branches:** function calls, method calls, constructors, `super(...)` calls, and dynamic dispatch. -- **Conditions:** `if`, `else if`, `case`/`when`, ternary, `&&` / `||`, equality and ordering operators, - exception handlers (`catch`, `rescue`, `except`). - -## References - -- Fitzpatrick, J. (1997). *Applying the ABC Metric to C, C++, and Java.* C++ Report, June 1997. - [Author archive (PDF)](https://www.softwarerenovation.com/Articles/ABC-Metric-paper.pdf). -- RuboCop: [`Metrics/AbcSize` cop documentation](https://docs.rubocop.org/rubocop/cops_metrics.html#metricsabcsize) - — production-grade Ruby implementation with documented thresholds. - -## See also - -- [Cyclomatic complexity](/metrics/code/cyclomatic) — counts branches/conditions differently. -- [LOC family](/metrics/code/loc) — orthogonal size measure. diff --git a/docs/metrics/code/blank.mdx b/docs/metrics/code/blank.mdx deleted file mode 100644 index e0e4d00e..00000000 --- a/docs/metrics/code/blank.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Blank lines" -description: "Whitespace-only lines." -keywords: ["blank lines", "whitespace", "loc"] ---- - -**Blank** lines are whitespace-only physical lines — no code, no comment. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `loc.blank` | int | Whitespace-only lines. | - -## How it is computed - -A line counts toward `loc.blank` when its full physical text is empty or whitespace-only. Lines that -contain only a comment do not count as blank — they count toward [CLOC](/metrics/code/cloc). - -## When it is useful - -- **Whitespace ratio** — a high blank-line ratio sometimes indicates excessive vertical separation, often - in generated code. -- **Identity check** — `sloc == ploc + cloc + blank` should hold (within the rules of how mixed lines are - attributed). If it doesn't, that's a parser bug. - -## References - -- Park, R. E. (1992). *Software Size Measurement: A Framework for Counting Source Statements.* - CMU/SEI-92-TR-20. - [SEI report](https://insights.sei.cmu.edu/library/software-size-measurement-a-framework-for-counting-source-statements/). - -## See also - -- [LOC family](/metrics/code/loc) — overview. -- [SLOC](/metrics/code/sloc), [PLOC](/metrics/code/ploc), [CLOC](/metrics/code/cloc). diff --git a/docs/metrics/code/cloc.mdx b/docs/metrics/code/cloc.mdx deleted file mode 100644 index da8487d4..00000000 --- a/docs/metrics/code/cloc.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: "CLOC — Comment Lines of Code" -description: "Comment lines: line, block, and documentation comments." -keywords: ["cloc", "comments", "comment density"] ---- - -**CLOC** (Comment Lines of Code) counts lines that contain at least one comment token. Mehen does not -distinguish line, block, or doc comments in the headline metric — they all contribute one line per -physical line they occupy. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `loc.cloc` | int | Comment lines (line + block + doc comments). | - -## How it is computed - -A line counts toward CLOC when the parser reports at least one comment trivia token on it. -A pure comment line (e.g., a `//` line in Rust or a `#` line in Python) counts once. Mixed lines (code -followed by an inline comment) count toward both [PLOC](/metrics/code/ploc) and CLOC. - -## When it is useful - -- **Comment density** — `cloc / (cloc + ploc)` is a coarse proxy for documentation effort. -- **Generated code detection** — heavily generated files often have unusually low or unusually high - comment density. -- **Maintainability** — the [Maintainability Index](/metrics/code/mi) `mi.original` variant uses comment - count as one of its inputs. - - -A high CLOC is **not** automatically a good thing. Stale, copy-pasted, or boilerplate comments hurt -maintainability. Read CLOC alongside [Cognitive complexity](/metrics/code/cognitive) — clear code with -few comments often beats opaque code with many. - - -## References - -- Park, R. E. (1992). *Software Size Measurement: A Framework for Counting Source Statements.* - CMU/SEI-92-TR-20 — comment-line conventions. - [SEI report](https://insights.sei.cmu.edu/library/software-size-measurement-a-framework-for-counting-source-statements/). -- Sonar: [`comment_lines` and `comment_lines_density`](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [LOC family](/metrics/code/loc) — overview. -- [PLOC](/metrics/code/ploc) — physical instruction lines. -- [Maintainability Index](/metrics/code/mi) — uses comment counts. diff --git a/docs/metrics/code/cognitive.mdx b/docs/metrics/code/cognitive.mdx deleted file mode 100644 index 598f8c18..00000000 --- a/docs/metrics/code/cognitive.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: "Cognitive complexity" -description: "How difficult code is to understand, weighted by nesting and control-flow breaks." -keywords: ["cognitive complexity", "sonar", "readability", "complexity"] ---- - -**Cognitive complexity** measures how difficult code is to understand. Unlike -[cyclomatic complexity](/metrics/code/cyclomatic), which measures paths through the control-flow graph, -cognitive complexity penalizes constructs that disrupt the linear flow of reading and rewards constructs -that aid comprehension. - -The metric was introduced by SonarSource in 2018 explicitly to address shortcomings of cyclomatic -complexity. It applies three rules: - -1. Ignore structures that allow multiple statements to be readably shorthanded into one. -2. Increment for break in linear flow (`if`, `else`, ternary, `switch`, loop, `catch`, `goto`, recursion, - `&&`/`||` chains). -3. Increment for nested flow-breaking structures, with the increment proportional to the nesting depth. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `cognitive` | int | Cognitive complexity for the space. | -| `cognitive.sum` | int | Sum across child spaces. | -| `cognitive.average` | float | Mean across functions. | -| `cognitive.min` | int | Minimum across functions. | -| `cognitive.max` | int | Maximum across functions. | - -## How it differs from cyclomatic - -```python -# Cyclomatic: 4 (one + for each of the four boolean operators) -# Cognitive: 3 (1 for the if, +2 for the &&/|| mix; no nesting increment for a top-level if) -def is_eligible(user): - if user and (user.is_active or user.is_admin) and not user.is_banned: - return True - return False -``` - -```python -# Cyclomatic: 4 (one + for the three branches) -# Cognitive: 6 (1 + 2 + 3 because each nested branch costs nesting depth) -def deep(x): - if x > 0: - if x < 100: - if x % 2 == 0: - return True - return False -``` - -## Per-language increments - -mehen mirrors Sonar's specification closely. Each language analyzer contributes: - -- **+1** for each control-flow break: `if`, `else if`, `else`, ternary, `switch` (Sonar counts the - `switch` itself, not each `case`), loop, `catch`, `goto`, recursive call, etc. -- **+1 per nesting level** of the construct relative to its enclosing function. -- **+1** for each *change* in a sequence of `&&` / `||` operators (chains of the same operator do not - re-charge). - -## How to read it - -| Value | Interpretation | -|---|---| -| 0–5 | Easy to read. | -| 6–10 | Moderate; usually fine. | -| 11–15 | Hard; consider extracting helpers. | -| 16+ | Likely a refactor candidate — readers will get lost. | - -## References - -- Campbell, G. A. (2018). *Cognitive Complexity — A new way of measuring understandability.* - SonarSource white paper. [PDF](https://www.sonarsource.com/resources/cognitive-complexity/). -- Muñoz Barón, M., Wyrich, M. & Wagner, S. (2020). *An empirical validation of cognitive complexity - as a measure of source code understandability.* ESEM 2020. - [arXiv:2007.12520](https://arxiv.org/abs/2007.12520). -- Sonar: [Cognitive complexity in metric definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [Cyclomatic complexity](/metrics/code/cyclomatic) — paths through the CFG. -- [Halstead metrics](/metrics/code/halstead) — vocabulary-based complexity. -- [Maintainability Index](/metrics/code/mi) — composite that blends cyclomatic + Halstead + LOC. diff --git a/docs/metrics/code/cyclomatic.mdx b/docs/metrics/code/cyclomatic.mdx deleted file mode 100644 index 092f58c7..00000000 --- a/docs/metrics/code/cyclomatic.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: "Cyclomatic complexity" -description: "McCabe's count of linearly independent paths through a function." -keywords: ["cyclomatic complexity", "mccabe", "control flow", "complexity"] ---- - -**Cyclomatic complexity** is McCabe's count of the number of linearly independent paths through a -function's control-flow graph. A function with no branches has complexity 1. Each `if`, `for`, `while`, -`case`, boolean `&&` / `||`, ternary, or exception handler increments the count. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `cyclomatic` | int | Total cyclomatic complexity for the space (function/method/file). | -| `cyclomatic.sum` | int | Sum across child spaces. | -| `cyclomatic.average` | float | Mean across functions. | -| `cyclomatic.min` | int | Minimum across functions. | -| `cyclomatic.max` | int | Maximum across functions. | - -## Formula - -```text -CC = E − N + 2P -``` - -For a connected control-flow graph with `E` edges, `N` nodes, and `P` connected components. -In practice, mehen counts decisions plus 1: - -```text -CC = 1 + decisions -``` - -where decisions are language-specific. Each language analyzer contributes increments for `if`, `else if`, -loops, switch arms, `&&` / `||`, ternary expressions, exception handlers, and other control-flow -constructs. - -## Per-language increments - -The exact set of node kinds that increment complexity is owned by each language analyzer crate. The list -matches McCabe's original prescription closely: - -- **Branches:** `if`, `else if`, `case`/`when` arms. -- **Loops:** `for`, `while`, `do`, `loop`, `until`. -- **Boolean operators:** `&&`, `||` (each occurrence). -- **Ternary / conditional expression:** the `?:` operator. -- **Exception handlers:** `catch`, `rescue`, `except`. -- **Early returns:** counted in [NEXITS](/metrics/code/nexits), not cyclomatic. - -## How to read it - -| Value | Interpretation | -|---|---| -| 1–4 | Simple, low risk. | -| 5–10 | Moderate, well within McCabe's recommended ceiling. | -| 11–20 | Complex; refactor candidate. | -| 21+ | Untestable in practice — split into smaller functions. | - -McCabe's original 1976 paper recommended **10 as the upper limit per function**, with rare exceptions for -state machines. - - -Cyclomatic complexity counts paths, not understanding. A long chain of `else if` arms might score 8 but -read clearly. A nested ternary scoring 4 might be near-impossible to follow. Pair this metric with -[Cognitive complexity](/metrics/code/cognitive). - - -## References - -- McCabe, T. J. (1976). *A Complexity Measure*. IEEE Transactions on Software Engineering, SE-2(4): - 308–320. [DOI](https://doi.org/10.1109/TSE.1976.233837) · - [PDF (literateprogramming.com archive)](http://www.literateprogramming.com/mccabe.pdf). -- Kearney, J. K., et al. *Software Complexity Measurement* — MIT lecture notes covering McCabe and - Halstead together. [PDF (MIT OCW 16.355)](http://sunnyday.mit.edu/16.355/kearney.pdf). -- Watson, A. H. & McCabe, T. J. (1996). *Structured Testing: A Testing Methodology Using the - Cyclomatic Complexity Metric.* NIST Special Publication 500-235. - [NIST PDF](https://www.nist.gov/publications/structured-testing-testing-methodology-using-cyclomatic-complexity-metric). -- Sonar: [Cyclomatic complexity](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [Cognitive complexity](/metrics/code/cognitive) — Sonar's "how hard to understand" complement. -- [Weighted Methods per Class (WMC)](/metrics/code/wmc) — sum of cyclomatic across class methods. diff --git a/docs/metrics/code/halstead.mdx b/docs/metrics/code/halstead.mdx deleted file mode 100644 index b41f85b6..00000000 --- a/docs/metrics/code/halstead.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: "Halstead metrics" -description: "Maurice Halstead's vocabulary-based suite — volume, difficulty, effort, bugs, and time." -keywords: ["halstead", "volume", "difficulty", "effort", "bugs", "complexity"] ---- - -The **Halstead metrics** are a suite of measures derived purely from the operators and operands in a -source file. Maurice Halstead proposed them in *Elements of Software Science* (1977) as a way to -characterize program size, difficulty, effort, and bug count from token statistics alone — without -running the code. - -mehen reports the canonical Halstead suite per space and per file. - -## What mehen emits - -| Key | Type | Definition | -|---|---|---| -| `halstead` | float | Default surface; equals `halstead.volume`. | -| `halstead.volume` | float | `V = N · log₂(η)` | -| `halstead.difficulty` | float | `D = (η₁ / 2) · (N₂ / η₂)` | -| `halstead.effort` | float | `E = D · V` | -| `halstead.vocabulary` | int | `η = η₁ + η₂` | -| `halstead.length` | int | `N = N₁ + N₂` | -| `halstead.n1` | int | Distinct operators. | -| `halstead.N1` | int | Total operators. | -| `halstead.n2` | int | Distinct operands. | -| `halstead.N2` | int | Total operands. | -| `halstead.bugs` | float | `B = V / 3000` (estimated delivered bugs). | -| `halstead.time` | float | `T = E / 18` (estimated implementation time, seconds). | -| `halstead.estimated_program_length` | float | `Ñ = η₁ · log₂(η₁) + η₂ · log₂(η₂)` | -| `halstead.level` | float | `L = 1 / D` | -| `halstead.purity_ratio` | float | `Ñ / N` | - -## Definitions - -| Term | Meaning | -|---|---| -| η₁ | Number of **distinct** operators in the program. | -| η₂ | Number of **distinct** operands. | -| N₁ | Total occurrences of operators. | -| N₂ | Total occurrences of operands. | - -The classical Halstead derived quantities follow: - -```text -η = η₁ + η₂ (vocabulary) -N = N₁ + N₂ (length) -V = N · log₂(η) (volume) -D = (η₁ / 2) · (N₂ / η₂) (difficulty) -E = D · V (effort) -B = V / 3000 (estimated bugs) -T = E / 18 (estimated implementation time) -``` - -The constant `18` in the time formula is Halstead's "Stroud number" — the number of mental -discriminations per second a programmer is assumed to make. - -## Per-language operator/operand split - -What counts as an operator vs. an operand is language-specific. mehen's analyzers follow the prevailing -convention: - -- **Operators:** keywords (`if`, `for`, `return`, …), arithmetic and logical symbols (`+`, `&&`, …), - parentheses pair `()`, brackets `[]`, and assignment operators. -- **Operands:** identifiers, literal values (numbers, strings, booleans, null/undefined), and type names. - -The exact mapping for each language lives in its analyzer crate at `crates/mehen-/`. - -## How to read it - -| Halstead | Interpretation | -|---|---| -| `volume` low, `difficulty` low | Small, easy code. | -| `volume` high, `difficulty` low | Long but mechanical (e.g., big lookup table). | -| `volume` low, `difficulty` high | Compact but tricky (clever one-liner). | -| `volume` high, `difficulty` high | Large *and* tricky — refactor candidate. | - -`halstead.bugs` and `halstead.time` are **rough estimates** with limited empirical backing. Treat them as -order-of-magnitude signals, not promises. - -## References - -- Halstead, M. H. (1977). *Elements of Software Science.* Operating and Programming Systems Series. - Elsevier. [OSTI record](https://www.osti.gov/biblio/5685613). -- Kearney, J. K., et al. *Software Complexity Measurement* — MIT lecture notes that summarize the - Halstead operator/operand formulation alongside McCabe. - [PDF (MIT OCW 16.355)](http://sunnyday.mit.edu/16.355/kearney.pdf). -- Christensen, K., Fitsos, G. P. & Smith, C. P. (1981). *A perspective on software science.* IBM - Systems Journal 20(4): 372–387. [DOI](https://doi.org/10.1147/sj.204.0372). -- Sonar: [Halstead in the metrics definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). -- Radon: [Halstead](https://radon.readthedocs.io/en/latest/intro.html#halstead-metrics) — Python - reference implementation of the formulas. - -## See also - -- [Maintainability Index](/metrics/code/mi) — uses Halstead volume. -- [Cyclomatic complexity](/metrics/code/cyclomatic) — control-flow complexity. -- [Cognitive complexity](/metrics/code/cognitive) — readability complexity. diff --git a/docs/metrics/code/lloc.mdx b/docs/metrics/code/lloc.mdx deleted file mode 100644 index 52b41fd3..00000000 --- a/docs/metrics/code/lloc.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "LLOC — Logical Lines of Code" -description: "Logical lines — statements as defined by each language's grammar." -keywords: ["lloc", "logical lines", "statements", "code metric"] ---- - -**LLOC** (Logical Lines of Code) counts statements as the language's grammar defines them. Where PLOC -counts physical instruction lines, LLOC counts logical units of work — independent of how those units -happen to be wrapped across physical lines. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `loc.lloc` | int | Logical lines (statements). | - -## How it is computed - -The exact rule is language-specific because what counts as a statement depends on the grammar. Each -analyzer crate implements LLOC by walking the parse tree and counting nodes that match its language's -statement kinds — `expression_statement`, `declaration_statement`, `if_statement`, `for_statement`, -`return_statement`, etc. - -## Worked example - -```rust -fn factorial(num: u64) -> u64 { - (1..=num).product() -} -``` - -This file has **one** logical line: the single expression returned from `factorial`. PLOC for the same -file is 3 (the function signature line, the body line, and the closing brace), and SLOC is the full file -length. - -The split between PLOC and LLOC is sharper in languages where one statement spans many lines (e.g., a -chained call in JavaScript or a multi-line tuple in Python). - -## When it is useful - -- Comparing language idioms: a Python list comprehension might be 1 LLOC where the equivalent loop is 5 - PLOC. LLOC normalizes for that. -- Detecting "hidden" complexity: when LLOC is much larger than PLOC suggests, the file is statement-dense. - -## References - -- Park, R. E. (1992). *Software Size Measurement: A Framework for Counting Source Statements.* - CMU/SEI-92-TR-20 — defines logical-statement counting and the difference between physical and - logical lines. - [SEI report](https://insights.sei.cmu.edu/library/software-size-measurement-a-framework-for-counting-source-statements/). -- Halstead, M. H. (1977). *Elements of Software Science.* Elsevier — early discussion of - statement-level counting. - -## See also - -- [LOC family](/metrics/code/loc) — overview. -- [PLOC](/metrics/code/ploc) — physical instruction lines. -- [SLOC](/metrics/code/sloc) — total physical lines. diff --git a/docs/metrics/code/loc.mdx b/docs/metrics/code/loc.mdx deleted file mode 100644 index 80891982..00000000 --- a/docs/metrics/code/loc.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: "LOC family" -description: "Lines of code measured five ways: SLOC, PLOC, LLOC, CLOC, and blank lines." -keywords: ["loc", "sloc", "ploc", "lloc", "cloc", "lines of code"] ---- - -The **Lines of Code (LOC)** family is the simplest size metric mehen reports — and one of the oldest. A -single number is misleading, so mehen separates physical lines, instruction lines, statements, comments, -and blanks. - -## What mehen emits - -| Key | Page | Counts | -|---|---|---| -| `loc.sloc` | [SLOC](/metrics/code/sloc) | Every physical line, including comments and blanks. | -| `loc.ploc` | [PLOC](/metrics/code/ploc) | Physical instruction lines (excludes comments and blanks). | -| `loc.lloc` | [LLOC](/metrics/code/lloc) | Logical lines — statements per the language's grammar. | -| `loc.cloc` | [CLOC](/metrics/code/cloc) | Comment lines (line, block, and doc comments). | -| `loc.blank` | [Blank](/metrics/code/blank) | Whitespace-only lines. | -| `loc` | — | Alias for `loc.sloc`. | - -## Worked example - -```rust -/* -Instruction: Implement factorial function -For extra credits, do not use mutable state or imperative loops. - */ - -/// Factorial: n! = n*(n-1)*(n-2)*...*3*2*1 -fn factorial(num: u64) -> u64 { - - // use `product` on `Iterator` - (1..=num).product() -} -``` - -| Metric | Value | -|---|---| -| `loc.sloc` | 11 | -| `loc.ploc` | 3 | -| `loc.lloc` | 1 | -| `loc.cloc` | 6 | -| `loc.blank` | 2 | - -## Why split the count - -The LOC family separates concerns that "lines of code" conflates: - -- **SLOC** is the simplest size signal — useful for repository-level dashboards. -- **PLOC** removes whitespace and comments and is closest to "real code". -- **LLOC** counts statements, so it is the right axis for comparing language idioms (one Python - comprehension vs. a multi-line Rust loop). -- **CLOC** and **Blank** are reported separately because comment and whitespace ratios are themselves - signals of style and readability. - -## References - -- Park, R. E. (1992). *Software Size Measurement: A Framework for Counting Source Statements.* - CMU/SEI-92-TR-20, Software Engineering Institute, Carnegie Mellon. - [SEI report](https://insights.sei.cmu.edu/library/software-size-measurement-a-framework-for-counting-source-statements/) — - the standard reference for what does and does not count as a "line". -- Nguyen, V., Deeds-Rubin, S., Tan, T. & Boehm, B. (2007). *A SLOC Counting Standard.* USC Center for - Systems and Software Engineering Technical Report. - [USC PDF](https://csse.usc.edu/TECHRPTS/2007/usc-csse-2007-737/usc-csse-2007-737.pdf). -- Sonar: [Lines of code in metric definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [Concepts → Spaces](/concepts/spaces) — how the LOC family aggregates from spaces to files. -- [Developers → How-to: implement LoC](/developers/loc) — internal implementation guide. diff --git a/docs/metrics/code/mi.mdx b/docs/metrics/code/mi.mdx deleted file mode 100644 index 05dd016b..00000000 --- a/docs/metrics/code/mi.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: "Maintainability Index" -description: "Composite maintainability score that blends Halstead volume, cyclomatic complexity, and SLOC." -keywords: ["maintainability index", "mi", "sei", "visual studio", "complexity"] ---- - -The **Maintainability Index (MI)** is a composite score that blends Halstead volume, cyclomatic -complexity, and SLOC into a single number representing how maintainable a unit of code is. mehen reports -all three commonly used variants. - -## What mehen emits - -| Key | Type | Variant | -|---|---|---| -| `mi.original` | float | Oman & Hagemeister, 1992 (raw, can be negative). | -| `mi.visual_studio` | float | Microsoft Visual Studio rescale to 0–100. | -| `mi.sei` | float | Software Engineering Institute (SEI) variant including comment ratio. | - -## Formulas - -### Original (Oman & Hagemeister, 1992) - -```text -MI_original = 171 - − 5.2 · ln(V_avg) - − 0.23 · CC_avg - − 16.2 · ln(LOC_avg) -``` - -where `V_avg`, `CC_avg`, `LOC_avg` are averages across the unit. - -### Visual Studio (rescaled 0–100) - -Microsoft rescaled MI to a 0–100 range so a single threshold could be applied across files: - -```text -MI_VS = max(0, MI_original · 100 / 171) -``` - -### SEI (with comment ratio) - -The SEI variant adds a documentation term: - -```text -MI_SEI = 171 - − 5.2 · log₂(V) - − 0.23 · CC - − 16.2 · log₂(SLOC) - + 50 · sin(sqrt(2.4 · CM)) -``` - -where `CM` is the ratio of comment lines to total lines. - -## How to read it - -| `mi.visual_studio` | Interpretation (Visual Studio default) | -|---|---| -| 20–100 | Maintainable (green). | -| 10–19 | Moderately maintainable (yellow). | -| 0–9 | Hard to maintain (red). | - -Visual Studio uses these thresholds out of the box. - - -MI is a **composite** — it aggregates a few simpler signals. When MI changes, look at the components -([Halstead volume](/metrics/code/halstead), [Cyclomatic complexity](/metrics/code/cyclomatic), -[SLOC](/metrics/code/sloc), [CLOC](/metrics/code/cloc)) to understand which input moved. The composite is -useful for ranking files and tracking trends; it is not the right tool to argue about a specific -function in isolation. - - -## References - -- Oman, P. & Hagemeister, J. (1992). *Metrics for assessing a software system's maintainability.* - Proc. Conf. on Software Maintenance. - [DOI](https://doi.org/10.1109/ICSM.1992.242525). -- Coleman, D., Ash, D., Lowther, B. & Oman, P. (1994). *Using metrics to evaluate software system - maintainability.* Computer 27(8): 44–49. - [DOI](https://doi.org/10.1109/2.303623). -- Welker, K. D. (2001). *The Software Maintainability Index Revisited.* CrossTalk — The Journal of - Defense Software Engineering, August 2001. - [PDF (DTIC archive)](https://apps.dtic.mil/sti/tr/pdf/ADA607106.pdf). -- Microsoft: [Code metrics — Maintainability Index range and meaning](https://learn.microsoft.com/visualstudio/code-quality/code-metrics-values). -- Radon: [Maintainability Index reference implementation](https://radon.readthedocs.io/en/latest/intro.html#maintainability-index). - -## See also - -- [Halstead metrics](/metrics/code/halstead) — input for MI. -- [Cyclomatic complexity](/metrics/code/cyclomatic) — input for MI. -- [LOC family](/metrics/code/loc) — SLOC and CLOC are inputs. diff --git a/docs/metrics/code/nargs.mdx b/docs/metrics/code/nargs.mdx deleted file mode 100644 index 6c3fd5b6..00000000 --- a/docs/metrics/code/nargs.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "NARGS — Number of Arguments" -description: "Argument count per function or method, with file-level aggregates." -keywords: ["nargs", "arguments", "parameters", "function size"] ---- - -**NARGS** counts the number of formal arguments declared by each function, method, or closure. mehen -reports per-function values plus aggregate statistics (total, min, max, average) at the file level. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `nargs` | int | Total arguments across all functions and closures in the space. | -| `nargs.average` | float | Mean argument count per function. | -| `nargs.functions` | int | Total arguments declared by named functions. | -| `nargs.functions_min` / `_max` / `_average` | — | Aggregates over named functions only. | -| `nargs.closures` | int | Total arguments declared by closures/lambdas. | -| `nargs.closures_min` / `_max` / `_average` | — | Aggregates over closures only. | -| `nargs.average_functions` | float | Mean per named function. | -| `nargs.average_closures` | float | Mean per closure. | -| `nargs.total_functions` | int | Total of `nargs.functions` (alias). | -| `nargs.total_closures` | int | Total of `nargs.closures` (alias). | - -## Why both functions and closures are reported - -Closures are first-class values in TypeScript, Rust, Ruby, Kotlin, Python, etc. Mixing closure parameter -counts with named-function parameter counts hides the long-tail of inline lambdas. mehen reports both -buckets so you can see, for example, that a file's named functions average 2 arguments while its -callbacks average 4. - -## How to read it - -Conventional ceilings (no universal authority — pick one for your repo): - -| Per-function `nargs` | Interpretation | -|---|---| -| 0–3 | Easy to call. | -| 4–5 | Borderline; consider a parameter object. | -| 6+ | Refactor candidate. | - -Robert C. Martin's *Clean Code* recommends **≤ 3** as a soft cap; it's a stylistic preference, not a hard -rule. - -## References - -- Sonar: [Metrics definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). -- Martin, R. C. (2008). *Clean Code*, ch. 3. (Soft cap of 3 for "ideal" function arity.) - -## See also - -- [NOM](/metrics/code/nom) — number of methods. -- [NEXITS](/metrics/code/nexits) — exit-point count. diff --git a/docs/metrics/code/nexits.mdx b/docs/metrics/code/nexits.mdx deleted file mode 100644 index f336822c..00000000 --- a/docs/metrics/code/nexits.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "NEXITS — Number of Exit Points" -description: "Exit-point count per function or method (returns + throws + early breaks of control)." -keywords: ["nexits", "exit points", "early return", "control flow"] ---- - -**NEXITS** counts the number of exit points each function/method has. The classic structured-programming -recommendation is one exit per function — a high NEXITS suggests the function ought to be split. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `nexit` | int | Total exit points across functions in the space. | -| `nexit.average` | float | Mean exit-point count per function. | -| `nexit.min` | int | Minimum across functions. | -| `nexit.max` | int | Maximum across functions. | -| `nexit.sum` | int | Sum across child spaces. | - -## What counts as an exit - -Each language analyzer maps its language's exit-flow constructs: - -- `return` and value-returning expressions. -- `throw` / `raise` / `panic!` statements. -- `yield` / `yield return` (generator functions). -- `exit`, `os.exit`, and the equivalent process-exit calls where unambiguous. -- Labeled `break` that exits the function (rare in practice). - -The count is per-function: the parser walks each function body and adds 1 per matching node. - -## How to read it - -| `nexit` | Interpretation | -|---|---| -| 1 | Single exit point — classic structured style. | -| 2–4 | Pragmatic — early returns for guard clauses are a popular style. | -| 5+ | Function does multiple things — extract methods. | - - -Modern Rust, TypeScript, and Kotlin codebases tend to use early returns liberally. A NEXITS of 3–4 is -not, by itself, a problem. Read NEXITS alongside [Cognitive complexity](/metrics/code/cognitive) — if -both are high, the function is likely a refactor candidate. - - -## References - -- Dijkstra, E. W. (1968). *Go To Statement Considered Harmful.* Communications of the ACM, 11(3). -- Sonar: [Metrics definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [Cyclomatic complexity](/metrics/code/cyclomatic) — exit points are not branches; they're orthogonal. -- [NARGS](/metrics/code/nargs) — argument count. -- [NOM](/metrics/code/nom) — number of methods. diff --git a/docs/metrics/code/nom.mdx b/docs/metrics/code/nom.mdx deleted file mode 100644 index d35b51cb..00000000 --- a/docs/metrics/code/nom.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "NOM — Number of Methods" -description: "Number of functions and closures declared in a file, trait, or class." -keywords: ["nom", "number of methods", "functions", "closures"] ---- - -**NOM** (Number of Methods) counts how many functions and closures live inside a unit (file, trait, -class, or module). - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `nom` | int | Total methods (named functions + closures). | -| `nom.functions` | int | Number of named functions. | -| `nom.closures` | int | Number of closures/lambdas. | -| `nom.functions_min` / `_max` / `_average` | — | Aggregates across child spaces. | -| `nom.closures_min` / `_max` / `_average` | — | Aggregates across child spaces. | -| `nom.average_functions` / `nom.average_closures` | float | Means per child space. | -| `nom.total_functions` / `nom.total_closures` | int | Aliases of `nom.functions` and `nom.closures`. | - -## How to read it - -| `nom` | Interpretation | -|---|---| -| 1–10 | Small file/class; usually fine. | -| 11–25 | Medium; expected in most app-layer code. | -| 26+ | Likely a god-class candidate; pair with [WMC](/metrics/code/wmc) to confirm. | - -The split between `nom.functions` and `nom.closures` is informative. A file with 5 named functions and -50 closures is usually a callback-heavy piece (e.g., an event-driven module). - -## References - -- Chidamber, S. R. & Kemerer, C. F. (1994). *A Metrics Suite for Object Oriented Design.* IEEE TSE. - [DOI](https://doi.org/10.1109/32.295895). (NOM is one of the original CK metrics.) -- Sonar: [Metrics definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/) — `functions` count. - -## See also - -- [WMC](/metrics/code/wmc) — weighted methods per class (uses NOM as a divisor in some - implementations). -- [NPM](/metrics/code/npm) — public methods only. -- [NPA](/metrics/code/npa) — public attributes. diff --git a/docs/metrics/code/npa.mdx b/docs/metrics/code/npa.mdx deleted file mode 100644 index fbc09435..00000000 --- a/docs/metrics/code/npa.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: "NPA — Number of Public Attributes" -description: "Number of public attributes declared on classes and interfaces." -keywords: ["npa", "public attributes", "encapsulation"] ---- - -**NPA** (Number of Public Attributes) counts public fields/properties exposed by classes and interfaces -in a file. A high NPA usually signals weak encapsulation — internal state leaking outside the type. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `npa` | int | Total public attributes across classes and interfaces. | -| `npa.classes` | int | NPA contributed by classes. | -| `npa.interfaces` | int | NPA contributed by interfaces. | -| `npa.class_attributes` | int | Same as `npa.classes` (alias). | -| `npa.interface_attributes` | int | Same as `npa.interfaces` (alias). | -| `npa.classes_average` | float | Mean attributes per class. | -| `npa.interfaces_average` | float | Mean attributes per interface. | -| `npa.total_attributes` | int | Total NPA in the file (alias of `npa`). | -| `npa.average` | float | Mean attributes per declaration (class or interface). | - -## What counts as "public" - -The exact rule is language-specific: - -| Language | Public attribute is… | -|---|---| -| Java / Kotlin | A field declared `public` (or with no modifier in Kotlin classes). | -| TypeScript / JS | A class field without `private` / `protected` / `#` prefix. | -| Python | A class attribute that does not start with `_`. | -| Ruby | An `attr_accessor` / `attr_reader` / `attr_writer` declaration (Ruby fields are private by -default). | -| C# | A field, constant, or event declared `public`. A member with no access modifier is `private`, and `internal` is assembly-scoped, so neither counts. `enum` members are always public. | - -## How to read it - -A "few" public attributes is usually fine. Many can mean: - -- Data classes / records: `NPA = number of fields` is expected and benign. -- Property bags or "god objects": NPA grows past 10 — refactor candidate. - -Read NPA alongside [NPM](/metrics/code/npm). A class with NPA much greater than NPM is a struct in -disguise; a class with NPM much greater than NPA is encapsulating state behind methods. - -## References - -- Lorenz, M. & Kidd, J. (1994). *Object-Oriented Software Metrics: A Practical Guide.* Prentice Hall. -- Chidamber, S. R. & Kemerer, C. F. (1994). *A Metrics Suite for Object Oriented Design.* IEEE TSE - 20(6): 476–493. [DOI](https://doi.org/10.1109/32.295895). -- Briand, L. C., Daly, J. W. & Wüst, J. K. (1998). *A Unified Framework for Coupling Measurement in - Object-Oriented Systems.* IEEE TSE 25(1): 91–121. - [DOI](https://doi.org/10.1109/32.748920). - -## See also - -- [NPM](/metrics/code/npm) — number of public methods. -- [NOM](/metrics/code/nom) — number of methods (public + private). diff --git a/docs/metrics/code/npm.mdx b/docs/metrics/code/npm.mdx deleted file mode 100644 index adaa0417..00000000 --- a/docs/metrics/code/npm.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "NPM — Number of Public Methods" -description: "Number of public methods declared on classes and interfaces." -keywords: ["npm metric", "public methods", "interface size", "api surface"] ---- - -**NPM** (Number of Public Methods) counts the public methods exposed by classes and interfaces in a -file. NPM is the size of the unit's API surface. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `npm` | int | Total public methods across classes and interfaces. | -| `npm.classes` | int | NPM contributed by classes. | -| `npm.interfaces` | int | NPM contributed by interfaces. | -| `npm.class_methods` | int | Alias of `npm.classes`. | -| `npm.interface_methods` | int | Alias of `npm.interfaces`. | -| `npm.classes_average` | float | Mean public methods per class. | -| `npm.interfaces_average` | float | Mean public methods per interface. | -| `npm.total_methods` | int | Alias of `npm`. | -| `npm.average` | float | Mean public methods per declaration. | - - -Despite the name, this metric has nothing to do with the npm package manager. NPM here stands for -*Number of Public Methods*, a classic CK-style object-oriented metric. - - -## What counts as "public" - -| Language | Public method is… | -|---|---| -| Java / Kotlin | A method declared `public` (or with no modifier in Kotlin). | -| C# | A method, constructor, operator, property, or indexer declared `public`. A member with no access modifier is `private`, and `internal` is assembly-scoped, so neither counts. An interface member is public *by default* — but since C# 8 it may carry an explicit `private`, `protected`, or `internal` modifier (a default implementation can be a private helper), and an explicit non-public modifier wins. | -| TypeScript / JS | A class method without `private` / `protected` / `#` prefix. | -| Python | A method that does not start with `_`. | -| Ruby | A method *not* declared `private` or `protected`. | - -## How to read it - -Conventional reading: - -| `npm` | Interpretation | -|---|---| -| 1–10 | Small, focused class. | -| 11–25 | Normal application class. | -| 26+ | God-class candidate. | - -Pair with [WMC](/metrics/code/wmc) to gauge whether the surface is wide *and* heavy, and with -[NPA](/metrics/code/npa) to gauge whether the class encapsulates state. - -## References - -- Lorenz, M. & Kidd, J. (1994). *Object-Oriented Software Metrics: A Practical Guide.* Prentice Hall. -- Chidamber & Kemerer (1994). *A Metrics Suite for Object Oriented Design.* IEEE TSE. - -## See also - -- [NPA](/metrics/code/npa) — number of public attributes. -- [NOM](/metrics/code/nom) — total methods (public + private). -- [WMC](/metrics/code/wmc) — weighted methods per class. diff --git a/docs/metrics/code/overview.mdx b/docs/metrics/code/overview.mdx deleted file mode 100644 index 88916aef..00000000 --- a/docs/metrics/code/overview.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "Code metrics overview" -description: "What mehen reports for source code: size, complexity, and function/class shape." -keywords: ["code metrics", "complexity", "halstead", "loc", "maintainability"] ---- - -mehen reports three families of source-code metrics, all computed from the language analyzer's parse -tree. Every metric is described on its own page with the canonical formula, what mehen emits, and links -to authoritative references. - -## Size - -| Metric | Key | Description | -|---|---|---| -| [SLOC](/metrics/code/sloc) | `loc.sloc` | Total physical lines, including blanks and comments. | -| [PLOC](/metrics/code/ploc) | `loc.ploc` | Physical instruction lines (no blanks/comments). | -| [LLOC](/metrics/code/lloc) | `loc.lloc` | Logical lines — statements as defined per language. | -| [CLOC](/metrics/code/cloc) | `loc.cloc` | Comment lines (line + block + doc comments). | -| [Blank](/metrics/code/blank) | `loc.blank` | Whitespace-only lines. | - -The umbrella is described on the [LOC family](/metrics/code/loc) page. - -## Complexity - -| Metric | Key | Description | -|---|---|---| -| [Cyclomatic complexity](/metrics/code/cyclomatic) | `cyclomatic` | McCabe's count of linearly independent paths. | -| [Cognitive complexity](/metrics/code/cognitive) | `cognitive` | Sonar's "how hard to understand" complexity. | -| [Weighted Methods per Class](/metrics/code/wmc) | `wmc` | Sum of cyclomatic complexity across class methods. | -| [Halstead suite](/metrics/code/halstead) | `halstead.*` | Volume, difficulty, effort, bugs, time. | -| [Maintainability Index](/metrics/code/mi) | `mi.*` | Original, Visual Studio, and SEI variants. | -| [ABC](/metrics/code/abc) | `abc.*` | Assignments, branches, conditions, magnitude. | - -## Function and class shape - -| Metric | Key | Description | -|---|---|---| -| [NOM](/metrics/code/nom) | `nom` | Number of methods (functions + closures). | -| [NARGS](/metrics/code/nargs) | `nargs` | Argument count per function/method. | -| [NEXITS](/metrics/code/nexits) | `nexit` | Exit-point count per function/method. | -| [NPA](/metrics/code/npa) | `npa` | Number of public attributes (classes/interfaces). | -| [NPM](/metrics/code/npm) | `npm` | Number of public methods (classes/interfaces). | - -## Spaces - -Every metric is also reported per **space** — the language-aware container for a function, method, class, -trait, or module. See [Concepts → Spaces](/concepts/spaces) for how containers nest and how metric -aggregation rolls up to the file. - -## Markdown is separate - -Markdown documentation gets its own metric family — DMI, MRPC, MCC, link debt, filler/lazy risk, etc. — -because functions, classes, and statements do not exist in prose. See -[Markdown metrics](/metrics/markdown/overview). - -## History is separate too - -How a file *changed over time* — churn, code age, ownership, hotspots, change coupling, bug risk — -is the `history.*` family, computed from repository history rather than from the parse tree. See -[History metrics](/metrics/history/overview). diff --git a/docs/metrics/code/ploc.mdx b/docs/metrics/code/ploc.mdx deleted file mode 100644 index 7104938d..00000000 --- a/docs/metrics/code/ploc.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "PLOC — Physical Lines of Code" -description: "Physical instruction lines — code lines with comments and blanks excluded." -keywords: ["ploc", "physical lines", "ncloc", "non-comment lines"] ---- - -**PLOC** (Physical Lines of Code) counts source lines that contain at least one code token. Pure -comment lines and pure blank lines are excluded. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `loc.ploc` | int | Physical instruction lines. | - -## How it is computed - -A line counts toward PLOC when the parser reports at least one non-trivia token on it. Lines that hold -only whitespace, only block-comment continuation, or only line-comment text are excluded. Mixed lines -(code followed by an inline comment) count as PLOC. - -## When it is useful - -- "Real code" size: PLOC strips out comments and blanks, so it is closer to what reviewers think of as - the size of a file. -- Comparing comment density: pair with [CLOC](/metrics/code/cloc) to compute the comment ratio - `cloc / (cloc + ploc)`. -- Maintainability inputs: PLOC is one of the inputs to the - [Maintainability Index](/metrics/code/mi). - -## Equivalents in other tools - -| Tool | Equivalent | -|---|---| -| Sonar | `ncloc` (non-comment lines of code). | -| `cloc` (CLI) | "code" column. | -| Visual Studio MI calculation | "lines of code" input. | - -## References - -- Park, R. E. (1992). *Software Size Measurement: A Framework for Counting Source Statements.* - CMU/SEI-92-TR-20. - [SEI report](https://insights.sei.cmu.edu/library/software-size-measurement-a-framework-for-counting-source-statements/). -- Sonar: [`ncloc` in metric definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [LOC family](/metrics/code/loc) — overview. -- [CLOC](/metrics/code/cloc) — comment lines. -- [LLOC](/metrics/code/lloc) — logical (statement) lines. diff --git a/docs/metrics/code/sloc.mdx b/docs/metrics/code/sloc.mdx deleted file mode 100644 index b3a56017..00000000 --- a/docs/metrics/code/sloc.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "SLOC — Source Lines of Code" -description: "Total physical lines of source code, including comments and blanks." -keywords: ["sloc", "lines of code", "size metric"] ---- - -**SLOC** (Source Lines of Code) is the total count of physical lines in a source file, including code, -comments, and blank lines. It is the simplest possible size metric. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `loc.sloc` | int | Total physical lines in the file. | -| `loc` | int | Alias for `loc.sloc`. | - -## How it is computed - -mehen counts physical lines in the source bytes — every newline-terminated region is one line. Files that -do not end with a newline still count the trailing fragment. - -## When it is useful - -- Repository-level dashboards: total SLOC is a coarse but stable size signal. -- Trend reports: SLOC delta is what most engineering organizations track week over week. -- Sanity checking PR size: if a PR adds 5,000 SLOC, that's worth a comment. - - -SLOC is **not** a quality metric. A 50-line file can be more complex than a 500-line one. Use SLOC -alongside [PLOC](/metrics/code/ploc), [LLOC](/metrics/code/lloc), -[Cyclomatic complexity](/metrics/code/cyclomatic), and [Cognitive complexity](/metrics/code/cognitive). - - -## References - -- Park, R. E. (1992). *Software Size Measurement: A Framework for Counting Source Statements.* - CMU/SEI-92-TR-20. - [SEI report](https://insights.sei.cmu.edu/library/software-size-measurement-a-framework-for-counting-source-statements/). -- Nguyen, V., Deeds-Rubin, S., Tan, T. & Boehm, B. (2007). *A SLOC Counting Standard.* USC. - [USC PDF](https://csse.usc.edu/TECHRPTS/2007/usc-csse-2007-737/usc-csse-2007-737.pdf). -- Sonar: [`ncloc` in metric definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [LOC family](/metrics/code/loc) — overview of all five LOC variants. -- [PLOC](/metrics/code/ploc) — instruction lines only. -- [LLOC](/metrics/code/lloc) — logical (statement) lines. diff --git a/docs/metrics/code/wmc.mdx b/docs/metrics/code/wmc.mdx deleted file mode 100644 index 4af1b0af..00000000 --- a/docs/metrics/code/wmc.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: "WMC — Weighted Methods per Class" -description: "Sum of cyclomatic complexity across all methods declared in a class or interface." -keywords: ["wmc", "weighted methods", "ck metrics", "chidamber kemerer"] ---- - -**Weighted Methods per Class (WMC)** is one of the six classic CK (Chidamber & Kemerer) object-oriented -metrics. It sums the [cyclomatic complexity](/metrics/code/cyclomatic) of every method declared in a -class or interface. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `wmc` | int | Sum of cyclomatic complexity across all methods in the file. | -| `wmc.classes` | int | WMC summed over classes only. | -| `wmc.interfaces` | int | WMC summed over interfaces only. | - -## Definition - -```text -WMC(C) = Σ cyclomatic_complexity(m_i) -``` - -for each method `m_i` defined in class `C`. A class with five methods of cyclomatic complexity -`{1, 1, 4, 5, 8}` has `WMC = 19`. - -## Why a sum, not an average - -A class with one 50-CC method is different from a class with fifty 1-CC methods, even though the -average is the same. WMC captures the **total** decision burden of a class, which correlates with how -much of the class a maintainer must understand to make a change. - -## How to read it - -There is no universal threshold; common conventions: - -| `WMC` | Interpretation | -|---|---| -| 1–14 | Small/cohesive class. | -| 15–40 | Normal in Java/C# / TS classes. | -| 41+ | Likely god-class candidate. | - -Read WMC alongside [NOM](/metrics/code/nom): a high WMC with low NOM signals a few very complex methods; -a high WMC with high NOM signals a class doing too much. - -## Languages where WMC applies - -WMC is meaningful for languages with explicit class/interface declarations: Java, Kotlin, TypeScript, -Python (classes), Ruby, C++, C#. mehen reports `wmc = 0` for files with no declarations of those kinds -(e.g., a Go file or a procedural C file). - -## References - -- Chidamber, S. R. & Kemerer, C. F. (1994). *A Metrics Suite for Object Oriented Design.* - IEEE Transactions on Software Engineering 20(6): 476–493. - [DOI](https://doi.org/10.1109/32.295895) · - [Author copy (MIT)](https://www.researchgate.net/publication/3187307_A_Metrics_Suite_for_Object_Oriented_Design). -- Basili, V. R., Briand, L. C. & Melo, W. L. (1996). *A validation of object-oriented design metrics - as quality indicators.* IEEE TSE 22(10): 751–761. - [DOI](https://doi.org/10.1109/32.544352). -- Sonar: [Metrics definitions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/). - -## See also - -- [Cyclomatic complexity](/metrics/code/cyclomatic) — the per-method input. -- [NOM](/metrics/code/nom) — number of methods. -- [NPM](/metrics/code/npm) — number of public methods. diff --git a/docs/metrics/coverage/auto-discovery.mdx b/docs/metrics/coverage/auto-discovery.mdx deleted file mode 100644 index 8e5db718..00000000 --- a/docs/metrics/coverage/auto-discovery.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: "Auto-discovery" -description: "How bare --coverage finds report files with zero configuration: idiomatic locations, gitignored build directories, and declarative tool configs — bounded and deterministic." -keywords: ["coverage discovery", "lcov.info", "coverage directory", "TestResults", "nyc_output", "zero configuration"] ---- - -Coverage reports live exactly where mehen's source walk refuses to look: `coverage/`, `target/`, -`build/`, and `TestResults/` are gitignored in any healthy repository, and `.nyc_output/` is -hidden. Bare `--coverage` (or `--coverage=auto`) therefore runs a *dedicated* discovery pass with -the inverse policy — every ignore rule off, hidden entries visible — while staying strictly -bounded and deterministic. (A configured `[coverage] discover = false` opts the scan out even -under the flag; configured `reports` still load.) - -```bash -mehen top-offenders src --metric coverage.line --coverage -``` - -Discovery also runs without the flag when something asks for coverage: a `coverage.*` metric -selector, a configured `coverage.*` threshold, or an opting-in `[coverage]` section in -`mehen.toml`. `--coverage=off` disables it unconditionally; explicit paths -(`--coverage=lcov.info`) skip discovery entirely. - -## Three input tiers - -1. **Explicit reports** — `--coverage=` (repeatable) or `reports = […]` under - `[coverage]`. These are *your* statement of intent: a missing or unparsable explicit report - is a hard error, because an explicit gate input that silently disappears is a broken CI gate. -2. **Tool-config introspection** — mehen reads *declarative* tool configs that say where reports - get written: - - the c8/nyc JSON rc family (`.c8rc`, `.c8rc.json`, `.nycrc`, `.nycrc.json` — first found, in - c8's own precedence order): `reports-dir`/`report-dir`; - - `pyproject.toml`: `[tool.coverage.xml] output` and `[tool.coverage.lcov] output` - (coverage.py); - - `phpunit.xml` / `phpunit.xml.dist`: `` and the legacy - `` — PHPUnit writes **no** coverage file unless - configured, so this is the only zero-config path for PHP; - - `tarpaulin.toml` / `.tarpaulin.toml` (cargo-tarpaulin): the union of `out` formats and - `output-dir` values across run profiles and the reserved `[report]` table. Tarpaulin's file - names are fixed (`cobertura.xml`, `lcov.info`), so introspection matters exactly when - `output-dir` redirects them into territory the scan prunes (e.g. `target/cov/`). - - Executable configs — `jest.config.ts`, `vitest.config.ts`, `.simplecov`, Gradle DSLs, Pester - scripts — are **never executed and never regex-scraped**. Their values are routinely computed - (env vars, imported constants), so extraction would silently be wrong; their tools' *default* - output locations are already covered by the scan below. -3. **Artifact scan** — well-known report names and locations, matched relative to each discovery - root (the enclosing repository work dir, so reports at the repo root are found even when you - analyze `./src`): `lcov.info`, `coverage.info`, `*.lcov`, `coverage.out` / `cover.out` / - `coverage.txt` / `profile.cov` / `c.out` / `*.coverprofile`, `coverage-final.json`, - `.nyc_output/*.json`, `jacoco.xml`, `jacocoTestReport.xml`, `site/jacoco/*.xml`, - `reports/jacoco/**/*.xml`, `reports/kover/*.xml`, `coverage.xml`, `clover.xml`, - `cobertura.xml`, `coverage.cobertura.xml`. Every match is confirmed by - [content sniffing](/metrics/coverage/supported-formats#detection-is-content-based) before it - is believed. - -## Bounded by construction - -Build directories are enormous, so the walk carries explicit bounds — each converts a -pathological repository from "hangs" into "warns": - -| Bound | Default | Why | -|---|---|---| -| Pruned directories | `node_modules`, `vendor`, `.venv`/`venv`, `.git`, tool caches (`.gradle`, `.m2`, `.cargo`, `__pycache__`, …) | No mainstream tool defaults report output into them; `node_modules` alone is ~100k directory entries of zero expected yield. | -| Targeted descent in `target/` | only `llvm-cov/`, `tarpaulin/`, `site/` | `target/debug` is routinely 50k+ entries of compiler output; the three subtrees are the only idiomatic report locations (cargo-llvm-cov, tarpaulin, Maven `target/site/jacoco/`). | -| Targeted descent in `build/` | only `reports/`, `logs/`, `coverage/` | Gradle reports, Jenkins-PHP `build/logs/clover.xml`, CMake coverage output. | -| `coverage/tmp/` | never entered | c8/nyc raw V8 staging; never contains final reports. | -| Depth | 12 | The deepest idiomatic path is ~7 components; 12 leaves monorepo headroom. | -| Directory entries | 500,000 | Chromium-scale headroom after pruning. | -| Candidates sniffed | 256 (4 KiB each) | Total sniff I/O ≤ 1 MiB. | -| Candidates per directory | 64 | Bounds `.nyc_output` shard floods; the name-sorted walk keeps the lexicographically first shards. | -| Report size | 256 MiB | Beyond the largest real-world LCOV files. | -| Symlinks | never followed | A candidate that is a file symlink must resolve *inside* a discovery root, so a planted `lcov.info → /etc/passwd` is rejected unread. | - -An `extra-patterns` entry whose first component names a pruned directory lifts that directory for -the run — the escape hatch for exotic layouts: - -```toml -[coverage] -extra-patterns = ["node_modules/.cache/**/lcov.info"] -``` - -## Deterministic selection - -When several candidates survive, selection is order-independent by construction: - -- **Same directory, several formats** — one Jest run writes `lcov.info` + - `coverage-final.json` + `clover.xml` into `coverage/`; they describe the same test run, so only - the highest-priority format is parsed and the rest are recorded as superseded. -- **`TestResults//` re-runs** — coverlet writes each `dotnet test` run into a fresh GUID - directory; sibling runs holding the same report name keep only the newest (by mtime, - lexicographic tie-break). This is the *only* place mtimes are trusted — a fresh CI clone stamps - every file with clone time, so a global newest-wins rule would be meaningless. -- **Same file found twice** (scanned *and* named by a tool config) — recorded once, attributed to - the config. - -Everything else merges (union + saturating-max — see -[supported formats](/metrics/coverage/supported-formats#normalization-and-merge-semantics)), and -discovery never fails a run: unreadable directories, malformed configs, and cap overruns degrade -to warnings. - -## Staleness - -A report generated before the code it describes attributes hits to the wrong lines. When a -discovered report's mtime predates the newest `HEAD` commit across the discovery roots, mehen -warns (the report is still used — the heuristic has false positives around rebases and -cherry-picks, and silently dropping your only report would be worse). Disable with -`stale-warning = false` under `[coverage]`. - -## Configuration reference - -```toml -[coverage] -reports = ["ci-artifacts/lcov.info"] # explicit paths; hard error if unusable -discover = true # `true` also opts the run in without a flag -extra-patterns = ["qa/**/*.lcov"] # additive scan globs, root-relative -stale-warning = true # the mtime-vs-HEAD warning above -``` - -Flag/file precedence is per mode, not blanket: `--coverage=off` disables coverage regardless of -configuration, and `--coverage=` uses exactly the supplied reports — but bare -`--coverage`/`=auto` honors a configured `discover = false` (it forces ingestion of configured -reports, not the scan). Unknown keys and wrong types are rejected at load time with a caret -into the TOML source, like every other `mehen.toml` mistake. - -## See also - -- [Supported formats](/metrics/coverage/supported-formats) — what the candidates are sniffed - against. -- [Path matching](/metrics/coverage/path-matching) — what happens to the reports after ingestion. -- [Configuration](/configuration) — the rest of `mehen.toml`. - -## References - -- [c8 configuration](https://github.com/bcoe/c8#readme) and - [nyc configuration](https://github.com/istanbuljs/nyc#configuration-files) — the JSON rc - family and its precedence. -- [coverage.py configuration reference](https://coverage.readthedocs.io/en/latest/config.html) — - `[xml] output` / `[lcov] output` (the `[tool.coverage.*]` tables in `pyproject.toml`). -- [PHPUnit XML configuration](https://docs.phpunit.de/en/main/configuration.html) — the - ``/`` elements. -- [cargo-tarpaulin config file](https://github.com/xd009642/tarpaulin#config-file) — run - profiles, the reserved `[report]` table, and the `out`/`output-dir` keys. -- [coverlet VSTest integration](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/VSTestIntegration.md) - — why `TestResults//coverage.cobertura.xml` re-run clusters exist. -- [Kover Gradle plugin](https://kotlin.github.io/kotlinx-kover/gradle-plugin/) — the - JaCoCo-compatible `build/reports/kover/` XML. diff --git a/docs/metrics/coverage/branch.mdx b/docs/metrics/coverage/branch.mdx deleted file mode 100644 index d579abf8..00000000 --- a/docs/metrics/coverage/branch.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: "Branch coverage" -description: "The share of branch arms your tests take — the criterion that catches the untested else, the short-circuited condition, and the error path line coverage waves through." -keywords: ["branch coverage", "decision coverage", "condition coverage", "MC/DC", "branch arms"] ---- - -**Branch coverage** measures whether each *outcome* of each decision point executed: the taken -and not-taken arm of every `if`, each `case` of a `switch`, each short-circuit of `&&`/`||`. It -is strictly stronger than [line coverage](/metrics/coverage/line) — a one-line -`if x: return None` reads 100% line-covered after a single truthy test, while its false arm (and -whatever falls through) was never exercised. Testing folklore has carried this point since Myers: -exercising every line is among the *weakest* adequacy criteria; exercising every decision outcome -is the first one with teeth. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `coverage.branch` | float | `covered arms / total arms × 100`, in `0..=100`. | -| `coverage.branch.covered` | int | Branch arms taken at least once. | -| `coverage.branch.total` | int | Branch arms the report recorded. | - -Published on the file's root space and, span-scoped, on every function and closure space. -**Absent when the report format measured no branches** — a Go coverprofile, or an LCOV file -produced without branch instrumentation (`lcov`'s branch coverage is off by default), publishes -no `coverage.branch` keys at all, rather than a fabricated 0% or 100%. - -## The arm model — how formats fold in - -Formats encode branch data with different vocabularies; mehen normalizes them all to flat -*arms* — one countable outcome each: - -| Format | Encoding | Folding | -|---|---|---| -| LCOV | `BRDA:,,,` per arm | one arm per record; `-` taken-count means 0 | -| Cobertura | `condition-coverage="50% (1/2)"` per line | the fraction expands to *n* arms, *covered* of them hit — per-arm counts are not recoverable from this format | -| JaCoCo | `mb`/`cb` (missed/covered branches) per line | `mb + cb` arms, `cb` of them hit | -| Clover | `truecount`/`falsecount` on `type="cond"` lines | two arms per condition (true and false) | -| Istanbul | `b` arrays per branch site | one arm per array element | - -Two consequences worth knowing. First, **condition vs branch granularity is format-defined**: -Clover counts each boolean *condition*'s two outcomes, while Cobertura's fraction may aggregate a -whole decision — mehen reports what the tool measured and does not attempt to reconstruct a finer -criterion than the report contains. Second, arm *identity* is positional per line, so merging two -reports max-matches arms in order — sound for re-runs of the same build, approximate across -different instrumentations of the same file. - -## How to read it - -| Signal | Interpretation | -|---|---| -| `coverage.branch` well below `coverage.line` | The classic gap: happy paths tested, error/edge arms not. The uncovered arms are usually `else` branches, early returns, and error handling — precisely the code that only runs when something goes wrong. | -| Low branch coverage on a high-[cyclomatic](/metrics/code/cyclomatic) function | Cyclomatic complexity counts decision points; low branch coverage says their outcomes are untested. This pairing is the strongest per-function risk signal the coverage family offers. | -| Branch ≈ line, both high | The suite genuinely walks the control flow — the numbers corroborate each other. | -| Dimension absent | The report simply didn't measure branches. Re-instrument (e.g. `lcov --rc branch_coverage=1`, `coverage run --branch`) before concluding anything. | - -For safety-critical calibration: DO-178C requires decision coverage at level B and MC/DC -(modified condition/decision coverage) at level A — criteria stronger than anything a mainstream -report format carries. SQLite famously maintains 100% MC/DC of its core; the point of citing it -is proportion — that standard costs person-years and is *not* the implied target of a CI gate. -`coverage.branch` is the practical middle ground: strictly better evidence than line coverage, -available from the tools you already run. - -## Gating - -```toml -[thresholds] -"coverage.branch" = 70 # minimum; files whose reports measured no branches skip the gate -``` - -## See also - -- [Line coverage](/metrics/coverage/line) — the weaker, universal criterion. -- [Cyclomatic complexity](/metrics/code/cyclomatic) — counts the decision points whose outcomes - this metric checks. -- [Supported formats](/metrics/coverage/supported-formats) — which producers emit branch data. - -## References - -- Myers, G. J., Sandler, C., & Badgett, T. (2011). *The Art of Software Testing*, 3rd ed. Wiley. - (Coverage criteria hierarchy: statement < decision < condition variants.) -- Chilenski, J. J., & Miller, S. P. (1994). [Applicability of modified condition/decision - coverage to software testing](https://doi.org/10.1049/sej.1994.0025). *Software Engineering - Journal*, 9(5). -- RTCA DO-178C (2011). *Software Considerations in Airborne Systems and Equipment - Certification.* (Structural-coverage objectives by criticality level.) -- [How SQLite is tested](https://www.sqlite.org/testing.html) — 100% MC/DC in practice, and what - it costs. -- [geninfo(1)](https://ltp.sourceforge.net/coverage/lcov/geninfo.1.php) — `BRDA` record - semantics. diff --git a/docs/metrics/coverage/function.mdx b/docs/metrics/coverage/function.mdx deleted file mode 100644 index 13b778ae..00000000 --- a/docs/metrics/coverage/function.mdx +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Function coverage" -description: "The share of functions your tests execute at all — the bird's-eye dimension that finds entirely dead test blind spots in one glance." -keywords: ["function coverage", "method coverage", "untested functions", "FNDA", "test blind spots"] ---- - -**Function coverage** counts functions executed at least once, out of the functions the report -recorded. It is the coarsest dimension in the family — a function counts as covered the moment -one test touches its first line — and that coarseness is its value: a function at zero is a -*complete* blind spot, not a partially-tested one, and a file where half the functions never run -tells a different story than a file where every function runs halfway. Crap4j, the original CRAP -implementation, operated at exactly this granularity for the same reason: functions and methods -are the unit developers reason about, test, and refactor. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `coverage.function` | float | `covered / total × 100`, in `0..=100`. | -| `coverage.function.covered` | int | Recorded functions executed at least once. | -| `coverage.function.total` | int | Functions the report recorded for the file. | - -Published on the file's **root space** (file-level totals from the report's own function -records). Absent when the format records no functions — a Go coverprofile has none, and Clover -only knows the `method` lines its instrumenter marked. - -## Where the records come from - -| Format | Function records | -|---|---| -| LCOV | `FN:,` + `FNDA:,` | -| Istanbul | `fnMap` + `f` hit counts | -| JaCoCo | `` elements with `METHOD` counters | -| Cobertura | `` elements (hit derived from their line records) | -| Clover | `` entries | -| Go coverprofile | — (dimension absent) | - -Note the subtle relationship with the *per-function line coverage* mehen also publishes: the -file-level `coverage.function` above comes from the report's own records, while each function -*space* in the metric tree carries `coverage.line`/`coverage.branch` computed from mehen's own -parse of the function's line span. The two views agree on what "untested function" means but -serve different queries — "how many of this file's functions run at all?" versus "how covered is -*this* function?". The per-space values are the ones the CRAP composite will consume, because -they exist even for formats without function records. - -## How to read it - -| Signal | Interpretation | -|---|---| -| `coverage.function` far below `coverage.line` | Coverage is concentrated: a few well-tested functions carry the percentage while others never run. The file-level line number is hiding dead zones. | -| A function space whose `coverage.line` reads 0% on a public function | Either missing tests or dead API — both worth knowing. Cross-reference [NPM](/metrics/code/npm)/[NOM](/metrics/code/nom) for how much surface the file exposes. | -| A hit function with low span line-coverage | Tests enter it but bail early — typically only the happy path's first branch. The per-function `coverage.line` on the space pinpoints these. | -| Language-specific footnote | Import-time execution counts: a Python `def` line executes when the module loads, so an otherwise-untested function can show a hit declaration line while its body sits at zero. The body lines tell the truth. | - -## Gating - -```toml -[thresholds] -"coverage.function" = 90 # minimum share of recorded functions executed -``` - -Function coverage makes a forgiving first gate for legacy codebases: it demands *some* test -reaches each function without dictating depth, and it is cheap to satisfy incrementally — -one test per blind spot. - -## See also - -- [Line coverage](/metrics/coverage/line) — depth within the functions this metric counts. -- [Branch coverage](/metrics/coverage/branch) — outcome-level depth. -- [NOM](/metrics/code/nom) — how many functions a file defines in the first place. - -## References - -- [Crap4j](http://www.crap4j.org/) — the original method-granularity CRAP implementation. -- Savoia, A., & Evans, B. (2007). [The CRAP metric](https://www.artima.com/weblogs/viewpost.jsp?thread=210575). -- [geninfo(1)](https://ltp.sourceforge.net/coverage/lcov/geninfo.1.php) — `FN`/`FNDA` record - semantics. -- Ivanković, M., Petrović, G., Just, R., & Fraser, G. (2019). [Code coverage at - Google](https://research.google/pubs/code-coverage-at-google/). *ESEC/FSE 2019.* diff --git a/docs/metrics/coverage/line.mdx b/docs/metrics/coverage/line.mdx deleted file mode 100644 index 85adfafb..00000000 --- a/docs/metrics/coverage/line.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: "Line coverage" -description: "The share of instrumentable lines your tests execute — per file and per function, the denominator of test-suite risk and the coverage input of the CRAP index." -keywords: ["line coverage", "statement coverage", "coverage percentage", "coverage gate", "untested code"] ---- - -**Line coverage** is the fraction of *instrumentable* lines executed at least once while the test -suite ran. It is the lingua franca of coverage — every supported format measures it, every -coverage service reports it — and the weakest claim in the family: an executed line proves the -tests *reached* the code, not that they *asserted* anything about it. Read it as a risk -denominator: low coverage marks code where the suite can catch nothing at all. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `coverage.line` | float | `covered / total × 100`, in `0..=100`. | -| `coverage.line.covered` | int | Instrumentable lines executed at least once. | -| `coverage.line.total` | int | Instrumentable lines the report recorded for the file. | - -Published on the file's root space **and, span-scoped, on every function and closure space** in -the metric tree — the per-function values are what make the numbers actionable (and what the -planned CRAP composite consumes). - -## Semantics - -- **Instrumentable lines only.** The denominator is the lines the coverage tool instrumented — - blank lines, comments, and non-executable declarations are excluded *by the producing tool*, - not by mehen. LCOV `DA` records with negative counts (non-instrumentable markers some - instrumenters emit) are dropped. -- **Hit means hit at least once.** Execution counts are preserved internally (and used for - max-merging), but the rate counts a line as covered at any count ≥ 1 — matching how every - producing tool defines the percentage. -- **Statements fold to lines.** Istanbul statement maps and Go basic blocks resolve to line - numbers; multiple statements on one line keep the maximum count. -- **Unmeasured ≠ 0%.** A file absent from every report, or a function span containing no - instrumented lines (macro-generated code, `#[cfg(test)]` items, dead-code-eliminated - functions), publishes nothing. Only genuinely instrumented-but-unexecuted code reads `0`. -- **Per-function attribution is line-range based.** A function space spanning lines 10–24 - aggregates the report's records for those lines. Line ranges come from mehen's real parsers, - so the attribution is exact for the function body; a multi-line signature counts from the - declaration line the parser assigns. - -## How to read it - -| Signal | Interpretation | -|---|---| -| Low `coverage.line` on a high-[cognitive](/metrics/code/cognitive) function | The highest-risk combination this family can express — complex logic the suite never exercises. This intersection is the CRAP index's definition of change-risky code. | -| Low file coverage, but the uncovered functions are trivial | Often acceptable — getters, glue, generated code. Rank by function, not by file, before reacting. | -| 100% line coverage | The tests reach everything — it says nothing about assertion quality (mutation testing measures that). Treat as a floor, not a goal. | -| Coverage dropping over time | New code is landing untested; a `coverage.line` minimum in `mehen.toml` stops the bleeding without demanding retroactive heroics. | - -Google's large-scale guidance is a useful calibration: they characterize 60% as acceptable, 75% -as commendable, and 90% as exemplary — while explicitly warning against chasing the number for -its own sake, because the marginal lines are usually the least valuable to cover. The empirical -literature agrees from the other side: Inozemtseva & Holmes found coverage only weakly-to- -moderately correlated with suite effectiveness once suite size is controlled, so a high -percentage must never be read as proof of a strong suite. - -## Gating - -```toml -[thresholds] -"coverage.line" = 80 # higher-is-better: the limit is a minimum - -[languages.python.thresholds] -"coverage.line" = 90 # stricter floor for Python files only -``` - -A configured `coverage.line` threshold is itself the trigger for -[report ingestion](/metrics/coverage/auto-discovery) — no flag needed in CI. Unmeasured files -skip the gate (never a fabricated violation); genuinely 0%-covered files fail it. - -## See also - -- [Branch coverage](/metrics/coverage/branch) — the stricter criterion. -- [Function coverage](/metrics/coverage/function) — the coarser one. -- [Cognitive complexity](/metrics/code/cognitive) — the number to cross line coverage with. - -## References - -- Ivanković, M., Petrović, G., Just, R., & Fraser, G. (2019). [Code coverage at - Google](https://research.google/pubs/code-coverage-at-google/). *ESEC/FSE 2019.* -- Inozemtseva, L., & Holmes, R. (2014). [Coverage is not strongly correlated with test suite - effectiveness](https://dl.acm.org/doi/10.1145/2568225.2568271). *ICSE 2014.* -- Marick, B. (1999). [How to misuse code coverage](http://www.exampler.com/testing-com/writings/coverage.pdf). -- Fowler, M. (2012). [TestCoverage](https://martinfowler.com/bliki/TestCoverage.html). *martinfowler.com.* -- Savoia, A., & Evans, B. (2007). [The CRAP metric](https://www.artima.com/weblogs/viewpost.jsp?thread=210575) - — the complexity × (1 − coverage)³ composite the per-function values feed. diff --git a/docs/metrics/coverage/overview.mdx b/docs/metrics/coverage/overview.mdx deleted file mode 100644 index 0c2a32c3..00000000 --- a/docs/metrics/coverage/overview.mdx +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: "Coverage metrics" -description: "Ingest coverage reports from your test runner — LCOV, Cobertura, JaCoCo, Clover, Istanbul, Go coverprofile — and analyze coverage alongside complexity." -keywords: ["code coverage", "test coverage", "lcov", "cobertura", "jacoco", "coverage gate", "CI"] ---- - -The `coverage.*` family folds **test coverage** into mehen's metric tree, next to the complexity -and size metrics computed from source. mehen does not instrument or run your tests — your test -runner already produces a coverage report; mehen ingests it, maps its file paths onto the files -under analysis, and publishes coverage as a first-class metric category: selectable in -[`mehen top-offenders`](/commands/top-offenders), gateable through -[`mehen.toml` thresholds](/configuration), rendered in the JSON and Markdown reports of -[`mehen metrics`](/commands/metrics), and carried as per-file **trend columns** in -[`mehen diff`](/commands/diff#coverage-trend-columns) (base side supplied via `--base-coverage`, -retrieved for you by the [GitHub Action](/guides/github-action#coverage-trends)). - -Coverage answers a question no static metric can: *which of this code do the tests actually -exercise?* Using [GitHub Code Quality](/guides/github-action#works-with-github-code-quality)'s -built-in coverage checks? The same Cobertura report feeds both — see the action guide for the -shared setup. Combined with complexity it locates the riskiest code in a repository — complex **and** -untested — which is exactly the intersection the CRAP index formalizes (see -[roadmap](#coverage-and-complexity-together) below). - -## Quick start - -```bash -# 1. Produce a report with your usual tool, e.g. for Rust: -cargo llvm-cov --lcov --output-path lcov.info - -# 2. Analyze a file with coverage enrichment: -mehen metrics src/parser.rs --coverage=lcov.info --pretty - -# 3. Or let mehen find the report by itself: -mehen metrics src/parser.rs --coverage - -# 4. Rank the least-tested files: -mehen top-offenders src --metric coverage.line --coverage - -# 5. Gate CI: fail when line coverage drops below 80%. -printf '[thresholds]\n"coverage.line" = 80\n' >> mehen.toml -mehen metrics src/parser.rs # the threshold itself triggers ingestion -``` - -Bare `--coverage` means `auto`: mehen [discovers report files](/metrics/coverage/auto-discovery) -in their idiomatic locations — including gitignored directories like `coverage/`, `target/`, and -`TestResults/` where they conventionally live. Six report formats are recognized by content, not -by filename (see [supported formats](/metrics/coverage/supported-formats)), and report paths are -reconciled with workspace paths by a dedicated -[path-matching layer](/metrics/coverage/path-matching). - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `coverage.line` | float | Percentage of instrumentable lines executed at least once, `0..=100`. | -| `coverage.line.covered` | int | Instrumentable lines executed at least once. | -| `coverage.line.total` | int | Instrumentable lines the report recorded for this file. | -| `coverage.branch` | float | Percentage of branch arms taken at least once, `0..=100`. | -| `coverage.branch.covered` | int | Branch arms taken at least once. | -| `coverage.branch.total` | int | Branch arms the report recorded. | -| `coverage.function` | float | Percentage of recorded functions executed at least once, `0..=100`. | -| `coverage.function.covered` | int | Functions executed at least once. | -| `coverage.function.total` | int | Functions the report recorded. | - -Every `coverage.*` metric is **higher-is-better**: a configured threshold is a *minimum*, and -`top-offenders` ranks the *least* covered files as the worst offenders. - -## Semantics - -- **Report-scope, engine-published.** Like the [`history.*` family](/metrics/history/overview), - coverage is not computed by a language analyzer — the engine injects it after static analysis, - from the ingested reports. It works for any of mehen's source languages, because the report - formats are language-agnostic. -- **Unmeasured is never 0%.** A file absent from every report publishes *no* coverage keys: it - ranks as least concerning and never fires a threshold. `top-offenders` renders the missing - score as `n/a`, while `mehen metrics` omits the coverage family from its output entirely. A - file present in a report with zero executed lines publishes an honest `0`. The distinction is - load-bearing — a fabricated 0% would fail every gate on every file the moment path matching - hiccuped. -- **Dimensions are independent.** A format that cannot measure a dimension leaves it absent: a Go - coverprofile has no branch or function records, so only `coverage.line` appears. -- **Per-function attribution.** Beyond the file totals, every function and closure space in the - [metric tree](/concepts/spaces) receives `coverage.line` and `coverage.branch` scoped to its - line span — so you can see *which* function inside a 60%-covered file is the untested one. -- **Merging.** Multiple reports (monorepo per-package runs, `.nyc_output` shards, re-run - artifacts) merge as a union of files with saturating-max hit counts: covered anywhere ⇒ - covered. Max is order-independent, so the result is deterministic regardless of which report is - found first. - -## Coverage and complexity together - -Coverage percentages are a *risk denominator*, not a quality score: high coverage does not prove -the tests assert anything (Inozemtseva & Holmes measured only weak-to-moderate correlation between -coverage and suite effectiveness once suite size is controlled), and Google's large-scale -experience report treats coverage as a heuristic adopted for insight, not as a target to chase. -The productive use is *directional* and *combinatorial*: - -- rank by `coverage.line` ascending to find blind spots (`top-offenders`), -- gate on a floor so blind spots stop growing (`[thresholds]`), -- and cross it with complexity: a trivial getter at 0% is noise; a cognitive-complexity-30 - function at 0% is where bugs hide. The per-function `coverage.line` mehen publishes is the - direct input to the CRAP index — `comp(m)² × (1 − cov(m)/100)³ + comp(m)` (Savoia & Evans) — - planned as a follow-up composite in this family. - -## See also - -- [Supported formats](/metrics/coverage/supported-formats) — the six report formats and how they - are detected and merged. -- [Auto-discovery](/metrics/coverage/auto-discovery) — how `--coverage` finds reports with zero - configuration. -- [Path matching](/metrics/coverage/path-matching) — how report paths map onto workspace files. -- [Line](/metrics/coverage/line), [branch](/metrics/coverage/branch), and - [function](/metrics/coverage/function) coverage — the individual metrics. - -## References - -- Ivanković, M., Petrović, G., Just, R., & Fraser, G. (2019). [Code coverage at - Google](https://research.google/pubs/code-coverage-at-google/). *ESEC/FSE 2019.* -- Inozemtseva, L., & Holmes, R. (2014). [Coverage is not strongly correlated with test suite - effectiveness](https://dl.acm.org/doi/10.1145/2568225.2568271). *ICSE 2014.* -- Savoia, A., & Evans, B. (2007). [The CRAP metric](https://www.artima.com/weblogs/viewpost.jsp?thread=210575). -- Marick, B. (1999). [How to misuse code coverage](http://www.exampler.com/testing-com/writings/coverage.pdf). -- Fowler, M. (2012). [TestCoverage](https://martinfowler.com/bliki/TestCoverage.html). *martinfowler.com.* diff --git a/docs/metrics/coverage/path-matching.mdx b/docs/metrics/coverage/path-matching.mdx deleted file mode 100644 index c64ea565..00000000 --- a/docs/metrics/coverage/path-matching.mdx +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: "Path matching" -description: "How report-spelled file paths — CI-absolute, Java-package, Go-module, ./-relative — are reconciled with the files mehen analyzes, and why naive lookups silently read 0%." -keywords: ["path matching", "coverage paths", "monorepo coverage", "SF record", "prefix stripping"] ---- - -Path matching is where coverage integrations *silently* fail. mehen sees workspace paths -(`src/app.py`); a report contains whatever the producing tool decided to write. When the two -disagree, a naive map lookup returns nothing for 100% of files — and every function suddenly -"reads" 0% covered. Both cargo-crap and grcov document this as the central hazard of coverage -ingestion; mehen treats it as a first-class layer with pinned regression tests. - -## What reports actually contain - -| Producer | Report path | Workspace file | -|---|---|---| -| CI-generated LCOV | `/home/runner/work/repo/repo/src/lib.rs` | `src/lib.rs` | -| JaCoCo (Java packages) | `com/example/Foo.java` | `src/main/java/com/example/Foo.java` | -| Go coverprofile (module import paths) | `github.com/org/repo/pkg/handler.go` | `pkg/handler.go` | -| Cobertura (`` roots) | `/w` + `src/app.py` | `src/app.py` | -| Clover | absolute `path` attribute (fallback: basename) | anything | -| Merged `lcov -a` legs | `./src/lib.rs` *and* `src/lib.rs` | one file | - -Note the direction flips: JaCoCo paths are a *suffix* of the workspace path, while Go and -CI-absolute paths *contain* the workspace path as their suffix. Any fixed prefix-stripping rule -handles one direction and breaks the other. - -## The matching algorithm - -Report paths are normalized once (forward slashes, `.`/`..` segments resolved lexically — so -`./`-spelled variants of one file merge instead of racing), then each analyzed file resolves in -two levels: - -1. **Canonical identity.** A report path spelled absolute that exists *on this machine* - canonicalizes to an on-disk identity; a query resolving to the same file matches exactly. - Same-machine runs — the common local case — always take this precise path. -2. **Component-suffix match.** Otherwise the query and a report entry match when one's component - list is a trailing subsequence of the other's — components, never bytes, so `/foo/bar.rs` can - never match `oofoo/bar.rs`. The longest suffix wins; exact component equality outranks partial - consumption (`src/lib.rs` prefers the `src/lib.rs` entry over `vendor/dep/src/lib.rs`). -3. **Root-relative retry.** When an absolute *query* matches nothing — a local checkout being - compared against a report written on a CI machine, where neither absolute spelling contains - the other — the query is re-spelled relative to its repository root and resolved again. This - is grcov's `--prefix-dir` idea, automated and scoped to the repository boundary rather than - applied as a blanket basename match (which would happily hand `tests/util.py` the coverage of - `src/util.py`). - -Two rules are deliberately conservative: - -- **Relative report paths are never resolved against the working directory.** Doing so would - silently bind them to whatever happens to exist under the directory mehen was launched from — - cargo-crap pins the same invariant with a dedicated regression test, and so does mehen. -- **A genuine tie is unmeasured, not a coin flip.** When two distinct report entries match a - query with equal specificity (`a/sub/mod.rs` vs `b/sub/mod.rs` for the query `sub/mod.rs`), - mehen logs the ambiguity and treats the file as unmeasured rather than resolving by map order. - Deterministic *and* honest beats accidentally-right. - -## Failure visibility - -Because unmeasured files publish nothing (never 0% — see the -[overview](/metrics/coverage/overview#semantics)), a path-matching failure cannot fabricate gate -violations; it surfaces instead as: - -- `n/a` scores in `top-offenders` output and absent `coverage` families in `metrics` JSON, -- an info log naming how many ingested report entries the file was checked against, -- a warning on ambiguous matches naming the candidate count. - -If a report that should match reads as unmeasured, check the three usual suspects: the report was -generated in a different checkout layout (regenerate, or use explicit `--coverage=` from -the matching root), the workspace file is spelled through a symlinked directory (canonicalization -handles most of this), or two same-named files genuinely tie (make the report paths more specific -— e.g. configure the tool to emit paths relative to the repo root). - -## References - -- [cargo-crap — the path-matching problem](https://github.com/minikin/cargo-crap#the-path-matching-problem) - — the failure mode this design descends from, including the CWD-resolution regression. -- [grcov path mapping options](https://github.com/mozilla/grcov#usage) — `--prefix-dir`, - `--path-mapping`, `--ignore-not-existing`: the same problem at Firefox scale. -- [geninfo(1)](https://ltp.sourceforge.net/coverage/lcov/geninfo.1.php) — `SF:` record semantics. -- [JaCoCo XML report documentation](https://www.jacoco.org/jacoco/trunk/doc/) — package-relative - `sourcefile` naming. diff --git a/docs/metrics/coverage/supported-formats.mdx b/docs/metrics/coverage/supported-formats.mdx deleted file mode 100644 index 0febff33..00000000 --- a/docs/metrics/coverage/supported-formats.mdx +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: "Supported formats" -description: "The six coverage-report formats mehen parses — LCOV, Go coverprofile, Istanbul JSON, JaCoCo XML, Clover XML, Cobertura XML — and how they are detected and merged." -keywords: ["lcov", "cobertura", "jacoco", "clover", "istanbul", "coverprofile", "coverage formats"] ---- - -mehen parses six report formats in-house — no external tools, no network — covering the default -or one-flag-away output of the mainstream test runners in every language mehen analyzes. The -parsers are streaming (large monorepo reports never sit fully in memory) and were adapted from -the MIT-licensed [covrs](https://github.com/scttnlsn/covrs) project. - -## The formats - -| Format | Shape | Typical producers | Dimensions | -|---|---|---|---| -| **LCOV** | line records (`SF:`/`DA:`/`BRDA:`/`FN:`) | cargo-llvm-cov, tarpaulin, `lcov`/`geninfo` (C/C++), Jest & c8 & nyc (`lcov` reporter), simplecov-lcov (Ruby), coverlet (`lcov` format), coverage.py (`coverage lcov`) | line, branch, function | -| **Go coverprofile** | `mode:` header + per-block ranges | `go test -coverprofile` | line | -| **Istanbul JSON** | `statementMap`/`branchMap`/`fnMap` objects | Jest, Vitest, nyc, c8 (`coverage-final.json`) | line, branch, function | -| **JaCoCo XML** | `` → `` → `` | JaCoCo (Maven/Gradle), Kotlin Kover, Pester 5 (PowerShell) | line, branch, function | -| **Clover XML** | `` → `` → `` | PHPUnit, OpenClover, Jest/Vitest (`clover` reporter) | line, branch (from `cond` lines), function (from `method` lines) | -| **Cobertura XML** | `` → `` | coverage.py (`coverage xml`), coverlet / `dotnet test`, gcovr, tarpaulin (`--out xml`) | line, branch (from `condition-coverage`), function (from ``) | - -## Detection is content-based - -Filenames lie: Pester writes JaCoCo XML into `coverage.xml`, coverage.py writes Cobertura XML into -the same name, and `.info` files are occasionally GNU documentation. mehen therefore *sniffs* the -first 4 KiB of every candidate and requires format-specific content markers before believing a -file, in a fixed priority order chosen so no format can false-positive on another's output: - -1. **LCOV** — `SF:` plus `DA:`/`FN:` records. -2. **Go coverprofile** — a `mode: set|count|atomic` header or `file.go:N.N,N.N …` block lines. -3. **Istanbul** — a JSON object containing `"statementMap"` and `"fnMap"`. -4. **JaCoCo** — `` argument goes through the same detection; a file no parser -recognizes is a hard error, while an auto-discovered candidate that fails sniffing is silently -recorded as rejected (that is business as usual for e.g. `coverage.txt` text summaries). - -## Normalization and merge semantics - -Formats disagree about granularity, so parsed records are normalized into one model — per-file -line hits, branch arms, and function records: - -- **Statements → lines.** Istanbul statements and Go blocks map onto lines; when several - statements share a line, the *maximum* hit count wins. -- **Branch encodings → arms.** LCOV `BRDA` records, Cobertura `condition-coverage="50% (1/2)"` - fractions, JaCoCo `mb`/`cb` counters, Clover `truecount`/`falsecount` pairs, and Istanbul `b` - arrays all become flat *branch arms* (see [branch coverage](/metrics/coverage/branch) for what - that folding means). -- **Duplicate records collapse.** `lcov -a`-merged tracefiles repeat `DA` lines; Cobertura emits - the same line under both `` and `` — duplicates keep the maximum. -- **Cross-report merge.** All ingested reports fold into one dataset: union of files, - saturating-max hits for records shared between reports ("covered anywhere ⇒ covered"). Max is - commutative and associative, so the merged result is independent of discovery order — - determinism is a hard requirement for reproducible CI gates. Hit-count *summing* was rejected - because re-running the same suite twice would double every count; newest-file-wins was rejected - because git checkouts do not preserve mtimes. - -## Hardening - -Coverage artifacts are ingested from build directories that other tools write into, so the -parsers are defensive by construction: branch expansion is capped at 1,024 arms per line, Go -block spans at 100,000 lines, report files at 256 MiB; XML parsing never resolves DTDs or -external entities (billion-laughs and XXE are structurally inert, and a regression test pins -that); and a malformed report is a per-file diagnostic, never a crash. - -## What about raw instrumentation output? - -`.profraw`/`.gcda` (LLVM/GCC counters), SimpleCov's `.resultset.json`, c8's raw V8 dumps in -`coverage/tmp/`, and coverlet's proprietary `coverage.json` are *not* report formats — decoding -them requires the compiled binaries or the producing tool's internals. Export a report instead -(`cargo llvm-cov --lcov`, `coverage xml`, `--coverageReporters=lcov`, …); grcov takes the same -report-level stance for Firefox-scale ingestion. - -## References - -- [geninfo(1) — the LCOV tracefile format](https://ltp.sourceforge.net/coverage/lcov/geninfo.1.php). *Linux Test Project.* -- [The cover story](https://go.dev/blog/cover) — Go's coverage design and the coverprofile format. *The Go Blog.* -- [Istanbul.js](https://istanbul.js.org/) and the [istanbuljs coverage object](https://github.com/istanbuljs/istanbuljs). -- [JaCoCo XML report documentation](https://www.jacoco.org/jacoco/trunk/doc/). -- [OpenClover documentation](https://openclover.org/documentation) — the Clover XML schema. -- [Cobertura](https://cobertura.github.io/cobertura/) — the original tool whose XML schema became - the de-facto interchange format. -- [mozilla/grcov](https://github.com/mozilla/grcov) — prior art for multi-format coverage - aggregation at scale. diff --git a/docs/metrics/history/age.mdx b/docs/metrics/history/age.mdx deleted file mode 100644 index f8d175e6..00000000 --- a/docs/metrics/history/age.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Code age" -description: "Months since a file's last change — a stability proxy with a deterministic clock." -keywords: ["code age", "stability", "code-maat", "crime scene"] ---- - -**Code age** is the time since a file last changed. It is a stability proxy: long-stable code has -had its bugs shaken out and can often be treated as settled, while recently-churned code is where -the risk lives. Tornhill uses age to find "islands of stability" worth extracting into packages — -and, inversely, old code that suddenly starts changing again deserves attention. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `history.age_months` | float | `(analyzed revision's committer time − file's last change) ÷ 2,629,746 s` (the average Gregorian month), clamped at zero. | - -## The determinism wrinkle - -Age depends on "now" — and wall-clock time would make the same repository state produce different -numbers on every run. mehen pins "now" to the **analyzed revision's committer timestamp**, so -results are reproducible across runs and machines. The clamp at zero guards against clock-skewed -commit metadata (a "last change" recorded after the analyzed revision). - -## How to read it - -| Signal | Interpretation | -|---|---| -| Old file, suddenly in a diff | Settled code being reopened — check the change against long-standing assumptions. | -| Very young age, high [churn](/metrics/history/churn) | Actively evolving code; expect follow-up changes. | -| Uniformly young ages across a module | The module hasn't stabilized — consider whether its design has converged before building on it. | - -## References - -- code-maat `age` analysis ([repo](https://github.com/adamtornhill/code-maat)). -- Tornhill, A. (2015). *Your Code as a Crime Scene.* Pragmatic Bookshelf. - -## See also - -- [Churn](/metrics/history/churn) — how much has moved, regardless of when. -- [Bug risk](/metrics/history/bug-risk) — time-decayed weighting of bug-fix history. diff --git a/docs/metrics/history/bug-risk.mdx b/docs/metrics/history/bug-risk.mdx deleted file mode 100644 index d7f792f7..00000000 --- a/docs/metrics/history/bug-risk.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Bug risk" -description: "Bug-fixing commit count and Google's Time-Weighted Risk — where fixes keep landing." -keywords: ["bug prediction", "time-weighted risk", "twr", "fixcache", "google"] ---- - -Where bugs were fixed before is where bugs tend to appear again. mehen ships the two transparent -forms of this signal from Google's bug-prediction study: a plain **bug-fix commit count** (the -"Rahman algorithm" — which Google's developers preferred for its transparency, and which performed -nearly as well as anything fancier) and **Time-Weighted Risk (TWR)**, which weights each fix by how -recently it happened so that a file's ancient sins eventually stop counting against it. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `history.bugfix_commits` | int | Commits touching the file whose message matches the bug-fix heuristic. | -| `history.twr` | float | `Σᵢ 1 / (1 + e^(−12·tᵢ + 12))` over the file's bug-fixing commits, where `tᵢ` is each fix's time normalized to `[0, 1]` across the walked history (0 = oldest commit, 1 = analyzed revision). | - -A fix at the analyzed revision contributes ~0.5; a fix at the start of history contributes -effectively zero (~e⁻¹²). TWR is quantized to 10⁻⁹ before publication so that identical -repositories produce bit-identical values across platforms. - -## The bug-fix heuristic - -TWR's honest weakness (acknowledged in the primary source) is that "bug-fixing commit" needs a -definition. mehen uses a transparent whole-word match on the commit message: `fix`, `fixes`, -`fixed`, `fixing`, `fixup`, `hotfix`, `bugfix`, `bug`, `bugs`. Word-boundary matching keeps -`prefix` and `debugging` from counting; issue references like `#123` are deliberately **not** -treated as bug markers, because on GitHub-style squash merges every PR commit carries one. - -## How to read it - -| Signal | Interpretation | -|---|---| -| High `bugfix_commits`, high TWR | Fixes keep landing here *recently* — the strongest "this file will bite again" signal. | -| High `bugfix_commits`, low TWR | A formerly buggy file that has been quiet — probably rehabilitated. | -| Rising TWR in a diff | The change touches a file in an active bug-fixing phase; extra review scrutiny is cheap insurance. | - -Present this signal modestly: Google's own deployment of TWR produced no significant change in -developer behavior. It is a review-attention hint, not a verdict. - -## References - -- Lewis, C., Lin, Z., Sadowski, C., Zhu, X., Ou, R. & Whitehead Jr., E. J. (2013). *Does Bug - Prediction Support Human Developers? Findings from a Google Case Study.* ICSE 2013. - [PDF](https://users.soe.ucsc.edu/~ejw/papers/lewis-icse-2013.pdf). -- Rahman, F., Posnett, D., Hindle, A., Barr, E. & Devanbu, P. (2011). *BugCache for inspections: - hit or miss?* ESEC/FSE 2011 — the frequency-ranking baseline. - -## See also - -- [Commit frequency](/metrics/history/commit-frequency) — all commits, not just fixes. -- [Code age](/metrics/history/age) — general recency, without the bug-fix filter. diff --git a/docs/metrics/history/churn.mdx b/docs/metrics/history/churn.mdx deleted file mode 100644 index 029383c7..00000000 --- a/docs/metrics/history/churn.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Code churn" -description: "Lines added and removed over a file's history, absolute and normalized by file size." -keywords: ["churn", "relative churn", "code churn", "nagappan", "defect prediction"] ---- - -**Code churn** measures how much a file has changed over its history. mehen ships both variants -from the literature: - -- **Absolute churn** — lines added + lines removed, summed across every commit that touched the - file. Matches code-maat's `abs-churn` and PyDriller's `(added + removed)` variant. -- **Relative churn** — absolute churn normalized by the file's size at the analyzed revision. - Nagappan & Ball showed that *relative* churn predicts defect density well while *absolute* - churn is a poor predictor: 500 churned lines mean something very different in a 100-line file - than in a 10,000-line one. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `history.churn.abs` | int | `Σ (added + removed)` across the file's walked history. | -| `history.churn.relative` | float | `churn.abs ÷ max(size, 1)` where size is the file's code-line count at the same revision. | - -The denominator is family-aware: source-code files use [`loc.sloc`](/metrics/code/sloc), SQL files -use `sql.loc.code`, Markdown files use `markdown.loc.tloc`. A file whose analyzer published no -line count falls back to a denominator of 1, keeping the value finite and deterministic. - -`history.churn.relative` is one of the **default [`mehen diff`](/commands/diff) columns**. - -## Semantics - -- Churn follows the file across **renames** — a renamed file keeps its accumulated churn instead - of resetting to zero. -- **Merge commits churn nothing** (their first-parent diff would double-count every line already - attributed to the merged commits — the `git log --no-merges` convention). -- **Binary and oversized blobs churn zero lines**: anything failing a NUL sniff or larger than - 8 MiB is counted the way `git log --numstat` reports it (`-`), so a committed archive doesn't - count its bytes as "source lines". - -## How to read it - -| Signal | Interpretation | -|---|---| -| High relative churn, small file | The file is being rewritten over and over — a stability problem or a design that keeps not fitting. | -| High absolute churn, low relative churn | A big file with proportionate change — usually fine. | -| Rising churn in a diff | This change adds to an already-turbulent history; review accordingly. | - -## References - -- Nagappan, N. & Ball, T. (2005). *Use of Relative Code Churn Measures to Predict System Defect - Density.* ICSE 2005. [DOI](https://dl.acm.org/doi/10.1145/1062455.1062514). -- [PyDriller process metrics](https://pydriller.readthedocs.io/en/latest/processmetrics.html). -- code-maat `abs-churn` ([repo](https://github.com/adamtornhill/code-maat)). - -## See also - -- [Commit frequency](/metrics/history/commit-frequency) — how *often*, not how *much*. -- [Hotspot](/metrics/history/hotspot) — change frequency × complexity. diff --git a/docs/metrics/history/commit-frequency.mdx b/docs/metrics/history/commit-frequency.mdx deleted file mode 100644 index 63db619e..00000000 --- a/docs/metrics/history/commit-frequency.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Commit frequency" -description: "How many commits touched a file — the change-frequency half of the hotspot signal." -keywords: ["commit frequency", "change frequency", "revisions", "hotspot"] ---- - -**Commit frequency** counts the commits that touched a file over its walked history. Change -frequency alone is a surprisingly strong signal — Tornhill's central observation is that most code -is rarely touched, so the files a team returns to over and over are where structural problems (and -future changes) concentrate. In Google's bug-prediction study, simply ranking files by the count of -their bug-fixing commits performed nearly as well as more sophisticated schemes. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `history.commit_frequency` | int | Non-merge commits that touched the file, following renames. | - -## Semantics - -- **Renames don't reset the count** — a renamed file keeps its accumulated commit history. -- **Merge commits are not counted** (the `git log --no-merges` convention): the merged commits - themselves are. -- Each commit counts once per file it touches. - -## How to read it - -Raw frequency is context-dependent — a 10-commit file in a young repository can be hotter than a -100-commit file in a decade-old one. Its main use is comparative (which files lead the ranking?) -and as the change-frequency input to the [hotspot composite](/metrics/history/hotspot). - -## References - -- Tornhill, A. (2015). *Your Code as a Crime Scene.* Pragmatic Bookshelf. -- Lewis, C. et al. (2013). *Does Bug Prediction Support Human Developers?* ICSE 2013 — the - "Rahman algorithm" finding on plain frequency ranking. - -## See also - -- [Hotspot](/metrics/history/hotspot) — frequency × cognitive complexity. -- [Churn](/metrics/history/churn) — line volume rather than commit count. diff --git a/docs/metrics/history/hotspot.mdx b/docs/metrics/history/hotspot.mdx deleted file mode 100644 index 169bc609..00000000 --- a/docs/metrics/history/hotspot.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "Hotspot" -description: "Cognitive complexity × commit frequency — files that are both fragile and frequently touched." -keywords: ["hotspot", "codescene", "tornhill", "refactoring targets", "complexity"] ---- - -A **hotspot** is a file where complexity and change frequency *overlap*: complicated code that the -team also touches all the time. That intersection is the highest-leverage refactoring target — -CodeScene reports that top hotspots typically occupy ~5% of a codebase yet absorb ~18% of -development effort and ~23% of fixed defects. Complexity alone over-flags stable legacy code -nobody touches; frequency alone flags churning-but-trivial files; the product flags what actually -costs money. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `history.hotspot` | float | `cognitive.sum × history.commit_frequency`. | - -`history.hotspot` is one of the **default [`mehen diff`](/commands/diff) columns**. - -## Better than the classic form - -The open hotspot definition from the literature uses **LOC** as its complexity proxy because -that's what a history-mining tool can compute without parsing code. mehen has real parsers, so it -upgrades the proxy to [cognitive complexity](/metrics/code/cognitive) summed over the file — a -measure of how hard the code actually is to understand, not merely how long it is. The complexity -input is family-aware: SQL files use `sql.cognitive_complexity` and Markdown files use their own -cognitive-load measure, so hotspots aren't degenerate outside the shared source-code suite. - -Note that CodeScene's *prioritization and ranking layer* on top of this signal is proprietary and -probabilistic; mehen deliberately implements only the open, reproducible -complexity-times-frequency overlap. - -## How to read it - -| Signal | Interpretation | -|---|---| -| High hotspot, rising in a diff | You are adding complexity to a file the team constantly revisits — the strongest refactoring signal this family produces. | -| High complexity, hotspot near zero | Complex but stable — usually not worth proactive refactoring. | -| Hotspot dropping in a diff | A refactor is paying off exactly where it matters. | - -## References - -- Tornhill, A. (2018). *Software Design X-Rays.* Pragmatic Bookshelf. -- [CodeScene hotspots documentation](https://codescene.io/docs/guides/technical/hotspots.html). - -## See also - -- [Cognitive complexity](/metrics/code/cognitive) — the complexity input. -- [Commit frequency](/metrics/history/commit-frequency) — the change-frequency input. diff --git a/docs/metrics/history/overview.mdx b/docs/metrics/history/overview.mdx deleted file mode 100644 index 3deed1a5..00000000 --- a/docs/metrics/history/overview.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: "History metrics overview" -description: "Git process metrics: churn, code age, ownership, hotspots, change coupling, and bug risk computed from repository history." -keywords: ["history metrics", "process metrics", "churn", "hotspot", "ownership", "code age", "git"] ---- - -The `history.*` family reports **process metrics** — signals derived from how a file *changed over -time* rather than from its current content. The empirical literature is consistent that process -metrics out-predict static code metrics for defects while costing far less to compute; mehen pairs -them with its real complexity metrics to get composites (like the -[hotspot](/metrics/history/hotspot)) that neither side can produce alone. - -## What mehen emits - -| Metric | Key | Description | -|---|---|---| -| [Churn](/metrics/history/churn) | `history.churn.abs` | Lines added + removed across the file's history. | -| [Churn](/metrics/history/churn) | `history.churn.relative` | Absolute churn normalized by the file's current size — the defect-predictive form. | -| [Code age](/metrics/history/age) | `history.age_months` | Months since the file's last change, relative to the analyzed revision. | -| [Ownership](/metrics/history/ownership) | `history.authors` | Distinct authors who ever touched the file. | -| [Ownership](/metrics/history/ownership) | `history.minor_contributors` | Authors contributing < 5% of the file's added lines. | -| [Ownership](/metrics/history/ownership) | `history.ownership` | The top contributor's share of the file's added lines. | -| [Commit frequency](/metrics/history/commit-frequency) | `history.commit_frequency` | Commits that touched the file. | -| [Hotspot](/metrics/history/hotspot) | `history.hotspot` | `cognitive.sum × commit_frequency` — fragile *and* frequently touched. | -| [Sum of coupling](/metrics/history/sum-of-coupling) | `history.sum_of_coupling` | How often the file changes together with other files. | -| [Bug risk](/metrics/history/bug-risk) | `history.bugfix_commits` | Bug-fixing commits that touched the file. | -| [Bug risk](/metrics/history/bug-risk) | `history.twr` | Google's Time-Weighted Risk — bug fixes weighted toward the recent past. | - -Two of these — `history.hotspot` and `history.churn.relative` — are part of the -**default [`mehen diff`](/commands/diff) columns** for source-code files. - -## How the history walk works - -History metrics cannot come from a language analyzer (which sees one file's content at one -revision). Instead, mehen walks the repository history reachable from the analyzed revision once -per revision and folds per-file statistics into each file's metric set after static analysis: - -- **Deterministic by construction.** The walk is a pure function of the repository state at the - analyzed revision: commits are visited in `--date-order` topological order, rename matching uses - pinned `gix` rewrite options over raw object bytes (ignoring local diff config and attributes), - and "now" for [code age](/metrics/history/age) is the analyzed revision's committer timestamp — - never wall-clock time. Two machines analyzing the same commit always report identical values. -- **Rename-aware identity.** A file renamed along the way accumulates **one** history: statistics - follow the file across renames instead of resetting. Delete-then-recreate sequences split - identity, so a new file that reuses an old path does not inherit the dead file's history — - including through merges, parallel branches, and path reuse. -- **Merges are identity-only.** Merge commits contribute no churn (matching - `git log --no-merges` and code-maat), but renames performed by conflict resolution still - establish file identity. -- **Binary-safe churn.** Blobs that are binary (NUL sniff) or larger than 8 MiB churn zero lines, - mirroring `git log --numstat` reporting `-` for binary files. - -## Requirements - -The walk needs the actual history: run against a **full clone**. In GitHub Actions use -`actions/checkout` with `fetch-depth: 0`. Because the walk costs one tree diff per commit, mehen -only runs it when a `history.*` metric is actually requested — a SQL-only or docs-only diff never -pays for it. - -## In diffs - -[`mehen diff`](/commands/diff) walks the history of **both** revisions, so history columns carry -real deltas — the commits and churn a file gained between base and head — rather than comparing -against a phantom zero baseline. - -## References - -- Rahman, F. & Devanbu, P. (2013). *How, and why, process metrics are better.* ICSE 2013. -- Tornhill, A. (2015). *Your Code as a Crime Scene.* Pragmatic Bookshelf. -- [PyDriller process metrics](https://pydriller.readthedocs.io/en/latest/processmetrics.html) — - the reference implementation for churn and ownership semantics. -- [code-maat](https://github.com/adamtornhill/code-maat) — Tornhill's original analyses (age, - authors, coupling, churn). diff --git a/docs/metrics/history/ownership.mdx b/docs/metrics/history/ownership.mdx deleted file mode 100644 index 9ba60de7..00000000 --- a/docs/metrics/history/ownership.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Ownership & authorship" -description: "Distinct authors, minor contributors, and the top contributor's share of a file." -keywords: ["ownership", "authors", "minor contributors", "bird", "knowledge distribution"] ---- - -**Ownership metrics** describe *who* wrote a file. Number-of-authors is one of the most-validated -defect signals in the literature, and Bird et al. showed that files with many **minor -contributors** — people who wrote only a sliver of the code — have significantly more defects, -while a strong top contributor is protective. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `history.authors` | int | Distinct authors who touched the file with any change. | -| `history.minor_contributors` | int | Authors whose added lines are < 5% of the file's total added lines (PyDriller's fixed threshold). | -| `history.ownership` | float | The top contributor's share of the file's added lines, in `[0, 1]`. | - -## Semantics - -- **Authorship = added lines.** Ownership and the minor-contributor classification count *lines - added* per author across the walked history — matching PyDriller, the reference implementation. - Deleting someone else's code or renaming a file does not count as writing code, so a - deletion-only toucher appears in `history.authors` but is never misclassified as a sub-5% "minor - contributor" of code they didn't write. -- **Identity** is the author's lower-cased email (falling back to the name for commits without - one). -- A history of pure renames and deletions has no added lines; ownership is then reported as `0` - rather than dividing by zero. - -## How to read it - -| Signal | Interpretation | -|---|---| -| `ownership` near 1.0, 1–2 authors | Strong ownership — but also a bus-factor risk worth knowing about. | -| Many `minor_contributors` | The classic defect signal: lots of drive-by edits, no steward. | -| `authors` growing in a diff | The file is becoming shared infrastructure; its implicit conventions may need writing down. | - -## References - -- Bird, C., Nagappan, N., Murphy, B., Gall, H. & Devanbu, P. (2011). *Don't Touch My Code! - Examining the Effects of Ownership on Software Quality.* ESEC/FSE 2011. -- [PyDriller process metrics](https://pydriller.readthedocs.io/en/latest/processmetrics.html) — - contribution-based ownership and the 5% minor-contributor threshold. -- code-maat `authors`, `main-dev`, `entity-ownership` ([repo](https://github.com/adamtornhill/code-maat)). - -## See also - -- [Commit frequency](/metrics/history/commit-frequency) — how often the file changes at all. diff --git a/docs/metrics/history/sum-of-coupling.mdx b/docs/metrics/history/sum-of-coupling.mdx deleted file mode 100644 index e3c980d7..00000000 --- a/docs/metrics/history/sum-of-coupling.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Sum of coupling" -description: "How often a file changes together with other files — an architectural-significance signal." -keywords: ["change coupling", "temporal coupling", "sum of coupling", "soc", "code-maat"] ---- - -**Change coupling** (temporal coupling) is the tendency of files to change *together* — a -dependency signal that no static analysis can see, because it captures logical coupling through -copy-paste, shared conventions, or protocol mirroring, not just imports. **Sum of Coupling (SoC)** -collapses the pairwise idea to a single number per file: how much company a file keeps when it -changes. Files with a high SoC sit at the architectural center of gravity — change them and -something else usually has to move too. - -## What mehen emits - -| Key | Type | Description | -|---|---|---| -| `history.sum_of_coupling` | int | For each commit touching the file, the number of *other* files in that commit, summed over the file's history. | - -## Semantics - -- Commits touching **more than 30 files** don't contribute (code-maat's changeset-noise - threshold): bulk reformats and license-header sweeps would otherwise dominate every file's - score. -- Merge commits don't contribute (their changesets replay the merged commits). -- Renames keep accumulating onto the surviving file's identity. - -mehen ships the per-file SoC aggregate rather than pairwise coupling percentages — SoC fits the -per-file metric model, and the research recommends it as the pragmatic first step before full -pairwise analysis. - -## How to read it - -| Signal | Interpretation | -|---|---| -| Top-of-ranking SoC | The file is an architectural hub. Interface changes here are expensive; treat its design with corresponding care. | -| High SoC on a file that "shouldn't" be central | Hidden logical coupling — often duplicated knowledge that wants a shared abstraction. | -| Low SoC everywhere | Changes are well-localized; module boundaries are doing their job. | - -## References - -- code-maat `soc` / `coupling` analyses ([repo](https://github.com/adamtornhill/code-maat)). -- Tornhill, A. (2015). *Your Code as a Crime Scene.* Pragmatic Bookshelf — temporal coupling - chapters. -- [CodeScene change-coupling documentation](https://codescene.io/docs/guides/technical/temporal-coupling.html). - -## See also - -- [Commit frequency](/metrics/history/commit-frequency) — how often the file changes at all. -- [Hotspot](/metrics/history/hotspot) — where frequency meets complexity. diff --git a/docs/metrics/markdown/artifact-debt.mdx b/docs/metrics/markdown/artifact-debt.mdx deleted file mode 100644 index 2dfdef38..00000000 --- a/docs/metrics/markdown/artifact-debt.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Artifact Debt" -description: "Cost of unlabelled, unparsable, oversized, unexplained, or externally fragile artifacts." -keywords: ["artifact debt", "code fences", "documentation hygiene"] ---- - -Artifacts (code fences, tables, diagrams, images, math blocks, raw HTML/MDX) are not bad on their own — -artifact **debt** is high when artifacts are unlabelled, unparsable, oversized, unexplained, or -externally fragile. - -## Formula - -```text -ArtifactDebtScore = clamp01( - 0.25 · sat(unlabelled_code_fences / max(1, code_fences); 0.05, 0.50) - + 0.20 · sat(artifact_parse_errors / max(1, artifacts); 0.00, 0.20) - + 0.15 · sat(oversized_artifacts / max(1, artifacts); 0.05, 0.30) - + 0.15 · sat(unexplained_artifacts / max(1, artifacts); 0.10, 0.60) - + 0.15 · sat(raw_html_or_mdx_lines / max(1, DLOC); 0.05, 0.25) - + 0.10 · sat(external_artifact_links/ max(1, artifacts); 0.10, 0.60) -) -``` - -## What each component flags - -- **Unlabelled code fences** — `` ``` `` instead of `` ```python `` (defeats syntax highlighting and - embedded-analyzer dispatch). -- **Parse errors** — broken Mermaid / Math / TOML / JSON inside artifacts. -- **Oversized artifacts** — code blocks or tables far above the document's median. -- **Unexplained artifacts** — no prose within ±2 blocks of the artifact. -- **Raw HTML / MDX density** — high HTML/MDX line ratio relative to DLOC. -- **External artifact links** — images and embeds pointing to external hosts (fragile under outages). - -## How DMI uses it - -Artifact Debt contributes to [DMI](/metrics/markdown/dmi) via the `A_norm` term. - -## References - -- Cunningham, W. (1992). *The WyCash Portfolio Management System.* OOPSLA '92 Experience Report — - origin of the "technical debt" metaphor this metric extends to documentation artifacts. - [DOI](https://doi.org/10.1145/157710.157715). -- Kruchten, P., Nord, R. L. & Ozkaya, I. (2012). *Technical Debt: From Metaphor to Theory and - Practice.* IEEE Software 29(6): 18–21. - [DOI](https://doi.org/10.1109/MS.2012.167). - -## See also - -- [Visual Scaffold](/metrics/markdown/visual-scaffold) — diagram-specific scaffolding. -- [Table Burden](/metrics/markdown/table-burden) — table-specific burden. diff --git a/docs/metrics/markdown/dmi.mdx b/docs/metrics/markdown/dmi.mdx deleted file mode 100644 index f705d416..00000000 --- a/docs/metrics/markdown/dmi.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "DMI — Documentation Maintainability Index" -description: "Composite 0–100 score blending Markdown Halstead, MCC, MRPC, link/table/artifact debt, section balance, filler risk, and good scaffold." -keywords: ["dmi", "documentation maintainability", "composite score", "documentation quality"] ---- - -**DMI** summarizes how maintainable a Markdown file is as a repository artifact. It is the documentation -analogue of the [Maintainability Index](/metrics/code/mi) for source code. - -## Formula - -Components are first normalized to `[0, 1]`, then combined: - -```text -DMI = clamp01( - 1 - − 0.18 · V_norm (Markdown Halstead volume) - − 0.18 · M_norm (MCC) - − 0.10 · R_norm (MRPC) - − 0.16 · L_norm (Link Debt) - − 0.10 · T_norm (Table Burden) - − 0.10 · A_norm (Artifact Debt) - − 0.10 · S_norm (Poor Section Balance) - − 0.12 · F_norm (Filler / Lazy Risk) - + 0.10 · G_norm (Good Scaffold) -) · 100 -``` - -## Bands - -| DMI | Band | Meaning | -|---|---|---| -| 85–100 | Highly maintainable | Easy to extend; low review cost. | -| 70–84 | Good | Normal repository documentation. | -| 50–69 | Needs attention | Inspect top contributors. | -| 30–49 | Hard | Review burden is real. | -| 0–29 | Documentation debt | Likely refactor / split candidate. | - -## DMI is not "usefulness" - -A long, linear filler document can score respectable DMI while scoring high on -[Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk). A short dense architecture note can score low -DMI but be extremely high-value. DMI measures maintainability burden, not value. - -The combined **DMI × RCI × Filler Risk** matrix -([review criticality](/metrics/markdown/review-criticality-index)) is the canonical way to read -DMI in context. - -## References - -- Oman, P. & Hagemeister, J. (1992). *Metrics for assessing a software system's maintainability.* - IEEE Conference on Software Maintenance — the source-code MI ancestor. - -## See also - -- [Maintainability Index](/metrics/code/mi) — the source-code analogue. -- [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk) — the orthogonal "is this filler?" axis. -- [Review Criticality Index](/metrics/markdown/review-criticality-index) — combines DMI with deltas. diff --git a/docs/metrics/markdown/effective-content-units.mdx b/docs/metrics/markdown/effective-content-units.mdx deleted file mode 100644 index 03b943e6..00000000 --- a/docs/metrics/markdown/effective-content-units.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "Effective Content Units (ECU)" -description: "Review-mass normalization across prose, code blocks, tables, diagrams, math, and HTML/MDX." -keywords: ["effective content units", "ecu", "review mass", "documentation size"] ---- - -**ECU** normalizes review mass so that a small-but-dense ADR is not overshadowed by a long linear README -in volume comparisons. It blends prose word count with weighted contributions from code, tables, -diagrams, math, and raw HTML/MDX. - -## Formula - -```text -ECU = W / 240 - + 0.35 · CLOC - + 0.06 · table_cells - + 0.40 · diagram_nodes - + 0.25 · diagram_edges - + 0.12 · math_tokens - + 0.20 · raw_html_or_mdx_lines -``` - -The `W / 240` term anchors on the standard adult silent-reading-rate scale (~240 words per minute). -Other coefficients are derived to make a small, dense diagram contribute roughly as much as the -equivalent paragraph of explanation. - -## Interpretation bands - -| ECU | Meaning | -|---|---| -| `< 5` | Small. | -| `5–20` | Normal. | -| `20–60` | Large. | -| `> 60` | Documentation subsystem — likely wants a split. | - -## Why not just word count? - -Word count systematically undercounts artifact-heavy docs (architecture diagrams, big tables, code-only -references) and over-weights prose-heavy docs that may be relatively easy to skim. ECU was introduced so -"dense vs. linear" shows up directly in volume comparisons. - -## References - -- Trauzettel-Klosinski, S. & Dietz, K. (2012). *Standardized assessment of reading performance: the - new International Reading Speed Texts IReST.* Investigative Ophthalmology & Visual Science 53(9): - 5452–5461 — the silent-reading-rate evidence base that anchors the `W / 240` term. - [DOI](https://doi.org/10.1167/iovs.11-8284). -- Brysbaert, M. (2019). *How many words do we read per minute? A review and meta-analysis of reading - rate.* Journal of Memory and Language 109: 104047. - [DOI](https://doi.org/10.1016/j.jml.2019.104047). - -## See also - -- [LOC family](/metrics/markdown/loc-family) — components that feed ECU. -- [Section tree](/metrics/markdown/section-tree) — per-section ECU aggregation. diff --git a/docs/metrics/markdown/evidence-coverage.mdx b/docs/metrics/markdown/evidence-coverage.mdx deleted file mode 100644 index b3510671..00000000 --- a/docs/metrics/markdown/evidence-coverage.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: "Evidence Coverage" -description: "Per-section structural support density across links, code, tables, and diagrams." -keywords: ["evidence coverage", "documentation", "anchors", "support"] ---- - -**Evidence Coverage** measures structural support for each section. Where -[Repository Grounding](/metrics/markdown/repository-grounding) is a document-level signal, Evidence -Coverage is per-section, so one well-linked section cannot hide many unsupported ones. - -## Formula - -```text -anchor_density_s = evidence_anchors_s / max(1, W_s / 250) -section_evidence_s = sat(anchor_density_s; 0.2, 1.5) - -EvidenceCoverageScore = - 0.5 · mean(section_evidence_s) - + 0.5 · p25(section_evidence_s) -``` - -## What is an "evidence anchor" - -For each section, mehen counts: - -- Resolved internal anchors. -- Resolved relative repository links. -- Code fences with explicit language tags. -- Diagram blocks (Mermaid, GraphViz, etc.). -- Table headers. -- Footnote references. - -These are normalized against the section's word count (per 250-word window). - -## Why the 25th-percentile term matters - -The mean alone hides skew: one section with 10 anchors and four sections with 0 anchors averages 2, -which looks fine. The 25th-percentile term ensures the score reflects the **worst supported** sections. - -## How downstream metrics use it - -Evidence Coverage feeds [DMI](/metrics/markdown/dmi) indirectly via Filler / Lazy Risk and is reported -in the [PR comment](/guides/pr-comment-design) drill-down. - -## References - -- Daugherty, S. R. & Krueger, K. R. (1991). *The 90-10 rule of unequal coverage and its - ramifications for measurement.* Psychological Reports 68(3) — motivation for percentile-based - reporting (the 25th-percentile term that prevents one well-anchored section from hiding many - unsupported ones). - [DOI](https://doi.org/10.2466/pr0.1991.68.3.939). -- Pirolli, P. & Card, S. (1999). *Information Foraging.* Psychological Review 106(4): 643–675 — - source for the "evidence anchor" concept (each link, code block, or table is a foraging cue). - [DOI](https://doi.org/10.1037/0033-295X.106.4.643). - -## See also - -- [Repository Grounding](/metrics/markdown/repository-grounding) — document-level analogue. -- [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk) — uses unanchored prose mass as an input. diff --git a/docs/metrics/markdown/filler-lazy-risk.mdx b/docs/metrics/markdown/filler-lazy-risk.mdx deleted file mode 100644 index e666eb54..00000000 --- a/docs/metrics/markdown/filler-lazy-risk.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: "Filler / Lazy Structure Risk" -description: "Structural evidence for 'big but vacuous' documents — without claiming anything about how the text was written." -keywords: ["filler risk", "lazy structure", "ai documentation", "documentation quality"] ---- - -This metric addresses the AI-era documentation problem: - -> The document is just filler: structure is lazy, there are no references, it is large but useless. - - -This is **not** AI-authorship detection. It reports structural evidence — unanchored prose, low artifact -density, weak repository grounding, lazy sectioning, repetition, specificity scarcity, hollow -references, and placeholder density — without making any claim about how the text was written. - - -## Sub-scores (.1–17.8) - -| Sub-score | What it captures | -|---|---| -| **UnanchoredProseMass** | Fraction of words living in sections with no evidence anchors. | -| **LowArtifactDensity** | `1 − sat(A / (W/800); 0.5, 2.0)` — too few code, tables, diagrams. | -| **LowRepoGrounding** | `1 − RepositoryGroundingScore`. | -| **LazySectioning** | Heading density, large-section rate, "shallow big doc" flag (`W > 2,500` AND max heading depth ≤ 2). | -| **RepetitionDensity** | Token-shingle Jaccard > 0.82 detects near-duplicate paragraphs. | -| **SpecificityScarcity** | Identifiers + paths + version tokens + inline code tokens relative to `W`. | -| **ReferenceHollowness** | Bibliography entries without verifiable DOI/arXiv/RFC/URL anchors. | -| **PlaceholderDensity** | TODO/TBD/FIXME/XXX/lorem and empty links per 1,000 words. | - -## Formula - -```text -FillerLazyRisk = clamp01( - 0.20 · UnanchoredProseMass - + 0.15 · LowArtifactDensity - + 0.20 · LowRepoGrounding - + 0.15 · LazySectioning - + 0.12 · RepetitionDensity - + 0.12 · SpecificityScarcity - + 0.04 · ReferenceHollowness - + 0.02 · PlaceholderDensity -) -``` - -## Bands - -| Score | Band | -|---|---| -| 0.00 – 0.20 | Low. | -| 0.21 – 0.40 | Mild. | -| 0.41 – 0.60 | Review. | -| 0.61 – 0.80 | High. | -| 0.81 – 1.00 | Severe. | - -## Diagnostic labels - -High scores attach stable string labels reviewers can act on: - -- `large-unanchored-prose` -- `low-repository-grounding` -- `lazy-sectioning` -- `low-artifact-density` -- `near-duplicate-paragraphs` -- `specificity-scarcity` -- `hollow-references` -- `placeholder-heavy` - -The PR comment quotes these labels verbatim instead of paraphrasing. - -## Example output - -```text -Filler / Lazy Structure Risk: 0.73 HIGH - -Top contributors: - - 71% of prose is in sections without evidence anchors - - 3,420 words, only 1 relative link and 0 code examples - - max heading depth = 2 with 4 sections > 1,200 words - - specificity density = 1.8% (threshold: 3%-15%) -``` - -## References - -- Pirolli, P. & Card, S. (1999). *Information Foraging.* Psychological Review 106(4): 643–675 — - motivates the evidence-anchor and specificity-scarcity sub-scores. - [DOI](https://doi.org/10.1037/0033-295X.106.4.643). -- Halliday, M. A. K. (1985). *Spoken and Written Language.* Oxford University Press — lexical-density - basis used by `SpecificityScarcity`. -- Manning, C. D., Raghavan, P. & Schütze, H. (2008). *Introduction to Information Retrieval*, ch. 6. - Cambridge University Press — Jaccard / token-shingle methods used by `RepetitionDensity`. - [Stanford online edition](https://nlp.stanford.edu/IR-book/). - -## See also - -- [DMI](/metrics/markdown/dmi) — uses Filler Risk as one of its inputs. -- [Repository Grounding](/metrics/markdown/repository-grounding) — feeds LowRepoGrounding. -- [Evidence Coverage](/metrics/markdown/evidence-coverage) — feeds UnanchoredProseMass. diff --git a/docs/metrics/markdown/good-scaffold.mdx b/docs/metrics/markdown/good-scaffold.mdx deleted file mode 100644 index 6af88ec2..00000000 --- a/docs/metrics/markdown/good-scaffold.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Good Scaffold" -description: "Bonus credit for helpful technical structure: visuals, tables, code examples, navigation." -keywords: ["good scaffold", "scaffolding", "documentation"] ---- - -**Good Scaffold** rewards helpful technical structure. Where most Markdown metrics measure -problems, this one measures structural assets that aid review. - -## Formula - -```text -GoodScaffoldScore = clamp01( - 0.25 · VisualScaffoldScore - + 0.20 · TableScaffoldScore - + 0.20 · bounded_labelled_code_example_score - + 0.15 · InformationScentScore - + 0.10 · section_summary_score - + 0.10 · successful_internal_navigation_score -) -``` - -## What each component captures - -- [**Visual Scaffold**](/metrics/markdown/visual-scaffold) — well-labelled, bounded, locally explained - diagrams and images. -- [**Table Scaffold**](/metrics/markdown/table-burden) — tables in the 6–60 cell sweet spot. -- **Bounded labelled code examples** — code fences with explicit language tags and bounded sizes. -- **Information Scent** ([Link Debt](/metrics/markdown/link-debt)) — descriptive link text. -- **Section summary** — sections that open with a short summary paragraph. -- **Internal navigation** — anchor links resolve and there's a usable navigation structure. - -## How DMI uses it - -Good Scaffold contributes **positively** to [DMI](/metrics/markdown/dmi) via the `+0.10 · G_norm` term. - -It offsets maintainability penalties **modestly**. It never erases objective defects like broken links, -parse failures, or inclusive-language flags. - -## References - -- Mayer, R. E. (2009). *Multimedia Learning*, 2nd ed. Cambridge University Press — multimedia - principles behind well-labelled visuals and bounded examples. -- Carroll, J. M. (1990). *The Nurnberg Funnel: Designing Minimalist Instruction for Practical - Computer Skill.* MIT Press — minimalist instruction principles supporting "bounded labelled - code examples" and "section summary" credits. - [MIT Press record](https://mitpress.mit.edu/9780262031639/the-nurnberg-funnel/). - -## See also - -- [DMI](/metrics/markdown/dmi) — destination of the bonus credit. -- [Visual Scaffold](/metrics/markdown/visual-scaffold), [Table Burden](/metrics/markdown/table-burden) — - largest contributors. diff --git a/docs/metrics/markdown/halstead.mdx b/docs/metrics/markdown/halstead.mdx deleted file mode 100644 index 00968235..00000000 --- a/docs/metrics/markdown/halstead.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Markdown Halstead" -description: "Halstead vocabulary and volume measured over Markdown-native operators and operands." -keywords: ["markdown halstead", "halstead", "documentation halstead", "documentation complexity"] ---- - -**Markdown Halstead** measures token vocabulary and volume using Markdown-native operators and operands -instead of code operators. It uses the same shape as -[source-code Halstead](/metrics/code/halstead) but with a documentation-specific operator/operand -taxonomy. - -## Operators - -- Heading markers by level (`#`, `##`, …). -- List markers (`-`, `*`, `1.`, …). -- Table delimiters (`|`, alignment markers). -- Link / image operators (`[…](…)`, `![…](…)`). -- Code-fence openers by language (`` ```python ``). -- Inline code, blockquote (`>`), math delimiters (`$…$`, `$$…$$`). -- Emphasis markers (`*`, `_`, `**`). -- Footnote operators. -- Raw-HTML / MDX / directive operators. -- Punctuation classes. -- Diagram DSL statement classes. -- Embedded-code operators. - -## Operands - -- Word-like tokens. -- Numeric / version tokens. -- Identifier-like tokens. -- Path-like tokens. -- Link destinations. -- Table headers. -- Image destinations / alt hashes. -- Code identifiers from embedded analyzers. -- Diagram node / edge labels. -- Math symbols and commands. - -## Formulas - -Same shape as source-code Halstead: - -```text -MDH_vocab = n1 + n2 -MDH_length = N1 + N2 -MDH_volume = MDH_length · log2(max(2, MDH_vocab)) -MDH_diff = (n1 / 2) · (N2 / max(1, n2)) -MDH_effort = MDH_volume · MDH_diff -``` - -## Embedded-code adjustment - -Embedded analyzers contribute: - -```text -0.20 · sqrt(code_halstead_volume) -+ 0.50 · code_cognitive -+ 0.10 · code_loc -``` - -per code block. Raw embedded volume is square-rooted because it can otherwise dwarf document-level -signals; cognitive complexity stays linear because a hard example genuinely requires review. - -## References - -- Halstead, M. H. (1977). *Elements of Software Science.* Elsevier — the operator/operand model - this metric ports to Markdown's token taxonomy. - [OSTI record](https://www.osti.gov/biblio/5685613). -- Kearney, J. K., et al. *Software Complexity Measurement* — MIT lecture notes summarizing the - Halstead operator/operand formulation. - [PDF (MIT OCW 16.355)](http://sunnyday.mit.edu/16.355/kearney.pdf). - -## See also - -- [Halstead metrics for code](/metrics/code/halstead) — same formulas, different operator set. -- [DMI](/metrics/markdown/dmi) — uses MDH volume as one of its inputs. diff --git a/docs/metrics/markdown/link-debt.mdx b/docs/metrics/markdown/link-debt.mdx deleted file mode 100644 index a6c46f4f..00000000 --- a/docs/metrics/markdown/link-debt.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "Link Debt" -description: "Link health and reference burden for Markdown documents." -keywords: ["link debt", "broken links", "documentation", "references"] ---- - -**Link Debt** quantifies link health as a 0–1 score. Broken and unresolved links dominate the score -because they are objective defects; external links are not bad by default but make a document fragile -when over-represented. - -## Link classification - -Every link in the AST is bucketed by destination: - -- Internal anchor. -- Relative repository file. -- Absolute same-repo URL. -- External. -- Issue / PR. -- Bare URL. -- Image target. -- Broken / unresolved. - -## Link Debt Score - -```text -broken_rate = L_broken / max(1, L_total) -external_rate = L_ext / max(1, L_total) -bare_rate = L_bare / max(1, L_total) -anchor_miss_rate = missing_internal_anchors / max(1, L_int) - -LinkDebtScore = clamp01( - 0.45 · sat(broken_rate; 0.00, 0.10) - + 0.20 · sat(anchor_miss_rate; 0.00, 0.10) - + 0.15 · sat(bare_rate; 0.05, 0.30) - + 0.10 · sat(external_rate; 0.60, 0.90) - + 0.10 · sat(link_density_per_100w; 6, 14) -) -``` - -## Companion scores - -- **Information Scent Score** rewards descriptive link text, resolved relative links, working - anchors, and a reference section when the doc is citation-heavy. -- **Link Review Burden** — - `0.3·L_int + 0.8·L_rel + 1.0·L_ext + 2.5·L_broken + 0.5·L_footnote` — - is the cost-per-PR signal used in diff reporting. - -## Bands - -| Link Debt | Meaning | -|---|---| -| 0.00 – 0.20 | Healthy. | -| 0.21 – 0.40 | Mild. | -| 0.41 – 0.60 | Inspect. | -| 0.61 – 0.80 | High. | -| 0.81 – 1.00 | Severe. | - -## References - -- Pirolli, P. & Card, S. (1999). *Information Foraging.* Psychological Review 106(4): 643–675 — - origin of the "information scent" companion score. - [DOI](https://doi.org/10.1037/0033-295X.106.4.643). -- Spool, J. M., Schroeder, W., Scanlon, T. & Snyder, C. (1998). *Web site usability: A designer's - guide.* Morgan Kaufmann — empirical evidence for descriptive link text and resolved-anchor - weighting. -- Nielsen, J. (1996). *Top ten mistakes in web design.* Nielsen Norman Group — broken-link - prevalence as the dominant link-debt term. - [Article](https://www.nngroup.com/articles/top-10-mistakes-web-design/). - -## See also - -- [DMI](/metrics/markdown/dmi) — uses Link Debt as one of its inputs. -- [Repository Grounding](/metrics/markdown/repository-grounding) — uses resolved link counts. diff --git a/docs/metrics/markdown/loc-family.mdx b/docs/metrics/markdown/loc-family.mdx deleted file mode 100644 index 689b9f32..00000000 --- a/docs/metrics/markdown/loc-family.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: "Markdown LOC family" -description: "Lines of Markdown by construct: physical, prose, code, tables, math, blanks, and artifacts." -keywords: ["markdown loc", "documentation size", "ploc", "tloc", "mloc"] ---- - -The Markdown LOC family separates physical lines by what they contain. A 1,000-line file with 700 lines -of code fences is not the same artifact as a 1,000-line prose file, and a single SLOC count would hide -that. - -## What mehen emits - -| Key | Meaning | -|---|---| -| `MD.DLOC` | Physical Markdown lines (everything). | -| `MD.PLOC` | Prose lines (narrative paragraphs, headings, list text). | -| `MD.CLOC` | Code-fence and indented-code lines. | -| `MD.TLOC` | Table lines. | -| `MD.MLOC` | Math block lines. | -| `MD.BLOC` | Blank lines. | -| `MD.ALOC` | Artifact lines = `CLOC + TLOC + MLOC` + diagram / raw HTML / MDX lines. | - -## Derived ratios - -Each component / `max(1, DLOC)` produces a ratio: - -- `ArtifactLineRatio` -- `CodeLineRatio` -- `TableLineRatio` -- `MathLineRatio` -- `BlankLineRatio` - -These ratios drive document classification (prose-dominant vs. artifact-dominant) and anomaly detection. - -## Worked example - -````markdown -# Auth API - -Brief intro paragraph. - -```ts -export async function login(): Promise { /* … */ } -``` - -| Field | Required | -|---|---| -| `email` | yes | -```` - -```yaml -loc: - dloc: 11 - ploc: 4 - cloc: 3 - tloc: 3 - mloc: 0 - bloc: 2 - aloc: 6 -``` - -## References - -- Park, R. E. (1992). *Software Size Measurement: A Framework for Counting Source Statements.* - CMU/SEI-92-TR-20 — the standard reference for LOC categorization that this Markdown family - extends to prose / code / table / math / blank lines. - [SEI report](https://insights.sei.cmu.edu/library/software-size-measurement-a-framework-for-counting-source-statements/). -- CommonMark Spec: [Container blocks and leaf blocks](https://spec.commonmark.org/0.30/) — the - parser-level distinctions the per-construct counts rely on. - -## See also - -- [Effective Content Units](/metrics/markdown/effective-content-units) — review-mass normalization that - uses these counts. -- [Section tree](/metrics/markdown/section-tree) — per-section LOC aggregation. diff --git a/docs/metrics/markdown/mcc.mdx b/docs/metrics/markdown/mcc.mdx deleted file mode 100644 index 3059deda..00000000 --- a/docs/metrics/markdown/mcc.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: "MCC — Markdown Cognitive Complexity" -description: "Local reading burden caused by flow breaks, nesting, context switches, and dense artifact clusters." -keywords: ["mcc", "markdown cognitive", "readability", "documentation complexity"] ---- - -**MCC** estimates local reading burden caused by flow breaks, nesting, context switches, and dense -artifact clusters. It is the documentation analogue of -[cognitive complexity](/metrics/code/cognitive) for source code. - -## Base weights - -Each construct contributes a base weight, ranging from `0.20` for a normal heading-level increment up to -`+4.00` for a verified broken external link. - -## Formula - -The MCC formula has three multiplicative layers: - -```text -MCC_positive = Σ base_weight(c) · nesting_multiplier(c) · clustering_multiplier(c) - -MCC = max(0, MCC_positive − min(Σ scaffold_credit(a), MCC_credit_cap)) -``` - -### Nesting multiplier - -```text -nesting_multiplier = 1 + 0.18 · nest(n) -``` - -Smaller than code-oriented nesting penalties because Markdown nesting is cheaper than control-flow -nesting. - -### Artifact clustering multiplier - -Dense clusters of artifacts in a 20-rendered-line window increase local switching cost. - -### Scaffolding credit - -Well-labelled, bounded, locally explained artifacts earn credit capped at `0.25 · MCC_positive`. Credit -applies only when label, nearby explanation, and bounded size are all present. - -## Interpretation - -| MCC | Meaning | -|---|---| -| 0–10 | Easy to read. | -| 11–25 | Normal. | -| 26–50 | Dense. | -| > 100 | Documentation subsystem rather than one page. | - -## References - -- Campbell, G. A. (2018). *Cognitive Complexity — A new way of measuring understandability.* - SonarSource white paper — the design ancestor. - [PDF](https://www.sonarsource.com/resources/cognitive-complexity/). -- Sweller, J. (1988). *Cognitive load during problem solving: Effects on learning.* Cognitive - Science 12(2): 257–285 — basis for the nesting and clustering multipliers. - [DOI](https://doi.org/10.1207/s15516709cog1202_4). -- Mayer, R. E. (2009). *Multimedia Learning*, 2nd ed. Cambridge University Press — - split-attention and contiguity principles behind the artifact-clustering penalty. - -## See also - -- [Cognitive complexity](/metrics/code/cognitive) — the source-code analogue. -- [MRPC](/metrics/markdown/mrpc) — global reading-path complexity. -- [Visual Scaffold](/metrics/markdown/visual-scaffold) — artifact scaffolding credit driver. diff --git a/docs/metrics/markdown/mrpc.mdx b/docs/metrics/markdown/mrpc.mdx deleted file mode 100644 index 579989d1..00000000 --- a/docs/metrics/markdown/mrpc.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "MRPC — Markdown Reading Path Complexity" -description: "Cyclomatic-complexity analogue for a Markdown document's navigation graph." -keywords: ["mrpc", "reading path", "cyclomatic", "documentation complexity"] ---- - -**MRPC** is the [cyclomatic complexity](/metrics/code/cyclomatic) analogue for a Markdown file. It -builds a document navigation graph `G_doc = (N, E)` where nodes are sections, large code blocks, -diagrams, footnotes, linked repository documents, and external domains, and edges are sequential, -parent-child, internal-link, relative-link, external-link, and artifact-explanation relations. - -## Classical form - -```text -MRPC_raw = |E| − |N| + 2P -``` - -where `P` is the number of connected components. - -## Weighted form - -Edges carry weights to reflect different navigation costs: - -| Edge type | Weight | -|---|---| -| Hierarchy (parent-child) | `0.15` | -| Sequential | `0.20` | -| Internal anchor | `0.50` | -| Relative repo link | `0.80` | -| External | `1.00` | -| Broken | `1.20` | - -```text -MRPC = max(1, Σ weight(e) − |N| + 2P) -``` - -## Interpretation - -| MRPC | Meaning | -|---|---| -| 1–5 | Mostly linear. | -| 6–15 | Branchy but contained. | -| 16–35 | Documentation hub — high navigational complexity. | -| > 35 | Documentation subsystem; consider split or profile-specific threshold. | - -A tutorial with `MRPC = 20` is suspect; an API index with `MRPC = 20` is normal. Use -profile-specific thresholds rather than a universal cap. - -## References - -- McCabe, T. J. (1976). *A Complexity Measure.* IEEE Transactions on Software Engineering, SE-2(4): - 308–320 — the cyclomatic ancestor. - [DOI](https://doi.org/10.1109/TSE.1976.233837) · - [PDF](http://www.literateprogramming.com/mccabe.pdf). -- Pirolli, P. & Card, S. (1999). *Information Foraging.* Psychological Review 106(4): 643–675 — - basis for weighting external vs. relative vs. anchor edges. - [DOI](https://doi.org/10.1037/0033-295X.106.4.643). - -## See also - -- [Cyclomatic complexity](/metrics/code/cyclomatic) — the source-code analogue. -- [MCC](/metrics/markdown/mcc) — local cognitive burden. -- [Link Debt](/metrics/markdown/link-debt) — broken/external link cost. diff --git a/docs/metrics/markdown/overview.mdx b/docs/metrics/markdown/overview.mdx deleted file mode 100644 index 67c66545..00000000 --- a/docs/metrics/markdown/overview.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "Markdown metrics overview" -description: "What mehen reports for Markdown documentation: structural metrics, prose layer, and the AI-era 'filler/lazy structure' family." -keywords: ["markdown metrics", "documentation maintainability", "dmi", "filler risk", "readability"] ---- - -mehen treats Markdown as a first-class artifact. Instead of stripping code fences, diagrams, tables, -images, links, and math before counting words, every construct contributes to a dedicated metric suite. - -The suite is split into two layers: - -- **[Structural layer](#structural-layer)** — language-opaque, AST-driven: LOC family, section tree, - reading-path complexity, link/table/visual scaffolds, repository grounding, filler/lazy risk, review - criticality. -- **[Prose layer](/metrics/markdown/prose/overview)** — language-aware (English and Japanese): readability - ensemble, lexical diversity, wording quality, JTF rules, textlint subset. - - -Code-style metrics like cyclomatic complexity, NOM, NPA, NPM, and WMC do **not** apply to Markdown — -prose has no functions, classes, or interfaces to score. mehen emits a Markdown-specific suite tailored -to prose, code blocks, and references. - - -## Structural layer - -| Page | Purpose | -|---|---| -| [LOC family](/metrics/markdown/loc-family) | Markdown LOC variants by construct: prose / code / tables / math / blank / artifact. | -| [Section tree](/metrics/markdown/section-tree) | Heading-derived structure with quality flags. | -| [Effective Content Units](/metrics/markdown/effective-content-units) | Review-mass normalization across prose and artifacts. | -| [MRPC](/metrics/markdown/mrpc) | Reading Path Complexity — cyclomatic-complexity analogue for navigation. | -| [MCC](/metrics/markdown/mcc) | Cognitive Complexity — local reading burden. | -| [Markdown Halstead](/metrics/markdown/halstead) | Markdown-native operators / operands. | -| [DMI](/metrics/markdown/dmi) | Documentation Maintainability Index — composite 0–100. | -| [Link Debt](/metrics/markdown/link-debt) | Link health and reference burden. | -| [Table Burden + Scaffold](/metrics/markdown/table-burden) | Table cost and cognitive scaffolding. | -| [Visual Scaffold](/metrics/markdown/visual-scaffold) | Diagrams and images: helping or hurting? | -| [Artifact Debt](/metrics/markdown/artifact-debt) | Unlabelled, unparsable, oversized, unexplained artifacts. | -| [Repository Grounding](/metrics/markdown/repository-grounding) | Resolved repo links, paths, identifiers, version facts. | -| [Evidence Coverage](/metrics/markdown/evidence-coverage) | Per-section structural support density. | -| [Filler / Lazy Structure Risk](/metrics/markdown/filler-lazy-risk) | AI-era flag for "big but vacuous". | -| [Review Criticality Index](/metrics/markdown/review-criticality-index) | "Should I review this carefully?" score. | -| [Section Balance](/metrics/markdown/section-balance) | Are sections sized in a maintainable way? | -| [Good Scaffold](/metrics/markdown/good-scaffold) | Bonus credit for helpful technical structure. | - -## Prose layer (opt-in, feature-gated) - -| Page | Purpose | -|---|---| -| [Overview](/metrics/markdown/prose/overview) | Architectural constraints and tier model. | -| [Block-level language detection](/metrics/markdown/prose/language-detection) | Per-block language tagging. | -| [English readability](/metrics/markdown/prose/english-readability) | FKGL, Fog, SMOG, ARI, Coleman-Liau, Dale-Chall, FORCAST, LIX/RIX. | -| [Lexical diversity](/metrics/markdown/prose/lexical-diversity) | MATTR, hapax, density. | -| [Wording quality](/metrics/markdown/prose/wording-quality) | Passive, hedges, weasels, wordy, adverbs, nominalizations, cliches. | -| [Inclusive language](/metrics/markdown/prose/inclusive-language) | alex / retext-equality flags. | -| [Japanese script composition](/metrics/markdown/prose/japanese-script-composition) | Kanji/hiragana/katakana ratios, registers. | -| [Tateishi RS + Jōyō grade](/metrics/markdown/prose/tateishi-and-jouyou) | Japanese readability scores. | -| [JTF rules](/metrics/markdown/prose/jtf-rules) | Japan Translation Federation 12 rules. | -| [textlint-ja subset](/metrics/markdown/prose/textlint-ja) | Selected rules from `textlint-rule-preset-ja-technical-writing`. | - -## See also - -- [PR comment design](/guides/pr-comment-design) — how Markdown metric deltas surface on pull requests. -- [Concepts → Output formats](/concepts/output-formats) — Markdown vs. JSON shape. diff --git a/docs/metrics/markdown/prose/english-readability.mdx b/docs/metrics/markdown/prose/english-readability.mdx deleted file mode 100644 index 10546edb..00000000 --- a/docs/metrics/markdown/prose/english-readability.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "English readability ensemble" -description: "Nine readability formulas reported with provenance: Flesch, FKGL, Fog, SMOG, ARI, Coleman-Liau, Dale-Chall, FORCAST, LIX/RIX." -keywords: ["readability", "flesch", "fkgl", "smog", "fog", "english"] ---- - -mehen emits **every formula's raw score with provenance** rather than averaging. Two formulas on the -same text routinely disagree by 2–4 grade levels because they target different comprehension thresholds -(SMOG ~100%, FKGL ~75%, Dale-Chall in between). Averaging them is statistically wrong. - -## Formulas - -| Formula | Syllables | Key notes | -|---|---|---| -| **Flesch Reading Ease** | yes | `206.835 − 1.015·ASL − 84.6·ASW`. Higher = easier. | -| **Flesch-Kincaid Grade** | yes | `0.39·ASL + 11.8·ASW − 15.59`. MIL-M-38784A standard. | -| **Gunning Fog** | yes | `0.4·(ASL + 100·P_complex)`. Target grade 7–12 for business writing. | -| **SMOG** | yes | `1.0430·sqrt(poly·30/sentences) + 3.1291`. `null` below 30 sentences. | -| **ARI** | no | `4.71·CPW + 0.5·ASL − 21.43`. Syllable-free. | -| **Coleman-Liau** | no | `0.0588·L − 0.296·S − 15.8`. Syllable-free. | -| **New Dale-Chall** | no | `0.1579·PDW + 0.0496·ASL` (+ `3.6365` if PDW > 5%). | -| **FORCAST** | counts 1-syllable | `20 − (N/10)`. Non-narrative text. | -| **LIX** | no | `ASL + 100·(long_words/words)`. | -| **RIX** | no | `long_words / sentences`. | - -## Ensemble reporting - -1. Emit every formula with provenance. -2. Compute an **ensemble grade band** as `[min(FKGL, Fog, ARI, CLI), max(…)]` — the interval where those - four "running-prose" formulas agree. -3. Emit FORCAST separately as the preferred single score for non-narrative docs. -4. Suppress SMOG when `sentences < 30`. -5. Report Dale-Chall only with an explicit `list:` provenance tag (NGSL 1.2 by default — Browne et al., - 2013). - -## Syllable counting - -Tier 0 default is a vowel-group heuristic (~85% agreement with CMU on open-domain text). Behind -`--features syllables-cmu`, mehen links the **CMU Pronouncing Dictionary** for exact counts on ~134k -words with the heuristic as an OOV fallback. - -## Sentence segmentation - -UAX #29 (`unicode-segmentation`) plus: - -- A bundled ~150-entry English abbreviation list (`Mr.`, `e.g.`, `i.e.`, `U.S.`, `v1.2.3`). -- No split when the period is followed by a lowercase letter, a digit, or ``. -- Markdown block boundaries (blank line, heading, fence open/close, list item start) are **hard** - terminators regardless of punctuation. - -## Doc-type thresholds - -| Doc type | FKGL | Fog | Passive max | Max sentence words | -|---|---:|---:|---:|---:| -| README / overview | ≤ 10 | ≤ 12 | 15 % | 30 | -| Tutorial | ≤ 9 | ≤ 11 | 10 % | 25 | -| API reference | ≤ 12 | ≤ 14 | 20 % | 35 | -| ADR / design | ≤ 12 | ≤ 14 | 25 % | 40 | -| Error messages | ≤ 7 | ≤ 9 | 5 % | 15 | -| Release notes | ≤ 11 | ≤ 13 | 15 % | 30 | - -These are conventions synthesized from Google, Microsoft, and 18F style guides. They are tunable -profile defaults. - -## References - -- Flesch, R. (1948). *A new readability yardstick.* Journal of Applied Psychology 32(3): 221–233. - [DOI](https://doi.org/10.1037/h0057532). -- Kincaid, J. P., Fishburne, R. P., Rogers, R. L. & Chissom, B. S. (1975). *Derivation of new - readability formulas (Automated Readability Index, Fog Count and Flesch Reading Ease Formula) for - Navy enlisted personnel.* Research Branch Report 8-75, Naval Technical Training Command. - [DTIC PDF](https://apps.dtic.mil/sti/pdfs/ADA006655.pdf). -- McLaughlin, G. H. (1969). *SMOG grading — a new readability formula.* Journal of Reading 12(8): - 639–646. [JSTOR](https://www.jstor.org/stable/40011226). -- Gunning, R. (1952). *The Technique of Clear Writing.* McGraw-Hill. -- Coleman, M. & Liau, T. L. (1975). *A computer readability formula designed for machine scoring.* - Journal of Applied Psychology 60(2): 283–284. - [DOI](https://doi.org/10.1037/h0076540). -- Senter, R. J. & Smith, E. A. (1967). *Automated Readability Index.* AMRL-TR-66-220. - [DTIC PDF](https://apps.dtic.mil/sti/citations/AD0667273). -- Chall, J. S. & Dale, E. (1995). *Readability Revisited: The New Dale-Chall Readability Formula.* - Brookline Books. -- Caylor, J. S. & Sticht, T. G. (1973). *Development of a Simple Readability Index for Job Reading - Material.* HumRRO Professional Paper 1-73 (FORCAST). - [DTIC](https://apps.dtic.mil/sti/citations/AD0773634). -- Anderson, J. (1983). *Lix and Rix: Variations on a little-known readability index.* Journal of - Reading 26(6): 490–496. [JSTOR](https://www.jstor.org/stable/40031755). - -## See also - -- [Lexical diversity](/metrics/markdown/prose/lexical-diversity) — formula-independent vocabulary - measures. -- [Wording quality](/metrics/markdown/prose/wording-quality) — passive voice, hedges, wordy phrases. diff --git a/docs/metrics/markdown/prose/inclusive-language.mdx b/docs/metrics/markdown/prose/inclusive-language.mdx deleted file mode 100644 index 0900257a..00000000 --- a/docs/metrics/markdown/prose/inclusive-language.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Inclusive Language Score" -description: "alex / retext-equality flags for gendered defaults, ableist idioms, exclusionary tech terms, and condescending phrasing." -keywords: ["inclusive language", "alex", "retext-equality", "writing quality"] ---- - -mehen runs an `alex`-style / `retext-equality`-style check against a bundled dictionary covering: - -## Categories - -- **Gendered defaults** — `mankind → humanity`, `fireman → firefighter`, `manhole → maintenance-hole`. -- **Ableist idioms** — `crazy`, `insane`, `lame`, `dumb`, `blind to`, `tone deaf`. -- **Exclusionary tech terms** — `master/slave → primary/replica`, - `whitelist/blacklist → allowlist/denylist`, `grandfather clause → legacy exception`, - `sanity check → spot check`. -- **Condescending** — `obviously`, `just`, `simply`, `easy`, `of course`. - -## Output - -Per-document `InclusiveLanguageScore` plus a list of flags with source spans. Any new -inclusive-language flag is a 🔴 regression in the [PR comment](/guides/pr-comment-design). - -## References - -- [alex](https://github.com/get-alex/alex). -- [retext-equality](https://github.com/retextjs/retext-equality). -- [Inclusive Naming Initiative](https://inclusivenaming.org/). - -## See also - -- [Wording quality](/metrics/markdown/prose/wording-quality) — orthogonal style flags. diff --git a/docs/metrics/markdown/prose/japanese-script-composition.mdx b/docs/metrics/markdown/prose/japanese-script-composition.mdx deleted file mode 100644 index 5615810d..00000000 --- a/docs/metrics/markdown/prose/japanese-script-composition.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Japanese script composition" -description: "Tier 0 Japanese register signal: kanji, hiragana, katakana, latin, and digit ratios." -keywords: ["japanese", "script composition", "kanji ratio", "tateishi"] ---- - -Japanese is unusual among major languages: script composition alone carries enough information to -produce defensible readability scores without a tokenizer. This is the foundational insight of -Tateishi, Ono & Yamada (1988) and remains the basis for mehen's Tier-0 Japanese layer. - -## Unicode script classification - -Each grapheme cluster classifies into: - -- Hiragana -- Katakana -- Kanji (Han + Extensions A/B + Compatibility) -- CJK punctuation -- Latin (+ Fullwidth) -- Digit - -## Primary ratios - -`kanji_ratio`, `hiragana_ratio`, `katakana_ratio`, `latin_ratio`, `digit_ratio`, `script_entropy` -(Shannon entropy over the five classes). - -## Register bands - -| Kanji ratio | Register | -|---|---| -| < 20 % | Children's writing, conversation. | -| 20–30 % | Casual prose, novels, user-facing content. | -| 30–40 % | Newspaper, business writing, non-fiction. | -| 40–50 % | Technical, legal, academic. | -| > 50 % | Classical / literary, specialist text. | - -Katakana > 15 % typically signals software documentation (loanwords like `データベース`) or marketing -copy. Hiragana > 75 % indicates text aimed at small children or machine-translated output. - -## Script-run features - -A "run" is a maximal substring of same-script characters. Per document: - -- Mean chars per alphabet run (`la`). -- Mean chars per hiragana run (`lh`). -- Mean chars per kanji run (`lc`). -- Mean chars per katakana run (`lk`). -- Percentages of each run type (`pa`, `ph`, `pc`, `pk`). -- Mean chars per sentence (`ls`). -- `、` per `。` (`cp`). - -These are the exact inputs the Tateishi formula needs. - -## Sentence segmentation - -Primary terminators `。`, `!`, `?` plus half-width equivalents. Do not split inside `「…」`, `『…』`, -`(…)`. Treat blank-line paragraph boundaries and Markdown block boundaries as hard terminators. -Ellipsis `…` / `‥` / `...` is not a terminator. - -## Sentence-length thresholds - -- Warning: > 60 chars. -- Hard-to-read: > 90. -- Error: > 120. -- Mean sentence length > 60 triggers a document-level warning. - -## References - -- Tateishi, K., Ono, Y. & Yamada, H. (1988). *A Computer Readability Formula of Japanese Texts for - Machine Scoring.* Proceedings of COLING-1988: 649–654. - [ACL Anthology](https://aclanthology.org/C88-2132/). -- Lee, J. & Hasebe, Y. (2017). *jReadability — a web-based Japanese text-readability indexing - system.* (Foundation for register-based Japanese readability work.) - [jReadability](https://jreadability.net/sys/en). - -## See also - -- [Tateishi RS + Jōyō grade](/metrics/markdown/prose/tateishi-and-jouyou) — readability scores built on - these inputs. -- [JTF rules](/metrics/markdown/prose/jtf-rules) — Japan Translation Federation conformance. diff --git a/docs/metrics/markdown/prose/jtf-rules.mdx b/docs/metrics/markdown/prose/jtf-rules.mdx deleted file mode 100644 index 34ab90a2..00000000 --- a/docs/metrics/markdown/prose/jtf-rules.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "JTF rule conformance" -description: "Japan Translation Federation's 12 rules, mechanically checkable on Markdown blocks." -keywords: ["jtf", "japan translation federation", "japanese style guide", "writing quality"] ---- - -The Japan Translation Federation's **JTF Japanese Style Guide for Translators** has 12 mechanical rules -that mehen checks on Japanese-tagged Markdown blocks. - -## Rules - -| # | Check | Severity | -|---|---|---| -| 1 | keitai/jōtai consistency (`である` / `です・ます`) | warn | -| 2 | `、` / `。` used as punctuation | info | -| 3 | Stick to Jōyō kanji (flag `hyōgai`) | warn | -| 4 | Okurigana per official rules | info | -| 5 | Trailing long-vowel mark on katakana compound endings (`コンピューター` not `コンピュータ`) | warn | -| 6 | Long katakana compounds broken with `・` or half-width space | info | -| 7 | Kanji / hiragana / katakana full-width | error | -| 8 | Digits and Latin alphabet half-width | warn | -| 9 | Symbols full-width | info | -| 10 | No space between full-width and half-width | info | -| 11 | `.`, `,`, spaces half-width | info | -| 12 | Standardize unit notation | info | - -## How violations surface - -Each violation contributes to: - -- The document's **`jtf_violation_density`** (input to Japanese WQS). -- A list of `(line, column, rule, message)` flags reported in the JSON output. -- Per-rule callouts in the [PR comment](/guides/pr-comment-design). - -## References - -- Japan Translation Federation: [Japanese Style Guide for Translators (3rd Edition)](https://www.jtf.jp/jp/style_guide/styleguide.html). - -## See also - -- [Japanese script composition](/metrics/markdown/prose/japanese-script-composition) — Tier 0 inputs. -- [textlint-ja subset](/metrics/markdown/prose/textlint-ja) — additional Japanese rules. diff --git a/docs/metrics/markdown/prose/language-detection.mdx b/docs/metrics/markdown/prose/language-detection.mdx deleted file mode 100644 index a753a7c5..00000000 --- a/docs/metrics/markdown/prose/language-detection.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "Block-level language detection" -description: "Per-Markdown-block language identification driving prose-metric dispatch." -keywords: ["language detection", "english", "japanese", "unicode block"] ---- - -Language identification happens once per Markdown block so prose-metric dispatch can choose the correct -locale pipeline. - -## Tier 0 default - -Zero-dependency Unicode-block heuristic. For the English/Japanese split, Unicode-block ratios outperform -trigram language models on short inputs because Chinese has no hiragana/katakana: - -```text -let total = non_whitespace_non_punct_chars -let kana = hiragana_chars + katakana_chars -let cjk = kana + han_chars -let latin = ascii_letter_chars + fullwidth_latin_letter_chars - -if kana / total >= 0.15: language = ja -elif cjk / total >= 0.40 and kana == 0: language = zh (treated as "other") -elif latin / total >= 0.80: language = en -else: language = other -``` - -## Opt-in trigram classifiers - -Behind Cargo features: - -| Feature | Library | Notes | -|---|---|---| -| `whatlang` | [whatlang-rs](https://github.com/greyblake/whatlang-rs) | Pure Rust, 70 languages, MIT, reliable above ~120 characters. | -| `lingua` | [lingua-rs](https://github.com/pemistahl/lingua-rs) | Highest accuracy in published benchmarks; restricted to `[English, Japanese]` for binary size. | - -## Tagging rules - -- A block inherits its parent heading's language when its own signal is inconclusive. -- Code fences, inline code, link targets, image targets, front matter, and HTML are tagged `none` and - excluded from prose metrics. -- A document with both English and Japanese blocks is labelled `mixed` at the document level but each - block keeps its own tag for metric routing. - -## Output - -Every block gets a `(range, language, confidence)` tuple. Metric dispatch reads the language tag to -decide which pipeline runs. - -## References - -- Cavnar, W. B. & Trenkle, J. M. (1994). *N-Gram-Based Text Categorization.* Proc. SDAIR-94 — - the trigram language-identification approach used by `whatlang` and `lingua`. - [PDF](https://www.let.rug.nl/~vannoord/TextCat/textcat.pdf). -- Brown, R. D. (2013). *Selecting and weighting n-grams to identify 1100 languages.* Proc. TSD — - modern accuracy benchmarks for trigram LID. - [DOI](https://doi.org/10.1007/978-3-642-40585-3_61). -- [Whatlang Rust crate](https://github.com/greyblake/whatlang-rs). -- [Lingua Rust crate](https://github.com/pemistahl/lingua-rs). - -## See also - -- [English readability ensemble](/metrics/markdown/prose/english-readability). -- [Japanese script composition](/metrics/markdown/prose/japanese-script-composition). diff --git a/docs/metrics/markdown/prose/lexical-diversity.mdx b/docs/metrics/markdown/prose/lexical-diversity.mdx deleted file mode 100644 index 0566bce0..00000000 --- a/docs/metrics/markdown/prose/lexical-diversity.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Lexical diversity" -description: "Formula-independent vocabulary richness: MATTR, hapax, lexical density, sentence/word moments." -keywords: ["lexical diversity", "mattr", "hapax", "ttr", "vocabulary"] ---- - -Formula-independent indicators of vocabulary richness and content-word saturation. They do not depend on -syllable counts and are robust across document types. - -## What mehen emits - -- **MATTR₅₀** — Moving-Average Type-Token Ratio over 50-token sliding windows - (Covington & McFall 2010). Length-invariant by construction and cheap to compute. MTLD and HD-D are - reported as alternative diversity measures behind `--features lexical-diversity`. -- **Hapax ratio / dis-legomena ratio** — `V_1 / V` and `V_2 / V`. Zipf's law predicts hapax ≈ 0.5 - on natural prose; > 0.6 flags laundry-list reference dumps, extremely low values flag repetitive - template content. -- **Lexical density** — content words / total words. Without POS tagging, approximated as - `1 − stopwords / tokens` using the 175-entry NLTK English stopword list. Typical ranges: spoken ~0.40, - written ~0.52, academic ~0.60. -- **Yule's K** — optional; MATTR is usually sufficient. -- **Sentence/word length moments** — `avg_sentence_words`, `p90_sentence_words`, - `max_sentence_words`, `stddev_sentence_words`, `avg_word_chars`, `p90_word_chars`. These drive the - readability formulas but are reported individually so writers see the levers directly. - -## References - -- Covington, M. A. & McFall, J. D. (2010). *Cutting the Gordian knot: The Moving-Average Type-Token - Ratio (MATTR).* Journal of Quantitative Linguistics. -- McCarthy, P. M. & Jarvis, S. (2010). *MTLD, vocd-D, and HD-D.* Behavior Research Methods. -- Yule, G. U. (1944). *The Statistical Study of Literary Vocabulary.* Cambridge University Press. -- Halliday, M. A. K. (1985). *Spoken and Written Language.* Oxford University Press — origin of the - modern lexical-density definition. -- Stanford NLP: [Type-Token Ratio overview in introductory NLP slides](https://web.stanford.edu/class/cs224n/) — - used by Stanford's CS 224N course as a teaching reference. - -## See also - -- [English readability ensemble](/metrics/markdown/prose/english-readability) — uses sentence-length - moments. -- [Wording quality](/metrics/markdown/prose/wording-quality) — orthogonal style metric. diff --git a/docs/metrics/markdown/prose/overview.mdx b/docs/metrics/markdown/prose/overview.mdx deleted file mode 100644 index 67f2c509..00000000 --- a/docs/metrics/markdown/prose/overview.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Prose layer overview" -description: "Language-aware Markdown signals: readability formulas, lexical diversity, wording quality, Japanese script composition and JTF conformance." -keywords: ["prose layer", "readability", "english", "japanese", "wording quality"] ---- - -The structural Markdown layer ([Markdown Metrics](/metrics/markdown/overview)) is deliberately -language-opaque. The **prose layer** adds language-aware signals — readability formulas, lexical -diversity, wording quality, Japanese script composition and JTF conformance — on top of the same AST. - -## Architectural constraints - -1. **Layered, not folded.** Prose metrics are a separate top-level section in the output schema. They do - not modify [DMI](/metrics/markdown/dmi), [MCC](/metrics/markdown/mcc), - [MRPC](/metrics/markdown/mrpc), or [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk) weights - silently. -2. **Per-block language tag.** Language detection runs per Markdown block (paragraph, heading, list - item, blockquote), not per document. -3. **Structural artifacts stay excluded.** Code fences, inline code, link destinations, image alt-text, - YAML/TOML/JSON front matter, HTML/MDX, and table delimiters are stripped before any readability or - wording calculation. -4. **Short-text refusal.** Grade-level formulas are suppressed when `words < 100` OR `sentences < 5`. -5. **Feature-gated dictionaries.** Dictionary-dependent features ship behind Cargo `--features` flags so - the default binary stays small. -6. **Deterministic and reproducible.** No network, no cloud, no sampling. - -## Tier model - -| Tier | Cargo features | Adds | Binary cost | -|---|---|---|---| -| **0 (default)** | none | Unicode-block language detection; UAX #29 segmentation; vowel-group syllables; Tateishi RS; basic wording heuristics; JTF mechanical checks | ~100–300 KB | -| **1a** | `syllables-cmu` | CMU Pronouncing Dictionary | +1–2 MB | -| **1b** | `japanese-jouyou` | Jōyō grade proxy, hyōgai ratio | +10 KB | -| **1c** | `japanese-jlpt` | JLPT N5–N1 word and kanji bands | +300 KB | -| **1d** | `lingua` | High-accuracy trigram language detection | +2–5 MB | -| **2a** | `japanese-morph` | Lindera + IPADIC, bunsetsu, POS, Shibasaki grade | +50 MB | -| **2b** | `japanese-unidic` | Vibrato + UniDic; jReadability | external dict | -| **2c** | `lexical-diversity` | MTLD, HD-D, Yule's K | +50 KB | -| **2d** | `vale-rules` | Parse vale-compatible YAML rule packs | +200 KB | - -## Pages - -| Page | Purpose | -|---|---| -| [Block-level language detection](/metrics/markdown/prose/language-detection) | Per-block English/Japanese/other tagging. | -| [English readability ensemble](/metrics/markdown/prose/english-readability) | Flesch, FKGL, Fog, SMOG, ARI, Coleman-Liau, Dale-Chall, FORCAST, LIX/RIX. | -| [Lexical diversity](/metrics/markdown/prose/lexical-diversity) | MATTR, hapax, density, sentence/word moments. | -| [Wording quality](/metrics/markdown/prose/wording-quality) | Passive, hedges, weasels, wordy, adverbs, nominalizations, cliches, illusions. | -| [Inclusive language](/metrics/markdown/prose/inclusive-language) | alex / retext-equality flags. | -| [Japanese script composition](/metrics/markdown/prose/japanese-script-composition) | Kanji/hiragana/katakana ratios, registers. | -| [Tateishi RS + Jōyō grade](/metrics/markdown/prose/tateishi-and-jouyou) | Japanese readability formulas. | -| [JTF rules](/metrics/markdown/prose/jtf-rules) | Japan Translation Federation 12 rules. | -| [textlint-ja subset](/metrics/markdown/prose/textlint-ja) | Selected `textlint-rule-preset-ja-technical-writing` rules. | - diff --git a/docs/metrics/markdown/prose/tateishi-and-jouyou.mdx b/docs/metrics/markdown/prose/tateishi-and-jouyou.mdx deleted file mode 100644 index 88f1e96d..00000000 --- a/docs/metrics/markdown/prose/tateishi-and-jouyou.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: "Tateishi RS + Jōyō grade" -description: "Japanese readability scores built from script composition without a morphological analyzer." -keywords: ["tateishi", "japanese readability", "jouyou grade", "rs"] ---- - -mehen's Tier-0 Japanese readability score is the **Tateishi simplified RS** (Tateishi, Ono & Yamada -1988). It needs only sentence boundaries and script-run features — both computable without a tokenizer. - -## Tateishi RS - -Simplified 6-variable form: - -```text -RS = −0.12·ls − 1.37·la + 7.4·lh − 23.18·lc − 5.4·lk − 4.67·cp + 115.79 -``` - -Calibrated so mean ≈ 50, SD ≈ 10. **Higher = easier**. Mehen emits this as `tateishi_rs` with sanity -guards: - -- Refuse when `hiragana_ratio > 0.90` (the formula is gamed upward). -- Refuse when character count < 300. - -## Jōyō grade proxy - -The 2,136-character 2010 Jōyō list maps each character to a grade 1–8 (1–6 elementary, 7 = secondary -Jōyō, 8 = non-Jōyō `hyōgai`). Ships as a ~6 KB static table behind `--features japanese-jouyou`: - -```text -jouyou_grade_mean = mean(grade(c) for each kanji c) -hyougai_ratio = non_jouyou_kanji_chars / kanji_chars -``` - -`jouyou_grade_mean` is a direct school-grade analogue to Flesch-Kincaid: < 3 indicates elementary -reading; > 6 indicates high-school+ technical prose. - -## Higher-tier formulas (gated) - -Behind `--features japanese-morph` (Lindera + IPADIC) or `--features japanese-unidic` (Vibrato + -UniDic): - -- **Shibasaki & Hara** — adds bunsetsu and morphological inputs. -- **Lee & Hasebe jReadability** — modern web-corpus-trained formula. -- **Obi / Obi2** — Japanese textbook-grade analogue. -- **Mizuno / Goda** — alternative readability work. - -JLPT bands — N5–N1 word and kanji bands — are optional behind `--features japanese-jlpt` -(~300 KB). - -## References - -- Tateishi, K., Ono, Y. & Yamada, H. (1988). *A Computer Readability Formula of Japanese Texts for - Machine Scoring.* Proceedings of COLING-1988: 649–654. - [ACL Anthology](https://aclanthology.org/C88-2132/). -- 文化庁 (Agency for Cultural Affairs of Japan, 2010). *常用漢字表.* (Jōyō kanji list, 2010 revision.) - [Official notice (PDF)](https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kakuki/14/tosin02/index.html). -- Lee, J. & Hasebe, Y. (2017). *jReadability — a web-based Japanese text-readability indexing system.* - [jReadability](https://jreadability.net/sys/en). -- Sato, S., Matsuyoshi, S. & Kondoh, Y. (2008). *Automatic Assessment of Japanese Text Readability - Based on a Textbook Corpus.* Proceedings of LREC 2008. - [LREC PDF](https://aclanthology.org/L08-1064/). - -## See also - -- [Japanese script composition](/metrics/markdown/prose/japanese-script-composition) — provides the - inputs. -- [JTF rules](/metrics/markdown/prose/jtf-rules) — Japan Translation Federation conformance. diff --git a/docs/metrics/markdown/prose/textlint-ja.mdx b/docs/metrics/markdown/prose/textlint-ja.mdx deleted file mode 100644 index 12c080ad..00000000 --- a/docs/metrics/markdown/prose/textlint-ja.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "textlint-ja subset" -description: "Selected rules from textlint-rule-preset-ja-technical-writing applied to Japanese Markdown blocks." -keywords: ["textlint", "japanese", "writing rules", "technical writing"] ---- - -mehen ports a subset of [`textlint-rule-preset-ja-technical-writing`](https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing) -with their documented defaults. - -## Rules - -| Rule | Default | Check | -|---|---|---| -| `sentence-length` | ≤ 100 chars | Long-sentence flag. | -| `max-comma` | ≤ 3 `,` / sentence | Over-comma'd sentences. | -| `max-ten` | ≤ 3 `、` / sentence | Over-reading-marked sentences. | -| `max-kanji-continuous-len` | ≤ 6 | Hard-to-read kanji runs. | -| `no-mix-dearu-desumasu` | zone-aware | JTF rule 1. | -| `ja-no-mixed-period` | `。` | Sentence terminator consistency. | -| `no-double-negative-ja` | — | `ないではない`. | -| `no-doubled-joshi` | `min_interval: 1` | Repeated particles (`を…を`). | -| `no-doubled-conjunctive-particle-ga` | — | Repeated `が`. | -| `no-doubled-conjunction` | — | `しかし…しかし`. | -| `no-dropping-the-ra` | — | Colloquial `見れる` for `見られる`. | -| `no-hankaku-kana` | — | Halfwidth kana forbidden. | -| `no-exclamation-question-mark` | — | `!` / `?` in technical docs. | -| `ja-no-weak-phrase` | — | `かもしれない`, `と思います`. | -| `ja-no-successive-word` | — | Repeated words. | -| `ja-no-abusage` | — | Misused kanji. | -| `ja-no-redundant-expression` | — | `することができる` → `できる`. | -| `ja-unnatural-alphabet` | — | IME miscarriages. | - -All thresholds are user-tunable via profile configuration. - -## References - -- textlint: [textlint.github.io](https://textlint.github.io). -- [`textlint-rule-preset-ja-technical-writing`](https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing). - -## See also - -- [JTF rules](/metrics/markdown/prose/jtf-rules) — orthogonal Japanese style guide. -- [Wording quality](/metrics/markdown/prose/wording-quality) — English style flags. diff --git a/docs/metrics/markdown/prose/wording-quality.mdx b/docs/metrics/markdown/prose/wording-quality.mdx deleted file mode 100644 index 8dcef35d..00000000 --- a/docs/metrics/markdown/prose/wording-quality.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "Wording quality" -description: "Style and register: passive voice, hedges, weasels, wordy phrases, adverbs, nominalizations, expletives, illusions, cliches, long sentences." -keywords: ["wording quality", "passive voice", "hedge words", "style", "writing quality"] ---- - -Wording quality is style and register. Where [readability formulas](/metrics/markdown/prose/english-readability) -score difficulty, wording quality flags writing patterns that consistently hurt clarity. - -## What mehen emits - -| Sub-metric | Default threshold | -|---|---| -| **Passive voice** ([write-good](https://github.com/btford/write-good) / retext-passive pattern) | Doc-type ratio from the [readability ensemble](/metrics/markdown/prose/english-readability). | -| **Hedge words** (Hyland 2005; ~165 entries) | Flag > 3 % in non-narrative docs. | -| **Weasel words** (write-good) | Count-based. | -| **Wordy phrases** (~240 entries from too-wordy / retext-simplify) | Per-match count / 100 words. | -| **Adverb density** (`-ly` endings minus exceptions) | Hemingway budget ≤ 1 per 100 words. | -| **Nominalizations** (`-tion`, `-sion`, `-ment`, `-ence`, `-ance`, `-ity`, `-ness`, `-ism`) | Flag paragraph > 10 % of content words. | -| **Expletive constructions** (`^(there\|it)\s+(is\|are\|was\|were)`) | Per 100 sentences. | -| **Lexical illusions** (`lower(t[i-1]) == lower(t[i])`) | Zero-tolerance defect. | -| **Clichés** (~700 entries) | Per 1,000 words. | -| **Non-words** (`irregardless → regardless`, `thusly → thus`, …) | Error-level flag. | -| **Long sentences** | Warning > 30 words, error > 40. | - -## Wording Quality Score - -```text -WordingQualityScore = clamp01( - 1 - − 0.18 · sat(passive_ratio; 0.25, 0.60) - − 0.15 · sat(hedge_density; 0.02, 0.08) - − 0.12 · sat(weasel_density; 0.01, 0.05) - − 0.12 · sat(wordy_density; 0.01, 0.05) - − 0.10 · sat(adverb_density; 0.02, 0.06) - − 0.08 · sat(nominalization_density; 0.08, 0.20) - − 0.08 · sat(long_sentence_rate; 0.05, 0.30) - − 0.07 · sat(cliche_density; 0.002, 0.02) - − 0.05 · (lexical_illusions > 0 ? 1 : 0) - − 0.05 · (nonword_count > 0 ? 1 : 0) -) -``` - -WQS is deliberately orthogonal to [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk): -Filler covers repetition and specificity, WQS covers style and register. - -## References - -- Hyland, K. (2005). *Metadiscourse: Exploring Interaction in Writing.* Continuum. -- Williams, J. M. (1981). *Style: Lessons in Clarity and Grace.* University of Chicago Press. -- [write-good rules](https://github.com/btford/write-good). -- [proselint](https://github.com/amperser/proselint). -- [retext-passive](https://github.com/retextjs/retext-passive). -- [Hemingway editor](https://hemingwayapp.com). - -## See also - -- [English readability ensemble](/metrics/markdown/prose/english-readability) — orthogonal difficulty - axis. -- [Inclusive language](/metrics/markdown/prose/inclusive-language) — separate flag list. diff --git a/docs/metrics/markdown/repository-grounding.mdx b/docs/metrics/markdown/repository-grounding.mdx deleted file mode 100644 index c1983fb1..00000000 --- a/docs/metrics/markdown/repository-grounding.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "Repository Grounding" -description: "How much a Markdown file connects to repository reality — files, commands, packages, APIs, configs, tests, and versioned facts." -keywords: ["repository grounding", "documentation", "cross-references"] ---- - -A Markdown file in a software project should connect to repository reality — files, commands, packages, -APIs, configs, tests, and versioned facts — or at least acknowledge that it doesn't. - -## Formula - -```text -RepositoryGroundingScore = clamp01( - 0.25 · sat(repo_link_density; 0.5, 4.0) - + 0.25 · path_resolution_rate - + 0.20 · sat(code_example_density; 0.5, 3.0) - + 0.15 · sat(identifier_density; 0.02, 0.12) - + 0.15 · sat(version_fact_density; 0.01, 0.08) -) -``` - -## Components - -- **Repo link density** — relative repo links per 100 words. -- **Path resolution rate** — how many path-like tokens resolve to actual files. -- **Code example density** — labelled code-fence count per 100 words. -- **Identifier density** — identifier-like tokens (CamelCase, snake_case, dotted paths) per word. -- **Version fact density** — version pins, semver, dates, hash references per word. - -## Bands - -| Score | Meaning | -|---|---| -| 0.00–0.20 | Almost none. | -| 0.21–0.50 | Weak. | -| 0.51–0.80 | Useful. | -| 0.81–1.00 | Very grounded. | - -## How downstream metrics use it - -- [**Filler / Lazy Risk**](/metrics/markdown/filler-lazy-risk) consumes `1 − RepositoryGroundingScore` - as one of its sub-scores. -- The PR comment surfaces a 🔴 callout when grounding crosses a band downward. - -## References - -- Pirolli, P. & Card, S. (1999). *Information Foraging.* Psychological Review 106(4): 643–675 — - underpins the "scent" intuition behind link-density and identifier-density. - [DOI](https://doi.org/10.1037/0033-295X.106.4.643). -- Spence, R. (1999). *A framework for navigation.* International Journal of Human-Computer Studies - 51(5): 919–945 — navigation framework that motivates resolved-link weighting. - [DOI](https://doi.org/10.1006/ijhc.1999.0265). - -## See also - -- [Evidence Coverage](/metrics/markdown/evidence-coverage) — per-section structural support. -- [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk) — uses grounding as an input. diff --git a/docs/metrics/markdown/review-criticality-index.mdx b/docs/metrics/markdown/review-criticality-index.mdx deleted file mode 100644 index 1ccf7aef..00000000 --- a/docs/metrics/markdown/review-criticality-index.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "Review Criticality Index" -description: "Should I review this document carefully? Combines per-word density with delta and changed-anchor terms." -keywords: ["rci", "review criticality", "documentation review", "diff"] ---- - -**RCI** answers "Should I review this document carefully?". A small document can be review-critical if -it is dense with technical anchors. RCI combines a per-word **DensityScore** with a delta term and a -changed-links/artifacts term. - -## Formula - -```text -DensityScore = mehen-internal blend of: - MCC per word - + MDH volume per word - + RepositoryGroundingScore - + EvidenceCoverageScore - + LinkReviewBurden per word - + embedded code complexity per word - -RCI = clamp01( - 0.65 · DensityScore - + 0.20 · sat(abs(metric_delta_percent); 10, 60) - + 0.15 · sat(changed_links_or_artifacts; 2, 20) -) · 100 -``` - -## Bands - -| RCI | Meaning | -|---|---| -| 0–25 | Low — skim is fine. | -| 26–50 | Normal review. | -| 51–75 | Careful review recommended. | -| 76–100 | High-risk change. | - -## DMI × RCI × Filler matrix - -| DMI | RCI | Filler Risk | Meaning | -|---|---|---|---| -| High | Low | Low | Long but easy and probably healthy. | -| High | Low | High | Easy to maintain but likely low-value filler. | -| Low | High | Low | Dense valuable doc; review carefully. | -| Low | High | High | Dangerous: hard to maintain *and* weakly grounded. | - -This matrix is the canonical way to summarize a Markdown file in CI. - -## References - -- Bacchelli, A. & Bird, C. (2013). *Expectations, outcomes, and challenges of modern code review.* - ICSE 2013 — empirical basis for prioritizing review attention by per-change density. - [DOI](https://doi.org/10.1109/ICSE.2013.6606617) · - [Author copy](https://www.microsoft.com/en-us/research/publication/expectations-outcomes-and-challenges-of-modern-code-review/). -- Rigby, P. C. & Bird, C. (2013). *Convergent contemporary software peer review practices.* - ESEC/FSE 2013 — supports the "review what changed" prioritization that RCI encodes. - [DOI](https://doi.org/10.1145/2491411.2491444). - -## See also - -- [DMI](/metrics/markdown/dmi) — orthogonal "is it maintainable?" axis. -- [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk) — orthogonal "is it filler?" axis. -- [PR comment design](/guides/pr-comment-design) — RCI in the drill-down section. diff --git a/docs/metrics/markdown/section-balance.mdx b/docs/metrics/markdown/section-balance.mdx deleted file mode 100644 index ec62b7a8..00000000 --- a/docs/metrics/markdown/section-balance.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Section Balance" -description: "Whether a Markdown document is chunked in a maintainable way." -keywords: ["section balance", "headings", "structure", "documentation"] ---- - -**Section Balance** checks whether the document is chunked in a maintainable way. It penalizes: - -- Oversized sections at the 95th percentile. -- A high rate of very large sections. -- A high rate of tiny sections. -- Heading skips (e.g., `H2 → H4`). -- Heading depth deviation from a profile-specific expectation. - -## Inputs - -- The [section tree](/metrics/markdown/section-tree). -- Per-section word counts from the LOC family. -- Profile-specific expected depth (default depends on doc type). - -## How DMI uses it - -Section Balance feeds [DMI](/metrics/markdown/dmi) via the `S_norm` term — "poor section balance" -*reduces* DMI. - -## References - -- Miller, G. A. (1956). *The magical number seven, plus or minus two: some limits on our capacity - for processing information.* Psychological Review 63(2): 81–97 — working-memory ceiling that - motivates the oversized-section penalty. - [DOI](https://doi.org/10.1037/h0043158). -- Sweller, J. (1988). *Cognitive load during problem solving: Effects on learning.* Cognitive - Science 12(2): 257–285 — cognitive-load theory underlying the "too-many-tiny-sections vs. - too-large-section" trade-off. - [DOI](https://doi.org/10.1207/s15516709cog1202_4). - -## See also - -- [Section tree](/metrics/markdown/section-tree) — input structure. -- [Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk) — separate "lazy sectioning" sub-score. -- [Good Scaffold](/metrics/markdown/good-scaffold) — orthogonal "did the scaffolding help?" axis. diff --git a/docs/metrics/markdown/section-tree.mdx b/docs/metrics/markdown/section-tree.mdx deleted file mode 100644 index e6cdf075..00000000 --- a/docs/metrics/markdown/section-tree.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "Section tree" -description: "Heading-derived section structure with quality flags (skips, chunking smell, fragmentation smell)." -keywords: ["section tree", "headings", "structure", "documentation"] ---- - -Headings produce a derived **section tree** that downstream metrics ([MCC](/metrics/markdown/mcc), -[Filler / Lazy Risk](/metrics/markdown/filler-lazy-risk), -[Section Balance](/metrics/markdown/section-balance)) read from. Every section has a heading level, -byte/line range, parent/child IDs, word count, and per-section artifact and link counts. - -## Structure - -Each section node carries: - -```text -Section -├── heading_level : 1..6 -├── byte_range -├── line_range -├── parent_id, children_ids -├── word_count -├── artifact_counts : { code, table, image, diagram, math } -└── link_counts : { internal, relative, external, broken } -``` - -## Quality flags - -mehen marks three structural smells on the section tree: - -| Flag | Trigger | -|---|---| -| **Heading skip** | Direct nesting jump (e.g., `H1 → H4` without an intervening `H2`/`H3`). | -| **Chunking smell** | An `H2` section that is oversized relative to the document's `p95` length. | -| **Fragmentation smell** | A document flooded with very short `H5`/`H6` nodes — over-decomposition. | - -These flags surface on the [PR comment](/guides/pr-comment-design) as advisory callouts. - -## How downstream metrics use the tree - -- [**MCC**](/metrics/markdown/mcc) reads heading-level changes to charge nesting penalties. -- [**Filler / Lazy Risk**](/metrics/markdown/filler-lazy-risk) reads section sizes to detect "shallow big - doc". -- [**Section Balance**](/metrics/markdown/section-balance) penalizes oversized sections at the 95th - percentile. -- [**Evidence Coverage**](/metrics/markdown/evidence-coverage) computes per-section evidence anchor - density. - -## References - -- W3C: [Web Content Accessibility Guidelines 2.1 — Heading levels](https://www.w3.org/WAI/WCAG21/Understanding/headings-and-labels.html) - — the source of the heading-skip quality flag (assistive-technology users rely on heading-level - ordering). -- CommonMark Spec: [ATX headings](https://spec.commonmark.org/0.30/#atx-headings) and - [setext headings](https://spec.commonmark.org/0.30/#setext-headings) — the parser-level definition - the section tree builds on. - -## See also - -- [LOC family](/metrics/markdown/loc-family) — feeds per-section line counts. -- [Section Balance](/metrics/markdown/section-balance) — balance scoring on the tree. diff --git a/docs/metrics/markdown/table-burden.mdx b/docs/metrics/markdown/table-burden.mdx deleted file mode 100644 index 708d7a7f..00000000 --- a/docs/metrics/markdown/table-burden.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Table Burden + Scaffold" -description: "When tables help comprehension and when they become maintenance artifacts." -keywords: ["table burden", "table scaffold", "documentation", "tables"] ---- - -Tables are valuable up to a point. A table with 6–60 cells usually improves comprehension; a table with -300+ cells is usually a maintenance artifact that belongs in generated output or structured data. - -## Per-table burden - -Combines wide, long, and cell-count saturation terms with missing-header, empty-cell, and -alignment-complexity penalties: - -```text -TableBurdenScore = 0.5 · mean(T_burden) + 0.5 · max(T_burden) -``` - -The blend of mean and max means a single very large table moves the score even when most other tables -are fine. - -## Table Scaffolding Score - -Uses a piecewise size credit: - -| Cells | Credit | -|---|---| -| 1–5 | `0.2` — too small to matter. | -| 6–60 | `1.0` — useful comparison scaffold. | -| 61–150 | `max(0, 1 − (cells − 60) / 120)`. | -| > 150 | More burden than scaffold; credit is near zero. | - -A **hard warning** fires when `cells > 300` OR `cols > 12` OR `rows > 100`, with the suggested -remediation: split the table, generate it from structured data, or move the source to YAML/JSON/CSV. - -## How DMI uses it - -Table Burden contributes to [DMI](/metrics/markdown/dmi) via the `T_norm` term; Table Scaffolding is one -of the components of [Good Scaffold](/metrics/markdown/good-scaffold). - -## References - -- Tufte, E. R. (2001). *The Visual Display of Quantitative Information*, 2nd ed. Graphics Press — - classic reference on when tables aid comprehension and when they become noise. -- Few, S. (2012). *Show Me the Numbers: Designing Tables and Graphs to Enlighten*, 2nd ed. - Analytics Press — concrete guidance on table sizing and the cell-count thresholds adopted here. -- W3C: [Tables Tutorial — Tables in WCAG](https://www.w3.org/WAI/tutorials/tables/) — defines - header-row requirements that the missing-header penalty enforces. - -## See also - -- [Visual Scaffold](/metrics/markdown/visual-scaffold) — same idea for diagrams and images. -- [Artifact Debt](/metrics/markdown/artifact-debt) — broader artifact-hygiene metric. diff --git a/docs/metrics/markdown/visual-scaffold.mdx b/docs/metrics/markdown/visual-scaffold.mdx deleted file mode 100644 index bc073ad1..00000000 --- a/docs/metrics/markdown/visual-scaffold.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Visual Scaffold + Net Effect" -description: "How much diagrams and images help vs. hurt comprehension." -keywords: ["visual scaffold", "diagrams", "images", "documentation"] ---- - -A diagram or image helps comprehension only when it is labelled, bounded, nearby-explained, and its -target resolves. - -## Per-visual scaffold - -```text -V_scaffold(v) = - alt_or_caption(v) - · nearby_reference(v) - · bounded_size(v) - · repo_resolved(v) -``` - -Each factor is in `[0, 1]`. A diagram that is well captioned, referenced from prose nearby, bounded in -size, and whose target resolves earns a full credit; missing any factor pulls the credit toward zero. - -Aggregated with diminishing returns: - -```text -VisualScaffoldScore = clamp01(sum(V_scaffold(v)) / max(1, sqrt(W/500 + 1))) -``` - -## Diagram Complexity - -For parseable diagrams (Mermaid, GraphViz, etc.): - -```text -DiagramComplexity = - 0.40 · diagram_nodes - + 0.55 · diagram_edges - + 1.50 · diagram_cycles - + 2.00 · parse_error - + 1.00 · missing_title_or_caption -``` - -Cycles require mental simulation; parse errors and missing captions are maintenance defects. - -## Visual Net Effect - -```text -VisualNetEffect = Σ DiagramComplexity + Σ image_complexity − 2.0 · Σ V_scaffold(v) -``` - -| Sign | Meaning | -|---|---| -| Negative | Visuals probably help more than they hurt. | -| Positive | Visuals are under-explained or too complex. | - -## References - -- Mayer, R. E. (2009). *Multimedia Learning*, 2nd ed. Cambridge University Press — multimedia - principle and contiguity principle behind "must be referenced from prose nearby". -- Larkin, J. H. & Simon, H. A. (1987). *Why a diagram is (sometimes) worth ten thousand words.* - Cognitive Science 11(1): 65–100 — when diagrams help vs. hurt comprehension; the basis for the - bounded-size and parse-error terms. - [DOI](https://doi.org/10.1111/j.1551-6708.1987.tb00863.x). -- W3C: [WCAG 2.1 — Non-text Content (1.1.1)](https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html) - — the source of the alt-or-caption requirement. - -## See also - -- [Table Burden + Scaffold](/metrics/markdown/table-burden) — same idea for tables. -- [Artifact Debt](/metrics/markdown/artifact-debt) — broader hygiene metric. -- [Good Scaffold](/metrics/markdown/good-scaffold) — combines visual + table + code-example credits. diff --git a/docs/metrics/sql/coverage.mdx b/docs/metrics/sql/coverage.mdx deleted file mode 100644 index 6ec51b5e..00000000 --- a/docs/metrics/sql/coverage.mdx +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: "SQL coverage" -description: "Ingesting test coverage for .sql files from utPLSQL (Oracle) and SQLCover (SQL Server): file-name mapping so report entries match repository paths, and the Cobertura transform for OpenCover output." -keywords: ["sql coverage", "utPLSQL", "SQLCover", "tSQLt", "cobertura", "opencover", "reportgenerator", "file mapping"] ---- - -Coverage ingestion in mehen is language-agnostic: the [coverage metrics](/metrics/coverage/overview) -attach to any analyzed file that a report measures, and `.sql` files are no exception. Two -mainstream stacks produce real coverage for SQL sources: - -| Stack | Test framework | Coverage emitter | Format | -|---|---|---|---| -| Oracle PL/SQL | [utPLSQL](https://www.utplsql.org/) | `ut_coverage_cobertura_reporter` | Cobertura XML — ingested directly | -| SQL Server T-SQL | [tSQLt](https://tsqlt.org/) | [SQLCover](https://github.com/GoEddie/SQLCover) | OpenCover XML — needs a transform | - -Both need one deliberate step in the pipeline before mehen sees usable data. This page covers -those two steps; the metric semantics live on the -[line](/metrics/coverage/line), [branch](/metrics/coverage/branch), and -[function](/metrics/coverage/function) pages. - -## What to expect from SQL coverage - -Oracle's instrumentation (`DBMS_PLSQL_CODE_COVERAGE`, which utPLSQL drives) reports **lines -only**: utPLSQL's Cobertura output marks every line `branch="false"` and emits no `` -elements. A measured `.sql` file therefore publishes `coverage.line`, `coverage.line.covered`, -and `coverage.line.total` — and nothing else. `coverage.branch` and `coverage.function` stay -*absent*, not zero: a gate on an unmeasured dimension skips rather than fails, per the -[measured-or-absent rule](/metrics/coverage/overview). SQLCover reports statement coverage, -which likewise lands on the line dimension after the Cobertura transform. - -Coverage attaches at two granularities for SQL. The file root carries the totals, and every -*routine* — a standalone `CREATE FUNCTION`/`PROCEDURE`/`TRIGGER`, a routine inside a package or -type body, or a subprogram declared in another routine's DECLARE section — is a function space -in the [metric tree](/concepts/spaces), nested under its statement's span. Each routine space -receives `coverage.line` (and `coverage.branch`, when measured) scoped to its own line range, -exactly like functions in any other language: a package body at 50% stops being one opaque -number and becomes "``get_a`` 100%, ``set_b`` 0%". Statement spaces themselves carry no -coverage keys — the routine is the meaningful unit, and it is the granularity the planned CRAP -composite consumes. [`top-offenders`](/commands/top-offenders) ranks files, so gates stay -file-level; the per-routine values live on the spaces in the JSON report. - -## utPLSQL: map database objects to file names - -This is the step most pipelines miss. Run without file mapping, utPLSQL writes *database object -identifiers* where Cobertura expects file paths: - -```xml - -``` - -`hr.betwnstr` is `schema.unit` from the Oracle dictionary. No spelling of a repository path ends -in it, so [path matching](/metrics/coverage/path-matching) correctly refuses to attribute the -data — every `.sql` file reports "unmeasured", and `mehen metrics -v` logs that the report's -entries matched nothing. - -utPLSQL's fix is [project-based coverage](https://www.utplsql.org/utPLSQL/latest/userguide/coverage.html): -hand utPLSQL-cli your source tree with `-source_path`, and it maps database objects back to the -files that created them, writing repository paths into the report: - -```bash -utPLSQL-cli/bin/utplsql run test_runner/pass@db_url \ - -p=hr \ - -source_path=sources \ - -f=ut_coverage_cobertura_reporter -o=cobertura.xml -``` - -```xml - -``` - -Run utPLSQL-cli from the repository root so the emitted paths are root-relative, then: - -```bash -mehen metrics sources --coverage=cobertura.xml -``` - -Naming the output `cobertura.xml` (or `coverage.xml`) also makes it eligible for -[auto-discovery](/metrics/coverage/auto-discovery), so bare `--coverage` works too. - - -utPLSQL's default mapping expects `owner.object_name.type` file names (`hr.betwnstr.fnc`). If -your layout encodes owner or type in directories instead (`sources/hr/functions/betwnstr.sql`), -pass the documented `-regex_expression`, `-owner_subexpression`, `-name_subexpression`, and -`-type_mapping` options to describe it — see -[file mapping using custom regular expressions](https://www.utplsql.org/utPLSQL/latest/userguide/coverage.html). - - - -Report line numbers come from the *stored unit source*, which begins at the unit header -(`FUNCTION betwnstr(...)`) — Oracle strips the `CREATE OR REPLACE` prefix. utPLSQL's -[object-file mapping rules](https://www.utplsql.org/utPLSQL/latest/userguide/coverage.html) -require each file to hold exactly one object "as is", with no commands or blank lines before -`CREATE`: that discipline is what keeps report line numbers aligned with file line numbers. -A prologue of `SET` commands or license comments shifts every measured line. - - -## SQLCover: transform OpenCover output to Cobertura - -SQLCover (the coverage layer usually paired with tSQLt) emits **OpenCover-format XML**, which is -not one of mehen's [ingested formats](/metrics/coverage/supported-formats). The standard .NET -bridge closes the gap: [ReportGenerator](https://github.com/danielpalme/ReportGenerator) -converts OpenCover to Cobertura. Add one step between test run and mehen: - -```bash -# 1. Run tSQLt tests under SQLCover -> Coverage.opencover.xml -# 2. Transform to Cobertura -reportgenerator "-reports:Coverage.opencover.xml" \ - "-targetdir:coverage" "-reporttypes:Cobertura" - -# 3. Ingest (ReportGenerator writes coverage/Cobertura.xml) -mehen metrics . --coverage=coverage/Cobertura.xml -``` - -The same caveat applies as with utPLSQL: SQLCover only knows object names the database knows. -Its reports name objects like `[dbo].[betwnstr]`, and the paths that reach the Cobertura output -depend on how your deployment scripts fed SQLCover. Inspect one `filename` attribute from the -transformed report and confirm a repository path can end with it before wiring a gate — the -[path-matching page](/metrics/coverage/path-matching) explains exactly which spellings -reconcile. - -## Gating - -Once report entries carry repository paths, SQL files participate in coverage thresholds and -ranking like any other language: - -```toml -[thresholds] -"coverage.line" = 80 -``` - -```bash -mehen top-offenders sources -M coverage.line --coverage=cobertura.xml -``` - -Unmeasured files skip the gate entirely — so a mapping regression degrades to "no data", never -to a spurious red build. If a previously measured directory suddenly reports nothing, that is -the signal to re-check the file-name mapping, not the tests. - -## References - -- [utPLSQL user guide: Code coverage](https://www.utplsql.org/utPLSQL/latest/userguide/coverage.html) — - project-based coverage, file mapping parameters, and object-file mapping rules. *utPLSQL project.* -- [utPLSQL-cli README](https://github.com/utPLSQL/utPLSQL-cli) — `-source_path`, `-regex_expression`, - and reporter options. *utPLSQL project.* -- [DBMS_PLSQL_CODE_COVERAGE](https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/DBMS_PLSQL_CODE_COVERAGE.html) — - the Oracle-supplied instrumentation utPLSQL drives (basic-block granularity). *Oracle Database documentation.* -- [SQLCover](https://github.com/GoEddie/SQLCover) — coverage collection for SQL Server, OpenCover output. *Ed Elliott.* -- [tSQLt](https://tsqlt.org/) — the SQL Server unit-testing framework SQLCover pairs with. -- [ReportGenerator](https://github.com/danielpalme/ReportGenerator) — OpenCover-to-Cobertura - conversion (`-reporttypes:Cobertura`). *Daniel Palme.* diff --git a/docs/metrics/sql/overview.mdx b/docs/metrics/sql/overview.mdx deleted file mode 100644 index 8eea42e4..00000000 --- a/docs/metrics/sql/overview.mdx +++ /dev/null @@ -1,144 +0,0 @@ ---- -title: "SQL metrics" -description: "What the mehen-sql analyzer measures: query-block structure, CTE graphs, join graphs, predicate complexity, object-touch risk, and an SQL Halstead." -keywords: ["sql metrics", "mehen-sql", "query complexity", "cte", "halstead sql"] ---- - -A dedicated SQL analyzer (`mehen-sql`) introduces a new `sql.*` metric namespace tailored to -standalone `.sql` files — ad-hoc queries, analytics models, migration scripts, stored-program -bodies, DDL packages, and mixed scripts. It is backed by the -[sqruff](https://github.com/quarylabs/sqruff) dialect-aware SQL parser. - - -SQL files (`.sql`, `.ddl`, `.dml`) are analyzed automatically. The dialect is inferred from syntax -hints with a reported confidence (`sql.dialect.confidence`), falling back to ANSI. mehen compiles -ANSI, postgres, T-SQL, snowflake, bigquery, mysql, sqlite, oracle, clickhouse, redshift, sparksql, -hive, athena, and db2. - - -## Selecting a dialect - -Dialect inference is a best-effort guess. To pin a file's dialect deterministically, add an in-file -directive on its own line, using the same syntax as -[SQLFluff's in-file configuration](https://docs.sqlfluff.com/en/stable/configuration/setting_configuration.html#in-file-configuration-directives): - -```sql --- sqlfluff:dialect:postgres -SELECT id FROM users RETURNING id; -``` - -When present, the directive overrides inference: `sql.dialect.confidence` is reported as `1.0`, -`sql.dialect.directive_present` is `1`, and `sql.dialect.is_` reflects the pinned dialect. - -mehen mirrors SQLFluff's parsing of this directive: - -- Both `-- sqlfluff:dialect:` and `--sqlfluff:dialect:` (no space) are accepted. - Whitespace around the `dialect:` separator is ignored, but the `sqlfluff:` prefix itself must - be exact. -- The directive must start at the beginning of the line — an **indented** directive is ignored (this - matches SQLFluff). -- Only `--` line comments are honored; **block comments** (`/* sqlfluff:dialect:… */`) are not. -- If several directives appear, the **last** one wins. -- An **unknown** dialect name (`sql.dialect.unknown`) or one **not compiled** into this build such as - `databricks`, `duckdb`, or `trino` (`sql.dialect.unsupported`) emits a non-blocking warning and - falls back to inference — it never aborts the analysis. - - -sqruff (mehen's parser) does **not** itself consume SQLFluff in-file configuration — it silently -ignores the directive (and older builds panic on some inline-config forms). mehen therefore parses -the `dialect` directive itself and only ever hands sqruff a resolved, validated dialect. One -intentional divergence from SQLFluff: SQLFluff matches dialect names **case-sensitively**, and so -does mehen — `-- sqlfluff:dialect:Postgres` (capital P) is reported as an unknown dialect, exactly as -SQLFluff would reject it. - - -## Why SQL gets its own family - -SQL should not be squeezed into the existing function/class-centric metric model. The dominant -complexity mechanism in standalone SQL is **relational/dataflow structure** rather than imperative -control flow: - -- Cyclomatic complexity is meaningful for procedural PL/SQL or T-SQL, but not for ordinary declarative - SELECT-heavy files. -- A SELECT with 10 joins and 5 CTEs may have no imperative branches while still being difficult to - review. -- Object-touch risk (DROP, TRUNCATE, MERGE without WHERE) often dominates "review burden" in migration - scripts. - -## Metric namespaces - -These `sql.*` keys are published today (raw metrics — research foundation §15): - -| Namespace | Keys | -|---|---| -| `sql.loc.*` | `physical`, `code`, `comment`, `blank`, `logical`, `comment_density`, `max_statement_lines`, `avg_statement_lines`. | -| `sql.statement.*` | `count`, `kind_count.`, `kind_distinct`, `kind_entropy`, `unparsed_count`. | -| `sql.query_block.*` | `count`, `max_depth`, `avg_select_items`, `max_select_items`. | -| `sql.cte.*` | `count`, `recursive_count`, `dependency_edges`, `max_dependency_depth`, `max_fan_out`, `unused_count`. | -| `sql.join.*` | `count`, `kind_count.`, `outer_count`, `cross_count`, `natural_count`, `non_equi_count`, `missing_condition_count`. | -| `sql.subquery.*`, `sql.derived_table.*` | `count`, `max_depth`, `correlated_count`, `scalar_count`, `exists_count`, `in_count`. | -| `sql.predicate.*` | `boolean_operator_count`, `max_boolean_depth`, `not_count`, `comparison_count`, `null_semantics_risk_count`. | -| `sql.case.*` | `count`, `max_depth`, `when_count`, `max_when_count`, `missing_else_count`. | -| `sql.aggregate.*`, `sql.group_by.*`, `sql.having.*` | `function_count`, `distinct_count`, `count`, `rollup_count`, `cube_count`, `grouping_sets_count`. | -| `sql.window.*` | `function_count`, `frame_count`, `partition_expression_count`, `order_expression_count`. | -| `sql.set_op.*` | `count`, `kind_count.`, `union_all_ratio`. | -| `sql.expression.*`, `sql.function.*`, `sql.cast.*` | `max_depth`, `call_count`, `distinct_count`, `nested_call_depth`, `count`. | -| `sql.select.*` | `star_count`, `outer_star_count`, `expression_without_alias_count`, `output_alias_coverage`. | -| `sql.identifier.*`, `sql.alias.*`, `sql.relation.*` | `unqualified_column_ratio`, `quoted_count`, `table_alias_count`, `ref_count`. | -| `sql.object.*`, `sql.dml.*`, `sql.ddl.*`, `sql.dcl.*`, `sql.transaction.*` | Object-touch and migration-risk counts (`read_count`, `write_count`, `drop_count`, `truncate_count`, `update_without_where_count`, …). | -| `sql.dialect.*` | `confidence`, `conflict_count`, `requested`, `directive_present`, `is_`. | -| `sql.parser.*` | `diagnostic_count`, `unparsable_segment_count`, `unparsable_line_count`, `unparsable_ratio`. | -| `sql.halstead.*` | `distinct_operators`, `distinct_operands`, `total_operators`, `total_operands`, `vocabulary`, `length`, `volume`, `difficulty`, `effort`. | - -Procedural-SQL metrics (`sql.procedural.*` — cyclomatic/cognitive complexity for PL/SQL and T-SQL -routines) remain on the [roadmap](/metrics/sql/roadmap). - -## Composite scores - -All six explainable composite scores ship today (research foundation §8): - -- `sql.structural_complexity` — CTE depth, join count, subquery depth, CASE depth, window count, set op - count. -- `sql.cognitive_complexity` — SQL analogue of code cognitive complexity. -- `sql.review_burden_index` — file-level rank (0–100) for likely PR review effort. -- `sql.change_risk_score` — operational risk in migration scripts. -- `sql.maintainability_index` — composite (0–100, higher is better) with band interpretation. -- `sql.modularity_health` — CTE use ratio, fan-out, derived-table penalty (0–100; N/A without CTEs). - -## Prior art and scientific basis - -The metric model is informed by the following work: - -- **SonarQube PL/SQL and T-SQL** — defines cyclomatic complexity for procedural blocks (anonymous - blocks, procedures, triggers, loops, `WHEN`, `IF`/`ELSIF`, `RAISE`, `AND`/`OR`). - [PL/SQL docs](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/pl-sql) · - [T-SQL docs](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/t-sql). -- **SQLFluff** and **sqruff** — dialect-aware parsing and linting; their structure rules - (nested-CASE, unused-CTE, ambiguous-column-count, qualification, implicit cross-join) are - reusable inspiration for metric contributors. - [SQLFluff docs](https://docs.sqlfluff.com/en/stable/) · - [sqruff docs](https://playground.quary.dev/docs/). -- **`sqlfluff-complexity` plugin** — practical baseline for CPX-style metrics: CTE count, join - count, nested subquery depth, CASE expressions, boolean operators, window functions, CTE - dependency depth, set operations, derived tables. - [Repo](https://github.com/yu-iskw/sqlfluff-complexity). -- **Vashistha & Jain — *Measuring Query Complexity in SQLShare Workload*** — frames query - complexity as cognitive load on users authoring SQL, with operators / operands / runtime / - Halstead-style measures. - [PDF](https://uwescience.github.io/sqlshare/pdfs/Jain-Vashistha.pdf). -- **Piattini & Martínez — *Measuring for Database Programs Maintainability*** — early SQL - maintainability measures with empirical validation. - [DOI](https://doi.org/10.1007/3-540-44469-6_7). -- **Spider** — text-to-SQL benchmark; its hardness criteria (number of components, selections, - conditions, keywords like `GROUP BY` / nested subqueries / aggregators) align well with static - query complexity features. - [arXiv:1809.08887](https://arxiv.org/abs/1809.08887) · - [Benchmark site](https://yale-lily.github.io/spider). - -See [SQL metrics roadmap](/metrics/sql/roadmap) for the implementation phases. - -## See also - -- [Code metrics](/metrics/code/overview) — the existing source-code suite. -- [Markdown metrics](/metrics/markdown/overview) — the existing documentation suite. -- [Concepts → Spaces](/concepts/spaces) — how SQL spaces will fit the existing model. diff --git a/docs/metrics/sql/roadmap.mdx b/docs/metrics/sql/roadmap.mdx deleted file mode 100644 index a935169f..00000000 --- a/docs/metrics/sql/roadmap.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: "SQL metrics roadmap" -description: "Implementation phases for the mehen-sql analyzer." -keywords: ["mehen-sql roadmap", "sql analyzer", "implementation"] ---- - -The SQL analyzer ships in phases. Each phase delivers usable output before the next phase compounds on -it. - -## Phase 1 — parser adapter and raw metrics ✅ shipped - -Deliverables: - -- Dialect selection / configuration (CLI flag, project config, conservative inference). -- Parse diagnostics and parser-confidence metrics. -- Statement count and statement-kind classification. -- LOC / comment / blank / code metrics for `.sql` files. -- Query-block count / depth. -- CTE count and dependency graph. -- Join count / kind metrics. -- Subquery and derived-table metrics. -- CASE, boolean predicate, window, aggregate, set-operation counts. -- SELECT `*`, missing alias, unqualified column ratio. -- Basic DDL/DML risk metrics. -- SQL Halstead counts. - -This phase is enough to produce valuable top-offender output. - -## Phase 2 — composite scores ✅ shipped - -- `sql.structural_complexity`. -- `sql.cognitive_complexity`. -- `sql.review_burden_index`. -- `sql.change_risk_score`. -- `sql.maintainability_index`. -- `sql.modularity_health`. - -Composite scores are published alongside the raw metrics and feed `mehen top-offenders` / -`mehen diff` directly — any `sql.*` key is a valid selector and threshold target -(e.g. `mehen top-offenders --metric sql.change_risk_score`). Risk/complexity scores default to -higher-is-worse and maintainability/health scores to higher-is-better; prefix a metric with `+`/`-` -to override. Named profile presets (`sql.analytics_default`, `sql.migration_default`, -`sql.procedural_default`) and diff-aware delta gates remain to be wired through the threshold engine. - -## Phase 3 — procedural SQL - -- PL/SQL and T-SQL procedural block detection. -- Procedural cyclomatic / cognitive complexity (using Sonar's PL/SQL increments as reference). -- Exception / cursor / loop / dynamic-SQL metrics. -- Embedded query complexity attribution inside routines. - -## Phase 4 — optional schema and lineage enrichments - -- Optional schema catalog input. -- More accurate object/column reference resolution. -- Foreign-key-aware join graph classification. -- Optional sqruff lineage integration or mehen lineage implementation. -- Schema blast-radius metrics. - -## Dialect coverage - -`ansi` (default), `postgres`, `tsql`, `snowflake`, `bigquery`, `mysql`, `sqlite`, `oracle`, -`clickhouse`, `redshift`, `sparksql`, `athena`, `db2`. The dialect is inferred from syntax hints with -a reported confidence (`sql.dialect.confidence`), falling back to ANSI. - -## Validation strategy - -- **Golden fixtures** by dialect and file role (analytics, migration, procedural). -- **Prior-art compatibility tests** against `sqlfluff-complexity` CPX rules. -- **Repository calibration** on migration-heavy, dbt/analytics, app-embedded SQL, and PL/SQL projects. -- **Human validation** ranking sampled SQL files against `structural_complexity`, `cognitive_complexity`, - `review_burden_index`, Halstead volume, and LOC. - -## References - -- [SonarQube PL/SQL](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/pl-sql). -- [SonarQube T-SQL](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/t-sql). -- [SQLFluff complexity plugin](https://github.com/yu-iskw/sqlfluff-complexity). -- [sqruff](https://playground.quary.dev/docs/). -- Yu et al. (2018). *Spider: A Large-Scale Human-Labeled Dataset for Complex and Cross-Domain - Semantic Parsing and Text-to-SQL Task.* [arXiv:1809.08887](https://arxiv.org/abs/1809.08887) · - [Benchmark site](https://yale-lily.github.io/spider). -- Vashistha, A. & Jain, S. *Measuring Query Complexity in SQLShare Workload.* - [PDF](https://uwescience.github.io/sqlshare/pdfs/Jain-Vashistha.pdf). -- Piattini, M. & Martínez, A. *Measuring for Database Programs Maintainability.* - [DOI](https://doi.org/10.1007/3-540-44469-6_7). - -## See also - -- [SQL metrics overview](/metrics/sql/overview) — namespace inventory. -- [Concepts → Architecture](/concepts/architecture) — where `mehen-sql` will fit. diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx deleted file mode 100644 index d7109347..00000000 --- a/docs/quickstart.mdx +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: "Quickstart" -description: "Run your first mehen analysis, read the output, and wire mehen into a pull request workflow." -keywords: ["mehen quickstart", "first run", "github action"] ---- - -This guide covers three things: analyzing one file, scanning a repository for the worst offenders, and -producing a per-PR metric report from CI. - - - - See the full [installation guide](/installation). The shortest path: - - ```bash - npm install -g mehen - ``` - - - `mehen metrics` is the one-file command. It auto-detects the language and emits a report in - JSON (default), Markdown, YAML, or TOML. - - ```bash - mehen metrics src/main.py --pretty - ``` - - Source-code files yield the [code metric family](/metrics/code/overview); Markdown files yield the - [documentation suite](/metrics/markdown/overview). - - - `mehen top-offenders` walks one or more paths and ranks the files by one or more metrics: - - ```bash - mehen top-offenders src --metric cognitive --metric loc.lloc --max-results 20 - ``` - - Polarity is automatic — mehen knows that lower cognitive complexity is better. Override with `+` - or `-` prefixes when you want different ordering. - - - `mehen diff` compares two git revisions. This is the workhorse behind the - [GitHub Action](/guides/github-action): - - ```bash - mehen diff --from main --to HEAD --paths src --output-format markdown - ``` - - The same command renders the sticky GitHub comment when run from the action. - - - Drop a few lines into `.github/workflows/mehen.yml` to publish a metric trend on every PR: - - ```yaml - name: mehen - on: pull_request - - jobs: - mehen: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - issues: write - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - uses: ophi-dev/mehen@v1 - with: - paths: src - ``` - - See the [GitHub Action guide](/guides/github-action) for thresholds, monorepos, and the sticky - comment template. - - - -## Where to next - - - - Read what each metric means, with formulas and references. - - - Documentation Maintainability Index, link debt, filler/lazy risk, prose layer. - - - Inputs, outputs, thresholds, and PR comment design. - - - How mehen organizes parsers, analyzers, and the metric pipeline. - - diff --git a/docs/supported-languages.mdx b/docs/supported-languages.mdx deleted file mode 100644 index 57bbfeb8..00000000 --- a/docs/supported-languages.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: "Supported languages" -description: "Source-code and documentation languages mehen analyzes today, plus the parser backing each one." -keywords: ["mehen languages", "supported languages", "polyglot", "ruff", "oxc", "mago", "prism", "tree-sitter", "antlr", "pulldown-cmark"] ---- - -mehen supports eleven source languages, Markdown, and SQL. Per-file language detection is by extension, and the -matching analyzer crate owns parsing and metric interpretation. Each language uses the parser that -gives mehen the best semantic coverage for that ecosystem. - -## Source languages - -| Language | Extensions | Parser | -|---|---|---| -| **Python** | `.py` | [Ruff](https://docs.astral.sh/ruff/) (`ruff_python_parser` + `ruff_python_ast`) | -| **TypeScript / JavaScript** | `.ts`, `.mts`, `.cts`, `.js`, `.mjs`, `.cjs` | [Oxc](https://oxc.rs/) (`oxc_parser`) | -| **TSX / JSX** | `.tsx`, `.jsx` | [Oxc](https://oxc.rs/) (`oxc_parser`) | -| **PHP** | `.php` | [Mago](https://github.com/carthage-software/mago) (`mago-syntax`) | -| **Ruby** | `.rb` | [Prism](https://ruby.github.io/prism/) (`ruby-prism`) | -| **Rust** | `.rs` | [`ra_ap_syntax`](https://docs.rs/ra_ap_syntax/) (rust-analyzer's syntax library) | -| **Go** | `.go` | [tree-sitter-go](https://github.com/tree-sitter/tree-sitter-go) | -| **Kotlin** | `.kt`, `.kts` | [ANTLR](https://www.antlr.org/) — official [Kotlin spec grammar](https://github.com/Kotlin/kotlin-spec) via [antlr-rust-runtime](https://github.com/ophi-dev/antlr-rust-runtime) | -| **Java** | `.java` | [ANTLR](https://www.antlr.org/) — [grammars-v4 Java grammar](https://github.com/antlr/grammars-v4/tree/master/java/java) via [antlr-rust-runtime](https://github.com/ophi-dev/antlr-rust-runtime) | -| **C#** | `.cs`, `.csx` | [ANTLR](https://www.antlr.org/) — [Roslyn's own generated grammar](https://github.com/dotnet/roslyn/blob/main/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4) via [antlr-rust-runtime](https://github.com/ophi-dev/antlr-rust-runtime) | -| **C** | `.c`, `.h` | [tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c) | -| **PowerShell** | `.ps1`, `.psm1`, `.psd1` | [tree-sitter-pwsh](https://github.com/wharflab/tree-sitter-powershell) | - - -TypeScript is a superset of JavaScript, so mehen analyzes `.js` / `.mjs` / `.cjs` through the Oxc -TypeScript front-end and `.jsx` through Oxc's TSX front-end. - - -## Why these parsers - -- **Ruff** parses Python with full support for current syntax (3.13/3.14 features, f-strings, - `match`/`case`, exception groups, async constructs) and exposes a typed AST plus a semantic model. -- **Oxc** is a JavaScript/TypeScript toolchain in Rust and one of the fastest TS parsers in - production. It handles decorators, class fields, parameter properties, JSX, `satisfies`, `using`, - and dynamic import natively. -- **Mago** is a PHP toolchain in Rust. It understands attributes, promoted properties, enums, traits, - anonymous classes, readonly members, null-safe calls, and `match` expressions out of the box. -- **Prism** is the official Ruby parser maintained by the Ruby core team. It covers blocks, lambdas, - numbered parameters, modifier conditionals, rescue modifiers, endless methods, pattern matching, - and safe navigation. -- **`ra_ap_syntax`** is the syntax tree library used by rust-analyzer; it gives mehen exactly the - syntactic granularity rust-analyzer uses for its own analyses. -- **ANTLR** parses Kotlin, Java, and C#, generated to Rust by - [`ophi-dev/antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime). Kotlin uses the - official [Kotlin specification grammar](https://github.com/Kotlin/kotlin-spec), which models Kotlin - constructs (`when` entries, the elvis `?:` and safe-call `?.` operators, `catch` blocks, labeled - jumps, property accessors) as first-class, semantically-named rules. Java uses the community - [grammars-v4 Java grammar](https://github.com/antlr/grammars-v4/tree/master/java/java), which - covers modern Java (records, sealed types, switch expressions, text blocks, pattern matching, - modules). C# uses [Roslyn's own generated - grammar](https://github.com/dotnet/roslyn/blob/main/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4), - which the C# compiler generates from the same `Syntax.xml` model that produces its syntax node - classes — so it tracks C# *as implemented*: records, `is not`, `and`/`or` and relational patterns, - list patterns, collection expressions, raw strings, primary constructors, `required` members, and - the C# 14 additions (`field`, extension blocks). It replaced the community grammars-v4 C# grammar, - which stops at C# 7 and parsed 93 of 322 `System.Text.Json` files against 317 for the derived - Roslyn grammar; see `crates/mehen-csharp-parser/grammar/PROVENANCE.md` for the pinned revision and - what the derivation repairs. All three are richer than a tree-sitter CST. -- **Tree-sitter** is mehen's pick for Go, C, and PowerShell, where its grammar quality and - ecosystem maturity make it the best fit. - -## Documentation - -| Format | Extensions | Parser | -|---|---|---| -| **Markdown** | `.md`, `.markdown`, `.mdown`, `.mkd`, `.mkdn`, `.mdx` | [pulldown-cmark](https://github.com/pulldown-cmark/pulldown-cmark) | - -Markdown gets a dedicated documentation metric suite — code-style metrics like cyclomatic complexity -and NOM/NPA/NPM/WMC do not apply because Markdown has no functions or classes. See -[Markdown metrics](/metrics/markdown/overview) for the full set. - -## SQL - -| Format | Extensions | Parser | -|---|---|---| -| **SQL** | `.sql`, `.ddl`, `.dml` | [sqruff](https://github.com/quarylabs/sqruff) | - -A dedicated SQL analyzer (`mehen-sql`) ships its own metric family — query-block structure, CTE -graphs, join graphs, predicate complexity, object-touch risk, dialect portability, and an -SQL-flavored Halstead. Code-style metrics like cyclomatic complexity and NOM/NPA/NPM/WMC do not -apply to declarative SQL. The dialect is inferred from syntax hints (postgres, T-SQL, snowflake, -bigquery, mysql, sqlite, oracle, clickhouse, redshift, sparksql, hive, athena, db2) with a reported -confidence, defaulting to ANSI. See [SQL metrics overview](/metrics/sql/overview) for the full set. - -## Polyglot monorepos - -mehen runs per-file language detection over any directory tree. Pass multiple paths to limit which -trees are walked and let mehen pick supported languages from each: - -```bash -mehen top-offenders crates/api/src apps/web/src tools --metric cognitive -``` - -The [GitHub Action](/guides/github-action) accepts the same multi-path input. diff --git a/enums/Cargo.toml b/enums/Cargo.toml new file mode 100644 index 00000000..ca737674 --- /dev/null +++ b/enums/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "enums" +version = "0.0.1" +authors = ["Konstantin Vyatkin "] +edition = "2024" + +[dependencies] +clap = { version = "^4.0", features = ["derive"] } +askama = "^0.14" + +tree-sitter = "=0.25.3" +tree-sitter-typescript = "=0.23.2" +tree-sitter-python = "=0.23.6" +tree-sitter-rust = "=0.23.2" +tree-sitter-go = "=0.23.4" + +[profile.release] +strip = "debuginfo" diff --git a/enums/src/common.rs b/enums/src/common.rs new file mode 100644 index 00000000..50d2aaa1 --- /dev/null +++ b/enums/src/common.rs @@ -0,0 +1,172 @@ +use std::collections::hash_map::{Entry, HashMap}; +use std::collections::BTreeMap; +use tree_sitter::Language; + +pub fn capitalize(s: &str) -> String { + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} + +pub fn sanitize_identifier(name: &str) -> String { + if name == "" { + return "BOM".to_string(); + } + if name == "_" { + return "UNDERSCORE".to_string(); + } + if name == "self" { + return "Zelf".to_string(); + } + if name == "Self" { + return "SELF".to_string(); + } + + let mut result = String::with_capacity(name.len()); + for c in name.chars() { + if ('a'..='z').contains(&c) + || ('A'..='Z').contains(&c) + || ('0'..='9').contains(&c) + || c == '_' + { + result.push(c); + } else { + let replacement = match c { + '~' => "TILDE", + '`' => "BQUOTE", + '!' => "BANG", + '@' => "AT", + '#' => "HASH", + '$' => "DOLLAR", + '%' => "PERCENT", + '^' => "CARET", + '&' => "AMP", + '*' => "STAR", + '(' => "LPAREN", + ')' => "RPAREN", + '-' => "DASH", + '+' => "PLUS", + '=' => "EQ", + '{' => "LBRACE", + '}' => "RBRACE", + '[' => "LBRACK", + ']' => "RBRACK", + '\\' => "BSLASH", + '|' => "PIPE", + ':' => "COLON", + ';' => "SEMI", + '"' => "DQUOTE", + '\'' => "SQUOTE", + '<' => "LT", + '>' => "GT", + ',' => "COMMA", + '.' => "DOT", + '?' => "QMARK", + '/' => "SLASH", + '\n' => "LF", + '\r' => "CR", + '\t' => "TAB", + _ => continue, + }; + if !result.is_empty() && !result.ends_with('_') { + result.push('_'); + } + result += replacement; + } + } + + // If all characters were unmapped (e.g. Unicode symbols like `·`), + // generate identifier from their codepoints. + if result.is_empty() { + if name.is_empty() { + result = "EMPTY".to_string(); + } else { + result = name + .chars() + .map(|c| format!("U{:04X}", c as u32)) + .collect::>() + .join("_"); + } + } + + result +} + +pub fn sanitize_string(name: &str, escape: bool) -> String { + let mut result = String::with_capacity(name.len()); + if escape { + for c in name.chars() { + match c { + '\"' => result += "\\\\\\\"", + '\\' => result += "\\\\\\\\", + '\t' => result += "\\\\t", + '\n' => result += "\\\\n", + '\r' => result += "\\\\r", + _ => result.push(c), + } + } + } else { + for c in name.chars() { + match c { + '\"' => result += "\\\"", + '\\' => result += "\\\\", + '\t' => result += "\\t", + '\n' => result += "\\n", + '\r' => result += "\\r", + _ => result.push(c), + } + } + } + result +} + +pub fn camel_case(name: String) -> String { + let mut result = String::with_capacity(name.len()); + let mut cap = true; + for c in name.chars() { + if c == '_' { + cap = true; + } else if cap { + result.extend(c.to_uppercase().collect::>()); + cap = false; + } else { + result.push(c); + } + } + result +} + +pub fn get_token_names(language: &Language, escape: bool) -> Vec<(String, bool, String)> { + let count = language.node_kind_count(); + let mut names = BTreeMap::default(); + let mut name_count = HashMap::new(); + for anon in &[false, true] { + for i in 0..count { + let anonymous = !language.node_kind_is_named(i as u16); + if anonymous != *anon { + continue; + } + let kind = language.node_kind_for_id(i as u16).unwrap(); + let name = sanitize_identifier(kind); + let ts_name = sanitize_string(kind, escape); + let name = camel_case(name); + let e = match name_count.entry(name.clone()) { + Entry::Occupied(mut e) => { + *e.get_mut() += 1; + (format!("{}{}", name, e.get()), true, ts_name) + } + Entry::Vacant(e) => { + e.insert(1); + (name, false, ts_name) + } + }; + names.insert(i, e); + } + } + let mut names: Vec<_> = names.values().cloned().collect(); + names.push(("Error".to_string(), false, "ERROR".to_string())); + + names +} diff --git a/enums/src/go.rs b/enums/src/go.rs new file mode 100644 index 00000000..544c801f --- /dev/null +++ b/enums/src/go.rs @@ -0,0 +1,39 @@ +use askama::Template; +use std::fs::File; +use std::io::Write; +use std::path::Path; + +use crate::common::*; +use crate::languages::*; + +#[derive(Debug, Template)] +#[template(path = "go.go", escape = "none")] +struct GoTemplate { + c_name: String, + names: Vec<(String, bool, String, String)>, +} + +pub fn generate_go(output: &Path, file_template: &str) -> std::io::Result<()> { + for lang in Lang::into_enum_iter() { + let language = get_language(&lang); + let name = get_language_name(&lang); + let c_name = camel_case(name.to_string()); + + let file_name = format!("{}.go", file_template.replace('$', &c_name.to_lowercase())); + let path = output.join(file_name); + let mut file = File::create(path)?; + + let mut names = get_token_names(&language, false); + let max_len = names.iter().map(|x| x.0.len()).max().unwrap(); + let names: Vec<_> = names + .drain(..) + .map(move |(n, d, t)| (n.clone(), d, t, format!("{: , +} + +pub fn generate_json(output: &Path, file_template: &str) -> std::io::Result<()> { + for lang in Lang::into_enum_iter() { + let language = get_language(&lang); + let name = get_language_name(&lang); + let c_name = camel_case(name.to_string()); + + let file_name = format!( + "{}.json", + file_template.replace('$', &c_name.to_lowercase()) + ); + let path = output.join(file_name); + let mut file = File::create(path)?; + + let names = get_token_names(&language, true); + + let args = JsonTemplate { names }; + + file.write_all(args.render().unwrap().as_bytes())?; + } + + Ok(()) +} diff --git a/enums/src/languages.rs b/enums/src/languages.rs new file mode 100644 index 00000000..45a89076 --- /dev/null +++ b/enums/src/languages.rs @@ -0,0 +1,11 @@ +use tree_sitter::Language; + +mk_langs!( + // 1) Name for enum + // 2) tree-sitter function to call to get a Language + (Rust, tree_sitter_rust), + (Python, tree_sitter_python), + (Tsx, tree_sitter_tsx), + (Typescript, tree_sitter_typescript), + (Go, tree_sitter_go) +); diff --git a/enums/src/lib.rs b/enums/src/lib.rs new file mode 100644 index 00000000..0a3761a8 --- /dev/null +++ b/enums/src/lib.rs @@ -0,0 +1,18 @@ +#[macro_use] +mod macros; +pub use crate::macros::*; + +mod common; +pub use crate::common::*; + +mod languages; +pub use crate::languages::*; + +mod rust; +pub use crate::rust::*; + +mod go; +pub use crate::go::*; + +mod json; +pub use crate::json::*; diff --git a/enums/src/macros.rs b/enums/src/macros.rs new file mode 100644 index 00000000..e3558181 --- /dev/null +++ b/enums/src/macros.rs @@ -0,0 +1,50 @@ +macro_rules! mk_enum { + ( $( $camel:ident ),* ) => { + #[derive(Clone, Debug, PartialEq)] + pub enum Lang { + $( + $camel, + )* + } + impl Lang { + pub fn into_enum_iter() -> impl Iterator { + use Lang::*; + [$( $camel, )*].into_iter() + } + } + }; +} + +macro_rules! mk_get_language { + ( $( ($camel:ident, $name:ident) ),* ) => { + pub fn get_language(lang: &Lang) -> Language { + match lang { + Lang::Typescript => tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(), + Lang::Tsx => tree_sitter_typescript::LANGUAGE_TSX.into(), + Lang::Python => tree_sitter_python::LANGUAGE.into(), + Lang::Rust => tree_sitter_rust::LANGUAGE.into(), + Lang::Go => tree_sitter_go::LANGUAGE.into(), + } + } + }; +} + +macro_rules! mk_get_language_name { + ( $( $camel:ident ),* ) => { + pub fn get_language_name(lang: &Lang) -> &'static str { + match lang { + $( + Lang::$camel => stringify!($camel), + )* + } + } + }; +} + +macro_rules! mk_langs { + ( $( ($camel:ident, $name:ident) ),* ) => { + mk_enum!($( $camel ),*); + mk_get_language!($( ($camel, $name) ),*); + mk_get_language_name!($( $camel ),*); + }; +} diff --git a/enums/src/main.rs b/enums/src/main.rs new file mode 100644 index 00000000..f07b67a4 --- /dev/null +++ b/enums/src/main.rs @@ -0,0 +1,74 @@ +use std::path::PathBuf; + +use clap::builder::{PossibleValuesParser, TypedValueParser}; +use clap::Parser; + +use enums::*; + +#[derive(Debug, Clone)] +enum OutputLanguage { + Rust, + Go, + Json, +} + +impl std::str::FromStr for OutputLanguage { + type Err = &'static str; + + fn from_str(env: &str) -> std::result::Result { + match env { + "rust" => Ok(Self::Rust), + "go" => Ok(Self::Go), + "json" => Ok(Self::Json), + _ => Err("Not a valid value, run `--help` to know valid values"), + } + } +} + +impl OutputLanguage { + const fn variants() -> [&'static str; 4] { + ["rust", "go", "json", "c_macros"] + } +} + +#[derive(Parser, Debug)] +#[clap( + name = "enums", + version, + author, + about = "Generate enums for a target language to use with tree-sitter." +)] +struct Opts { + /// Output directory. + #[clap(long, short, default_value = ".", value_parser)] + output: PathBuf, + /// Target language. + #[clap(long, short, default_value = "rust", value_parser = PossibleValuesParser::new(OutputLanguage::variants()) + .map(|s| s.parse::().unwrap()))] + language: OutputLanguage, + /// File name template. + #[clap(long, short, default_value = "language_$")] + file_template: String, +} + +fn main() { + let opts = Opts::parse(); + + match opts.language { + OutputLanguage::Rust => { + if let Some(err) = generate_rust(&opts.output, &opts.file_template).err() { + eprintln!("{:?}", err); + } + } + OutputLanguage::Go => { + if let Some(err) = generate_go(&opts.output, &opts.file_template).err() { + eprintln!("{:?}", err); + } + } + OutputLanguage::Json => { + if let Some(err) = generate_json(&opts.output, &opts.file_template).err() { + eprintln!("{:?}", err); + } + } + } +} diff --git a/enums/src/rust.rs b/enums/src/rust.rs new file mode 100644 index 00000000..ad2e307a --- /dev/null +++ b/enums/src/rust.rs @@ -0,0 +1,35 @@ +use askama::Template; +use std::env; +use std::fs::File; +use std::io::{Read, Write}; +use std::path::Path; + +use crate::common::*; +use crate::languages::*; + +#[derive(Debug, Template)] +#[template(path = "rust.rs", escape = "none")] +struct RustTemplate { + c_name: String, + names: Vec<(String, bool, String)>, +} + +pub fn generate_rust(output: &Path, file_template: &str) -> std::io::Result<()> { + for lang in Lang::into_enum_iter() { + let language = get_language(&lang); + let name = get_language_name(&lang); + let c_name = camel_case(name.to_string()); + + let file_name = format!("{}.rs", file_template.replace('$', &c_name.to_lowercase())); + let path = output.join(file_name); + let mut file = File::create(path)?; + + let names = get_token_names(&language, false); + + let args = RustTemplate { c_name, names }; + + file.write_all(args.render().unwrap().as_bytes())?; + } + + Ok(()) +} diff --git a/enums/templates/foo.rs b/enums/templates/foo.rs new file mode 100644 index 00000000..3551906e --- /dev/null +++ b/enums/templates/foo.rs @@ -0,0 +1,8 @@ +// Generated. DON'T MODIFY BY HAND! + +#[derive(Debug, PartialEq)] +pub enum {{ c_name }} { + {% for (name, _, _) in names %} + {{ name }} = {{ loop.index }}; + {% endfor %} +} diff --git a/enums/templates/go.go b/enums/templates/go.go new file mode 100644 index 00000000..4aef36ef --- /dev/null +++ b/enums/templates/go.go @@ -0,0 +1,35 @@ +// Code generated; DO NOT EDIT. + +package {{ c_name.to_lowercase() }} + +type SyntaxType{{ c_name }} int16 + +const ( + {% for (_, _, _, name) in names -%} + {{ name }} SyntaxType{{ c_name }} = iota + {% endfor %} +) + +// String return the string version of the type +func (st SyntaxType{{ c_name }}) String() string { + switch st { + {% for (name, _, ts_name, _) in names -%} + case {{ name }}: + return "{{ ts_name }}"; + {% endfor %} + } + panic("Unsupported SyntaxType{{ c_name }}") +} + +// FromString a SyntaxType{{ c_name }} from the string, panic if not found +func FromString(str String) SyntaxType{{ c_name }} { + switch str { + {% for (name, dup, ts_name, _) in names -%} + {% if !dup %} + case "{{ ts_name }}": + return {{ name }}; + {%- endif -%} + {% endfor %} + } + panic("Unsupported SyntaxType{{ c_name }}") +} diff --git a/enums/templates/json.json b/enums/templates/json.json new file mode 100644 index 00000000..750b8822 --- /dev/null +++ b/enums/templates/json.json @@ -0,0 +1,7 @@ +[ + {% for (name, dup, ts_name) in names -%} + {% if !dup %} + ["{{ name }}", "{{ ts_name }}"]{% if !loop.last %},{% endif %} + {%- endif -%} + {% endfor %} +] diff --git a/xtask/templates/grammar.rs b/enums/templates/rust.rs similarity index 84% rename from xtask/templates/grammar.rs rename to enums/templates/rust.rs index e8acbbc2..ef5fcc86 100644 --- a/xtask/templates/grammar.rs +++ b/enums/templates/rust.rs @@ -1,12 +1,9 @@ // Code generated; DO NOT EDIT. -#![allow(clippy::enum_variant_names)] -#![allow(clippy::upper_case_acronyms)] - use num_derive::FromPrimitive; -#[derive(Clone, Copy, Debug, PartialEq, Eq, FromPrimitive)] -pub(crate) enum {{ c_name }} { +#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)] +pub enum {{ c_name }} { {% for (name, _, _) in names -%} {{ name }} = {{ loop.index0 }}, {% endfor %} @@ -45,3 +42,4 @@ impl PartialEq<{{ c_name }}> for u16 { *x == *self } } + diff --git a/hk.pkl b/hk.pkl deleted file mode 100644 index 930f64b8..00000000 --- a/hk.pkl +++ /dev/null @@ -1,25 +0,0 @@ -amends "package://github.com/jdx/hk/releases/download/v1.44.2/hk@1.44.2#/Config.pkl" -import "package://github.com/jdx/hk/releases/download/v1.44.2/hk@1.44.2#/Builtins.pkl" - -local linters = new Mapping { - ["oxlint"] = (Builtins.ox_lint) { - fix = "bunx -y -q oxlint --fix --fix-suggestions {{files}}" - } - ["clippy"] = Builtins.cargo_clippy - ["rustfmt"] = Builtins.cargo_fmt -} - -hooks { - ["pre-commit"] { - fix = true - stash = "git" - steps = linters - } - ["fix"] { - fix = true - steps = linters - } - ["check"] { - steps = linters - } -} diff --git a/mehen-book/.gitignore b/mehen-book/.gitignore new file mode 100644 index 00000000..ffd8ffe5 --- /dev/null +++ b/mehen-book/.gitignore @@ -0,0 +1,3 @@ +book +src/debug/* +src/.rustc_info.json diff --git a/mehen-book/book.toml b/mehen-book/book.toml new file mode 100644 index 00000000..d4f8e32e --- /dev/null +++ b/mehen-book/book.toml @@ -0,0 +1,20 @@ +[book] +title = "Mehen Documentation" +description = "Documentation for Mehen - code analysis library for Go, Python, Rust, and TypeScript" +authors = ["Konstantin Vyatkin "] +language = "en" + +[output.html] +mathjax-support = true + +[output.html.playpen] +line-numbers = true + +[output.html.search] +limit-results = 25 +use-boolean-and = true +boost-title = 2 +boost-hierarchy = 2 +boost-paragraph = 1 +expand = true +heading-split-level = 3 diff --git a/mehen-book/deploy-to-GitHub-Pages b/mehen-book/deploy-to-GitHub-Pages new file mode 100755 index 00000000..ff08a5d2 --- /dev/null +++ b/mehen-book/deploy-to-GitHub-Pages @@ -0,0 +1,10 @@ +#!/bin/sh + +[ -d /tmp/book ] || (git worktree prune && git branch -D gh-pages) + +git worktree add -b gh-pages /tmp/book +rm -rf /tmp/book/* # this won't delete the .git directory +cp -rp mehen-book/book/* /tmp/book/ +cd /tmp/book +git add -A +git commit -m "Deploy mehen documentation" diff --git a/mehen-book/src/README.md b/mehen-book/src/README.md new file mode 100644 index 00000000..7eec4615 --- /dev/null +++ b/mehen-book/src/README.md @@ -0,0 +1,36 @@ +# mehen + +**mehen** is a Rust library to analyze and extract information +from source codes written in many different programming languages. +It is based on a parser generator tool and an incremental parsing library +called +Tree Sitter. + +You can find the source code of this software on +GitHub, +while issues and feature requests can be posted on the respective +GitHub Issue Tracker. + +## Supported platforms + +**mehen** can run on the most common platforms: Linux, macOS, +and Windows. + +On our +GitHub Release Page +you can find the `Linux` and `Windows` binaries already compiled and +packed for you. + + +## API docs + +If you prefer to use **mehen** as a crate, you can find the +`API docs` generated by `Rustdoc` +here. + + + +## License + +**mehen** and **mehen-cli** (binary: `mehen`) are released under the +Mozilla Public License v2.0. diff --git a/mehen-book/src/SUMMARY.md b/mehen-book/src/SUMMARY.md new file mode 100644 index 00000000..0c2ef68f --- /dev/null +++ b/mehen-book/src/SUMMARY.md @@ -0,0 +1,12 @@ +# Summary + +- [mehen](./README.md) + - [Supported Languages](./languages.md) + - [Supported Metrics](./metrics.md) +- [Commands](commands/README.md) + - [Metrics](commands/metrics.md) + - [Nodes](commands/nodes.md) +- [Developers Guide](developers/README.md) + - [How-to: Add a new language](developers/new-language.md) + - [How-to: Implement LoC](developers/loc.md) + - [How-to: Update grammars](developers/update-grammars.md) diff --git a/mehen-book/src/commands/README.md b/mehen-book/src/commands/README.md new file mode 100644 index 00000000..467b4719 --- /dev/null +++ b/mehen-book/src/commands/README.md @@ -0,0 +1,31 @@ +# Commands + +The **mehen** CLI offers a range of **commands** to analyze and extract information from source code. Each command **may** include parameters specific to the task it performs. Below, we describe the core types of commands available. + +## Metrics + +Metrics provide quantitative measures about source code, which can help in: + +- Compare different programming languages +- Provide information on the quality of a code +- Tell developers where their code is more tough to handle +- Discovering potential issues early in the development process + +**mehen** calculates the metrics starting from the +source code of a program. These kind of metrics are called *static metrics*. + +## Nodes + +To represent the structure of program code, **mehen** builds +an +Abstract Syntax Tree (AST). +A **node** is an element of this tree and denotes any syntactic construct +present in a language. + +Nodes can be used to: + +- Create the syntactic structure of a source file +- Discover if a construct of a language is present in the analyzed + code +- Count the number of constructs of a certain kind +- Detect errors in the source code diff --git a/mehen-book/src/commands/metrics.md b/mehen-book/src/commands/metrics.md new file mode 100644 index 00000000..6ff135e2 --- /dev/null +++ b/mehen-book/src/commands/metrics.md @@ -0,0 +1,45 @@ +# Metrics + +Metrics can be displayed or exported in various formats using **mehen**. + +## Display Metrics + +To compute and display metrics for a given file or directory, run: + +```bash +mehen -m -p /path/to/your/file/or/directory +``` + +- `-p`: Path to the file or directory to analyze. If a directory is provided, metrics will be computed for all supported files it contains. + +## Exporting Metrics + +**mehen** supports multiple output formats for exporting metrics, including: + +- CBOR +- JSON +- TOML +- YAML + +Both `JSON` and `TOML` can be exported as pretty-printed. + +### Export Command + +To export metrics as a JSON file: + +```bash +mehen -m -p /path/to/your/file/or/directory -O json -o /path/to/output/directory +``` + +- `-O`: Specifies the output format (e.g., json, toml, yaml, cbor). +- `-o`: Path to save the output file. The filename of the output file is the same as the input file plus the extension associated to the format. If not specified, the result will be printed in the shell. + +### Pretty Print + +To output pretty-printed JSON metrics: + +```bash +mehen -m -p /path/to/your/file/or/directory --pr -O json +``` + +This command prints the formatted metrics to the console or the specified output path. diff --git a/mehen-book/src/commands/nodes.md b/mehen-book/src/commands/nodes.md new file mode 100644 index 00000000..4de5ff13 --- /dev/null +++ b/mehen-book/src/commands/nodes.md @@ -0,0 +1,43 @@ +# Nodes + +The `mehen` provides commands to analyze and extract information from the nodes in the **Abstract Syntax Tree (AST)** of a source file. + +## Error Detection + +To detect syntactic errors in your code, run: + +```console +mehen -p /path/to/your/file/or/directory -I "*.ext" -f error +``` + +- `-p`: Path to a file or directory (analyzes all files in the directory). +- `-I`: Glob filter for selecting files by extension (e.g., `*.js`, `*.rs`). +- `-f`: Flag to search for nodes of a specific type (e.g., errors). + + +## Counting Nodes + +You can count the number of specific node types in your code by using the `--count` flag: + +```console +mehen -p /path/to/your/file/or/directory -I "*.ext" --count +``` +This counts how many nodes of the specified type exist in the analyzed files. + +## Printing the AST + +To visualize the AST of a source file, use the `-d` flag: + +```console +mehen -p /path/to/your/file/or/directory -d +``` +The `-d` flag prints the entire AST, allowing you to inspect the code's syntactic structure. + +## Analyzing Code Portions + +To analyze only a specific part of the code, use the `--ls` (line start) and `--le` (line end) options. +For example, if we want to print the AST of a single function which starts at line 5 and ends at line 10: + +```console +mehen -p /path/to/your/file/or/directory -d --ls 5 --le 10 +``` diff --git a/mehen-book/src/developers/README.md b/mehen-book/src/developers/README.md new file mode 100644 index 00000000..fafe196c --- /dev/null +++ b/mehen-book/src/developers/README.md @@ -0,0 +1,131 @@ +# Developers Guide + +If you want to contribute to the development of `mehen` we have +summarized here a series of guidelines that are supposed to help you in your +building process. + +As prerequisite, you need to install the last available version of `Rust`. +You can learn how to do that +here. + +## Clone Repository + +First of all, you need to clone the repository. +You can do that: + +through **HTTPS** + +``` +git clone -j8 https://github.com/ophidiarium/mehen.git +``` + +or through **SSH** + +``` +git clone -j8 git@github.com:ophidiarium/mehen.git +``` + +## Building + +To build the `mehen` library, you need to run the following +command: + +```console +cargo build +``` + +If you want to build the CLI: + +```console +cargo build -p mehen-cli +``` + +To build everything: + +```console +cargo build --workspace +``` + +## Testing + +After you have finished changing the code, you should **always** verify whether +all tests pass with the `cargo test` command. + +```console +cargo test --workspace --all-features --verbose +``` + +## Code Formatting + +If all previous steps went well, and you want to make a pull request +to integrate your invaluable help in the codebase, the last step left is +code formatting. + +### Rustfmt + +This tool formats your code according to Rust style guidelines. + +To install: + +```console +rustup component add rustfmt +``` + +To format the code: + +```console +cargo fmt +``` + +### Clippy + +This tool helps developers to write better code catching automatically lots of +common mistakes for them. It detects in your code a series of errors and +warnings that **must** be fixed before making a pull request. + +To install: + +```console +rustup component add clippy +``` + +To detect errors and warnings: + +```console +cargo clippy --workspace --all-targets -- +``` + +## Code Documentation + +If you have documented your code, to generate the final documentation, +run this command: + +```console +cargo doc --open --no-deps +``` + +Remove the `--no-deps` option if you also want to build the documentation of +each dependency used by **mehen**. + +## Run your code + +You can run the **mehen** CLI using: + +```console +cargo run -p mehen-cli -- [mehen-parameters] +``` + +To know the list of **mehen** CLI parameters, run: + +```console +cargo run -p mehen-cli -- --help +``` + +## Practical advice + +- When you add a new feature, add at least one unit or integration test to + verify that everything works correctly +- Document public API +- Do not add dead code +- Comment intricate code such that others can comprehend what you have + accomplished diff --git a/mehen-book/src/developers/loc.md b/mehen-book/src/developers/loc.md new file mode 100644 index 00000000..ba73644e --- /dev/null +++ b/mehen-book/src/developers/loc.md @@ -0,0 +1,57 @@ +# Lines of Code (LoC) + +In this document we give some guidance on how to implement the LoC metrics available in this crate. +[Lines of code](https://en.wikipedia.org/wiki/Source_lines_of_code) is a software metric that gives an indication of the size of some source code by counting the lines of the source code. +There are many types of LoC so we will first explain those by way of an example. + +## Types of LoC + +```rust +/* +Instruction: Implement factorial function +For extra credits, do not use mutable state or a imperative loop like `for` or `while`. + */ + +/// Factorial: n! = n*(n-1)*(n-2)*(n-3)...3*2*1 +fn factorial(num: u64) -> u64 { + + // use `product` on `Iterator` + (1..=num).product() +} +``` + +The example above will be used to illustrate each of the **LoC** metrics described below. + +### SLOC + +A straight count of all lines in the file including code, comments, and blank lines. +METRIC VALUE: 11 + +### PLOC + +A count of the instruction lines of code contained in the source code. This would include any brackets or similar syntax on a new line. +Note that comments and blank lines are not counted in this. +METRIC VALUE: 3 + +### LLOC + +The "logical" lines is a count of the number of statements in the code. Note that what a statement is depends on the language. +In the above example there is only a single statement which id the function call of `product` with the `Iterator` as its argument. +METRIC VALUE: 1 + +### CLOC + +A count of the comments in the code. The type of comment does not matter ie single line, block, or doc. +METRIC VALUE: 6 + +### BLANK + +Last but not least, this metric counts the blank lines present in a code. +METRIC VALUE: 2 + +## Implementation + +To implement the LoC related metrics described above you need to implement the `Loc` trait for the language you want to support. + +This requires implementing the `compute` function. +See [/src/metrics/loc.rs](https://github.com/ophidiarium/mehen/blob/master/src/metrics/loc.rs) for where to implement, as well as examples from other languages. diff --git a/mehen-book/src/developers/new-language.md b/mehen-book/src/developers/new-language.md new file mode 100644 index 00000000..7cfe76a6 --- /dev/null +++ b/mehen-book/src/developers/new-language.md @@ -0,0 +1,56 @@ +# Supporting a new language + +This section is to help developers implement support for a new language in `mehen`. + +To implement a new language, two steps are required: + +1. Generate the grammar +2. Add the grammar to `mehen` + +A number of [metrics are supported](../metrics.md) and help to implement those are covered elsewhere in the documentation. + +## Generating the grammar + +As a **prerequisite** for adding a new grammar, there needs to exist a [tree-sitter](https://github.com/tree-sitter) version for the desired language that matches the [version used in this project](https://github.com/ophidiarium/mehen/blob/master/Cargo.toml). + +The grammars are generated by a project in this repository called [enums](https://github.com/ophidiarium/mehen/tree/master/enums). The following steps add the language support from the language crate and generate an enum file that is then used as the grammar in this project to evaluate metrics. + +1. Add the language specific `tree-sitter` crate to the `enum` crate, making sure to tie it to the `tree-sitter` version used in the `mehen` crate. For example, for the Rust support at time of writing the following line exists in the [/enums/Cargo.toml](https://github.com/ophidiarium/mehen/blob/master/enums/Cargo.toml): `tree-sitter-rust = "version number"`. +2. Append the language to the `enum` crate in [/enums/src/languages.rs](https://github.com/ophidiarium/mehen/blob/master/enums/src/languages.rs). Keeping with Rust as the example, the line would be `(Rust, tree_sitter_rust)`. The first parameter is the name of the Rust enum that will be generated, the second is the `tree-sitter` function to call to get the language's grammar. +3. Add a case to the end of the match in `mk_get_language` macro rule in [/enums/src/macros.rs](https://github.com/ophidiarium/mehen/blob/master/enums/src/macros.rs) eg. for Rust `Lang::Rust => tree_sitter_rust::language()`. +4. Lastly, we execute the [/recreate-grammars.sh](https://github.com/ophidiarium/mehen/blob/master/recreate-grammars.sh) script that runs the `enums` crate to generate the grammar for the new language. + +At this point we should have a new grammar file for the new language in [/src/languages/](https://github.com/ophidiarium/mehen/tree/master/src/languages). See [/src/languages/language_rust.rs](https://github.com/ophidiarium/mehen/blob/master/src/languages/language_rust.rs) as an example of the generated enum. + +## Adding the new grammar to mehen + +1. Add the language specific `tree-sitter` crate to the `mehen` project, making sure to tie it to the `tree-sitter` version used in this project. For example, for the Rust support at time of writing the following line exists in the [Cargo.toml](https://github.com/ophidiarium/mehen/blob/master/Cargo.toml): `tree-sitter-rust = "0.19.0"`. +2. Next we add the new `tree-sitter` language namespace to [/src/languages/mod.rs](https://github.com/ophidiarium/mehen/blob/master/src/languages/mod.rs) eg. + +```rust +pub mod language_rust; +pub use language_rust::*; +``` + +3. Lastly, we add a definition of the language to the arguments of `mk_langs!` macro in [/src/langs.rs](https://github.com/ophidiarium/mehen/blob/master/src/langs.rs). + +```rust +// 1) Name for enum +// 2) Language description +// 3) Display name +// 4) Empty struct name to implement +// 5) Parser name +// 6) tree-sitter function to call to get a Language +// 7) file extensions +// 8) emacs modes +( + Rust, + "The `Rust` language", + "rust", + RustCode, + RustParser, + tree_sitter_rust, + [rs], + ["rust"] +) +``` diff --git a/mehen-book/src/developers/update-grammars.md b/mehen-book/src/developers/update-grammars.md new file mode 100644 index 00000000..0c037d11 --- /dev/null +++ b/mehen-book/src/developers/update-grammars.md @@ -0,0 +1,45 @@ +# Update grammars + +Each programming language needs to be parsed in order to extract its syntax and semantic: the so-called grammar of a language. +In `mehen`, we use [tree-sitter](https://github.com/tree-sitter) as parsing library since it provides a set of distinct grammars for each of our +supported programming languages. Grammars change over time and may have bugs, so they need to be updated periodically. + +Grammars can be updated on **Linux** and **macOS** natively, or on **Windows** using **WSL**. + +## Updating Grammars + +Mehen uses **third-party grammars** published on `crates.io` and maintained by external developers. + +### Current Supported Grammars + +- `tree-sitter-go` = "=0.23.4" +- `tree-sitter-python` = "=0.23.6" +- `tree-sitter-rust` = "=0.23.2" +- `tree-sitter-typescript` = "=0.23.2" + +### Update Process + +1. Update the grammar version in both `Cargo.toml` and `enums/Cargo.toml`: + +```toml +tree-sitter-go = "=x.xx.x" +``` + +2. Run the grammar regeneration script: + +```bash +./recreate-grammars.sh +``` + +This script regenerates all language enum files in `src/languages/`. + +3. Fix any failing tests or compilation errors introduced by grammar changes. + +4. Test thoroughly: + +```bash +cargo test --workspace +cargo clippy --workspace -- -D warnings +``` + +5. Commit your changes and create a pull request. diff --git a/mehen-book/src/languages.md b/mehen-book/src/languages.md new file mode 100644 index 00000000..3474ab5c --- /dev/null +++ b/mehen-book/src/languages.md @@ -0,0 +1,9 @@ +# Supported Languages + +**Mehen** supports these programming languages: + +- [x] **Go** (.go) - via tree-sitter-go v0.23.4 +- [x] **Python** (.py) - via tree-sitter-python v0.23.6 +- [x] **Rust** (.rs) - via tree-sitter-rust v0.23.2 +- [x] **TypeScript** (.ts, .jsw, .jsmw) - via tree-sitter-typescript v0.23.2 +- [x] **TSX** (.tsx) - via tree-sitter-typescript v0.23.2 diff --git a/mehen-book/src/metrics.md b/mehen-book/src/metrics.md new file mode 100644 index 00000000..a68aed04 --- /dev/null +++ b/mehen-book/src/metrics.md @@ -0,0 +1,29 @@ +# Supported Metrics + +**mehen** implements a series of metrics: + +- **ABC**: it measures the size of a source code by counting the number of +Assignments (`A`), Branches (`B`) and Conditions (`C`). +- **BLANK**: it counts the number of blank lines in a source file. +- **CC**: it calculates the _Cyclomatic complexity_ examining the + control flow of a program. +- **CLOC**: it counts the number of comments in a source file. +- **COGNITIVE**: it calculates the _Cognitive complexity_, measuring how complex +it is to understand a unit of code. +- **HALSTEAD**: it is a suite that provides a series of information, such as the + effort required to maintain the analyzed code, the size in bits to store the + program, the difficulty to understand the code, an estimate of the number of + bugs present in the codebase, and an estimate of the time needed to + implement the software. +- **LLOC**: it counts the number of logical lines (statements) contained in a +source file. +- **MI**: it is a suite that allows to evaluate the maintainability of a software. +- **NARGS**: it counts the number of arguments of a function/method. +- **NEXITS**: it counts the number of possible exit points from a method/function. +- **NOM**: it counts the number of functions and closures in a file/trait/class. +- **NPA**: it counts the number of public attributes in classes/interfaces. +- **NPM**: it counts the number of public methods in classes/interfaces. +- **PLOC**: it counts the number of physical lines (instructions) contained in +a source file. +- **SLOC**: it counts the number of lines in a source file. +- **WMC**: it sums the _Cyclomatic complexity_ of every method defined in a class. diff --git a/mehen-cli/Cargo.toml b/mehen-cli/Cargo.toml new file mode 100644 index 00000000..53fd5762 --- /dev/null +++ b/mehen-cli/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "mehen-cli" +version.workspace = true +authors.workspace = true +repository.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +keywords = ["metrics"] +description = "Tool to compute and export code metrics" + +[[bin]] +name = "mehen" +path = "src/main.rs" + +[dependencies] +clap = { version = "^4.0", features = ["derive"] } +globset = "^0.4" +mehen = { path = ".." } +serde = "^1.0" +serde_cbor = "^0.11" +serde_json = "^1.0" +serde_yaml = "^0.9" +toml = "^0.9" diff --git a/mehen-cli/README.md b/mehen-cli/README.md new file mode 100644 index 00000000..29d86291 --- /dev/null +++ b/mehen-cli/README.md @@ -0,0 +1,59 @@ +# mehen-cli + +`mehen` is a tool designed to compute and export code metrics, analyze source code, and perform various operations such as removing comments, counting nodes, retrieving functions, and computing code metrics in different formats. + +## Features + +- Analyze source code for different programming languages. +- Export results in different formats (CBOR, JSON, TOML, YAML). +- Perform various operations on source code (e.g., dumping abstract syntax tree to stdout, counting nodes, computing code metrics). + +## Installation + +Clone the repository and build the project: + +```sh +cd mehen-cli/ +cargo build +``` + +## Usage + +Run the tool by specifying the input file and the desired operation: + +```sh +mehen [OPTIONS] +``` + +## Available Options + +- `-p, --paths ...`: Input files to analyze. +- `-d, --dump`: Dump the abstract syntax tree to stdout. +- `-c, --comments`: Remove comments from specified files. +- `-f, --find `: Find nodes of the given type. +- `-F, --function`: Get functions and their spans. +- `-C, --count `: Count nodes of the given type. +- `-m, --metrics`: Compute code metrics. +- `--ops`: Retrieve all operands and operators in the code. +- `-i, --in-place`: Perform actions in place. +- `-I, --include [...]`: Include files matching the given pattern. +- `-X, --exclude [...]`: Exclude files matching the given pattern. +- `-j, --num-jobs `: Number of threads to use. +- `-l, --language-type `: Language of the input files. +- `-O, --output-format `: Output format for the results (CBOR, JSON, TOML, YAML). +- `--pr`: Dump a pretty JSON output file. +- `-o, --output `: Output directory for the results. +- `--preproc `: Get preprocessor directives for C/C++ files. +- `--ls `: Start line for the analysis. +- `--le `: End line for the analysis. +- `-w, --warning`: Show warnings. +- `-v, --version`: Show version information. +- `-h, --help`: Show help information. + +## Examples + +To analyze the code in a file and export the metrics in JSON format: + +```sh +mehen --metrics --output-format json --output . --paths path/to/file.rs +``` diff --git a/mehen-cli/src/formats.rs b/mehen-cli/src/formats.rs new file mode 100644 index 00000000..2f5a3a54 --- /dev/null +++ b/mehen-cli/src/formats.rs @@ -0,0 +1,235 @@ +use std::fs::{File, create_dir_all}; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use serde::Serialize; + +#[derive(Debug, Clone)] +pub enum Format { + Cbor, + Json, + Toml, + Yaml, +} + +impl Format { + pub const fn all() -> &'static [&'static str] { + &["cbor", "json", "toml", "yaml"] + } + + pub fn dump_formats( + &self, + space: T, + path: PathBuf, + output_path: Option<&PathBuf>, + pretty: bool, + ) { + if let Some(output_path) = output_path { + match self { + Self::Cbor => Cbor::with_writer(space, path, output_path), + Self::Json => Json::with_pretty_writer(space, path, output_path, pretty), + Self::Toml => Toml::with_pretty_writer(space, path, output_path, pretty), + Self::Yaml => Yaml::with_writer(space, path, output_path), + } + } else { + match self { + Self::Json => Json::write_on_stdout_pretty(space, pretty), + Self::Toml => Toml::write_on_stdout_pretty(space, pretty), + Self::Yaml => Yaml::write_on_stdout(space), + Self::Cbor => panic!("Cbor format cannot be printed to stdout"), + } + } + } +} + +impl FromStr for Format { + type Err = String; + + fn from_str(format: &str) -> Result { + match format { + "cbor" => Ok(Self::Cbor), + "json" => Ok(Self::Json), + "toml" => Ok(Self::Toml), + "yaml" => Ok(Self::Yaml), + format => Err(format!("{format:?} is not a supported format")), + } + } +} + +#[inline(always)] +fn print_on_stdout(content: String) { + writeln!(std::io::stdout().lock(), "{content}").unwrap(); +} + +trait WriteOnStdout { + #[inline(always)] + fn write_on_stdout(content: T) { + print_on_stdout(Self::format(content)); + } + + fn format(content: T) -> String; +} + +trait WritePrettyOnStdout: WriteOnStdout { + fn write_on_stdout_pretty(content: T, pretty: bool) { + print_on_stdout(if pretty { + Self::format_pretty(content) + } else { + Self::format(content) + }); + } + fn format_pretty(content: T) -> String; +} + +fn handle_path(path: PathBuf, output_path: &Path, extension: &str) -> PathBuf { + // Remove root / + let path = path.as_path().strip_prefix("/").unwrap_or(path.as_path()); + + // Remove root ./ + let path = path.strip_prefix("./").unwrap_or(path); + + // Replace .. with . to keep files inside the output folder + let cleaned_path: Vec<&str> = path + .iter() + .map(|os_str| { + let s_str = os_str.to_str().unwrap(); + if s_str == ".." { "." } else { s_str } + }) + .collect(); + + // Create the filename + let filename = cleaned_path.join("/") + extension; + + // Build the file path + output_path.join(filename) +} + +trait WriteFile { + const EXTENSION: &'static str; + + fn open_file(path: PathBuf, output_path: &Path) -> File { + // Handle output path + let format_path = handle_path(path, output_path, Self::EXTENSION); + + // Create directories + create_dir_all(format_path.parent().unwrap()).unwrap(); + + File::create(format_path).unwrap() + } + + fn with_writer(content: T, path: PathBuf, output_path: &Path); +} + +trait WritePrettyFile: WriteFile { + fn with_pretty_writer( + content: T, + path: PathBuf, + output_path: &Path, + pretty: bool, + ); +} + +struct Json; + +impl WriteOnStdout for Json { + fn format(content: T) -> String { + serde_json::to_string(&content).unwrap() + } +} + +impl WritePrettyOnStdout for Json { + fn format_pretty(content: T) -> String { + serde_json::to_string_pretty(&content).unwrap() + } +} + +impl WriteFile for Json { + const EXTENSION: &'static str = ".json"; + + fn with_writer(content: T, path: PathBuf, output_path: &Path) { + serde_json::to_writer(Self::open_file(path, output_path), &content).unwrap() + } +} + +impl WritePrettyFile for Json { + fn with_pretty_writer( + content: T, + path: PathBuf, + output_path: &Path, + pretty: bool, + ) { + if pretty { + serde_json::to_writer_pretty(Self::open_file(path, output_path), &content).unwrap(); + } else { + Self::with_writer(content, path, output_path); + } + } +} + +struct Toml; + +impl WriteOnStdout for Toml { + fn format(content: T) -> String { + toml::to_string(&content).unwrap() + } +} + +impl WritePrettyOnStdout for Toml { + fn format_pretty(content: T) -> String { + toml::to_string_pretty(&content).unwrap() + } +} + +impl WriteFile for Toml { + const EXTENSION: &'static str = ".toml"; + + fn with_writer(content: T, path: PathBuf, output_path: &Path) { + Self::open_file(path, output_path) + .write_all(Self::format(content).as_bytes()) + .unwrap(); + } +} + +impl WritePrettyFile for Toml { + fn with_pretty_writer( + content: T, + path: PathBuf, + output_path: &Path, + pretty: bool, + ) { + if pretty { + Self::open_file(path, output_path) + .write_all(Self::format_pretty(&content).as_bytes()) + .unwrap(); + } else { + Self::with_writer(content, path, output_path); + } + } +} + +struct Yaml; + +impl WriteOnStdout for Yaml { + fn format(content: T) -> String { + serde_yaml::to_string(&content).unwrap() + } +} + +impl WriteFile for Yaml { + const EXTENSION: &'static str = ".yml"; + + fn with_writer(content: T, path: PathBuf, output_path: &Path) { + serde_yaml::to_writer(Self::open_file(path, output_path), &content).unwrap() + } +} + +struct Cbor; + +impl WriteFile for Cbor { + const EXTENSION: &'static str = ".cbor"; + + fn with_writer(content: T, path: PathBuf, output_path: &Path) { + serde_cbor::to_writer(Self::open_file(path, output_path), &content).unwrap() + } +} diff --git a/mehen-cli/src/main.rs b/mehen-cli/src/main.rs new file mode 100644 index 00000000..8efded0c --- /dev/null +++ b/mehen-cli/src/main.rs @@ -0,0 +1,268 @@ +mod formats; + +use std::path::PathBuf; +use std::process; +use std::sync::{Arc, Mutex}; +use std::thread::available_parallelism; + +use clap::Parser; +use clap::builder::{PossibleValuesParser, TypedValueParser}; +use globset::{Glob, GlobSet, GlobSetBuilder}; + +use formats::Format; + +// Enums +use mehen::LANG; + +// Structs +use mehen::{ + CommentRm, CommentRmCfg, ConcurrentRunner, Count, CountCfg, Dump, DumpCfg, FilesData, Find, + FindCfg, Function, FunctionCfg, Metrics, MetricsCfg, OpsCfg, OpsCode, +}; + +// Functions +use mehen::{ + action, get_from_ext, get_function_spaces, get_ops, guess_language, read_file_with_eol, +}; + +#[derive(Debug)] +struct Config { + dump: bool, + in_place: bool, + comments: bool, + find_filter: Vec, + count_filter: Vec, + language: Option, + function: bool, + metrics: bool, + ops: bool, + output_format: Option, + output: Option, + pretty: bool, + line_start: Option, + line_end: Option, + count_lock: Option>>, +} + +fn mk_globset(elems: Vec) -> GlobSet { + if elems.is_empty() { + return GlobSet::empty(); + } + + let mut globset = GlobSetBuilder::new(); + elems.iter().filter(|e| !e.is_empty()).for_each(|e| { + if let Ok(glob) = Glob::new(e) { + globset.add(glob); + } + }); + globset.build().map_or(GlobSet::empty(), |globset| globset) +} + +fn act_on_file(path: PathBuf, cfg: &Config) -> std::io::Result<()> { + let source = if let Some(source) = read_file_with_eol(&path)? { + source + } else { + return Ok(()); + }; + + let language = if let Some(language) = cfg.language { + language + } else if let Some(language) = guess_language(&source, &path).0 { + language + } else { + return Ok(()); + }; + + if cfg.dump { + let cfg = DumpCfg { + line_start: cfg.line_start, + line_end: cfg.line_end, + }; + action::(&language, source, &path, None, cfg) + } else if cfg.metrics { + if let Some(output_format) = &cfg.output_format { + if let Some(space) = get_function_spaces(&language, source, &path, None) { + output_format.dump_formats(space, path, cfg.output.as_ref(), cfg.pretty); + } + Ok(()) + } else { + let cfg = MetricsCfg { path }; + let path = cfg.path.clone(); + action::(&language, source, &path, None, cfg) + } + } else if cfg.ops { + if let Some(output_format) = &cfg.output_format { + let ops = get_ops(&language, source, &path, None).unwrap(); + output_format.dump_formats(ops, path, cfg.output.as_ref(), cfg.pretty); + Ok(()) + } else { + let cfg = OpsCfg { path }; + let path = cfg.path.clone(); + action::(&language, source, &path, None, cfg) + } + } else if cfg.comments { + let cfg = CommentRmCfg { + in_place: cfg.in_place, + path, + }; + let path = cfg.path.clone(); + action::(&language, source, &path, None, cfg) + } else if cfg.function { + let cfg = FunctionCfg { path: path.clone() }; + action::(&language, source, &path, None, cfg) + } else if !cfg.find_filter.is_empty() { + let cfg = FindCfg { + path: path.clone(), + filters: cfg.find_filter.clone(), + line_start: cfg.line_start, + line_end: cfg.line_end, + }; + action::(&language, source, &path, None, cfg) + } else if let Some(count_lock) = &cfg.count_lock { + let cfg = CountCfg { + filters: cfg.count_filter.clone(), + stats: count_lock.clone(), + }; + action::(&language, source, &path, None, cfg) + } else { + Ok(()) + } +} + +#[derive(Parser, Debug)] +#[clap(name = "mehen", version, author, about = "Analyze source code.")] +struct Opts { + /// Input files to analyze. + #[clap(long, short, value_parser)] + paths: Vec, + /// Output AST to stdout. + #[clap(long, short)] + dump: bool, + /// Remove comments in the specified files. + #[clap(long, short)] + comments: bool, + /// Find nodes of the given type. + #[clap(long, short, number_of_values = 1)] + find: Vec, + /// Get functions and their spans. + #[clap(long, short = 'F')] + function: bool, + /// Count nodes of the given type: comma separated list. + #[clap(long, short = 'C', number_of_values = 1)] + count: Vec, + /// Compute different metrics. + #[clap(long, short)] + metrics: bool, + /// Retrieve all operands and operators in a code. + #[clap(long, conflicts_with = "metrics")] + ops: bool, + /// Do action in place. + #[clap(long, short)] + in_place: bool, + /// Glob to include files. + #[clap(long, short = 'I', num_args(0..))] + include: Vec, + /// Glob to exclude files. + #[clap(long, short = 'X', num_args(0..))] + exclude: Vec, + /// Number of jobs. + #[clap(long, short = 'j')] + num_jobs: Option, + /// Language type. + #[clap(long, short)] + language_type: Option, + /// Output metrics as different formats. + #[clap(long, short = 'O', value_parser = PossibleValuesParser::new(Format::all()) + .map(|s| s.parse::().unwrap()))] + output_format: Option, + /// Dump a pretty json file. + #[clap(long = "pr")] + pretty: bool, + /// Output file/directory. + #[clap(long, short, value_parser)] + output: Option, + /// Line start. + #[clap(long = "ls")] + line_start: Option, + /// Line end. + #[clap(long = "le")] + line_end: Option, + /// Print the warnings. + #[clap(long, short)] + warning: bool, +} + +fn main() { + let opts = Opts::parse(); + + let count_lock = if !opts.count.is_empty() { + Some(Arc::new(Mutex::new(Count::default()))) + } else { + None + }; + + let output_is_dir = opts.output.as_ref().map(|p| p.is_dir()).unwrap_or(false); + if (opts.metrics || opts.ops) && opts.output.is_some() && !output_is_dir { + eprintln!("Error: The output parameter must be a directory"); + process::exit(1); + } + + let typ = opts.language_type.unwrap_or_default(); + let language = if typ.is_empty() { + None + } else { + get_from_ext(&typ) + }; + + let num_jobs = opts + .num_jobs + .map(|num_jobs| std::cmp::max(2, num_jobs) - 1) + .unwrap_or_else(|| { + std::cmp::max( + 2, + available_parallelism() + .expect("Unrecoverable: Failed to get thread count") + .get(), + ) - 1 + }); + + let include = mk_globset(opts.include); + let exclude = mk_globset(opts.exclude); + + let cfg = Config { + dump: opts.dump, + in_place: opts.in_place, + comments: opts.comments, + find_filter: opts.find, + count_filter: opts.count, + language, + function: opts.function, + metrics: opts.metrics, + ops: opts.ops, + output_format: opts.output_format, + pretty: opts.pretty, + output: opts.output.clone(), + line_start: opts.line_start, + line_end: opts.line_end, + count_lock: count_lock.clone(), + }; + + let files_data = FilesData { + include, + exclude, + paths: opts.paths, + }; + + let _all_files = match ConcurrentRunner::new(num_jobs, act_on_file).run(cfg, files_data) { + Ok(all_files) => all_files, + Err(e) => { + eprintln!("{e:?}"); + process::exit(1); + } + }; + + if let Some(count) = count_lock { + let count = Arc::try_unwrap(count).unwrap().into_inner().unwrap(); + println!("{count}"); + } +} diff --git a/npm/mehen/README.md b/npm/mehen/README.md deleted file mode 100644 index b092d7ed..00000000 --- a/npm/mehen/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# mehen - -Rust-powered CLI for heuristic source code and documentation metrics: complexity, maintainability, -lines of code, and Markdown documentation health. - -📚 **Documentation: ** - -## Install - -```bash -npm install -g mehen -``` - -Or run without installing: - -```bash -npx -y mehen --help -bunx mehen --help -``` - -Also available on [PyPI](https://pypi.org/project/mehen/): - -```bash -uvx mehen --help -``` - -## Commands - -```bash -# Analyze exactly one file -mehen metrics - -# Compare metrics between two git revisions (powers the GitHub Action) -mehen diff --from --to --paths ... - -# Rank the worst-offending files in one or more trees -mehen top-offenders ... --metric -``` - -Full quickstart: . - -## What mehen computes - -For source code: cyclomatic complexity, cognitive complexity, Halstead suite, Maintainability Index, -ABC, LOC family (SLOC, PLOC, LLOC, CLOC, blank), NARGS, NEXITS, NOM, NPA, NPM, WMC. - -For Markdown documentation: Documentation Maintainability Index (DMI), Markdown Reading Path Complexity -(MRPC), Markdown Cognitive Complexity (MCC), Markdown Halstead, Link Debt, Table Burden, Visual -Scaffold, Artifact Debt, Repository Grounding, Evidence Coverage, Filler / Lazy Structure Risk, Review -Criticality Index, plus an opt-in English / Japanese prose layer. - -Full metric catalog with formulas and references: . - -## Supported languages - -Python (Ruff), TypeScript / JavaScript / JSX / TSX (Oxc), PHP (Mago), Ruby (Prism), Rust -(`ra_ap_syntax`), Kotlin (ANTLR — official Kotlin spec grammar), Go (tree-sitter), C (tree-sitter), -PowerShell (tree-sitter), and Markdown (pulldown-cmark). - -## CI integration - -`mehen` ships a GitHub Action that computes changed-file metric trends on pull requests, compares -against the base branch, and posts a summary comment: - -```yaml -permissions: - contents: read - pull-requests: write - issues: write - -steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - uses: ophi-dev/mehen@v1 - with: - paths: src - thresholds: | - cyclomatic=5 - cognitive=4 -``` - -Full reference: . - -## Platforms - -Native binaries are provided for: - -| OS | x64 | arm64 | -|---|---|---| -| Linux (glibc) | `@mehen/linux-x64-gnu` | `@mehen/linux-arm64-gnu` | -| Linux (musl) | `@mehen/linux-x64-musl` | `@mehen/linux-arm64-musl` | -| macOS | `@mehen/darwin-x64` | `@mehen/darwin-arm64` | -| Windows | `@mehen/win32-x64` | `@mehen/win32-arm64` | - -The correct binary is selected automatically at runtime. - -Requires Node.js >= 18. - -## Links - -- [Documentation](https://mehen.ophi.dev) -- [GitHub](https://github.com/ophi-dev/mehen) -- [Issues](https://github.com/ophi-dev/mehen/issues) -- [PyPI package](https://pypi.org/project/mehen/) - -## License - -[AGPL-3.0-only](https://www.gnu.org/licenses/agpl-3.0.html) diff --git a/npm/mehen/bin/mehen.js b/npm/mehen/bin/mehen.js index 58f3b461..e8b3b6fc 100644 --- a/npm/mehen/bin/mehen.js +++ b/npm/mehen/bin/mehen.js @@ -26,7 +26,7 @@ function detectMusl() { } return false; - } catch { + } catch (error) { return false; } } @@ -83,7 +83,7 @@ function main() { let binPath; try { binPath = require.resolve(`${pkgName}/bin/${binName}`); - } catch { + } catch (resolveError) { console.error(`Error: Could not find mehen binary for your platform (${pkgName}).`); console.error(''); console.error('This usually means:'); @@ -119,29 +119,9 @@ function main() { windowsHide: false }); } catch (execError) { - if (typeof execError.status === 'number') { + if (execError.status !== undefined) { process.exit(execError.status); } - if (execError.code === 'EACCES') { - if (process.platform === 'win32') { - console.error(`Error: access denied when launching mehen binary at ${binPath}.`); - console.error('On Windows this usually means the file is locked by another process'); - console.error('(e.g. antivirus scan) or was quarantined. Try rerunning the command,'); - console.error('and if it persists, reinstall mehen or whitelist the binary.'); - } else { - console.error(`Error: mehen binary at ${binPath} is not executable.`); - console.error('This is likely a packaging bug — please report it at:'); - console.error(' https://github.com/ophi-dev/mehen/issues'); - console.error(''); - console.error(`Workaround: chmod +x "${binPath}"`); - } - process.exit(126); - } - if (execError.code === 'ENOENT') { - console.error(`Error: mehen binary not found at ${binPath}.`); - console.error('Try reinstalling mehen.'); - process.exit(127); - } console.error(`Error executing mehen binary: ${execError.message}`); process.exit(1); } diff --git a/npm/mehen/package.json b/npm/mehen/package.json index a7e4d93b..31cd82e2 100644 --- a/npm/mehen/package.json +++ b/npm/mehen/package.json @@ -1,6 +1,6 @@ { "name": "mehen", - "version": "1.10.0", + "version": "0.0.1", "description": "Tool to compute and export code metrics", "keywords": [ "metrics", @@ -9,19 +9,17 @@ "cyclomatic", "halstead", "rust", - "go", - "typescript", "cli" ], - "homepage": "https://mehen.ophi.dev", + "homepage": "https://github.com/ophidiarium/mehen", "repository": { "type": "git", - "url": "https://github.com/ophi-dev/mehen.git" + "url": "https://github.com/ophidiarium/mehen.git" }, "bugs": { - "url": "https://github.com/ophi-dev/mehen/issues" + "url": "https://github.com/ophidiarium/mehen/issues" }, - "license": "AGPL-3.0-only", + "license": "MPL-2.0", "author": { "name": "Konstantin Vyatkin", "email": "tino@vtkn.io" @@ -37,14 +35,14 @@ "node": ">=18.0.0" }, "optionalDependencies": { - "@mehen/linux-x64-gnu": "1.10.0", - "@mehen/linux-x64-musl": "1.10.0", - "@mehen/linux-arm64-gnu": "1.10.0", - "@mehen/linux-arm64-musl": "1.10.0", - "@mehen/darwin-x64": "1.10.0", - "@mehen/darwin-arm64": "1.10.0", - "@mehen/win32-x64": "1.10.0", - "@mehen/win32-arm64": "1.10.0" + "@mehen/linux-x64-gnu": "0.0.1", + "@mehen/linux-x64-musl": "0.0.1", + "@mehen/linux-arm64-gnu": "0.0.1", + "@mehen/linux-arm64-musl": "0.0.1", + "@mehen/darwin-x64": "0.0.1", + "@mehen/darwin-arm64": "0.0.1", + "@mehen/win32-x64": "0.0.1", + "@mehen/win32-arm64": "0.0.1" }, "publishConfig": { "access": "public" diff --git a/npm/package.json.tmpl b/npm/package.json.tmpl index f7da7d72..ac2c8000 100644 --- a/npm/package.json.tmpl +++ b/npm/package.json.tmpl @@ -3,21 +3,24 @@ "version": "${node_version}", "description": "Mehen binary for ${node_os}-${node_arch}", "keywords": ["metrics", "code-analysis", "complexity", "rust", "cli"], - "homepage": "https://mehen.ophi.dev", + "homepage": "https://github.com/ophidiarium/mehen", "repository": { "type": "git", - "url": "https://github.com/ophi-dev/mehen.git" + "url": "https://github.com/ophidiarium/mehen.git" }, "bugs": { - "url": "https://github.com/ophi-dev/mehen/issues" + "url": "https://github.com/ophidiarium/mehen/issues" }, - "license": "AGPL-3.0-only", + "license": "MPL-2.0", "author": { "name": "Konstantin Vyatkin", "email": "tino@vtkn.io" }, "os": ["${node_os}"], "cpu": ["${node_arch}"], + "bin": { + "mehen": "./bin/mehen${extension}" + }, "files": [ "bin/", "README.md" diff --git a/pyproject.toml b/pyproject.toml index 6a9684be..d08b92d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,14 +7,14 @@ name = "mehen" dynamic = ["version"] description = "Tool to compute and export code metrics" authors = [{ name = "Konstantin Vyatkin", email = "tino@vtkn.io" }] -license = "AGPL-3.0-only" -license-files = ["LICENSE", "LICENSE-THIRD-PARTY"] +license = { file = "LICENSE" } readme = "README.md" requires-python = ">=3.8" dependencies = [] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", + "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -26,16 +26,12 @@ classifiers = [ keywords = ["metrics", "code-analysis", "complexity", "cyclomatic", "halstead"] [project.urls] -Homepage = "https://github.com/ophi-dev/mehen" -Repository = "https://github.com/ophi-dev/mehen" -Documentation = "https://mehen.ophi.dev" -Issues = "https://github.com/ophi-dev/mehen/issues" +Homepage = "https://github.com/ophidiarium/mehen" +Repository = "https://github.com/ophidiarium/mehen" +Documentation = "https://github.com/ophidiarium/mehen#readme" +Issues = "https://github.com/ophidiarium/mehen/issues" [tool.maturin] bindings = "bin" python-source = "python" -# Point at the `mehen` package's manifest. The repo root's -# `Cargo.toml` is a virtual workspace (no `[package]`/no binary -# target), so giving maturin the workspace manifest produces no -# packageable wheel. -manifest-path = "crates/mehen-cli/Cargo.toml" +manifest-path = "mehen-cli/Cargo.toml" diff --git a/recreate-grammars.sh b/recreate-grammars.sh new file mode 100755 index 00000000..00dc1035 --- /dev/null +++ b/recreate-grammars.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Clean old grammars builds +cargo clean --manifest-path ./enums/Cargo.toml + +# Recreate all grammars +cargo run --manifest-path ./enums/Cargo.toml -- -lrust -o ./src/languages + +# Format the code of the recreated grammars +cargo fmt diff --git a/release-please-config.json b/release-please-config.json index 08023d55..21dd1830 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -9,8 +9,14 @@ "draft": false, "prerelease": false, "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": false, - "changelog-sections": [ + "bump-patch-for-minor-pre-major": true, + "changelog-types": [ + { + "type": "chore", + "scope": "deps", + "section": "Dependencies", + "hidden": false + }, { "type": "feat", "section": "Features", @@ -27,13 +33,43 @@ "hidden": false }, { - "type": "deps", - "section": "Parser & Grammar Updates", + "type": "revert", + "section": "Reverts", "hidden": false }, { - "type": "revert", - "section": "Reverts", + "type": "docs", + "section": "Documentation", + "hidden": false + }, + { + "type": "style", + "section": "Styles", + "hidden": false + }, + { + "type": "chore", + "section": "Miscellaneous", + "hidden": false + }, + { + "type": "refactor", + "section": "Code Refactoring", + "hidden": false + }, + { + "type": "test", + "section": "Tests", + "hidden": false + }, + { + "type": "build", + "section": "Build System", + "hidden": false + }, + { + "type": "ci", + "section": "Continuous Integration", "hidden": false } ], @@ -46,7 +82,7 @@ { "type": "toml", "path": "Cargo.lock", - "jsonpath": "$.package[?(@.name.value == 'mehen')].version" + "jsonpath": "$.package[?(@.name == 'mehen')].version" }, { "type": "json", diff --git a/repro/roslyn-csharp-perf/.gitignore b/repro/roslyn-csharp-perf/.gitignore deleted file mode 100644 index bf04877a..00000000 --- a/repro/roslyn-csharp-perf/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Generated by run.sh (a 4.6 MB parser — not checked in). -/src/generated/ -/target/ -/Cargo.lock diff --git a/repro/roslyn-csharp-perf/Cargo.toml b/repro/roslyn-csharp-perf/Cargo.toml deleted file mode 100644 index 2ab9647c..00000000 --- a/repro/roslyn-csharp-perf/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "roslyn-csharp-perf" -version = "0.0.0" -edition = "2024" -publish = false - -[dependencies] -# The generated modules import the runtime as `antlr4_runtime`. -antlr4_runtime = { package = "antlr-rust-runtime", version = "=0.33.1" } - -# Standalone: this repro is deliberately NOT a workspace member, so it can be -# copied out of the mehen tree and built on its own. -[workspace] diff --git a/repro/roslyn-csharp-perf/README.md b/repro/roslyn-csharp-perf/README.md deleted file mode 100644 index 7b8f448e..00000000 --- a/repro/roslyn-csharp-perf/README.md +++ /dev/null @@ -1,124 +0,0 @@ -# Roslyn C# grammar — member-scaling performance repro - -Reproduces a ~quadratic-in-members-per-type parse cost on `dotnet/roslyn`'s -published C# grammar, and the fix. Self-contained: no need to re-derive a lexer -or hunt for fixtures. - -Context: [`antlr-rust-runtime#248`](https://github.com/ophi-dev/antlr-rust-runtime/issues/248) -(closed — the cause is in the grammar, not the runtime). - -## Quick start - -```bash -cargo install antlr-rust-codegen --version 0.33.1 \ - --bin antlr4-rust-gen --force - -./run.sh slow # as-published: record keyword is the catch-all `syntax_token` -./run.sh fixed # record contextual keyword restored (default) -``` - -## Root cause - -Roslyn's `Syntax.xml` declares the record keyword as a **contextual** kind: - -```xml - - - -``` - -Its grammar generator reads only `` children of a ``, never -`` — and this is the **only** `` in all of -`Syntax.xml` (versus 1018 plain ``), so it is the single field that hits -that blind spot. The published grammar therefore contains **no `'record'` -literal at all** and falls back to the catch-all `syntax_token`: - -```antlr -record_declaration - : attribute_list* modifier* syntax_token ('class' | 'struct')? … ; - -syntax_token - : character_literal_token | identifier_token | keyword - | numeric_literal_token | operator_token | punctuation_token - | string_literal_token ; -``` - -Because `syntax_token` accepts `keyword`, a `class` token is viable as **both** -`class_declaration` and `record_declaration`. Full-context prediction carries -that impossible record path across every member boundary, which is what scales -quadratically in members per type. - -Credit for this diagnosis goes to the antlr-rust-runtime team on #248. My -original hypothesis — Roslyn's optional body braces — was wrong: requiring the -braces only shortens the ambiguity window and masks the real cause. - -## Measured (runtime 0.21.0, release build, M-series macOS) - -| members | `slow` (as-published) | `fixed` (record restored) | -|---|---|---| -| 4 | 188 ms | 27 ms | -| 8 | 757 ms | 67 ms | -| 12 | 2 166 ms | 204 ms | -| 18 | 5 645 ms | 267 ms | -| 24 | 12 160 ms | **423 ms** | - -All inputs are valid C# parsing with **0 recovered syntax errors** in both -variants, and **both keep the body braces optional** — the difference is the -record keyword alone. - -On real code (`dotnet/runtime` `System.Text.Json`, 321 files): the whole library -went from **>600 s (timed out)** to **~3 m 50 s**, with the worst single file -dropping from **272 s** to under 6 s. Note that 52 files still exceed 1 s, so -some residual cost remains beyond this fix. - -## The fix - -`record` is a *contextual* keyword — legal as an ordinary name (`int record = 1;`) -— so it must not become a reserved token. Reserving it silently mis-parses -`record R(int X);` as two enum members plus a parenthesized expression, with zero -reported errors. Instead the declaration position is restricted to an identifier -whose text is `record`: - -```antlr -record_keyword - : {this.IsRecordKeyword()}? identifier_token - ; -``` - -`patterns.toml` lowers that predicate to a pure SemIR comparison -(`cmp(eq, token_text(1), str("record"))` → `LookaheadTextEquals`), so **no typed -hook is needed** and the grammar still generates under -`--sem-unknown error --require-full-semantics`. - -Verified: `record R(int X);` produces a real `record_declaration`; `record` still -works as a variable, field, and method name; 13/13 modern-C# probes pass. - -## What is here - -| Path | What it is | -|---|---| -| `grammar/` | The prepared pair plus `patterns.toml`. Roslyn ships a **parser-only** grammar, so the lexer (terminals, comment/directive channels) is supplied here. The interpolation and XML-doc *mode definitions* are present but not reached — see Known gap. | -| `grammar/unnarrowed-record/` | Same, with the record fix reverted — the `slow` control. | -| `fixtures/gen-fixture.py` | Emits a class with N members. The cost scales with members per type, not file length, so a generated fixture reproduces it exactly and avoids vendoring third-party source. | -| `fixtures/omitted-nodes.cs` | Regression fixture for Roslyn's "omitted" (empty) syntax nodes — `int[,]`, `int[,,]`, `Dictionary<,>`. Deleting those empty rules without preserving the syntax they expressed silently breaks all of it; `run.sh` asserts 0 errors here via `time-parse --require-clean`. | -| `src/bin/time-parse.rs` | Times `compilation_unit` per file; prints ms + recovered-error count. `--require-clean` exits 1 on any error, so a regression step can actually fail. | -| `run.sh` | Generate → build → measure, either variant. | - -The grammar is derived by -`crates/mehen-csharp-parser/grammar/prepare-grammar.py` from a pinned -upstream revision (`dotnet/roslyn` `76234ec6a1`, 2026-06-24). See that script and -`crates/mehen-csharp-parser/grammar/PROVENANCE.md` for every correction and why. - -## Known unrelated gap - -Interpolated strings do not parse in **this snapshot**: `$"` is harvested as an -ordinary literal, so the `INTERPOLATION` mode is defined but never entered. The -mode definitions in `grammar/CSharpLexer.g4` are therefore dead code here — read -them as inert, not as working support. - -This is a defect in the *snapshot*, not in the current preparation: the grammar -under `crates/mehen-csharp-parser/` rewrites those literals to the mode-pushing -`INTERP_START` / `INTERP_VERBATIM_START` / `INTERP_RAW_START` tokens and does -parse interpolated strings. This directory is a frozen reproduction for the -`record`-keyword timing issue and is deliberately not resynced; it does not -affect these timings, since no fixture uses `$"`. diff --git a/repro/roslyn-csharp-perf/fixtures/gen-fixture.py b/repro/roslyn-csharp-perf/fixtures/gen-fixture.py deleted file mode 100755 index cae11c85..00000000 --- a/repro/roslyn-csharp-perf/fixtures/gen-fixture.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python3 -"""Emit a synthetic C# file with N members in one class. - -The blow-up scales with *members per type*, not with file length or statement -count, so a generated fixture reproduces it exactly and avoids vendoring -third-party source. Verified against real code: `JsonDocument.Parse.cs` -(953 lines, dotnet/runtime System.Text.Json) takes ~272 s as-published. - - python3 gen-fixture.py 18 > members-18.cs -""" -import sys - -n = int(sys.argv[1]) if len(sys.argv) > 1 else 18 -# `range(-1)` is empty, so a negative count would silently emit a zero-member -# fixture and the timing row would read as "fast" rather than as a mistake. -if n < 0: - sys.exit(f"error: member count must be non-negative, got {n}") -print("class C\n{") -for i in range(n): - print(f" public int P{i}() {{ return {i}; }}") -print("}") diff --git a/repro/roslyn-csharp-perf/fixtures/omitted-nodes.cs b/repro/roslyn-csharp-perf/fixtures/omitted-nodes.cs deleted file mode 100644 index 32633f7c..00000000 --- a/repro/roslyn-csharp-perf/fixtures/omitted-nodes.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Regression fixture: syntax that Roslyn expresses with its "omitted" (empty) -// syntax nodes. The preparation must remove those empty *rules* (ANTLR forbids -// an empty rule inside a closure) WITHOUT losing the syntax they expressed — -// deleting the alternatives outright makes every line below fail to parse. -class C -{ - // omitted_array_size_expression: the blank sizes in a multi-dimensional rank - int[,] _field; - - int[,] MultiDim() - { - int[,] local; - return new int[2, 3]; - } - - int[,,] ThreeDim() { return new int[1, 2, 3]; } - - // omitted_type_argument: unbound generic names - System.Type Unbound() { return typeof(System.Collections.Generic.Dictionary<,>); } - System.Type UnboundOne() { return typeof(System.Collections.Generic.List<>); } -} diff --git a/repro/roslyn-csharp-perf/grammar/.gitignore b/repro/roslyn-csharp-perf/grammar/.gitignore deleted file mode 100644 index 5dac6683..00000000 --- a/repro/roslyn-csharp-perf/grammar/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ANTLR IDE plugin scratch output. -.antlr/ diff --git a/repro/roslyn-csharp-perf/grammar/CSharpLexer.g4 b/repro/roslyn-csharp-perf/grammar/CSharpLexer.g4 deleted file mode 100644 index c159b78c..00000000 --- a/repro/roslyn-csharp-perf/grammar/CSharpLexer.g4 +++ /dev/null @@ -1,359 +0,0 @@ -// @generated from Roslyn's CSharp.Generated.g4 by prepare-roslyn-grammar.py — do not hand-edit. -// Roslyn publishes a parser-only grammar; this lexer supplies the -// terminals it references. Literal tokens below are harvested from the -// parser's inline literals; the rest is spliced from `lexer-tokens.g4.in`. -// See PROVENANCE.md. -lexer grammar CSharpLexer; - -channels { COMMENTS_CHANNEL, DIRECTIVE } - -// Emitted only from their lexer modes, but referenced by the parser, -// so they must be declared up front. -tokens { INTERPOLATED_TEXT, XML_TEXT_LIT } - -// ---- keywords, operators, punctuation (must precede IDENTIFIER) ---- -KW___REFVALUE : '__refvalue' ; -KW_DESCENDING : 'descending' ; -KW_STACKALLOC : 'stackalloc' ; -KW___ARGLIST : '__arglist' ; -KW___MAKEREF : '__makeref' ; -KW___REFTYPE : '__reftype' ; -KW_ASCENDING : 'ascending' ; -KW_EXTENSION : 'extension' ; -KW_INTERFACE : 'interface' ; -KW_NAMESPACE : 'namespace' ; -KW_PROTECTED : 'protected' ; -KW_UNCHECKED : 'unchecked' ; -KW_UNMANAGED : 'unmanaged' ; -KW_ABSTRACT : 'abstract' ; -KW_CONTINUE : 'continue' ; -KW_DELEGATE : 'delegate' ; -KW_EXPLICIT : 'explicit' ; -KW_IMPLICIT : 'implicit' ; -KW_INTERNAL : 'internal' ; -KW_OPERATOR : 'operator' ; -KW_OVERRIDE : 'override' ; -KW_READONLY : 'readonly' ; -KW_REQUIRED : 'required' ; -KW_VOLATILE : 'volatile' ; -KW_CHECKED : 'checked' ; -KW_DECIMAL : 'decimal' ; -KW_DEFAULT : 'default' ; -KW_FINALLY : 'finally' ; -KW_FOREACH : 'foreach' ; -KW_MANAGED : 'managed' ; -KW_ORDERBY : 'orderby' ; -KW_PARTIAL : 'partial' ; -KW_PRIVATE : 'private' ; -KW_VIRTUAL : 'virtual' ; -KW_ALLOWS : 'allows' ; -KW_CLOSED : 'closed' ; -KW_DOUBLE : 'double' ; -KW_EQUALS : 'equals' ; -KW_EXTERN : 'extern' ; -KW_GLOBAL : 'global' ; -KW_OBJECT : 'object' ; -KW_PARAMS : 'params' ; -KW_PUBLIC : 'public' ; -KW_REMOVE : 'remove' ; -KW_RETURN : 'return' ; -KW_SCOPED : 'scoped' ; -KW_SEALED : 'sealed' ; -KW_SELECT : 'select' ; -KW_SIZEOF : 'sizeof' ; -KW_STATIC : 'static' ; -KW_STRING : 'string' ; -KW_STRUCT : 'struct' ; -KW_SWITCH : 'switch' ; -KW_TYPEOF : 'typeof' ; -KW_UNSAFE : 'unsafe' ; -KW_USHORT : 'ushort' ; -KW_ALIAS : 'alias' ; -KW_ASYNC : 'async' ; -KW_AWAIT : 'await' ; -KW_BREAK : 'break' ; -KW_CATCH : 'catch' ; -KW_CLASS : 'class' ; -KW_CONST : 'const' ; -KW_EVENT : 'event' ; -KW_FALSE : 'false' ; -KW_FIELD : 'field' ; -KW_FIXED : 'fixed' ; -KW_FLOAT : 'float' ; -KW_GROUP : 'group' ; -KW_SBYTE : 'sbyte' ; -KW_SHORT : 'short' ; -KW_THROW : 'throw' ; -KW_ULONG : 'ulong' ; -KW_UNION : 'union' ; -KW_USING : 'using' ; -KW_WHERE : 'where' ; -KW_WHILE : 'while' ; -KW_YIELD : 'yield' ; -OP_078 : '>>>=' ; -KW_BASE : 'base' ; -KW_BOOL : 'bool' ; -KW_BYTE : 'byte' ; -KW_CASE : 'case' ; -KW_CHAR : 'char' ; -KW_ELSE : 'else' ; -KW_ENUM : 'enum' ; -KW_FILE : 'file' ; -KW_FROM : 'from' ; -KW_GOTO : 'goto' ; -KW_INIT : 'init' ; -KW_INTO : 'into' ; -KW_JOIN : 'join' ; -KW_LOCK : 'lock' ; -KW_LONG : 'long' ; -KW_NULL : 'null' ; -KW_SAFE : 'safe' ; -KW_THIS : 'this' ; -KW_TRUE : 'true' ; -KW_UINT : 'uint' ; -KW_VOID : 'void' ; -KW_WHEN : 'when' ; -KW_WITH : 'with' ; -OP_102 : '"""' ; -OP_103 : '<<=' ; -OP_104 : '>>=' ; -OP_105 : '>>>' ; -OP_106 : '??=' ; -KW_ADD : 'add' ; -KW_AND : 'and' ; -KW_FOR : 'for' ; -KW_GET : 'get' ; -KW_INT : 'int' ; -KW_LET : 'let' ; -KW_NEW : 'new' ; -KW_NOT : 'not' ; -KW_OUT : 'out' ; -KW_REF : 'ref' ; -KW_SET : 'set' ; -KW_TRY : 'try' ; -KW_VAR : 'var' ; -OP_120 : '!=' ; -OP_121 : '%=' ; -OP_122 : '&&' ; -OP_123 : '&=' ; -OP_124 : '*=' ; -OP_125 : '++' ; -OP_126 : '+=' ; -OP_127 : '--' ; -OP_128 : '-=' ; -OP_129 : '->' ; -OP_130 : '..' ; -OP_131 : '/=' ; -OP_132 : '/>' ; -OP_133 : '::' ; -OP_134 : '' ; -OP_139 : '>=' ; -OP_140 : '>>' ; -OP_141 : '??' ; -KW_U8 : 'U8' ; -OP_143 : '\'' ; -OP_144 : '\\' ; -OP_145 : '^=' ; -KW_AS : 'as' ; -KW_BY : 'by' ; -KW_DO : 'do' ; -KW_IF : 'if' ; -KW_IN : 'in' ; -KW_IS : 'is' ; -KW_ON : 'on' ; -KW_OR : 'or' ; -KW_U8_154 : 'u8' ; -OP_155 : '|=' ; -OP_156 : '||' ; -OP_157 : '!' ; -OP_158 : '"' ; -OP_159 : '#' ; -OP_160 : '$' ; -OP_161 : '%' ; -OP_162 : '&' ; -OP_163 : '(' ; -OP_164 : ')' ; -OP_165 : '*' ; -OP_166 : '+' ; -OP_167 : ',' ; -OP_168 : '-' ; -OP_169 : '.' ; -OP_170 : '/' ; -OP_171 : ':' ; -OP_172 : ';' ; -OP_173 : '<' ; -OP_174 : '=' ; -OP_175 : '>' ; -OP_176 : '?' ; -OP_177 : '[' ; -OP_178 : ']' ; -OP_179 : '^' ; -KW__ : '_' ; -OP_181 : '{' ; -OP_182 : '|' ; -OP_183 : '}' ; -OP_184 : '~' ; - -// Lexer rules supplied for Roslyn's parser-only C# grammar, spliced verbatim -// into the generated `CSharpLexer.g4` by `prepare-roslyn-grammar.py`. -// -// Roslyn's `CSharp.Generated.g4` describes its terminals as character-level -// *parser* rules (`identifier_token : '@'? identifier_start_character …`, -// `decimal_digit : '0' | '1' | …`). Those cannot stay in the parser: single -// character tokens would shadow multi-character ones, so `'C'` beats -// `IDENTIFIER` and `'1'` beats a decimal literal. Each rule below replaces one -// such Roslyn rule, following the C# lexical grammar (ECMA-334 §6.4). -// -// This file is hand-written ANTLR (not generated), kept separate from the -// script so the ANTLR-level escaping is readable and reviewable as grammar -// source rather than as nested Python string escapes. -// -// The `TOKEN <-> roslyn_rule` mapping is declared in the script's -// LEXER_TOKEN_RULES table; adding a rule here requires adding it there too. - -// §6.4.3 Identifiers. `@` is the verbatim-identifier prefix; the character -// classes follow identifier_start_character / identifier_part_character. -IDENTIFIER - : '@'? [\p{L}\p{Nl}_] [\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]* - ; - -// §6.4.5.3 Integer literals. Two suffix slots cover `ul` / `lu`. -DEC_INT_LIT - : [0-9] [0-9_]* [uUlL]? [uUlL]? - ; - -HEX_INT_LIT - : '0' [xX] [0-9a-fA-F_]+ [uUlL]? [uUlL]? - ; - -BIN_INT_LIT - : '0' [bB] [01_]+ [uUlL]? [uUlL]? - ; - -// §6.4.5.5 Real literals — embedded dot, leading dot, exponent-only, and -// suffix-only forms. -REAL_LIT - : [0-9] [0-9_]* '.' [0-9] [0-9_]* ExponentPart? [fFdDmM]? - | '.' [0-9] [0-9_]* ExponentPart? [fFdDmM]? - | [0-9] [0-9_]* ExponentPart [fFdDmM]? - | [0-9] [0-9_]* [fFdDmM] - ; - -fragment ExponentPart - : [eE] [+-]? [0-9] [0-9_]* - ; - -// §6.4.5.6 Character literals. -CHAR_LIT - : '\'' ( '\\' . | ~['\\\r\n] ) '\'' - ; - -// §6.4.5.7 String literals. -STRING_LIT - : '"' ( '\\' . | ~["\\\r\n] )* '"' - ; - -VERBATIM_STRING_LIT - : '@"' ( '""' | ~'"' )* '"' - ; - -// C# 11 raw string literals. The real rule requires the closing fence to be at -// least as long as the opening one, which a context-free lexer rule cannot -// express; a non-greedy match is sufficient here because every metric that -// touches a string literal (LOC rows, Halstead operand) only needs the token's -// extent, not its internal structure. -ML_RAW_STRING_LIT - : '"""' '"'* .*? '"""' '"'* - ; - -SL_RAW_STRING_LIT - : '""' ~[\r\n]*? '""' - ; - -// ---- trivia ------------------------------------------------------------- -// Comments go to a dedicated channel so the CLOC sweep can read them while the -// parser never sees them. Roslyn models trivia as syntax, so its grammar has no -// rules for these at all. -SINGLE_LINE_DOC_COMMENT : '///' ~[\r\n]* -> channel(COMMENTS_CHANNEL) ; -DELIMITED_DOC_COMMENT : '/**' .*? '*/' -> channel(COMMENTS_CHANNEL) ; -SINGLE_LINE_COMMENT : '//' ~[\r\n]* -> channel(COMMENTS_CHANNEL) ; -DELIMITED_COMMENT : '/*' .*? '*/' -> channel(COMMENTS_CHANNEL) ; -WHITESPACES : [ \t\r\n\f]+ -> channel(HIDDEN) ; -BYTE_ORDER_MARK : '' -> skip ; - -// A preprocessor directive line. mehen does not evaluate `#if` (unlike the -// grammars-v4 lexer's `CSharpLexerBase`, which needs a stateful hook for it); -// directives are routed to their own channel so they are neither code nor -// comment for LOC, and inactive regions are still parsed as ordinary code. -DIRECTIVE_LINE : '#' ~[\r\n]* -> channel(DIRECTIVE) ; - -// ---- interpolated strings ---------------------------------------------- -// Roslyn spells interpolated strings as -// -// interpolated_string_expression -// : '$"' interpolated_string_content* '"' -// | '$@"' interpolated_string_content* '"' ; -// interpolation : '{' expression … '}' ; -// -// The *text* between holes needs its own lexer mode: in the default mode a -// broad negated set would swallow ordinary code (an earlier flat-lexer attempt -// lexed `class C ` as one token that way). -// -// NOTE: in this frozen snapshot these modes are never entered at all — `$"` is -// harvested as an ordinary literal, so nothing pushes INTERPOLATION. The rules -// below are inert. (The live grammar under `crates/mehen-csharp-parser/` rewrites -// those literals to mode-pushing tokens and does parse interpolated strings; see -// that crate's `grammar/lexer-tokens.g4.in`. This directory is deliberately not -// resynced — it reproduces one timing issue and no fixture uses `$"`.) -// -// The comment below described a design that no longer exists: there is no -// `../src/hooks.rs`, and the live grammar drives every transition from grammar -// commands with the brace depth held in `@lexer::members`. It is kept because the -// *problem* it states is the real one: the `}` that closes a hole is lexically -// identical to the one closing a nested block — -// -// $"a{ new[]{ 1, 2 }.Length }b" -// ^^^^^^^^^ must NOT end the hole -// -// so it needs a brace depth per open hole and a *conditional* pop. Keeping the -// grammar free of mode commands also keeps the two halves from fighting over -// the mode stack. See `CSharpLexerHooks` for the state machine. -// -// `prepare-roslyn-grammar.py` rewrites the harvested `'$"'` / `'$@"'` literals -// to the named tokens below (INTERP_TOKEN_LITERALS) so the hook can recognize -// them by a stable name. -INTERP_START : '$"' ; -INTERP_VERBATIM_START : '$@"' ; - -mode INTERPOLATION; - -// `{{` / `}}` are escaped literal braces, not holes — first so they win the -// longest match over the single-brace rules below. -INTERP_ESCAPED_OPEN : '{{' -> type(INTERPOLATED_TEXT) ; -INTERP_ESCAPED_CLOSE : '}}' -> type(INTERPOLATED_TEXT) ; - -// Text between holes. -INTERPOLATED_TEXT : ~[{}"\\]+ ; - -// A hole opens / the string ends. Both emit the token type the parser expects -// (`{` and `"` respectively); the hook performs the mode change. -INTERP_HOLE_OPEN : '{' -> type(OP_181) ; -INTERP_END : '"' -> type(OP_158) ; - -// A format specifier (`{x:D4}`) is a third mode: after the `:` that ends a -// hole's expression, the remaining text up to the closing `}` is literal format -// text, not C# code — `D4` must not lex as an identifier. (The grammars-v4 C# -// lexer has an INTERPOLATION_FORMAT mode for the same reason.) The hook enters -// this mode on a `:` seen at brace depth 0 inside a hole. -mode INTERPOLATION_FORMAT; - -// The format text, emitted as the same token the grammar's -// `interpolation_format_clause : ':' interpolated_string_text_token` expects. -INTERP_FORMAT_TEXT : ~[}"]+ -> type(INTERPOLATED_TEXT) ; - -// The `}` that closes the hole; the hook restores the interpolation mode. -INTERP_FORMAT_END : '}' -> type(OP_183) ; diff --git a/repro/roslyn-csharp-perf/grammar/CSharpParser.g4 b/repro/roslyn-csharp-perf/grammar/CSharpParser.g4 deleted file mode 100644 index f795e385..00000000 --- a/repro/roslyn-csharp-perf/grammar/CSharpParser.g4 +++ /dev/null @@ -1,1451 +0,0 @@ -// @generated from Roslyn's CSharp.Generated.g4 by prepare-roslyn-grammar.py — do not hand-edit. -// See PROVENANCE.md for the pinned upstream revision and the patch rationale. -parser grammar CSharpParser; - -options { tokenVocab=CSharpLexer; } - -compilation_unit - : extern_alias_directive* using_directive* attribute_list* member_declaration* - ; - -extern_alias_directive - : KW_EXTERN KW_ALIAS identifier_token OP_172 - ; - -using_directive - : KW_GLOBAL? KW_USING (KW_STATIC | (KW_UNSAFE? name_equals))? type OP_172 - ; - -name_equals - : identifier_name OP_174 - ; - -identifier_name - : KW_GLOBAL - | identifier_token - ; - -attribute_list - : OP_177 attribute_target_specifier? attribute (OP_167 attribute)* OP_178 - ; - -attribute_target_specifier - : syntax_token OP_171 - ; - -attribute - : name attribute_argument_list? - ; - -name - : alias_qualified_name - | qualified_name - | simple_name - ; - -alias_qualified_name - : identifier_name OP_133 simple_name - ; - -simple_name - : generic_name - | identifier_name - ; - -generic_name - : identifier_token type_argument_list - ; - -type_argument_list - : OP_173 (type? (OP_167 type?)*)? OP_175 - ; - -qualified_name - : name OP_169 simple_name - ; - -attribute_argument_list - : OP_163 (attribute_argument (OP_167 attribute_argument)*)? OP_164 - ; - -attribute_argument - : (name_equals? | name_colon?) expression - ; - -name_colon - : identifier_name OP_171 - ; - -member_declaration - : base_field_declaration - | base_method_declaration - | base_namespace_declaration - | base_property_declaration - | base_type_declaration - | delegate_declaration - | enum_member_declaration - | global_statement - | incomplete_member - ; - -base_field_declaration - : event_field_declaration - | field_declaration - ; - -event_field_declaration - : attribute_list* modifier* KW_EVENT variable_declaration OP_172 - ; - -modifier - : KW_ABSTRACT - | KW_ASYNC - | KW_CLOSED - | KW_CONST - | KW_EXTERN - | KW_FILE - | KW_FIXED - | KW_INTERNAL - | KW_NEW - | KW_OVERRIDE - | KW_PARTIAL - | KW_PRIVATE - | KW_PROTECTED - | KW_PUBLIC - | KW_READONLY - | KW_REF - | KW_REQUIRED - | KW_SAFE - | KW_SCOPED - | KW_SEALED - | KW_STATIC - | KW_UNSAFE - | KW_VIRTUAL - | KW_VOLATILE - ; - -variable_declaration - : type variable_declarator (OP_167 variable_declarator)* - ; - -variable_declarator - : identifier_token bracketed_argument_list? equals_value_clause? - ; - -bracketed_argument_list - : OP_177 argument (OP_167 argument)* OP_178 - ; - -argument - : name_colon? (KW_REF | KW_OUT | KW_IN)? expression - ; - -equals_value_clause - : OP_174 expression - ; - -field_declaration - : attribute_list* modifier* variable_declaration OP_172 - ; - -base_method_declaration - : constructor_declaration - | conversion_operator_declaration - | destructor_declaration - | method_declaration - | operator_declaration - ; - -constructor_declaration - : attribute_list* modifier* identifier_token parameter_list constructor_initializer? (block | (arrow_expression_clause OP_172)) - ; - -parameter_list - : OP_163 (parameter (OP_167 parameter)*)? OP_164 - ; - -parameter - : attribute_list* modifier* type? (identifier_token | KW___ARGLIST)? equals_value_clause? - ; - -constructor_initializer - : OP_171 (KW_BASE | KW_THIS) argument_list - ; - -argument_list - : OP_163 (argument (OP_167 argument)*)? OP_164 - ; - -block - : attribute_list* OP_181 statement* OP_183 - ; - -arrow_expression_clause - : OP_138 expression - ; - -conversion_operator_declaration - : attribute_list* modifier* (KW_IMPLICIT | KW_EXPLICIT) explicit_interface_specifier? KW_OPERATOR KW_CHECKED? type parameter_list (block | (arrow_expression_clause OP_172)) - ; - -explicit_interface_specifier - : name OP_169 - ; - -destructor_declaration - : attribute_list* modifier* OP_184 identifier_token parameter_list (block | (arrow_expression_clause OP_172)) - ; - -method_declaration - : attribute_list* modifier* type explicit_interface_specifier? identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* (block | (arrow_expression_clause OP_172)) - ; - -type_parameter_list - : OP_173 type_parameter (OP_167 type_parameter)* OP_175 - ; - -type_parameter - : attribute_list* (KW_IN | KW_OUT)? identifier_token - ; - -type_parameter_constraint_clause - : KW_WHERE identifier_name OP_171 type_parameter_constraint (OP_167 type_parameter_constraint)* - ; - -type_parameter_constraint - : allows_constraint_clause - | class_or_struct_constraint - | constructor_constraint - | default_constraint - | type_constraint - ; - -allows_constraint_clause - : KW_ALLOWS allows_constraint (OP_167 allows_constraint)* - ; - -allows_constraint - : ref_struct_constraint - ; - -ref_struct_constraint - : KW_REF KW_STRUCT - ; - -class_or_struct_constraint - : KW_CLASS OP_176? - | KW_STRUCT OP_176? - ; - -constructor_constraint - : KW_NEW OP_163 OP_164 - ; - -default_constraint - : KW_DEFAULT - ; - -type_constraint - : type - ; - -operator_declaration - : attribute_list* modifier* type explicit_interface_specifier? KW_OPERATOR KW_CHECKED? (OP_166 | OP_168 | OP_157 | OP_184 | OP_125 | OP_127 | OP_165 | OP_170 | OP_161 | OP_135 | OP_140 | OP_105 | OP_182 | OP_162 | OP_179 | OP_137 | OP_120 | OP_173 | OP_136 | OP_175 | OP_139 | KW_FALSE | KW_TRUE | KW_IS | OP_126 | OP_128 | OP_124 | OP_131 | OP_121 | OP_123 | OP_155 | OP_145 | OP_103 | OP_104 | OP_078) parameter_list (block | (arrow_expression_clause OP_172)) - ; - -base_namespace_declaration - : file_scoped_namespace_declaration - | namespace_declaration - ; - -file_scoped_namespace_declaration - : attribute_list* modifier* KW_NAMESPACE name OP_172 extern_alias_directive* using_directive* member_declaration* - ; - -namespace_declaration - : attribute_list* modifier* KW_NAMESPACE name OP_181 extern_alias_directive* using_directive* member_declaration* OP_183 OP_172? - ; - -base_property_declaration - : event_declaration - | indexer_declaration - | property_declaration - ; - -event_declaration - : attribute_list* modifier* KW_EVENT type explicit_interface_specifier? identifier_token (accessor_list | OP_172) - ; - -accessor_list - : OP_181 accessor_declaration* OP_183 - ; - -accessor_declaration - : attribute_list* modifier* (KW_GET | KW_SET | KW_INIT | KW_ADD | KW_REMOVE | identifier_token) (block | (arrow_expression_clause OP_172)) - ; - -indexer_declaration - : attribute_list* modifier* type explicit_interface_specifier? KW_THIS bracketed_parameter_list (accessor_list | (arrow_expression_clause OP_172)) - ; - -bracketed_parameter_list - : OP_177 parameter (OP_167 parameter)* OP_178 - ; - -property_declaration - : attribute_list* modifier* type explicit_interface_specifier? identifier_token (accessor_list | ((arrow_expression_clause | equals_value_clause) OP_172)) - ; - -base_type_declaration - : enum_declaration - | type_declaration - ; - -enum_declaration - : attribute_list* modifier* KW_ENUM identifier_token base_list? OP_181? (enum_member_declaration (OP_167 enum_member_declaration)* OP_167?)? OP_183? OP_172? - ; - -base_list - : OP_171 base_type (OP_167 base_type)* - ; - -base_type - : primary_constructor_base_type - | simple_base_type - ; - -primary_constructor_base_type - : type argument_list - ; - -simple_base_type - : type - ; - -enum_member_declaration - : attribute_list* modifier* identifier_token equals_value_clause? - ; - -type_declaration - : class_declaration - | extension_block_declaration - | interface_declaration - | record_declaration - | struct_declaration - | union_declaration - ; - -class_declaration - : attribute_list* modifier* KW_CLASS identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -extension_block_declaration - : attribute_list* modifier* KW_EXTENSION type_parameter_list? parameter_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -interface_declaration - : attribute_list* modifier* KW_INTERFACE identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -record_declaration - : attribute_list* modifier* record_keyword (KW_CLASS | KW_STRUCT)? identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -struct_declaration - : attribute_list* modifier* KW_STRUCT identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -union_declaration - : attribute_list* modifier* KW_UNION identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -delegate_declaration - : attribute_list* modifier* KW_DELEGATE type identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* OP_172 - ; - -global_statement - : attribute_list* modifier* statement - ; - -incomplete_member - : attribute_list* modifier* type - ; - -type - : array_type - | function_pointer_type - | name - | nullable_type - | pointer_type - | predefined_type - | ref_type - | scoped_type - | tuple_type - ; - -array_type - : type array_rank_specifier+ - ; - -array_rank_specifier - : OP_177 (expression? (OP_167 expression?)*)? OP_178 - ; - -function_pointer_type - : KW_DELEGATE OP_165 function_pointer_calling_convention? function_pointer_parameter_list - ; - -function_pointer_calling_convention - : KW_MANAGED function_pointer_unmanaged_calling_convention_list? - | KW_UNMANAGED function_pointer_unmanaged_calling_convention_list? - ; - -function_pointer_unmanaged_calling_convention_list - : OP_177 function_pointer_unmanaged_calling_convention (OP_167 function_pointer_unmanaged_calling_convention)* OP_178 - ; - -function_pointer_unmanaged_calling_convention - : identifier_token - ; - -function_pointer_parameter_list - : OP_173 function_pointer_parameter (OP_167 function_pointer_parameter)* OP_175 - ; - -function_pointer_parameter - : attribute_list* modifier* type - ; - -nullable_type - : type OP_176 - ; - -pointer_type - : type OP_165 - ; - -predefined_type - : KW_BOOL - | KW_BYTE - | KW_CHAR - | KW_DECIMAL - | KW_DOUBLE - | KW_FLOAT - | KW_INT - | KW_LONG - | KW_OBJECT - | KW_SBYTE - | KW_SHORT - | KW_STRING - | KW_UINT - | KW_ULONG - | KW_USHORT - | KW_VOID - ; - -ref_type - : KW_REF KW_READONLY? type - ; - -scoped_type - : KW_SCOPED type - ; - -tuple_type - : OP_163 tuple_element (OP_167 tuple_element)+ OP_164 - ; - -tuple_element - : type identifier_token? - ; - -statement - : block - | break_statement - | checked_statement - | common_for_each_statement - | continue_statement - | do_statement - | empty_statement - | expression_statement - | fixed_statement - | for_statement - | goto_statement - | if_statement - | labeled_statement - | local_declaration_statement - | local_function_statement - | lock_statement - | return_statement - | switch_statement - | throw_statement - | try_statement - | unsafe_statement - | using_statement - | while_statement - | yield_statement - ; - -break_statement - : attribute_list* KW_BREAK identifier_name? OP_172 - ; - -checked_statement - : attribute_list* (KW_CHECKED | KW_UNCHECKED) block - ; - -common_for_each_statement - : for_each_statement - | for_each_variable_statement - ; - -for_each_statement - : attribute_list* KW_AWAIT? KW_FOREACH OP_163 type identifier_token KW_IN expression OP_164 statement - ; - -for_each_variable_statement - : attribute_list* KW_AWAIT? KW_FOREACH OP_163 expression KW_IN expression OP_164 statement - ; - -continue_statement - : attribute_list* KW_CONTINUE identifier_name? OP_172 - ; - -do_statement - : attribute_list* KW_DO statement KW_WHILE OP_163 expression OP_164 OP_172 - ; - -empty_statement - : attribute_list* OP_172 - ; - -expression_statement - : attribute_list* expression OP_172 - ; - -fixed_statement - : attribute_list* KW_FIXED OP_163 variable_declaration OP_164 statement - ; - -for_statement - : attribute_list* KW_FOR OP_163 (variable_declaration? | (expression (OP_167 expression)*)?) OP_172 expression? OP_172 (expression (OP_167 expression)*)? OP_164 statement - ; - -goto_statement - : attribute_list* KW_GOTO (KW_CASE | KW_DEFAULT)? expression? OP_172 - ; - -if_statement - : attribute_list* KW_IF OP_163 expression OP_164 statement else_clause? - ; - -else_clause - : KW_ELSE statement - ; - -labeled_statement - : attribute_list* identifier_token OP_171 statement - ; - -local_declaration_statement - : attribute_list* KW_AWAIT? KW_USING? modifier* variable_declaration OP_172 - ; - -local_function_statement - : attribute_list* modifier* type identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* (block | (arrow_expression_clause OP_172)) - ; - -lock_statement - : attribute_list* KW_LOCK OP_163 expression OP_164 statement - ; - -return_statement - : attribute_list* KW_RETURN expression? OP_172 - ; - -switch_statement - : attribute_list* KW_SWITCH OP_163? expression OP_164? OP_181 switch_section* OP_183 - ; - -switch_section - : switch_label+ statement+ - ; - -switch_label - : case_pattern_switch_label - | case_switch_label - | default_switch_label - ; - -case_pattern_switch_label - : KW_CASE pattern when_clause? OP_171 - ; - -pattern - : binary_pattern - | constant_pattern - | declaration_pattern - | discard_pattern - | list_pattern - | parenthesized_pattern - | recursive_pattern - | relational_pattern - | slice_pattern - | type_pattern - | unary_pattern - | var_pattern - ; - -binary_pattern - : pattern (KW_OR | KW_AND) pattern - ; - -constant_pattern - : expression - ; - -declaration_pattern - : type variable_designation - ; - -variable_designation - : discard_designation - | parenthesized_variable_designation - | single_variable_designation - ; - -discard_designation - : KW__ - ; - -parenthesized_variable_designation - : OP_163 (variable_designation (OP_167 variable_designation)*)? OP_164 - ; - -single_variable_designation - : identifier_token - ; - -discard_pattern - : KW__ - ; - -list_pattern - : OP_177 (pattern (OP_167 pattern)* OP_167?)? OP_178 variable_designation? - ; - -parenthesized_pattern - : OP_163 pattern OP_164 - ; - -recursive_pattern - : type? positional_pattern_clause? property_pattern_clause? variable_designation? - ; - -positional_pattern_clause - : OP_163 (subpattern (OP_167 subpattern)*)? OP_164 - ; - -subpattern - : base_expression_colon? pattern - ; - -base_expression_colon - : expression_colon - | name_colon - ; - -expression_colon - : expression OP_171 - ; - -property_pattern_clause - : OP_181 (subpattern (OP_167 subpattern)* OP_167?)? OP_183 - ; - -relational_pattern - : OP_120 expression - | OP_173 expression - | OP_136 expression - | OP_137 expression - | OP_175 expression - | OP_139 expression - ; - -slice_pattern - : OP_130 pattern? - ; - -type_pattern - : type - ; - -unary_pattern - : KW_NOT pattern - ; - -var_pattern - : KW_VAR variable_designation - ; - -when_clause - : KW_WHEN expression - ; - -case_switch_label - : KW_CASE expression OP_171 - ; - -default_switch_label - : KW_DEFAULT OP_171 - ; - -throw_statement - : attribute_list* KW_THROW expression? OP_172 - ; - -try_statement - : attribute_list* KW_TRY block catch_clause* finally_clause? - ; - -catch_clause - : KW_CATCH catch_declaration? catch_filter_clause? block - ; - -catch_declaration - : OP_163 type identifier_token? OP_164 - ; - -catch_filter_clause - : KW_WHEN OP_163 expression OP_164 - ; - -finally_clause - : KW_FINALLY block - ; - -unsafe_statement - : attribute_list* KW_UNSAFE block - ; - -using_statement - : attribute_list* KW_AWAIT? KW_USING OP_163 (variable_declaration | expression) OP_164 statement - ; - -while_statement - : attribute_list* KW_WHILE OP_163 expression OP_164 statement - ; - -yield_statement - : attribute_list* KW_YIELD (KW_RETURN | KW_BREAK) expression? OP_172 - ; - -expression - : anonymous_function_expression - | anonymous_object_creation_expression - | array_creation_expression - | assignment_expression - | await_expression - | base_object_creation_expression - | binary_expression - | cast_expression - | checked_expression - | collection_expression - | conditional_access_expression - | conditional_expression - | declaration_expression - | default_expression - | element_access_expression - | element_binding_expression - | field_expression - | implicit_array_creation_expression - | implicit_element_access - | implicit_stack_alloc_array_creation_expression - | initializer_expression - | instance_expression - | interpolated_string_expression - | invocation_expression - | is_pattern_expression - | literal_expression - | make_ref_expression - | member_access_expression - | member_binding_expression - | parenthesized_expression - | postfix_unary_expression - | prefix_unary_expression - | query_expression - | range_expression - | ref_expression - | ref_type_expression - | ref_value_expression - | size_of_expression - | stack_alloc_array_creation_expression - | switch_expression - | throw_expression - | tuple_expression - | type - | type_of_expression - | unsafe_expression - | with_expression - ; - -anonymous_function_expression - : anonymous_method_expression - | lambda_expression - ; - -anonymous_method_expression - : modifier* KW_DELEGATE parameter_list? block expression? - ; - -lambda_expression - : parenthesized_lambda_expression - | simple_lambda_expression - ; - -parenthesized_lambda_expression - : attribute_list* modifier* type? parameter_list OP_138 (block | expression) - ; - -simple_lambda_expression - : attribute_list* modifier* parameter OP_138 (block | expression) - ; - -anonymous_object_creation_expression - : KW_NEW OP_181 (anonymous_object_member_declarator (OP_167 anonymous_object_member_declarator)* OP_167?)? OP_183 - ; - -anonymous_object_member_declarator - : name_equals? expression - ; - -array_creation_expression - : KW_NEW array_type initializer_expression? - ; - -initializer_expression - : OP_181 (expression (OP_167 expression)* OP_167?)? OP_183 - ; - -assignment_expression - : expression (OP_174 | OP_126 | OP_128 | OP_124 | OP_131 | OP_121 | OP_123 | OP_145 | OP_155 | OP_103 | OP_104 | OP_078 | OP_106) expression - ; - -await_expression - : KW_AWAIT expression - ; - -base_object_creation_expression - : implicit_object_creation_expression - | object_creation_expression - ; - -implicit_object_creation_expression - : KW_NEW argument_list initializer_expression? - ; - -object_creation_expression - : KW_NEW type argument_list? initializer_expression? - ; - -binary_expression - : expression (OP_166 | OP_168 | OP_165 | OP_170 | OP_161 | OP_135 | OP_140 | OP_105 | OP_156 | OP_122 | OP_182 | OP_162 | OP_179 | OP_137 | OP_120 | OP_173 | OP_136 | OP_175 | OP_139 | KW_IS | KW_AS | OP_141) expression - ; - -cast_expression - : OP_163 type OP_164 expression - ; - -checked_expression - : KW_CHECKED OP_163 expression OP_164 - | KW_UNCHECKED OP_163 expression OP_164 - ; - -collection_expression - : OP_177 (collection_element (OP_167 collection_element)* OP_167?)? OP_178 - ; - -collection_element - : expression_element - | spread_element - | with_element - ; - -expression_element - : expression - ; - -spread_element - : OP_130 expression - ; - -with_element - : KW_WITH argument_list - ; - -conditional_access_expression - : expression OP_176 expression - ; - -conditional_expression - : expression OP_176 expression OP_171 expression - ; - -declaration_expression - : type variable_designation - ; - -default_expression - : KW_DEFAULT OP_163 type OP_164 - ; - -element_access_expression - : expression bracketed_argument_list - ; - -element_binding_expression - : bracketed_argument_list - ; - -field_expression - : KW_FIELD - ; - -implicit_array_creation_expression - : KW_NEW OP_177 OP_167* OP_178 initializer_expression - ; - -implicit_element_access - : bracketed_argument_list - ; - -implicit_stack_alloc_array_creation_expression - : KW_STACKALLOC OP_177 OP_178 initializer_expression - ; - -instance_expression - : base_expression - | this_expression - ; - -base_expression - : KW_BASE - ; - -this_expression - : KW_THIS - ; - -interpolated_string_expression - : INTERP_START interpolated_string_content* OP_158 - | INTERP_VERBATIM_START interpolated_string_content* OP_158 - | interpolated_multi_line_raw_string_start_token interpolated_string_content* interpolated_raw_string_end_token - | interpolated_single_line_raw_string_start_token interpolated_string_content* interpolated_raw_string_end_token - ; - -interpolated_string_content - : interpolated_string_text - | interpolation - ; - -interpolated_string_text - : interpolated_string_text_token - ; - -interpolation - : OP_181 expression interpolation_alignment_clause? interpolation_format_clause? OP_183 - ; - -interpolation_alignment_clause - : OP_167 expression - ; - -interpolation_format_clause - : OP_171 interpolated_string_text_token - ; - -interpolated_multi_line_raw_string_start_token - : OP_160+ OP_102 OP_158* - ; - -interpolated_raw_string_end_token - : OP_102 OP_158* /* must match number of quotes in raw_string_start_token */ - ; - -interpolated_single_line_raw_string_start_token - : OP_160+ OP_102 OP_158* - ; - -invocation_expression - : expression argument_list - ; - -is_pattern_expression - : expression KW_IS pattern - ; - -literal_expression - : KW_DEFAULT - | KW_FALSE - | KW_NULL - | KW_TRUE - | KW___ARGLIST - | character_literal_token - | multi_line_raw_string_literal_token - | numeric_literal_token - | single_line_raw_string_literal_token - | string_literal_token - | utf8_multi_line_raw_string_literal_token - | utf8_single_line_raw_string_literal_token - | utf8_string_literal_token - ; - -utf8_multi_line_raw_string_literal_token - : multi_line_raw_string_literal_token (KW_U8 | KW_U8_154) - ; - -utf8_single_line_raw_string_literal_token - : single_line_raw_string_literal_token (KW_U8 | KW_U8_154) - ; - -utf8_string_literal_token - : string_literal_token (KW_U8 | KW_U8_154) - ; - -make_ref_expression - : KW___MAKEREF OP_163 expression OP_164 - ; - -member_access_expression - : expression (OP_169 | OP_129) simple_name - ; - -member_binding_expression - : OP_169 simple_name - ; - -parenthesized_expression - : OP_163 expression OP_164 - ; - -postfix_unary_expression - : expression (OP_125 | OP_127 | OP_157) - ; - -prefix_unary_expression - : OP_157 expression - | OP_162 expression - | OP_165 expression - | OP_166 expression - | OP_125 expression - | OP_168 expression - | OP_127 expression - | OP_179 expression - | OP_184 expression - ; - -query_expression - : from_clause query_body - ; - -from_clause - : KW_FROM type? identifier_token KW_IN expression - ; - -query_body - : query_clause+ select_or_group_clause query_continuation? - ; - -query_clause - : from_clause - | join_clause - | let_clause - | order_by_clause - | where_clause - ; - -join_clause - : KW_JOIN type? identifier_token KW_IN expression KW_ON expression KW_EQUALS expression join_into_clause? - ; - -join_into_clause - : KW_INTO identifier_token - ; - -let_clause - : KW_LET identifier_token OP_174 expression - ; - -order_by_clause - : KW_ORDERBY ordering (OP_167 ordering)* - ; - -ordering - : expression (KW_ASCENDING | KW_DESCENDING)? - ; - -where_clause - : KW_WHERE expression - ; - -select_or_group_clause - : group_clause - | select_clause - ; - -group_clause - : KW_GROUP expression KW_BY expression - ; - -select_clause - : KW_SELECT expression - ; - -query_continuation - : KW_INTO identifier_token query_body - ; - -range_expression - : expression? OP_130 expression? - ; - -ref_expression - : KW_REF expression - ; - -ref_type_expression - : KW___REFTYPE OP_163 expression OP_164 - ; - -ref_value_expression - : KW___REFVALUE OP_163 expression OP_167 type OP_164 - ; - -size_of_expression - : KW_SIZEOF OP_163 type OP_164 - ; - -stack_alloc_array_creation_expression - : KW_STACKALLOC type initializer_expression? - ; - -switch_expression - : expression KW_SWITCH OP_181 (switch_expression_arm (OP_167 switch_expression_arm)* OP_167?)? OP_183 - ; - -switch_expression_arm - : pattern when_clause? OP_138 expression - ; - -throw_expression - : KW_THROW expression - ; - -tuple_expression - : OP_163 argument (OP_167 argument)+ OP_164 - ; - -type_of_expression - : KW_TYPEOF OP_163 type OP_164 - ; - -unsafe_expression - : KW_UNSAFE OP_163 expression OP_164 - ; - -with_expression - : expression KW_WITH initializer_expression - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -syntax_token - : character_literal_token - | identifier_token - | keyword - | numeric_literal_token - | operator_token - | punctuation_token - | string_literal_token - ; - -identifier_token - : IDENTIFIER - ; - - - - - - - - - -keyword - : KW_AS - | KW_BASE - | KW_BOOL - | KW_BREAK - | KW_BYTE - | KW_CASE - | KW_CATCH - | KW_CHAR - | KW_CHECKED - | KW_CLASS - | KW_CONTINUE - | KW_DECIMAL - | KW_DEFAULT - | KW_DELEGATE - | KW_DO - | KW_DOUBLE - | KW_ELSE - | KW_ENUM - | KW_EVENT - | KW_EXPLICIT - | KW_FALSE - | KW_FINALLY - | KW_FLOAT - | KW_FOR - | KW_FOREACH - | KW_GOTO - | KW_IF - | KW_IMPLICIT - | KW_IN - | KW_INT - | KW_INTERFACE - | KW_IS - | KW_LOCK - | KW_LONG - | KW_NAMESPACE - | KW_NULL - | KW_OBJECT - | KW_OPERATOR - | KW_OUT - | KW_PARAMS - | KW_RETURN - | KW_SBYTE - | KW_SHORT - | KW_SIZEOF - | KW_STACKALLOC - | KW_STRING - | KW_STRUCT - | KW_SWITCH - | KW_THIS - | KW_THROW - | KW_TRUE - | KW_TRY - | KW_TYPEOF - | KW_UINT - | KW_ULONG - | KW_UNCHECKED - | KW_USHORT - | KW_USING - | KW_VOID - | KW_WHILE - | KW___ARGLIST - | KW___MAKEREF - | KW___REFTYPE - | KW___REFVALUE - | modifier - ; - -numeric_literal_token - : integer_literal_token - | real_literal_token - ; - -integer_literal_token - : decimal_integer_literal_token - | hexadecimal_integer_literal_token - ; - -decimal_integer_literal_token - : DEC_INT_LIT - ; - - - -hexadecimal_integer_literal_token - : HEX_INT_LIT - ; - - -real_literal_token - : REAL_LIT - ; - - - -character_literal_token - : CHAR_LIT - ; - - - - - - -string_literal_token - : regular_string_literal_token - | verbatim_string_literal_token - ; - -regular_string_literal_token - : STRING_LIT - ; - - - -verbatim_string_literal_token - : VERBATIM_STRING_LIT - ; - - - - -operator_token - : OP_157 - | OP_120 - | OP_161 - | OP_121 - | OP_122 - | OP_162 - | OP_123 - | OP_165 - | OP_124 - | OP_166 - | OP_125 - | OP_126 - | OP_168 - | OP_127 - | OP_128 - | OP_170 - | OP_131 - | OP_173 - | OP_135 - | OP_103 - | OP_136 - | OP_174 - | OP_137 - | OP_175 - | OP_139 - | OP_140 - | OP_104 - | OP_105 - | OP_078 - | OP_141 - | OP_106 - | KW_AS - | KW_IS - | OP_179 - | OP_145 - | OP_182 - | OP_155 - | OP_156 - | OP_184 - ; - -punctuation_token - : OP_158 - | OP_159 - | OP_163 - | OP_164 - | OP_167 - | OP_129 - | OP_169 - | OP_130 - | OP_132 - | OP_171 - | OP_133 - | OP_172 - | OP_134 - | OP_138 - | OP_176 - | OP_177 - | OP_143 - | OP_144 - | OP_178 - | OP_181 - | OP_183 - ; - - - - - - -interpolated_string_text_token - : INTERPOLATED_TEXT - ; - -multi_line_raw_string_literal_token - : ML_RAW_STRING_LIT - ; - -single_line_raw_string_literal_token - : SL_RAW_STRING_LIT - ; - - - -// Contextual keyword: `record` lexes as an ordinary IDENTIFIER (it is legal as a -// name), so the declaration position is restricted by a predicate on the token -// text. This restores Roslyn's , which its -// grammar generator drops. Lowered by `patterns.toml` to a pure SemIR -// comparison, so no hooks are needed. -record_keyword - : {this.IsRecordKeyword()}? identifier_token - ; diff --git a/repro/roslyn-csharp-perf/grammar/patterns.toml b/repro/roslyn-csharp-perf/grammar/patterns.toml deleted file mode 100644 index 5fd78459..00000000 --- a/repro/roslyn-csharp-perf/grammar/patterns.toml +++ /dev/null @@ -1,16 +0,0 @@ -version = 1 - -# `record` is a contextual keyword. Roslyn declares -# `` on -# RecordDeclarationSyntax.Keyword, but its grammar generator reads only -# ``, so the published grammar spells the keyword as the catch-all -# `syntax_token` — which makes `class` viable as a record declaration and -# costs ~quadratic prediction time per type member. `prepare-roslyn-grammar.py` -# restores the restriction as a text comparison on the lookahead token; it -# lowers to a pure SemIR expression, so no typed hook is needed. - -[[helper]] -kind = "parser-predicate" -name = "IsRecordKeyword" -returns = "bool" -lower = "cmp(eq, token_text(1), str(\"record\"))" diff --git a/repro/roslyn-csharp-perf/grammar/unnarrowed-record/CSharpLexer.g4 b/repro/roslyn-csharp-perf/grammar/unnarrowed-record/CSharpLexer.g4 deleted file mode 100644 index c159b78c..00000000 --- a/repro/roslyn-csharp-perf/grammar/unnarrowed-record/CSharpLexer.g4 +++ /dev/null @@ -1,359 +0,0 @@ -// @generated from Roslyn's CSharp.Generated.g4 by prepare-roslyn-grammar.py — do not hand-edit. -// Roslyn publishes a parser-only grammar; this lexer supplies the -// terminals it references. Literal tokens below are harvested from the -// parser's inline literals; the rest is spliced from `lexer-tokens.g4.in`. -// See PROVENANCE.md. -lexer grammar CSharpLexer; - -channels { COMMENTS_CHANNEL, DIRECTIVE } - -// Emitted only from their lexer modes, but referenced by the parser, -// so they must be declared up front. -tokens { INTERPOLATED_TEXT, XML_TEXT_LIT } - -// ---- keywords, operators, punctuation (must precede IDENTIFIER) ---- -KW___REFVALUE : '__refvalue' ; -KW_DESCENDING : 'descending' ; -KW_STACKALLOC : 'stackalloc' ; -KW___ARGLIST : '__arglist' ; -KW___MAKEREF : '__makeref' ; -KW___REFTYPE : '__reftype' ; -KW_ASCENDING : 'ascending' ; -KW_EXTENSION : 'extension' ; -KW_INTERFACE : 'interface' ; -KW_NAMESPACE : 'namespace' ; -KW_PROTECTED : 'protected' ; -KW_UNCHECKED : 'unchecked' ; -KW_UNMANAGED : 'unmanaged' ; -KW_ABSTRACT : 'abstract' ; -KW_CONTINUE : 'continue' ; -KW_DELEGATE : 'delegate' ; -KW_EXPLICIT : 'explicit' ; -KW_IMPLICIT : 'implicit' ; -KW_INTERNAL : 'internal' ; -KW_OPERATOR : 'operator' ; -KW_OVERRIDE : 'override' ; -KW_READONLY : 'readonly' ; -KW_REQUIRED : 'required' ; -KW_VOLATILE : 'volatile' ; -KW_CHECKED : 'checked' ; -KW_DECIMAL : 'decimal' ; -KW_DEFAULT : 'default' ; -KW_FINALLY : 'finally' ; -KW_FOREACH : 'foreach' ; -KW_MANAGED : 'managed' ; -KW_ORDERBY : 'orderby' ; -KW_PARTIAL : 'partial' ; -KW_PRIVATE : 'private' ; -KW_VIRTUAL : 'virtual' ; -KW_ALLOWS : 'allows' ; -KW_CLOSED : 'closed' ; -KW_DOUBLE : 'double' ; -KW_EQUALS : 'equals' ; -KW_EXTERN : 'extern' ; -KW_GLOBAL : 'global' ; -KW_OBJECT : 'object' ; -KW_PARAMS : 'params' ; -KW_PUBLIC : 'public' ; -KW_REMOVE : 'remove' ; -KW_RETURN : 'return' ; -KW_SCOPED : 'scoped' ; -KW_SEALED : 'sealed' ; -KW_SELECT : 'select' ; -KW_SIZEOF : 'sizeof' ; -KW_STATIC : 'static' ; -KW_STRING : 'string' ; -KW_STRUCT : 'struct' ; -KW_SWITCH : 'switch' ; -KW_TYPEOF : 'typeof' ; -KW_UNSAFE : 'unsafe' ; -KW_USHORT : 'ushort' ; -KW_ALIAS : 'alias' ; -KW_ASYNC : 'async' ; -KW_AWAIT : 'await' ; -KW_BREAK : 'break' ; -KW_CATCH : 'catch' ; -KW_CLASS : 'class' ; -KW_CONST : 'const' ; -KW_EVENT : 'event' ; -KW_FALSE : 'false' ; -KW_FIELD : 'field' ; -KW_FIXED : 'fixed' ; -KW_FLOAT : 'float' ; -KW_GROUP : 'group' ; -KW_SBYTE : 'sbyte' ; -KW_SHORT : 'short' ; -KW_THROW : 'throw' ; -KW_ULONG : 'ulong' ; -KW_UNION : 'union' ; -KW_USING : 'using' ; -KW_WHERE : 'where' ; -KW_WHILE : 'while' ; -KW_YIELD : 'yield' ; -OP_078 : '>>>=' ; -KW_BASE : 'base' ; -KW_BOOL : 'bool' ; -KW_BYTE : 'byte' ; -KW_CASE : 'case' ; -KW_CHAR : 'char' ; -KW_ELSE : 'else' ; -KW_ENUM : 'enum' ; -KW_FILE : 'file' ; -KW_FROM : 'from' ; -KW_GOTO : 'goto' ; -KW_INIT : 'init' ; -KW_INTO : 'into' ; -KW_JOIN : 'join' ; -KW_LOCK : 'lock' ; -KW_LONG : 'long' ; -KW_NULL : 'null' ; -KW_SAFE : 'safe' ; -KW_THIS : 'this' ; -KW_TRUE : 'true' ; -KW_UINT : 'uint' ; -KW_VOID : 'void' ; -KW_WHEN : 'when' ; -KW_WITH : 'with' ; -OP_102 : '"""' ; -OP_103 : '<<=' ; -OP_104 : '>>=' ; -OP_105 : '>>>' ; -OP_106 : '??=' ; -KW_ADD : 'add' ; -KW_AND : 'and' ; -KW_FOR : 'for' ; -KW_GET : 'get' ; -KW_INT : 'int' ; -KW_LET : 'let' ; -KW_NEW : 'new' ; -KW_NOT : 'not' ; -KW_OUT : 'out' ; -KW_REF : 'ref' ; -KW_SET : 'set' ; -KW_TRY : 'try' ; -KW_VAR : 'var' ; -OP_120 : '!=' ; -OP_121 : '%=' ; -OP_122 : '&&' ; -OP_123 : '&=' ; -OP_124 : '*=' ; -OP_125 : '++' ; -OP_126 : '+=' ; -OP_127 : '--' ; -OP_128 : '-=' ; -OP_129 : '->' ; -OP_130 : '..' ; -OP_131 : '/=' ; -OP_132 : '/>' ; -OP_133 : '::' ; -OP_134 : '' ; -OP_139 : '>=' ; -OP_140 : '>>' ; -OP_141 : '??' ; -KW_U8 : 'U8' ; -OP_143 : '\'' ; -OP_144 : '\\' ; -OP_145 : '^=' ; -KW_AS : 'as' ; -KW_BY : 'by' ; -KW_DO : 'do' ; -KW_IF : 'if' ; -KW_IN : 'in' ; -KW_IS : 'is' ; -KW_ON : 'on' ; -KW_OR : 'or' ; -KW_U8_154 : 'u8' ; -OP_155 : '|=' ; -OP_156 : '||' ; -OP_157 : '!' ; -OP_158 : '"' ; -OP_159 : '#' ; -OP_160 : '$' ; -OP_161 : '%' ; -OP_162 : '&' ; -OP_163 : '(' ; -OP_164 : ')' ; -OP_165 : '*' ; -OP_166 : '+' ; -OP_167 : ',' ; -OP_168 : '-' ; -OP_169 : '.' ; -OP_170 : '/' ; -OP_171 : ':' ; -OP_172 : ';' ; -OP_173 : '<' ; -OP_174 : '=' ; -OP_175 : '>' ; -OP_176 : '?' ; -OP_177 : '[' ; -OP_178 : ']' ; -OP_179 : '^' ; -KW__ : '_' ; -OP_181 : '{' ; -OP_182 : '|' ; -OP_183 : '}' ; -OP_184 : '~' ; - -// Lexer rules supplied for Roslyn's parser-only C# grammar, spliced verbatim -// into the generated `CSharpLexer.g4` by `prepare-roslyn-grammar.py`. -// -// Roslyn's `CSharp.Generated.g4` describes its terminals as character-level -// *parser* rules (`identifier_token : '@'? identifier_start_character …`, -// `decimal_digit : '0' | '1' | …`). Those cannot stay in the parser: single -// character tokens would shadow multi-character ones, so `'C'` beats -// `IDENTIFIER` and `'1'` beats a decimal literal. Each rule below replaces one -// such Roslyn rule, following the C# lexical grammar (ECMA-334 §6.4). -// -// This file is hand-written ANTLR (not generated), kept separate from the -// script so the ANTLR-level escaping is readable and reviewable as grammar -// source rather than as nested Python string escapes. -// -// The `TOKEN <-> roslyn_rule` mapping is declared in the script's -// LEXER_TOKEN_RULES table; adding a rule here requires adding it there too. - -// §6.4.3 Identifiers. `@` is the verbatim-identifier prefix; the character -// classes follow identifier_start_character / identifier_part_character. -IDENTIFIER - : '@'? [\p{L}\p{Nl}_] [\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]* - ; - -// §6.4.5.3 Integer literals. Two suffix slots cover `ul` / `lu`. -DEC_INT_LIT - : [0-9] [0-9_]* [uUlL]? [uUlL]? - ; - -HEX_INT_LIT - : '0' [xX] [0-9a-fA-F_]+ [uUlL]? [uUlL]? - ; - -BIN_INT_LIT - : '0' [bB] [01_]+ [uUlL]? [uUlL]? - ; - -// §6.4.5.5 Real literals — embedded dot, leading dot, exponent-only, and -// suffix-only forms. -REAL_LIT - : [0-9] [0-9_]* '.' [0-9] [0-9_]* ExponentPart? [fFdDmM]? - | '.' [0-9] [0-9_]* ExponentPart? [fFdDmM]? - | [0-9] [0-9_]* ExponentPart [fFdDmM]? - | [0-9] [0-9_]* [fFdDmM] - ; - -fragment ExponentPart - : [eE] [+-]? [0-9] [0-9_]* - ; - -// §6.4.5.6 Character literals. -CHAR_LIT - : '\'' ( '\\' . | ~['\\\r\n] ) '\'' - ; - -// §6.4.5.7 String literals. -STRING_LIT - : '"' ( '\\' . | ~["\\\r\n] )* '"' - ; - -VERBATIM_STRING_LIT - : '@"' ( '""' | ~'"' )* '"' - ; - -// C# 11 raw string literals. The real rule requires the closing fence to be at -// least as long as the opening one, which a context-free lexer rule cannot -// express; a non-greedy match is sufficient here because every metric that -// touches a string literal (LOC rows, Halstead operand) only needs the token's -// extent, not its internal structure. -ML_RAW_STRING_LIT - : '"""' '"'* .*? '"""' '"'* - ; - -SL_RAW_STRING_LIT - : '""' ~[\r\n]*? '""' - ; - -// ---- trivia ------------------------------------------------------------- -// Comments go to a dedicated channel so the CLOC sweep can read them while the -// parser never sees them. Roslyn models trivia as syntax, so its grammar has no -// rules for these at all. -SINGLE_LINE_DOC_COMMENT : '///' ~[\r\n]* -> channel(COMMENTS_CHANNEL) ; -DELIMITED_DOC_COMMENT : '/**' .*? '*/' -> channel(COMMENTS_CHANNEL) ; -SINGLE_LINE_COMMENT : '//' ~[\r\n]* -> channel(COMMENTS_CHANNEL) ; -DELIMITED_COMMENT : '/*' .*? '*/' -> channel(COMMENTS_CHANNEL) ; -WHITESPACES : [ \t\r\n\f]+ -> channel(HIDDEN) ; -BYTE_ORDER_MARK : '' -> skip ; - -// A preprocessor directive line. mehen does not evaluate `#if` (unlike the -// grammars-v4 lexer's `CSharpLexerBase`, which needs a stateful hook for it); -// directives are routed to their own channel so they are neither code nor -// comment for LOC, and inactive regions are still parsed as ordinary code. -DIRECTIVE_LINE : '#' ~[\r\n]* -> channel(DIRECTIVE) ; - -// ---- interpolated strings ---------------------------------------------- -// Roslyn spells interpolated strings as -// -// interpolated_string_expression -// : '$"' interpolated_string_content* '"' -// | '$@"' interpolated_string_content* '"' ; -// interpolation : '{' expression … '}' ; -// -// The *text* between holes needs its own lexer mode: in the default mode a -// broad negated set would swallow ordinary code (an earlier flat-lexer attempt -// lexed `class C ` as one token that way). -// -// NOTE: in this frozen snapshot these modes are never entered at all — `$"` is -// harvested as an ordinary literal, so nothing pushes INTERPOLATION. The rules -// below are inert. (The live grammar under `crates/mehen-csharp-parser/` rewrites -// those literals to mode-pushing tokens and does parse interpolated strings; see -// that crate's `grammar/lexer-tokens.g4.in`. This directory is deliberately not -// resynced — it reproduces one timing issue and no fixture uses `$"`.) -// -// The comment below described a design that no longer exists: there is no -// `../src/hooks.rs`, and the live grammar drives every transition from grammar -// commands with the brace depth held in `@lexer::members`. It is kept because the -// *problem* it states is the real one: the `}` that closes a hole is lexically -// identical to the one closing a nested block — -// -// $"a{ new[]{ 1, 2 }.Length }b" -// ^^^^^^^^^ must NOT end the hole -// -// so it needs a brace depth per open hole and a *conditional* pop. Keeping the -// grammar free of mode commands also keeps the two halves from fighting over -// the mode stack. See `CSharpLexerHooks` for the state machine. -// -// `prepare-roslyn-grammar.py` rewrites the harvested `'$"'` / `'$@"'` literals -// to the named tokens below (INTERP_TOKEN_LITERALS) so the hook can recognize -// them by a stable name. -INTERP_START : '$"' ; -INTERP_VERBATIM_START : '$@"' ; - -mode INTERPOLATION; - -// `{{` / `}}` are escaped literal braces, not holes — first so they win the -// longest match over the single-brace rules below. -INTERP_ESCAPED_OPEN : '{{' -> type(INTERPOLATED_TEXT) ; -INTERP_ESCAPED_CLOSE : '}}' -> type(INTERPOLATED_TEXT) ; - -// Text between holes. -INTERPOLATED_TEXT : ~[{}"\\]+ ; - -// A hole opens / the string ends. Both emit the token type the parser expects -// (`{` and `"` respectively); the hook performs the mode change. -INTERP_HOLE_OPEN : '{' -> type(OP_181) ; -INTERP_END : '"' -> type(OP_158) ; - -// A format specifier (`{x:D4}`) is a third mode: after the `:` that ends a -// hole's expression, the remaining text up to the closing `}` is literal format -// text, not C# code — `D4` must not lex as an identifier. (The grammars-v4 C# -// lexer has an INTERPOLATION_FORMAT mode for the same reason.) The hook enters -// this mode on a `:` seen at brace depth 0 inside a hole. -mode INTERPOLATION_FORMAT; - -// The format text, emitted as the same token the grammar's -// `interpolation_format_clause : ':' interpolated_string_text_token` expects. -INTERP_FORMAT_TEXT : ~[}"]+ -> type(INTERPOLATED_TEXT) ; - -// The `}` that closes the hole; the hook restores the interpolation mode. -INTERP_FORMAT_END : '}' -> type(OP_183) ; diff --git a/repro/roslyn-csharp-perf/grammar/unnarrowed-record/CSharpParser.g4 b/repro/roslyn-csharp-perf/grammar/unnarrowed-record/CSharpParser.g4 deleted file mode 100644 index 8725a1c1..00000000 --- a/repro/roslyn-csharp-perf/grammar/unnarrowed-record/CSharpParser.g4 +++ /dev/null @@ -1,1458 +0,0 @@ -// @generated from Roslyn's CSharp.Generated.g4 by prepare-roslyn-grammar.py — do not hand-edit. -// See PROVENANCE.md for the pinned upstream revision and the patch rationale. -parser grammar CSharpParser; - -options { tokenVocab=CSharpLexer; } - -compilation_unit - : extern_alias_directive* using_directive* attribute_list* member_declaration* - ; - -extern_alias_directive - : KW_EXTERN KW_ALIAS identifier_token OP_172 - ; - -using_directive - : KW_GLOBAL? KW_USING (KW_STATIC | (KW_UNSAFE? name_equals))? type OP_172 - ; - -name_equals - : identifier_name OP_174 - ; - -identifier_name - : KW_GLOBAL - | identifier_token - ; - -attribute_list - : OP_177 attribute_target_specifier? attribute (OP_167 attribute)* OP_178 - ; - -attribute_target_specifier - : syntax_token OP_171 - ; - -attribute - : name attribute_argument_list? - ; - -name - : alias_qualified_name - | qualified_name - | simple_name - ; - -alias_qualified_name - : identifier_name OP_133 simple_name - ; - -simple_name - : generic_name - | identifier_name - ; - -generic_name - : identifier_token type_argument_list - ; - -type_argument_list - : OP_173 (type? (OP_167 type?)*)? OP_175 - ; - -qualified_name - : name OP_169 simple_name - ; - -attribute_argument_list - : OP_163 (attribute_argument (OP_167 attribute_argument)*)? OP_164 - ; - -attribute_argument - : (name_equals? | name_colon?) expression - ; - -name_colon - : identifier_name OP_171 - ; - -member_declaration - : base_field_declaration - | base_method_declaration - | base_namespace_declaration - | base_property_declaration - | base_type_declaration - | delegate_declaration - | enum_member_declaration - | global_statement - | incomplete_member - ; - -base_field_declaration - : event_field_declaration - | field_declaration - ; - -event_field_declaration - : attribute_list* modifier* KW_EVENT variable_declaration OP_172 - ; - -modifier - : KW_ABSTRACT - | KW_ASYNC - | KW_CLOSED - | KW_CONST - | KW_EXTERN - | KW_FILE - | KW_FIXED - | KW_INTERNAL - | KW_NEW - | KW_OVERRIDE - | KW_PARTIAL - | KW_PRIVATE - | KW_PROTECTED - | KW_PUBLIC - | KW_READONLY - | KW_REF - | KW_REQUIRED - | KW_SAFE - | KW_SCOPED - | KW_SEALED - | KW_STATIC - | KW_UNSAFE - | KW_VIRTUAL - | KW_VOLATILE - ; - -variable_declaration - : type variable_declarator (OP_167 variable_declarator)* - ; - -variable_declarator - : identifier_token bracketed_argument_list? equals_value_clause? - ; - -bracketed_argument_list - : OP_177 argument (OP_167 argument)* OP_178 - ; - -argument - : name_colon? (KW_REF | KW_OUT | KW_IN)? expression - ; - -equals_value_clause - : OP_174 expression - ; - -field_declaration - : attribute_list* modifier* variable_declaration OP_172 - ; - -base_method_declaration - : constructor_declaration - | conversion_operator_declaration - | destructor_declaration - | method_declaration - | operator_declaration - ; - -constructor_declaration - : attribute_list* modifier* identifier_token parameter_list constructor_initializer? (block | (arrow_expression_clause OP_172)) - ; - -parameter_list - : OP_163 (parameter (OP_167 parameter)*)? OP_164 - ; - -parameter - : attribute_list* modifier* type? (identifier_token | KW___ARGLIST)? equals_value_clause? - ; - -constructor_initializer - : OP_171 (KW_BASE | KW_THIS) argument_list - ; - -argument_list - : OP_163 (argument (OP_167 argument)*)? OP_164 - ; - -block - : attribute_list* OP_181 statement* OP_183 - ; - -arrow_expression_clause - : OP_138 expression - ; - -conversion_operator_declaration - : attribute_list* modifier* (KW_IMPLICIT | KW_EXPLICIT) explicit_interface_specifier? KW_OPERATOR KW_CHECKED? type parameter_list (block | (arrow_expression_clause OP_172)) - ; - -explicit_interface_specifier - : name OP_169 - ; - -destructor_declaration - : attribute_list* modifier* OP_184 identifier_token parameter_list (block | (arrow_expression_clause OP_172)) - ; - -method_declaration - : attribute_list* modifier* type explicit_interface_specifier? identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* (block | (arrow_expression_clause OP_172)) - ; - -type_parameter_list - : OP_173 type_parameter (OP_167 type_parameter)* OP_175 - ; - -type_parameter - : attribute_list* (KW_IN | KW_OUT)? identifier_token - ; - -type_parameter_constraint_clause - : KW_WHERE identifier_name OP_171 type_parameter_constraint (OP_167 type_parameter_constraint)* - ; - -type_parameter_constraint - : allows_constraint_clause - | class_or_struct_constraint - | constructor_constraint - | default_constraint - | type_constraint - ; - -allows_constraint_clause - : KW_ALLOWS allows_constraint (OP_167 allows_constraint)* - ; - -allows_constraint - : ref_struct_constraint - ; - -ref_struct_constraint - : KW_REF KW_STRUCT - ; - -class_or_struct_constraint - : KW_CLASS OP_176? - | KW_STRUCT OP_176? - ; - -constructor_constraint - : KW_NEW OP_163 OP_164 - ; - -default_constraint - : KW_DEFAULT - ; - -type_constraint - : type - ; - -operator_declaration - : attribute_list* modifier* type explicit_interface_specifier? KW_OPERATOR KW_CHECKED? (OP_166 | OP_168 | OP_157 | OP_184 | OP_125 | OP_127 | OP_165 | OP_170 | OP_161 | OP_135 | OP_140 | OP_105 | OP_182 | OP_162 | OP_179 | OP_137 | OP_120 | OP_173 | OP_136 | OP_175 | OP_139 | KW_FALSE | KW_TRUE | KW_IS | OP_126 | OP_128 | OP_124 | OP_131 | OP_121 | OP_123 | OP_155 | OP_145 | OP_103 | OP_104 | OP_078) parameter_list (block | (arrow_expression_clause OP_172)) - ; - -base_namespace_declaration - : file_scoped_namespace_declaration - | namespace_declaration - ; - -file_scoped_namespace_declaration - : attribute_list* modifier* KW_NAMESPACE name OP_172 extern_alias_directive* using_directive* member_declaration* - ; - -namespace_declaration - : attribute_list* modifier* KW_NAMESPACE name OP_181 extern_alias_directive* using_directive* member_declaration* OP_183 OP_172? - ; - -base_property_declaration - : event_declaration - | indexer_declaration - | property_declaration - ; - -event_declaration - : attribute_list* modifier* KW_EVENT type explicit_interface_specifier? identifier_token (accessor_list | OP_172) - ; - -accessor_list - : OP_181 accessor_declaration* OP_183 - ; - -accessor_declaration - : attribute_list* modifier* (KW_GET | KW_SET | KW_INIT | KW_ADD | KW_REMOVE | identifier_token) (block | (arrow_expression_clause OP_172)) - ; - -indexer_declaration - : attribute_list* modifier* type explicit_interface_specifier? KW_THIS bracketed_parameter_list (accessor_list | (arrow_expression_clause OP_172)) - ; - -bracketed_parameter_list - : OP_177 parameter (OP_167 parameter)* OP_178 - ; - -property_declaration - : attribute_list* modifier* type explicit_interface_specifier? identifier_token (accessor_list | ((arrow_expression_clause | equals_value_clause) OP_172)) - ; - -base_type_declaration - : enum_declaration - | type_declaration - ; - -enum_declaration - : attribute_list* modifier* KW_ENUM identifier_token base_list? OP_181? (enum_member_declaration (OP_167 enum_member_declaration)* OP_167?)? OP_183? OP_172? - ; - -base_list - : OP_171 base_type (OP_167 base_type)* - ; - -base_type - : primary_constructor_base_type - | simple_base_type - ; - -primary_constructor_base_type - : type argument_list - ; - -simple_base_type - : type - ; - -enum_member_declaration - : attribute_list* modifier* identifier_token equals_value_clause? - ; - -type_declaration - : class_declaration - | extension_block_declaration - | interface_declaration - | record_declaration - | struct_declaration - | union_declaration - ; - -class_declaration - : attribute_list* modifier* KW_CLASS identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -extension_block_declaration - : attribute_list* modifier* KW_EXTENSION type_parameter_list? parameter_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -interface_declaration - : attribute_list* modifier* KW_INTERFACE identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -record_declaration - : attribute_list* modifier* syntax_token (KW_CLASS | KW_STRUCT)? identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -struct_declaration - : attribute_list* modifier* KW_STRUCT identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -union_declaration - : attribute_list* modifier* KW_UNION identifier_token type_parameter_list? parameter_list? base_list? type_parameter_constraint_clause* OP_181? member_declaration* OP_183? OP_172? - ; - -delegate_declaration - : attribute_list* modifier* KW_DELEGATE type identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* OP_172 - ; - -global_statement - : attribute_list* modifier* statement - ; - -incomplete_member - : attribute_list* modifier* type - ; - -type - : array_type - | function_pointer_type - | name - | nullable_type - | pointer_type - | predefined_type - | ref_type - | scoped_type - | tuple_type - ; - -array_type - : type array_rank_specifier+ - ; - -array_rank_specifier - : OP_177 (expression? (OP_167 expression?)*)? OP_178 - ; - -function_pointer_type - : KW_DELEGATE OP_165 function_pointer_calling_convention? function_pointer_parameter_list - ; - -function_pointer_calling_convention - : KW_MANAGED function_pointer_unmanaged_calling_convention_list? - | KW_UNMANAGED function_pointer_unmanaged_calling_convention_list? - ; - -function_pointer_unmanaged_calling_convention_list - : OP_177 function_pointer_unmanaged_calling_convention (OP_167 function_pointer_unmanaged_calling_convention)* OP_178 - ; - -function_pointer_unmanaged_calling_convention - : identifier_token - ; - -function_pointer_parameter_list - : OP_173 function_pointer_parameter (OP_167 function_pointer_parameter)* OP_175 - ; - -function_pointer_parameter - : attribute_list* modifier* type - ; - -nullable_type - : type OP_176 - ; - -pointer_type - : type OP_165 - ; - -predefined_type - : KW_BOOL - | KW_BYTE - | KW_CHAR - | KW_DECIMAL - | KW_DOUBLE - | KW_FLOAT - | KW_INT - | KW_LONG - | KW_OBJECT - | KW_SBYTE - | KW_SHORT - | KW_STRING - | KW_UINT - | KW_ULONG - | KW_USHORT - | KW_VOID - ; - -ref_type - : KW_REF KW_READONLY? type - ; - -scoped_type - : KW_SCOPED type - ; - -tuple_type - : OP_163 tuple_element (OP_167 tuple_element)+ OP_164 - ; - -tuple_element - : type identifier_token? - ; - -statement - : block - | break_statement - | checked_statement - | common_for_each_statement - | continue_statement - | do_statement - | empty_statement - | expression_statement - | fixed_statement - | for_statement - | goto_statement - | if_statement - | labeled_statement - | local_declaration_statement - | local_function_statement - | lock_statement - | return_statement - | switch_statement - | throw_statement - | try_statement - | unsafe_statement - | using_statement - | while_statement - | yield_statement - ; - -break_statement - : attribute_list* KW_BREAK identifier_name? OP_172 - ; - -checked_statement - : attribute_list* (KW_CHECKED | KW_UNCHECKED) block - ; - -common_for_each_statement - : for_each_statement - | for_each_variable_statement - ; - -for_each_statement - : attribute_list* KW_AWAIT? KW_FOREACH OP_163 type identifier_token KW_IN expression OP_164 statement - ; - -for_each_variable_statement - : attribute_list* KW_AWAIT? KW_FOREACH OP_163 expression KW_IN expression OP_164 statement - ; - -continue_statement - : attribute_list* KW_CONTINUE identifier_name? OP_172 - ; - -do_statement - : attribute_list* KW_DO statement KW_WHILE OP_163 expression OP_164 OP_172 - ; - -empty_statement - : attribute_list* OP_172 - ; - -expression_statement - : attribute_list* expression OP_172 - ; - -fixed_statement - : attribute_list* KW_FIXED OP_163 variable_declaration OP_164 statement - ; - -for_statement - : attribute_list* KW_FOR OP_163 (variable_declaration? | (expression (OP_167 expression)*)?) OP_172 expression? OP_172 (expression (OP_167 expression)*)? OP_164 statement - ; - -goto_statement - : attribute_list* KW_GOTO (KW_CASE | KW_DEFAULT)? expression? OP_172 - ; - -if_statement - : attribute_list* KW_IF OP_163 expression OP_164 statement else_clause? - ; - -else_clause - : KW_ELSE statement - ; - -labeled_statement - : attribute_list* identifier_token OP_171 statement - ; - -local_declaration_statement - : attribute_list* KW_AWAIT? KW_USING? modifier* variable_declaration OP_172 - ; - -local_function_statement - : attribute_list* modifier* type identifier_token type_parameter_list? parameter_list type_parameter_constraint_clause* (block | (arrow_expression_clause OP_172)) - ; - -lock_statement - : attribute_list* KW_LOCK OP_163 expression OP_164 statement - ; - -return_statement - : attribute_list* KW_RETURN expression? OP_172 - ; - -switch_statement - : attribute_list* KW_SWITCH OP_163? expression OP_164? OP_181 switch_section* OP_183 - ; - -switch_section - : switch_label+ statement+ - ; - -switch_label - : case_pattern_switch_label - | case_switch_label - | default_switch_label - ; - -case_pattern_switch_label - : KW_CASE pattern when_clause? OP_171 - ; - -pattern - : binary_pattern - | constant_pattern - | declaration_pattern - | discard_pattern - | list_pattern - | parenthesized_pattern - | recursive_pattern - | relational_pattern - | slice_pattern - | type_pattern - | unary_pattern - | var_pattern - ; - -binary_pattern - : pattern (KW_OR | KW_AND) pattern - ; - -constant_pattern - : expression - ; - -declaration_pattern - : type variable_designation - ; - -variable_designation - : discard_designation - | parenthesized_variable_designation - | single_variable_designation - ; - -discard_designation - : KW__ - ; - -parenthesized_variable_designation - : OP_163 (variable_designation (OP_167 variable_designation)*)? OP_164 - ; - -single_variable_designation - : identifier_token - ; - -discard_pattern - : KW__ - ; - -list_pattern - : OP_177 (pattern (OP_167 pattern)* OP_167?)? OP_178 variable_designation? - ; - -parenthesized_pattern - : OP_163 pattern OP_164 - ; - -recursive_pattern - : type? positional_pattern_clause? property_pattern_clause? variable_designation? - ; - -positional_pattern_clause - : OP_163 (subpattern (OP_167 subpattern)*)? OP_164 - ; - -subpattern - : base_expression_colon? pattern - ; - -base_expression_colon - : expression_colon - | name_colon - ; - -expression_colon - : expression OP_171 - ; - -property_pattern_clause - : OP_181 (subpattern (OP_167 subpattern)* OP_167?)? OP_183 - ; - -relational_pattern - : OP_120 expression - | OP_173 expression - | OP_136 expression - | OP_137 expression - | OP_175 expression - | OP_139 expression - ; - -slice_pattern - : OP_130 pattern? - ; - -type_pattern - : type - ; - -unary_pattern - : KW_NOT pattern - ; - -var_pattern - : KW_VAR variable_designation - ; - -when_clause - : KW_WHEN expression - ; - -case_switch_label - : KW_CASE expression OP_171 - ; - -default_switch_label - : KW_DEFAULT OP_171 - ; - -throw_statement - : attribute_list* KW_THROW expression? OP_172 - ; - -try_statement - : attribute_list* KW_TRY block catch_clause* finally_clause? - ; - -catch_clause - : KW_CATCH catch_declaration? catch_filter_clause? block - ; - -catch_declaration - : OP_163 type identifier_token? OP_164 - ; - -catch_filter_clause - : KW_WHEN OP_163 expression OP_164 - ; - -finally_clause - : KW_FINALLY block - ; - -unsafe_statement - : attribute_list* KW_UNSAFE block - ; - -using_statement - : attribute_list* KW_AWAIT? KW_USING OP_163 (variable_declaration | expression) OP_164 statement - ; - -while_statement - : attribute_list* KW_WHILE OP_163 expression OP_164 statement - ; - -yield_statement - : attribute_list* KW_YIELD (KW_RETURN | KW_BREAK) expression? OP_172 - ; - -expression - : anonymous_function_expression - | anonymous_object_creation_expression - | array_creation_expression - | assignment_expression - | await_expression - | base_object_creation_expression - | binary_expression - | cast_expression - | checked_expression - | collection_expression - | conditional_access_expression - | conditional_expression - | declaration_expression - | default_expression - | element_access_expression - | element_binding_expression - | field_expression - | implicit_array_creation_expression - | implicit_element_access - | implicit_stack_alloc_array_creation_expression - | initializer_expression - | instance_expression - | interpolated_string_expression - | invocation_expression - | is_pattern_expression - | literal_expression - | make_ref_expression - | member_access_expression - | member_binding_expression - | parenthesized_expression - | postfix_unary_expression - | prefix_unary_expression - | query_expression - | range_expression - | ref_expression - | ref_type_expression - | ref_value_expression - | size_of_expression - | stack_alloc_array_creation_expression - | switch_expression - | throw_expression - | tuple_expression - | type - | type_of_expression - | unsafe_expression - | with_expression - ; - -anonymous_function_expression - : anonymous_method_expression - | lambda_expression - ; - -anonymous_method_expression - : modifier* KW_DELEGATE parameter_list? block expression? - ; - -lambda_expression - : parenthesized_lambda_expression - | simple_lambda_expression - ; - -parenthesized_lambda_expression - : attribute_list* modifier* type? parameter_list OP_138 (block | expression) - ; - -simple_lambda_expression - : attribute_list* modifier* parameter OP_138 (block | expression) - ; - -anonymous_object_creation_expression - : KW_NEW OP_181 (anonymous_object_member_declarator (OP_167 anonymous_object_member_declarator)* OP_167?)? OP_183 - ; - -anonymous_object_member_declarator - : name_equals? expression - ; - -array_creation_expression - : KW_NEW array_type initializer_expression? - ; - -initializer_expression - : OP_181 (expression (OP_167 expression)* OP_167?)? OP_183 - ; - -assignment_expression - : expression (OP_174 | OP_126 | OP_128 | OP_124 | OP_131 | OP_121 | OP_123 | OP_145 | OP_155 | OP_103 | OP_104 | OP_078 | OP_106) expression - ; - -await_expression - : KW_AWAIT expression - ; - -base_object_creation_expression - : implicit_object_creation_expression - | object_creation_expression - ; - -implicit_object_creation_expression - : KW_NEW argument_list initializer_expression? - ; - -object_creation_expression - : KW_NEW type argument_list? initializer_expression? - ; - -binary_expression - : expression (OP_166 | OP_168 | OP_165 | OP_170 | OP_161 | OP_135 | OP_140 | OP_105 | OP_156 | OP_122 | OP_182 | OP_162 | OP_179 | OP_137 | OP_120 | OP_173 | OP_136 | OP_175 | OP_139 | KW_IS | KW_AS | OP_141) expression - ; - -cast_expression - : OP_163 type OP_164 expression - ; - -checked_expression - : KW_CHECKED OP_163 expression OP_164 - | KW_UNCHECKED OP_163 expression OP_164 - ; - -collection_expression - : OP_177 (collection_element (OP_167 collection_element)* OP_167?)? OP_178 - ; - -collection_element - : expression_element - | spread_element - | with_element - ; - -expression_element - : expression - ; - -spread_element - : OP_130 expression - ; - -with_element - : KW_WITH argument_list - ; - -conditional_access_expression - : expression OP_176 expression - ; - -conditional_expression - : expression OP_176 expression OP_171 expression - ; - -declaration_expression - : type variable_designation - ; - -default_expression - : KW_DEFAULT OP_163 type OP_164 - ; - -element_access_expression - : expression bracketed_argument_list - ; - -element_binding_expression - : bracketed_argument_list - ; - -field_expression - : KW_FIELD - ; - -implicit_array_creation_expression - : KW_NEW OP_177 OP_167* OP_178 initializer_expression - ; - -implicit_element_access - : bracketed_argument_list - ; - -implicit_stack_alloc_array_creation_expression - : KW_STACKALLOC OP_177 OP_178 initializer_expression - ; - -instance_expression - : base_expression - | this_expression - ; - -base_expression - : KW_BASE - ; - -this_expression - : KW_THIS - ; - -interpolated_string_expression - : INTERP_START interpolated_string_content* OP_158 - | INTERP_VERBATIM_START interpolated_string_content* OP_158 - | interpolated_multi_line_raw_string_start_token interpolated_string_content* interpolated_raw_string_end_token - | interpolated_single_line_raw_string_start_token interpolated_string_content* interpolated_raw_string_end_token - ; - -interpolated_string_content - : interpolated_string_text - | interpolation - ; - -interpolated_string_text - : interpolated_string_text_token - ; - -interpolation - : OP_181 expression interpolation_alignment_clause? interpolation_format_clause? OP_183 - ; - -interpolation_alignment_clause - : OP_167 expression - ; - -interpolation_format_clause - : OP_171 interpolated_string_text_token - ; - -interpolated_multi_line_raw_string_start_token - : OP_160+ OP_102 OP_158* - ; - -interpolated_raw_string_end_token - : OP_102 OP_158* /* must match number of quotes in raw_string_start_token */ - ; - -interpolated_single_line_raw_string_start_token - : OP_160+ OP_102 OP_158* - ; - -invocation_expression - : expression argument_list - ; - -is_pattern_expression - : expression KW_IS pattern - ; - -literal_expression - : KW_DEFAULT - | KW_FALSE - | KW_NULL - | KW_TRUE - | KW___ARGLIST - | character_literal_token - | multi_line_raw_string_literal_token - | numeric_literal_token - | single_line_raw_string_literal_token - | string_literal_token - | utf8_multi_line_raw_string_literal_token - | utf8_single_line_raw_string_literal_token - | utf8_string_literal_token - ; - -utf8_multi_line_raw_string_literal_token - : multi_line_raw_string_literal_token (KW_U8 | KW_U8_154) - ; - -utf8_single_line_raw_string_literal_token - : single_line_raw_string_literal_token (KW_U8 | KW_U8_154) - ; - -utf8_string_literal_token - : string_literal_token (KW_U8 | KW_U8_154) - ; - -make_ref_expression - : KW___MAKEREF OP_163 expression OP_164 - ; - -member_access_expression - : expression (OP_169 | OP_129) simple_name - ; - -member_binding_expression - : OP_169 simple_name - ; - -parenthesized_expression - : OP_163 expression OP_164 - ; - -postfix_unary_expression - : expression (OP_125 | OP_127 | OP_157) - ; - -prefix_unary_expression - : OP_157 expression - | OP_162 expression - | OP_165 expression - | OP_166 expression - | OP_125 expression - | OP_168 expression - | OP_127 expression - | OP_179 expression - | OP_184 expression - ; - -query_expression - : from_clause query_body - ; - -from_clause - : KW_FROM type? identifier_token KW_IN expression - ; - -query_body - : query_clause+ select_or_group_clause query_continuation? - ; - -query_clause - : from_clause - | join_clause - | let_clause - | order_by_clause - | where_clause - ; - -join_clause - : KW_JOIN type? identifier_token KW_IN expression KW_ON expression KW_EQUALS expression join_into_clause? - ; - -join_into_clause - : KW_INTO identifier_token - ; - -let_clause - : KW_LET identifier_token OP_174 expression - ; - -order_by_clause - : KW_ORDERBY ordering (OP_167 ordering)* - ; - -ordering - : expression (KW_ASCENDING | KW_DESCENDING)? - ; - -where_clause - : KW_WHERE expression - ; - -select_or_group_clause - : group_clause - | select_clause - ; - -group_clause - : KW_GROUP expression KW_BY expression - ; - -select_clause - : KW_SELECT expression - ; - -query_continuation - : KW_INTO identifier_token query_body - ; - -range_expression - : expression? OP_130 expression? - ; - -ref_expression - : KW_REF expression - ; - -ref_type_expression - : KW___REFTYPE OP_163 expression OP_164 - ; - -ref_value_expression - : KW___REFVALUE OP_163 expression OP_167 type OP_164 - ; - -size_of_expression - : KW_SIZEOF OP_163 type OP_164 - ; - -stack_alloc_array_creation_expression - : KW_STACKALLOC type initializer_expression? - ; - -switch_expression - : expression KW_SWITCH OP_181 (switch_expression_arm (OP_167 switch_expression_arm)* OP_167?)? OP_183 - ; - -switch_expression_arm - : pattern when_clause? OP_138 expression - ; - -throw_expression - : KW_THROW expression - ; - -tuple_expression - : OP_163 argument (OP_167 argument)+ OP_164 - ; - -type_of_expression - : KW_TYPEOF OP_163 type OP_164 - ; - -unsafe_expression - : KW_UNSAFE OP_163 expression OP_164 - ; - -with_expression - : expression KW_WITH initializer_expression - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -syntax_token - : character_literal_token - | identifier_token - | keyword - | numeric_literal_token - | operator_token - | punctuation_token - | string_literal_token - ; - -identifier_token - : IDENTIFIER - ; - - - - - - - - - -keyword - : KW_AS - | KW_BASE - | KW_BOOL - | KW_BREAK - | KW_BYTE - | KW_CASE - | KW_CATCH - | KW_CHAR - | KW_CHECKED - | KW_CLASS - | KW_CONTINUE - | KW_DECIMAL - | KW_DEFAULT - | KW_DELEGATE - | KW_DO - | KW_DOUBLE - | KW_ELSE - | KW_ENUM - | KW_EVENT - | KW_EXPLICIT - | KW_FALSE - | KW_FINALLY - | KW_FLOAT - | KW_FOR - | KW_FOREACH - | KW_GOTO - | KW_IF - | KW_IMPLICIT - | KW_IN - | KW_INT - | KW_INTERFACE - | KW_IS - | KW_LOCK - | KW_LONG - | KW_NAMESPACE - | KW_NULL - | KW_OBJECT - | KW_OPERATOR - | KW_OUT - | KW_PARAMS - | KW_RETURN - | KW_SBYTE - | KW_SHORT - | KW_SIZEOF - | KW_STACKALLOC - | KW_STRING - | KW_STRUCT - | KW_SWITCH - | KW_THIS - | KW_THROW - | KW_TRUE - | KW_TRY - | KW_TYPEOF - | KW_UINT - | KW_ULONG - | KW_UNCHECKED - | KW_USHORT - | KW_USING - | KW_VOID - | KW_WHILE - | KW___ARGLIST - | KW___MAKEREF - | KW___REFTYPE - | KW___REFVALUE - | modifier - ; - -numeric_literal_token - : integer_literal_token - | real_literal_token - ; - -integer_literal_token - : decimal_integer_literal_token - | hexadecimal_integer_literal_token - ; - -decimal_integer_literal_token - : DEC_INT_LIT - ; - - - -hexadecimal_integer_literal_token - : HEX_INT_LIT - ; - - -real_literal_token - : REAL_LIT - ; - - - -character_literal_token - : CHAR_LIT - ; - - - - - - -string_literal_token - : regular_string_literal_token - | verbatim_string_literal_token - ; - -regular_string_literal_token - : STRING_LIT - ; - - - -verbatim_string_literal_token - : VERBATIM_STRING_LIT - ; - - - - -operator_token - : OP_157 - | OP_120 - | OP_161 - | OP_121 - | OP_122 - | OP_162 - | OP_123 - | OP_165 - | OP_124 - | OP_166 - | OP_125 - | OP_126 - | OP_168 - | OP_127 - | OP_128 - | OP_170 - | OP_131 - | OP_173 - | OP_135 - | OP_103 - | OP_136 - | OP_174 - | OP_137 - | OP_175 - | OP_139 - | OP_140 - | OP_104 - | OP_105 - | OP_078 - | OP_141 - | OP_106 - | KW_AS - | KW_IS - | OP_179 - | OP_145 - | OP_182 - | OP_155 - | OP_156 - | OP_184 - ; - -punctuation_token - : OP_158 - | OP_159 - | OP_163 - | OP_164 - | OP_167 - | OP_129 - | OP_169 - | OP_130 - | OP_132 - | OP_171 - | OP_133 - | OP_172 - | OP_134 - | OP_138 - | OP_176 - | OP_177 - | OP_143 - | OP_144 - | OP_178 - | OP_181 - | OP_183 - ; - - - - - - -interpolated_string_text_token - : INTERPOLATED_TEXT - ; - -multi_line_raw_string_literal_token - : ML_RAW_STRING_LIT - ; - -single_line_raw_string_literal_token - : SL_RAW_STRING_LIT - ; - - - -// Contextual keyword: `record` lexes as an ordinary IDENTIFIER (it is legal as a -// name), so the declaration position is restricted by a predicate on the token -// text. This restores Roslyn's , which its -// grammar generator drops. Lowered by `patterns.toml` to a pure SemIR -// comparison, so no hooks are needed. -// -// UNREFERENCED IN THIS VARIANT. This is the `slow` control: `record_declaration` -// above deliberately keeps Roslyn's catch-all `syntax_token`, which is what makes -// `class` viable as a record and drives the timing blow-up being reproduced. The -// rule (and the `IsRecordKeyword` helper in this directory's `patterns.toml`) is -// kept only so both variants generate from the identical helper set, isolating the -// single grammar difference under measurement. -record_keyword - : {this.IsRecordKeyword()}? identifier_token - ; diff --git a/repro/roslyn-csharp-perf/grammar/unnarrowed-record/patterns.toml b/repro/roslyn-csharp-perf/grammar/unnarrowed-record/patterns.toml deleted file mode 100644 index 5fd78459..00000000 --- a/repro/roslyn-csharp-perf/grammar/unnarrowed-record/patterns.toml +++ /dev/null @@ -1,16 +0,0 @@ -version = 1 - -# `record` is a contextual keyword. Roslyn declares -# `` on -# RecordDeclarationSyntax.Keyword, but its grammar generator reads only -# ``, so the published grammar spells the keyword as the catch-all -# `syntax_token` — which makes `class` viable as a record declaration and -# costs ~quadratic prediction time per type member. `prepare-roslyn-grammar.py` -# restores the restriction as a text comparison on the lookahead token; it -# lowers to a pure SemIR expression, so no typed hook is needed. - -[[helper]] -kind = "parser-predicate" -name = "IsRecordKeyword" -returns = "bool" -lower = "cmp(eq, token_text(1), str(\"record\"))" diff --git a/repro/roslyn-csharp-perf/run.sh b/repro/roslyn-csharp-perf/run.sh deleted file mode 100755 index a725ad18..00000000 --- a/repro/roslyn-csharp-perf/run.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash -# One-command reproduction of the Roslyn-grammar member-scaling blow-up. -# -# ./run.sh slow # as-published: record keyword is the catch-all `syntax_token` -# ./run.sh fixed # record contextual keyword restored (default) -# -# Needs `antlr4-rust-gen` 0.33.1 on PATH — it must MATCH the runtime version -# pinned in Cargo.toml, or the generated modules call a different API than the -# crate they link against (e.g. the 0.23 `SyntaxErrorEvent` change): -# cargo install antlr-rust-codegen --version 0.33.1 \ -# --bin antlr4-rust-gen --force -set -euo pipefail -cd "$(dirname "$0")" - -VARIANT="${1:-fixed}" -# ANTLR requires the file name to match the grammar name, so each variant -# lives in its own directory with identically-named files. -case "$VARIANT" in - fixed) GDIR=grammar ;; # record contextual keyword restored - slow) GDIR=grammar/unnarrowed-record ;; # as-published: keyword is `syntax_token` - *) echo "usage: $0 [fixed|slow]" >&2; exit 2 ;; -esac - -command -v antlr4-rust-gen >/dev/null || { - echo "antlr4-rust-gen not on PATH — see the header of this script" >&2 - exit 1 -} - -echo "== generating ($VARIANT) ==" -rm -rf src/generated && mkdir -p src/generated -# `--sem-unknown error --require-full-semantics` mirrors how mehen generates: -# nothing may be silently assumed. The grammar needs no hooks or patterns. -antlr4-rust-gen "$GDIR/CSharpLexer.g4" "$GDIR/CSharpParser.g4" \ - --out-dir src/generated --sem-patterns "$GDIR/patterns.toml" \ - --sem-unknown error --require-full-semantics - -echo "== building ==" -cargo build --release --quiet --bin time-parse - -echo "== members-per-class scaling ==" -mkdir -p target/fixtures -for n in 4 8 12 18 24; do - python3 fixtures/gen-fixture.py "$n" > "target/fixtures/members-$n.cs" -done -printf '%s\n' " (elapsed ms / recovered errors / fixture)" -./target/release/time-parse target/fixtures/members-*.cs - -echo "== regression: omitted-node syntax must parse with 0 errors ==" -# `--require-clean` makes a nonzero error count exit 1, so `set -e` actually -# enforces the assertion this step advertises. Without it `time-parse` printed -# the count and exited 0, so a broken grammar passed silently. -./target/release/time-parse --require-clean fixtures/omitted-nodes.cs - -if [ "$#" -gt 1 ]; then - shift - echo "== extra files ==" - ./target/release/time-parse "$@" -fi diff --git a/repro/roslyn-csharp-perf/src/bin/time-parse.rs b/repro/roslyn-csharp-perf/src/bin/time-parse.rs deleted file mode 100644 index 595b42f4..00000000 --- a/repro/roslyn-csharp-perf/src/bin/time-parse.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! Time `compilation_unit` over one or more C# files. -//! -//! Usage: time-parse [--require-clean] ... -//! Prints one line per file: elapsed ms, recovered syntax-error count, path. -//! -//! `--require-clean` additionally exits 1 if any file reported a recovered error -//! or hard-failed, so `run.sh` can assert a parse regression rather than only -//! printing one. Without it the exit status is 0 whatever the counts, which is -//! what a timing run wants. - -use antlr4_runtime::{CommonTokenStream, InputStream, Parser}; -use roslyn_csharp_perf::c_sharp_lexer::CSharpLexer; -use roslyn_csharp_perf::c_sharp_parser::CSharpParser; -use std::time::Instant; - -fn main() { - let mut args: Vec = std::env::args().skip(1).collect(); - let require_clean = args.iter().any(|arg| arg == "--require-clean"); - args.retain(|arg| arg != "--require-clean"); - if args.is_empty() { - eprintln!("usage: time-parse [--require-clean] ..."); - std::process::exit(2); - } - let mut unclean = 0usize; - for path in &args { - let src = std::fs::read_to_string(path).expect("readable source file"); - let started = Instant::now(); - let lexer = CSharpLexer::new(InputStream::new(&src)); - let mut parser = CSharpParser::new(CommonTokenStream::new(lexer)); - parser.remove_error_listeners(); - let errors = match parser.compilation_unit() { - Ok(tree) => { - let n = parser.number_of_syntax_errors(); - let _ = parser.into_parsed_file(tree); - n - } - // A hard failure still costs the time we are measuring. - Err(_) => usize::MAX, - }; - let ms = started.elapsed().as_millis(); - if errors != 0 { - unclean += 1; - } - let errors = if errors == usize::MAX { - "hard-fail".to_string() - } else { - errors.to_string() - }; - println!("{ms:>8} ms {errors:>9} errs {path}"); - } - if require_clean && unclean > 0 { - eprintln!("error: {unclean} file(s) did not parse cleanly"); - std::process::exit(1); - } -} diff --git a/repro/roslyn-csharp-perf/src/lib.rs b/repro/roslyn-csharp-perf/src/lib.rs deleted file mode 100644 index 055cd1af..00000000 --- a/repro/roslyn-csharp-perf/src/lib.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Generated C# lexer/parser for the Roslyn-grammar performance repro. -//! -//! `src/generated/` is produced by `./run.sh`; it is not checked in (a 4.6 MB -//! parser), so build via that script rather than `cargo build` directly. -//! -//! Everything here is `pub` on purpose. `src/bin/time-parse.rs` is a separate crate -//! from this library, so a private facade could not reach the generated modules at -//! all — narrowing the surface would mean re-exporting the same names one level in, -//! which is the same surface with an extra hop. This crate is `publish = false` and -//! exists only to be measured by its own binary; there is no downstream consumer for -//! the surface to matter to. (The real parser crate, `mehen-csharp-parser`, is the -//! one with a public API worth curating.) -pub use antlr4_runtime; - -#[path = "generated/c_sharp_lexer.rs"] -pub mod c_sharp_lexer; - -#[path = "generated/c_sharp_parser.rs"] -pub mod c_sharp_parser; diff --git a/scripts/check_pr_template_catalog.sh b/scripts/check_pr_template_catalog.sh deleted file mode 100644 index c2b0475d..00000000 --- a/scripts/check_pr_template_catalog.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env bash -# shellcheck shell=bash -# -# check_pr_template_catalog.sh — Phase-F emitter linter (§39.5.3). -# -# Guards the strict §39.5.2 template catalog contract for -# `src/diff_markdown.rs`: -# -# 1. Every `format!(` / `write!(` / `writeln!(` call must be inside a helper -# whose name starts with `tmpl_` (the catalog slot-fillers) or must match -# the narrow allow-list of mechanical rendering helpers below. Doc and -# line comments are skipped. -# 2. No §39.5.3 forbidden phrase appears in a non-comment line. The list is -# identical to the spec: causation / intent / speculation verbs. -# -# The script exits non-zero on any violation and prints the offending -# line(s). It is designed to be shellcheck-clean. - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" -TARGET="${REPO_ROOT}/src/diff_markdown.rs" - -if [[ ! -f "${TARGET}" ]]; then - echo "error: target file not found: ${TARGET}" >&2 - exit 1 -fi - -# Allow-listed helpers: mechanical rendering that feeds a catalog template. -# Each name matches a `fn (` declaration (at any indentation). -ALLOWED_FUNCS=( - "render_doc_section" - "render_drill_down" - "render_drill_structural" - "render_drill_en_wording" - "render_drill_en_lexical" - "render_drill_ja" - "render_filler_contributors" - "write_headline_table" - "heading_scope" - "format_int_thousands" - "format_link_list" - "format_surface_list_without_line" - "format_value" - "build_file_link" - "render" -) - -allowed_pattern="$(IFS='|'; echo "${ALLOWED_FUNCS[*]}")" - -violations=0 - -# Build a (line_no, enclosing_fn_name) index via a single awk pass. -# The awk script tracks the most recent `fn NAME(` declaration (at any -# indentation level) and prints a `LINE\tFN` record for every `format!`, -# `write!`, or `writeln!` call that is not inside a comment. -mapfile -t fn_lines < <(awk ' - # Track the nearest preceding fn declaration (any indent). - match($0, /(^|[[:space:]])fn +[A-Za-z_][A-Za-z0-9_]*/) { - name_part = substr($0, RSTART, RLENGTH) - sub(/.*fn +/, "", name_part) - enclosing = name_part - next - } - # Skip line comments outright. - /^[[:space:]]*\/\// { next } - /^[[:space:]]*\/\*/ { next } - /^[[:space:]]*\*/ { next } - /format!\(|write!\(|writeln!\(/ { - printf "%d\t%s\n", NR, enclosing - } -' "${TARGET}") - -for record in "${fn_lines[@]}"; do - line_no="${record%%$'\t'*}" - enclosing_fn="${record#*$'\t'}" - case "${enclosing_fn}" in - tmpl_*) - continue - ;; - esac - if [[ -n "${enclosing_fn}" ]] \ - && echo "${enclosing_fn}" | grep -Eq "^(${allowed_pattern})\$"; then - continue - fi - # Read the offending source line for the error message. - line_text="$(sed -n "${line_no}p" "${TARGET}")" - echo "violation: format!/write! outside template catalog" >&2 - echo " enclosing_fn: ${enclosing_fn:-(top-level)}" >&2 - echo " ${TARGET}:${line_no}: ${line_text}" >&2 - violations=$((violations + 1)) -done - -# §39.5.3 forbidden phrases. Matching is case-insensitive, against -# non-comment lines only. -FORBIDDEN_PHRASES=( - 'because' - 'due to' - 'caused by' - 'following' - 'since' - 'likely' - 'probably' - 'appears to' - 'seems' - 'may indicate' - 'suggests' - 'possibly' -) - -for phrase in "${FORBIDDEN_PHRASES[@]}"; do - # Strip comments, then grep for the phrase. - matches="$(grep -n -F -i -- "${phrase}" "${TARGET}" \ - | awk -F: '$0 !~ /^[0-9]+:[[:space:]]*\/\//' \ - || true)" - if [[ -n "${matches}" ]]; then - echo "violation: §39.5.3 forbidden phrase '${phrase}' found:" >&2 - while IFS= read -r m; do - echo " ${TARGET}:${m}" >&2 - done <<< "${matches}" - violations=$((violations + 1)) - fi -done - -if (( violations > 0 )); then - echo "" >&2 - echo "scripts/check_pr_template_catalog.sh found ${violations} violation(s)." >&2 - exit 1 -fi - -echo "scripts/check_pr_template_catalog.sh: OK" -exit 0 diff --git a/scripts/generate-npm-packages.js b/scripts/generate-npm-packages.js index 8aa3cb5d..cec434fa 100644 --- a/scripts/generate-npm-packages.js +++ b/scripts/generate-npm-packages.js @@ -148,7 +148,7 @@ This package contains the Mehen binary for ${nodeOs}-${nodeArch}. This package is automatically installed as an optional dependency when you install the main \`mehen\` package. -For more information, visit: https://github.com/ophi-dev/mehen +For more information, visit: https://github.com/ophidiarium/mehen `; fs.writeFileSync(path.join(pkgDir, 'README.md'), readmeContent); diff --git a/scripts/github-action.mjs b/scripts/github-action.mjs deleted file mode 100644 index 645fdd69..00000000 --- a/scripts/github-action.mjs +++ /dev/null @@ -1,1585 +0,0 @@ -#!/usr/bin/env node - -import fs from "node:fs"; -import os from "node:os"; -import path from "node:path"; -import zlib from "node:zlib"; -import { spawnSync } from "node:child_process"; -import { fileURLToPath } from "node:url"; - -const MARKER = ""; -const DEFAULT_TITLE = "## 📊 Source Code Metrics"; -const FOOTER_PREFIX = - "> Generated by [mehen](https://github.com/ophi-dev/mehen)"; -const FOOTER_SUFFIX = "— the code quality watcher."; -const LOWER_IS_BETTER = "lower-is-better"; -const HIGHER_IS_BETTER = "higher-is-better"; - -const DEFAULT_TEST_EXCLUDES = [ - // Go - "**/*_test.go", - // Python - "**/test_*.py", - "**/*_test.py", - "**/tests/**", - "**/test/**", - // JavaScript / TypeScript - "**/__tests__/**", - "**/*.test.js", - "**/*.test.jsx", - "**/*.test.ts", - "**/*.test.tsx", - "**/*.test.mjs", - "**/*.test.cjs", - "**/*.spec.js", - "**/*.spec.jsx", - "**/*.spec.ts", - "**/*.spec.tsx", - "**/*.spec.mjs", - "**/*.spec.cjs", - // Ruby - "**/*_test.rb", - "**/*_spec.rb", - "**/spec/**", -]; - -const METRIC_ALIASES = new Map([ - ["functions", "nom.functions"], - ["nom", "nom.functions"], - ["lloc", "loc.lloc"], - ["loc", "loc.lloc"], - ["halsteadvol", "halstead.volume"], - ["halsteadvolume", "halstead.volume"], -]); - -// Declared above the entrypoint block below: `main()` starts running -// during module evaluation, so any `const` it reaches synchronously -// must already be initialized (a later declaration would be a -// temporal-dead-zone crash — seen live as "Cannot access -// 'CODECOV_PENDING_RETRIES' before initialization"). -const CODECOV_PENDING_RETRIES = 3; -const CODECOV_RETRY_DELAY_MS = 5000; -// Mirrors mehen's own per-report ingestion cap (256 MiB): a base -// artifact bigger than that could never be fed to the CLI anyway. -// Enforced in three layers — artifact metadata, downloaded bytes, and -// declared/actual decompressed size — so a hostile or corrupt archive -// degrades instead of exhausting the runner. -const ARTIFACT_MAX_BYTES = 256 * 1024 * 1024; -// Artifact listings are newest-first; a base SHA older than ~1000 -// same-named uploads is better served by the lower rungs than by an -// unbounded listing walk. -const ARTIFACT_MAX_PAGES = 10; -const ARTIFACT_DOWNLOAD_TIMEOUT_MS = 60_000; - -if (isEntrypoint()) { - main().catch((error) => { - console.error(error instanceof Error ? error.message : String(error)); - process.exit(1); - }); -} - -function isEntrypoint() { - return ( - process.argv[1] && - path.resolve(process.argv[1]) === - path.resolve(fileURLToPath(import.meta.url)) - ); -} - -async function main() { - const thresholds = parseThresholds(input("THRESHOLDS")); - const context = readGithubContext(); - let baseCoverage = await resolveBaseCoverage(context); - const cli = prepareMehen(); - const version = detectMehenVersion(cli); - let diffArgs = buildDiffArgs(baseCoverage.args); - let diff; - try { - diff = runMehen(cli, diffArgs, { acceptGateOutput: isGateFailureReport }); - } catch (error) { - // mehen hard-errors on an explicit report it cannot read or parse - // — correct for a CLI gate input, but the retrieved base reports - // are not fully controlled (a prefix cache key can restore another - // configuration's files; an interrupted run can cache a truncated - // report). The ladder's contract is disclosure and degradation, - // never a failed action with no comment: retry once without the - // base side and disclose the downgrade. - if (!isBaseCoverageFailure(error, baseCoverage.args)) { - throw error; - } - console.warn( - "mehen rejected the retrieved base coverage report(s); continuing without base coverage.", - ); - baseCoverage = { - args: [], - disclosure: `Base coverage: a retrieved report for \`${context.baseSha.slice(0, 7)}\` was unusable — coverage values are shown without a base to compare against, not as trends.`, - }; - // Rebuild — not just rerun — so every later consumer of the - // argument list (the Markdown docs rerun) also sees the degraded - // arguments instead of re-tripping over the rejected report. - diffArgs = buildDiffArgs(); - diff = runMehen(cli, diffArgs, { - acceptGateOutput: isGateFailureReport, - }); - } - const reportsDir = process.env.RUNNER_TEMP || os.tmpdir(); - const reportJson = path.join(reportsDir, `mehen-diff-${Date.now()}.json`); - fs.writeFileSync(reportJson, `${diff.stdout.trim()}\n`, "utf8"); - - const diffs = parseDiffJson(diff.stdout); - const gateViolations = parseGateViolations(diff.stdout); - const violations = collectThresholdViolations(diffs, thresholds); - let markdown = renderMarkdown( - diffs, - context, - thresholds, - violations, - version, - gateViolations, - baseCoverage.disclosure, - ); - - // Phase F (§39): `mehen diff --output-format markdown` emits a - // `` block whenever a changed Markdown file is in - // scope. The JSON payload already says whether that is the case - // (its `markdown` array), so the second invocation — needed only - // for the *rendered* section — is skipped entirely when no Markdown - // file changed, and runs history-free when it is needed. - const docsSection = diffJsonHasDocs(diff.stdout) - ? fetchMarkdownDocsSection(cli, diffArgs) - : null; - if (docsSection) { - markdown = `${markdown.trimEnd()}\n\n${docsSection}\n`; - } - - const reportMarkdown = path.join(reportsDir, `mehen-report-${Date.now()}.md`); - fs.writeFileSync(reportMarkdown, markdown, "utf8"); - - writeStepSummary(markdown); - try { - await maybeComment(markdown, context); - } catch (error) { - console.warn(`Unable to publish mehen PR comment: ${error.message}`); - } - - // The advertised violation count covers both gates: Action-input - // delta thresholds and repository `mehen.toml` breaches parsed from - // the diff report. - setOutput("violations", String(violations.length + gateViolations.length)); - setOutput("report_json", reportJson); - setOutput("report_markdown", reportMarkdown); - - if (violations.length > 0 && boolInput("FAIL_ON_THRESHOLD", true)) { - console.error( - `Mehen threshold check failed with ${violations.length} violation(s).`, - ); - process.exit(1); - } - - // A deferred quality-gate failure from the diff itself (configured - // `mehen.toml` thresholds): the comment and report outputs above - // landed with the complete report; now the workflow step fails. - if (diff.gateStatus) { - console.error( - `mehen diff exited with status ${diff.gateStatus}: a configured quality gate failed (see the report above).`, - ); - process.exit(1); - } -} - -function input(name, fallback = "") { - return process.env[`GHA_MEHEN_${name}`] ?? fallback; -} - -function boolInput(name, fallback) { - const value = input(name).trim().toLowerCase(); - if (!value) { - return fallback; - } - return ["1", "true", "yes", "on"].includes(value); -} - -function parseList(value) { - const trimmed = String(value ?? "").trim(); - if (!trimmed) { - return []; - } - const parts = trimmed.split(/\r?\n|[;,]/); - return parts.map((part) => part.trim()).filter(Boolean); -} - -function buildDiffArgs(extraArgs = []) { - const args = ["diff", "--output-format", "json"]; - const from = input("FROM").trim(); - const to = input("TO").trim(); - const metrics = input("METRICS").trim(); - const paths = parseList(input("PATHS")); - const include = parseList(input("INCLUDE")); - const exclude = parseList(input("EXCLUDE")); - const coverageFiles = parseList(input("COVERAGE_FILES")); - if (boolInput("EXCLUDE_TESTS", true)) { - for (const pattern of DEFAULT_TEST_EXCLUDES) { - if (!exclude.includes(pattern)) { - exclude.push(pattern); - } - } - } - - if (from) { - args.push("--from", from); - } - if (to) { - args.push("--to", to); - } - if (metrics) { - args.push("--metrics", metrics); - } - if (paths.length > 0 && !(paths.length === 1 && paths[0] === ".")) { - args.push("--paths", ...paths); - } - if (include.length > 0) { - args.push("--include", ...include); - } - if (exclude.length > 0) { - args.push("--exclude", ...exclude); - } - if (boolInput("SHOW_UNCHANGED", false)) { - args.push("--show-unchanged"); - } - // Head-side coverage: the reports the caller's test step just wrote. - // A configured-but-missing file is warned about and skipped rather - // than passed through — mehen hard-errors on missing explicit - // reports (an explicit gate input that silently disappears is a - // broken gate), but the action is a reporter: the caller's test - // step owns failing the build when coverage generation breaks. - const presentCoverageFiles = coverageFiles.filter((file) => { - if (fs.existsSync(file)) { - return true; - } - console.warn( - `mehen: coverage file '${file}' not found; head-side coverage will be missing for it`, - ); - return false; - }); - for (const file of presentCoverageFiles) { - args.push(`--coverage=${file}`); - } - // Every configured report is missing: pin coverage off. Without the - // pin, a `--base-coverage` argument would flip mehen's lazy trigger - // into head-side auto-discovery, silently substituting whatever - // stale artifact the working tree happens to hold for the reports - // the caller explicitly configured. - if (coverageFiles.length > 0 && presentCoverageFiles.length === 0) { - args.push("--coverage=off"); - } - args.push(...extraArgs); - - return args; -} - -// ── Base coverage retrieval (issue #248, artifact rung: #254) ──────── -// -// The action, not the mehen binary, owns base-revision coverage: mehen -// stays network-free and receives plain report paths. Degradation -// ladder: exact cache hit → workflow artifact by base SHA → codecov by -// SHA → nearest default-branch cache (recency-based, so explicitly -// disclosed) → absent (columns render as new measurements). Every -// level is stated in the sticky PR comment — never silently. - -/** - * Resolve base-revision coverage into `--base-coverage=` CLI arguments - * plus a human-readable disclosure line for the PR comment. Returns - * `{ args: [], disclosure: null }` when base coverage does not apply - * (no coverage-files configured, source off, or not a pull request). - */ -async function resolveBaseCoverage(context) { - const none = { args: [], disclosure: null }; - const files = parseList(input("COVERAGE_FILES")); - const source = - input("COVERAGE_BASE_SOURCE", "auto").trim().toLowerCase() || "auto"; - if (files.length === 0 || source === "off") { - return none; - } - if (!["auto", "cache", "artifact", "codecov"].includes(source)) { - throw new Error( - `Unsupported coverage-base-source '${source}'. Use auto, cache, artifact, codecov, or off.`, - ); - } - const artifactName = input("COVERAGE_ARTIFACT_NAME").trim(); - if (source === "artifact" && !artifactName) { - throw new Error( - "coverage-base-source: artifact requires the coverage-artifact-name input.", - ); - } - // Base trends are a pull-request concept: pushes and manual runs - // compare event-defined ranges whose base has no retrievable report. - if (context.eventName !== "pull_request" || !context.baseSha) { - return none; - } - const shortBase = context.baseSha.slice(0, 7); - - const cacheDir = input("COVERAGE_BASE_DIR").trim(); - const exactHit = input("COVERAGE_CACHE_HIT").trim().toLowerCase() === "true"; - const matchedKey = input("COVERAGE_CACHE_KEY").trim(); - const cachedReports = listFilesRecursively(cacheDir); - - // Rung 1 — exact cache hit: the base SHA's own reports. - if (source !== "codecov" && source !== "artifact") { - if (exactHit && cachedReports.length > 0) { - return { - args: cachedReports.map((file) => `--base-coverage=${file}`), - disclosure: `Base coverage: restored from the Actions cache for \`${shortBase}\`.`, - }; - } - } - - // Rung 2 — workflow artifact by exact base SHA. Artifacts persist - // ~90 days (the Actions cache evicts after 7 unused days or under - // repository size pressure), and many repositories already upload - // their coverage reports as artifacts — including for GitHub Code - // Quality's own upload job. Requires `actions: read` on the job's - // token; opt-in via the coverage-artifact-name input. - if ((source === "auto" || source === "artifact") && artifactName) { - const artifactFiles = await fetchArtifactBaseReports( - context, - artifactName, - ); - if (artifactFiles) { - return { - args: artifactFiles.map((file) => `--base-coverage=${file}`), - disclosure: `Base coverage: restored from the \`${artifactName}\` workflow artifact for \`${shortBase}\`.`, - }; - } - } - - // Rung 3 — codecov by exact SHA. Line dimension only: codecov's - // merged view has no original branch arms, and fabricating BRDA - // records would poison branch-coverage gates. - if (source === "auto" || source === "codecov") { - const lcov = await fetchCodecovBaseReport(context); - if (lcov) { - const dir = path.join( - process.env.RUNNER_TEMP || os.tmpdir(), - "mehen-codecov-base", - ); - fs.mkdirSync(dir, { recursive: true }); - const reportPath = path.join(dir, "codecov-base.lcov"); - fs.writeFileSync(reportPath, lcov, "utf8"); - return { - args: [`--base-coverage=${reportPath}`], - disclosure: `Base coverage: fetched from codecov.io for \`${shortBase}\` (line dimension only).`, - }; - } - } - - // Rung 4 — nearest default-branch cache via the prefix restore-key: - // recency-based, not ancestor-aware, so the staleness is disclosed - // (mehen itself also warns when the report predates the base - // commit). - if (source !== "codecov" && source !== "artifact") { - if (cachedReports.length > 0) { - const label = matchedKey ? ` (\`${matchedKey}\`)` : ""; - return { - args: cachedReports.map((file) => `--base-coverage=${file}`), - disclosure: `Base coverage: nearest default-branch cache${label} — no saved report for \`${shortBase}\` itself, so coverage trends may compare against an older commit.`, - }; - } - } - - // Rung 5 — absent. Coverage cells show head values without a base - // to compare against (`85 (main: n/a)` on changed files, `85 🆕` on - // new ones), never fabricated regressions. - return { - args: [], - disclosure: `Base coverage: unavailable for \`${shortBase}\` — coverage values are shown without a base to compare against, not as trends.`, - }; -} - -/** - * Fetch the codecov commit report for the PR base SHA and convert it - * to LCOV. Returns null (never throws) when codecov has no usable - * report — the ladder degrades instead. A `pending` report state is - * retried briefly; a 404 means no upload exists for that SHA and is - * final. - */ -async function fetchCodecovBaseReport(context) { - const [owner, repo] = context.repository.split("/"); - if (!owner || !repo) { - return null; - } - const token = input("CODECOV_TOKEN").trim(); - const url = `https://api.codecov.io/api/v2/github/${encodeURIComponent(owner)}/repos/${encodeURIComponent(repo)}/report/?sha=${encodeURIComponent(context.baseSha)}`; - for (let attempt = 1; attempt <= CODECOV_PENDING_RETRIES; attempt += 1) { - let payload; - try { - const headers = { - Accept: "application/json", - "User-Agent": "mehen-action", - }; - if (token) { - headers.Authorization = `bearer ${token}`; - } - const response = await fetch(url, { headers }); - if (response.status === 404) { - console.log( - `codecov has no report for base ${context.baseSha}; trying the next base-coverage source.`, - ); - return null; - } - if (!response.ok) { - console.warn( - `codecov API responded ${response.status} for base ${context.baseSha}; trying the next base-coverage source.`, - ); - return null; - } - payload = await response.json(); - } catch (error) { - console.warn( - `codecov API request failed (${error.message}); trying the next base-coverage source.`, - ); - return null; - } - if (payload && payload.state === "pending") { - console.log( - `codecov report for ${context.baseSha} is still processing (attempt ${attempt}/${CODECOV_PENDING_RETRIES}).`, - ); - if (attempt < CODECOV_PENDING_RETRIES) { - await sleep(CODECOV_RETRY_DELAY_MS); - } - continue; - } - const lcov = codecovToLcov(payload); - if (!lcov) { - console.log( - `codecov report for ${context.baseSha} carries no per-file line data; trying the next base-coverage source.`, - ); - } - return lcov; - } - console.warn( - `codecov report for ${context.baseSha} stayed pending; trying the next base-coverage source.`, - ); - return null; -} - -/** - * Convert a codecov API v2 commit report to LCOV `SF:`/`DA:` records. - * - * `line_coverage` entries are `[line, status]` pairs with - * 0 = hit, 1 = miss, 2 = partial (verified against this repository's - * own codecov data for 0/1; 2 follows codecov's documented session - * encoding). A partial line executed, so it maps to a hit — and no - * `BRDA` records are fabricated: codecov's merged view does not - * preserve original branch arms, and invented arms would poison - * `coverage.branch` gates. Unknown statuses and malformed entries are - * skipped (measured-or-absent). Returns null when no file yields any - * line record — an empty LCOV file would fail mehen's format sniff, - * and "absent with disclosure" is the honest degradation. - */ -function codecovToLcov(report) { - const files = Array.isArray(report?.files) ? report.files : []; - let out = ""; - for (const file of files) { - const name = typeof file?.name === "string" ? file.name.trim() : ""; - const lines = Array.isArray(file?.line_coverage) ? file.line_coverage : []; - if (!name || lines.length === 0) { - continue; - } - let records = ""; - for (const entry of lines) { - if (!Array.isArray(entry) || entry.length < 2) { - continue; - } - const [line, status] = entry; - if (!Number.isInteger(line) || line <= 0) { - continue; - } - if (status === 0 || status === 2) { - records += `DA:${line},1\n`; - } else if (status === 1) { - records += `DA:${line},0\n`; - } - } - if (!records) { - continue; - } - out += `SF:${name}\n${records}end_of_record\n`; - } - return out || null; -} - -/** - * Whether a failed `mehen diff` invocation is attributable to one of - * the *base-side* coverage reports: mehen's coverage setup errors name - * the offending report path on stderr ("cannot read coverage report - * `PATH`", "failed to parse coverage report `PATH`", "unrecognized - * coverage report format: `PATH`"). Matching on the base paths keeps - * the degradation retry away from unrelated failures — including a - * corrupt *head* report, which is the caller's own fresh artifact and - * must keep failing loudly on its own step. - */ -function isBaseCoverageFailure(error, baseArgs) { - const stderr = typeof error?.stderr === "string" ? error.stderr : ""; - if (!stderr || !Array.isArray(baseArgs) || baseArgs.length === 0) { - return false; - } - return baseArgs.some((arg) => { - const reportPath = String(arg).replace(/^--base-coverage=/, ""); - return reportPath.length > 0 && stderr.includes(reportPath); - }); -} - -/** - * Pick the workflow artifact holding the base revision's coverage - * reports: non-expired, produced by a run whose head SHA is exactly - * the PR base SHA. Several runs can produce the same-named artifact - * for one SHA (re-runs, multiple workflows) — the newest upload wins. - */ -function pickBaseArtifact(artifacts, baseSha) { - if (!Array.isArray(artifacts) || !baseSha) { - return null; - } - const candidates = artifacts.filter( - (artifact) => - artifact && - artifact.expired !== true && - artifact.workflow_run?.head_sha === baseSha, - ); - if (candidates.length === 0) { - return null; - } - candidates.sort( - (a, b) => new Date(b.created_at ?? 0) - new Date(a.created_at ?? 0), - ); - return candidates[0]; -} - -/** - * Fetch base-revision coverage reports from a workflow artifact - * (rung 2). Returns the extracted file paths, or null (never throws) - * so the ladder degrades: missing artifact, expired entry, oversized - * archive, download or extraction failure all fall through to the - * next source. Needs `actions: read` on the token; a 403 therefore - * degrades with a permission hint rather than failing the action. - */ -async function fetchArtifactBaseReports(context, artifactName) { - const token = input("GITHUB_TOKEN").trim() || process.env.GITHUB_TOKEN || ""; - const [owner, repo] = context.repository.split("/"); - if (!owner || !repo || !token) { - return null; - } - // Listings are newest-first across all runs, so the base SHA's - // artifact can sit past the first page in a busy repository; the - // first page containing a match holds the newest match overall. - // The page budget keeps a pathological history from stalling the - // rung — beyond it, the lower rungs serve better than a long walk. - let artifact = null; - try { - for (let page = 1; page <= ARTIFACT_MAX_PAGES; page += 1) { - const listing = await githubRequest( - "GET", - `/repos/${owner}/${repo}/actions/artifacts?name=${encodeURIComponent(artifactName)}&per_page=100&page=${page}`, - token, - undefined, - { timeoutMs: ARTIFACT_DOWNLOAD_TIMEOUT_MS }, - ); - const artifacts = Array.isArray(listing?.artifacts) - ? listing.artifacts - : []; - artifact = pickBaseArtifact(artifacts, context.baseSha); - if (artifact || artifacts.length < 100) { - break; - } - } - } catch (error) { - const hint = String(error.message).includes(" 403 ") - ? " (does the job grant `actions: read`?)" - : ""; - console.warn( - `artifact lookup for '${artifactName}' failed${hint}: ${error.message}; trying the next base-coverage source.`, - ); - return null; - } - if (!artifact) { - console.log( - `no '${artifactName}' artifact found for base ${context.baseSha}; trying the next base-coverage source.`, - ); - return null; - } - const size = Number(artifact.size_in_bytes); - if (Number.isFinite(size) && size > ARTIFACT_MAX_BYTES) { - console.warn( - `artifact '${artifactName}' for base ${context.baseSha} is ${size} bytes (cap ${ARTIFACT_MAX_BYTES}); trying the next base-coverage source.`, - ); - return null; - } - try { - // fetch follows the 302 to blob storage automatically; undici - // drops the Authorization header on the cross-origin redirect, - // which is exactly what the signed blob URL expects. The abort - // signal turns a stalled blob transfer into a ladder degradation - // instead of a job-timeout hang. - const response = await fetch( - `https://api.github.com/repos/${owner}/${repo}/actions/artifacts/${artifact.id}/zip`, - { - headers: { - Accept: "application/vnd.github+json", - Authorization: `Bearer ${token}`, - "User-Agent": "mehen-action", - "X-GitHub-Api-Version": "2022-11-28", - }, - signal: AbortSignal.timeout(ARTIFACT_DOWNLOAD_TIMEOUT_MS), - }, - ); - if (!response.ok) { - console.warn( - `artifact download for '${artifactName}' responded ${response.status}; trying the next base-coverage source.`, - ); - return null; - } - // The metadata check above trusts the API; these two enforce the - // cap on what actually arrives (a missing size_in_bytes field or - // a chunked response must not become an unbounded read). - const declared = Number(response.headers.get("content-length")); - if (Number.isFinite(declared) && declared > ARTIFACT_MAX_BYTES) { - console.warn( - `artifact '${artifactName}' download declares ${declared} bytes (cap ${ARTIFACT_MAX_BYTES}); trying the next base-coverage source.`, - ); - return null; - } - const buffer = Buffer.from(await response.arrayBuffer()); - if (buffer.length > ARTIFACT_MAX_BYTES) { - console.warn( - `artifact '${artifactName}' download is ${buffer.length} bytes (cap ${ARTIFACT_MAX_BYTES}); trying the next base-coverage source.`, - ); - return null; - } - const dir = path.join( - process.env.RUNNER_TEMP || os.tmpdir(), - "mehen-artifact-base", - ); - fs.mkdirSync(dir, { recursive: true }); - const extracted = extractZip(buffer, dir, ARTIFACT_MAX_BYTES); - if (extracted.length === 0) { - console.log( - `artifact '${artifactName}' for base ${context.baseSha} contained no files; trying the next base-coverage source.`, - ); - return null; - } - return extracted; - } catch (error) { - console.warn( - `artifact retrieval for '${artifactName}' failed (${error.message}); trying the next base-coverage source.`, - ); - return null; - } -} - -/** - * Extract a standard ZIP archive (the format GitHub serves for - * workflow artifacts) into `destDir`, returning the extracted file - * paths sorted. Zero-dependency by design: entries are read from the - * central directory (whose sizes are authoritative even when a local - * header deferred them to a data descriptor) and inflated with - * node:zlib. Supports the two methods artifact zips use — stored (0) - * and deflate (8); no zip64 (the artifact size cap is far below 4 - * GiB). Entries that would escape `destDir` (zip-slip) are rejected - * loudly rather than skipped, and `maxTotalBytes` bounds the - * *decompressed* output — checked against the declared sizes up - * front and enforced per entry via zlib's maxOutputLength, so an - * archive whose metadata lies (a zip bomb) aborts mid-inflate - * instead of exhausting the runner. A hostile archive is not a - * degradation case but an integrity failure. - */ -function extractZip(buffer, destDir, maxTotalBytes = Infinity) { - const EOCD_SIG = 0x06054b50; - const CENTRAL_SIG = 0x02014b50; - const LOCAL_SIG = 0x04034b50; - const eocdFloor = Math.max(0, buffer.length - 22 - 0xffff); - let eocd = -1; - for (let i = buffer.length - 22; i >= eocdFloor; i -= 1) { - if (buffer.readUInt32LE(i) === EOCD_SIG) { - eocd = i; - break; - } - } - if (eocd < 0) { - throw new Error("not a zip archive (no end-of-central-directory record)"); - } - const entryCount = buffer.readUInt16LE(eocd + 10); - let cursor = buffer.readUInt32LE(eocd + 16); - const extracted = []; - let declaredTotal = 0; - let writtenTotal = 0; - for (let i = 0; i < entryCount; i += 1) { - if (buffer.readUInt32LE(cursor) !== CENTRAL_SIG) { - throw new Error("corrupt zip archive (central directory signature)"); - } - const method = buffer.readUInt16LE(cursor + 10); - const compressedSize = buffer.readUInt32LE(cursor + 20); - const uncompressedSize = buffer.readUInt32LE(cursor + 24); - const nameLength = buffer.readUInt16LE(cursor + 28); - const extraLength = buffer.readUInt16LE(cursor + 30); - const commentLength = buffer.readUInt16LE(cursor + 32); - const localOffset = buffer.readUInt32LE(cursor + 42); - const name = buffer.toString("utf8", cursor + 46, cursor + 46 + nameLength); - cursor = cursor + 46 + nameLength + extraLength + commentLength; - if (name.endsWith("/")) { - continue; // directory entry - } - declaredTotal += uncompressedSize; - if (declaredTotal > maxTotalBytes) { - throw new Error( - `zip archive declares more than ${maxTotalBytes} decompressed bytes`, - ); - } - const destPath = path.join(destDir, name); - const relative = path.relative(destDir, destPath); - if ( - name.startsWith("/") || - relative.startsWith("..") || - path.isAbsolute(relative) - ) { - throw new Error(`zip entry escapes the extraction directory: ${name}`); - } - if (buffer.readUInt32LE(localOffset) !== LOCAL_SIG) { - throw new Error("corrupt zip archive (local header signature)"); - } - const localNameLength = buffer.readUInt16LE(localOffset + 26); - const localExtraLength = buffer.readUInt16LE(localOffset + 28); - const dataStart = localOffset + 30 + localNameLength + localExtraLength; - const data = buffer.subarray(dataStart, dataStart + compressedSize); - let content; - if (method === 0) { - content = data; - } else if (method === 8) { - // The declared sizes above are metadata a hostile archive can - // understate; the inflate budget is the enforcement on actual - // output. zlib validates maxOutputLength against - // buffer.kMaxLength — 4 GiB on Node 24 — so the unbounded case - // omits the option entirely and finite budgets are clamped - // below that floor (clamping down only tightens enforcement). - if (maxTotalBytes === Infinity) { - content = zlib.inflateRawSync(data); - } else { - const budget = Math.min( - 0xffffffff, - Math.max(1, maxTotalBytes - writtenTotal), - ); - content = zlib.inflateRawSync(data, { maxOutputLength: budget }); - } - } else { - throw new Error(`unsupported zip compression method ${method}: ${name}`); - } - writtenTotal += content.length; - if (writtenTotal > maxTotalBytes) { - throw new Error( - `zip archive expands past ${maxTotalBytes} decompressed bytes`, - ); - } - fs.mkdirSync(path.dirname(destPath), { recursive: true }); - fs.writeFileSync(destPath, content); - extracted.push(destPath); - } - return extracted.sort(); -} - -/** Every file under `dir`, recursively, sorted for determinism. */ -function listFilesRecursively(dir) { - if (!dir || !fs.existsSync(dir)) { - return []; - } - const out = []; - const stack = [dir]; - while (stack.length > 0) { - const current = stack.pop(); - for (const entry of fs.readdirSync(current, { withFileTypes: true })) { - const full = path.join(current, entry.name); - if (entry.isDirectory()) { - stack.push(full); - } else if (entry.isFile()) { - out.push(full); - } - } - } - return out.sort(); -} - -function sleep(ms) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); -} - -function prepareMehen() { - const method = input("INSTALL_METHOD", "npm").trim().toLowerCase(); - - if (method === "npm") { - const version = input("VERSION").trim(); - const pkg = version ? `mehen@${version}` : "mehen"; - return { command: "npx", args: ["-y", pkg] }; - } - - if (method === "cargo") { - const actionPath = process.env.GITHUB_ACTION_PATH || process.cwd(); - // The repo root is a virtual workspace manifest (no `[package]`), - // so `cargo install --path ` fails with "found a virtual - // manifest … instead of a package manifest". `cargo install - // --path ` works against the `mehen` package's directory. - const cratePath = path.join(actionPath, "crates", "mehen-cli"); - const root = path.join( - process.env.RUNNER_TEMP || os.tmpdir(), - "mehen-action-cli", - ); - const bin = process.platform === "win32" ? "mehen.exe" : "mehen"; - const binPath = path.join(root, "bin", bin); - - if (!fs.existsSync(binPath)) { - fs.rmSync(root, { recursive: true, force: true }); - runCommand( - "cargo", - ["install", "--path", cratePath, "--locked", "--root", root], - { - cwd: actionPath, - stdio: "inherit", - }, - ); - } else { - console.log(`Using cached mehen binary at ${binPath}.`); - } - - return { command: binPath, args: [] }; - } - - if (method === "path") { - return { command: input("PATH", "mehen").trim() || "mehen", args: [] }; - } - - throw new Error( - `Unsupported mehen install-method '${method}'. Use npm, cargo, or path.`, - ); -} - -function detectMehenVersion(cli) { - const result = spawnSync( - cli.command, - [...cli.args, "--version", "--json"], - { - encoding: "utf8", - maxBuffer: 1024 * 1024, - }, - ); - if (result.error || result.status !== 0) { - return ""; - } - return parseVersionOutput(result.stdout); -} - -function parseVersionOutput(stdout) { - const text = String(stdout ?? "").trim(); - if (!text) { - return ""; - } - try { - const payload = JSON.parse(text); - if (payload && typeof payload.version === "string") { - return payload.version.trim(); - } - } catch { - // Fall through to return "" so older mehen builds without - // `--version --json` don't break the action. - } - return ""; -} - -function runMehen(cli, args, options = {}) { - console.log(`Running: ${[cli.command, ...cli.args, ...args].join(" ")}`); - const result = spawnSync(cli.command, [...cli.args, ...args], { - encoding: "utf8", - maxBuffer: 64 * 1024 * 1024, - }); - - if (result.error) { - throw result.error; - } - if (result.status !== 0) { - // A nonzero exit that still produced the requested report is a - // quality-gate failure (`mehen.toml` thresholds exit 1, `--fail-on` - // documentation gates exit 2), not a broken run: surface the - // stderr report in the log, keep the stdout report so the PR - // comment and outputs still land, and let the caller defer the - // failure. Everything else keeps failing fast. - if ( - typeof options.acceptGateOutput === "function" && - options.acceptGateOutput(result.stdout) - ) { - if (result.stderr) { - process.stderr.write(result.stderr); - } - return { ...result, gateStatus: result.status }; - } - if (result.stdout) { - console.error(result.stdout); - } - if (result.stderr) { - console.error(result.stderr); - } - const error = new Error(`mehen exited with status ${result.status}`); - // Attach the streams so callers can classify the failure (e.g. - // the base-coverage degradation retry in `main`). - error.stdout = result.stdout; - error.stderr = result.stderr; - throw error; - } - if (result.stderr) { - process.stderr.write(result.stderr); - } - return result; -} - -/** - * Whether a failing `mehen diff --output-format json` invocation is a - * configured quality-gate exit: the payload must be complete AND carry - * the explicit `threshold_violations` signal the CLI emits only when a - * `mehen.toml` gate fired. An analysis failure also exits 1 with - * well-formed JSON but without that key — it must keep failing fast - * instead of publishing a partial report under the wrong reason. - */ -function isGateFailureReport(stdout) { - try { - const parsed = JSON.parse(typeof stdout === "string" ? stdout : ""); - return Boolean( - parsed && - Array.isArray(parsed.source_code) && - Array.isArray(parsed.threshold_violations) && - parsed.threshold_violations.length > 0, - ); - } catch { - return false; - } -} - -function runCommand(command, args, options = {}) { - const result = spawnSync(command, args, { - encoding: "utf8", - ...options, - }); - if (result.error) { - throw result.error; - } - if (result.status !== 0) { - throw new Error( - `${command} ${args.join(" ")} exited with status ${result.status}`, - ); - } - return result; -} - -/** - * Whether the JSON diff payload carries a documentation section — the - * signal that a second (markdown-format) invocation would actually - * yield a `` block worth extracting. - */ -function diffJsonHasDocs(stdout) { - try { - const parsed = JSON.parse(typeof stdout === "string" ? stdout : ""); - return Boolean( - parsed && Array.isArray(parsed.markdown) && parsed.markdown.length > 0, - ); - } catch { - return false; - } -} - -/** - * Re-run `mehen diff --output-format markdown` with the same scope as - * the JSON run, then carve out the `` section per - * §39.1. Returns null when the section is absent (no Markdown files in - * scope) or when the CLI fails — callers treat null as "just publish - * the source-code section". - * - * The rerun is forced history-free: the docs section comes from the - * documentation pipeline (fixed `markdown.*` columns, never history), - * and this run's source-code section is discarded — without the - * override, the default history columns would make the rerun pay for - * two more full repository walks that feed nothing. - */ -function fetchMarkdownDocsSection(cli, baseArgs) { - const mdArgs = [...baseArgs]; - const fmtIdx = mdArgs.indexOf("--output-format"); - if (fmtIdx >= 0) { - mdArgs[fmtIdx + 1] = "markdown"; - } - const metricsIdx = mdArgs.indexOf("--metrics"); - if (metricsIdx >= 0) { - mdArgs[metricsIdx + 1] = "cognitive"; - } else { - mdArgs.push("--metrics", "cognitive"); - } - let mdResult; - try { - // The rerun trips the same configured quality gates as the main - // diff (exit 1 with the markdown report on stdout); accept any - // non-empty output so the docs section still reaches the comment. - mdResult = runMehen(cli, mdArgs, { - acceptGateOutput: (stdout) => - typeof stdout === "string" && stdout.trim().length > 0, - }); - } catch (error) { - console.warn( - `mehen diff --output-format markdown failed (docs section will be omitted): ${error.message}`, - ); - return null; - } - return extractMarkdownDocsSection(mdResult?.stdout ?? ""); -} - -/** - * Pure extractor for the `` section so it can be - * unit-tested without spawning the CLI. Treats any of the following as - * "no docs section" (returns null): - * - input is null, undefined, or whitespace-only, - * - the anchor is absent, - * - the slice starting at the anchor contains nothing beyond the - * anchor itself (e.g. truncated/partial CLI output). - */ -function extractMarkdownDocsSection(stdout) { - const body = typeof stdout === "string" ? stdout : ""; - if (!body.trim()) { - return null; - } - const anchor = ""; - const start = body.indexOf(anchor); - if (start < 0) { - return null; - } - // Anchor through end-of-output is the docs section — §39.1 places - // the anchor at the start of the section and the CLI never emits - // anything after it. - const section = body.slice(start).trim(); - // An anchor-only output (no headline/table/callouts after it) is - // effectively empty — treat as missing rather than publishing a bare - // comment marker into the sticky PR comment. - if (section === anchor) { - return null; - } - return section; -} - -function parseDiffJson(stdout) { - try { - const parsed = JSON.parse(stdout); - // Phase F (§39) introduced the `{ source_code: [...], markdown?: ... }` - // shape so a single `mehen diff --output-format json` run can carry - // both sections. Accept either the new object form or the legacy - // top-level array for backward compatibility with older mehen CLIs. - if (Array.isArray(parsed)) { - return parsed; - } - if (parsed && Array.isArray(parsed.source_code)) { - return parsed.source_code; - } - throw new Error( - "mehen diff JSON output was not an array or {source_code: [...]} object", - ); - } catch (error) { - throw new Error( - `Failed to parse mehen diff JSON: ${error.message}\n${stdout}`, - ); - } -} - -function readGithubContext() { - let payload = {}; - const eventPath = process.env.GITHUB_EVENT_PATH; - if (eventPath && fs.existsSync(eventPath)) { - payload = JSON.parse(fs.readFileSync(eventPath, "utf8")); - } - - const pullRequest = payload.pull_request; - return { - eventName: process.env.GITHUB_EVENT_NAME || "", - repository: process.env.GITHUB_REPOSITORY || "", - sha: pullRequest?.head?.sha || process.env.GITHUB_SHA || "", - baseSha: pullRequest?.base?.sha || "", - baseLabel: pullRequest?.base?.ref || input("FROM").trim() || "base", - prNumber: pullRequest?.number || payload.number || null, - token: input("GITHUB_TOKEN").trim() || process.env.GITHUB_TOKEN || "", - }; -} - -/** - * The `threshold_violations` array a gate-failing `mehen diff` embeds - * in its JSON report (absolute `mehen.toml` breaches at head — see the - * Configuration docs). Empty for passing runs, older CLIs, and - * non-JSON output. - */ -function parseGateViolations(stdout) { - try { - const parsed = JSON.parse(typeof stdout === "string" ? stdout : ""); - return parsed && Array.isArray(parsed.threshold_violations) - ? parsed.threshold_violations - : []; - } catch { - return []; - } -} - -function renderMarkdown( - diffs, - context, - thresholds, - violations, - version = "", - gateViolations = [], - coverageNote = null, -) { - const title = input("COMMENT_TITLE", DEFAULT_TITLE).trim() || DEFAULT_TITLE; - const scope = - context.eventName === "pull_request" - ? ` (this PR vs \`${context.baseLabel}\`)` - : ""; - let body = `${MARKER}\n${title}${scope}\n\n`; - - let sawNotApplicable = false; - - if (diffs.length === 0) { - body += "No metric changes detected.\n"; - } else { - const metrics = unionMetricColumns(diffs); - body += "| File |"; - for (const metric of metrics) { - body += ` ${escapeCell(metric.label || metric.name)} |`; - } - body += "\n|---|"; - for (const _metric of metrics) { - body += "---:|"; - } - body += "\n"; - - for (const file of diffs) { - body += `| ${renderFile(file.path, context)} |`; - const row = alignFileMetrics(file.metrics || [], metrics); - for (const metric of row) { - if (isNotApplicable(metric)) { - sawNotApplicable = true; - } - body += ` ${escapeCell(formatMetricCell(metric, context.baseLabel))} |`; - } - body += "\n"; - } - } - - if (thresholds.size > 0) { - body += "\n### Thresholds\n\n"; - if (violations.length === 0) { - body += "All configured thresholds passed.\n"; - } else { - body += "| File | Metric | Delta | Limit |\n"; - body += "|---|---|---:|---:|\n"; - for (const violation of violations) { - body += `| ${renderFile(violation.path, context)} | ${escapeCell(violation.label)} | ${formatSigned(violation.delta)} | ${formatNumber(violation.limit)} |\n`; - } - } - } - - // Absolute `mehen.toml` breaches at head: the diff table above may - // not name these files at all (an unchanged-but-over-limit metric - // is dropped as an unchanged row), so the failing gate must be - // spelled out here or the comment would say "no changes" while the - // workflow step fails. - if (gateViolations.length > 0) { - body += "\n### Repository thresholds (mehen.toml)\n\n"; - body += "| File | Metric | Value | Limit | Set by |\n"; - body += "|---|---|---:|---:|---|\n"; - for (const violation of gateViolations) { - const bound = violation.polarity === "higher_is_better" ? "min" : "max"; - body += `| ${renderFile(violation.path, context)} | ${escapeCell(violation.metric)} | ${formatExactNumber(violation.value)} | ${bound} ${formatExactNumber(violation.limit)} | ${escapeCell(violation.source_table)} |\n`; - } - } - - if (sawNotApplicable) { - body += - "\n> `—` indicates the metric does not apply to the file's language.\n"; - } - - // Base-coverage source disclosure (issue #248): every rung of the - // retrieval ladder is stated — never silently. - if (coverageNote) { - body += `\n> ${coverageNote}\n`; - } - - body += `\n${renderFooter(version)}\n`; - - return body; -} - -function renderFooter(version) { - const trimmed = String(version ?? "").trim(); - const versionSuffix = trimmed ? ` v${trimmed}` : ""; - return `${FOOTER_PREFIX}${versionSuffix} ${FOOTER_SUFFIX}`; -} - -function renderFile(filePath, context) { - const escaped = escapeCell(filePath); - if (!context.repository || !context.sha) { - return escaped; - } - const urlPath = String(filePath) - .split("/") - .map((part) => encodeURIComponent(part)) - .join("/"); - return `[${escaped}](https://github.com/${context.repository}/blob/${context.sha}/${urlPath})`; -} - -// Build the master header as the union of metrics across all files, preserving -// first-seen order. Using `diffs[0].metrics` alone would silently drop any -// metric that only appears in later files (e.g. when the first file omits it -// under the language-applicability rules). -function unionMetricColumns(diffs) { - const seen = new Map(); - for (const file of diffs) { - for (const metric of file.metrics || []) { - const key = metric && (metric.name || metric.label); - if (key && !seen.has(key)) { - seen.set(key, metric); - } - } - } - return [...seen.values()]; -} - -// Normalize a file's metric list against the header's master list so that a -// file which omits a metric still produces a cell in the row. Missing metrics -// are filled with a placeholder that isNotApplicable() recognizes, so they -// render as `—`. -function alignFileMetrics(fileMetrics, headerMetrics) { - const byKey = new Map(); - for (const m of fileMetrics) { - if (m && (m.name || m.label)) { - byKey.set(m.name || m.label, m); - } - } - return headerMetrics.map((h) => { - const key = h.name || h.label; - const found = byKey.get(key); - if (found) { - return found; - } - return { - name: h.name, - label: h.label, - not_applicable: true, - current: null, - baseline: null, - delta: 0, - polarity: h.polarity, - }; - }); -} - -function isNotApplicable(metric) { - if (!metric) { - return true; - } - if (metric.not_applicable === true) { - return true; - } - const current = metric.current; - const baseline = metric.baseline; - const missing = (v) => v === null || v === undefined; - return missing(current) && missing(baseline); -} - -function formatMetricCell(metric, baseLabel) { - if (isNotApplicable(metric)) { - return "—"; - } - // A side flagged unavailable carries a numeric `0.0` placeholder - // that is *not* a measurement (static analysis was impossible for - // that side — undecodable content, blocking parse diagnostic, or a - // feature-gated analyzer). Render `n/a` and claim no trend, exactly - // like the native CLI table. - const currentUnavailable = metric.current_unavailable === true; - const baselineUnavailable = metric.baseline_unavailable === true; - const current = currentUnavailable ? "n/a" : formatNumber(metric.current); - if (metric.is_new) { - return `${current} \u{1F195}`; - } - if (metric.is_deleted) { - if (baselineUnavailable) { - return "0 (was: n/a)"; - } - return `0 (was: ${formatNumber(metric.baseline)}) ${trendEmoji(metric)}`; - } - if (currentUnavailable || baselineUnavailable) { - if (currentUnavailable && baselineUnavailable) { - return "n/a"; - } - const baseline = baselineUnavailable ? "n/a" : formatNumber(metric.baseline); - return `${current} (${baseLabel}: ${baseline})`; - } - if (Number(metric.delta) === 0) { - return `${current} \u{26AA}`; - } - return `${current} (${baseLabel}: ${formatNumber(metric.baseline)}) ${trendEmoji(metric)}`; -} - -function trendEmoji(metric) { - const delta = Number(metric.delta); - if (delta === 0) { - return "\u{26AA}"; - } - const polarity = metric.polarity || inferPolarity(metric.name); - if (polarity === HIGHER_IS_BETTER) { - return delta > 0 ? "\u{1F7E2}" : "\u{1F534}"; - } - return delta > 0 ? "\u{1F534}" : "\u{1F7E2}"; -} - -function collectThresholdViolations(diffs, thresholds) { - const violations = []; - if (thresholds.size === 0) { - return violations; - } - - for (const file of diffs) { - for (const metric of file.metrics || []) { - if (isNotApplicable(metric)) { - continue; - } - // An unavailable side means the delta is a placeholder, not a - // measured change — never a threshold violation. - if (metric.current_unavailable === true || metric.baseline_unavailable === true) { - continue; - } - const key = canonicalMetricName(metric.name || metric.label || ""); - const labelKey = canonicalMetricName(metric.label || metric.name || ""); - const limit = thresholds.get(key) ?? thresholds.get(labelKey); - if (limit === undefined) { - continue; - } - - const adverseDelta = getAdverseDelta(metric); - if (adverseDelta > limit) { - violations.push({ - path: file.path, - label: metric.label || metric.name, - delta: Number(metric.delta), - limit, - }); - } - } - } - - return violations; -} - -function getAdverseDelta(metric) { - const delta = Number(metric.delta); - const polarity = metric.polarity || inferPolarity(metric.name); - if (polarity === HIGHER_IS_BETTER) { - return delta < 0 ? Math.abs(delta) : 0; - } - return delta > 0 ? delta : 0; -} - -function parseThresholds(value) { - const thresholds = new Map(); - for (const raw of parseList(value)) { - const match = raw.match( - /^([^:=<>]+)\s*(?:<=|=|:)\s*([0-9]+(?:\.[0-9]+)?)$/, - ); - if (!match) { - throw new Error(`Invalid threshold '${raw}'. Expected metric=number.`); - } - thresholds.set(canonicalMetricName(match[1]), Number(match[2])); - } - return thresholds; -} - -function canonicalMetricName(name) { - const raw = String(name) - .replace(/[\s_-]+/g, "") - .replace(/\.+/g, "."); - // `halstead.n1`/`halstead.N1` and `halstead.n2`/`halstead.N2` are - // case-distinct published keys (distinct vs total operator/operand - // counts): lowercasing would collapse a threshold onto the wrong - // measurement, so their case is preserved verbatim. - if (/^halstead\.[nN][12]$/.test(raw)) { - return raw; - } - const normalized = raw.toLowerCase(); - return METRIC_ALIASES.get(normalized) || normalized; -} - -function inferPolarity(name) { - const canonical = canonicalMetricName(name); - return canonical === "mi" || canonical.startsWith("mi.") - ? HIGHER_IS_BETTER - : LOWER_IS_BETTER; -} - -function formatNumber(value) { - const number = Number(value); - if (!Number.isFinite(number)) { - return String(value); - } - return Number.isInteger(number) ? String(number) : number.toFixed(2); -} - -/** - * Shortest exact representation for repository-gate values: rounding - * both sides of a close crossing to two decimals would render an - * apparently impossible failure (`0.50` versus `max 0.50` for a - * `0.504` value over a `0.503` limit). - */ -function formatExactNumber(value) { - const number = Number(value); - return Number.isFinite(number) ? String(number) : String(value); -} - -function formatSigned(value) { - const number = Number(value); - if (!Number.isFinite(number)) { - return String(value); - } - const formatted = formatNumber(number); - return number > 0 ? `+${formatted}` : formatted; -} - -function escapeCell(value) { - return String(value).replace(/\|/g, "\\|").replace(/\n/g, " "); -} - -function writeStepSummary(markdown) { - const summary = process.env.GITHUB_STEP_SUMMARY; - if (summary) { - fs.appendFileSync(summary, `${markdown}\n`, "utf8"); - } -} - -async function maybeComment(markdown, context) { - if (!boolInput("COMMENT", true) || context.eventName !== "pull_request") { - return; - } - if (!context.repository || !context.prNumber) { - console.log( - "Skipping mehen PR comment because pull request context is unavailable.", - ); - return; - } - if (!context.token) { - console.log( - "Skipping mehen PR comment because github-token is unavailable.", - ); - return; - } - - const [owner, repo] = context.repository.split("/"); - const comments = await listComments( - owner, - repo, - context.prNumber, - context.token, - ); - const title = input("COMMENT_TITLE", DEFAULT_TITLE).trim() || DEFAULT_TITLE; - const previous = comments.find( - (comment) => - comment.body?.includes(MARKER) || comment.body?.startsWith(title), - ); - - if (previous) { - await githubRequest( - "PATCH", - `/repos/${owner}/${repo}/issues/comments/${previous.id}`, - context.token, - { body: markdown }, - ); - console.log(`Updated mehen metrics comment ${previous.id}.`); - } else { - await githubRequest( - "POST", - `/repos/${owner}/${repo}/issues/${context.prNumber}/comments`, - context.token, - { body: markdown }, - ); - console.log("Created mehen metrics comment."); - } -} - -async function listComments(owner, repo, issueNumber, token) { - const comments = []; - for (let page = 1; ; page += 1) { - const batch = await githubRequest( - "GET", - `/repos/${owner}/${repo}/issues/${issueNumber}/comments?per_page=100&page=${page}`, - token, - ); - comments.push(...batch); - if (batch.length < 100) { - return comments; - } - } -} - -async function githubRequest(method, apiPath, token, body = undefined, options = {}) { - const response = await fetch(`https://api.github.com${apiPath}`, { - method, - headers: { - Accept: "application/vnd.github+json", - Authorization: `Bearer ${token}`, - "User-Agent": "mehen-action", - "X-GitHub-Api-Version": "2022-11-28", - }, - body: body === undefined ? undefined : JSON.stringify(body), - // Callers on a degradation path (the artifact rung) bound their - // requests so a stalled API call becomes a fallback, not a hang. - signal: options.timeoutMs ? AbortSignal.timeout(options.timeoutMs) : undefined, - }); - - if (!response.ok) { - const text = await response.text(); - throw new Error( - `GitHub API ${method} ${apiPath} failed: ${response.status} ${text}`, - ); - } - - if (response.status === 204) { - return null; - } - - return response.json(); -} - -function setOutput(name, value) { - const output = process.env.GITHUB_OUTPUT; - if (output) { - fs.appendFileSync(output, `${name}=${value}\n`, "utf8"); - } -} - -export { - DEFAULT_TEST_EXCLUDES, - alignFileMetrics, - buildDiffArgs, - canonicalMetricName, - codecovToLcov, - collectThresholdViolations, - diffJsonHasDocs, - extractMarkdownDocsSection, - extractZip, - formatMetricCell, - inferPolarity, - isBaseCoverageFailure, - isGateFailureReport, - isNotApplicable, - listFilesRecursively, - parseGateViolations, - parseList, - parseThresholds, - parseVersionOutput, - pickBaseArtifact, - renderFooter, - unionMetricColumns, -}; diff --git a/scripts/github-action.test.mjs b/scripts/github-action.test.mjs deleted file mode 100644 index 8d228c31..00000000 --- a/scripts/github-action.test.mjs +++ /dev/null @@ -1,807 +0,0 @@ -import assert from "node:assert/strict"; -import fs from "node:fs"; -import os from "node:os"; -import path from "node:path"; -import test from "node:test"; -import zlib from "node:zlib"; - -import { - DEFAULT_TEST_EXCLUDES, - alignFileMetrics, - buildDiffArgs, - canonicalMetricName, - codecovToLcov, - collectThresholdViolations, - diffJsonHasDocs, - extractMarkdownDocsSection, - extractZip, - formatMetricCell, - inferPolarity, - isBaseCoverageFailure, - isGateFailureReport, - isNotApplicable, - listFilesRecursively, - parseGateViolations, - parseList, - parseThresholds, - parseVersionOutput, - pickBaseArtifact, - renderFooter, - unionMetricColumns, -} from "./github-action.mjs"; - -test("canonicalMetricName preserves case-distinct halstead count keys", () => { - // `n1`/`N1` (and `n2`/`N2`) are distinct published measurements — - // distinct vs total operator/operand counts; lowercasing would - // gate the wrong one. - assert.equal(canonicalMetricName("halstead.N1"), "halstead.N1"); - assert.equal(canonicalMetricName("halstead.n1"), "halstead.n1"); - assert.equal(canonicalMetricName("halstead.N2"), "halstead.N2"); - assert.equal(canonicalMetricName("halstead.n2"), "halstead.n2"); - // Everything else keeps the legacy case-insensitive aliasing. - assert.equal(canonicalMetricName("Cognitive"), "cognitive"); - assert.equal(canonicalMetricName("loc"), "loc.lloc"); - assert.equal(canonicalMetricName("nom"), "nom.functions"); -}); - -test("parseGateViolations extracts the embedded gate breaches", () => { - const payload = - '{"source_code": [], "threshold_violations": [{"path": "a.py", "metric": "cognitive", "value": 23, "limit": 15, "polarity": "higher_is_worse", "source_table": "languages.py.thresholds"}]}'; - const violations = parseGateViolations(payload); - assert.equal(violations.length, 1); - assert.equal(violations[0].metric, "cognitive"); - assert.equal(violations[0].source_table, "languages.py.thresholds"); -}); - -test("parseGateViolations is empty for passing runs and older CLIs", () => { - assert.deepEqual(parseGateViolations('{"source_code": []}'), []); - assert.deepEqual(parseGateViolations("[]"), []); - assert.deepEqual(parseGateViolations("not json"), []); - assert.deepEqual(parseGateViolations(undefined), []); -}); - -test("isGateFailureReport requires the explicit threshold_violations signal", () => { - assert.equal( - isGateFailureReport( - '{"source_code": [], "threshold_violations": [{"path": "a.py", "metric": "cognitive"}]}', - ), - true, - ); - assert.equal( - isGateFailureReport( - '{"source_code": [{"path": "a.py"}], "markdown": [], "threshold_violations": [{}]}', - ), - true, - ); -}); - -test("isGateFailureReport rejects reports without a fired gate", () => { - // An analysis failure also exits 1 with well-formed JSON — without - // the threshold_violations key it must keep failing fast. - assert.equal(isGateFailureReport('{"source_code": [], "markdown": []}'), false); - assert.equal(isGateFailureReport('{"source_code": [{"path": "a.py"}]}'), false); - assert.equal( - isGateFailureReport('{"source_code": [], "threshold_violations": []}'), - false, - ); -}); - -test("isGateFailureReport rejects partial or non-JSON output", () => { - // A setup/IO failure leaves stdout empty or truncated — that must - // keep failing fast instead of being treated as a quality gate. - assert.equal(isGateFailureReport(""), false); - assert.equal(isGateFailureReport("error: not json"), false); - assert.equal(isGateFailureReport('{"source_code": '), false); - assert.equal(isGateFailureReport('{"markdown": []}'), false); - assert.equal(isGateFailureReport(undefined), false); -}); - -test("parseList uses explicit separators only", () => { - assert.deepEqual(parseList("src"), ["src"]); - assert.deepEqual(parseList("apps/web src"), ["apps/web src"]); - assert.deepEqual(parseList("apps/web\ncrates/api,tools;fixtures/data"), [ - "apps/web", - "crates/api", - "tools", - "fixtures/data", - ]); -}); - -test("parseList preserves paths and thresholds containing spaces", () => { - assert.deepEqual(parseList("my folder"), ["my folder"]); - assert.deepEqual(parseList("cyclomatic = 5"), ["cyclomatic = 5"]); -}); - -test("DEFAULT_TEST_EXCLUDES covers common test filename patterns", () => { - for (const pattern of [ - "**/*_test.go", - "**/__tests__/**", - "**/*.test.ts", - "**/*.spec.ts", - "**/tests/**", - ]) { - assert.ok( - DEFAULT_TEST_EXCLUDES.includes(pattern), - `expected DEFAULT_TEST_EXCLUDES to include ${pattern}`, - ); - } -}); - -test("parseThresholds accepts whitespace around operators", () => { - const thresholds = parseThresholds("cyclomatic = 5\ncognitive: 4,loc.lloc <= 120"); - - assert.equal(thresholds.get("cyclomatic"), 5); - assert.equal(thresholds.get("cognitive"), 4); - assert.equal(thresholds.get("loc.lloc"), 120); -}); - -test("diffJsonHasDocs detects the documentation section", () => { - // The docs rerun (a second full `mehen diff`) must only happen when - // the JSON payload actually carries a markdown section. - assert.equal(diffJsonHasDocs(JSON.stringify({ source_code: [] })), false); - assert.equal( - diffJsonHasDocs(JSON.stringify({ source_code: [], markdown: [] })), - false, - ); - assert.equal( - diffJsonHasDocs( - JSON.stringify({ source_code: [], markdown: [{ path: "README.md" }] }), - ), - true, - ); - assert.equal(diffJsonHasDocs("not json"), false); - assert.equal(diffJsonHasDocs(undefined), false); -}); - -test("isNotApplicable detects explicit flag and missing values", () => { - assert.equal(isNotApplicable({ not_applicable: true, current: 0, baseline: 0 }), true); - assert.equal(isNotApplicable({ current: null, baseline: null }), true); - assert.equal(isNotApplicable({ current: undefined, baseline: undefined }), true); - assert.equal(isNotApplicable({ current: 0, baseline: 0 }), false); - assert.equal(isNotApplicable({ current: 3, baseline: null }), false); -}); - -test("formatMetricCell renders em dash for non-applicable metrics", () => { - assert.equal(formatMetricCell({ not_applicable: true }, "main"), "—"); - assert.equal(formatMetricCell({ current: null, baseline: null }, "main"), "—"); -}); - -test("formatMetricCell still renders normal values", () => { - const metric = { - name: "cyclomatic", - label: "Cyclomatic", - current: 5, - baseline: 3, - delta: 2, - polarity: "lower-is-better", - }; - assert.ok(formatMetricCell(metric, "main").startsWith("5 (main: 3)")); -}); - -test("formatMetricCell honors unavailable sides without claiming a trend", () => { - // A side flagged unavailable carries a numeric 0.0 placeholder that - // must not render as a real zero (or a green "improvement"). - const base = { - name: "history.hotspot", - label: "Hotspot", - current: 0, - baseline: 12, - delta: 0, - polarity: "lower-is-better", - }; - assert.equal( - formatMetricCell({ ...base, current_unavailable: true }, "main"), - "n/a (main: 12)", - ); - assert.equal( - formatMetricCell({ ...base, baseline_unavailable: true }, "main"), - "0 (main: n/a)", - ); - assert.equal( - formatMetricCell( - { ...base, current_unavailable: true, baseline_unavailable: true }, - "main", - ), - "n/a", - ); - assert.equal( - formatMetricCell({ ...base, current_unavailable: true, is_new: true }, "main"), - "n/a \u{1F195}", - ); - assert.equal( - formatMetricCell( - { ...base, baseline_unavailable: true, is_deleted: true }, - "main", - ), - "0 (was: n/a)", - ); -}); - -test("collectThresholdViolations skips unavailable placeholder deltas", () => { - const diffs = [ - { - path: "broken.py", - metrics: [ - { - name: "cognitive", - label: "Cognitive", - current: 0, - baseline: 12, - delta: -12, - current_unavailable: true, - polarity: "lower-is-better", - }, - ], - }, - ]; - const thresholds = new Map([["cognitive", 1]]); - assert.deepEqual(collectThresholdViolations(diffs, thresholds), []); -}); - -test("unionMetricColumns includes metrics only present in later files", () => { - const diffs = [ - { - path: "foo.go", - metrics: [{ name: "cyclomatic", label: "Cyclomatic" }], - }, - { - path: "bar.py", - metrics: [ - { name: "cyclomatic", label: "Cyclomatic" }, - { name: "wmc", label: "WMC" }, - ], - }, - ]; - const columns = unionMetricColumns(diffs); - assert.deepEqual( - columns.map((c) => c.name), - ["cyclomatic", "wmc"], - ); -}); - -test("alignFileMetrics fills missing metrics with a non-applicable placeholder", () => { - const header = [ - { name: "cyclomatic", label: "Cyclomatic" }, - { name: "wmc", label: "WMC", polarity: "lower-is-better" }, - ]; - const fileMetrics = [ - { - name: "cyclomatic", - label: "Cyclomatic", - current: 5, - baseline: 3, - delta: 2, - polarity: "lower-is-better", - }, - ]; - const aligned = alignFileMetrics(fileMetrics, header); - assert.equal(aligned.length, 2); - assert.equal(aligned[0].current, 5); - assert.equal(isNotApplicable(aligned[1]), true); - assert.equal(aligned[1].name, "wmc"); -}); - -test("alignFileMetrics preserves existing metrics when present", () => { - const header = [{ name: "cyclomatic", label: "Cyclomatic" }]; - const source = { - name: "cyclomatic", - label: "Cyclomatic", - current: 1, - baseline: 1, - delta: 0, - }; - const aligned = alignFileMetrics([source], header); - assert.equal(aligned.length, 1); - assert.equal(aligned[0], source); -}); - -test("inferPolarity treats MI variants as higher-is-better", () => { - assert.equal(inferPolarity("mi.original"), "higher-is-better"); - assert.equal(inferPolarity("mi.sei"), "higher-is-better"); - assert.equal(inferPolarity("mi.visual_studio"), "higher-is-better"); - assert.equal(inferPolarity("cyclomatic"), "lower-is-better"); -}); - -test("parseVersionOutput extracts version from --version --json payload", () => { - assert.equal( - parseVersionOutput('{"name":"mehen","version":"0.4.3"}'), - "0.4.3", - ); - assert.equal( - parseVersionOutput(' {"name":"mehen","version":"1.2.3-beta.1"} \n'), - "1.2.3-beta.1", - ); -}); - -test("parseVersionOutput returns empty string for unparsable input", () => { - assert.equal(parseVersionOutput(""), ""); - assert.equal(parseVersionOutput("mehen 0.4.3"), ""); - assert.equal(parseVersionOutput("{}"), ""); -}); - -test("renderFooter includes version when provided", () => { - const footer = renderFooter("0.4.3"); - assert.ok(footer.includes("mehen")); - assert.ok(footer.includes("v0.4.3")); - assert.ok(footer.includes("code quality watcher")); -}); - -test("renderFooter omits version suffix when missing", () => { - const footer = renderFooter(""); - assert.ok(footer.includes("mehen")); - assert.ok(!footer.includes(" v ")); - assert.ok(!/v\d/.test(footer)); -}); - -test("extractMarkdownDocsSection returns null for empty or whitespace-only input", () => { - assert.equal(extractMarkdownDocsSection(""), null); - assert.equal(extractMarkdownDocsSection(" \n\t "), null); - assert.equal(extractMarkdownDocsSection(null), null); - assert.equal(extractMarkdownDocsSection(undefined), null); -}); - -test("extractMarkdownDocsSection returns null when the anchor is missing", () => { - const stdout = [ - "## [Mehen] Summary", - "", - "| File | Cyclomatic |", - "|---|---:|", - "| src/main.rs | 3 (main: 2) 🔴 |", - ].join("\n"); - assert.equal(extractMarkdownDocsSection(stdout), null); -}); - -test("extractMarkdownDocsSection returns null when the anchor is present but the section is empty", () => { - assert.equal(extractMarkdownDocsSection(""), null); - assert.equal(extractMarkdownDocsSection("prelude\n\n\n "), null); -}); - -test("extractMarkdownDocsSection slices from the anchor to end-of-output and trims", () => { - const section = [ - "", - "## Documentation Metrics (this PR vs `main`)", - "", - "| File | DMI |", - "|---|---:|", - "| README.md | 74 (main: 71) 🟢 |", - ].join("\n"); - const stdout = `## [Mehen] Summary\n\n| File |\n|---|\n\n${section}\n\n`; - const extracted = extractMarkdownDocsSection(stdout); - assert.equal(extracted, section); -}); - -test("extractMarkdownDocsSection preserves later anchors as literal text", () => { - // Defensive: if the CLI ever emits the anchor twice (e.g. inside a - // fenced example), indexOf finds the first one and we keep everything - // after it — the second anchor stays embedded rather than re-splitting. - const stdout = [ - "", - "## Documentation Metrics", - "", - "```markdown", - "", - "```", - ].join("\n"); - const extracted = extractMarkdownDocsSection(stdout); - assert.ok(extracted?.startsWith("")); - assert.ok(extracted.includes("```markdown")); -}); - -test("collectThresholdViolations skips non-applicable metrics", () => { - const thresholds = parseThresholds("wmc=5"); - const diffs = [ - { - path: "pkg/foo.go", - metrics: [ - { - name: "wmc", - label: "WMC", - not_applicable: true, - current: null, - baseline: null, - delta: 0, - polarity: "lower-is-better", - }, - ], - }, - ]; - const violations = collectThresholdViolations(diffs, thresholds); - assert.deepEqual(violations, []); -}); - - -// ── Base coverage retrieval (issue #248) ───────────────────────────── - -test("codecovToLcov maps hit, miss, and partial statuses to DA records", () => { - const lcov = codecovToLcov({ - totals: { coverage: 66.67 }, - files: [ - { - name: "src/lib.rs", - totals: { lines: 3 }, - // 0 = hit, 1 = miss, 2 = partial (partial executed → hit). - line_coverage: [ - [1, 0], - [2, 1], - [3, 2], - ], - }, - ], - }); - assert.equal(lcov, "SF:src/lib.rs\nDA:1,1\nDA:2,0\nDA:3,1\nend_of_record\n"); -}); - -test("codecovToLcov never fabricates branch records", () => { - const lcov = codecovToLcov({ - files: [ - { - name: "a.py", - line_coverage: [ - [1, 2], - [2, 2], - ], - }, - ], - }); - // Partials come from branch data upstream, but codecov's merged view - // has no original arms — inventing BRDA records would poison - // coverage.branch gates. - assert.ok(!lcov.includes("BRDA")); - assert.equal(lcov, "SF:a.py\nDA:1,1\nDA:2,1\nend_of_record\n"); -}); - -test("codecovToLcov skips malformed entries and unknown statuses", () => { - const lcov = codecovToLcov({ - files: [ - { - name: "b.go", - line_coverage: [ - [1, 0], - [0, 0], // non-positive line - [-3, 1], // negative line - [2.5, 0], // fractional line - [4], // too short - "junk", // not an array - [5, "1/2"], // unknown status encoding → skipped, not guessed - [6, 3], // unknown numeric status - [7, 1], - ], - }, - ], - }); - assert.equal(lcov, "SF:b.go\nDA:1,1\nDA:7,0\nend_of_record\n"); -}); - -test("codecovToLcov returns null when nothing usable remains", () => { - assert.equal(codecovToLcov(null), null); - assert.equal(codecovToLcov({}), null); - assert.equal(codecovToLcov({ files: [] }), null); - // A file without line data contributes nothing; an empty LCOV would - // fail mehen's format sniff, so the ladder must degrade to absent. - assert.equal( - codecovToLcov({ files: [{ name: "a.rs", line_coverage: [] }] }), - null, - ); - assert.equal( - codecovToLcov({ files: [{ name: "", line_coverage: [[1, 0]] }] }), - null, - ); - assert.equal( - codecovToLcov({ files: [{ name: "c.ts", line_coverage: [[1, 9]] }] }), - null, - ); -}); - -test("codecovToLcov emits one record block per usable file", () => { - const lcov = codecovToLcov({ - files: [ - { name: "a.rs", line_coverage: [[1, 0]] }, - { name: "skipped.rs", line_coverage: [] }, - { name: "b.rs", line_coverage: [[9, 1]] }, - ], - }); - assert.equal( - lcov, - "SF:a.rs\nDA:1,1\nend_of_record\nSF:b.rs\nDA:9,0\nend_of_record\n", - ); -}); - -test("listFilesRecursively returns [] for absent or empty inputs", () => { - assert.deepEqual(listFilesRecursively(""), []); - assert.deepEqual(listFilesRecursively(undefined), []); - assert.deepEqual( - listFilesRecursively("/nonexistent/mehen-test-dir"), - [], - ); -}); - - -test("every top-level const is declared before the entrypoint block", () => { - // `main()` is invoked from the `isEntrypoint()` block during module - // evaluation, so its synchronous call graph runs before any - // statement below that block has executed. Function declarations - // hoist; `const` bindings do not — a top-level const declared after - // the block is a temporal-dead-zone crash waiting for the first - // synchronous path that reads it. Seen live in CI as "Cannot access - // 'CODECOV_PENDING_RETRIES' before initialization"; importing the - // module (as these tests do) can never reproduce it, hence this - // source-order invariant. - const source = fs.readFileSync( - new URL("./github-action.mjs", import.meta.url), - "utf8", - ); - const entry = source.indexOf("if (isEntrypoint())"); - assert.ok(entry > 0, "entrypoint block must be present"); - const offender = source.slice(entry).match(/^const\s+\S+/m); - assert.equal( - offender, - null, - `top-level const declared after the entrypoint block: '${offender?.[0]}'`, - ); -}); - - -test("buildDiffArgs pins coverage off when every configured report is missing", () => { - const saved = process.env.GHA_MEHEN_COVERAGE_FILES; - try { - // All configured files missing: without the pin, a --base-coverage - // argument would flip mehen's lazy trigger into head-side - // auto-discovery, substituting stale working-tree artifacts for - // the reports the caller explicitly configured. - process.env.GHA_MEHEN_COVERAGE_FILES = - "/nonexistent/mehen-a.info,/nonexistent/mehen-b.info"; - const args = buildDiffArgs(["--base-coverage=/tmp/base.lcov"]); - assert.ok(args.includes("--coverage=off"), args.join(" ")); - assert.ok( - !args.some((a) => a.startsWith("--coverage=/")), - "missing files must not be passed through", - ); - assert.ok(args.includes("--base-coverage=/tmp/base.lcov")); - - // No coverage configured at all: no pin — lazy semantics stay. - process.env.GHA_MEHEN_COVERAGE_FILES = ""; - assert.ok(!buildDiffArgs().includes("--coverage=off")); - } finally { - if (saved === undefined) { - delete process.env.GHA_MEHEN_COVERAGE_FILES; - } else { - process.env.GHA_MEHEN_COVERAGE_FILES = saved; - } - } -}); - -test("isBaseCoverageFailure matches only stderr naming a base report path", () => { - const baseArgs = ["--base-coverage=/tmp/mehen-base-coverage/lcov.info"]; - const failure = (stderr) => ({ stderr }); - // mehen's setup error names the offending report. - assert.equal( - isBaseCoverageFailure( - failure( - "[ERROR] failed to parse coverage report `/tmp/mehen-base-coverage/lcov.info`: truncated record", - ), - baseArgs, - ), - true, - ); - // A corrupt *head* report is the caller's own artifact — no retry. - assert.equal( - isBaseCoverageFailure( - failure("[ERROR] failed to parse coverage report `coverage/lcov.info`"), - baseArgs, - ), - false, - ); - // Unrelated failures, missing stderr, or no base args: never retry. - assert.equal( - isBaseCoverageFailure(failure("[ERROR] git: object not found"), baseArgs), - false, - ); - assert.equal(isBaseCoverageFailure(new Error("spawn failed"), baseArgs), false); - assert.equal( - isBaseCoverageFailure(failure("failed to parse coverage report"), []), - false, - ); -}); - - -// ── Workflow-artifact base source (issue #254, rung 2) ─────────────── - -/** - * Build a standard ZIP archive in memory — local headers, central - * directory, end-of-central-directory — so extractZip is tested - * against real archive bytes without a binary fixture. Entries: - * `{ name, content, method }` with method 0 (stored) or 8 (deflate), - * matching what GitHub serves for workflow artifacts. - */ -function buildZip(entries) { - const localParts = []; - const centralParts = []; - let offset = 0; - for (const entry of entries) { - const nameBytes = Buffer.from(entry.name, "utf8"); - const raw = Buffer.from(entry.content ?? "", "utf8"); - const method = entry.method ?? 8; - const data = method === 8 ? zlib.deflateRawSync(raw) : raw; - const local = Buffer.alloc(30); - local.writeUInt32LE(0x04034b50, 0); - local.writeUInt16LE(20, 4); // version needed - local.writeUInt16LE(method, 8); - local.writeUInt32LE(data.length, 18); // compressed size - local.writeUInt32LE(raw.length, 22); // uncompressed size - local.writeUInt16LE(nameBytes.length, 26); - localParts.push(local, nameBytes, data); - - const central = Buffer.alloc(46); - central.writeUInt32LE(0x02014b50, 0); - central.writeUInt16LE(20, 6); // version needed - central.writeUInt16LE(method, 10); - central.writeUInt32LE(data.length, 20); - central.writeUInt32LE(raw.length, 24); - central.writeUInt16LE(nameBytes.length, 28); - central.writeUInt32LE(offset, 42); // local header offset - centralParts.push(central, nameBytes); - - offset += 30 + nameBytes.length + data.length; - } - const centralStart = offset; - const centralBuffer = Buffer.concat(centralParts); - const eocd = Buffer.alloc(22); - eocd.writeUInt32LE(0x06054b50, 0); - eocd.writeUInt16LE(entries.length, 8); - eocd.writeUInt16LE(entries.length, 10); - eocd.writeUInt32LE(centralBuffer.length, 12); - eocd.writeUInt32LE(centralStart, 16); - return Buffer.concat([...localParts, centralBuffer, eocd]); -} - -function tempExtractDir() { - return fs.mkdtempSync(path.join(os.tmpdir(), "mehen-zip-test-")); -} - -test("extractZip extracts stored and deflated entries with nested paths", () => { - const zip = buildZip([ - { name: "lcov.info", content: "TN:\nSF:a.rs\nDA:1,1\nend_of_record\n" }, - { - name: "nested/dir/cobertura.xml", - content: "", - method: 0, - }, - ]); - const dir = tempExtractDir(); - try { - const files = extractZip(zip, dir); - assert.deepEqual( - files.map((f) => path.relative(dir, f)).sort(), - ["lcov.info", path.join("nested", "dir", "cobertura.xml")].sort(), - ); - assert.equal( - fs.readFileSync(path.join(dir, "lcov.info"), "utf8"), - "TN:\nSF:a.rs\nDA:1,1\nend_of_record\n", - ); - assert.equal( - fs.readFileSync(path.join(dir, "nested", "dir", "cobertura.xml"), "utf8"), - "", - ); - } finally { - fs.rmSync(dir, { recursive: true, force: true }); - } -}); - -test("extractZip skips directory entries and rejects zip-slip escapes", () => { - const clean = buildZip([ - { name: "reports/", content: "" }, - { name: "reports/lcov.info", content: "SF:a\nDA:1,1\nend_of_record\n" }, - ]); - const dir = tempExtractDir(); - try { - const files = extractZip(clean, dir); - assert.equal(files.length, 1); - } finally { - fs.rmSync(dir, { recursive: true, force: true }); - } - - // A hostile entry escaping the destination is an integrity failure, - // not a degradation case: extraction must throw, never write. - const hostile = buildZip([{ name: "../evil.txt", content: "boom" }]); - const dir2 = tempExtractDir(); - try { - assert.throws( - () => extractZip(hostile, dir2), - /escapes the extraction directory/, - ); - assert.ok(!fs.existsSync(path.join(dir2, "..", "evil.txt"))); - } finally { - fs.rmSync(dir2, { recursive: true, force: true }); - } -}); - -test("extractZip rejects non-zip input", () => { - const dir = tempExtractDir(); - try { - assert.throws( - () => extractZip(Buffer.from("definitely not a zip"), dir), - /not a zip archive/, - ); - } finally { - fs.rmSync(dir, { recursive: true, force: true }); - } -}); - -test("pickBaseArtifact picks the newest non-expired artifact for the base SHA", () => { - const baseSha = "a".repeat(40); - const artifacts = [ - { - id: 1, - expired: false, - created_at: "2026-08-01T00:00:00Z", - workflow_run: { head_sha: baseSha }, - }, - { - id: 2, - expired: false, - created_at: "2026-08-02T00:00:00Z", - workflow_run: { head_sha: baseSha }, - }, - // Expired entries and other SHAs never match. - { - id: 3, - expired: true, - created_at: "2026-08-03T00:00:00Z", - workflow_run: { head_sha: baseSha }, - }, - { - id: 4, - expired: false, - created_at: "2026-08-04T00:00:00Z", - workflow_run: { head_sha: "b".repeat(40) }, - }, - ]; - assert.equal(pickBaseArtifact(artifacts, baseSha)?.id, 2); - assert.equal(pickBaseArtifact(artifacts, "c".repeat(40)), null); - assert.equal(pickBaseArtifact([], baseSha), null); - assert.equal(pickBaseArtifact(undefined, baseSha), null); - assert.equal(pickBaseArtifact(artifacts, ""), null); -}); - - -test("extractZip enforces the decompressed-size budget", () => { - // Honest metadata over budget: rejected up front from the declared - // central-directory sizes, before any inflation. - const big = buildZip([{ name: "big.info", content: "x".repeat(4096) }]); - const dir = tempExtractDir(); - try { - assert.throws( - () => extractZip(big, dir, 1024), - /declares more than 1024 decompressed bytes/, - ); - assert.deepEqual(fs.readdirSync(dir), [], "nothing may be written"); - } finally { - fs.rmSync(dir, { recursive: true, force: true }); - } - - // Lying metadata (the zip-bomb shape): declared sizes pass, but the - // actual inflate output exceeds the budget — zlib's maxOutputLength - // aborts mid-inflate instead of allocating the full expansion. - const bomb = buildZip([{ name: "bomb.info", content: "y".repeat(64 * 1024) }]); - // Corrupt the declared uncompressed sizes down to 1 byte (central - // directory offset 24, local header offset 22). - const cdStart = bomb.readUInt32LE(bomb.length - 22 + 16); - bomb.writeUInt32LE(1, cdStart + 24); - bomb.writeUInt32LE(1, 22); - const dir2 = tempExtractDir(); - try { - assert.throws(() => extractZip(bomb, dir2, 1024)); - assert.deepEqual(fs.readdirSync(dir2), [], "nothing may be written"); - } finally { - fs.rmSync(dir2, { recursive: true, force: true }); - } - - // Within budget: extraction is unaffected. - const fine = buildZip([{ name: "ok.info", content: "SF:a\nDA:1,1\nend_of_record\n" }]); - const dir3 = tempExtractDir(); - try { - assert.equal(extractZip(fine, dir3, 1024).length, 1); - } finally { - fs.rmSync(dir3, { recursive: true, force: true }); - } -}); diff --git a/scripts/publish-npm.js b/scripts/publish-npm.js index f5761512..63df36ee 100644 --- a/scripts/publish-npm.js +++ b/scripts/publish-npm.js @@ -28,12 +28,20 @@ function execCommandWithOutput(command, options = {}) { const result = spawnSync(command, { shell: true, encoding: 'utf8', - stdio: 'inherit', ...options }); + if (result.stdout) { + process.stdout.write(result.stdout); + } + if (result.stderr) { + process.stderr.write(result.stderr); + } + if (result.status !== 0) { const error = new Error(`Command failed: ${command}`); + error.stdout = result.stdout; + error.stderr = result.stderr; throw error; } diff --git a/split-minimal-tests.py b/split-minimal-tests.py new file mode 100755 index 00000000..8dc84f9d --- /dev/null +++ b/split-minimal-tests.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 + +"""split-minimal-tests +This script splits HTML minimal-tests, produced by a software called +`json-minimal-tests`, into distinct directories depending on metric differences. + +Usage: + +./split-minimal-tests.py -i INPUT_DIR -o OUTPUT_DIR [-t MT_THRESHOLD] + +NOTE: OUTPUT_DIR is the path to the output directory to be created. +This directory could contain either a series of directories, called as +the metrics that presents differences, or be empty if no metric differences +are found. +MT_THRESHOLD determines the maximum number of considered minimal tests +for a metric. +""" + +import argparse +import pathlib +import re +import shutil +import typing as T + +# List of metrics +# TODO: Implement a command into mehen-cli that returns all +# computed metrics https://github.com/mozilla/mehen/issues/478 +METRICS = [ + "cognitive", + "sloc", + "ploc", + "lloc", + "cloc", + "blank", + "cyclomatic", + "halstead", + "nom", + "nexits", + "nargs", +] + + +def main() -> None: + parser = argparse.ArgumentParser( + prog="split-minimal-tests", + description="This tool splits HTML minimal-tests, produced by " + "a software called `json-minimal-tests`, into distinct directories " + "depending on metric differences.", + epilog="The source code of this program can be found on " + "GitHub at https://github.com/mozilla/mehen", + ) + + # Arguments + parser.add_argument( + "--input", + "-i", + type=lambda value: pathlib.Path(value), + required=True, + help="Input directory containing HTML minimal tests.", + ) + + parser.add_argument( + "--output", + "-o", + type=lambda value: pathlib.Path(value), + required=True, + help="Path to the output directory.", + ) + + # Optional arguments + parser.add_argument( + "--threshold", + "-t", + type=int, + help="Maximum number of considered minimal tests for a metric.", + ) + + # Parse arguments + args = parser.parse_args() + + # Create output directory + args.output.mkdir(parents=True, exist_ok=True) + + # Save files associated to each metric + metrics_saver: T.Dict[str, T.List] = {metric_name: [] for metric_name in METRICS} + + # Iterate over the files contained in the input directory + for path in args.input.glob("*.html"): + # Open a file + with open(path) as f: + # Read a file + file_str = f.read() + + # Remove all code inside
 tags
+            file_no_pre = re.sub(r"
(.|\n)*?<\/pre>", "", file_str)
+
+            # Iterate over metrics
+            for metric_name, metric_files in metrics_saver.items():
+                # Check if there is a metric difference in a file
+                m = re.search(f"(\.{metric_name})", file_no_pre)
+
+                # If some errors occurred, skip to the next metric
+                if m is None:
+                    continue
+
+                # Save path if there is a metric difference in a file
+                if m.group(1):
+                    metric_files.append(path)
+
+    # Iterate over metrics to print them
+    for metric_name, metric_files in metrics_saver.items():
+        # Create path for metric directory
+        metric_path = args.output / metric_name
+
+        if metric_files:
+            # Create metric directory
+            metric_path.mkdir(parents=True, exist_ok=True)
+
+            # Save the number of files specified in the threshold
+            output_paths = (
+                metric_files[: args.threshold] if args.threshold else metric_files
+            )
+
+            for path in output_paths:
+                # Copy files in the directory
+                shutil.copy(path, metric_path)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/src/alterator.rs b/src/alterator.rs
new file mode 100644
index 00000000..b2f86be1
--- /dev/null
+++ b/src/alterator.rs
@@ -0,0 +1,98 @@
+use crate::*;
+
+/// A trait to create a richer `AST` node for a programming language, mainly
+/// thought to be sent on the network.
+pub trait Alterator
+where
+    Self: Checker,
+{
+    /// Creates a new `AST` node containing the code associated to the node,
+    /// its span, and its children.
+    ///
+    /// This function can be overloaded according to the needs of each
+    /// programming language.
+    fn alter(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode {
+        Self::get_default(node, code, span, children)
+    }
+
+    /// Gets the code as text and the span associated to a node.
+    fn get_text_span(node: &Node, code: &[u8], span: bool, text: bool) -> (String, Span) {
+        let text = if text {
+            String::from_utf8(code[node.start_byte()..node.end_byte()].to_vec()).unwrap()
+        } else {
+            "".to_string()
+        };
+        if span {
+            let (spos_row, spos_column) = node.start_position();
+            let (epos_row, epos_column) = node.end_position();
+            (
+                text,
+                Some((spos_row + 1, spos_column + 1, epos_row + 1, epos_column + 1)),
+            )
+        } else {
+            (text, None)
+        }
+    }
+
+    /// Gets a default `AST` node containing the code associated to the node,
+    /// its span, and its children.
+    fn get_default(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode {
+        let (text, span) = Self::get_text_span(node, code, span, node.child_count() == 0);
+        AstNode::new(node.kind(), text, span, children)
+    }
+
+    /// Gets a new `AST` node if and only if the code is not a comment,
+    /// otherwise [`None`] is returned.
+    fn get_ast_node(
+        node: &Node,
+        code: &[u8],
+        children: Vec,
+        span: bool,
+        comment: bool,
+    ) -> Option {
+        if comment && Self::is_comment(node) {
+            None
+        } else {
+            Some(Self::alter(node, code, span, children))
+        }
+    }
+}
+
+impl Alterator for PythonCode {}
+impl Alterator for GoCode {}
+
+impl Alterator for TypescriptCode {
+    fn alter(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode {
+        match Typescript::from(node.kind_id()) {
+            Typescript::String => {
+                let (text, span) = Self::get_text_span(node, code, span, true);
+                AstNode::new(node.kind(), text, span, Vec::new())
+            }
+            _ => Self::get_default(node, code, span, children),
+        }
+    }
+}
+
+impl Alterator for TsxCode {
+    fn alter(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode {
+        match Tsx::from(node.kind_id()) {
+            Tsx::String => {
+                let (text, span) = Self::get_text_span(node, code, span, true);
+                AstNode::new(node.kind(), text, span, Vec::new())
+            }
+            _ => Self::get_default(node, code, span, children),
+        }
+    }
+}
+
+impl Alterator for RustCode {
+    fn alter(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode {
+        match Rust::from(node.kind_id()) {
+            Rust::StringLiteral | Rust::CharLiteral => {
+                let (text, span) = Self::get_text_span(node, code, span, true);
+                AstNode::new(node.kind(), text, span, Vec::new())
+            }
+            _ => Self::get_default(node, code, span, children),
+        }
+    }
+}
diff --git a/src/ast.rs b/src/ast.rs
new file mode 100644
index 00000000..79556459
--- /dev/null
+++ b/src/ast.rs
@@ -0,0 +1,152 @@
+use serde::ser::{SerializeStruct, Serializer};
+use serde::{Deserialize, Serialize};
+
+use crate::*;
+
+/// Start and end positions of a node in a code in terms of rows and columns.
+///
+/// The first and second fields represent the row and column associated to
+/// the start position of a node.
+///
+/// The third and fourth fields represent the row and column associated to
+/// the end position of a node.
+pub type Span = Option<(usize, usize, usize, usize)>;
+
+/// The payload of an `Ast` request.
+#[derive(Debug, Deserialize, Serialize)]
+pub struct AstPayload {
+    /// The id associated to a request for an `AST`
+    pub id: String,
+    /// The filename associated to a source code file
+    pub file_name: String,
+    /// The code to be represented as an `AST`
+    pub code: String,
+    /// If `true`, nodes representing comments are ignored
+    pub comment: bool,
+    /// If `true`, the start and end positions of a node in a code
+    /// are considered
+    pub span: bool,
+}
+
+/// The response of an `AST` request.
+#[derive(Debug, Serialize)]
+pub struct AstResponse {
+    /// The id associated to a request for an `AST`
+    pub id: String,
+    /// The root node of an `AST`
+    ///
+    /// If `None`, an error has occurred
+    pub root: Option,
+}
+
+/// Information on an `AST` node.
+#[derive(Debug)]
+pub struct AstNode {
+    /// The type of node
+    pub r#type: &'static str,
+    /// The code associated to a node
+    pub value: String,
+    /// The start and end positions of a node in a code
+    pub span: Span,
+    /// The children of a node
+    pub children: Vec,
+}
+
+impl Serialize for AstNode {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("Node", 4)?;
+        st.serialize_field("Type", &self.r#type)?;
+        st.serialize_field("TextValue", &self.value)?;
+        st.serialize_field("Span", &self.span)?;
+        st.serialize_field("Children", &self.children)?;
+        st.end()
+    }
+}
+
+impl AstNode {
+    pub fn new(r#type: &'static str, value: String, span: Span, children: Vec) -> Self {
+        Self {
+            r#type,
+            value,
+            span,
+            children,
+        }
+    }
+}
+
+fn build(parser: &T, span: bool, comment: bool) -> Option {
+    let code = parser.get_code();
+    let root = parser.get_root();
+    let mut cursor = root.cursor();
+    let mut node_stack = Vec::new();
+    let mut child_stack = Vec::new();
+
+    node_stack.push(root);
+    child_stack.push(Vec::new());
+
+    /* To avoid Rc, RefCell and stuff like that (or use of unsafe)
+    the idea here is to build AstNode from bottom-to-top and from left-to-right.
+    So once we have built the array of children we can build the node itself until the root. */
+    loop {
+        let ts_node = node_stack.last().unwrap();
+        cursor.reset(ts_node);
+        if cursor.goto_first_child() {
+            let node = cursor.node();
+            child_stack.push(Vec::with_capacity(node.child_count()));
+            node_stack.push(node);
+        } else {
+            loop {
+                let ts_node = node_stack.pop().unwrap();
+                if let Some(node) = T::Checker::get_ast_node(
+                    &ts_node,
+                    code,
+                    child_stack.pop().unwrap(),
+                    span,
+                    comment,
+                ) {
+                    if !child_stack.is_empty() {
+                        child_stack.last_mut().unwrap().push(node);
+                    } else {
+                        return Some(node);
+                    }
+                }
+                if let Some(next_node) = ts_node.next_sibling() {
+                    child_stack.push(Vec::with_capacity(next_node.child_count()));
+                    node_stack.push(next_node);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+pub struct AstCallback {
+    _guard: (),
+}
+
+/// Configuration options for retrieving the nodes of an `AST`.
+#[derive(Debug)]
+pub struct AstCfg {
+    /// The id associated to a request for an `AST`
+    pub id: String,
+    /// If `true`, nodes representing comments are ignored
+    pub comment: bool,
+    /// If `true`, the start and end positions of a node in a code
+    /// are considered
+    pub span: bool,
+}
+
+impl Callback for AstCallback {
+    type Res = AstResponse;
+    type Cfg = AstCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        AstResponse {
+            id: cfg.id,
+            root: build(parser, cfg.span, cfg.comment),
+        }
+    }
+}
diff --git a/src/checker.rs b/src/checker.rs
new file mode 100644
index 00000000..437835e2
--- /dev/null
+++ b/src/checker.rs
@@ -0,0 +1,397 @@
+use std::sync::OnceLock;
+
+use regex::bytes::Regex;
+
+use crate::*;
+
+static RE: OnceLock = OnceLock::new();
+
+macro_rules! check_if_func {
+    ($parser: ident, $node: ident) => {
+        $node.count_specific_ancestors::<$parser>(
+            |node| {
+                matches!(
+                    node.kind_id().into(),
+                    VariableDeclarator | AssignmentExpression | LabeledStatement | Pair
+                )
+            },
+            |node| {
+                matches!(
+                    node.kind_id().into(),
+                    StatementBlock | ReturnStatement | NewExpression | Arguments
+                )
+            },
+        ) > 0
+            || $node.is_child(Identifier as u16)
+    };
+}
+
+macro_rules! check_if_arrow_func {
+    ($parser: ident, $node: ident) => {
+        $node.count_specific_ancestors::<$parser>(
+            |node| {
+                matches!(
+                    node.kind_id().into(),
+                    VariableDeclarator | AssignmentExpression | LabeledStatement
+                )
+            },
+            |node| {
+                matches!(
+                    node.kind_id().into(),
+                    StatementBlock | ReturnStatement | NewExpression | CallExpression
+                )
+            },
+        ) > 0
+            || $node.has_sibling(PropertyIdentifier as u16)
+    };
+}
+
+macro_rules! is_js_func {
+    ($parser: ident, $node: ident) => {
+        match $node.kind_id().into() {
+            FunctionDeclaration | MethodDefinition => true,
+            FunctionExpression => check_if_func!($parser, $node),
+            ArrowFunction => check_if_arrow_func!($parser, $node),
+            _ => false,
+        }
+    };
+}
+
+macro_rules! is_js_closure {
+    ($parser: ident, $node: ident) => {
+        match $node.kind_id().into() {
+            GeneratorFunction | GeneratorFunctionDeclaration => true,
+            FunctionExpression => !check_if_func!($parser, $node),
+            ArrowFunction => !check_if_arrow_func!($parser, $node),
+            _ => false,
+        }
+    };
+}
+
+macro_rules! is_js_func_and_closure_checker {
+    ($parser: ident, $language: ident) => {
+        #[inline(always)]
+        fn is_func(node: &Node) -> bool {
+            use $language::*;
+            is_js_func!($parser, node)
+        }
+
+        #[inline(always)]
+        fn is_closure(node: &Node) -> bool {
+            use $language::*;
+            is_js_closure!($parser, node)
+        }
+    };
+}
+
+pub trait Checker {
+    fn is_comment(_: &Node) -> bool;
+    fn is_useful_comment(_: &Node, _: &[u8]) -> bool;
+    fn is_func_space(_: &Node) -> bool;
+    fn is_func(_: &Node) -> bool;
+    fn is_closure(_: &Node) -> bool;
+    fn is_call(_: &Node) -> bool;
+    fn is_non_arg(_: &Node) -> bool;
+    fn is_string(_: &Node) -> bool;
+    fn is_else_if(_: &Node) -> bool;
+    fn is_primitive(_id: u16) -> bool;
+
+    fn is_error(node: &Node) -> bool {
+        node.has_error()
+    }
+}
+
+impl Checker for PythonCode {
+    fn is_comment(node: &Node) -> bool {
+        node.kind_id() == Python::Comment
+    }
+
+    fn is_useful_comment(node: &Node, code: &[u8]) -> bool {
+        // comment containing coding info are useful
+        node.start_row() <= 1
+            && RE
+                .get_or_init(|| {
+                    Regex::new(r"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)").unwrap()
+                })
+                .is_match(&code[node.start_byte()..node.end_byte()])
+    }
+
+    fn is_func_space(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Python::Module | Python::FunctionDefinition | Python::ClassDefinition
+        )
+    }
+
+    fn is_func(node: &Node) -> bool {
+        node.kind_id() == Python::FunctionDefinition
+    }
+
+    fn is_closure(node: &Node) -> bool {
+        node.kind_id() == Python::Lambda
+    }
+
+    fn is_call(node: &Node) -> bool {
+        node.kind_id() == Python::Call
+    }
+
+    fn is_non_arg(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Python::LPAREN | Python::COMMA | Python::RPAREN
+        )
+    }
+
+    fn is_string(node: &Node) -> bool {
+        node.kind_id() == Python::String || node.kind_id() == Python::ConcatenatedString
+    }
+
+    fn is_else_if(_: &Node) -> bool {
+        false
+    }
+
+    fn is_primitive(_id: u16) -> bool {
+        false
+    }
+}
+
+impl Checker for TypescriptCode {
+    fn is_comment(node: &Node) -> bool {
+        node.kind_id() == Typescript::Comment
+    }
+
+    fn is_useful_comment(_: &Node, _: &[u8]) -> bool {
+        false
+    }
+
+    fn is_func_space(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Typescript::Program
+                | Typescript::FunctionExpression
+                | Typescript::Class
+                | Typescript::GeneratorFunction
+                | Typescript::FunctionDeclaration
+                | Typescript::MethodDefinition
+                | Typescript::GeneratorFunctionDeclaration
+                | Typescript::ClassDeclaration
+                | Typescript::InterfaceDeclaration
+                | Typescript::ArrowFunction
+        )
+    }
+
+    is_js_func_and_closure_checker!(TypescriptParser, Typescript);
+
+    fn is_call(node: &Node) -> bool {
+        node.kind_id() == Typescript::CallExpression
+    }
+
+    fn is_non_arg(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Typescript::LPAREN | Typescript::COMMA | Typescript::RPAREN
+        )
+    }
+
+    fn is_string(node: &Node) -> bool {
+        node.kind_id() == Typescript::String || node.kind_id() == Typescript::TemplateString
+    }
+
+    #[inline(always)]
+    fn is_else_if(node: &Node) -> bool {
+        if node.kind_id() != Typescript::IfStatement {
+            return false;
+        }
+        if let Some(parent) = node.parent() {
+            return parent.kind_id() == Typescript::ElseClause;
+        }
+        false
+    }
+
+    #[inline(always)]
+    fn is_primitive(id: u16) -> bool {
+        id == Typescript::PredefinedType
+    }
+}
+
+impl Checker for TsxCode {
+    fn is_comment(node: &Node) -> bool {
+        node.kind_id() == Tsx::Comment
+    }
+
+    fn is_useful_comment(_: &Node, _: &[u8]) -> bool {
+        false
+    }
+
+    fn is_func_space(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Tsx::Program
+                | Tsx::FunctionExpression
+                | Tsx::Class
+                | Tsx::GeneratorFunction
+                | Tsx::FunctionDeclaration
+                | Tsx::MethodDefinition
+                | Tsx::GeneratorFunctionDeclaration
+                | Tsx::ClassDeclaration
+                | Tsx::InterfaceDeclaration
+                | Tsx::ArrowFunction
+        )
+    }
+
+    is_js_func_and_closure_checker!(TsxParser, Tsx);
+
+    fn is_call(node: &Node) -> bool {
+        node.kind_id() == Tsx::CallExpression
+    }
+
+    fn is_non_arg(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Tsx::LPAREN | Tsx::COMMA | Tsx::RPAREN
+        )
+    }
+
+    fn is_string(node: &Node) -> bool {
+        node.kind_id() == Tsx::String || node.kind_id() == Tsx::TemplateString
+    }
+
+    fn is_else_if(node: &Node) -> bool {
+        if node.kind_id() != Tsx::IfStatement {
+            return false;
+        }
+        if let Some(parent) = node.parent() {
+            return node.kind_id() == Tsx::IfStatement && parent.kind_id() == Tsx::IfStatement;
+        }
+        false
+    }
+
+    #[inline(always)]
+    fn is_primitive(id: u16) -> bool {
+        id == Tsx::PredefinedType
+    }
+}
+
+impl Checker for RustCode {
+    fn is_comment(node: &Node) -> bool {
+        node.kind_id() == Rust::LineComment || node.kind_id() == Rust::BlockComment
+    }
+
+    fn is_useful_comment(node: &Node, code: &[u8]) -> bool {
+        if let Some(parent) = node.parent()
+            && parent.kind_id() == Rust::TokenTree
+        {
+            // A comment could be a macro token
+            return true;
+        }
+        let code = &code[node.start_byte()..node.end_byte()];
+        code.starts_with(b"/// cbindgen:")
+    }
+
+    fn is_func_space(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Rust::SourceFile
+                | Rust::FunctionItem
+                | Rust::ImplItem
+                | Rust::TraitItem
+                | Rust::ClosureExpression
+        )
+    }
+
+    fn is_func(node: &Node) -> bool {
+        node.kind_id() == Rust::FunctionItem
+    }
+
+    fn is_closure(node: &Node) -> bool {
+        node.kind_id() == Rust::ClosureExpression
+    }
+
+    fn is_call(node: &Node) -> bool {
+        node.kind_id() == Rust::CallExpression
+    }
+
+    fn is_non_arg(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Rust::LPAREN | Rust::COMMA | Rust::RPAREN | Rust::PIPE | Rust::AttributeItem
+        )
+    }
+
+    fn is_string(node: &Node) -> bool {
+        node.kind_id() == Rust::StringLiteral || node.kind_id() == Rust::RawStringLiteral
+    }
+
+    #[inline(always)]
+    fn is_else_if(node: &Node) -> bool {
+        if node.kind_id() != Rust::IfExpression {
+            return false;
+        }
+        if let Some(parent) = node.parent() {
+            return parent.kind_id() == Rust::ElseClause;
+        }
+        false
+    }
+
+    #[inline(always)]
+    fn is_primitive(id: u16) -> bool {
+        id == Rust::PrimitiveType
+    }
+}
+
+impl Checker for GoCode {
+    fn is_comment(node: &Node) -> bool {
+        node.kind_id() == Go::Comment
+    }
+
+    fn is_useful_comment(_: &Node, _: &[u8]) -> bool {
+        false
+    }
+
+    fn is_func_space(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Go::SourceFile | Go::FunctionDeclaration | Go::MethodDeclaration
+        )
+    }
+
+    fn is_func(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Go::FunctionDeclaration | Go::MethodDeclaration
+        )
+    }
+
+    fn is_closure(node: &Node) -> bool {
+        node.kind_id() == Go::FuncLiteral
+    }
+
+    fn is_call(node: &Node) -> bool {
+        node.kind_id() == Go::CallExpression
+    }
+
+    fn is_non_arg(node: &Node) -> bool {
+        matches!(node.kind_id().into(), Go::LPAREN | Go::COMMA | Go::RPAREN)
+    }
+
+    fn is_string(node: &Node) -> bool {
+        matches!(
+            node.kind_id().into(),
+            Go::RawStringLiteral | Go::InterpretedStringLiteral
+        )
+    }
+
+    fn is_else_if(node: &Node) -> bool {
+        if node.kind_id() != Go::IfStatement {
+            return false;
+        }
+        if let Some(parent) = node.parent() {
+            return parent.kind_id() == Go::IfStatement;
+        }
+        false
+    }
+
+    fn is_primitive(_id: u16) -> bool {
+        false
+    }
+}
diff --git a/src/comment_rm.rs b/src/comment_rm.rs
new file mode 100644
index 00000000..80ecf12c
--- /dev/null
+++ b/src/comment_rm.rs
@@ -0,0 +1,132 @@
+use std::io::{self, Write};
+use std::path::PathBuf;
+
+use crate::checker::Checker;
+
+use crate::tools::*;
+use crate::traits::*;
+
+const CR: [u8; 8192] = [b'\n'; 8192];
+
+/// Removes comments from a code.
+pub fn rm_comments(parser: &T) -> Option> {
+    let node = parser.get_root();
+    let mut stack = Vec::new();
+    let mut cursor = node.cursor();
+    let mut spans = Vec::new();
+
+    stack.push(node);
+
+    while let Some(node) = stack.pop() {
+        if T::Checker::is_comment(&node) && !T::Checker::is_useful_comment(&node, parser.get_code())
+        {
+            let lines = node.end_row() - node.start_row();
+            spans.push((node.start_byte(), node.end_byte(), lines));
+        } else {
+            cursor.reset(&node);
+            if cursor.goto_first_child() {
+                loop {
+                    stack.push(cursor.node());
+                    if !cursor.goto_next_sibling() {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    if !spans.is_empty() {
+        Some(remove_from_code(parser.get_code(), spans))
+    } else {
+        None
+    }
+}
+
+fn remove_from_code(code: &[u8], mut spans: Vec<(usize, usize, usize)>) -> Vec {
+    let mut new_code = Vec::with_capacity(code.len());
+    let mut code_start = 0;
+    for (start, end, lines) in spans.drain(..).rev() {
+        new_code.extend(&code[code_start..start]);
+        if lines != 0 {
+            if lines <= CR.len() {
+                new_code.extend(&CR[..lines]);
+            } else {
+                new_code.resize_with(new_code.len() + lines, || b'\n');
+            }
+        }
+        code_start = end;
+    }
+    if code_start < code.len() {
+        new_code.extend(&code[code_start..]);
+    }
+    new_code
+}
+
+/// Configuration options for removing comments from a code.
+#[derive(Debug)]
+pub struct CommentRmCfg {
+    /// If `true`, the modified code is saved on a file
+    pub in_place: bool,
+    /// Path to output file
+    pub path: PathBuf,
+}
+
+pub struct CommentRm {
+    _guard: (),
+}
+
+impl Callback for CommentRm {
+    type Res = std::io::Result<()>;
+    type Cfg = CommentRmCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        if let Some(new_source) = rm_comments(parser) {
+            if cfg.in_place {
+                write_file(&cfg.path, &new_source)?;
+            } else if let Ok(new_source) = std::str::from_utf8(&new_source) {
+                println!("{new_source}");
+            } else {
+                io::stdout().write_all(&new_source)?;
+            }
+        }
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::path::PathBuf;
+
+    use crate::{ParserTrait, RustParser};
+
+    use super::rm_comments;
+
+    const SOURCE_CODE: &str = "/* Remove this code block */\n\
+                               let a = 42; // Remove this comment\n\
+                               // Remove this comment\n\
+                               let b = 42;\n\
+                               /* Remove\n\
+                                * this\n\
+                                * comment\n\
+                                */";
+
+    const SOURCE_CODE_NO_COMMENTS: &str = "\n\
+                                           let a = 42; \n\
+                                           \n\
+                                           let b = 42;\n\
+                                           \n\
+                                           \n\
+                                           \n\
+                                           \n";
+
+    #[test]
+    fn rust_remove_comments() {
+        let path = PathBuf::from("foo.rs");
+        let mut trimmed_bytes = SOURCE_CODE.as_bytes().to_vec();
+        trimmed_bytes.push(b'\n');
+        let parser = RustParser::new(trimmed_bytes, &path, None);
+
+        let no_comments = rm_comments(&parser).unwrap();
+
+        assert_eq!(no_comments.as_slice(), SOURCE_CODE_NO_COMMENTS.as_bytes());
+    }
+}
diff --git a/src/concurrent_files.rs b/src/concurrent_files.rs
new file mode 100644
index 00000000..20c34a42
--- /dev/null
+++ b/src/concurrent_files.rs
@@ -0,0 +1,280 @@
+use std::collections::HashMap;
+use std::path::{Path, PathBuf};
+use std::sync::Arc;
+use std::thread;
+
+use crossbeam::channel::{Receiver, Sender, unbounded};
+use globset::GlobSet;
+use walkdir::{DirEntry, WalkDir};
+
+type ProcFilesFunction = dyn Fn(PathBuf, &Config) -> std::io::Result<()> + Send + Sync;
+
+type ProcDirPathsFunction =
+    dyn Fn(&mut HashMap>, &Path, &Config) + Send + Sync;
+
+type ProcPathFunction = dyn Fn(&Path, &Config) + Send + Sync;
+
+// Null functions removed at compile time
+fn null_proc_dir_paths(_: &mut HashMap>, _: &Path, _: &Config) {}
+fn null_proc_path(_: &Path, _: &Config) {}
+
+#[derive(Debug)]
+struct JobItem {
+    path: PathBuf,
+    cfg: Arc,
+}
+
+type JobReceiver = Receiver>>;
+type JobSender = Sender>>;
+
+fn consumer(receiver: JobReceiver, func: Arc)
+where
+    ProcFiles: Fn(PathBuf, &Config) -> std::io::Result<()> + Send + Sync,
+{
+    while let Ok(job) = receiver.recv() {
+        if job.is_none() {
+            break;
+        }
+        // Cannot panic because of the check immediately above.
+        let job = job.unwrap();
+        let path = job.path.clone();
+
+        if let Err(err) = func(job.path, &job.cfg) {
+            eprintln!("{err:?} for file {path:?}");
+        }
+    }
+}
+
+fn send_file(
+    path: PathBuf,
+    cfg: &Arc,
+    sender: &JobSender,
+) -> Result<(), ConcurrentErrors> {
+    sender
+        .send(Some(JobItem {
+            path,
+            cfg: Arc::clone(cfg),
+        }))
+        .map_err(|e| ConcurrentErrors::Sender(e.to_string()))
+}
+
+fn is_hidden(entry: &DirEntry) -> bool {
+    entry
+        .file_name()
+        .to_str()
+        .map(|s| s.starts_with('.'))
+        .unwrap_or(false)
+}
+
+fn explore(
+    files_data: FilesData,
+    cfg: &Arc,
+    proc_dir_paths: ProcDirPaths,
+    proc_path: ProcPath,
+    sender: &JobSender,
+) -> Result>, ConcurrentErrors>
+where
+    ProcDirPaths: Fn(&mut HashMap>, &Path, &Config) + Send + Sync,
+    ProcPath: Fn(&Path, &Config) + Send + Sync,
+{
+    let FilesData {
+        mut paths,
+        ref include,
+        ref exclude,
+    } = files_data;
+
+    let mut all_files: HashMap> = HashMap::new();
+
+    for path in paths.drain(..) {
+        if !path.exists() {
+            eprintln!("Warning: File doesn't exist: {path:?}");
+            continue;
+        }
+        if path.is_dir() {
+            for entry in WalkDir::new(path)
+                .into_iter()
+                .filter_entry(|e| !is_hidden(e))
+            {
+                let entry = match entry {
+                    Ok(entry) => entry,
+                    Err(e) => return Err(ConcurrentErrors::Sender(e.to_string())),
+                };
+                let path = entry.path().to_path_buf();
+                if (include.is_empty() || include.is_match(&path))
+                    && (exclude.is_empty() || !exclude.is_match(&path))
+                    && path.is_file()
+                {
+                    proc_dir_paths(&mut all_files, &path, cfg);
+                    send_file(path, cfg, sender)?;
+                }
+            }
+        } else if (include.is_empty() || include.is_match(&path))
+            && (exclude.is_empty() || !exclude.is_match(&path))
+            && path.is_file()
+        {
+            proc_path(&path, cfg);
+            send_file(path, cfg, sender)?;
+        }
+    }
+
+    Ok(all_files)
+}
+
+/// Series of errors that might happen when processing files concurrently.
+#[derive(Debug)]
+pub enum ConcurrentErrors {
+    /// Producer side error.
+    ///
+    /// An error occurred inside the producer thread.
+    Producer(String),
+    /// Sender side error.
+    ///
+    /// An error occurred when sending an item.
+    Sender(String),
+    /// Receiver side error.
+    ///
+    /// An error occurred inside one of the receiver threads.
+    Receiver(String),
+    /// Thread side error.
+    ///
+    /// A general error occurred when a thread is being spawned or run.
+    Thread(String),
+}
+
+/// Data related to files.
+#[derive(Debug)]
+pub struct FilesData {
+    /// Kind of files included in a search.
+    pub include: GlobSet,
+    /// Kind of files excluded from a search.
+    pub exclude: GlobSet,
+    /// List of file paths.
+    pub paths: Vec,
+}
+
+/// A runner to process files concurrently.
+pub struct ConcurrentRunner {
+    proc_files: Box>,
+    proc_dir_paths: Box>,
+    proc_path: Box>,
+    num_jobs: usize,
+}
+
+impl ConcurrentRunner {
+    /// Creates a new `ConcurrentRunner`.
+    ///
+    /// * `num_jobs` - Number of jobs utilized to process files concurrently.
+    /// * `proc_files` - Function that processes each file found during
+    ///   the search.
+    pub fn new(num_jobs: usize, proc_files: ProcFiles) -> Self
+    where
+        ProcFiles: 'static + Fn(PathBuf, &Config) -> std::io::Result<()> + Send + Sync,
+    {
+        let num_jobs = std::cmp::max(2, num_jobs) - 1;
+        Self {
+            proc_files: Box::new(proc_files),
+            proc_dir_paths: Box::new(null_proc_dir_paths),
+            proc_path: Box::new(null_proc_path),
+            num_jobs,
+        }
+    }
+
+    /// Sets the function to process the paths and subpaths contained in a
+    /// directory.
+    pub fn set_proc_dir_paths(mut self, proc_dir_paths: ProcDirPaths) -> Self
+    where
+        ProcDirPaths:
+            'static + Fn(&mut HashMap>, &Path, &Config) + Send + Sync,
+    {
+        self.proc_dir_paths = Box::new(proc_dir_paths);
+        self
+    }
+
+    /// Sets the function to process a single path.
+    pub fn set_proc_path(mut self, proc_path: ProcPath) -> Self
+    where
+        ProcPath: 'static + Fn(&Path, &Config) + Send + Sync,
+    {
+        self.proc_path = Box::new(proc_path);
+        self
+    }
+
+    /// Runs the producer-consumer approach to process the files
+    /// contained in a directory and in its own subdirectories.
+    ///
+    /// * `config` - Information used to process a file.
+    /// * `files_data` - Information about the files to be included or excluded
+    ///   from a search more the number of paths considered in the search.
+    pub fn run(
+        self,
+        config: Config,
+        files_data: FilesData,
+    ) -> Result>, ConcurrentErrors> {
+        let cfg = Arc::new(config);
+
+        let (sender, receiver) = unbounded();
+
+        let producer = {
+            let sender = sender.clone();
+
+            match thread::Builder::new()
+                .name(String::from("Producer"))
+                .spawn(move || {
+                    explore(
+                        files_data,
+                        &cfg,
+                        self.proc_dir_paths,
+                        self.proc_path,
+                        &sender,
+                    )
+                }) {
+                Ok(producer) => producer,
+                Err(e) => return Err(ConcurrentErrors::Thread(e.to_string())),
+            }
+        };
+
+        let mut receivers = Vec::with_capacity(self.num_jobs);
+        let proc_files = Arc::new(self.proc_files);
+        for i in 0..self.num_jobs {
+            let receiver = receiver.clone();
+            let proc_files = proc_files.clone();
+
+            let t = match thread::Builder::new()
+                .name(format!("Consumer {i}"))
+                .spawn(move || {
+                    consumer(receiver, proc_files);
+                }) {
+                Ok(receiver) => receiver,
+                Err(e) => return Err(ConcurrentErrors::Thread(e.to_string())),
+            };
+
+            receivers.push(t);
+        }
+
+        let all_files = match producer.join() {
+            Ok(res) => res,
+            Err(_) => {
+                return Err(ConcurrentErrors::Producer(
+                    "Child thread panicked".to_owned(),
+                ));
+            }
+        };
+
+        // Poison the receiver, now that the producer is finished.
+        for _ in 0..self.num_jobs {
+            if let Err(e) = sender.send(None) {
+                return Err(ConcurrentErrors::Sender(e.to_string()));
+            }
+        }
+
+        for receiver in receivers {
+            if receiver.join().is_err() {
+                return Err(ConcurrentErrors::Receiver(
+                    "A thread used to process a file panicked".to_owned(),
+                ));
+            }
+        }
+
+        all_files
+    }
+}
diff --git a/src/count.rs b/src/count.rs
new file mode 100644
index 00000000..739c9a53
--- /dev/null
+++ b/src/count.rs
@@ -0,0 +1,89 @@
+extern crate num_format;
+
+use num_format::{Locale, ToFormattedString};
+use std::fmt;
+use std::sync::{Arc, Mutex};
+
+use crate::traits::*;
+
+/// Counts the types of nodes specified in the input slice
+/// and the number of nodes in a code.
+pub fn count(parser: &T, filters: &[String]) -> (usize, usize) {
+    let filters = parser.get_filters(filters);
+    let node = parser.get_root();
+    let mut cursor = node.cursor();
+    let mut stack = Vec::new();
+    let mut good = 0;
+    let mut total = 0;
+
+    stack.push(node);
+
+    while let Some(node) = stack.pop() {
+        total += 1;
+        if filters.any(&node) {
+            good += 1;
+        }
+        cursor.reset(&node);
+        if cursor.goto_first_child() {
+            loop {
+                stack.push(cursor.node());
+                if !cursor.goto_next_sibling() {
+                    break;
+                }
+            }
+        }
+    }
+    (good, total)
+}
+
+/// Configuration options for counting different
+/// types of nodes in a code.
+#[derive(Debug)]
+pub struct CountCfg {
+    /// Types of nodes to count
+    pub filters: Vec,
+    /// Number of nodes of a certain type counted by each thread
+    pub stats: Arc>,
+}
+
+/// Count of different types of nodes in a code.
+#[derive(Debug, Default)]
+pub struct Count {
+    /// The number of specific types of nodes searched in a code
+    pub good: usize,
+    /// The total number of nodes in a code
+    pub total: usize,
+}
+
+impl Callback for Count {
+    type Res = std::io::Result<()>;
+    type Cfg = CountCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        let (good, total) = count(parser, &cfg.filters);
+        let mut results = cfg.stats.lock().unwrap();
+        results.good += good;
+        results.total += total;
+        Ok(())
+    }
+}
+
+impl fmt::Display for Count {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "Total nodes: {}",
+            self.total.to_formatted_string(&Locale::en)
+        )?;
+        writeln!(
+            f,
+            "Found nodes: {}",
+            self.good.to_formatted_string(&Locale::en)
+        )?;
+        write!(
+            f,
+            "Percentage: {:.2}%",
+            (self.good as f64) / (self.total as f64) * 100.
+        )
+    }
+}
diff --git a/src/find.rs b/src/find.rs
new file mode 100644
index 00000000..b6c37b91
--- /dev/null
+++ b/src/find.rs
@@ -0,0 +1,79 @@
+use std::path::PathBuf;
+
+use crate::node::Node;
+
+use crate::dump::*;
+use crate::traits::*;
+
+/// Finds the types of nodes specified in the input slice.
+pub fn find<'a, T: ParserTrait>(parser: &'a T, filters: &[String]) -> Option>> {
+    let filters = parser.get_filters(filters);
+    let node = parser.get_root();
+    let mut cursor = node.cursor();
+    let mut stack = Vec::new();
+    let mut good = Vec::new();
+    let mut children = Vec::new();
+
+    stack.push(node);
+
+    while let Some(node) = stack.pop() {
+        if filters.any(&node) {
+            good.push(node);
+        }
+        cursor.reset(&node);
+        if cursor.goto_first_child() {
+            loop {
+                children.push(cursor.node());
+                if !cursor.goto_next_sibling() {
+                    break;
+                }
+            }
+            for child in children.drain(..).rev() {
+                stack.push(child);
+            }
+        }
+    }
+    Some(good)
+}
+
+/// Configuration options for finding different
+/// types of nodes in a code.
+#[derive(Debug)]
+pub struct FindCfg {
+    /// Path to the file containing the code
+    pub path: PathBuf,
+    /// Types of nodes to find
+    pub filters: Vec,
+    /// The first line of code considered in the search
+    ///
+    /// If `None`, the search starts from the
+    /// first line of code in a file
+    pub line_start: Option,
+    /// The end line of code considered in the search
+    ///
+    /// If `None`, the search ends at the
+    /// last line of code in a file
+    pub line_end: Option,
+}
+
+pub struct Find {
+    _guard: (),
+}
+
+impl Callback for Find {
+    type Res = std::io::Result<()>;
+    type Cfg = FindCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        if let Some(good) = find(parser, &cfg.filters)
+            && !good.is_empty()
+        {
+            println!("In file {}", cfg.path.to_str().unwrap());
+            for node in good {
+                dump_node(parser.get_code(), &node, 1, cfg.line_start, cfg.line_end)?;
+            }
+            println!();
+        }
+        Ok(())
+    }
+}
diff --git a/src/function.rs b/src/function.rs
new file mode 100644
index 00000000..d7be98ef
--- /dev/null
+++ b/src/function.rs
@@ -0,0 +1,133 @@
+use std::io::Write;
+use std::path::PathBuf;
+
+use serde::Serialize;
+use termcolor::{Color, ColorChoice, StandardStream, StandardStreamLock};
+
+use crate::traits::*;
+
+use crate::checker::Checker;
+use crate::getter::Getter;
+
+use crate::tools::{color, intense_color};
+
+/// Function span data.
+#[derive(Debug, Serialize)]
+pub struct FunctionSpan {
+    /// The function name
+    pub name: String,
+    /// The first line of a function
+    pub start_line: usize,
+    /// The last line of a function
+    pub end_line: usize,
+    /// If `true`, an error is occurred in determining the span
+    /// of a function
+    pub error: bool,
+}
+
+/// Detects the span of each function in a code.
+///
+/// Returns a vector containing the [`FunctionSpan`] of each function
+///
+/// [`FunctionSpan`]: struct.FunctionSpan.html
+pub fn function(parser: &T) -> Vec {
+    let root = parser.get_root();
+    let code = parser.get_code();
+    let mut spans = Vec::new();
+    root.act_on_node(&mut |n| {
+        if T::Checker::is_func(n) {
+            let start_line = n.start_row() + 1;
+            let end_line = n.end_row() + 1;
+            if let Some(name) = T::Getter::get_func_name(n, code) {
+                spans.push(FunctionSpan {
+                    name: name.to_string(),
+                    start_line,
+                    end_line,
+                    error: false,
+                });
+            } else {
+                spans.push(FunctionSpan {
+                    name: "".to_string(),
+                    start_line,
+                    end_line,
+                    error: true,
+                });
+            }
+        }
+    });
+
+    spans
+}
+
+fn dump_span(
+    span: FunctionSpan,
+    stdout: &mut StandardStreamLock,
+    last: bool,
+) -> std::io::Result<()> {
+    /*if !span.error {
+        return Ok(());
+    }*/
+
+    let pref = if last { "   `- " } else { "   |- " };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{pref}")?;
+
+    if span.error {
+        intense_color(stdout, Color::Red)?;
+        write!(stdout, "error: ")?;
+    } else {
+        intense_color(stdout, Color::Magenta)?;
+        write!(stdout, "{}: ", span.name)?;
+    }
+
+    color(stdout, Color::Green)?;
+    write!(stdout, "from line ")?;
+
+    color(stdout, Color::White)?;
+    write!(stdout, "{}", span.start_line)?;
+
+    color(stdout, Color::Green)?;
+    write!(stdout, " to line ")?;
+
+    color(stdout, Color::White)?;
+    writeln!(stdout, "{}.", span.end_line)
+}
+
+fn dump_spans(mut spans: Vec, path: PathBuf) -> std::io::Result<()> {
+    if !spans.is_empty() {
+        let stdout = StandardStream::stdout(ColorChoice::Always);
+        let mut stdout = stdout.lock();
+
+        intense_color(&mut stdout, Color::Yellow)?;
+        writeln!(&mut stdout, "In file {}", path.to_str().unwrap_or("..."))?;
+
+        for span in spans.drain(..spans.len() - 1) {
+            dump_span(span, &mut stdout, false)?;
+        }
+        dump_span(spans.pop().unwrap(), &mut stdout, true)?;
+        color(&mut stdout, Color::White)?;
+    }
+    Ok(())
+}
+
+/// Configuration options for detecting the span of
+/// each function in a code.
+#[derive(Debug)]
+pub struct FunctionCfg {
+    /// Path to the file containing the code
+    pub path: PathBuf,
+}
+
+pub struct Function {
+    _guard: (),
+}
+
+impl Callback for Function {
+    type Res = std::io::Result<()>;
+    type Cfg = FunctionCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        dump_spans(function(parser), cfg.path)
+    }
+}
diff --git a/src/getter.rs b/src/getter.rs
new file mode 100644
index 00000000..75a34224
--- /dev/null
+++ b/src/getter.rs
@@ -0,0 +1,331 @@
+use crate::metrics::halstead::HalsteadType;
+
+use crate::spaces::SpaceKind;
+
+use crate::*;
+
+macro_rules! get_operator {
+    ($language:ident) => {
+        #[inline(always)]
+        fn get_operator_id_as_str(id: u16) -> &'static str {
+            let typ = id.into();
+            match typ {
+                $language::LPAREN => "()",
+                $language::LBRACK => "[]",
+                $language::LBRACE => "{}",
+                _ => typ.into(),
+            }
+        }
+    };
+}
+
+pub trait Getter {
+    fn get_func_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
+        Self::get_func_space_name(node, code)
+    }
+
+    fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
+        // we're in a function or in a class
+        if let Some(name) = node.child_by_field_name("name") {
+            let code = &code[name.start_byte()..name.end_byte()];
+            std::str::from_utf8(code).ok()
+        } else {
+            Some("")
+        }
+    }
+
+    fn get_space_kind(_node: &Node) -> SpaceKind {
+        SpaceKind::Unknown
+    }
+
+    fn get_op_type(_node: &Node) -> HalsteadType {
+        HalsteadType::Unknown
+    }
+
+    fn get_operator_id_as_str(_id: u16) -> &'static str {
+        ""
+    }
+}
+
+impl Getter for PythonCode {
+    fn get_space_kind(node: &Node) -> SpaceKind {
+        match node.kind_id().into() {
+            Python::FunctionDefinition => SpaceKind::Function,
+            Python::ClassDefinition => SpaceKind::Class,
+            Python::Module => SpaceKind::Unit,
+            _ => SpaceKind::Unknown,
+        }
+    }
+
+    fn get_op_type(node: &Node) -> HalsteadType {
+        use Python::*;
+
+        match node.kind_id().into() {
+            Import | DOT | From | COMMA | As | STAR | GTGT | Assert | COLONEQ | Return | Def
+            | Del | Raise | Pass | Break | Continue | If | Elif | Else | Async | For | In
+            | While | Try | Except | Finally | With | DASHGT | EQ | Global | Exec | AT | Not
+            | And | Or | PLUS | DASH | SLASH | PERCENT | SLASHSLASH | STARSTAR | PIPE | AMP
+            | CARET | LTLT | TILDE | LT | LTEQ | EQEQ | BANGEQ | GTEQ | GT | LTGT | Is | PLUSEQ
+            | DASHEQ | STAREQ | SLASHEQ | ATEQ | SLASHSLASHEQ | PERCENTEQ | STARSTAREQ | GTGTEQ
+            | LTLTEQ | AMPEQ | CARETEQ | PIPEEQ | Yield | Await | Await2 | Print => {
+                HalsteadType::Operator
+            }
+            Identifier | Integer | Float | True | False | None => HalsteadType::Operand,
+            String => {
+                let mut operator = HalsteadType::Unknown;
+                // check if we've a documentation string or a multiline comment
+                if let Some(parent) = node.parent()
+                    && (parent.kind_id() != ExpressionStatement || parent.child_count() != 1)
+                {
+                    operator = HalsteadType::Operand;
+                };
+                operator
+            }
+            _ => HalsteadType::Unknown,
+        }
+    }
+
+    fn get_operator_id_as_str(id: u16) -> &'static str {
+        Into::::into(id).into()
+    }
+}
+
+impl Getter for TypescriptCode {
+    fn get_space_kind(node: &Node) -> SpaceKind {
+        use Typescript::*;
+
+        match node.kind_id().into() {
+            FunctionExpression
+            | MethodDefinition
+            | GeneratorFunction
+            | FunctionDeclaration
+            | GeneratorFunctionDeclaration
+            | ArrowFunction => SpaceKind::Function,
+            Class | ClassDeclaration => SpaceKind::Class,
+            InterfaceDeclaration => SpaceKind::Interface,
+            Program => SpaceKind::Unit,
+            _ => SpaceKind::Unknown,
+        }
+    }
+
+    fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
+        if let Some(name) = node.child_by_field_name("name") {
+            let code = &code[name.start_byte()..name.end_byte()];
+            std::str::from_utf8(code).ok()
+        } else {
+            // We can be in a pair: foo: function() {}
+            // Or in a variable declaration: var aFun = function() {}
+            if let Some(parent) = node.parent() {
+                match parent.kind_id().into() {
+                    Typescript::Pair => {
+                        if let Some(name) = parent.child_by_field_name("key") {
+                            let code = &code[name.start_byte()..name.end_byte()];
+                            return std::str::from_utf8(code).ok();
+                        }
+                    }
+                    Typescript::VariableDeclarator => {
+                        if let Some(name) = parent.child_by_field_name("name") {
+                            let code = &code[name.start_byte()..name.end_byte()];
+                            return std::str::from_utf8(code).ok();
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            Some("")
+        }
+    }
+
+    fn get_op_type(node: &Node) -> HalsteadType {
+        use Typescript::*;
+
+        match node.kind_id().into() {
+            Export | Import | Import2 | Extends | DOT | From | LPAREN | COMMA | As | STAR
+            | GTGT | GTGTGT | COLON | Return | Delete | Throw | Break | Continue | If | Else
+            | Switch | Case | Default | Async | For | In | Of | While | Try | Catch | Finally
+            | With | EQ | AT | AMPAMP | PIPEPIPE | PLUS | DASH | DASHDASH | PLUSPLUS | SLASH
+            | PERCENT | STARSTAR | PIPE | AMP | LTLT | TILDE | LT | LTEQ | EQEQ | BANGEQ | GTEQ
+            | GT | PLUSEQ | BANG | BANGEQEQ | EQEQEQ | DASHEQ | STAREQ | SLASHEQ | PERCENTEQ
+            | STARSTAREQ | GTGTEQ | GTGTGTEQ | LTLTEQ | AMPEQ | CARET | CARETEQ | PIPEEQ
+            | Yield | LBRACK | LBRACE | Await | QMARK | QMARKQMARK | New | Let | Var | Const
+            | Function | FunctionExpression | SEMI => HalsteadType::Operator,
+            Identifier | NestedIdentifier | MemberExpression | PropertyIdentifier | String
+            | Number | True | False | Null | Void | This | Super | Undefined | Set | Get
+            | Typeof | Instanceof => HalsteadType::Operand,
+            _ => HalsteadType::Unknown,
+        }
+    }
+
+    get_operator!(Typescript);
+}
+
+impl Getter for TsxCode {
+    fn get_space_kind(node: &Node) -> SpaceKind {
+        use Tsx::*;
+
+        match node.kind_id().into() {
+            FunctionExpression
+            | MethodDefinition
+            | GeneratorFunction
+            | FunctionDeclaration
+            | GeneratorFunctionDeclaration
+            | ArrowFunction => SpaceKind::Function,
+            Class | ClassDeclaration => SpaceKind::Class,
+            InterfaceDeclaration => SpaceKind::Interface,
+            Program => SpaceKind::Unit,
+            _ => SpaceKind::Unknown,
+        }
+    }
+
+    fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
+        if let Some(name) = node.child_by_field_name("name") {
+            let code = &code[name.start_byte()..name.end_byte()];
+            std::str::from_utf8(code).ok()
+        } else {
+            // We can be in a pair: foo: function() {}
+            // Or in a variable declaration: var aFun = function() {}
+            if let Some(parent) = node.parent() {
+                match parent.kind_id().into() {
+                    Tsx::Pair => {
+                        if let Some(name) = parent.child_by_field_name("key") {
+                            let code = &code[name.start_byte()..name.end_byte()];
+                            return std::str::from_utf8(code).ok();
+                        }
+                    }
+                    Tsx::VariableDeclarator => {
+                        if let Some(name) = parent.child_by_field_name("name") {
+                            let code = &code[name.start_byte()..name.end_byte()];
+                            return std::str::from_utf8(code).ok();
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            Some("")
+        }
+    }
+
+    fn get_op_type(node: &Node) -> HalsteadType {
+        use Tsx::*;
+
+        match node.kind_id().into() {
+            Export | Import | Import2 | Extends | DOT | From | LPAREN | COMMA | As | STAR
+            | GTGT | GTGTGT | COLON | Return | Delete | Throw | Break | Continue | If | Else
+            | Switch | Case | Default | Async | For | In | Of | While | Try | Catch | Finally
+            | With | EQ | AT | AMPAMP | PIPEPIPE | PLUS | DASH | DASHDASH | PLUSPLUS | SLASH
+            | PERCENT | STARSTAR | PIPE | AMP | LTLT | TILDE | LT | LTEQ | EQEQ | BANGEQ | GTEQ
+            | GT | PLUSEQ | BANG | BANGEQEQ | EQEQEQ | DASHEQ | STAREQ | SLASHEQ | PERCENTEQ
+            | STARSTAREQ | GTGTEQ | GTGTGTEQ | LTLTEQ | AMPEQ | CARET | CARETEQ | PIPEEQ
+            | Yield | LBRACK | LBRACE | Await | QMARK | QMARKQMARK | New | Let | Var | Const
+            | Function | FunctionExpression | SEMI => HalsteadType::Operator,
+            Identifier | NestedIdentifier | MemberExpression | PropertyIdentifier | String
+            | String2 | Number | True | False | Null | Void | This | Super | Undefined | Set
+            | Get | Typeof | Instanceof => HalsteadType::Operand,
+            _ => HalsteadType::Unknown,
+        }
+    }
+
+    get_operator!(Tsx);
+}
+
+impl Getter for RustCode {
+    fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
+        // we're in a function or in a class or an impl
+        // for an impl: we've  'impl ... type {...'
+        if let Some(name) = node
+            .child_by_field_name("name")
+            .or_else(|| node.child_by_field_name("type"))
+        {
+            let code = &code[name.start_byte()..name.end_byte()];
+            std::str::from_utf8(code).ok()
+        } else {
+            Some("")
+        }
+    }
+
+    fn get_space_kind(node: &Node) -> SpaceKind {
+        use Rust::*;
+
+        match node.kind_id().into() {
+            FunctionItem | ClosureExpression => SpaceKind::Function,
+            TraitItem => SpaceKind::Trait,
+            ImplItem => SpaceKind::Impl,
+            SourceFile => SpaceKind::Unit,
+            _ => SpaceKind::Unknown,
+        }
+    }
+
+    fn get_op_type(node: &Node) -> HalsteadType {
+        use Rust::*;
+
+        match node.kind_id().into() {
+            // `||` is treated as an operator only if it's part of a binary expression.
+            // This prevents misclassification inside macros where closures without arguments (e.g., `let closure = || { /* ... */ };`)
+            // are not recognized as `ClosureExpression` and their `||` node is identified as `PIPEPIPE` instead of `ClosureParameters`.
+            //
+            // Similarly, exclude `/` when it corresponds to the third slash in `///` (`OuterDocCommentMarker`)
+            PIPEPIPE | SLASH => match node.parent() {
+                Some(parent) if matches!(parent.kind_id().into(), BinaryExpression) => {
+                    HalsteadType::Operator
+                }
+                _ => HalsteadType::Unknown,
+            },
+            // Ensure `!` is counted as an operator unless it belongs to an `InnerDocCommentMarker` `//!`
+            BANG => match node.parent() {
+                Some(parent) if !matches!(parent.kind_id().into(), InnerDocCommentMarker) => {
+                    HalsteadType::Operator
+                }
+                _ => HalsteadType::Unknown,
+            },
+            LPAREN | LBRACE | LBRACK | EQGT | PLUS | STAR | Async | Await | Continue | For | If
+            | Let | Loop | Match | Return | Unsafe | While | EQ | COMMA | DASHGT | QMARK | LT
+            | GT | AMP | MutableSpecifier | DOTDOT | DOTDOTEQ | DASH | AMPAMP | PIPE | CARET
+            | EQEQ | BANGEQ | LTEQ | GTEQ | LTLT | GTGT | PERCENT | PLUSEQ | DASHEQ | STAREQ
+            | SLASHEQ | PERCENTEQ | AMPEQ | PIPEEQ | CARETEQ | LTLTEQ | GTGTEQ | Move | DOT
+            | PrimitiveType | Fn | SEMI => HalsteadType::Operator,
+            Identifier | StringLiteral | RawStringLiteral | IntegerLiteral | FloatLiteral
+            | BooleanLiteral | Zelf | CharLiteral | UNDERSCORE => HalsteadType::Operand,
+            _ => HalsteadType::Unknown,
+        }
+    }
+
+    get_operator!(Rust);
+}
+
+impl Getter for GoCode {
+    fn get_space_kind(node: &Node) -> SpaceKind {
+        use crate::Go::*;
+        match node.kind_id().into() {
+            FunctionDeclaration | MethodDeclaration | FuncLiteral => SpaceKind::Function,
+            SourceFile => SpaceKind::Unit,
+            _ => SpaceKind::Unknown,
+        }
+    }
+
+    fn get_op_type(node: &Node) -> HalsteadType {
+        use crate::Go::*;
+        match node.kind_id().into() {
+            // Operators: keywords and control flow
+            // Note: Go::Go is the `go` keyword for goroutines
+            Func | Go | Defer | Return | If | Else | For | Range | Switch | Select
+            | Case | Default | Break | Continue | Goto | Fallthrough | Chan | Map | Struct
+            | Interface | Type | Var | Const | Package | Import
+            // Operators: punctuation
+            | DOT | COMMA | SEMI | COLON | COLONEQ | EQ
+            | PLUSEQ | DASHEQ | STAREQ | SLASHEQ | PERCENTEQ
+            | AMPEQ | PIPEEQ | CARETEQ | LTLTEQ | GTGTEQ | AMPCARETEQ
+            // Operators: arithmetic/logic
+            | PLUS | DASH | STAR | SLASH | PERCENT | AMP | PIPE | CARET | LTLT | GTGT
+            | AMPAMP | PIPEPIPE | AMPCARET | PLUSPLUS | DASHDASH
+            | EQEQ | BANGEQ | LT | LTEQ | GT | GTEQ | BANG
+            | LPAREN | LBRACK | LBRACE | DOTDOTDOT => HalsteadType::Operator,
+            // Operands
+            Identifier | IntLiteral | FloatLiteral | ImaginaryLiteral | RuneLiteral
+            | RawStringLiteral | InterpretedStringLiteral | True | False | Nil
+            | Iota => HalsteadType::Operand,
+            _ => HalsteadType::Unknown,
+        }
+    }
+
+    get_operator!(Go);
+}
diff --git a/src/langs.rs b/src/langs.rs
new file mode 100644
index 00000000..0e6bca26
--- /dev/null
+++ b/src/langs.rs
@@ -0,0 +1,76 @@
+use std::path::Path;
+use std::sync::Arc;
+use tree_sitter::Language;
+
+use crate::macros::{
+    get_language, mk_action, mk_code, mk_emacs_mode, mk_extensions, mk_lang, mk_langs,
+};
+use crate::preproc::PreprocResults;
+use crate::*;
+
+mk_langs!(
+    // 1) Name for enum
+    // 2) Language description
+    // 3) Display name
+    // 4) Empty struct name to implement
+    // 5) Parser name
+    // 6) tree-sitter function to call to get a Language
+    // 7) file extensions
+    // 8) emacs modes
+    (
+        Rust,
+        "The `Rust` language",
+        "rust",
+        RustCode,
+        RustParser,
+        tree_sitter_rust,
+        [rs],
+        ["rust"]
+    ),
+    (
+        Python,
+        "The `Python` language",
+        "python",
+        PythonCode,
+        PythonParser,
+        tree_sitter_python,
+        [py],
+        ["python"]
+    ),
+    (
+        Tsx,
+        "The `Tsx` language incorporates the `JSX` syntax inside `TypeScript`",
+        "typescript",
+        TsxCode,
+        TsxParser,
+        tree_sitter_tsx,
+        [tsx],
+        []
+    ),
+    (
+        Typescript,
+        "The `TypeScript` language",
+        "typescript",
+        TypescriptCode,
+        TypescriptParser,
+        tree_sitter_typescript,
+        [ts, jsw, jsmw],
+        ["typescript"]
+    ),
+    (
+        Go,
+        "The `Go` language",
+        "go",
+        GoCode,
+        GoParser,
+        tree_sitter_go,
+        [go],
+        ["go"]
+    )
+);
+
+pub(crate) mod fake {
+    pub(crate) fn get_true<'a>(_ext: &str, _mode: &str) -> Option<&'a str> {
+        None
+    }
+}
diff --git a/crates/mehen-go/src/grammar.rs b/src/languages/language_go.rs
similarity index 98%
rename from crates/mehen-go/src/grammar.rs
rename to src/languages/language_go.rs
index 6f8ad0a3..7f996935 100644
--- a/crates/mehen-go/src/grammar.rs
+++ b/src/languages/language_go.rs
@@ -1,17 +1,14 @@
 // Code generated; DO NOT EDIT.
 
-#![allow(clippy::enum_variant_names)]
-#![allow(clippy::upper_case_acronyms)]
-
 use num_derive::FromPrimitive;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, FromPrimitive)]
-pub(crate) enum Go {
+#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)]
+pub enum Go {
     End = 0,
     Identifier = 1,
     SourceFileToken1 = 2,
     SEMI = 3,
-    EMPTY = 4,
+    LF = 4,
     Package = 5,
     Import = 6,
     DOT = 7,
@@ -237,7 +234,7 @@ impl From for &'static str {
             Go::Identifier => "identifier",
             Go::SourceFileToken1 => "source_file_token1",
             Go::SEMI => ";",
-            Go::EMPTY => "",
+            Go::LF => "\n",
             Go::Package => "package",
             Go::Import => "import",
             Go::DOT => ".",
@@ -370,7 +367,7 @@ impl From for &'static str {
             Go::ChannelType => "channel_type",
             Go::FunctionType => "function_type",
             Go::Block => "block",
-            Go::StatementList => "statement_list",
+            Go::StatementList => "_statement_list",
             Go::Statement => "_statement",
             Go::EmptyStatement => "empty_statement",
             Go::SimpleStatement => "_simple_statement",
@@ -439,7 +436,7 @@ impl From for &'static str {
             Go::FieldDeclarationRepeat1 => "field_declaration_repeat1",
             Go::InterfaceTypeRepeat1 => "interface_type_repeat1",
             Go::TypeElemRepeat1 => "type_elem_repeat1",
-            Go::StatementListRepeat1 => "statement_list_repeat1",
+            Go::StatementListRepeat1 => "_statement_list_repeat1",
             Go::ExpressionSwitchStatementRepeat1 => "expression_switch_statement_repeat1",
             Go::TypeSwitchStatementRepeat1 => "type_switch_statement_repeat1",
             Go::TypeCaseRepeat1 => "type_case_repeat1",
diff --git a/src/languages/language_python.rs b/src/languages/language_python.rs
new file mode 100644
index 00000000..1d12c16d
--- /dev/null
+++ b/src/languages/language_python.rs
@@ -0,0 +1,590 @@
+// Code generated; DO NOT EDIT.
+
+use num_derive::FromPrimitive;
+
+#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)]
+pub enum Python {
+    End = 0,
+    Identifier = 1,
+    SEMI = 2,
+    Import = 3,
+    DOT = 4,
+    From = 5,
+    Future = 6,
+    LPAREN = 7,
+    RPAREN = 8,
+    COMMA = 9,
+    As = 10,
+    STAR = 11,
+    Print = 12,
+    GTGT = 13,
+    Assert = 14,
+    COLONEQ = 15,
+    Return = 16,
+    Del = 17,
+    Raise = 18,
+    Pass = 19,
+    Break = 20,
+    Continue = 21,
+    If = 22,
+    COLON = 23,
+    Elif = 24,
+    Else = 25,
+    Match = 26,
+    Case = 27,
+    Async = 28,
+    For = 29,
+    In = 30,
+    While = 31,
+    Try = 32,
+    Except = 33,
+    ExceptSTAR = 34,
+    Finally = 35,
+    With = 36,
+    Def = 37,
+    DASHGT = 38,
+    STARSTAR = 39,
+    Global = 40,
+    Nonlocal = 41,
+    Exec = 42,
+    Type2 = 43,
+    EQ = 44,
+    Class = 45,
+    LBRACK = 46,
+    RBRACK = 47,
+    AT = 48,
+    DASH = 49,
+    UNDERSCORE = 50,
+    PIPE = 51,
+    LBRACE = 52,
+    RBRACE = 53,
+    PLUS = 54,
+    Not = 55,
+    And = 56,
+    Or = 57,
+    SLASH = 58,
+    PERCENT = 59,
+    SLASHSLASH = 60,
+    AMP = 61,
+    CARET = 62,
+    LTLT = 63,
+    TILDE = 64,
+    Is = 65,
+    LT = 66,
+    LTEQ = 67,
+    EQEQ = 68,
+    BANGEQ = 69,
+    GTEQ = 70,
+    GT = 71,
+    LTGT = 72,
+    Lambda3 = 73,
+    PLUSEQ = 74,
+    DASHEQ = 75,
+    STAREQ = 76,
+    SLASHEQ = 77,
+    ATEQ = 78,
+    SLASHSLASHEQ = 79,
+    PERCENTEQ = 80,
+    STARSTAREQ = 81,
+    GTGTEQ = 82,
+    LTLTEQ = 83,
+    AMPEQ = 84,
+    CARETEQ = 85,
+    PIPEEQ = 86,
+    Yield2 = 87,
+    Ellipsis = 88,
+    EscapeSequence = 89,
+    BSLASH = 90,
+    FormatSpecifierToken1 = 91,
+    TypeConversion = 92,
+    Integer = 93,
+    Float = 94,
+    Await2 = 95,
+    True = 96,
+    False = 97,
+    None = 98,
+    Comment = 99,
+    LineContinuation = 100,
+    Newline = 101,
+    Indent = 102,
+    Dedent = 103,
+    StringStart = 104,
+    StringContent2 = 105,
+    EscapeInterpolation = 106,
+    StringEnd = 107,
+    Module = 108,
+    Statement = 109,
+    SimpleStatements = 110,
+    ImportStatement = 111,
+    ImportPrefix = 112,
+    RelativeImport = 113,
+    FutureImportStatement = 114,
+    ImportFromStatement = 115,
+    ImportList = 116,
+    AliasedImport = 117,
+    WildcardImport = 118,
+    PrintStatement = 119,
+    Chevron = 120,
+    AssertStatement = 121,
+    ExpressionStatement = 122,
+    NamedExpression = 123,
+    NamedExpressionLhs = 124,
+    ReturnStatement = 125,
+    DeleteStatement = 126,
+    RaiseStatement = 127,
+    PassStatement = 128,
+    BreakStatement = 129,
+    ContinueStatement = 130,
+    IfStatement = 131,
+    ElifClause = 132,
+    ElseClause = 133,
+    MatchStatement = 134,
+    Block = 135,
+    CaseClause = 136,
+    ForStatement = 137,
+    WhileStatement = 138,
+    TryStatement = 139,
+    ExceptClause = 140,
+    ExceptGroupClause = 141,
+    FinallyClause = 142,
+    WithStatement = 143,
+    WithClause = 144,
+    WithItem = 145,
+    FunctionDefinition = 146,
+    Parameters = 147,
+    LambdaParameters = 148,
+    ListSplat = 149,
+    DictionarySplat = 150,
+    GlobalStatement = 151,
+    NonlocalStatement = 152,
+    ExecStatement = 153,
+    TypeAliasStatement = 154,
+    ClassDefinition = 155,
+    TypeParameter = 156,
+    ParenthesizedListSplat = 157,
+    ArgumentList = 158,
+    DecoratedDefinition = 159,
+    Decorator = 160,
+    Block2 = 161,
+    ExpressionList = 162,
+    DottedName = 163,
+    CasePattern = 164,
+    SimplePattern = 165,
+    AsPattern = 166,
+    UnionPattern = 167,
+    ListPattern = 168,
+    TuplePattern = 169,
+    DictPattern = 170,
+    KeyValuePattern = 171,
+    KeywordPattern = 172,
+    SplatPattern = 173,
+    ClassPattern = 174,
+    ComplexPattern = 175,
+    Parameters2 = 176,
+    Patterns = 177,
+    Parameter = 178,
+    Pattern = 179,
+    TuplePattern2 = 180,
+    ListPattern2 = 181,
+    DefaultParameter = 182,
+    TypedDefaultParameter = 183,
+    ListSplatPattern = 184,
+    DictionarySplatPattern = 185,
+    AsPattern2 = 186,
+    ExpressionWithinForInClause = 187,
+    Expression = 188,
+    PrimaryExpression = 189,
+    NotOperator = 190,
+    BooleanOperator = 191,
+    BinaryOperator = 192,
+    UnaryOperator = 193,
+    Notin = 194,
+    Isnot = 195,
+    ComparisonOperator = 196,
+    Lambda = 197,
+    Lambda2 = 198,
+    Assignment = 199,
+    AugmentedAssignment = 200,
+    PatternList = 201,
+    RightHandSide = 202,
+    Yield = 203,
+    Attribute = 204,
+    Subscript = 205,
+    Slice = 206,
+    Call = 207,
+    TypedParameter = 208,
+    Type = 209,
+    SplatType = 210,
+    GenericType = 211,
+    UnionType = 212,
+    ConstrainedType = 213,
+    MemberType = 214,
+    KeywordArgument = 215,
+    List = 216,
+    Set = 217,
+    Tuple = 218,
+    Dictionary = 219,
+    Pair = 220,
+    ListComprehension = 221,
+    DictionaryComprehension = 222,
+    SetComprehension = 223,
+    GeneratorExpression = 224,
+    ComprehensionClauses = 225,
+    ParenthesizedExpression = 226,
+    CollectionElements = 227,
+    ForInClause = 228,
+    IfClause = 229,
+    ConditionalExpression = 230,
+    ConcatenatedString = 231,
+    String = 232,
+    StringContent = 233,
+    Interpolation = 234,
+    FExpression = 235,
+    NotEscapeSequence = 236,
+    FormatSpecifier = 237,
+    Await = 238,
+    PositionalSeparator = 239,
+    KeywordSeparator = 240,
+    ModuleRepeat1 = 241,
+    SimpleStatementsRepeat1 = 242,
+    ImportPrefixRepeat1 = 243,
+    ImportListRepeat1 = 244,
+    PrintStatementRepeat1 = 245,
+    AssertStatementRepeat1 = 246,
+    IfStatementRepeat1 = 247,
+    MatchStatementRepeat1 = 248,
+    MatchBlockRepeat1 = 249,
+    CaseClauseRepeat1 = 250,
+    TryStatementRepeat1 = 251,
+    TryStatementRepeat2 = 252,
+    WithClauseRepeat1 = 253,
+    GlobalStatementRepeat1 = 254,
+    TypeParameterRepeat1 = 255,
+    ArgumentListRepeat1 = 256,
+    DecoratedDefinitionRepeat1 = 257,
+    DottedNameRepeat1 = 258,
+    UnionPatternRepeat1 = 259,
+    DictPatternRepeat1 = 260,
+    ParametersRepeat1 = 261,
+    PatternsRepeat1 = 262,
+    ComparisonOperatorRepeat1 = 263,
+    SubscriptRepeat1 = 264,
+    DictionaryRepeat1 = 265,
+    ComprehensionClausesRepeat1 = 266,
+    CollectionElementsRepeat1 = 267,
+    ForInClauseRepeat1 = 268,
+    ConcatenatedStringRepeat1 = 269,
+    StringRepeat1 = 270,
+    StringContentRepeat1 = 271,
+    FormatSpecifierRepeat1 = 272,
+    AsPatternTarget = 273,
+    FormatExpression = 274,
+    Error = 275,
+}
+
+impl From for &'static str {
+    #[inline(always)]
+    fn from(tok: Python) -> Self {
+        match tok {
+            Python::End => "end",
+            Python::Identifier => "identifier",
+            Python::SEMI => ";",
+            Python::Import => "import",
+            Python::DOT => ".",
+            Python::From => "from",
+            Python::Future => "__future__",
+            Python::LPAREN => "(",
+            Python::RPAREN => ")",
+            Python::COMMA => ",",
+            Python::As => "as",
+            Python::STAR => "*",
+            Python::Print => "print",
+            Python::GTGT => ">>",
+            Python::Assert => "assert",
+            Python::COLONEQ => ":=",
+            Python::Return => "return",
+            Python::Del => "del",
+            Python::Raise => "raise",
+            Python::Pass => "pass",
+            Python::Break => "break",
+            Python::Continue => "continue",
+            Python::If => "if",
+            Python::COLON => ":",
+            Python::Elif => "elif",
+            Python::Else => "else",
+            Python::Match => "match",
+            Python::Case => "case",
+            Python::Async => "async",
+            Python::For => "for",
+            Python::In => "in",
+            Python::While => "while",
+            Python::Try => "try",
+            Python::Except => "except",
+            Python::ExceptSTAR => "except*",
+            Python::Finally => "finally",
+            Python::With => "with",
+            Python::Def => "def",
+            Python::DASHGT => "->",
+            Python::STARSTAR => "**",
+            Python::Global => "global",
+            Python::Nonlocal => "nonlocal",
+            Python::Exec => "exec",
+            Python::Type2 => "type",
+            Python::EQ => "=",
+            Python::Class => "class",
+            Python::LBRACK => "[",
+            Python::RBRACK => "]",
+            Python::AT => "@",
+            Python::DASH => "-",
+            Python::UNDERSCORE => "_",
+            Python::PIPE => "|",
+            Python::LBRACE => "{",
+            Python::RBRACE => "}",
+            Python::PLUS => "+",
+            Python::Not => "not",
+            Python::And => "and",
+            Python::Or => "or",
+            Python::SLASH => "/",
+            Python::PERCENT => "%",
+            Python::SLASHSLASH => "//",
+            Python::AMP => "&",
+            Python::CARET => "^",
+            Python::LTLT => "<<",
+            Python::TILDE => "~",
+            Python::Is => "is",
+            Python::LT => "<",
+            Python::LTEQ => "<=",
+            Python::EQEQ => "==",
+            Python::BANGEQ => "!=",
+            Python::GTEQ => ">=",
+            Python::GT => ">",
+            Python::LTGT => "<>",
+            Python::Lambda3 => "lambda",
+            Python::PLUSEQ => "+=",
+            Python::DASHEQ => "-=",
+            Python::STAREQ => "*=",
+            Python::SLASHEQ => "/=",
+            Python::ATEQ => "@=",
+            Python::SLASHSLASHEQ => "//=",
+            Python::PERCENTEQ => "%=",
+            Python::STARSTAREQ => "**=",
+            Python::GTGTEQ => ">>=",
+            Python::LTLTEQ => "<<=",
+            Python::AMPEQ => "&=",
+            Python::CARETEQ => "^=",
+            Python::PIPEEQ => "|=",
+            Python::Yield2 => "yield",
+            Python::Ellipsis => "ellipsis",
+            Python::EscapeSequence => "escape_sequence",
+            Python::BSLASH => "\\",
+            Python::FormatSpecifierToken1 => "format_specifier_token1",
+            Python::TypeConversion => "type_conversion",
+            Python::Integer => "integer",
+            Python::Float => "float",
+            Python::Await2 => "await",
+            Python::True => "true",
+            Python::False => "false",
+            Python::None => "none",
+            Python::Comment => "comment",
+            Python::LineContinuation => "line_continuation",
+            Python::Newline => "_newline",
+            Python::Indent => "_indent",
+            Python::Dedent => "_dedent",
+            Python::StringStart => "string_start",
+            Python::StringContent2 => "_string_content",
+            Python::EscapeInterpolation => "escape_interpolation",
+            Python::StringEnd => "string_end",
+            Python::Module => "module",
+            Python::Statement => "_statement",
+            Python::SimpleStatements => "_simple_statements",
+            Python::ImportStatement => "import_statement",
+            Python::ImportPrefix => "import_prefix",
+            Python::RelativeImport => "relative_import",
+            Python::FutureImportStatement => "future_import_statement",
+            Python::ImportFromStatement => "import_from_statement",
+            Python::ImportList => "_import_list",
+            Python::AliasedImport => "aliased_import",
+            Python::WildcardImport => "wildcard_import",
+            Python::PrintStatement => "print_statement",
+            Python::Chevron => "chevron",
+            Python::AssertStatement => "assert_statement",
+            Python::ExpressionStatement => "expression_statement",
+            Python::NamedExpression => "named_expression",
+            Python::NamedExpressionLhs => "_named_expression_lhs",
+            Python::ReturnStatement => "return_statement",
+            Python::DeleteStatement => "delete_statement",
+            Python::RaiseStatement => "raise_statement",
+            Python::PassStatement => "pass_statement",
+            Python::BreakStatement => "break_statement",
+            Python::ContinueStatement => "continue_statement",
+            Python::IfStatement => "if_statement",
+            Python::ElifClause => "elif_clause",
+            Python::ElseClause => "else_clause",
+            Python::MatchStatement => "match_statement",
+            Python::Block => "block",
+            Python::CaseClause => "case_clause",
+            Python::ForStatement => "for_statement",
+            Python::WhileStatement => "while_statement",
+            Python::TryStatement => "try_statement",
+            Python::ExceptClause => "except_clause",
+            Python::ExceptGroupClause => "except_group_clause",
+            Python::FinallyClause => "finally_clause",
+            Python::WithStatement => "with_statement",
+            Python::WithClause => "with_clause",
+            Python::WithItem => "with_item",
+            Python::FunctionDefinition => "function_definition",
+            Python::Parameters => "parameters",
+            Python::LambdaParameters => "lambda_parameters",
+            Python::ListSplat => "list_splat",
+            Python::DictionarySplat => "dictionary_splat",
+            Python::GlobalStatement => "global_statement",
+            Python::NonlocalStatement => "nonlocal_statement",
+            Python::ExecStatement => "exec_statement",
+            Python::TypeAliasStatement => "type_alias_statement",
+            Python::ClassDefinition => "class_definition",
+            Python::TypeParameter => "type_parameter",
+            Python::ParenthesizedListSplat => "parenthesized_list_splat",
+            Python::ArgumentList => "argument_list",
+            Python::DecoratedDefinition => "decorated_definition",
+            Python::Decorator => "decorator",
+            Python::Block2 => "block",
+            Python::ExpressionList => "expression_list",
+            Python::DottedName => "dotted_name",
+            Python::CasePattern => "case_pattern",
+            Python::SimplePattern => "_simple_pattern",
+            Python::AsPattern => "as_pattern",
+            Python::UnionPattern => "union_pattern",
+            Python::ListPattern => "list_pattern",
+            Python::TuplePattern => "tuple_pattern",
+            Python::DictPattern => "dict_pattern",
+            Python::KeyValuePattern => "_key_value_pattern",
+            Python::KeywordPattern => "keyword_pattern",
+            Python::SplatPattern => "splat_pattern",
+            Python::ClassPattern => "class_pattern",
+            Python::ComplexPattern => "complex_pattern",
+            Python::Parameters2 => "_parameters",
+            Python::Patterns => "_patterns",
+            Python::Parameter => "parameter",
+            Python::Pattern => "pattern",
+            Python::TuplePattern2 => "tuple_pattern",
+            Python::ListPattern2 => "list_pattern",
+            Python::DefaultParameter => "default_parameter",
+            Python::TypedDefaultParameter => "typed_default_parameter",
+            Python::ListSplatPattern => "list_splat_pattern",
+            Python::DictionarySplatPattern => "dictionary_splat_pattern",
+            Python::AsPattern2 => "as_pattern",
+            Python::ExpressionWithinForInClause => "_expression_within_for_in_clause",
+            Python::Expression => "expression",
+            Python::PrimaryExpression => "primary_expression",
+            Python::NotOperator => "not_operator",
+            Python::BooleanOperator => "boolean_operator",
+            Python::BinaryOperator => "binary_operator",
+            Python::UnaryOperator => "unary_operator",
+            Python::Notin => "not in",
+            Python::Isnot => "is not",
+            Python::ComparisonOperator => "comparison_operator",
+            Python::Lambda => "lambda",
+            Python::Lambda2 => "lambda",
+            Python::Assignment => "assignment",
+            Python::AugmentedAssignment => "augmented_assignment",
+            Python::PatternList => "pattern_list",
+            Python::RightHandSide => "_right_hand_side",
+            Python::Yield => "yield",
+            Python::Attribute => "attribute",
+            Python::Subscript => "subscript",
+            Python::Slice => "slice",
+            Python::Call => "call",
+            Python::TypedParameter => "typed_parameter",
+            Python::Type => "type",
+            Python::SplatType => "splat_type",
+            Python::GenericType => "generic_type",
+            Python::UnionType => "union_type",
+            Python::ConstrainedType => "constrained_type",
+            Python::MemberType => "member_type",
+            Python::KeywordArgument => "keyword_argument",
+            Python::List => "list",
+            Python::Set => "set",
+            Python::Tuple => "tuple",
+            Python::Dictionary => "dictionary",
+            Python::Pair => "pair",
+            Python::ListComprehension => "list_comprehension",
+            Python::DictionaryComprehension => "dictionary_comprehension",
+            Python::SetComprehension => "set_comprehension",
+            Python::GeneratorExpression => "generator_expression",
+            Python::ComprehensionClauses => "_comprehension_clauses",
+            Python::ParenthesizedExpression => "parenthesized_expression",
+            Python::CollectionElements => "_collection_elements",
+            Python::ForInClause => "for_in_clause",
+            Python::IfClause => "if_clause",
+            Python::ConditionalExpression => "conditional_expression",
+            Python::ConcatenatedString => "concatenated_string",
+            Python::String => "string",
+            Python::StringContent => "string_content",
+            Python::Interpolation => "interpolation",
+            Python::FExpression => "_f_expression",
+            Python::NotEscapeSequence => "_not_escape_sequence",
+            Python::FormatSpecifier => "format_specifier",
+            Python::Await => "await",
+            Python::PositionalSeparator => "positional_separator",
+            Python::KeywordSeparator => "keyword_separator",
+            Python::ModuleRepeat1 => "module_repeat1",
+            Python::SimpleStatementsRepeat1 => "_simple_statements_repeat1",
+            Python::ImportPrefixRepeat1 => "import_prefix_repeat1",
+            Python::ImportListRepeat1 => "_import_list_repeat1",
+            Python::PrintStatementRepeat1 => "print_statement_repeat1",
+            Python::AssertStatementRepeat1 => "assert_statement_repeat1",
+            Python::IfStatementRepeat1 => "if_statement_repeat1",
+            Python::MatchStatementRepeat1 => "match_statement_repeat1",
+            Python::MatchBlockRepeat1 => "_match_block_repeat1",
+            Python::CaseClauseRepeat1 => "case_clause_repeat1",
+            Python::TryStatementRepeat1 => "try_statement_repeat1",
+            Python::TryStatementRepeat2 => "try_statement_repeat2",
+            Python::WithClauseRepeat1 => "with_clause_repeat1",
+            Python::GlobalStatementRepeat1 => "global_statement_repeat1",
+            Python::TypeParameterRepeat1 => "type_parameter_repeat1",
+            Python::ArgumentListRepeat1 => "argument_list_repeat1",
+            Python::DecoratedDefinitionRepeat1 => "decorated_definition_repeat1",
+            Python::DottedNameRepeat1 => "dotted_name_repeat1",
+            Python::UnionPatternRepeat1 => "union_pattern_repeat1",
+            Python::DictPatternRepeat1 => "dict_pattern_repeat1",
+            Python::ParametersRepeat1 => "_parameters_repeat1",
+            Python::PatternsRepeat1 => "_patterns_repeat1",
+            Python::ComparisonOperatorRepeat1 => "comparison_operator_repeat1",
+            Python::SubscriptRepeat1 => "subscript_repeat1",
+            Python::DictionaryRepeat1 => "dictionary_repeat1",
+            Python::ComprehensionClausesRepeat1 => "_comprehension_clauses_repeat1",
+            Python::CollectionElementsRepeat1 => "_collection_elements_repeat1",
+            Python::ForInClauseRepeat1 => "for_in_clause_repeat1",
+            Python::ConcatenatedStringRepeat1 => "concatenated_string_repeat1",
+            Python::StringRepeat1 => "string_repeat1",
+            Python::StringContentRepeat1 => "string_content_repeat1",
+            Python::FormatSpecifierRepeat1 => "format_specifier_repeat1",
+            Python::AsPatternTarget => "as_pattern_target",
+            Python::FormatExpression => "format_expression",
+            Python::Error => "ERROR",
+        }
+    }
+}
+
+impl From for Python {
+    #[inline(always)]
+    fn from(x: u16) -> Self {
+        num::FromPrimitive::from_u16(x).unwrap_or(Self::Error)
+    }
+}
+
+// Python == u16
+impl PartialEq for Python {
+    #[inline(always)]
+    fn eq(&self, x: &u16) -> bool {
+        *self == Into::::into(*x)
+    }
+}
+
+// u16 == Python
+impl PartialEq for u16 {
+    #[inline(always)]
+    fn eq(&self, x: &Python) -> bool {
+        *x == *self
+    }
+}
diff --git a/src/languages/language_rust.rs b/src/languages/language_rust.rs
new file mode 100644
index 00000000..e9b9f8e9
--- /dev/null
+++ b/src/languages/language_rust.rs
@@ -0,0 +1,740 @@
+// Code generated; DO NOT EDIT.
+
+use num_derive::FromPrimitive;
+
+#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)]
+pub enum Rust {
+    End = 0,
+    Identifier = 1,
+    SEMI = 2,
+    MacroRulesBANG = 3,
+    LPAREN = 4,
+    RPAREN = 5,
+    LBRACK = 6,
+    RBRACK = 7,
+    LBRACE = 8,
+    RBRACE = 9,
+    EQGT = 10,
+    COLON = 11,
+    DOLLAR = 12,
+    TokenRepetitionPatternToken1 = 13,
+    PLUS = 14,
+    STAR = 15,
+    QMARK = 16,
+    Block2 = 17,
+    Expr = 18,
+    Ident = 19,
+    Item = 20,
+    Lifetime2 = 21,
+    Literal = 22,
+    Meta = 23,
+    Pat = 24,
+    Path = 25,
+    Stmt = 26,
+    Tt = 27,
+    Ty = 28,
+    Vis = 29,
+    PrimitiveType = 30,
+    PrimitiveType2 = 31,
+    PrimitiveType3 = 32,
+    PrimitiveType4 = 33,
+    PrimitiveType5 = 34,
+    PrimitiveType6 = 35,
+    PrimitiveType7 = 36,
+    PrimitiveType8 = 37,
+    PrimitiveType9 = 38,
+    PrimitiveType10 = 39,
+    PrimitiveType11 = 40,
+    PrimitiveType12 = 41,
+    PrimitiveType13 = 42,
+    PrimitiveType14 = 43,
+    PrimitiveType15 = 44,
+    PrimitiveType16 = 45,
+    PrimitiveType17 = 46,
+    DASH = 47,
+    SLASH = 48,
+    PERCENT = 49,
+    CARET = 50,
+    BANG = 51,
+    AMP = 52,
+    PIPE = 53,
+    AMPAMP = 54,
+    PIPEPIPE = 55,
+    LTLT = 56,
+    GTGT = 57,
+    PLUSEQ = 58,
+    DASHEQ = 59,
+    STAREQ = 60,
+    SLASHEQ = 61,
+    PERCENTEQ = 62,
+    CARETEQ = 63,
+    AMPEQ = 64,
+    PIPEEQ = 65,
+    LTLTEQ = 66,
+    GTGTEQ = 67,
+    EQ = 68,
+    EQEQ = 69,
+    BANGEQ = 70,
+    GT = 71,
+    LT = 72,
+    GTEQ = 73,
+    LTEQ = 74,
+    AT = 75,
+    UNDERSCORE = 76,
+    DOT = 77,
+    DOTDOT = 78,
+    DOTDOTDOT = 79,
+    DOTDOTEQ = 80,
+    COMMA = 81,
+    COLONCOLON = 82,
+    DASHGT = 83,
+    HASH = 84,
+    SQUOTE = 85,
+    As = 86,
+    Async = 87,
+    Await = 88,
+    Break = 89,
+    Const = 90,
+    Continue = 91,
+    Default = 92,
+    Enum = 93,
+    Fn = 94,
+    For = 95,
+    Gen = 96,
+    If = 97,
+    Impl = 98,
+    Let = 99,
+    Loop = 100,
+    Match = 101,
+    Mod = 102,
+    Pub = 103,
+    Return = 104,
+    Static = 105,
+    Struct = 106,
+    Trait = 107,
+    Type = 108,
+    Union = 109,
+    Unsafe = 110,
+    Use = 111,
+    Where = 112,
+    While = 113,
+    Extern = 114,
+    Ref = 115,
+    Else = 116,
+    In = 117,
+    LT2 = 118,
+    Dyn = 119,
+    MutableSpecifier = 120,
+    Raw = 121,
+    Yield = 122,
+    Move = 123,
+    Try = 124,
+    IntegerLiteral = 125,
+    DQUOTE = 126,
+    DQUOTE2 = 127,
+    CharLiteral = 128,
+    EscapeSequence = 129,
+    True = 130,
+    False = 131,
+    SLASHSLASH = 132,
+    LineCommentToken1 = 133,
+    LineCommentToken2 = 134,
+    LineCommentToken3 = 135,
+    BANG2 = 136,
+    SLASH2 = 137,
+    SLASHSTAR = 138,
+    STARSLASH = 139,
+    Shebang = 140,
+    Zelf = 141,
+    Super = 142,
+    Crate = 143,
+    Metavariable = 144,
+    StringContent = 145,
+    RawStringLiteralStart = 146,
+    StringContent2 = 147,
+    RawStringLiteralEnd = 148,
+    FloatLiteral = 149,
+    OuterDocCommentMarker = 150,
+    InnerDocCommentMarker = 151,
+    BlockCommentContent = 152,
+    DocComment = 153,
+    ErrorSentinel = 154,
+    SourceFile = 155,
+    Statement = 156,
+    EmptyStatement = 157,
+    ExpressionStatement = 158,
+    MacroDefinition = 159,
+    MacroRule = 160,
+    TokenPattern = 161,
+    TokenTreePattern = 162,
+    TokenBindingPattern = 163,
+    TokenRepetitionPattern = 164,
+    FragmentSpecifier = 165,
+    TokenTree = 166,
+    TokenRepetition = 167,
+    AttributeItem = 168,
+    InnerAttributeItem = 169,
+    Attribute = 170,
+    ModItem = 171,
+    ForeignModItem = 172,
+    DeclarationList = 173,
+    StructItem = 174,
+    UnionItem = 175,
+    EnumItem = 176,
+    EnumVariantList = 177,
+    EnumVariant = 178,
+    FieldDeclarationList = 179,
+    FieldDeclaration = 180,
+    OrderedFieldDeclarationList = 181,
+    ExternCrateDeclaration = 182,
+    ConstItem = 183,
+    StaticItem = 184,
+    TypeItem = 185,
+    FunctionItem = 186,
+    FunctionSignatureItem = 187,
+    FunctionModifiers = 188,
+    WhereClause = 189,
+    WherePredicate = 190,
+    ImplItem = 191,
+    TraitItem = 192,
+    AssociatedType = 193,
+    TraitBounds = 194,
+    HigherRankedTraitBound = 195,
+    RemovedTraitBound = 196,
+    TypeParameters = 197,
+    ConstParameter = 198,
+    ConstrainedTypeParameter = 199,
+    OptionalTypeParameter = 200,
+    LetDeclaration = 201,
+    UseDeclaration = 202,
+    UseClause = 203,
+    ScopedUseList = 204,
+    UseList = 205,
+    UseAsClause = 206,
+    UseWildcard = 207,
+    Parameters = 208,
+    SelfParameter = 209,
+    VariadicParameter = 210,
+    Parameter = 211,
+    ExternModifier = 212,
+    VisibilityModifier = 213,
+    Type2 = 214,
+    BracketedType = 215,
+    QualifiedType = 216,
+    Lifetime = 217,
+    ArrayType = 218,
+    ForLifetimes = 219,
+    FunctionType = 220,
+    TupleType = 221,
+    UnitType = 222,
+    GenericFunction = 223,
+    GenericType = 224,
+    GenericTypeWithTurbofish = 225,
+    BoundedType = 226,
+    TypeArguments = 227,
+    TypeBinding = 228,
+    ReferenceType = 229,
+    PointerType = 230,
+    NeverType = 231,
+    AbstractType = 232,
+    DynamicType = 233,
+    ExpressionExceptRange = 234,
+    Expression = 235,
+    MacroInvocation = 236,
+    TokenTree2 = 237,
+    DelimTokens = 238,
+    NonDelimToken = 239,
+    ScopedIdentifier = 240,
+    ScopedTypeIdentifier = 241,
+    ScopedTypeIdentifier2 = 242,
+    RangeExpression = 243,
+    UnaryExpression = 244,
+    TryExpression = 245,
+    ReferenceExpression = 246,
+    BinaryExpression = 247,
+    AssignmentExpression = 248,
+    CompoundAssignmentExpr = 249,
+    TypeCastExpression = 250,
+    ReturnExpression = 251,
+    YieldExpression = 252,
+    CallExpression = 253,
+    Arguments = 254,
+    ArrayExpression = 255,
+    ParenthesizedExpression = 256,
+    TupleExpression = 257,
+    UnitExpression = 258,
+    StructExpression = 259,
+    FieldInitializerList = 260,
+    ShorthandFieldInitializer = 261,
+    FieldInitializer = 262,
+    BaseFieldInitializer = 263,
+    IfExpression = 264,
+    LetCondition = 265,
+    LetChain2 = 266,
+    Condition = 267,
+    ElseClause = 268,
+    MatchExpression = 269,
+    MatchBlock = 270,
+    MatchArm = 271,
+    MatchArm2 = 272,
+    MatchPattern = 273,
+    WhileExpression = 274,
+    LoopExpression = 275,
+    ForExpression = 276,
+    ConstBlock = 277,
+    ClosureExpression = 278,
+    ClosureParameters = 279,
+    Label = 280,
+    BreakExpression = 281,
+    ContinueExpression = 282,
+    IndexExpression = 283,
+    AwaitExpression = 284,
+    FieldExpression = 285,
+    UnsafeBlock = 286,
+    AsyncBlock = 287,
+    GenBlock = 288,
+    TryBlock = 289,
+    Block = 290,
+    Pattern = 291,
+    TuplePattern = 292,
+    SlicePattern = 293,
+    TupleStructPattern = 294,
+    StructPattern = 295,
+    FieldPattern = 296,
+    RemainingFieldPattern = 297,
+    MutPattern = 298,
+    RangePattern = 299,
+    RefPattern = 300,
+    CapturedPattern = 301,
+    ReferencePattern = 302,
+    OrPattern = 303,
+    Literal2 = 304,
+    LiteralPattern = 305,
+    NegativeLiteral = 306,
+    StringLiteral = 307,
+    RawStringLiteral = 308,
+    BooleanLiteral = 309,
+    LineComment = 310,
+    LineDocCommentMarker = 311,
+    InnerDocCommentMarker2 = 312,
+    OuterDocCommentMarker2 = 313,
+    BlockComment = 314,
+    BlockDocCommentMarker = 315,
+    SourceFileRepeat1 = 316,
+    MacroDefinitionRepeat1 = 317,
+    TokenTreePatternRepeat1 = 318,
+    TokenTreeRepeat1 = 319,
+    NonSpecialTokenRepeat1 = 320,
+    DeclarationListRepeat1 = 321,
+    EnumVariantListRepeat1 = 322,
+    EnumVariantListRepeat2 = 323,
+    FieldDeclarationListRepeat1 = 324,
+    OrderedFieldDeclarationListRepeat1 = 325,
+    FunctionModifiersRepeat1 = 326,
+    WhereClauseRepeat1 = 327,
+    TraitBoundsRepeat1 = 328,
+    TypeParametersRepeat1 = 329,
+    UseListRepeat1 = 330,
+    ParametersRepeat1 = 331,
+    ForLifetimesRepeat1 = 332,
+    TupleTypeRepeat1 = 333,
+    TypeArgumentsRepeat1 = 334,
+    DelimTokenTreeRepeat1 = 335,
+    ArgumentsRepeat1 = 336,
+    TupleExpressionRepeat1 = 337,
+    FieldInitializerListRepeat1 = 338,
+    MatchBlockRepeat1 = 339,
+    MatchArmRepeat1 = 340,
+    ClosureParametersRepeat1 = 341,
+    TuplePatternRepeat1 = 342,
+    SlicePatternRepeat1 = 343,
+    StructPatternRepeat1 = 344,
+    StringLiteralRepeat1 = 345,
+    FieldIdentifier = 346,
+    LetChain = 347,
+    ShorthandFieldIdentifier = 348,
+    TypeIdentifier = 349,
+    Error = 350,
+}
+
+impl From for &'static str {
+    #[inline(always)]
+    fn from(tok: Rust) -> Self {
+        match tok {
+            Rust::End => "end",
+            Rust::Identifier => "identifier",
+            Rust::SEMI => ";",
+            Rust::MacroRulesBANG => "macro_rules!",
+            Rust::LPAREN => "(",
+            Rust::RPAREN => ")",
+            Rust::LBRACK => "[",
+            Rust::RBRACK => "]",
+            Rust::LBRACE => "{",
+            Rust::RBRACE => "}",
+            Rust::EQGT => "=>",
+            Rust::COLON => ":",
+            Rust::DOLLAR => "$",
+            Rust::TokenRepetitionPatternToken1 => "token_repetition_pattern_token1",
+            Rust::PLUS => "+",
+            Rust::STAR => "*",
+            Rust::QMARK => "?",
+            Rust::Block2 => "block",
+            Rust::Expr => "expr",
+            Rust::Ident => "ident",
+            Rust::Item => "item",
+            Rust::Lifetime2 => "lifetime",
+            Rust::Literal => "literal",
+            Rust::Meta => "meta",
+            Rust::Pat => "pat",
+            Rust::Path => "path",
+            Rust::Stmt => "stmt",
+            Rust::Tt => "tt",
+            Rust::Ty => "ty",
+            Rust::Vis => "vis",
+            Rust::PrimitiveType => "primitive_type",
+            Rust::PrimitiveType2 => "primitive_type",
+            Rust::PrimitiveType3 => "primitive_type",
+            Rust::PrimitiveType4 => "primitive_type",
+            Rust::PrimitiveType5 => "primitive_type",
+            Rust::PrimitiveType6 => "primitive_type",
+            Rust::PrimitiveType7 => "primitive_type",
+            Rust::PrimitiveType8 => "primitive_type",
+            Rust::PrimitiveType9 => "primitive_type",
+            Rust::PrimitiveType10 => "primitive_type",
+            Rust::PrimitiveType11 => "primitive_type",
+            Rust::PrimitiveType12 => "primitive_type",
+            Rust::PrimitiveType13 => "primitive_type",
+            Rust::PrimitiveType14 => "primitive_type",
+            Rust::PrimitiveType15 => "primitive_type",
+            Rust::PrimitiveType16 => "primitive_type",
+            Rust::PrimitiveType17 => "primitive_type",
+            Rust::DASH => "-",
+            Rust::SLASH => "/",
+            Rust::PERCENT => "%",
+            Rust::CARET => "^",
+            Rust::BANG => "!",
+            Rust::AMP => "&",
+            Rust::PIPE => "|",
+            Rust::AMPAMP => "&&",
+            Rust::PIPEPIPE => "||",
+            Rust::LTLT => "<<",
+            Rust::GTGT => ">>",
+            Rust::PLUSEQ => "+=",
+            Rust::DASHEQ => "-=",
+            Rust::STAREQ => "*=",
+            Rust::SLASHEQ => "/=",
+            Rust::PERCENTEQ => "%=",
+            Rust::CARETEQ => "^=",
+            Rust::AMPEQ => "&=",
+            Rust::PIPEEQ => "|=",
+            Rust::LTLTEQ => "<<=",
+            Rust::GTGTEQ => ">>=",
+            Rust::EQ => "=",
+            Rust::EQEQ => "==",
+            Rust::BANGEQ => "!=",
+            Rust::GT => ">",
+            Rust::LT => "<",
+            Rust::GTEQ => ">=",
+            Rust::LTEQ => "<=",
+            Rust::AT => "@",
+            Rust::UNDERSCORE => "_",
+            Rust::DOT => ".",
+            Rust::DOTDOT => "..",
+            Rust::DOTDOTDOT => "...",
+            Rust::DOTDOTEQ => "..=",
+            Rust::COMMA => ",",
+            Rust::COLONCOLON => "::",
+            Rust::DASHGT => "->",
+            Rust::HASH => "#",
+            Rust::SQUOTE => "'",
+            Rust::As => "as",
+            Rust::Async => "async",
+            Rust::Await => "await",
+            Rust::Break => "break",
+            Rust::Const => "const",
+            Rust::Continue => "continue",
+            Rust::Default => "default",
+            Rust::Enum => "enum",
+            Rust::Fn => "fn",
+            Rust::For => "for",
+            Rust::Gen => "gen",
+            Rust::If => "if",
+            Rust::Impl => "impl",
+            Rust::Let => "let",
+            Rust::Loop => "loop",
+            Rust::Match => "match",
+            Rust::Mod => "mod",
+            Rust::Pub => "pub",
+            Rust::Return => "return",
+            Rust::Static => "static",
+            Rust::Struct => "struct",
+            Rust::Trait => "trait",
+            Rust::Type => "type",
+            Rust::Union => "union",
+            Rust::Unsafe => "unsafe",
+            Rust::Use => "use",
+            Rust::Where => "where",
+            Rust::While => "while",
+            Rust::Extern => "extern",
+            Rust::Ref => "ref",
+            Rust::Else => "else",
+            Rust::In => "in",
+            Rust::LT2 => "<",
+            Rust::Dyn => "dyn",
+            Rust::MutableSpecifier => "mutable_specifier",
+            Rust::Raw => "raw",
+            Rust::Yield => "yield",
+            Rust::Move => "move",
+            Rust::Try => "try",
+            Rust::IntegerLiteral => "integer_literal",
+            Rust::DQUOTE => "\"",
+            Rust::DQUOTE2 => "\"",
+            Rust::CharLiteral => "char_literal",
+            Rust::EscapeSequence => "escape_sequence",
+            Rust::True => "true",
+            Rust::False => "false",
+            Rust::SLASHSLASH => "//",
+            Rust::LineCommentToken1 => "line_comment_token1",
+            Rust::LineCommentToken2 => "line_comment_token2",
+            Rust::LineCommentToken3 => "line_comment_token3",
+            Rust::BANG2 => "!",
+            Rust::SLASH2 => "/",
+            Rust::SLASHSTAR => "/*",
+            Rust::STARSLASH => "*/",
+            Rust::Shebang => "shebang",
+            Rust::Zelf => "self",
+            Rust::Super => "super",
+            Rust::Crate => "crate",
+            Rust::Metavariable => "metavariable",
+            Rust::StringContent => "string_content",
+            Rust::RawStringLiteralStart => "_raw_string_literal_start",
+            Rust::StringContent2 => "string_content",
+            Rust::RawStringLiteralEnd => "_raw_string_literal_end",
+            Rust::FloatLiteral => "float_literal",
+            Rust::OuterDocCommentMarker => "outer_doc_comment_marker",
+            Rust::InnerDocCommentMarker => "inner_doc_comment_marker",
+            Rust::BlockCommentContent => "_block_comment_content",
+            Rust::DocComment => "doc_comment",
+            Rust::ErrorSentinel => "_error_sentinel",
+            Rust::SourceFile => "source_file",
+            Rust::Statement => "_statement",
+            Rust::EmptyStatement => "empty_statement",
+            Rust::ExpressionStatement => "expression_statement",
+            Rust::MacroDefinition => "macro_definition",
+            Rust::MacroRule => "macro_rule",
+            Rust::TokenPattern => "_token_pattern",
+            Rust::TokenTreePattern => "token_tree_pattern",
+            Rust::TokenBindingPattern => "token_binding_pattern",
+            Rust::TokenRepetitionPattern => "token_repetition_pattern",
+            Rust::FragmentSpecifier => "fragment_specifier",
+            Rust::TokenTree => "token_tree",
+            Rust::TokenRepetition => "token_repetition",
+            Rust::AttributeItem => "attribute_item",
+            Rust::InnerAttributeItem => "inner_attribute_item",
+            Rust::Attribute => "attribute",
+            Rust::ModItem => "mod_item",
+            Rust::ForeignModItem => "foreign_mod_item",
+            Rust::DeclarationList => "declaration_list",
+            Rust::StructItem => "struct_item",
+            Rust::UnionItem => "union_item",
+            Rust::EnumItem => "enum_item",
+            Rust::EnumVariantList => "enum_variant_list",
+            Rust::EnumVariant => "enum_variant",
+            Rust::FieldDeclarationList => "field_declaration_list",
+            Rust::FieldDeclaration => "field_declaration",
+            Rust::OrderedFieldDeclarationList => "ordered_field_declaration_list",
+            Rust::ExternCrateDeclaration => "extern_crate_declaration",
+            Rust::ConstItem => "const_item",
+            Rust::StaticItem => "static_item",
+            Rust::TypeItem => "type_item",
+            Rust::FunctionItem => "function_item",
+            Rust::FunctionSignatureItem => "function_signature_item",
+            Rust::FunctionModifiers => "function_modifiers",
+            Rust::WhereClause => "where_clause",
+            Rust::WherePredicate => "where_predicate",
+            Rust::ImplItem => "impl_item",
+            Rust::TraitItem => "trait_item",
+            Rust::AssociatedType => "associated_type",
+            Rust::TraitBounds => "trait_bounds",
+            Rust::HigherRankedTraitBound => "higher_ranked_trait_bound",
+            Rust::RemovedTraitBound => "removed_trait_bound",
+            Rust::TypeParameters => "type_parameters",
+            Rust::ConstParameter => "const_parameter",
+            Rust::ConstrainedTypeParameter => "constrained_type_parameter",
+            Rust::OptionalTypeParameter => "optional_type_parameter",
+            Rust::LetDeclaration => "let_declaration",
+            Rust::UseDeclaration => "use_declaration",
+            Rust::UseClause => "_use_clause",
+            Rust::ScopedUseList => "scoped_use_list",
+            Rust::UseList => "use_list",
+            Rust::UseAsClause => "use_as_clause",
+            Rust::UseWildcard => "use_wildcard",
+            Rust::Parameters => "parameters",
+            Rust::SelfParameter => "self_parameter",
+            Rust::VariadicParameter => "variadic_parameter",
+            Rust::Parameter => "parameter",
+            Rust::ExternModifier => "extern_modifier",
+            Rust::VisibilityModifier => "visibility_modifier",
+            Rust::Type2 => "_type",
+            Rust::BracketedType => "bracketed_type",
+            Rust::QualifiedType => "qualified_type",
+            Rust::Lifetime => "lifetime",
+            Rust::ArrayType => "array_type",
+            Rust::ForLifetimes => "for_lifetimes",
+            Rust::FunctionType => "function_type",
+            Rust::TupleType => "tuple_type",
+            Rust::UnitType => "unit_type",
+            Rust::GenericFunction => "generic_function",
+            Rust::GenericType => "generic_type",
+            Rust::GenericTypeWithTurbofish => "generic_type_with_turbofish",
+            Rust::BoundedType => "bounded_type",
+            Rust::TypeArguments => "type_arguments",
+            Rust::TypeBinding => "type_binding",
+            Rust::ReferenceType => "reference_type",
+            Rust::PointerType => "pointer_type",
+            Rust::NeverType => "never_type",
+            Rust::AbstractType => "abstract_type",
+            Rust::DynamicType => "dynamic_type",
+            Rust::ExpressionExceptRange => "_expression_except_range",
+            Rust::Expression => "_expression",
+            Rust::MacroInvocation => "macro_invocation",
+            Rust::TokenTree2 => "token_tree",
+            Rust::DelimTokens => "_delim_tokens",
+            Rust::NonDelimToken => "_non_delim_token",
+            Rust::ScopedIdentifier => "scoped_identifier",
+            Rust::ScopedTypeIdentifier => "scoped_type_identifier",
+            Rust::ScopedTypeIdentifier2 => "scoped_type_identifier",
+            Rust::RangeExpression => "range_expression",
+            Rust::UnaryExpression => "unary_expression",
+            Rust::TryExpression => "try_expression",
+            Rust::ReferenceExpression => "reference_expression",
+            Rust::BinaryExpression => "binary_expression",
+            Rust::AssignmentExpression => "assignment_expression",
+            Rust::CompoundAssignmentExpr => "compound_assignment_expr",
+            Rust::TypeCastExpression => "type_cast_expression",
+            Rust::ReturnExpression => "return_expression",
+            Rust::YieldExpression => "yield_expression",
+            Rust::CallExpression => "call_expression",
+            Rust::Arguments => "arguments",
+            Rust::ArrayExpression => "array_expression",
+            Rust::ParenthesizedExpression => "parenthesized_expression",
+            Rust::TupleExpression => "tuple_expression",
+            Rust::UnitExpression => "unit_expression",
+            Rust::StructExpression => "struct_expression",
+            Rust::FieldInitializerList => "field_initializer_list",
+            Rust::ShorthandFieldInitializer => "shorthand_field_initializer",
+            Rust::FieldInitializer => "field_initializer",
+            Rust::BaseFieldInitializer => "base_field_initializer",
+            Rust::IfExpression => "if_expression",
+            Rust::LetCondition => "let_condition",
+            Rust::LetChain2 => "_let_chain",
+            Rust::Condition => "_condition",
+            Rust::ElseClause => "else_clause",
+            Rust::MatchExpression => "match_expression",
+            Rust::MatchBlock => "match_block",
+            Rust::MatchArm => "match_arm",
+            Rust::MatchArm2 => "match_arm",
+            Rust::MatchPattern => "match_pattern",
+            Rust::WhileExpression => "while_expression",
+            Rust::LoopExpression => "loop_expression",
+            Rust::ForExpression => "for_expression",
+            Rust::ConstBlock => "const_block",
+            Rust::ClosureExpression => "closure_expression",
+            Rust::ClosureParameters => "closure_parameters",
+            Rust::Label => "label",
+            Rust::BreakExpression => "break_expression",
+            Rust::ContinueExpression => "continue_expression",
+            Rust::IndexExpression => "index_expression",
+            Rust::AwaitExpression => "await_expression",
+            Rust::FieldExpression => "field_expression",
+            Rust::UnsafeBlock => "unsafe_block",
+            Rust::AsyncBlock => "async_block",
+            Rust::GenBlock => "gen_block",
+            Rust::TryBlock => "try_block",
+            Rust::Block => "block",
+            Rust::Pattern => "_pattern",
+            Rust::TuplePattern => "tuple_pattern",
+            Rust::SlicePattern => "slice_pattern",
+            Rust::TupleStructPattern => "tuple_struct_pattern",
+            Rust::StructPattern => "struct_pattern",
+            Rust::FieldPattern => "field_pattern",
+            Rust::RemainingFieldPattern => "remaining_field_pattern",
+            Rust::MutPattern => "mut_pattern",
+            Rust::RangePattern => "range_pattern",
+            Rust::RefPattern => "ref_pattern",
+            Rust::CapturedPattern => "captured_pattern",
+            Rust::ReferencePattern => "reference_pattern",
+            Rust::OrPattern => "or_pattern",
+            Rust::Literal2 => "_literal",
+            Rust::LiteralPattern => "_literal_pattern",
+            Rust::NegativeLiteral => "negative_literal",
+            Rust::StringLiteral => "string_literal",
+            Rust::RawStringLiteral => "raw_string_literal",
+            Rust::BooleanLiteral => "boolean_literal",
+            Rust::LineComment => "line_comment",
+            Rust::LineDocCommentMarker => "_line_doc_comment_marker",
+            Rust::InnerDocCommentMarker2 => "inner_doc_comment_marker",
+            Rust::OuterDocCommentMarker2 => "outer_doc_comment_marker",
+            Rust::BlockComment => "block_comment",
+            Rust::BlockDocCommentMarker => "_block_doc_comment_marker",
+            Rust::SourceFileRepeat1 => "source_file_repeat1",
+            Rust::MacroDefinitionRepeat1 => "macro_definition_repeat1",
+            Rust::TokenTreePatternRepeat1 => "token_tree_pattern_repeat1",
+            Rust::TokenTreeRepeat1 => "token_tree_repeat1",
+            Rust::NonSpecialTokenRepeat1 => "_non_special_token_repeat1",
+            Rust::DeclarationListRepeat1 => "declaration_list_repeat1",
+            Rust::EnumVariantListRepeat1 => "enum_variant_list_repeat1",
+            Rust::EnumVariantListRepeat2 => "enum_variant_list_repeat2",
+            Rust::FieldDeclarationListRepeat1 => "field_declaration_list_repeat1",
+            Rust::OrderedFieldDeclarationListRepeat1 => "ordered_field_declaration_list_repeat1",
+            Rust::FunctionModifiersRepeat1 => "function_modifiers_repeat1",
+            Rust::WhereClauseRepeat1 => "where_clause_repeat1",
+            Rust::TraitBoundsRepeat1 => "trait_bounds_repeat1",
+            Rust::TypeParametersRepeat1 => "type_parameters_repeat1",
+            Rust::UseListRepeat1 => "use_list_repeat1",
+            Rust::ParametersRepeat1 => "parameters_repeat1",
+            Rust::ForLifetimesRepeat1 => "for_lifetimes_repeat1",
+            Rust::TupleTypeRepeat1 => "tuple_type_repeat1",
+            Rust::TypeArgumentsRepeat1 => "type_arguments_repeat1",
+            Rust::DelimTokenTreeRepeat1 => "delim_token_tree_repeat1",
+            Rust::ArgumentsRepeat1 => "arguments_repeat1",
+            Rust::TupleExpressionRepeat1 => "tuple_expression_repeat1",
+            Rust::FieldInitializerListRepeat1 => "field_initializer_list_repeat1",
+            Rust::MatchBlockRepeat1 => "match_block_repeat1",
+            Rust::MatchArmRepeat1 => "match_arm_repeat1",
+            Rust::ClosureParametersRepeat1 => "closure_parameters_repeat1",
+            Rust::TuplePatternRepeat1 => "tuple_pattern_repeat1",
+            Rust::SlicePatternRepeat1 => "slice_pattern_repeat1",
+            Rust::StructPatternRepeat1 => "struct_pattern_repeat1",
+            Rust::StringLiteralRepeat1 => "string_literal_repeat1",
+            Rust::FieldIdentifier => "field_identifier",
+            Rust::LetChain => "let_chain",
+            Rust::ShorthandFieldIdentifier => "shorthand_field_identifier",
+            Rust::TypeIdentifier => "type_identifier",
+            Rust::Error => "ERROR",
+        }
+    }
+}
+
+impl From for Rust {
+    #[inline(always)]
+    fn from(x: u16) -> Self {
+        num::FromPrimitive::from_u16(x).unwrap_or(Self::Error)
+    }
+}
+
+// Rust == u16
+impl PartialEq for Rust {
+    #[inline(always)]
+    fn eq(&self, x: &u16) -> bool {
+        *self == Into::::into(*x)
+    }
+}
+
+// u16 == Rust
+impl PartialEq for u16 {
+    #[inline(always)]
+    fn eq(&self, x: &Rust) -> bool {
+        *x == *self
+    }
+}
diff --git a/src/languages/language_tsx.rs b/src/languages/language_tsx.rs
new file mode 100644
index 00000000..e9020451
--- /dev/null
+++ b/src/languages/language_tsx.rs
@@ -0,0 +1,840 @@
+// Code generated; DO NOT EDIT.
+
+use num_derive::FromPrimitive;
+
+#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)]
+pub enum Tsx {
+    End = 0,
+    Identifier = 1,
+    HashBangLine = 2,
+    Export = 3,
+    STAR = 4,
+    Default = 5,
+    Type = 6,
+    EQ = 7,
+    As = 8,
+    Namespace = 9,
+    LBRACE = 10,
+    COMMA = 11,
+    RBRACE = 12,
+    Typeof = 13,
+    Import2 = 14,
+    From = 15,
+    With = 16,
+    Assert = 17,
+    Var = 18,
+    Let = 19,
+    Const = 20,
+    BANG = 21,
+    Else = 22,
+    If = 23,
+    Switch = 24,
+    For = 25,
+    LPAREN = 26,
+    SEMI = 27,
+    RPAREN = 28,
+    Await = 29,
+    In = 30,
+    Of = 31,
+    While = 32,
+    Do = 33,
+    Try = 34,
+    Break = 35,
+    Continue = 36,
+    Debugger = 37,
+    Return = 38,
+    Throw = 39,
+    COLON = 40,
+    Case = 41,
+    Catch = 42,
+    Finally = 43,
+    Yield = 44,
+    LBRACK = 45,
+    RBRACK = 46,
+    HtmlCharacterReference = 47,
+    GT = 48,
+    Identifier2 = 49,
+    DOT = 50,
+    LTSLASH = 51,
+    SLASHGT = 52,
+    DQUOTE = 53,
+    SQUOTE = 54,
+    StringFragment = 55,
+    StringFragment2 = 56,
+    Class2 = 57,
+    Async = 58,
+    Function = 59,
+    EQGT = 60,
+    QMARKDOT = 61,
+    New = 62,
+    Using = 63,
+    PLUSEQ = 64,
+    DASHEQ = 65,
+    STAREQ = 66,
+    SLASHEQ = 67,
+    PERCENTEQ = 68,
+    CARETEQ = 69,
+    AMPEQ = 70,
+    PIPEEQ = 71,
+    GTGTEQ = 72,
+    GTGTGTEQ = 73,
+    LTLTEQ = 74,
+    STARSTAREQ = 75,
+    AMPAMPEQ = 76,
+    PIPEPIPEEQ = 77,
+    QMARKQMARKEQ = 78,
+    DOTDOTDOT = 79,
+    AMPAMP = 80,
+    PIPEPIPE = 81,
+    GTGT = 82,
+    GTGTGT = 83,
+    LTLT = 84,
+    AMP = 85,
+    CARET = 86,
+    PIPE = 87,
+    PLUS = 88,
+    DASH = 89,
+    SLASH = 90,
+    PERCENT = 91,
+    STARSTAR = 92,
+    LT = 93,
+    LTEQ = 94,
+    EQEQ = 95,
+    EQEQEQ = 96,
+    BANGEQ = 97,
+    BANGEQEQ = 98,
+    GTEQ = 99,
+    QMARKQMARK = 100,
+    Instanceof = 101,
+    TILDE = 102,
+    Void = 103,
+    Delete = 104,
+    PLUSPLUS = 105,
+    DASHDASH = 106,
+    StringFragment3 = 107,
+    StringFragment4 = 108,
+    EscapeSequence = 109,
+    Comment = 110,
+    BQUOTE = 111,
+    DOLLARLBRACE = 112,
+    SLASH2 = 113,
+    RegexPattern = 114,
+    RegexFlags = 115,
+    Number = 116,
+    PrivatePropertyIdentifier = 117,
+    Target = 118,
+    Meta = 119,
+    This = 120,
+    Super = 121,
+    True = 122,
+    False = 123,
+    Null = 124,
+    Undefined = 125,
+    AT = 126,
+    Static = 127,
+    Readonly = 128,
+    Get = 129,
+    Set = 130,
+    QMARK = 131,
+    Declare = 132,
+    Public = 133,
+    Private = 134,
+    Protected = 135,
+    Override = 136,
+    Module2 = 137,
+    Any = 138,
+    Number2 = 139,
+    Boolean = 140,
+    String3 = 141,
+    Symbol = 142,
+    Object2 = 143,
+    Abstract = 144,
+    Accessor = 145,
+    Satisfies = 146,
+    Require = 147,
+    Extends = 148,
+    Implements = 149,
+    Global = 150,
+    Interface = 151,
+    Enum = 152,
+    DASHQMARKCOLON = 153,
+    PLUSQMARKCOLON = 154,
+    QMARKCOLON = 155,
+    Asserts2 = 156,
+    Infer = 157,
+    Is = 158,
+    Keyof = 159,
+    Uniquesymbol = 160,
+    Unknown = 161,
+    Never = 162,
+    LBRACEPIPE = 163,
+    PIPERBRACE = 164,
+    AutomaticSemicolon = 165,
+    StringFragment5 = 166,
+    QMARK2 = 167,
+    HtmlComment = 168,
+    JsxText = 169,
+    FunctionSignatureAutomaticSemicolon = 170,
+    ErrorRecovery = 171,
+    Program = 172,
+    ExportStatement = 173,
+    NamespaceExport = 174,
+    ExportClause = 175,
+    ExportSpecifier = 176,
+    ModuleExportName = 177,
+    Declaration = 178,
+    Import = 179,
+    ImportStatement = 180,
+    ImportClause = 181,
+    FromClause = 182,
+    NamespaceImport = 183,
+    NamedImports = 184,
+    ImportSpecifier = 185,
+    ImportAttribute = 186,
+    Statement = 187,
+    ExpressionStatement = 188,
+    VariableDeclaration = 189,
+    LexicalDeclaration = 190,
+    VariableDeclarator = 191,
+    StatementBlock = 192,
+    ElseClause = 193,
+    IfStatement = 194,
+    SwitchStatement = 195,
+    ForStatement = 196,
+    ForInStatement = 197,
+    ForHeader = 198,
+    WhileStatement = 199,
+    DoStatement = 200,
+    TryStatement = 201,
+    WithStatement = 202,
+    BreakStatement = 203,
+    ContinueStatement = 204,
+    DebuggerStatement = 205,
+    ReturnStatement = 206,
+    ThrowStatement = 207,
+    EmptyStatement = 208,
+    LabeledStatement = 209,
+    SwitchBody = 210,
+    SwitchCase = 211,
+    SwitchDefault = 212,
+    CatchClause = 213,
+    FinallyClause = 214,
+    ParenthesizedExpression = 215,
+    Expression = 216,
+    PrimaryExpression = 217,
+    YieldExpression = 218,
+    Object = 219,
+    ObjectPattern = 220,
+    AssignmentPattern = 221,
+    ObjectAssignmentPattern = 222,
+    Array = 223,
+    ArrayPattern = 224,
+    JsxElement = 225,
+    JsxExpression = 226,
+    JsxOpeningElement = 227,
+    NestedIdentifier = 228,
+    JsxNamespaceName = 229,
+    JsxClosingElement = 230,
+    JsxSelfClosingElement = 231,
+    JsxAttribute = 232,
+    String = 233,
+    Class = 234,
+    ClassDeclaration = 235,
+    ClassHeritage = 236,
+    FunctionExpression = 237,
+    FunctionDeclaration = 238,
+    GeneratorFunction = 239,
+    GeneratorFunctionDeclaration = 240,
+    ArrowFunction = 241,
+    CallSignature2 = 242,
+    FormalParameter = 243,
+    OptionalChain = 244,
+    CallExpression = 245,
+    NewExpression = 246,
+    AwaitExpression = 247,
+    MemberExpression = 248,
+    SubscriptExpression = 249,
+    AssignmentExpression = 250,
+    AugmentedAssignmentLhs = 251,
+    AugmentedAssignmentExpression = 252,
+    Initializer = 253,
+    DestructuringPattern = 254,
+    SpreadElement = 255,
+    TernaryExpression = 256,
+    BinaryExpression = 257,
+    UnaryExpression = 258,
+    UpdateExpression = 259,
+    SequenceExpression = 260,
+    String2 = 261,
+    TemplateString = 262,
+    TemplateSubstitution = 263,
+    Regex = 264,
+    MetaProperty = 265,
+    Arguments = 266,
+    Decorator = 267,
+    MemberExpression2 = 268,
+    CallExpression2 = 269,
+    ClassBody = 270,
+    FormalParameters = 271,
+    ClassStaticBlock = 272,
+    Pattern = 273,
+    RestPattern = 274,
+    MethodDefinition = 275,
+    Pair = 276,
+    PairPattern = 277,
+    PropertyName = 278,
+    ComputedPropertyName = 279,
+    PublicFieldDefinition = 280,
+    ImportIdentifier = 281,
+    NonNullExpression = 282,
+    MethodSignature = 283,
+    AbstractMethodSignature = 284,
+    FunctionSignature = 285,
+    ParenthesizedExpression2 = 286,
+    AsExpression = 287,
+    SatisfiesExpression = 288,
+    InstantiationExpression = 289,
+    ImportRequireClause = 290,
+    ExtendsClause = 291,
+    ExtendsClauseSingle = 292,
+    ImplementsClause = 293,
+    AmbientDeclaration = 294,
+    AbstractClassDeclaration = 295,
+    Module = 296,
+    InternalModule = 297,
+    Module3 = 298,
+    ImportAlias = 299,
+    NestedTypeIdentifier = 300,
+    InterfaceDeclaration = 301,
+    ExtendsTypeClause = 302,
+    EnumDeclaration = 303,
+    EnumBody = 304,
+    EnumAssignment = 305,
+    TypeAliasDeclaration = 306,
+    AccessibilityModifier = 307,
+    OverrideModifier = 308,
+    RequiredParameter = 309,
+    OptionalParameter = 310,
+    ParameterName = 311,
+    OmittingTypeAnnotation = 312,
+    AddingTypeAnnotation = 313,
+    OptingTypeAnnotation = 314,
+    TypeAnnotation = 315,
+    MemberExpression3 = 316,
+    CallExpression3 = 317,
+    Asserts = 318,
+    AssertsAnnotation = 319,
+    Type2 = 320,
+    RequiredParameter2 = 321,
+    OptionalParameter2 = 322,
+    OptionalType = 323,
+    RestType = 324,
+    TupleTypeMember = 325,
+    ConstructorType = 326,
+    PrimaryType = 327,
+    TemplateType = 328,
+    TemplateLiteralType = 329,
+    InferType = 330,
+    ConditionalType = 331,
+    GenericType = 332,
+    TypePredicate = 333,
+    TypePredicateAnnotation = 334,
+    MemberExpression4 = 335,
+    SubscriptExpression2 = 336,
+    CallExpression4 = 337,
+    InstantiationExpression2 = 338,
+    TypeQuery = 339,
+    IndexTypeQuery = 340,
+    LookupType = 341,
+    MappedTypeClause = 342,
+    LiteralType = 343,
+    UnaryExpression2 = 344,
+    ExistentialType = 345,
+    FlowMaybeType = 346,
+    ParenthesizedType = 347,
+    PredefinedType = 348,
+    TypeArguments = 349,
+    ObjectType = 350,
+    CallSignature = 351,
+    PropertySignature = 352,
+    TypeParameters = 353,
+    TypeParameter = 354,
+    DefaultType = 355,
+    Constraint = 356,
+    ConstructSignature = 357,
+    IndexSignature = 358,
+    ArrayType = 359,
+    TupleType = 360,
+    ReadonlyType = 361,
+    UnionType = 362,
+    IntersectionType = 363,
+    FunctionType = 364,
+    ProgramRepeat1 = 365,
+    ExportStatementRepeat1 = 366,
+    ExportClauseRepeat1 = 367,
+    NamedImportsRepeat1 = 368,
+    VariableDeclarationRepeat1 = 369,
+    SwitchBodyRepeat1 = 370,
+    ObjectRepeat1 = 371,
+    ObjectPatternRepeat1 = 372,
+    ArrayRepeat1 = 373,
+    ArrayPatternRepeat1 = 374,
+    JsxElementRepeat1 = 375,
+    JsxStringRepeat1 = 376,
+    JsxStringRepeat2 = 377,
+    SequenceExpressionRepeat1 = 378,
+    StringRepeat1 = 379,
+    StringRepeat2 = 380,
+    TemplateStringRepeat1 = 381,
+    ClassBodyRepeat1 = 382,
+    FormalParametersRepeat1 = 383,
+    JsxStartOpeningElementRepeat1 = 384,
+    ExtendsClauseRepeat1 = 385,
+    ImplementsClauseRepeat1 = 386,
+    ExtendsTypeClauseRepeat1 = 387,
+    EnumBodyRepeat1 = 388,
+    TemplateLiteralTypeRepeat1 = 389,
+    ObjectTypeRepeat1 = 390,
+    TypeParametersRepeat1 = 391,
+    TupleTypeRepeat1 = 392,
+    InterfaceBody = 393,
+    PropertyIdentifier = 394,
+    ShorthandPropertyIdentifier = 395,
+    ShorthandPropertyIdentifierPattern = 396,
+    StatementIdentifier = 397,
+    ThisType = 398,
+    TypeIdentifier = 399,
+    Error = 400,
+}
+
+impl From for &'static str {
+    #[inline(always)]
+    fn from(tok: Tsx) -> Self {
+        match tok {
+            Tsx::End => "end",
+            Tsx::Identifier => "identifier",
+            Tsx::HashBangLine => "hash_bang_line",
+            Tsx::Export => "export",
+            Tsx::STAR => "*",
+            Tsx::Default => "default",
+            Tsx::Type => "type",
+            Tsx::EQ => "=",
+            Tsx::As => "as",
+            Tsx::Namespace => "namespace",
+            Tsx::LBRACE => "{",
+            Tsx::COMMA => ",",
+            Tsx::RBRACE => "}",
+            Tsx::Typeof => "typeof",
+            Tsx::Import2 => "import",
+            Tsx::From => "from",
+            Tsx::With => "with",
+            Tsx::Assert => "assert",
+            Tsx::Var => "var",
+            Tsx::Let => "let",
+            Tsx::Const => "const",
+            Tsx::BANG => "!",
+            Tsx::Else => "else",
+            Tsx::If => "if",
+            Tsx::Switch => "switch",
+            Tsx::For => "for",
+            Tsx::LPAREN => "(",
+            Tsx::SEMI => ";",
+            Tsx::RPAREN => ")",
+            Tsx::Await => "await",
+            Tsx::In => "in",
+            Tsx::Of => "of",
+            Tsx::While => "while",
+            Tsx::Do => "do",
+            Tsx::Try => "try",
+            Tsx::Break => "break",
+            Tsx::Continue => "continue",
+            Tsx::Debugger => "debugger",
+            Tsx::Return => "return",
+            Tsx::Throw => "throw",
+            Tsx::COLON => ":",
+            Tsx::Case => "case",
+            Tsx::Catch => "catch",
+            Tsx::Finally => "finally",
+            Tsx::Yield => "yield",
+            Tsx::LBRACK => "[",
+            Tsx::RBRACK => "]",
+            Tsx::HtmlCharacterReference => "html_character_reference",
+            Tsx::GT => ">",
+            Tsx::Identifier2 => "identifier",
+            Tsx::DOT => ".",
+            Tsx::LTSLASH => " "/>",
+            Tsx::DQUOTE => "\"",
+            Tsx::SQUOTE => "'",
+            Tsx::StringFragment => "string_fragment",
+            Tsx::StringFragment2 => "string_fragment",
+            Tsx::Class2 => "class",
+            Tsx::Async => "async",
+            Tsx::Function => "function",
+            Tsx::EQGT => "=>",
+            Tsx::QMARKDOT => "?.",
+            Tsx::New => "new",
+            Tsx::Using => "using",
+            Tsx::PLUSEQ => "+=",
+            Tsx::DASHEQ => "-=",
+            Tsx::STAREQ => "*=",
+            Tsx::SLASHEQ => "/=",
+            Tsx::PERCENTEQ => "%=",
+            Tsx::CARETEQ => "^=",
+            Tsx::AMPEQ => "&=",
+            Tsx::PIPEEQ => "|=",
+            Tsx::GTGTEQ => ">>=",
+            Tsx::GTGTGTEQ => ">>>=",
+            Tsx::LTLTEQ => "<<=",
+            Tsx::STARSTAREQ => "**=",
+            Tsx::AMPAMPEQ => "&&=",
+            Tsx::PIPEPIPEEQ => "||=",
+            Tsx::QMARKQMARKEQ => "??=",
+            Tsx::DOTDOTDOT => "...",
+            Tsx::AMPAMP => "&&",
+            Tsx::PIPEPIPE => "||",
+            Tsx::GTGT => ">>",
+            Tsx::GTGTGT => ">>>",
+            Tsx::LTLT => "<<",
+            Tsx::AMP => "&",
+            Tsx::CARET => "^",
+            Tsx::PIPE => "|",
+            Tsx::PLUS => "+",
+            Tsx::DASH => "-",
+            Tsx::SLASH => "/",
+            Tsx::PERCENT => "%",
+            Tsx::STARSTAR => "**",
+            Tsx::LT => "<",
+            Tsx::LTEQ => "<=",
+            Tsx::EQEQ => "==",
+            Tsx::EQEQEQ => "===",
+            Tsx::BANGEQ => "!=",
+            Tsx::BANGEQEQ => "!==",
+            Tsx::GTEQ => ">=",
+            Tsx::QMARKQMARK => "??",
+            Tsx::Instanceof => "instanceof",
+            Tsx::TILDE => "~",
+            Tsx::Void => "void",
+            Tsx::Delete => "delete",
+            Tsx::PLUSPLUS => "++",
+            Tsx::DASHDASH => "--",
+            Tsx::StringFragment3 => "string_fragment",
+            Tsx::StringFragment4 => "string_fragment",
+            Tsx::EscapeSequence => "escape_sequence",
+            Tsx::Comment => "comment",
+            Tsx::BQUOTE => "`",
+            Tsx::DOLLARLBRACE => "${",
+            Tsx::SLASH2 => "/",
+            Tsx::RegexPattern => "regex_pattern",
+            Tsx::RegexFlags => "regex_flags",
+            Tsx::Number => "number",
+            Tsx::PrivatePropertyIdentifier => "private_property_identifier",
+            Tsx::Target => "target",
+            Tsx::Meta => "meta",
+            Tsx::This => "this",
+            Tsx::Super => "super",
+            Tsx::True => "true",
+            Tsx::False => "false",
+            Tsx::Null => "null",
+            Tsx::Undefined => "undefined",
+            Tsx::AT => "@",
+            Tsx::Static => "static",
+            Tsx::Readonly => "readonly",
+            Tsx::Get => "get",
+            Tsx::Set => "set",
+            Tsx::QMARK => "?",
+            Tsx::Declare => "declare",
+            Tsx::Public => "public",
+            Tsx::Private => "private",
+            Tsx::Protected => "protected",
+            Tsx::Override => "override",
+            Tsx::Module2 => "module",
+            Tsx::Any => "any",
+            Tsx::Number2 => "number",
+            Tsx::Boolean => "boolean",
+            Tsx::String3 => "string",
+            Tsx::Symbol => "symbol",
+            Tsx::Object2 => "object",
+            Tsx::Abstract => "abstract",
+            Tsx::Accessor => "accessor",
+            Tsx::Satisfies => "satisfies",
+            Tsx::Require => "require",
+            Tsx::Extends => "extends",
+            Tsx::Implements => "implements",
+            Tsx::Global => "global",
+            Tsx::Interface => "interface",
+            Tsx::Enum => "enum",
+            Tsx::DASHQMARKCOLON => "-?:",
+            Tsx::PLUSQMARKCOLON => "+?:",
+            Tsx::QMARKCOLON => "?:",
+            Tsx::Asserts2 => "asserts",
+            Tsx::Infer => "infer",
+            Tsx::Is => "is",
+            Tsx::Keyof => "keyof",
+            Tsx::Uniquesymbol => "unique symbol",
+            Tsx::Unknown => "unknown",
+            Tsx::Never => "never",
+            Tsx::LBRACEPIPE => "{|",
+            Tsx::PIPERBRACE => "|}",
+            Tsx::AutomaticSemicolon => "_automatic_semicolon",
+            Tsx::StringFragment5 => "string_fragment",
+            Tsx::QMARK2 => "?",
+            Tsx::HtmlComment => "html_comment",
+            Tsx::JsxText => "jsx_text",
+            Tsx::FunctionSignatureAutomaticSemicolon => "_function_signature_automatic_semicolon",
+            Tsx::ErrorRecovery => "__error_recovery",
+            Tsx::Program => "program",
+            Tsx::ExportStatement => "export_statement",
+            Tsx::NamespaceExport => "namespace_export",
+            Tsx::ExportClause => "export_clause",
+            Tsx::ExportSpecifier => "export_specifier",
+            Tsx::ModuleExportName => "_module_export_name",
+            Tsx::Declaration => "declaration",
+            Tsx::Import => "import",
+            Tsx::ImportStatement => "import_statement",
+            Tsx::ImportClause => "import_clause",
+            Tsx::FromClause => "_from_clause",
+            Tsx::NamespaceImport => "namespace_import",
+            Tsx::NamedImports => "named_imports",
+            Tsx::ImportSpecifier => "import_specifier",
+            Tsx::ImportAttribute => "import_attribute",
+            Tsx::Statement => "statement",
+            Tsx::ExpressionStatement => "expression_statement",
+            Tsx::VariableDeclaration => "variable_declaration",
+            Tsx::LexicalDeclaration => "lexical_declaration",
+            Tsx::VariableDeclarator => "variable_declarator",
+            Tsx::StatementBlock => "statement_block",
+            Tsx::ElseClause => "else_clause",
+            Tsx::IfStatement => "if_statement",
+            Tsx::SwitchStatement => "switch_statement",
+            Tsx::ForStatement => "for_statement",
+            Tsx::ForInStatement => "for_in_statement",
+            Tsx::ForHeader => "_for_header",
+            Tsx::WhileStatement => "while_statement",
+            Tsx::DoStatement => "do_statement",
+            Tsx::TryStatement => "try_statement",
+            Tsx::WithStatement => "with_statement",
+            Tsx::BreakStatement => "break_statement",
+            Tsx::ContinueStatement => "continue_statement",
+            Tsx::DebuggerStatement => "debugger_statement",
+            Tsx::ReturnStatement => "return_statement",
+            Tsx::ThrowStatement => "throw_statement",
+            Tsx::EmptyStatement => "empty_statement",
+            Tsx::LabeledStatement => "labeled_statement",
+            Tsx::SwitchBody => "switch_body",
+            Tsx::SwitchCase => "switch_case",
+            Tsx::SwitchDefault => "switch_default",
+            Tsx::CatchClause => "catch_clause",
+            Tsx::FinallyClause => "finally_clause",
+            Tsx::ParenthesizedExpression => "parenthesized_expression",
+            Tsx::Expression => "expression",
+            Tsx::PrimaryExpression => "primary_expression",
+            Tsx::YieldExpression => "yield_expression",
+            Tsx::Object => "object",
+            Tsx::ObjectPattern => "object_pattern",
+            Tsx::AssignmentPattern => "assignment_pattern",
+            Tsx::ObjectAssignmentPattern => "object_assignment_pattern",
+            Tsx::Array => "array",
+            Tsx::ArrayPattern => "array_pattern",
+            Tsx::JsxElement => "jsx_element",
+            Tsx::JsxExpression => "jsx_expression",
+            Tsx::JsxOpeningElement => "jsx_opening_element",
+            Tsx::NestedIdentifier => "nested_identifier",
+            Tsx::JsxNamespaceName => "jsx_namespace_name",
+            Tsx::JsxClosingElement => "jsx_closing_element",
+            Tsx::JsxSelfClosingElement => "jsx_self_closing_element",
+            Tsx::JsxAttribute => "jsx_attribute",
+            Tsx::String => "string",
+            Tsx::Class => "class",
+            Tsx::ClassDeclaration => "class_declaration",
+            Tsx::ClassHeritage => "class_heritage",
+            Tsx::FunctionExpression => "function_expression",
+            Tsx::FunctionDeclaration => "function_declaration",
+            Tsx::GeneratorFunction => "generator_function",
+            Tsx::GeneratorFunctionDeclaration => "generator_function_declaration",
+            Tsx::ArrowFunction => "arrow_function",
+            Tsx::CallSignature2 => "_call_signature",
+            Tsx::FormalParameter => "_formal_parameter",
+            Tsx::OptionalChain => "optional_chain",
+            Tsx::CallExpression => "call_expression",
+            Tsx::NewExpression => "new_expression",
+            Tsx::AwaitExpression => "await_expression",
+            Tsx::MemberExpression => "member_expression",
+            Tsx::SubscriptExpression => "subscript_expression",
+            Tsx::AssignmentExpression => "assignment_expression",
+            Tsx::AugmentedAssignmentLhs => "_augmented_assignment_lhs",
+            Tsx::AugmentedAssignmentExpression => "augmented_assignment_expression",
+            Tsx::Initializer => "_initializer",
+            Tsx::DestructuringPattern => "_destructuring_pattern",
+            Tsx::SpreadElement => "spread_element",
+            Tsx::TernaryExpression => "ternary_expression",
+            Tsx::BinaryExpression => "binary_expression",
+            Tsx::UnaryExpression => "unary_expression",
+            Tsx::UpdateExpression => "update_expression",
+            Tsx::SequenceExpression => "sequence_expression",
+            Tsx::String2 => "string",
+            Tsx::TemplateString => "template_string",
+            Tsx::TemplateSubstitution => "template_substitution",
+            Tsx::Regex => "regex",
+            Tsx::MetaProperty => "meta_property",
+            Tsx::Arguments => "arguments",
+            Tsx::Decorator => "decorator",
+            Tsx::MemberExpression2 => "member_expression",
+            Tsx::CallExpression2 => "call_expression",
+            Tsx::ClassBody => "class_body",
+            Tsx::FormalParameters => "formal_parameters",
+            Tsx::ClassStaticBlock => "class_static_block",
+            Tsx::Pattern => "pattern",
+            Tsx::RestPattern => "rest_pattern",
+            Tsx::MethodDefinition => "method_definition",
+            Tsx::Pair => "pair",
+            Tsx::PairPattern => "pair_pattern",
+            Tsx::PropertyName => "_property_name",
+            Tsx::ComputedPropertyName => "computed_property_name",
+            Tsx::PublicFieldDefinition => "public_field_definition",
+            Tsx::ImportIdentifier => "_import_identifier",
+            Tsx::NonNullExpression => "non_null_expression",
+            Tsx::MethodSignature => "method_signature",
+            Tsx::AbstractMethodSignature => "abstract_method_signature",
+            Tsx::FunctionSignature => "function_signature",
+            Tsx::ParenthesizedExpression2 => "parenthesized_expression",
+            Tsx::AsExpression => "as_expression",
+            Tsx::SatisfiesExpression => "satisfies_expression",
+            Tsx::InstantiationExpression => "instantiation_expression",
+            Tsx::ImportRequireClause => "import_require_clause",
+            Tsx::ExtendsClause => "extends_clause",
+            Tsx::ExtendsClauseSingle => "_extends_clause_single",
+            Tsx::ImplementsClause => "implements_clause",
+            Tsx::AmbientDeclaration => "ambient_declaration",
+            Tsx::AbstractClassDeclaration => "abstract_class_declaration",
+            Tsx::Module => "module",
+            Tsx::InternalModule => "internal_module",
+            Tsx::Module3 => "_module",
+            Tsx::ImportAlias => "import_alias",
+            Tsx::NestedTypeIdentifier => "nested_type_identifier",
+            Tsx::InterfaceDeclaration => "interface_declaration",
+            Tsx::ExtendsTypeClause => "extends_type_clause",
+            Tsx::EnumDeclaration => "enum_declaration",
+            Tsx::EnumBody => "enum_body",
+            Tsx::EnumAssignment => "enum_assignment",
+            Tsx::TypeAliasDeclaration => "type_alias_declaration",
+            Tsx::AccessibilityModifier => "accessibility_modifier",
+            Tsx::OverrideModifier => "override_modifier",
+            Tsx::RequiredParameter => "required_parameter",
+            Tsx::OptionalParameter => "optional_parameter",
+            Tsx::ParameterName => "_parameter_name",
+            Tsx::OmittingTypeAnnotation => "omitting_type_annotation",
+            Tsx::AddingTypeAnnotation => "adding_type_annotation",
+            Tsx::OptingTypeAnnotation => "opting_type_annotation",
+            Tsx::TypeAnnotation => "type_annotation",
+            Tsx::MemberExpression3 => "member_expression",
+            Tsx::CallExpression3 => "call_expression",
+            Tsx::Asserts => "asserts",
+            Tsx::AssertsAnnotation => "asserts_annotation",
+            Tsx::Type2 => "type",
+            Tsx::RequiredParameter2 => "required_parameter",
+            Tsx::OptionalParameter2 => "optional_parameter",
+            Tsx::OptionalType => "optional_type",
+            Tsx::RestType => "rest_type",
+            Tsx::TupleTypeMember => "_tuple_type_member",
+            Tsx::ConstructorType => "constructor_type",
+            Tsx::PrimaryType => "primary_type",
+            Tsx::TemplateType => "template_type",
+            Tsx::TemplateLiteralType => "template_literal_type",
+            Tsx::InferType => "infer_type",
+            Tsx::ConditionalType => "conditional_type",
+            Tsx::GenericType => "generic_type",
+            Tsx::TypePredicate => "type_predicate",
+            Tsx::TypePredicateAnnotation => "type_predicate_annotation",
+            Tsx::MemberExpression4 => "member_expression",
+            Tsx::SubscriptExpression2 => "subscript_expression",
+            Tsx::CallExpression4 => "call_expression",
+            Tsx::InstantiationExpression2 => "instantiation_expression",
+            Tsx::TypeQuery => "type_query",
+            Tsx::IndexTypeQuery => "index_type_query",
+            Tsx::LookupType => "lookup_type",
+            Tsx::MappedTypeClause => "mapped_type_clause",
+            Tsx::LiteralType => "literal_type",
+            Tsx::UnaryExpression2 => "unary_expression",
+            Tsx::ExistentialType => "existential_type",
+            Tsx::FlowMaybeType => "flow_maybe_type",
+            Tsx::ParenthesizedType => "parenthesized_type",
+            Tsx::PredefinedType => "predefined_type",
+            Tsx::TypeArguments => "type_arguments",
+            Tsx::ObjectType => "object_type",
+            Tsx::CallSignature => "call_signature",
+            Tsx::PropertySignature => "property_signature",
+            Tsx::TypeParameters => "type_parameters",
+            Tsx::TypeParameter => "type_parameter",
+            Tsx::DefaultType => "default_type",
+            Tsx::Constraint => "constraint",
+            Tsx::ConstructSignature => "construct_signature",
+            Tsx::IndexSignature => "index_signature",
+            Tsx::ArrayType => "array_type",
+            Tsx::TupleType => "tuple_type",
+            Tsx::ReadonlyType => "readonly_type",
+            Tsx::UnionType => "union_type",
+            Tsx::IntersectionType => "intersection_type",
+            Tsx::FunctionType => "function_type",
+            Tsx::ProgramRepeat1 => "program_repeat1",
+            Tsx::ExportStatementRepeat1 => "export_statement_repeat1",
+            Tsx::ExportClauseRepeat1 => "export_clause_repeat1",
+            Tsx::NamedImportsRepeat1 => "named_imports_repeat1",
+            Tsx::VariableDeclarationRepeat1 => "variable_declaration_repeat1",
+            Tsx::SwitchBodyRepeat1 => "switch_body_repeat1",
+            Tsx::ObjectRepeat1 => "object_repeat1",
+            Tsx::ObjectPatternRepeat1 => "object_pattern_repeat1",
+            Tsx::ArrayRepeat1 => "array_repeat1",
+            Tsx::ArrayPatternRepeat1 => "array_pattern_repeat1",
+            Tsx::JsxElementRepeat1 => "jsx_element_repeat1",
+            Tsx::JsxStringRepeat1 => "_jsx_string_repeat1",
+            Tsx::JsxStringRepeat2 => "_jsx_string_repeat2",
+            Tsx::SequenceExpressionRepeat1 => "sequence_expression_repeat1",
+            Tsx::StringRepeat1 => "string_repeat1",
+            Tsx::StringRepeat2 => "string_repeat2",
+            Tsx::TemplateStringRepeat1 => "template_string_repeat1",
+            Tsx::ClassBodyRepeat1 => "class_body_repeat1",
+            Tsx::FormalParametersRepeat1 => "formal_parameters_repeat1",
+            Tsx::JsxStartOpeningElementRepeat1 => "_jsx_start_opening_element_repeat1",
+            Tsx::ExtendsClauseRepeat1 => "extends_clause_repeat1",
+            Tsx::ImplementsClauseRepeat1 => "implements_clause_repeat1",
+            Tsx::ExtendsTypeClauseRepeat1 => "extends_type_clause_repeat1",
+            Tsx::EnumBodyRepeat1 => "enum_body_repeat1",
+            Tsx::TemplateLiteralTypeRepeat1 => "template_literal_type_repeat1",
+            Tsx::ObjectTypeRepeat1 => "object_type_repeat1",
+            Tsx::TypeParametersRepeat1 => "type_parameters_repeat1",
+            Tsx::TupleTypeRepeat1 => "tuple_type_repeat1",
+            Tsx::InterfaceBody => "interface_body",
+            Tsx::PropertyIdentifier => "property_identifier",
+            Tsx::ShorthandPropertyIdentifier => "shorthand_property_identifier",
+            Tsx::ShorthandPropertyIdentifierPattern => "shorthand_property_identifier_pattern",
+            Tsx::StatementIdentifier => "statement_identifier",
+            Tsx::ThisType => "this_type",
+            Tsx::TypeIdentifier => "type_identifier",
+            Tsx::Error => "ERROR",
+        }
+    }
+}
+
+impl From for Tsx {
+    #[inline(always)]
+    fn from(x: u16) -> Self {
+        num::FromPrimitive::from_u16(x).unwrap_or(Self::Error)
+    }
+}
+
+// Tsx == u16
+impl PartialEq for Tsx {
+    #[inline(always)]
+    fn eq(&self, x: &u16) -> bool {
+        *self == Into::::into(*x)
+    }
+}
+
+// u16 == Tsx
+impl PartialEq for u16 {
+    #[inline(always)]
+    fn eq(&self, x: &Tsx) -> bool {
+        *x == *self
+    }
+}
diff --git a/src/languages/language_typescript.rs b/src/languages/language_typescript.rs
new file mode 100644
index 00000000..ff997606
--- /dev/null
+++ b/src/languages/language_typescript.rs
@@ -0,0 +1,810 @@
+// Code generated; DO NOT EDIT.
+
+use num_derive::FromPrimitive;
+
+#[derive(Clone, Debug, PartialEq, Eq, FromPrimitive)]
+pub enum Typescript {
+    End = 0,
+    Identifier = 1,
+    HashBangLine = 2,
+    Export = 3,
+    STAR = 4,
+    Default = 5,
+    Type = 6,
+    EQ = 7,
+    As = 8,
+    Namespace = 9,
+    LBRACE = 10,
+    COMMA = 11,
+    RBRACE = 12,
+    Typeof = 13,
+    Import2 = 14,
+    From = 15,
+    With = 16,
+    Assert = 17,
+    Var = 18,
+    Let = 19,
+    Const = 20,
+    BANG = 21,
+    Else = 22,
+    If = 23,
+    Switch = 24,
+    For = 25,
+    LPAREN = 26,
+    SEMI = 27,
+    RPAREN = 28,
+    Await = 29,
+    In = 30,
+    Of = 31,
+    While = 32,
+    Do = 33,
+    Try = 34,
+    Break = 35,
+    Continue = 36,
+    Debugger = 37,
+    Return = 38,
+    Throw = 39,
+    COLON = 40,
+    Case = 41,
+    Catch = 42,
+    Finally = 43,
+    Yield = 44,
+    LBRACK = 45,
+    RBRACK = 46,
+    DOT = 47,
+    Class2 = 48,
+    Async = 49,
+    Function = 50,
+    EQGT = 51,
+    QMARKDOT = 52,
+    New = 53,
+    Using = 54,
+    PLUSEQ = 55,
+    DASHEQ = 56,
+    STAREQ = 57,
+    SLASHEQ = 58,
+    PERCENTEQ = 59,
+    CARETEQ = 60,
+    AMPEQ = 61,
+    PIPEEQ = 62,
+    GTGTEQ = 63,
+    GTGTGTEQ = 64,
+    LTLTEQ = 65,
+    STARSTAREQ = 66,
+    AMPAMPEQ = 67,
+    PIPEPIPEEQ = 68,
+    QMARKQMARKEQ = 69,
+    DOTDOTDOT = 70,
+    AMPAMP = 71,
+    PIPEPIPE = 72,
+    GTGT = 73,
+    GTGTGT = 74,
+    LTLT = 75,
+    AMP = 76,
+    CARET = 77,
+    PIPE = 78,
+    PLUS = 79,
+    DASH = 80,
+    SLASH = 81,
+    PERCENT = 82,
+    STARSTAR = 83,
+    LT = 84,
+    LTEQ = 85,
+    EQEQ = 86,
+    EQEQEQ = 87,
+    BANGEQ = 88,
+    BANGEQEQ = 89,
+    GTEQ = 90,
+    GT = 91,
+    QMARKQMARK = 92,
+    Instanceof = 93,
+    TILDE = 94,
+    Void = 95,
+    Delete = 96,
+    PLUSPLUS = 97,
+    DASHDASH = 98,
+    DQUOTE = 99,
+    SQUOTE = 100,
+    StringFragment = 101,
+    StringFragment2 = 102,
+    EscapeSequence = 103,
+    Comment = 104,
+    BQUOTE = 105,
+    DOLLARLBRACE = 106,
+    SLASH2 = 107,
+    RegexPattern = 108,
+    RegexFlags = 109,
+    Number = 110,
+    PrivatePropertyIdentifier = 111,
+    Target = 112,
+    Meta = 113,
+    This = 114,
+    Super = 115,
+    True = 116,
+    False = 117,
+    Null = 118,
+    Undefined = 119,
+    AT = 120,
+    Static = 121,
+    Readonly = 122,
+    Get = 123,
+    Set = 124,
+    QMARK = 125,
+    Declare = 126,
+    Public = 127,
+    Private = 128,
+    Protected = 129,
+    Override = 130,
+    Module2 = 131,
+    Any = 132,
+    Number2 = 133,
+    Boolean = 134,
+    String2 = 135,
+    Symbol = 136,
+    Object2 = 137,
+    Abstract = 138,
+    Accessor = 139,
+    Satisfies = 140,
+    Require = 141,
+    Extends = 142,
+    Implements = 143,
+    Global = 144,
+    Interface = 145,
+    Enum = 146,
+    DASHQMARKCOLON = 147,
+    PLUSQMARKCOLON = 148,
+    QMARKCOLON = 149,
+    Asserts2 = 150,
+    Infer = 151,
+    Is = 152,
+    Keyof = 153,
+    Uniquesymbol = 154,
+    Unknown = 155,
+    Never = 156,
+    LBRACEPIPE = 157,
+    PIPERBRACE = 158,
+    AutomaticSemicolon = 159,
+    StringFragment3 = 160,
+    QMARK2 = 161,
+    HtmlComment = 162,
+    JsxText = 163,
+    FunctionSignatureAutomaticSemicolon = 164,
+    ErrorRecovery = 165,
+    Program = 166,
+    ExportStatement = 167,
+    NamespaceExport = 168,
+    ExportClause = 169,
+    ExportSpecifier = 170,
+    ModuleExportName = 171,
+    Declaration = 172,
+    Import = 173,
+    ImportStatement = 174,
+    ImportClause = 175,
+    FromClause = 176,
+    NamespaceImport = 177,
+    NamedImports = 178,
+    ImportSpecifier = 179,
+    ImportAttribute = 180,
+    Statement = 181,
+    ExpressionStatement = 182,
+    VariableDeclaration = 183,
+    LexicalDeclaration = 184,
+    VariableDeclarator = 185,
+    StatementBlock = 186,
+    ElseClause = 187,
+    IfStatement = 188,
+    SwitchStatement = 189,
+    ForStatement = 190,
+    ForInStatement = 191,
+    ForHeader = 192,
+    WhileStatement = 193,
+    DoStatement = 194,
+    TryStatement = 195,
+    WithStatement = 196,
+    BreakStatement = 197,
+    ContinueStatement = 198,
+    DebuggerStatement = 199,
+    ReturnStatement = 200,
+    ThrowStatement = 201,
+    EmptyStatement = 202,
+    LabeledStatement = 203,
+    SwitchBody = 204,
+    SwitchCase = 205,
+    SwitchDefault = 206,
+    CatchClause = 207,
+    FinallyClause = 208,
+    ParenthesizedExpression = 209,
+    Expression = 210,
+    PrimaryExpression = 211,
+    YieldExpression = 212,
+    Object = 213,
+    ObjectPattern = 214,
+    AssignmentPattern = 215,
+    ObjectAssignmentPattern = 216,
+    Array = 217,
+    ArrayPattern = 218,
+    NestedIdentifier = 219,
+    Class = 220,
+    ClassDeclaration = 221,
+    ClassHeritage = 222,
+    FunctionExpression = 223,
+    FunctionDeclaration = 224,
+    GeneratorFunction = 225,
+    GeneratorFunctionDeclaration = 226,
+    ArrowFunction = 227,
+    CallSignature2 = 228,
+    FormalParameter = 229,
+    OptionalChain = 230,
+    CallExpression = 231,
+    NewExpression = 232,
+    AwaitExpression = 233,
+    MemberExpression = 234,
+    SubscriptExpression = 235,
+    AssignmentExpression = 236,
+    AugmentedAssignmentLhs = 237,
+    AugmentedAssignmentExpression = 238,
+    Initializer = 239,
+    DestructuringPattern = 240,
+    SpreadElement = 241,
+    TernaryExpression = 242,
+    BinaryExpression = 243,
+    UnaryExpression = 244,
+    UpdateExpression = 245,
+    SequenceExpression = 246,
+    String = 247,
+    TemplateString = 248,
+    TemplateSubstitution = 249,
+    Regex = 250,
+    MetaProperty = 251,
+    Arguments = 252,
+    Decorator = 253,
+    MemberExpression2 = 254,
+    CallExpression2 = 255,
+    ClassBody = 256,
+    FormalParameters = 257,
+    ClassStaticBlock = 258,
+    Pattern = 259,
+    RestPattern = 260,
+    MethodDefinition = 261,
+    Pair = 262,
+    PairPattern = 263,
+    PropertyName = 264,
+    ComputedPropertyName = 265,
+    PublicFieldDefinition = 266,
+    ImportIdentifier = 267,
+    NonNullExpression = 268,
+    MethodSignature = 269,
+    AbstractMethodSignature = 270,
+    FunctionSignature = 271,
+    ParenthesizedExpression2 = 272,
+    TypeAssertion = 273,
+    AsExpression = 274,
+    SatisfiesExpression = 275,
+    InstantiationExpression = 276,
+    ImportRequireClause = 277,
+    ExtendsClause = 278,
+    ExtendsClauseSingle = 279,
+    ImplementsClause = 280,
+    AmbientDeclaration = 281,
+    AbstractClassDeclaration = 282,
+    Module = 283,
+    InternalModule = 284,
+    Module3 = 285,
+    ImportAlias = 286,
+    NestedTypeIdentifier = 287,
+    InterfaceDeclaration = 288,
+    ExtendsTypeClause = 289,
+    EnumDeclaration = 290,
+    EnumBody = 291,
+    EnumAssignment = 292,
+    TypeAliasDeclaration = 293,
+    AccessibilityModifier = 294,
+    OverrideModifier = 295,
+    RequiredParameter = 296,
+    OptionalParameter = 297,
+    ParameterName = 298,
+    OmittingTypeAnnotation = 299,
+    AddingTypeAnnotation = 300,
+    OptingTypeAnnotation = 301,
+    TypeAnnotation = 302,
+    MemberExpression3 = 303,
+    CallExpression3 = 304,
+    Asserts = 305,
+    AssertsAnnotation = 306,
+    Type2 = 307,
+    RequiredParameter2 = 308,
+    OptionalParameter2 = 309,
+    OptionalType = 310,
+    RestType = 311,
+    TupleTypeMember = 312,
+    ConstructorType = 313,
+    PrimaryType = 314,
+    TemplateType = 315,
+    TemplateLiteralType = 316,
+    InferType = 317,
+    ConditionalType = 318,
+    GenericType = 319,
+    TypePredicate = 320,
+    TypePredicateAnnotation = 321,
+    MemberExpression4 = 322,
+    SubscriptExpression2 = 323,
+    CallExpression4 = 324,
+    InstantiationExpression2 = 325,
+    TypeQuery = 326,
+    IndexTypeQuery = 327,
+    LookupType = 328,
+    MappedTypeClause = 329,
+    LiteralType = 330,
+    UnaryExpression2 = 331,
+    ExistentialType = 332,
+    FlowMaybeType = 333,
+    ParenthesizedType = 334,
+    PredefinedType = 335,
+    TypeArguments = 336,
+    ObjectType = 337,
+    CallSignature = 338,
+    PropertySignature = 339,
+    TypeParameters = 340,
+    TypeParameter = 341,
+    DefaultType = 342,
+    Constraint = 343,
+    ConstructSignature = 344,
+    IndexSignature = 345,
+    ArrayType = 346,
+    TupleType = 347,
+    ReadonlyType = 348,
+    UnionType = 349,
+    IntersectionType = 350,
+    FunctionType = 351,
+    ProgramRepeat1 = 352,
+    ExportStatementRepeat1 = 353,
+    ExportClauseRepeat1 = 354,
+    NamedImportsRepeat1 = 355,
+    VariableDeclarationRepeat1 = 356,
+    SwitchBodyRepeat1 = 357,
+    ObjectRepeat1 = 358,
+    ObjectPatternRepeat1 = 359,
+    ArrayRepeat1 = 360,
+    ArrayPatternRepeat1 = 361,
+    SequenceExpressionRepeat1 = 362,
+    StringRepeat1 = 363,
+    StringRepeat2 = 364,
+    TemplateStringRepeat1 = 365,
+    ClassBodyRepeat1 = 366,
+    FormalParametersRepeat1 = 367,
+    ExtendsClauseRepeat1 = 368,
+    ImplementsClauseRepeat1 = 369,
+    ExtendsTypeClauseRepeat1 = 370,
+    EnumBodyRepeat1 = 371,
+    TemplateLiteralTypeRepeat1 = 372,
+    ObjectTypeRepeat1 = 373,
+    TypeParametersRepeat1 = 374,
+    TupleTypeRepeat1 = 375,
+    InterfaceBody = 376,
+    PropertyIdentifier = 377,
+    ShorthandPropertyIdentifier = 378,
+    ShorthandPropertyIdentifierPattern = 379,
+    StatementIdentifier = 380,
+    ThisType = 381,
+    TypeIdentifier = 382,
+    Error = 383,
+}
+
+impl From for &'static str {
+    #[inline(always)]
+    fn from(tok: Typescript) -> Self {
+        match tok {
+            Typescript::End => "end",
+            Typescript::Identifier => "identifier",
+            Typescript::HashBangLine => "hash_bang_line",
+            Typescript::Export => "export",
+            Typescript::STAR => "*",
+            Typescript::Default => "default",
+            Typescript::Type => "type",
+            Typescript::EQ => "=",
+            Typescript::As => "as",
+            Typescript::Namespace => "namespace",
+            Typescript::LBRACE => "{",
+            Typescript::COMMA => ",",
+            Typescript::RBRACE => "}",
+            Typescript::Typeof => "typeof",
+            Typescript::Import2 => "import",
+            Typescript::From => "from",
+            Typescript::With => "with",
+            Typescript::Assert => "assert",
+            Typescript::Var => "var",
+            Typescript::Let => "let",
+            Typescript::Const => "const",
+            Typescript::BANG => "!",
+            Typescript::Else => "else",
+            Typescript::If => "if",
+            Typescript::Switch => "switch",
+            Typescript::For => "for",
+            Typescript::LPAREN => "(",
+            Typescript::SEMI => ";",
+            Typescript::RPAREN => ")",
+            Typescript::Await => "await",
+            Typescript::In => "in",
+            Typescript::Of => "of",
+            Typescript::While => "while",
+            Typescript::Do => "do",
+            Typescript::Try => "try",
+            Typescript::Break => "break",
+            Typescript::Continue => "continue",
+            Typescript::Debugger => "debugger",
+            Typescript::Return => "return",
+            Typescript::Throw => "throw",
+            Typescript::COLON => ":",
+            Typescript::Case => "case",
+            Typescript::Catch => "catch",
+            Typescript::Finally => "finally",
+            Typescript::Yield => "yield",
+            Typescript::LBRACK => "[",
+            Typescript::RBRACK => "]",
+            Typescript::DOT => ".",
+            Typescript::Class2 => "class",
+            Typescript::Async => "async",
+            Typescript::Function => "function",
+            Typescript::EQGT => "=>",
+            Typescript::QMARKDOT => "?.",
+            Typescript::New => "new",
+            Typescript::Using => "using",
+            Typescript::PLUSEQ => "+=",
+            Typescript::DASHEQ => "-=",
+            Typescript::STAREQ => "*=",
+            Typescript::SLASHEQ => "/=",
+            Typescript::PERCENTEQ => "%=",
+            Typescript::CARETEQ => "^=",
+            Typescript::AMPEQ => "&=",
+            Typescript::PIPEEQ => "|=",
+            Typescript::GTGTEQ => ">>=",
+            Typescript::GTGTGTEQ => ">>>=",
+            Typescript::LTLTEQ => "<<=",
+            Typescript::STARSTAREQ => "**=",
+            Typescript::AMPAMPEQ => "&&=",
+            Typescript::PIPEPIPEEQ => "||=",
+            Typescript::QMARKQMARKEQ => "??=",
+            Typescript::DOTDOTDOT => "...",
+            Typescript::AMPAMP => "&&",
+            Typescript::PIPEPIPE => "||",
+            Typescript::GTGT => ">>",
+            Typescript::GTGTGT => ">>>",
+            Typescript::LTLT => "<<",
+            Typescript::AMP => "&",
+            Typescript::CARET => "^",
+            Typescript::PIPE => "|",
+            Typescript::PLUS => "+",
+            Typescript::DASH => "-",
+            Typescript::SLASH => "/",
+            Typescript::PERCENT => "%",
+            Typescript::STARSTAR => "**",
+            Typescript::LT => "<",
+            Typescript::LTEQ => "<=",
+            Typescript::EQEQ => "==",
+            Typescript::EQEQEQ => "===",
+            Typescript::BANGEQ => "!=",
+            Typescript::BANGEQEQ => "!==",
+            Typescript::GTEQ => ">=",
+            Typescript::GT => ">",
+            Typescript::QMARKQMARK => "??",
+            Typescript::Instanceof => "instanceof",
+            Typescript::TILDE => "~",
+            Typescript::Void => "void",
+            Typescript::Delete => "delete",
+            Typescript::PLUSPLUS => "++",
+            Typescript::DASHDASH => "--",
+            Typescript::DQUOTE => "\"",
+            Typescript::SQUOTE => "'",
+            Typescript::StringFragment => "string_fragment",
+            Typescript::StringFragment2 => "string_fragment",
+            Typescript::EscapeSequence => "escape_sequence",
+            Typescript::Comment => "comment",
+            Typescript::BQUOTE => "`",
+            Typescript::DOLLARLBRACE => "${",
+            Typescript::SLASH2 => "/",
+            Typescript::RegexPattern => "regex_pattern",
+            Typescript::RegexFlags => "regex_flags",
+            Typescript::Number => "number",
+            Typescript::PrivatePropertyIdentifier => "private_property_identifier",
+            Typescript::Target => "target",
+            Typescript::Meta => "meta",
+            Typescript::This => "this",
+            Typescript::Super => "super",
+            Typescript::True => "true",
+            Typescript::False => "false",
+            Typescript::Null => "null",
+            Typescript::Undefined => "undefined",
+            Typescript::AT => "@",
+            Typescript::Static => "static",
+            Typescript::Readonly => "readonly",
+            Typescript::Get => "get",
+            Typescript::Set => "set",
+            Typescript::QMARK => "?",
+            Typescript::Declare => "declare",
+            Typescript::Public => "public",
+            Typescript::Private => "private",
+            Typescript::Protected => "protected",
+            Typescript::Override => "override",
+            Typescript::Module2 => "module",
+            Typescript::Any => "any",
+            Typescript::Number2 => "number",
+            Typescript::Boolean => "boolean",
+            Typescript::String2 => "string",
+            Typescript::Symbol => "symbol",
+            Typescript::Object2 => "object",
+            Typescript::Abstract => "abstract",
+            Typescript::Accessor => "accessor",
+            Typescript::Satisfies => "satisfies",
+            Typescript::Require => "require",
+            Typescript::Extends => "extends",
+            Typescript::Implements => "implements",
+            Typescript::Global => "global",
+            Typescript::Interface => "interface",
+            Typescript::Enum => "enum",
+            Typescript::DASHQMARKCOLON => "-?:",
+            Typescript::PLUSQMARKCOLON => "+?:",
+            Typescript::QMARKCOLON => "?:",
+            Typescript::Asserts2 => "asserts",
+            Typescript::Infer => "infer",
+            Typescript::Is => "is",
+            Typescript::Keyof => "keyof",
+            Typescript::Uniquesymbol => "unique symbol",
+            Typescript::Unknown => "unknown",
+            Typescript::Never => "never",
+            Typescript::LBRACEPIPE => "{|",
+            Typescript::PIPERBRACE => "|}",
+            Typescript::AutomaticSemicolon => "_automatic_semicolon",
+            Typescript::StringFragment3 => "string_fragment",
+            Typescript::QMARK2 => "?",
+            Typescript::HtmlComment => "html_comment",
+            Typescript::JsxText => "jsx_text",
+            Typescript::FunctionSignatureAutomaticSemicolon => {
+                "_function_signature_automatic_semicolon"
+            }
+            Typescript::ErrorRecovery => "__error_recovery",
+            Typescript::Program => "program",
+            Typescript::ExportStatement => "export_statement",
+            Typescript::NamespaceExport => "namespace_export",
+            Typescript::ExportClause => "export_clause",
+            Typescript::ExportSpecifier => "export_specifier",
+            Typescript::ModuleExportName => "_module_export_name",
+            Typescript::Declaration => "declaration",
+            Typescript::Import => "import",
+            Typescript::ImportStatement => "import_statement",
+            Typescript::ImportClause => "import_clause",
+            Typescript::FromClause => "_from_clause",
+            Typescript::NamespaceImport => "namespace_import",
+            Typescript::NamedImports => "named_imports",
+            Typescript::ImportSpecifier => "import_specifier",
+            Typescript::ImportAttribute => "import_attribute",
+            Typescript::Statement => "statement",
+            Typescript::ExpressionStatement => "expression_statement",
+            Typescript::VariableDeclaration => "variable_declaration",
+            Typescript::LexicalDeclaration => "lexical_declaration",
+            Typescript::VariableDeclarator => "variable_declarator",
+            Typescript::StatementBlock => "statement_block",
+            Typescript::ElseClause => "else_clause",
+            Typescript::IfStatement => "if_statement",
+            Typescript::SwitchStatement => "switch_statement",
+            Typescript::ForStatement => "for_statement",
+            Typescript::ForInStatement => "for_in_statement",
+            Typescript::ForHeader => "_for_header",
+            Typescript::WhileStatement => "while_statement",
+            Typescript::DoStatement => "do_statement",
+            Typescript::TryStatement => "try_statement",
+            Typescript::WithStatement => "with_statement",
+            Typescript::BreakStatement => "break_statement",
+            Typescript::ContinueStatement => "continue_statement",
+            Typescript::DebuggerStatement => "debugger_statement",
+            Typescript::ReturnStatement => "return_statement",
+            Typescript::ThrowStatement => "throw_statement",
+            Typescript::EmptyStatement => "empty_statement",
+            Typescript::LabeledStatement => "labeled_statement",
+            Typescript::SwitchBody => "switch_body",
+            Typescript::SwitchCase => "switch_case",
+            Typescript::SwitchDefault => "switch_default",
+            Typescript::CatchClause => "catch_clause",
+            Typescript::FinallyClause => "finally_clause",
+            Typescript::ParenthesizedExpression => "parenthesized_expression",
+            Typescript::Expression => "expression",
+            Typescript::PrimaryExpression => "primary_expression",
+            Typescript::YieldExpression => "yield_expression",
+            Typescript::Object => "object",
+            Typescript::ObjectPattern => "object_pattern",
+            Typescript::AssignmentPattern => "assignment_pattern",
+            Typescript::ObjectAssignmentPattern => "object_assignment_pattern",
+            Typescript::Array => "array",
+            Typescript::ArrayPattern => "array_pattern",
+            Typescript::NestedIdentifier => "nested_identifier",
+            Typescript::Class => "class",
+            Typescript::ClassDeclaration => "class_declaration",
+            Typescript::ClassHeritage => "class_heritage",
+            Typescript::FunctionExpression => "function_expression",
+            Typescript::FunctionDeclaration => "function_declaration",
+            Typescript::GeneratorFunction => "generator_function",
+            Typescript::GeneratorFunctionDeclaration => "generator_function_declaration",
+            Typescript::ArrowFunction => "arrow_function",
+            Typescript::CallSignature2 => "_call_signature",
+            Typescript::FormalParameter => "_formal_parameter",
+            Typescript::OptionalChain => "optional_chain",
+            Typescript::CallExpression => "call_expression",
+            Typescript::NewExpression => "new_expression",
+            Typescript::AwaitExpression => "await_expression",
+            Typescript::MemberExpression => "member_expression",
+            Typescript::SubscriptExpression => "subscript_expression",
+            Typescript::AssignmentExpression => "assignment_expression",
+            Typescript::AugmentedAssignmentLhs => "_augmented_assignment_lhs",
+            Typescript::AugmentedAssignmentExpression => "augmented_assignment_expression",
+            Typescript::Initializer => "_initializer",
+            Typescript::DestructuringPattern => "_destructuring_pattern",
+            Typescript::SpreadElement => "spread_element",
+            Typescript::TernaryExpression => "ternary_expression",
+            Typescript::BinaryExpression => "binary_expression",
+            Typescript::UnaryExpression => "unary_expression",
+            Typescript::UpdateExpression => "update_expression",
+            Typescript::SequenceExpression => "sequence_expression",
+            Typescript::String => "string",
+            Typescript::TemplateString => "template_string",
+            Typescript::TemplateSubstitution => "template_substitution",
+            Typescript::Regex => "regex",
+            Typescript::MetaProperty => "meta_property",
+            Typescript::Arguments => "arguments",
+            Typescript::Decorator => "decorator",
+            Typescript::MemberExpression2 => "member_expression",
+            Typescript::CallExpression2 => "call_expression",
+            Typescript::ClassBody => "class_body",
+            Typescript::FormalParameters => "formal_parameters",
+            Typescript::ClassStaticBlock => "class_static_block",
+            Typescript::Pattern => "pattern",
+            Typescript::RestPattern => "rest_pattern",
+            Typescript::MethodDefinition => "method_definition",
+            Typescript::Pair => "pair",
+            Typescript::PairPattern => "pair_pattern",
+            Typescript::PropertyName => "_property_name",
+            Typescript::ComputedPropertyName => "computed_property_name",
+            Typescript::PublicFieldDefinition => "public_field_definition",
+            Typescript::ImportIdentifier => "_import_identifier",
+            Typescript::NonNullExpression => "non_null_expression",
+            Typescript::MethodSignature => "method_signature",
+            Typescript::AbstractMethodSignature => "abstract_method_signature",
+            Typescript::FunctionSignature => "function_signature",
+            Typescript::ParenthesizedExpression2 => "parenthesized_expression",
+            Typescript::TypeAssertion => "type_assertion",
+            Typescript::AsExpression => "as_expression",
+            Typescript::SatisfiesExpression => "satisfies_expression",
+            Typescript::InstantiationExpression => "instantiation_expression",
+            Typescript::ImportRequireClause => "import_require_clause",
+            Typescript::ExtendsClause => "extends_clause",
+            Typescript::ExtendsClauseSingle => "_extends_clause_single",
+            Typescript::ImplementsClause => "implements_clause",
+            Typescript::AmbientDeclaration => "ambient_declaration",
+            Typescript::AbstractClassDeclaration => "abstract_class_declaration",
+            Typescript::Module => "module",
+            Typescript::InternalModule => "internal_module",
+            Typescript::Module3 => "_module",
+            Typescript::ImportAlias => "import_alias",
+            Typescript::NestedTypeIdentifier => "nested_type_identifier",
+            Typescript::InterfaceDeclaration => "interface_declaration",
+            Typescript::ExtendsTypeClause => "extends_type_clause",
+            Typescript::EnumDeclaration => "enum_declaration",
+            Typescript::EnumBody => "enum_body",
+            Typescript::EnumAssignment => "enum_assignment",
+            Typescript::TypeAliasDeclaration => "type_alias_declaration",
+            Typescript::AccessibilityModifier => "accessibility_modifier",
+            Typescript::OverrideModifier => "override_modifier",
+            Typescript::RequiredParameter => "required_parameter",
+            Typescript::OptionalParameter => "optional_parameter",
+            Typescript::ParameterName => "_parameter_name",
+            Typescript::OmittingTypeAnnotation => "omitting_type_annotation",
+            Typescript::AddingTypeAnnotation => "adding_type_annotation",
+            Typescript::OptingTypeAnnotation => "opting_type_annotation",
+            Typescript::TypeAnnotation => "type_annotation",
+            Typescript::MemberExpression3 => "member_expression",
+            Typescript::CallExpression3 => "call_expression",
+            Typescript::Asserts => "asserts",
+            Typescript::AssertsAnnotation => "asserts_annotation",
+            Typescript::Type2 => "type",
+            Typescript::RequiredParameter2 => "required_parameter",
+            Typescript::OptionalParameter2 => "optional_parameter",
+            Typescript::OptionalType => "optional_type",
+            Typescript::RestType => "rest_type",
+            Typescript::TupleTypeMember => "_tuple_type_member",
+            Typescript::ConstructorType => "constructor_type",
+            Typescript::PrimaryType => "primary_type",
+            Typescript::TemplateType => "template_type",
+            Typescript::TemplateLiteralType => "template_literal_type",
+            Typescript::InferType => "infer_type",
+            Typescript::ConditionalType => "conditional_type",
+            Typescript::GenericType => "generic_type",
+            Typescript::TypePredicate => "type_predicate",
+            Typescript::TypePredicateAnnotation => "type_predicate_annotation",
+            Typescript::MemberExpression4 => "member_expression",
+            Typescript::SubscriptExpression2 => "subscript_expression",
+            Typescript::CallExpression4 => "call_expression",
+            Typescript::InstantiationExpression2 => "instantiation_expression",
+            Typescript::TypeQuery => "type_query",
+            Typescript::IndexTypeQuery => "index_type_query",
+            Typescript::LookupType => "lookup_type",
+            Typescript::MappedTypeClause => "mapped_type_clause",
+            Typescript::LiteralType => "literal_type",
+            Typescript::UnaryExpression2 => "unary_expression",
+            Typescript::ExistentialType => "existential_type",
+            Typescript::FlowMaybeType => "flow_maybe_type",
+            Typescript::ParenthesizedType => "parenthesized_type",
+            Typescript::PredefinedType => "predefined_type",
+            Typescript::TypeArguments => "type_arguments",
+            Typescript::ObjectType => "object_type",
+            Typescript::CallSignature => "call_signature",
+            Typescript::PropertySignature => "property_signature",
+            Typescript::TypeParameters => "type_parameters",
+            Typescript::TypeParameter => "type_parameter",
+            Typescript::DefaultType => "default_type",
+            Typescript::Constraint => "constraint",
+            Typescript::ConstructSignature => "construct_signature",
+            Typescript::IndexSignature => "index_signature",
+            Typescript::ArrayType => "array_type",
+            Typescript::TupleType => "tuple_type",
+            Typescript::ReadonlyType => "readonly_type",
+            Typescript::UnionType => "union_type",
+            Typescript::IntersectionType => "intersection_type",
+            Typescript::FunctionType => "function_type",
+            Typescript::ProgramRepeat1 => "program_repeat1",
+            Typescript::ExportStatementRepeat1 => "export_statement_repeat1",
+            Typescript::ExportClauseRepeat1 => "export_clause_repeat1",
+            Typescript::NamedImportsRepeat1 => "named_imports_repeat1",
+            Typescript::VariableDeclarationRepeat1 => "variable_declaration_repeat1",
+            Typescript::SwitchBodyRepeat1 => "switch_body_repeat1",
+            Typescript::ObjectRepeat1 => "object_repeat1",
+            Typescript::ObjectPatternRepeat1 => "object_pattern_repeat1",
+            Typescript::ArrayRepeat1 => "array_repeat1",
+            Typescript::ArrayPatternRepeat1 => "array_pattern_repeat1",
+            Typescript::SequenceExpressionRepeat1 => "sequence_expression_repeat1",
+            Typescript::StringRepeat1 => "string_repeat1",
+            Typescript::StringRepeat2 => "string_repeat2",
+            Typescript::TemplateStringRepeat1 => "template_string_repeat1",
+            Typescript::ClassBodyRepeat1 => "class_body_repeat1",
+            Typescript::FormalParametersRepeat1 => "formal_parameters_repeat1",
+            Typescript::ExtendsClauseRepeat1 => "extends_clause_repeat1",
+            Typescript::ImplementsClauseRepeat1 => "implements_clause_repeat1",
+            Typescript::ExtendsTypeClauseRepeat1 => "extends_type_clause_repeat1",
+            Typescript::EnumBodyRepeat1 => "enum_body_repeat1",
+            Typescript::TemplateLiteralTypeRepeat1 => "template_literal_type_repeat1",
+            Typescript::ObjectTypeRepeat1 => "object_type_repeat1",
+            Typescript::TypeParametersRepeat1 => "type_parameters_repeat1",
+            Typescript::TupleTypeRepeat1 => "tuple_type_repeat1",
+            Typescript::InterfaceBody => "interface_body",
+            Typescript::PropertyIdentifier => "property_identifier",
+            Typescript::ShorthandPropertyIdentifier => "shorthand_property_identifier",
+            Typescript::ShorthandPropertyIdentifierPattern => {
+                "shorthand_property_identifier_pattern"
+            }
+            Typescript::StatementIdentifier => "statement_identifier",
+            Typescript::ThisType => "this_type",
+            Typescript::TypeIdentifier => "type_identifier",
+            Typescript::Error => "ERROR",
+        }
+    }
+}
+
+impl From for Typescript {
+    #[inline(always)]
+    fn from(x: u16) -> Self {
+        num::FromPrimitive::from_u16(x).unwrap_or(Self::Error)
+    }
+}
+
+// Typescript == u16
+impl PartialEq for Typescript {
+    #[inline(always)]
+    fn eq(&self, x: &u16) -> bool {
+        *self == Into::::into(*x)
+    }
+}
+
+// u16 == Typescript
+impl PartialEq for u16 {
+    #[inline(always)]
+    fn eq(&self, x: &Typescript) -> bool {
+        *x == *self
+    }
+}
diff --git a/src/languages/mod.rs b/src/languages/mod.rs
new file mode 100644
index 00000000..a21e50f7
--- /dev/null
+++ b/src/languages/mod.rs
@@ -0,0 +1,16 @@
+#![allow(clippy::enum_variant_names)]
+
+pub mod language_python;
+pub use language_python::*;
+
+pub mod language_rust;
+pub use language_rust::*;
+
+pub mod language_tsx;
+pub use language_tsx::*;
+
+pub mod language_typescript;
+pub use language_typescript::*;
+
+pub mod language_go;
+pub use language_go::*;
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 00000000..38ee3f36
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,107 @@
+//! mehen is a library to analyze and extract information
+//! from source codes written in many different programming languages.
+//!
+//! You can find the source code of this software on
+//! GitHub,
+//! while issues and feature requests can be posted on the respective
+//! GitHub Issue Tracker.
+//!
+//! ## Supported Languages
+//!
+//! - C++
+//! - C#
+//! - CSS
+//! - Go
+//! - HTML
+//! - Java
+//! - JavaScript
+//! - The JavaScript used in Firefox internal
+//! - Python
+//! - Rust
+//! - Typescript
+//!
+//! ## Supported Metrics
+//!
+//! - CC: it calculates the code complexity examining the
+//!   control flow of a program.
+//! - SLOC: it counts the number of lines in a source file.
+//! - PLOC: it counts the number of physical lines (instructions)
+//!   contained in a source file.
+//! - LLOC: it counts the number of logical lines (statements)
+//!   contained in a source file.
+//! - CLOC: it counts the number of comments in a source file.
+//! - BLANK: it counts the number of blank lines in a source file.
+//! - HALSTEAD: it is a suite that provides a series of information,
+//!   such as the effort required to maintain the analyzed code,
+//!   the size in bits to store the program, the difficulty to understand
+//!   the code, an estimate of the number of bugs present in the codebase,
+//!   and an estimate of the time needed to implement the software.
+//! - MI: it is a suite that allows to evaluate the maintainability
+//!   of a software.
+//! - NOM: it counts the number of functions and closures
+//!   in a file/trait/class.
+//! - NEXITS: it counts the number of possible exit points
+//!   from a method/function.
+//! - NARGS: it counts the number of arguments of a function/method.
+
+#![allow(clippy::upper_case_acronyms)]
+
+mod getter;
+mod macros;
+
+mod alterator;
+pub use alterator::*;
+
+mod node;
+pub use crate::node::*;
+
+mod metrics;
+pub use metrics::*;
+
+mod languages;
+pub(crate) use languages::*;
+
+mod checker;
+pub(crate) use checker::*;
+
+mod output;
+pub use output::*;
+
+mod spaces;
+pub use crate::spaces::*;
+
+mod ops;
+pub use crate::ops::*;
+
+mod find;
+pub use crate::find::*;
+
+mod function;
+pub use crate::function::*;
+
+mod ast;
+pub use crate::ast::*;
+
+mod count;
+pub use crate::count::*;
+
+mod preproc;
+pub use crate::preproc::*;
+
+mod langs;
+pub use crate::langs::*;
+
+mod tools;
+pub use crate::tools::*;
+
+mod concurrent_files;
+pub use crate::concurrent_files::*;
+
+mod traits;
+pub use crate::traits::*;
+
+mod parser;
+pub use crate::parser::*;
+
+mod comment_rm;
+pub use crate::comment_rm::*;
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 00000000..9c94e942
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,319 @@
+macro_rules! get_language {
+    (tree_sitter_cpp) => {
+        tree_sitter_mozcpp::LANGUAGE.into()
+    };
+    (tree_sitter_typescript) => {
+        tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()
+    };
+    (tree_sitter_tsx) => {
+        tree_sitter_typescript::LANGUAGE_TSX.into()
+    };
+    ($name:ident) => {
+        $name::LANGUAGE.into()
+    };
+}
+
+macro_rules! implement_metric_trait {
+    (Abc, $($code:ident),+) => (
+        $(
+           impl Abc for $code {
+               fn compute(_node: &Node, _stats: &mut Stats) {}
+           }
+        )+
+    );
+    (Cognitive, $($code:ident),+) => (
+        $(
+           impl Cognitive for $code {
+               fn compute(_node: &Node, _stats: &mut Stats, _nesting_map: &mut HashMap,) {}
+           }
+        )+
+    );
+    (Halstead, $($code:ident),+) => (
+        $(
+           impl Halstead for $code {
+               fn compute<'a>(_node: &Node<'a>, _code: &'a [u8], _halstead_maps: &mut HalsteadMaps<'a>) {}
+           }
+        )+
+    );
+    (Loc, $($code:ident),+) => (
+        $(
+           impl Loc for $code {
+               fn compute(_node: &Node, _stats: &mut Stats, _is_func_space: bool, _is_unit: bool) {}
+           }
+        )+
+    );
+    (Wmc, $($code:ident),+) => (
+        $(
+           impl Wmc for $code {
+               fn compute(_space_kind: SpaceKind, _cyclomatic: &cyclomatic::Stats, _stats: &mut Stats) {}
+           }
+        )+
+    );
+    ([$trait:ident], $($code:ident),+) => (
+        $(
+           impl $trait for $code {}
+        )+
+    );
+    ($trait:ident, $($code:ident),+) => (
+        $(
+           impl $trait for $code {
+               fn compute(_node: &Node, _stats: &mut Stats) {}
+           }
+        )+
+    )
+}
+
+macro_rules! mk_lang {
+    ( $( ($camel:ident, $name:ident, $display: expr, $description:expr) ),* ) => {
+        /// The list of supported languages.
+        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
+        pub enum LANG {
+            $(
+                #[doc = $description]
+                $camel,
+            )*
+        }
+        impl LANG {
+            /// Return an iterator over the supported languages.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use mehen::LANG;
+            ///
+            /// for lang in LANG::into_enum_iter() {
+            ///     println!("{:?}", lang);
+            /// }
+            /// ```
+            pub fn into_enum_iter() -> impl Iterator {
+                use LANG::*;
+                [$( $camel, )*].into_iter()
+            }
+
+            /// Returns the name of a language as a `&str`.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use mehen::LANG;
+            ///
+            /// println!("{}", LANG::Rust.get_name());
+            /// ```
+            pub fn get_name(&self) -> &'static str {
+                match self {
+                    $(
+                        LANG::$camel => $display,
+                    )*
+                }
+            }
+
+            // Returns a tree-sitter language.
+            // This function is only used to construct a parser.
+            pub(crate) fn get_ts_language(&self) -> Language {
+                    match self {
+                        $(
+                            LANG::$camel => get_language!($name),
+                        )*
+                    }
+            }
+        }
+    };
+}
+
+macro_rules! mk_action {
+    ( $( ($camel:ident, $parser:ident) ),* ) => {
+        /// Runs a function, which implements the [`Callback`] trait,
+        /// on a code written in one of the supported languages.
+        ///
+        /// # Examples
+        ///
+        /// The following example dumps to shell every metric computed using
+        /// the dummy source code.
+        ///
+        /// ```
+        /// use std::path::PathBuf;
+        ///
+        /// use mehen::{action, Callback, LANG, Metrics, MetricsCfg};
+        ///
+        /// let source_code = "fn main() { let a = 42; }";
+        /// let language = LANG::Rust;
+        ///
+        /// let path = PathBuf::from("foo.rs");
+        /// let source_as_vec = source_code.as_bytes().to_vec();
+        ///
+        /// let cfg = MetricsCfg {
+        ///     path,
+        /// };
+        ///
+        /// action::(&language, source_as_vec, &cfg.path.clone(), None, cfg);
+        /// ```
+        ///
+        /// [`Callback`]: trait.Callback.html
+        #[inline(always)]
+        pub fn action(lang: &LANG, source: Vec, path: &Path, pr: Option>, cfg: T::Cfg) -> T::Res {
+            match lang {
+                $(
+                    LANG::$camel => {
+                        let parser = $parser::new(source, path, pr);
+                        T::call(cfg, &parser)
+                    },
+                )*
+            }
+        }
+
+        /// Returns all function spaces data of a code.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// use std::path::PathBuf;
+        ///
+        /// use mehen::{get_function_spaces, LANG};
+        ///
+        /// let source_code = "fn main() { let a = 42; }";
+        /// let language = LANG::Rust;
+        ///
+        /// let path = PathBuf::from("foo.rs");
+        /// let source_as_vec = source_code.as_bytes().to_vec();
+        ///
+        /// get_function_spaces(&language, source_as_vec, &path, None).unwrap();
+        /// ```
+        #[inline(always)]
+        pub fn get_function_spaces(lang: &LANG, source: Vec, path: &Path, pr: Option>) -> Option {
+            match lang {
+                $(
+                    LANG::$camel => {
+                        let parser = $parser::new(source, &path, pr);
+                        metrics(&parser, &path)
+                    },
+                )*
+            }
+        }
+
+        /// Returns all operators and operands of each space in a code.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// use std::path::PathBuf;
+        ///
+        /// use mehen::{get_ops, LANG};
+        ///
+        /// # fn main() {
+        /// let source_code = "fn main() { let a = 42; }";
+        /// let language = LANG::Rust;
+        ///
+        /// let path = PathBuf::from("foo.rs");
+        /// let source_as_vec = source_code.as_bytes().to_vec();
+        ///
+        /// get_ops(&language, source_as_vec, &path, None).unwrap();
+        /// # }
+        /// ```
+        #[inline(always)]
+        pub fn get_ops(lang: &LANG, source: Vec, path: &Path, pr: Option>) -> Option {
+            match lang {
+                $(
+                    LANG::$camel => {
+                        let parser = $parser::new(source, &path, pr);
+                        operands_and_operators(&parser, &path)
+                    },
+                )*
+            }
+        }
+    };
+}
+
+macro_rules! mk_extensions {
+    ( $( ($camel:ident, [ $( $ext:ident ),* ]) ),* ) => {
+        /// Detects the language associated to the input file extension.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// use mehen::get_from_ext;
+        ///
+        /// let ext = "rs";
+        ///
+        /// get_from_ext(ext).unwrap();
+        /// ```
+        pub fn get_from_ext(ext: &str) -> Option{
+            match ext {
+                $(
+                    $(
+                        stringify!($ext) => Some(LANG::$camel),
+                    )*
+                )*
+                _ => None,
+            }
+        }
+    };
+}
+
+macro_rules! mk_emacs_mode {
+    ( $( ($camel:ident, [ $( $emacs_mode:expr ),* ]) ),* ) => {
+        /// Detects the language associated to the input `Emacs` mode.
+        ///
+        /// An `Emacs` mode is used to detect a language according to
+        /// particular text-information contained in a file.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// use mehen::get_from_emacs_mode;
+        ///
+        /// let emacs_mode = "rust";
+        ///
+        /// get_from_emacs_mode(emacs_mode).unwrap();
+        /// ```
+        pub fn get_from_emacs_mode(mode: &str) -> Option{
+            match mode {
+                $(
+                    $(
+                        $emacs_mode => Some(LANG::$camel),
+                    )*
+                )*
+                _ => None,
+            }
+        }
+    };
+}
+
+macro_rules! mk_code {
+    ( $( ($camel:ident, $code:ident, $parser:ident, $name:ident, $docname:expr) ),* ) => {
+        $(
+            pub struct $code { _guard: (), }
+
+            impl LanguageInfo for $code {
+                type BaseLang = $camel;
+
+                fn get_lang() -> LANG {
+                    LANG::$camel
+                }
+
+                fn get_lang_name() -> &'static str {
+                    $docname
+                }
+            }
+
+            #[doc = "The `"]
+            #[doc = $docname]
+            #[doc = "` language parser."]
+            pub type $parser = Parser<$code>;
+        )*
+    };
+}
+
+macro_rules! mk_langs {
+    ( $( ($camel:ident, $description: expr, $display: expr, $code:ident, $parser:ident, $name:ident, [ $( $ext:ident ),* ], [ $( $emacs_mode:expr ),* ]) ),* ) => {
+        mk_lang!($( ($camel, $name, $display, $description) ),*);
+        mk_action!($( ($camel, $parser) ),*);
+        mk_extensions!($( ($camel, [ $( $ext ),* ]) ),*);
+        mk_emacs_mode!($( ($camel, [ $( $emacs_mode ),* ]) ),*);
+        mk_code!($( ($camel, $code, $parser, $name, stringify!($camel)) ),*);
+    };
+}
+
+pub(crate) use implement_metric_trait;
+pub(crate) use {
+    get_language, mk_action, mk_code, mk_emacs_mode, mk_extensions, mk_lang, mk_langs,
+};
diff --git a/src/metrics/abc.rs b/src/metrics/abc.rs
new file mode 100644
index 00000000..c696aef5
--- /dev/null
+++ b/src/metrics/abc.rs
@@ -0,0 +1,248 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::macros::implement_metric_trait;
+use crate::node::Node;
+use crate::*;
+
+/// The `ABC` metric.
+///
+/// The `ABC` metric measures the size of a source code by counting
+/// the number of Assignments (`A`), Branches (`B`) and Conditions (`C`).
+/// The metric defines an ABC score as a vector of three elements (``).
+/// The ABC score can be represented by its individual components (`A`, `B` and `C`)
+/// or by the magnitude of the vector (`|| = sqrt(A^2 + B^2 + C^2)`).
+///
+/// Official paper and definition:
+///
+/// Fitzpatrick, Jerry (1997). "Applying the ABC metric to C, C++ and Java". C++ Report.
+///
+/// 
+#[derive(Debug, Clone)]
+pub struct Stats {
+    assignments: f64,
+    assignments_sum: f64,
+    assignments_min: f64,
+    assignments_max: f64,
+    branches: f64,
+    branches_sum: f64,
+    branches_min: f64,
+    branches_max: f64,
+    conditions: f64,
+    conditions_sum: f64,
+    conditions_min: f64,
+    conditions_max: f64,
+    space_count: usize,
+}
+
+impl Default for Stats {
+    fn default() -> Self {
+        Self {
+            assignments: 0.,
+            assignments_sum: 0.,
+            assignments_min: f64::MAX,
+            assignments_max: 0.,
+            branches: 0.,
+            branches_sum: 0.,
+            branches_min: f64::MAX,
+            branches_max: 0.,
+            conditions: 0.,
+            conditions_sum: 0.,
+            conditions_min: f64::MAX,
+            conditions_max: 0.,
+            space_count: 1,
+        }
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("abc", 13)?;
+        st.serialize_field("assignments", &self.assignments_sum())?;
+        st.serialize_field("branches", &self.branches_sum())?;
+        st.serialize_field("conditions", &self.conditions_sum())?;
+        st.serialize_field("magnitude", &self.magnitude_sum())?;
+        st.serialize_field("assignments_average", &self.assignments_average())?;
+        st.serialize_field("branches_average", &self.branches_average())?;
+        st.serialize_field("conditions_average", &self.conditions_average())?;
+        st.serialize_field("assignments_min", &self.assignments_min())?;
+        st.serialize_field("assignments_max", &self.assignments_max())?;
+        st.serialize_field("branches_min", &self.branches_min())?;
+        st.serialize_field("branches_max", &self.branches_max())?;
+        st.serialize_field("conditions_min", &self.conditions_min())?;
+        st.serialize_field("conditions_max", &self.conditions_max())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "assignments: {}, branches: {}, conditions: {}, magnitude: {}, \
+            assignments_average: {}, branches_average: {}, conditions_average: {}, \
+            assignments_min: {}, assignments_max: {}, \
+            branches_min: {}, branches_max: {}, \
+            conditions_min: {}, conditions_max: {}",
+            self.assignments_sum(),
+            self.branches_sum(),
+            self.conditions_sum(),
+            self.magnitude_sum(),
+            self.assignments_average(),
+            self.branches_average(),
+            self.conditions_average(),
+            self.assignments_min(),
+            self.assignments_max(),
+            self.branches_min(),
+            self.branches_max(),
+            self.conditions_min(),
+            self.conditions_max()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Abc` metric into the first one.
+    pub fn merge(&mut self, other: &Stats) {
+        // Calculates minimum and maximum values
+        self.assignments_min = self.assignments_min.min(other.assignments_min);
+        self.assignments_max = self.assignments_max.max(other.assignments_max);
+        self.branches_min = self.branches_min.min(other.branches_min);
+        self.branches_max = self.branches_max.max(other.branches_max);
+        self.conditions_min = self.conditions_min.min(other.conditions_min);
+        self.conditions_max = self.conditions_max.max(other.conditions_max);
+
+        self.assignments_sum += other.assignments_sum;
+        self.branches_sum += other.branches_sum;
+        self.conditions_sum += other.conditions_sum;
+
+        self.space_count += other.space_count;
+    }
+
+    /// Returns the `Abc` assignments metric value.
+    pub fn assignments(&self) -> f64 {
+        self.assignments
+    }
+
+    /// Returns the `Abc` assignments sum metric value.
+    pub fn assignments_sum(&self) -> f64 {
+        self.assignments_sum
+    }
+
+    /// Returns the `Abc` assignments average value.
+    ///
+    /// This value is computed dividing the `Abc`
+    /// assignments value for the number of spaces.
+    pub fn assignments_average(&self) -> f64 {
+        self.assignments_sum() / self.space_count as f64
+    }
+
+    /// Returns the `Abc` assignments minimum value.
+    pub fn assignments_min(&self) -> f64 {
+        self.assignments_min
+    }
+
+    /// Returns the `Abc` assignments maximum value.
+    pub fn assignments_max(&self) -> f64 {
+        self.assignments_max
+    }
+
+    /// Returns the `Abc` branches metric value.
+    pub fn branches(&self) -> f64 {
+        self.branches
+    }
+
+    /// Returns the `Abc` branches sum metric value.
+    pub fn branches_sum(&self) -> f64 {
+        self.branches_sum
+    }
+
+    /// Returns the `Abc` branches average value.
+    ///
+    /// This value is computed dividing the `Abc`
+    /// branches value for the number of spaces.
+    pub fn branches_average(&self) -> f64 {
+        self.branches_sum() / self.space_count as f64
+    }
+
+    /// Returns the `Abc` branches minimum value.
+    pub fn branches_min(&self) -> f64 {
+        self.branches_min
+    }
+
+    /// Returns the `Abc` branches maximum value.
+    pub fn branches_max(&self) -> f64 {
+        self.branches_max
+    }
+
+    /// Returns the `Abc` conditions metric value.
+    pub fn conditions(&self) -> f64 {
+        self.conditions
+    }
+
+    /// Returns the `Abc` conditions sum metric value.
+    pub fn conditions_sum(&self) -> f64 {
+        self.conditions_sum
+    }
+
+    /// Returns the `Abc` conditions average value.
+    ///
+    /// This value is computed dividing the `Abc`
+    /// conditions value for the number of spaces.
+    pub fn conditions_average(&self) -> f64 {
+        self.conditions_sum() / self.space_count as f64
+    }
+
+    /// Returns the `Abc` conditions minimum value.
+    pub fn conditions_min(&self) -> f64 {
+        self.conditions_min
+    }
+
+    /// Returns the `Abc` conditions maximum value.
+    pub fn conditions_max(&self) -> f64 {
+        self.conditions_max
+    }
+
+    /// Returns the `Abc` magnitude metric value.
+    pub fn magnitude(&self) -> f64 {
+        (self.assignments.powi(2) + self.branches.powi(2) + self.conditions.powi(2)).sqrt()
+    }
+
+    /// Returns the `Abc` magnitude sum metric value.
+    pub fn magnitude_sum(&self) -> f64 {
+        (self.assignments_sum.powi(2) + self.branches_sum.powi(2) + self.conditions_sum.powi(2))
+            .sqrt()
+    }
+
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.assignments_sum += self.assignments;
+        self.branches_sum += self.branches;
+        self.conditions_sum += self.conditions;
+    }
+
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        self.assignments_min = self.assignments_min.min(self.assignments);
+        self.assignments_max = self.assignments_max.max(self.assignments);
+        self.branches_min = self.branches_min.min(self.branches);
+        self.branches_max = self.branches_max.max(self.branches);
+        self.conditions_min = self.conditions_min.min(self.conditions);
+        self.conditions_max = self.conditions_max.max(self.conditions);
+        self.compute_sum();
+    }
+}
+
+pub trait Abc
+where
+    Self: Checker,
+{
+    fn compute(node: &Node, stats: &mut Stats);
+}
+
+implement_metric_trait!(Abc, PythonCode, TypescriptCode, TsxCode, RustCode, GoCode);
diff --git a/src/metrics/cognitive.rs b/src/metrics/cognitive.rs
new file mode 100644
index 00000000..5b18edeb
--- /dev/null
+++ b/src/metrics/cognitive.rs
@@ -0,0 +1,1287 @@
+use std::collections::HashMap;
+
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::*;
+
+// TODO: Find a way to increment the cognitive complexity value
+// for recursive code. For some kind of languages, such as C++, it is pretty
+// hard to detect, just parsing the code, if a determined function is recursive
+// because the call graph of a function is solved at runtime.
+// So a possible solution could be searching for a crate which implements
+// a light language interpreter, computing the call graph, and then detecting
+// if there are cycles. At this point, it is possible to figure out if a
+// function is recursive or not.
+
+/// The `Cognitive Complexity` metric.
+#[derive(Debug, Clone)]
+pub struct Stats {
+    structural: usize,
+    structural_sum: usize,
+    structural_min: usize,
+    structural_max: usize,
+    nesting: usize,
+    total_space_functions: usize,
+    boolean_seq: BoolSequence,
+}
+
+impl Default for Stats {
+    fn default() -> Self {
+        Self {
+            structural: 0,
+            structural_sum: 0,
+            structural_min: usize::MAX,
+            structural_max: 0,
+            nesting: 0,
+            total_space_functions: 1,
+            boolean_seq: BoolSequence::default(),
+        }
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("cognitive", 4)?;
+        st.serialize_field("sum", &self.cognitive_sum())?;
+        st.serialize_field("average", &self.cognitive_average())?;
+        st.serialize_field("min", &self.cognitive_min())?;
+        st.serialize_field("max", &self.cognitive_max())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "sum: {}, average: {}, min:{}, max: {}",
+            self.cognitive(),
+            self.cognitive_average(),
+            self.cognitive_min(),
+            self.cognitive_max()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Cognitive Complexity` metric into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        self.structural_min = self.structural_min.min(other.structural_min);
+        self.structural_max = self.structural_max.max(other.structural_max);
+        self.structural_sum += other.structural_sum;
+    }
+
+    /// Returns the `Cognitive Complexity` metric value
+    pub fn cognitive(&self) -> f64 {
+        self.structural as f64
+    }
+    /// Returns the `Cognitive Complexity` sum metric value
+    pub fn cognitive_sum(&self) -> f64 {
+        self.structural_sum as f64
+    }
+
+    /// Returns the `Cognitive Complexity` minimum metric value
+    pub fn cognitive_min(&self) -> f64 {
+        self.structural_min as f64
+    }
+    /// Returns the `Cognitive Complexity` maximum metric value
+    pub fn cognitive_max(&self) -> f64 {
+        self.structural_max as f64
+    }
+
+    /// Returns the `Cognitive Complexity` metric average value
+    ///
+    /// This value is computed dividing the `Cognitive Complexity` value
+    /// for the total number of functions/closures in a space.
+    ///
+    /// If there are no functions in a code, its value is `NAN`.
+    pub fn cognitive_average(&self) -> f64 {
+        self.cognitive_sum() / self.total_space_functions as f64
+    }
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.structural_sum += self.structural;
+    }
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        self.structural_min = self.structural_min.min(self.structural);
+        self.structural_max = self.structural_max.max(self.structural);
+        self.compute_sum();
+    }
+
+    pub(crate) fn finalize(&mut self, total_space_functions: usize) {
+        self.total_space_functions = total_space_functions;
+    }
+}
+
+pub trait Cognitive
+where
+    Self: Checker,
+{
+    fn compute(
+        node: &Node,
+        stats: &mut Stats,
+        nesting_map: &mut HashMap,
+    );
+}
+
+fn compute_booleans>(
+    node: &Node,
+    stats: &mut Stats,
+    typs1: T,
+    typs2: T,
+) {
+    for child in node.children() {
+        if typs1 == child.kind_id().into() || typs2 == child.kind_id().into() {
+            stats.structural = stats
+                .boolean_seq
+                .eval_based_on_prev(child.kind_id(), stats.structural)
+        }
+    }
+}
+
+#[derive(Debug, Default, Clone)]
+struct BoolSequence {
+    boolean_op: Option,
+}
+
+impl BoolSequence {
+    fn reset(&mut self) {
+        self.boolean_op = None;
+    }
+
+    fn not_operator(&mut self, not_id: u16) {
+        self.boolean_op = Some(not_id);
+    }
+
+    fn eval_based_on_prev(&mut self, bool_id: u16, structural: usize) -> usize {
+        if let Some(prev) = self.boolean_op {
+            if prev != bool_id {
+                // The boolean operator is different from the previous one, so
+                // the counter is incremented.
+                structural + 1
+            } else {
+                // The boolean operator is equal to the previous one, so
+                // the counter is not incremented.
+                structural
+            }
+        } else {
+            // Save the first boolean operator in a sequence of
+            // logical operators and increment the counter.
+            self.boolean_op = Some(bool_id);
+            structural + 1
+        }
+    }
+}
+
+#[inline(always)]
+fn increment(stats: &mut Stats) {
+    stats.structural += stats.nesting + 1;
+}
+
+#[inline(always)]
+fn increment_by_one(stats: &mut Stats) {
+    stats.structural += 1;
+}
+
+fn get_nesting_from_map(
+    node: &Node,
+    nesting_map: &mut HashMap,
+) -> (usize, usize, usize) {
+    if let Some(parent) = node.parent() {
+        if let Some(n) = nesting_map.get(&parent.id()) {
+            *n
+        } else {
+            (0, 0, 0)
+        }
+    } else {
+        (0, 0, 0)
+    }
+}
+
+fn increment_function_depth>(
+    depth: &mut usize,
+    node: &Node,
+    stop: T,
+) {
+    // Increase depth function nesting if needed
+    let mut child = *node;
+    while let Some(parent) = child.parent() {
+        if stop == parent.kind_id().into() {
+            *depth += 1;
+            break;
+        }
+        child = parent;
+    }
+}
+
+#[inline(always)]
+fn increase_nesting(stats: &mut Stats, nesting: &mut usize, depth: usize, lambda: usize) {
+    stats.nesting = *nesting + depth + lambda;
+    increment(stats);
+    *nesting += 1;
+    stats.boolean_seq.reset();
+}
+
+impl Cognitive for PythonCode {
+    fn compute(
+        node: &Node,
+        stats: &mut Stats,
+        nesting_map: &mut HashMap,
+    ) {
+        use Python::*;
+
+        // Get nesting of the parent
+        let (mut nesting, mut depth, mut lambda) = get_nesting_from_map(node, nesting_map);
+
+        match node.kind_id().into() {
+            IfStatement | ForStatement | WhileStatement | ConditionalExpression => {
+                increase_nesting(stats, &mut nesting, depth, lambda);
+            }
+            ElifClause => {
+                // No nesting increment for them because their cost has already
+                // been paid by the if construct
+                increment_by_one(stats);
+                // Reset the boolean sequence
+                stats.boolean_seq.reset();
+            }
+            ElseClause | FinallyClause => {
+                // No nesting increment for them because their cost has already
+                // been paid by the if construct
+                increment_by_one(stats);
+            }
+            ExceptClause => {
+                nesting += 1;
+                increment(stats);
+            }
+            ExpressionList | ExpressionStatement | Tuple => {
+                stats.boolean_seq.reset();
+            }
+            NotOperator => {
+                stats.boolean_seq.not_operator(node.kind_id());
+            }
+            BooleanOperator => {
+                if node.count_specific_ancestors::(
+                    |node| node.kind_id() == BooleanOperator,
+                    |node| node.kind_id() == Lambda,
+                ) == 0
+                {
+                    stats.structural += node.count_specific_ancestors::(
+                        |node| node.kind_id() == Lambda,
+                        |node| {
+                            matches!(
+                                node.kind_id().into(),
+                                ExpressionList | IfStatement | ForStatement | WhileStatement
+                            )
+                        },
+                    );
+                }
+                compute_booleans::(node, stats, And, Or);
+            }
+            Lambda => {
+                // Increase lambda nesting
+                lambda += 1;
+            }
+            FunctionDefinition => {
+                // Increase depth function nesting if needed
+                increment_function_depth::(
+                    &mut depth,
+                    node,
+                    FunctionDefinition,
+                );
+            }
+            _ => {}
+        }
+        // Add node to nesting map
+        nesting_map.insert(node.id(), (nesting, depth, lambda));
+    }
+}
+
+impl Cognitive for RustCode {
+    fn compute(
+        node: &Node,
+        stats: &mut Stats,
+        nesting_map: &mut HashMap,
+    ) {
+        use Rust::*;
+        //TODO: Implement macros
+        let (mut nesting, mut depth, mut lambda) = get_nesting_from_map(node, nesting_map);
+
+        match node.kind_id().into() {
+            IfExpression => {
+                // Check if a node is not an else-if
+                if !Self::is_else_if(node) {
+                    increase_nesting(stats,&mut nesting, depth, lambda);
+                }
+            }
+            ForExpression | WhileExpression | MatchExpression => {
+                increase_nesting(stats,&mut nesting, depth, lambda);
+            }
+            Else /*else-if also */ => {
+                increment_by_one(stats);
+            }
+            BreakExpression | ContinueExpression => {
+                if let Some(label_child) = node.child(1)
+                    && let Label = label_child.kind_id().into()
+                {
+                    increment_by_one(stats);
+                }
+            }
+            UnaryExpression => {
+                stats.boolean_seq.not_operator(node.kind_id());
+            }
+            BinaryExpression => {
+                compute_booleans::(node, stats, AMPAMP, PIPEPIPE);
+            }
+            FunctionItem  => {
+                nesting = 0;
+                // Increase depth function nesting if needed
+                increment_function_depth::(&mut depth, node, FunctionItem);
+            }
+            ClosureExpression => {
+                lambda += 1;
+            }
+            _ => {}
+        }
+        nesting_map.insert(node.id(), (nesting, depth, lambda));
+    }
+}
+
+macro_rules! js_cognitive {
+    ($lang:ident) => {
+        fn compute(node: &Node, stats: &mut Stats, nesting_map: &mut HashMap) {
+            use $lang::*;
+            let (mut nesting, mut depth, mut lambda) = get_nesting_from_map(node, nesting_map);
+
+            match node.kind_id().into() {
+                IfStatement => {
+                    if !Self::is_else_if(&node) {
+                        increase_nesting(stats,&mut nesting, depth, lambda);
+                    }
+                }
+                ForStatement | ForInStatement | WhileStatement | DoStatement | SwitchStatement | CatchClause | TernaryExpression => {
+                    increase_nesting(stats,&mut nesting, depth, lambda);
+                }
+                Else /* else-if also */ => {
+                    increment_by_one(stats);
+                }
+                ExpressionStatement => {
+                    // Reset the boolean sequence
+                    stats.boolean_seq.reset();
+                }
+                UnaryExpression => {
+                    stats.boolean_seq.not_operator(node.kind_id());
+                }
+                BinaryExpression => {
+                    compute_booleans::<$lang>(node, stats, AMPAMP, PIPEPIPE);
+                }
+                FunctionDeclaration => {
+                    // Reset lambda nesting at function for JS
+                    nesting = 0;
+                    lambda = 0;
+                    // Increase depth function nesting if needed
+                    increment_function_depth::<$lang>(&mut depth, node, FunctionDeclaration);
+                }
+                ArrowFunction => {
+                    lambda += 1;
+                }
+                _ => {}
+            }
+            nesting_map.insert(node.id(), (nesting, depth, lambda));
+        }
+    };
+}
+
+impl Cognitive for TypescriptCode {
+    js_cognitive!(Typescript);
+}
+
+impl Cognitive for TsxCode {
+    js_cognitive!(Tsx);
+}
+
+impl Cognitive for GoCode {
+    fn compute(
+        node: &Node,
+        stats: &mut Stats,
+        nesting_map: &mut HashMap,
+    ) {
+        use crate::Go::*;
+
+        let (mut nesting, mut depth, mut lambda) = get_nesting_from_map(node, nesting_map);
+
+        match node.kind_id().into() {
+            IfStatement => {
+                if !Self::is_else_if(node) {
+                    increase_nesting(stats, &mut nesting, depth, lambda);
+                }
+            }
+            ForStatement | ExpressionSwitchStatement | TypeSwitchStatement | SelectStatement => {
+                increase_nesting(stats, &mut nesting, depth, lambda);
+            }
+            Else /* else-if also */ => {
+                increment_by_one(stats);
+            }
+            UnaryExpression => {
+                stats.boolean_seq.not_operator(node.kind_id());
+            }
+            BinaryExpression => {
+                compute_booleans::(node, stats, AMPAMP, PIPEPIPE);
+            }
+            FuncLiteral => {
+                lambda += 1;
+            }
+            FunctionDeclaration | MethodDeclaration => {
+                nesting = 0;
+                increment_function_depth::(&mut depth, node, FunctionDeclaration);
+            }
+            _ => {}
+        }
+        nesting_map.insert(node.id(), (nesting, depth, lambda));
+    }
+}
+
+// No languages require empty Cognitive implementations
+// implement_metric_trait!(Cognitive);
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn python_no_cognitive() {
+        check_metrics::("a = 42", "foo.py", |metric| {
+            insta::assert_json_snapshot!(
+                metric.cognitive,
+                @r###"
+                    {
+                      "sum": 0.0,
+                      "average": null,
+                      "min": 0.0,
+                      "max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_no_cognitive() {
+        check_metrics::("let a = 42;", "foo.rs", |metric| {
+            insta::assert_json_snapshot!(
+                metric.cognitive,
+                @r###"
+                    {
+                      "sum": 0.0,
+                      "average": null,
+                      "min": 0.0,
+                      "max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn python_simple_function() {
+        check_metrics::(
+            "def f(a, b):
+                if a and b:  # +2 (+1 and)
+                   return 1
+                if c and d: # +2 (+1 and)
+                   return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 4.0,
+                      "min": 0.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_expression_statement() {
+        // Boolean expressions containing `And` and `Or` operators were not
+        // considered in assignments
+        check_metrics::(
+            "def f(a, b):
+                c = True and True",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 1.0,
+                      "average": 1.0,
+                      "min": 0.0,
+                      "max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_tuple() {
+        // Boolean expressions containing `And` and `Or` operators were not
+        // considered inside tuples
+        check_metrics::(
+            "def f(a, b):
+                return \"%s%s\" % (a and \"Get\" or \"Set\", b)",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 2.0,
+                      "min": 0.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_elif_function() {
+        // Boolean expressions containing `And` and `Or` operators were not
+        // considered in `elif` statements
+        check_metrics::(
+            "def f(a, b):
+                if a and b:  # +2 (+1 and)
+                   return 1
+                elif c and d: # +2 (+1 and)
+                   return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 4.0,
+                      "min": 0.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_more_elifs_function() {
+        // Boolean expressions containing `And` and `Or` operators were not
+        // considered when there were more `elif` statements
+        check_metrics::(
+            "def f(a, b):
+                if a and b:  # +2 (+1 and)
+                   return 1
+                elif c and d: # +2 (+1 and)
+                   return 1
+                elif e and f: # +2 (+1 and)
+                   return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 6.0,
+                      "average": 6.0,
+                      "min": 0.0,
+                      "max": 6.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_simple_function() {
+        check_metrics::(
+            "fn f() {
+                 if a && b { // +2 (+1 &&)
+                     println!(\"test\");
+                 }
+                 if c && d { // +2 (+1 &&)
+                     println!(\"test\");
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 4.0,
+                      "min": 0.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_sequence_same_booleans() {
+        check_metrics::(
+            "def f(a, b):
+                if a and b and True:  # +2 (+1 sequence of and)
+                   return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 2.0,
+                      "min": 0.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_sequence_same_booleans() {
+        check_metrics::(
+            "fn f() {
+                 if a && b && true { // +2 (+1 sequence of &&)
+                     println!(\"test\");
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 2.0,
+                      "min": 0.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+
+        check_metrics::(
+            "fn f() {
+                 if a || b || c || d { // +2 (+1 sequence of ||)
+                     println!(\"test\");
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 2.0,
+                      "min": 0.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_not_booleans() {
+        check_metrics::(
+            "fn f() {
+                 if !a && !b { // +2 (+1 &&)
+                     println!(\"test\");
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 2.0,
+                      "min": 0.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+
+        check_metrics::(
+            "fn f() {
+                 if a && !(b && c) { // +3 (+1 &&, +1 &&)
+                     println!(\"test\");
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+
+        check_metrics::(
+            "fn f() {
+                 if !(a || b) && !(c || d) { // +4 (+1 ||, +1 &&, +1 ||)
+                     println!(\"test\");
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 4.0,
+                      "min": 0.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_sequence_different_booleans() {
+        check_metrics::(
+            "def f(a, b):
+                if a and b or True:  # +3 (+1 and, +1 or)
+                   return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_sequence_different_booleans() {
+        check_metrics::(
+            "fn f() {
+                 if a && b || true { // +3 (+1 &&, +1 ||)
+                     println!(\"test\");
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_formatted_sequence_different_booleans() {
+        check_metrics::(
+            "def f(a, b):
+                if (  # +1
+                    a and b and  # +1
+                    (c or d)  # +1
+                ):
+                   return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_1_level_nesting() {
+        check_metrics::(
+            "def f(a, b):
+                if a:  # +1
+                    for i in range(b):  # +2
+                        return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_1_level_nesting() {
+        check_metrics::(
+            "fn f() {
+                 if true { // +1
+                     if true { // +2 (nesting = 1)
+                         println!(\"test\");
+                     } else if 1 == 1 { // +1
+                         if true { // +3 (nesting = 2)
+                             println!(\"test\");
+                         }
+                     } else { // +1
+                         if true { // +3 (nesting = 2)
+                             println!(\"test\");
+                         }
+                     }
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 11.0,
+                      "average": 11.0,
+                      "min": 0.0,
+                      "max": 11.0
+                    }"###
+                );
+            },
+        );
+
+        check_metrics::(
+            "fn f() {
+                 if true { // +1
+                     match true { // +2 (nesting = 1)
+                         true => println!(\"test\"),
+                         false => println!(\"test\"),
+                     }
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_2_level_nesting() {
+        check_metrics::(
+            "def f(a, b):
+                if a:  # +1
+                    for i in range(b):  # +2
+                        if b:  # +3
+                            return 1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 6.0,
+                      "average": 6.0,
+                      "min": 0.0,
+                      "max": 6.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_2_level_nesting() {
+        check_metrics::(
+            "fn f() {
+                 if true { // +1
+                     for i in 0..4 { // +2 (nesting = 1)
+                         match true { // +3 (nesting = 2)
+                             true => println!(\"test\"),
+                             false => println!(\"test\"),
+                         }
+                     }
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 6.0,
+                      "average": 6.0,
+                      "min": 0.0,
+                      "max": 6.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_try_construct() {
+        check_metrics::(
+            "def f(a, b):
+                try:
+                    for foo in bar:  # +1
+                        return a
+                except Exception:  # +1
+                    if a < 0:  # +2
+                        return a",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 4.0,
+                      "min": 0.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_break_continue() {
+        // Only labeled break and continue statements are considered
+        check_metrics::(
+            "fn f() {
+                 'tens: for ten in 0..3 { // +1
+                     '_units: for unit in 0..=9 { // +2 (nesting = 1)
+                         if unit % 2 == 0 { // +3 (nesting = 2)
+                             continue;
+                         } else if unit == 5 { // +1
+                             continue 'tens; // +1
+                         } else if unit == 6 { // +1
+                             break;
+                         } else { // +1
+                             break 'tens; // +1
+                         }
+                     }
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 11.0,
+                      "average": 11.0,
+                      "min": 0.0,
+                      "max": 11.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_ternary_operator() {
+        check_metrics::(
+            "def f(a, b):
+                 if a % 2:  # +1
+                     return 'c' if a else 'd'  # +2
+                 return 'a' if a else 'b'  # +1",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 4.0,
+                      "min": 0.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_nested_functions_lambdas() {
+        check_metrics::(
+            "def f(a, b):
+                 def foo(a):
+                     if a:  # +2 (+1 nesting)
+                         return 1
+                 # +3 (+1 for boolean sequence +2 for lambda nesting)
+                 bar = lambda a: lambda b: b or True or True
+                 return bar(foo(a))(a)",
+            "foo.py",
+            |metric| {
+                // 2 functions + 2 lambdas = 4
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 5.0,
+                      "average": 1.25,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_real_function() {
+        check_metrics::(
+            "def process_raw_constant(constant, min_word_length):
+                 processed_words = []
+                 raw_camelcase_words = []
+                 for raw_word in re.findall(r'[a-z]+', constant):  # +1
+                     word = raw_word.strip()
+                         if (  # +2 (+1 if and +1 nesting)
+                             len(word) >= min_word_length
+                             and not (word.startswith('-') or word.endswith('-')) # +2 operators
+                         ):
+                             if is_camel_case_word(word):  # +3 (+1 if and +2 nesting)
+                                 raw_camelcase_words.append(word)
+                             else: # +1 else
+                                 processed_words.append(word.lower())
+                 return processed_words, raw_camelcase_words",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 9.0,
+                      "average": 9.0,
+                      "min": 0.0,
+                      "max": 9.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_if_let_else_if_else() {
+        check_metrics::(
+            "pub fn create_usage_no_title(p: &Parser, used: &[&str]) -> String {
+                 debugln!(\"usage::create_usage_no_title;\");
+                 if let Some(u) = p.meta.usage_str { // +1
+                     String::from(&*u)
+                 } else if used.is_empty() { // +1
+                     create_help_usage(p, true)
+                 } else { // +1
+                     create_smart_usage(p, used)
+                }
+            }",
+            "foo.rs",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn typescript_if_else_if_else() {
+        check_metrics::(
+            "function foo() {
+                 if (this._closed) return Promise.resolve(); // +1
+                 if (this._tempDirectory) { // +1
+                     this.kill();
+                 } else if (this.connection) { // +1
+                     this.kill();
+                 } else { // +1
+                     throw new Error(`Error`);
+                }
+                helper.removeEventListeners(this._listeners);
+                return this._processClosing;
+            }",
+            "foo.ts",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 4.0,
+                      "min": 0.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_no_cognitive() {
+        check_metrics::(
+            "package main
+
+            var x = 42",
+            "foo.go",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 0.0,
+                      "average": null,
+                      "min": 0.0,
+                      "max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_simple_function() {
+        check_metrics::(
+            "package main
+
+            func f() {
+                if true { // +1
+                    if false { // +2 (nesting = 1)
+                        println(\"test\")
+                    }
+                }
+            }",
+            "foo.go",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_for_loop() {
+        check_metrics::(
+            "package main
+
+            func f() {
+                for i := 0; i < 10; i++ { // +1
+                    if i > 5 { // +2 (nesting = 1)
+                        println(i)
+                    }
+                }
+            }",
+            "foo.go",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 3.0,
+                      "min": 0.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_logical_operators() {
+        check_metrics::(
+            "package main
+
+            func f(a, b, c bool) {
+                if a && b && c { // +1 (if) +1 (sequence of &&)
+                    println(\"all true\")
+                }
+            }",
+            "foo.go",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.cognitive,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 2.0,
+                      "min": 0.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/cyclomatic.rs b/src/metrics/cyclomatic.rs
new file mode 100644
index 00000000..de1b8340
--- /dev/null
+++ b/src/metrics/cyclomatic.rs
@@ -0,0 +1,360 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::*;
+
+/// The `Cyclomatic` metric.
+#[derive(Debug, Clone)]
+pub struct Stats {
+    cyclomatic_sum: f64,
+    cyclomatic: f64,
+    n: usize,
+    cyclomatic_max: f64,
+    cyclomatic_min: f64,
+}
+
+impl Default for Stats {
+    fn default() -> Self {
+        Self {
+            cyclomatic_sum: 0.,
+            cyclomatic: 1.,
+            n: 1,
+            cyclomatic_max: 0.,
+            cyclomatic_min: f64::MAX,
+        }
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("cyclomatic", 4)?;
+        st.serialize_field("sum", &self.cyclomatic_sum())?;
+        st.serialize_field("average", &self.cyclomatic_average())?;
+        st.serialize_field("min", &self.cyclomatic_min())?;
+        st.serialize_field("max", &self.cyclomatic_max())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "sum: {}, average: {}, min: {}, max: {}",
+            self.cyclomatic_sum(),
+            self.cyclomatic_average(),
+            self.cyclomatic_min(),
+            self.cyclomatic_max()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Cyclomatic` metric into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        //Calculate minimum and maximum values
+        self.cyclomatic_max = self.cyclomatic_max.max(other.cyclomatic_max);
+        self.cyclomatic_min = self.cyclomatic_min.min(other.cyclomatic_min);
+
+        self.cyclomatic_sum += other.cyclomatic_sum;
+        self.n += other.n;
+    }
+
+    /// Returns the `Cyclomatic` metric value
+    pub fn cyclomatic(&self) -> f64 {
+        self.cyclomatic
+    }
+    /// Returns the sum
+    pub fn cyclomatic_sum(&self) -> f64 {
+        self.cyclomatic_sum
+    }
+
+    /// Returns the `Cyclomatic` metric average value
+    ///
+    /// This value is computed dividing the `Cyclomatic` value for the
+    /// number of spaces.
+    pub fn cyclomatic_average(&self) -> f64 {
+        self.cyclomatic_sum() / self.n as f64
+    }
+    /// Returns the `Cyclomatic` maximum value
+    pub fn cyclomatic_max(&self) -> f64 {
+        self.cyclomatic_max
+    }
+    /// Returns the `Cyclomatic` minimum value
+    pub fn cyclomatic_min(&self) -> f64 {
+        self.cyclomatic_min
+    }
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.cyclomatic_sum += self.cyclomatic;
+    }
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        self.cyclomatic_max = self.cyclomatic_max.max(self.cyclomatic);
+        self.cyclomatic_min = self.cyclomatic_min.min(self.cyclomatic);
+        self.compute_sum();
+    }
+}
+
+pub trait Cyclomatic
+where
+    Self: Checker,
+{
+    fn compute(node: &Node, stats: &mut Stats);
+}
+
+impl Cyclomatic for PythonCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        use Python::*;
+
+        match node.kind_id().into() {
+            If | Elif | For | While | Except | With | Assert | And | Or => {
+                stats.cyclomatic += 1.;
+            }
+            Else => {
+                if node.has_ancestors(
+                    |node| matches!(node.kind_id().into(), ForStatement | WhileStatement),
+                    |node| node.kind_id() == ElseClause,
+                ) {
+                    stats.cyclomatic += 1.;
+                }
+            }
+            _ => {}
+        }
+    }
+}
+
+impl Cyclomatic for TypescriptCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        use Typescript::*;
+
+        match node.kind_id().into() {
+            If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => {
+                stats.cyclomatic += 1.;
+            }
+            _ => {}
+        }
+    }
+}
+
+impl Cyclomatic for TsxCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        use Tsx::*;
+
+        match node.kind_id().into() {
+            If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => {
+                stats.cyclomatic += 1.;
+            }
+            _ => {}
+        }
+    }
+}
+
+impl Cyclomatic for RustCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        use Rust::*;
+
+        match node.kind_id().into() {
+            If | For | While | Loop | MatchArm | MatchArm2 | TryExpression | AMPAMP | PIPEPIPE => {
+                stats.cyclomatic += 1.;
+            }
+            _ => {}
+        }
+    }
+}
+
+impl Cyclomatic for GoCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        use crate::Go::*;
+
+        match node.kind_id().into() {
+            If | For | ExpressionCase | DefaultCase | TypeCase | CommunicationCase | AMPAMP
+            | PIPEPIPE => {
+                stats.cyclomatic += 1.;
+            }
+            _ => {}
+        }
+    }
+}
+
+// No languages require empty Cyclomatic implementations
+// implement_metric_trait!(Cyclomatic);
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn python_simple_function() {
+        check_metrics::(
+            "def f(a, b): # +2 (+1 unit space)
+                if a and b:  # +2 (+1 and)
+                   return 1
+                if c and d: # +2 (+1 and)
+                   return 1",
+            "foo.py",
+            |metric| {
+                // nspace = 2 (func and unit)
+                insta::assert_json_snapshot!(
+                    metric.cyclomatic,
+                    @r###"
+                    {
+                      "sum": 6.0,
+                      "average": 3.0,
+                      "min": 1.0,
+                      "max": 5.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_1_level_nesting() {
+        check_metrics::(
+            "def f(a, b): # +2 (+1 unit space)
+                if a:  # +1
+                    for i in range(b):  # +1
+                        return 1",
+            "foo.py",
+            |metric| {
+                // nspace = 2 (func and unit)
+                insta::assert_json_snapshot!(
+                    metric.cyclomatic,
+                    @r###"
+                    {
+                      "sum": 4.0,
+                      "average": 2.0,
+                      "min": 1.0,
+                      "max": 3.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_1_level_nesting() {
+        check_metrics::(
+            "fn f() { // +2 (+1 unit space)
+                 if true { // +1
+                     match true {
+                         true => println!(\"test\"), // +1
+                         false => println!(\"test\"), // +1
+                     }
+                 }
+             }",
+            "foo.rs",
+            |metric| {
+                // nspace = 2 (func and unit)
+                insta::assert_json_snapshot!(
+                    metric.cyclomatic,
+                    @r###"
+                    {
+                      "sum": 5.0,
+                      "average": 2.5,
+                      "min": 1.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_simple_function() {
+        check_metrics::(
+            "package main
+
+            func calculate(a, b int) int { // +2 (+1 unit space)
+                if a > b { // +1
+                    return a
+                }
+                return b
+            }",
+            "foo.go",
+            |metric| {
+                // nspace = 2 (func and unit)
+                insta::assert_json_snapshot!(
+                    metric.cyclomatic,
+                    @r###"
+                    {
+                      "sum": 3.0,
+                      "average": 1.5,
+                      "min": 1.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_switch_statement() {
+        check_metrics::(
+            "package main
+
+            func grade(score int) string { // +2 (+1 unit space)
+                switch { // switch itself doesn't add, cases do
+                case score >= 90: // +1
+                    return \"A\"
+                case score >= 80: // +1
+                    return \"B\"
+                case score >= 70: // +1
+                    return \"C\"
+                default: // +1
+                    return \"F\"
+                }
+            }",
+            "foo.go",
+            |metric| {
+                // nspace = 2 (func and unit)
+                insta::assert_json_snapshot!(
+                    metric.cyclomatic,
+                    @r###"
+                    {
+                      "sum": 6.0,
+                      "average": 3.0,
+                      "min": 1.0,
+                      "max": 5.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_logical_operators() {
+        check_metrics::(
+            "package main
+
+            func check(a, b, c bool) bool { // +2 (+1 unit space)
+                if a && b || c { // +3 (+1 if, +1 &&, +1 ||)
+                    return true
+                }
+                return false
+            }",
+            "foo.go",
+            |metric| {
+                // nspace = 2 (func and unit)
+                insta::assert_json_snapshot!(
+                    metric.cyclomatic,
+                    @r###"
+                    {
+                      "sum": 5.0,
+                      "average": 2.5,
+                      "min": 1.0,
+                      "max": 4.0
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/exit.rs b/src/metrics/exit.rs
new file mode 100644
index 00000000..001de182
--- /dev/null
+++ b/src/metrics/exit.rs
@@ -0,0 +1,369 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::*;
+
+/// The `NExit` metric.
+///
+/// This metric counts the number of possible exit points
+/// from a function/method.
+#[derive(Debug, Clone)]
+pub struct Stats {
+    exit: usize,
+    exit_sum: usize,
+    total_space_functions: usize,
+    exit_min: usize,
+    exit_max: usize,
+}
+
+impl Default for Stats {
+    fn default() -> Self {
+        Self {
+            exit: 0,
+            exit_sum: 0,
+            total_space_functions: 1,
+            exit_min: usize::MAX,
+            exit_max: 0,
+        }
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("nexits", 4)?;
+        st.serialize_field("sum", &self.exit_sum())?;
+        st.serialize_field("average", &self.exit_average())?;
+        st.serialize_field("min", &self.exit_min())?;
+        st.serialize_field("max", &self.exit_max())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "sum: {}, average: {} min: {}, max: {}",
+            self.exit_sum(),
+            self.exit_average(),
+            self.exit_min(),
+            self.exit_max()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `NExit` metric into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        self.exit_max = self.exit_max.max(other.exit_max);
+        self.exit_min = self.exit_min.min(other.exit_min);
+        self.exit_sum += other.exit_sum;
+    }
+
+    /// Returns the `NExit` metric value
+    pub fn exit(&self) -> f64 {
+        self.exit as f64
+    }
+    /// Returns the `NExit` metric sum value
+    pub fn exit_sum(&self) -> f64 {
+        self.exit_sum as f64
+    }
+    /// Returns the `NExit` metric  minimum value
+    pub fn exit_min(&self) -> f64 {
+        self.exit_min as f64
+    }
+    /// Returns the `NExit` metric maximum value
+    pub fn exit_max(&self) -> f64 {
+        self.exit_max as f64
+    }
+
+    /// Returns the `NExit` metric average value
+    ///
+    /// This value is computed dividing the `NExit` value
+    /// for the total number of functions/closures in a space.
+    ///
+    /// If there are no functions in a code, its value is `NAN`.
+    pub fn exit_average(&self) -> f64 {
+        self.exit_sum() / self.total_space_functions as f64
+    }
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.exit_sum += self.exit;
+    }
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        self.exit_max = self.exit_max.max(self.exit);
+        self.exit_min = self.exit_min.min(self.exit);
+        self.compute_sum();
+    }
+    pub(crate) fn finalize(&mut self, total_space_functions: usize) {
+        self.total_space_functions = total_space_functions;
+    }
+}
+
+pub trait Exit
+where
+    Self: Checker,
+{
+    fn compute(node: &Node, stats: &mut Stats);
+}
+
+impl Exit for PythonCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        if matches!(node.kind_id().into(), Python::ReturnStatement) {
+            stats.exit += 1;
+        }
+    }
+}
+
+impl Exit for TypescriptCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        if matches!(node.kind_id().into(), Typescript::ReturnStatement) {
+            stats.exit += 1;
+        }
+    }
+}
+
+impl Exit for TsxCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        if matches!(node.kind_id().into(), Tsx::ReturnStatement) {
+            stats.exit += 1;
+        }
+    }
+}
+
+impl Exit for RustCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        if matches!(
+            node.kind_id().into(),
+            Rust::ReturnExpression | Rust::TryExpression
+        ) || Self::is_func(node) && node.child_by_field_name("return_type").is_some()
+        {
+            stats.exit += 1;
+        }
+    }
+}
+
+impl Exit for GoCode {
+    fn compute(node: &Node, stats: &mut Stats) {
+        if matches!(node.kind_id().into(), Go::ReturnStatement) {
+            stats.exit += 1;
+        }
+    }
+}
+
+// No languages require empty Exit implementations
+// implement_metric_trait!(Exit);
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn python_no_exit() {
+        check_metrics::("a = 42", "foo.py", |metric| {
+            // 0 functions
+            insta::assert_json_snapshot!(
+                metric.nexits,
+                @r###"
+                    {
+                      "sum": 0.0,
+                      "average": null,
+                      "min": 0.0,
+                      "max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_no_exit() {
+        check_metrics::("let a = 42;", "foo.rs", |metric| {
+            // 0 functions
+            insta::assert_json_snapshot!(
+                metric.nexits,
+                @r###"
+                    {
+                      "sum": 0.0,
+                      "average": null,
+                      "min": 0.0,
+                      "max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_question_mark() {
+        check_metrics::("let _ = a? + b? + c?;", "foo.rs", |metric| {
+            // 0 functions
+            insta::assert_json_snapshot!(
+                metric.nexits,
+                @r###"
+                    {
+                      "sum": 3.0,
+                      "average": null,
+                      "min": 3.0,
+                      "max": 3.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn python_simple_function() {
+        check_metrics::(
+            "def f(a, b):
+                 if a:
+                     return a",
+            "foo.py",
+            |metric| {
+                println!("{:?}", metric.nexits);
+                // 1 function
+                insta::assert_json_snapshot!(
+                    metric.nexits,
+                    @r###"
+                    {
+                      "sum": 1.0,
+                      "average": 1.0,
+                      "min": 0.0,
+                      "max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_more_functions() {
+        check_metrics::(
+            "def f(a, b):
+                 if a:
+                     return a
+            def f(a, b):
+                 if b:
+                     return b",
+            "foo.py",
+            |metric| {
+                // 2 functions
+                insta::assert_json_snapshot!(
+                    metric.nexits,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 1.0,
+                      "min": 0.0,
+                      "max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_nested_functions() {
+        check_metrics::(
+            "def f(a, b):
+                 def foo(a):
+                     if a:
+                         return 1
+                 bar = lambda a: lambda b: b or True or True
+                 return bar(foo(a))(a)",
+            "foo.py",
+            |metric| {
+                // 2 functions + 2 lambdas = 4
+                insta::assert_json_snapshot!(
+                    metric.nexits,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 0.5,
+                      "min": 0.0,
+                      "max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_no_exit() {
+        check_metrics::("var a = 42", "foo.go", |metric| {
+            // 0 functions
+            insta::assert_json_snapshot!(
+                metric.nexits,
+                @r###"
+                    {
+                      "sum": 0.0,
+                      "average": null,
+                      "min": 0.0,
+                      "max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn go_simple_function() {
+        check_metrics::(
+            "package main
+
+            func max(a, b int) int {
+                if a > b {
+                    return a
+                }
+                return b
+            }",
+            "foo.go",
+            |metric| {
+                // 2 exits / 1 function
+                insta::assert_json_snapshot!(
+                    metric.nexits,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 2.0,
+                      "min": 0.0,
+                      "max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_multiple_functions() {
+        check_metrics::(
+            "package main
+
+            func f1() int {
+                return 1
+            }
+
+            func f2() int {
+                return 2
+            }",
+            "foo.go",
+            |metric| {
+                // 2 exits / 2 functions
+                insta::assert_json_snapshot!(
+                    metric.nexits,
+                    @r###"
+                    {
+                      "sum": 2.0,
+                      "average": 1.0,
+                      "min": 0.0,
+                      "max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/halstead.rs b/src/metrics/halstead.rs
new file mode 100644
index 00000000..6e1ac354
--- /dev/null
+++ b/src/metrics/halstead.rs
@@ -0,0 +1,560 @@
+use std::collections::HashMap;
+
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::getter::Getter;
+
+use crate::*;
+
+/// The `Halstead` metric suite.
+#[derive(Default, Clone, Debug)]
+pub struct Stats {
+    u_operators: u64,
+    operators: u64,
+    u_operands: u64,
+    operands: u64,
+}
+
+/// Specifies the type of nodes accepted by the `Halstead` metric.
+pub enum HalsteadType {
+    /// The node is an `Halstead` operator
+    Operator,
+    /// The node is an `Halstead` operand
+    Operand,
+    /// The node is unknown to the `Halstead` metric
+    Unknown,
+}
+
+#[derive(Debug, Default, Clone)]
+pub struct HalsteadMaps<'a> {
+    pub(crate) operators: HashMap,
+    pub(crate) operands: HashMap<&'a [u8], u64>,
+}
+
+impl<'a> HalsteadMaps<'a> {
+    pub(crate) fn new() -> Self {
+        HalsteadMaps {
+            operators: HashMap::default(),
+            operands: HashMap::default(),
+        }
+    }
+
+    pub(crate) fn merge(&mut self, other: &HalsteadMaps<'a>) {
+        for (k, v) in other.operators.iter() {
+            *self.operators.entry(*k).or_insert(0) += v;
+        }
+        for (k, v) in other.operands.iter() {
+            *self.operands.entry(*k).or_insert(0) += v;
+        }
+    }
+
+    pub(crate) fn finalize(&self, stats: &mut Stats) {
+        stats.u_operators = self.operators.len() as u64;
+        stats.operators = self.operators.values().sum::();
+        stats.u_operands = self.operands.len() as u64;
+        stats.operands = self.operands.values().sum::();
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("halstead", 14)?;
+        st.serialize_field("n1", &self.u_operators())?;
+        st.serialize_field("N1", &self.operators())?;
+        st.serialize_field("n2", &self.u_operands())?;
+        st.serialize_field("N2", &self.operands())?;
+        st.serialize_field("length", &self.length())?;
+        st.serialize_field("estimated_program_length", &self.estimated_program_length())?;
+        st.serialize_field("purity_ratio", &self.purity_ratio())?;
+        st.serialize_field("vocabulary", &self.vocabulary())?;
+        st.serialize_field("volume", &self.volume())?;
+        st.serialize_field("difficulty", &self.difficulty())?;
+        st.serialize_field("level", &self.level())?;
+        st.serialize_field("effort", &self.effort())?;
+        st.serialize_field("time", &self.time())?;
+        st.serialize_field("bugs", &self.bugs())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "n1: {}, \
+             N1: {}, \
+             n2: {}, \
+             N2: {}, \
+             length: {}, \
+             estimated program length: {}, \
+             purity ratio: {}, \
+             size: {}, \
+             volume: {}, \
+             difficulty: {}, \
+             level: {}, \
+             effort: {}, \
+             time: {}, \
+             bugs: {}",
+            self.u_operators(),
+            self.operators(),
+            self.u_operands(),
+            self.operands(),
+            self.length(),
+            self.estimated_program_length(),
+            self.purity_ratio(),
+            self.vocabulary(),
+            self.volume(),
+            self.difficulty(),
+            self.level(),
+            self.effort(),
+            self.time(),
+            self.bugs(),
+        )
+    }
+}
+
+impl Stats {
+    pub(crate) fn merge(&mut self, _other: &Stats) {}
+
+    /// Returns `η1`, the number of distinct operators
+    #[inline(always)]
+    pub fn u_operators(&self) -> f64 {
+        self.u_operators as f64
+    }
+
+    /// Returns `N1`, the number of total operators
+    #[inline(always)]
+    pub fn operators(&self) -> f64 {
+        self.operators as f64
+    }
+
+    /// Returns `η2`, the number of distinct operands
+    #[inline(always)]
+    pub fn u_operands(&self) -> f64 {
+        self.u_operands as f64
+    }
+
+    /// Returns `N2`, the number of total operands
+    #[inline(always)]
+    pub fn operands(&self) -> f64 {
+        self.operands as f64
+    }
+
+    /// Returns the program length
+    #[inline(always)]
+    pub fn length(&self) -> f64 {
+        self.operands() + self.operators()
+    }
+
+    /// Returns the calculated estimated program length
+    #[inline(always)]
+    pub fn estimated_program_length(&self) -> f64 {
+        self.u_operators() * self.u_operators().log2()
+            + self.u_operands() * self.u_operands().log2()
+    }
+
+    /// Returns the purity ratio
+    #[inline(always)]
+    pub fn purity_ratio(&self) -> f64 {
+        self.estimated_program_length() / self.length()
+    }
+
+    /// Returns the program vocabulary
+    #[inline(always)]
+    pub fn vocabulary(&self) -> f64 {
+        self.u_operands() + self.u_operators()
+    }
+
+    /// Returns the program volume.
+    ///
+    /// Unit of measurement: bits
+    #[inline(always)]
+    pub fn volume(&self) -> f64 {
+        // Assumes a uniform binary encoding for the vocabulary is used.
+        self.length() * self.vocabulary().log2()
+    }
+
+    /// Returns the estimated difficulty required to program
+    #[inline(always)]
+    pub fn difficulty(&self) -> f64 {
+        self.u_operators() / 2. * self.operands() / self.u_operands()
+    }
+
+    /// Returns the estimated level of difficulty required to program
+    #[inline(always)]
+    pub fn level(&self) -> f64 {
+        1. / self.difficulty()
+    }
+
+    /// Returns the estimated effort required to program
+    #[inline(always)]
+    pub fn effort(&self) -> f64 {
+        self.difficulty() * self.volume()
+    }
+
+    /// Returns the estimated time required to program.
+    ///
+    /// Unit of measurement: seconds
+    #[inline(always)]
+    pub fn time(&self) -> f64 {
+        // The floating point `18.` aims to describe the processing rate of the
+        // human brain. It is called Stoud number, S, and its
+        // unit of measurement is moments/seconds.
+        // A moment is the time required by the human brain to carry out the
+        // most elementary decision.
+        // 5 <= S <= 20. Halstead uses 18.
+        // The value of S has been empirically developed from psychological
+        // reasoning, and its recommended value for
+        // programming applications is 18.
+        //
+        // Source: https://www.geeksforgeeks.org/software-engineering-halsteads-software-metrics/
+        self.effort() / 18.
+    }
+
+    /// Returns the estimated number of delivered bugs.
+    ///
+    /// This metric represents the average amount of work a programmer can do
+    /// without introducing an error.
+    #[inline(always)]
+    pub fn bugs(&self) -> f64 {
+        // The floating point `3000.` represents the number of elementary
+        // mental discriminations.
+        // A mental discrimination, in psychology, is the ability to perceive
+        // and respond to differences among stimuli.
+        //
+        // The value above is obtained starting from a constant that
+        // is different for every language and assumes that natural language is
+        // the language of the brain.
+        // For programming languages, the English language constant
+        // has been considered.
+        //
+        // After every 3000 mental discriminations a result is produced.
+        // This result, whether correct or incorrect, is more than likely
+        // either used as an input for the next operation or is output to the
+        // environment.
+        // If incorrect the error should become apparent.
+        // Thus, an opportunity for error occurs every 3000
+        // mental discriminations.
+        //
+        // Source: https://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1145&context=cstech
+        self.effort().powf(2. / 3.) / 3000.
+    }
+}
+
+pub trait Halstead
+where
+    Self: Checker,
+{
+    fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>);
+}
+
+#[inline(always)]
+fn get_id<'a>(node: &Node<'a>, code: &'a [u8]) -> &'a [u8] {
+    &code[node.start_byte()..node.end_byte()]
+}
+
+#[inline(always)]
+fn compute_halstead<'a, T: Getter>(
+    node: &Node<'a>,
+    code: &'a [u8],
+    halstead_maps: &mut HalsteadMaps<'a>,
+) {
+    match T::get_op_type(node) {
+        HalsteadType::Operator => {
+            *halstead_maps.operators.entry(node.kind_id()).or_insert(0) += 1;
+        }
+        HalsteadType::Operand => {
+            *halstead_maps
+                .operands
+                .entry(get_id(node, code))
+                .or_insert(0) += 1;
+        }
+        _ => {}
+    }
+}
+
+impl Halstead for PythonCode {
+    fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>) {
+        compute_halstead::(node, code, halstead_maps);
+    }
+}
+
+impl Halstead for TypescriptCode {
+    fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>) {
+        compute_halstead::(node, code, halstead_maps);
+    }
+}
+
+impl Halstead for TsxCode {
+    fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>) {
+        compute_halstead::(node, code, halstead_maps);
+    }
+}
+
+impl Halstead for RustCode {
+    fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>) {
+        compute_halstead::(node, code, halstead_maps);
+    }
+}
+
+impl Halstead for GoCode {
+    fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>) {
+        compute_halstead::(node, code, halstead_maps);
+    }
+}
+
+// No languages require empty Halstead implementations
+// implement_metric_trait!(Halstead);
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn python_operators_and_operands() {
+        check_metrics::(
+            "def foo():
+                 def bar():
+                     def toto():
+                        a = 1 + 1
+                     b = 2 + a
+                 c = 3 + 3",
+            "foo.py",
+            |metric| {
+                // unique operators: def, =, +
+                // operators: def, def, def, =, =, =, +, +, +
+                // unique operands: foo, bar, toto, a, b, c, 1, 2, 3
+                // operands: foo, bar, toto, a, b, c, 1, 1, 2, a, 3, 3
+                insta::assert_json_snapshot!(
+                    metric.halstead,
+                    @r###"
+                    {
+                      "n1": 3.0,
+                      "N1": 9.0,
+                      "n2": 9.0,
+                      "N2": 12.0,
+                      "length": 21.0,
+                      "estimated_program_length": 33.284212515144276,
+                      "purity_ratio": 1.584962500721156,
+                      "vocabulary": 12.0,
+                      "volume": 75.28421251514428,
+                      "difficulty": 2.0,
+                      "level": 0.5,
+                      "effort": 150.56842503028855,
+                      "time": 8.364912501682698,
+                      "bugs": 0.0094341190071077
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_operators_and_operands() {
+        check_metrics::(
+            "fn main() {
+              let a = 5; let b = 5; let c = 5;
+              let avg = (a + b + c) / 3;
+              println!(\"{}\", avg);
+            }",
+            "foo.rs",
+            |metric| {
+                // unique operators: fn, (), {}, let, =, +, /, ;, !, ,
+                // unique operands: main, a, b, c, avg, 5, 3, println, "{}"
+                insta::assert_json_snapshot!(
+                    metric.halstead,
+                    @r###"
+                    {
+                      "n1": 10.0,
+                      "N1": 23.0,
+                      "n2": 9.0,
+                      "N2": 15.0,
+                      "length": 38.0,
+                      "estimated_program_length": 61.74860596185444,
+                      "purity_ratio": 1.624963314785643,
+                      "vocabulary": 19.0,
+                      "volume": 161.42124551085624,
+                      "difficulty": 8.333333333333334,
+                      "level": 0.12,
+                      "effort": 1345.177045923802,
+                      "time": 74.7320581068779,
+                      "bugs": 0.040619232256751396
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn typescript_operators_and_operands() {
+        check_metrics::(
+            "function main() {
+              var a, b, c, avg;
+              a = 5; b = 5; c = 5;
+              avg = (a + b + c) / 3;
+              console.log(\"{}\", avg);
+            }",
+            "foo.ts",
+            |metric| {
+                // unique operators: function, (), {}, var, =, +, /, ,, ., ;
+                // unique operands: main, a, b, c, avg, 3, 5, console.log, console, log, "{}"
+                insta::assert_json_snapshot!(
+                    metric.halstead,
+                    @r###"
+                    {
+                      "n1": 10.0,
+                      "N1": 24.0,
+                      "n2": 11.0,
+                      "N2": 21.0,
+                      "length": 45.0,
+                      "estimated_program_length": 71.27302875388389,
+                      "purity_ratio": 1.583845083419642,
+                      "vocabulary": 21.0,
+                      "volume": 197.65428402504423,
+                      "difficulty": 9.545454545454545,
+                      "level": 0.10476190476190476,
+                      "effort": 1886.699983875422,
+                      "time": 104.81666577085679,
+                      "bugs": 0.05089564733125986
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn tsx_operators_and_operands() {
+        check_metrics::(
+            "function main() {
+              var a, b, c, avg;
+              a = 5; b = 5; c = 5;
+              avg = (a + b + c) / 3;
+              console.log(\"{}\", avg);
+            }",
+            "foo.ts",
+            |metric| {
+                // unique operators: function, (), {}, var, =, +, /, ,, ., ;
+                // unique operands: main, a, b, c, avg, 3, 5, console.log, console, log, "{}"
+                insta::assert_json_snapshot!(
+                    metric.halstead,
+                    @r###"
+                    {
+                      "n1": 10.0,
+                      "N1": 24.0,
+                      "n2": 11.0,
+                      "N2": 21.0,
+                      "length": 45.0,
+                      "estimated_program_length": 71.27302875388389,
+                      "purity_ratio": 1.583845083419642,
+                      "vocabulary": 21.0,
+                      "volume": 197.65428402504423,
+                      "difficulty": 9.545454545454545,
+                      "level": 0.10476190476190476,
+                      "effort": 1886.699983875422,
+                      "time": 104.81666577085679,
+                      "bugs": 0.05089564733125986
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_wrong_operators() {
+        check_metrics::("()[]{}", "foo.py", |metric| {
+            insta::assert_json_snapshot!(
+                metric.halstead,
+                @r###"
+                    {
+                      "n1": 0.0,
+                      "N1": 0.0,
+                      "n2": 0.0,
+                      "N2": 0.0,
+                      "length": 0.0,
+                      "estimated_program_length": null,
+                      "purity_ratio": null,
+                      "vocabulary": 0.0,
+                      "volume": null,
+                      "difficulty": null,
+                      "level": null,
+                      "effort": null,
+                      "time": null,
+                      "bugs": null
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn python_check_metrics() {
+        check_metrics::(
+            "def f():
+                 pass",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.halstead,
+                    @r###"
+                    {
+                      "n1": 2.0,
+                      "N1": 2.0,
+                      "n2": 1.0,
+                      "N2": 1.0,
+                      "length": 3.0,
+                      "estimated_program_length": 2.0,
+                      "purity_ratio": 0.6666666666666666,
+                      "vocabulary": 3.0,
+                      "volume": 4.754887502163468,
+                      "difficulty": 1.0,
+                      "level": 1.0,
+                      "effort": 4.754887502163468,
+                      "time": 0.26416041678685936,
+                      "bugs": 0.0009425525573729414
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_operators_and_operands() {
+        check_metrics::(
+            "package main
+
+            func add(a, b int) int {
+                return a + b
+            }",
+            "foo.go",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.halstead,
+                    @r###"
+                    {
+                      "n1": 7.0,
+                      "N1": 7.0,
+                      "n2": 3.0,
+                      "N2": 5.0,
+                      "length": 12.0,
+                      "estimated_program_length": 24.406371956566694,
+                      "purity_ratio": 2.033864329713891,
+                      "vocabulary": 10.0,
+                      "volume": 39.86313713864835,
+                      "difficulty": 5.833333333333333,
+                      "level": 0.17142857142857143,
+                      "effort": 232.53496664211536,
+                      "time": 12.918609257895298,
+                      "bugs": 0.012604847345273484
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/loc.rs b/src/metrics/loc.rs
new file mode 100644
index 00000000..1bd3d9a9
--- /dev/null
+++ b/src/metrics/loc.rs
@@ -0,0 +1,1939 @@
+use std::collections::HashSet;
+
+use crate::checker::Checker;
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::*;
+
+/// The `SLoc` metric suite.
+#[derive(Debug, Clone)]
+pub struct Sloc {
+    start: usize,
+    end: usize,
+    unit: bool,
+    sloc_min: usize,
+    sloc_max: usize,
+}
+
+impl Default for Sloc {
+    fn default() -> Self {
+        Self {
+            start: 0,
+            end: 0,
+            unit: false,
+            sloc_min: usize::MAX,
+            sloc_max: 0,
+        }
+    }
+}
+
+impl Sloc {
+    #[inline(always)]
+    pub fn sloc(&self) -> f64 {
+        // This metric counts the number of lines in a file
+        // The if construct is needed to count the line of code that represents
+        // the function signature in a function space
+        let sloc = if self.unit {
+            self.end - self.start
+        } else {
+            (self.end - self.start) + 1
+        };
+        sloc as f64
+    }
+
+    /// The `Sloc` metric minimum value.
+    #[inline(always)]
+    pub fn sloc_min(&self) -> f64 {
+        self.sloc_min as f64
+    }
+
+    /// The `Sloc` metric maximum value.
+    #[inline(always)]
+    pub fn sloc_max(&self) -> f64 {
+        self.sloc_max as f64
+    }
+
+    #[inline(always)]
+    pub fn merge(&mut self, other: &Sloc) {
+        self.sloc_min = self.sloc_min.min(other.sloc() as usize);
+        self.sloc_max = self.sloc_max.max(other.sloc() as usize);
+    }
+
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        if self.sloc_min == usize::MAX {
+            self.sloc_min = self.sloc_min.min(self.sloc() as usize);
+            self.sloc_max = self.sloc_max.max(self.sloc() as usize);
+        }
+    }
+}
+
+/// The `PLoc` metric suite.
+#[derive(Debug, Clone)]
+pub struct Ploc {
+    lines: HashSet,
+    ploc_min: usize,
+    ploc_max: usize,
+}
+
+impl Default for Ploc {
+    fn default() -> Self {
+        Self {
+            lines: HashSet::default(),
+            ploc_min: usize::MAX,
+            ploc_max: 0,
+        }
+    }
+}
+
+impl Ploc {
+    #[inline(always)]
+    pub fn ploc(&self) -> f64 {
+        // This metric counts the number of instruction lines in a code
+        // https://en.wikipedia.org/wiki/Source_lines_of_code
+        self.lines.len() as f64
+    }
+
+    /// The `Ploc` metric minimum value.
+    #[inline(always)]
+    pub fn ploc_min(&self) -> f64 {
+        self.ploc_min as f64
+    }
+
+    /// The `Ploc` metric maximum value.
+    #[inline(always)]
+    pub fn ploc_max(&self) -> f64 {
+        self.ploc_max as f64
+    }
+
+    #[inline(always)]
+    pub fn merge(&mut self, other: &Ploc) {
+        // Merge ploc lines
+        for l in other.lines.iter() {
+            self.lines.insert(*l);
+        }
+
+        self.ploc_min = self.ploc_min.min(other.ploc() as usize);
+        self.ploc_max = self.ploc_max.max(other.ploc() as usize);
+    }
+
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        if self.ploc_min == usize::MAX {
+            self.ploc_min = self.ploc_min.min(self.ploc() as usize);
+            self.ploc_max = self.ploc_max.max(self.ploc() as usize);
+        }
+    }
+}
+
+/// The `CLoc` metric suite.
+#[derive(Debug, Clone)]
+pub struct Cloc {
+    only_comment_lines: usize,
+    code_comment_lines: usize,
+    comment_line_end: Option,
+    cloc_min: usize,
+    cloc_max: usize,
+}
+
+impl Default for Cloc {
+    fn default() -> Self {
+        Self {
+            only_comment_lines: 0,
+            code_comment_lines: 0,
+            comment_line_end: Option::default(),
+            cloc_min: usize::MAX,
+            cloc_max: 0,
+        }
+    }
+}
+
+impl Cloc {
+    #[inline(always)]
+    pub fn cloc(&self) -> f64 {
+        // Comments are counted regardless of their placement
+        // https://en.wikipedia.org/wiki/Source_lines_of_code
+        (self.only_comment_lines + self.code_comment_lines) as f64
+    }
+
+    /// The `Ploc` metric minimum value.
+    #[inline(always)]
+    pub fn cloc_min(&self) -> f64 {
+        self.cloc_min as f64
+    }
+
+    /// The `Ploc` metric maximum value.
+    #[inline(always)]
+    pub fn cloc_max(&self) -> f64 {
+        self.cloc_max as f64
+    }
+
+    #[inline(always)]
+    pub fn merge(&mut self, other: &Cloc) {
+        // Merge cloc lines
+        self.only_comment_lines += other.only_comment_lines;
+        self.code_comment_lines += other.code_comment_lines;
+
+        self.cloc_min = self.cloc_min.min(other.cloc() as usize);
+        self.cloc_max = self.cloc_max.max(other.cloc() as usize);
+    }
+
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        if self.cloc_min == usize::MAX {
+            self.cloc_min = self.cloc_min.min(self.cloc() as usize);
+            self.cloc_max = self.cloc_max.max(self.cloc() as usize);
+        }
+    }
+}
+
+/// The `LLoc` metric suite.
+#[derive(Debug, Clone)]
+pub struct Lloc {
+    logical_lines: usize,
+    lloc_min: usize,
+    lloc_max: usize,
+}
+
+impl Default for Lloc {
+    fn default() -> Self {
+        Self {
+            logical_lines: 0,
+            lloc_min: usize::MAX,
+            lloc_max: 0,
+        }
+    }
+}
+
+impl Lloc {
+    #[inline(always)]
+    pub fn lloc(&self) -> f64 {
+        // This metric counts the number of statements in a code
+        // https://en.wikipedia.org/wiki/Source_lines_of_code
+        self.logical_lines as f64
+    }
+
+    /// The `Lloc` metric minimum value.
+    #[inline(always)]
+    pub fn lloc_min(&self) -> f64 {
+        self.lloc_min as f64
+    }
+
+    /// The `Lloc` metric maximum value.
+    #[inline(always)]
+    pub fn lloc_max(&self) -> f64 {
+        self.lloc_max as f64
+    }
+
+    #[inline(always)]
+    pub fn merge(&mut self, other: &Lloc) {
+        // Merge lloc lines
+        self.logical_lines += other.logical_lines;
+        self.lloc_min = self.lloc_min.min(other.lloc() as usize);
+        self.lloc_max = self.lloc_max.max(other.lloc() as usize);
+    }
+
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        if self.lloc_min == usize::MAX {
+            self.lloc_min = self.lloc_min.min(self.lloc() as usize);
+            self.lloc_max = self.lloc_max.max(self.lloc() as usize);
+        }
+    }
+}
+
+/// The `Loc` metric suite.
+#[derive(Debug, Clone)]
+pub struct Stats {
+    sloc: Sloc,
+    ploc: Ploc,
+    cloc: Cloc,
+    lloc: Lloc,
+    space_count: usize,
+    blank_min: usize,
+    blank_max: usize,
+}
+
+impl Default for Stats {
+    fn default() -> Self {
+        Self {
+            sloc: Sloc::default(),
+            ploc: Ploc::default(),
+            cloc: Cloc::default(),
+            lloc: Lloc::default(),
+            space_count: 1,
+            blank_min: usize::MAX,
+            blank_max: 0,
+        }
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("loc", 20)?;
+        st.serialize_field("sloc", &self.sloc())?;
+        st.serialize_field("ploc", &self.ploc())?;
+        st.serialize_field("lloc", &self.lloc())?;
+        st.serialize_field("cloc", &self.cloc())?;
+        st.serialize_field("blank", &self.blank())?;
+        st.serialize_field("sloc_average", &self.sloc_average())?;
+        st.serialize_field("ploc_average", &self.ploc_average())?;
+        st.serialize_field("lloc_average", &self.lloc_average())?;
+        st.serialize_field("cloc_average", &self.cloc_average())?;
+        st.serialize_field("blank_average", &self.blank_average())?;
+        st.serialize_field("sloc_min", &self.sloc_min())?;
+        st.serialize_field("sloc_max", &self.sloc_max())?;
+        st.serialize_field("cloc_min", &self.cloc_min())?;
+        st.serialize_field("cloc_max", &self.cloc_max())?;
+        st.serialize_field("ploc_min", &self.ploc_min())?;
+        st.serialize_field("ploc_max", &self.ploc_max())?;
+        st.serialize_field("lloc_min", &self.lloc_min())?;
+        st.serialize_field("lloc_max", &self.lloc_max())?;
+        st.serialize_field("blank_min", &self.blank_min())?;
+        st.serialize_field("blank_max", &self.blank_max())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "sloc: {}, ploc: {}, lloc: {}, cloc: {}, blank: {}, sloc_average: {}, ploc_average: {}, lloc_average: {}, cloc_average: {}, blank_average: {}, sloc_min: {}, sloc_max: {}, cloc_min: {}, cloc_max: {}, ploc_min: {}, ploc_max: {}, lloc_min: {}, lloc_max: {}, blank_min: {}, blank_max: {}",
+            self.sloc(),
+            self.ploc(),
+            self.lloc(),
+            self.cloc(),
+            self.blank(),
+            self.sloc_average(),
+            self.ploc_average(),
+            self.lloc_average(),
+            self.cloc_average(),
+            self.blank_average(),
+            self.sloc_min(),
+            self.sloc_max(),
+            self.cloc_min(),
+            self.cloc_max(),
+            self.ploc_min(),
+            self.ploc_max(),
+            self.lloc_min(),
+            self.lloc_max(),
+            self.blank_min(),
+            self.blank_max(),
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Loc` metric suite into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        self.sloc.merge(&other.sloc);
+        self.ploc.merge(&other.ploc);
+        self.cloc.merge(&other.cloc);
+        self.lloc.merge(&other.lloc);
+
+        // Count spaces
+        self.space_count += other.space_count;
+
+        // min and max
+
+        self.blank_min = self.blank_min.min(other.blank() as usize);
+        self.blank_max = self.blank_max.max(other.blank() as usize);
+    }
+
+    /// The `Sloc` metric.
+    ///
+    /// Counts the number of lines in a scope
+    #[inline(always)]
+    pub fn sloc(&self) -> f64 {
+        self.sloc.sloc()
+    }
+
+    /// The `Ploc` metric.
+    ///
+    /// Counts the number of instruction lines in a scope
+    #[inline(always)]
+    pub fn ploc(&self) -> f64 {
+        self.ploc.ploc()
+    }
+
+    /// The `Lloc` metric.
+    ///
+    /// Counts the number of statements in a scope
+    #[inline(always)]
+    pub fn lloc(&self) -> f64 {
+        self.lloc.lloc()
+    }
+
+    /// The `Cloc` metric.
+    ///
+    /// Counts the number of comments in a scope
+    #[inline(always)]
+    pub fn cloc(&self) -> f64 {
+        self.cloc.cloc()
+    }
+
+    /// The `Blank` metric.
+    ///
+    /// Counts the number of blank lines in a scope
+    #[inline(always)]
+    pub fn blank(&self) -> f64 {
+        self.sloc() - self.ploc() - self.cloc.only_comment_lines as f64
+    }
+
+    /// The `Sloc` metric average value.
+    ///
+    /// This value is computed dividing the `Sloc` value for the number of spaces
+    #[inline(always)]
+    pub fn sloc_average(&self) -> f64 {
+        self.sloc() / self.space_count as f64
+    }
+
+    /// The `Ploc` metric average value.
+    ///
+    /// This value is computed dividing the `Ploc` value for the number of spaces
+    #[inline(always)]
+    pub fn ploc_average(&self) -> f64 {
+        self.ploc() / self.space_count as f64
+    }
+
+    /// The `Lloc` metric average value.
+    ///
+    /// This value is computed dividing the `Lloc` value for the number of spaces
+    #[inline(always)]
+    pub fn lloc_average(&self) -> f64 {
+        self.lloc() / self.space_count as f64
+    }
+
+    /// The `Cloc` metric average value.
+    ///
+    /// This value is computed dividing the `Cloc` value for the number of spaces
+    #[inline(always)]
+    pub fn cloc_average(&self) -> f64 {
+        self.cloc() / self.space_count as f64
+    }
+
+    /// The `Blank` metric average value.
+    ///
+    /// This value is computed dividing the `Blank` value for the number of spaces
+    #[inline(always)]
+    pub fn blank_average(&self) -> f64 {
+        self.blank() / self.space_count as f64
+    }
+
+    /// The `Sloc` metric minimum value.
+    #[inline(always)]
+    pub fn sloc_min(&self) -> f64 {
+        self.sloc.sloc_min()
+    }
+
+    /// The `Sloc` metric maximum value.
+    #[inline(always)]
+    pub fn sloc_max(&self) -> f64 {
+        self.sloc.sloc_max()
+    }
+
+    /// The `Cloc` metric minimum value.
+    #[inline(always)]
+    pub fn cloc_min(&self) -> f64 {
+        self.cloc.cloc_min()
+    }
+
+    /// The `Cloc` metric maximum value.
+    #[inline(always)]
+    pub fn cloc_max(&self) -> f64 {
+        self.cloc.cloc_max()
+    }
+
+    /// The `Ploc` metric minimum value.
+    #[inline(always)]
+    pub fn ploc_min(&self) -> f64 {
+        self.ploc.ploc_min()
+    }
+
+    /// The `Ploc` metric maximum value.
+    #[inline(always)]
+    pub fn ploc_max(&self) -> f64 {
+        self.ploc.ploc_max()
+    }
+
+    /// The `Lloc` metric minimum value.
+    #[inline(always)]
+    pub fn lloc_min(&self) -> f64 {
+        self.lloc.lloc_min()
+    }
+
+    /// The `Lloc` metric maximum value.
+    #[inline(always)]
+    pub fn lloc_max(&self) -> f64 {
+        self.lloc.lloc_max()
+    }
+
+    /// The `Blank` metric minimum value.
+    #[inline(always)]
+    pub fn blank_min(&self) -> f64 {
+        self.blank_min as f64
+    }
+
+    /// The `Blank` metric maximum value.
+    #[inline(always)]
+    pub fn blank_max(&self) -> f64 {
+        self.blank_max as f64
+    }
+
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        self.sloc.compute_minmax();
+        self.ploc.compute_minmax();
+        self.cloc.compute_minmax();
+        self.lloc.compute_minmax();
+
+        if self.blank_min == usize::MAX {
+            self.blank_min = self.blank_min.min(self.blank() as usize);
+            self.blank_max = self.blank_max.max(self.blank() as usize);
+        }
+    }
+}
+
+pub trait Loc
+where
+    Self: Checker,
+{
+    fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool);
+}
+
+#[inline(always)]
+fn init(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) -> (usize, usize) {
+    let start = node.start_row();
+    let end = node.end_row();
+
+    if is_func_space {
+        stats.sloc.start = start;
+        stats.sloc.end = end;
+        stats.sloc.unit = is_unit;
+    }
+    (start, end)
+}
+
+#[inline(always)]
+// Discriminates among the comments that are *after* a code line and
+// the ones that are on an independent line.
+// This difference is necessary in order to avoid having
+// a wrong count for the blank metric.
+fn add_cloc_lines(stats: &mut Stats, start: usize, end: usize) {
+    let comment_diff = end - start;
+    let is_comment_after_code_line = stats.ploc.lines.contains(&start);
+    if is_comment_after_code_line && comment_diff == 0 {
+        // A comment is *entirely* next to a code line
+        stats.cloc.code_comment_lines += 1;
+    } else if is_comment_after_code_line && comment_diff > 0 {
+        // A block comment that starts next to a code line and ends on
+        // independent lines.
+        stats.cloc.code_comment_lines += 1;
+        stats.cloc.only_comment_lines += comment_diff;
+    } else {
+        // A comment on an independent line AND
+        // a block comment on independent lines OR
+        // a comment *before* a code line
+        stats.cloc.only_comment_lines += (end - start) + 1;
+        // Save line end of a comment to check whether
+        // a comment *before* a code line is considered
+        stats.cloc.comment_line_end = Some(end);
+    }
+}
+
+#[inline(always)]
+// Detects the comments that are on a code line but *before* the code part.
+// This difference is necessary in order to avoid having
+// a wrong count for the blank metric.
+fn check_comment_ends_on_code_line(stats: &mut Stats, start_code_line: usize) {
+    if let Some(end) = stats.cloc.comment_line_end
+        && end == start_code_line
+        && !stats.ploc.lines.contains(&start_code_line)
+    {
+        // Comment entirely *before* a code line
+        stats.cloc.only_comment_lines -= 1;
+        stats.cloc.code_comment_lines += 1;
+    }
+}
+
+impl Loc for PythonCode {
+    fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
+        use Python::*;
+
+        let (start, end) = init(node, stats, is_func_space, is_unit);
+
+        match node.kind_id().into() {
+            StringStart | StringEnd | StringContent | Block | Module => {}
+            Comment => {
+                add_cloc_lines(stats, start, end);
+            }
+            String => {
+                let parent = node.parent().unwrap();
+                if let ExpressionStatement = parent.kind_id().into() {
+                    add_cloc_lines(stats, start, end);
+                } else if parent.start_row() != start {
+                    check_comment_ends_on_code_line(stats, start);
+                    stats.ploc.lines.insert(start);
+                }
+            }
+            Statement
+            | SimpleStatements
+            | ImportStatement
+            | FutureImportStatement
+            | ImportFromStatement
+            | PrintStatement
+            | AssertStatement
+            | ReturnStatement
+            | DeleteStatement
+            | RaiseStatement
+            | PassStatement
+            | BreakStatement
+            | ContinueStatement
+            | IfStatement
+            | ForStatement
+            | WhileStatement
+            | TryStatement
+            | WithStatement
+            | GlobalStatement
+            | NonlocalStatement
+            | ExecStatement
+            | ExpressionStatement => {
+                stats.lloc.logical_lines += 1;
+            }
+            _ => {
+                check_comment_ends_on_code_line(stats, start);
+                stats.ploc.lines.insert(start);
+            }
+        }
+    }
+}
+
+impl Loc for TypescriptCode {
+    fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
+        use Typescript::*;
+
+        let (start, end) = init(node, stats, is_func_space, is_unit);
+
+        match node.kind_id().into() {
+            String | DQUOTE | Program => {}
+            Comment => {
+                add_cloc_lines(stats, start, end);
+            }
+            ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
+            | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
+            | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
+            | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
+            | StatementIdentifier => {
+                stats.lloc.logical_lines += 1;
+            }
+            _ => {
+                check_comment_ends_on_code_line(stats, start);
+                stats.ploc.lines.insert(start);
+            }
+        }
+    }
+}
+
+impl Loc for TsxCode {
+    fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
+        use Tsx::*;
+
+        let (start, end) = init(node, stats, is_func_space, is_unit);
+
+        match node.kind_id().into() {
+            String | DQUOTE | Program => {}
+            Comment => {
+                add_cloc_lines(stats, start, end);
+            }
+            ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
+            | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
+            | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
+            | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
+            | StatementIdentifier => {
+                stats.lloc.logical_lines += 1;
+            }
+            _ => {
+                check_comment_ends_on_code_line(stats, start);
+                stats.ploc.lines.insert(start);
+            }
+        }
+    }
+}
+
+impl Loc for RustCode {
+    fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
+        use Rust::*;
+
+        let (start, end) = init(node, stats, is_func_space, is_unit);
+
+        match node.kind_id().into() {
+            StringLiteral
+            | RawStringLiteral
+            | Block
+            | SourceFile
+            | SLASH
+            | SLASHSLASH
+            | SLASHSTAR
+            | STARSLASH
+            | OuterDocCommentMarker
+            | OuterDocCommentMarker2
+            | DocComment
+            | InnerDocCommentMarker
+            | BANG => {}
+            BlockComment => {
+                add_cloc_lines(stats, start, end);
+            }
+            LineComment => {
+                // Exclude the last line for `LineComment` containing a `DocComment`,
+                // since the `DocComment` includes the newline,
+                // as explained here: https://github.com/tree-sitter/tree-sitter-rust/blob/2eaf126458a4d6a69401089b6ba78c5e5d6c1ced/src/scanner.c#L194-L195
+                let end = if node.is_child(DocComment as u16) {
+                    end - 1
+                } else {
+                    end
+                };
+                add_cloc_lines(stats, start, end);
+            }
+            Statement
+            | EmptyStatement
+            | ExpressionStatement
+            | LetDeclaration
+            | AssignmentExpression
+            | CompoundAssignmentExpr => {
+                stats.lloc.logical_lines += 1;
+            }
+            _ => {
+                check_comment_ends_on_code_line(stats, start);
+                stats.ploc.lines.insert(start);
+            }
+        }
+    }
+}
+
+impl Loc for GoCode {
+    fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
+        use crate::Go::*;
+
+        let (start, end) = init(node, stats, is_func_space, is_unit);
+        match node.kind_id().into() {
+            SourceFile => {}
+            Comment => {
+                add_cloc_lines(stats, start, end);
+            }
+            // LLOC: count statements
+            ExpressionStatement
+            | SendStatement
+            | IncStatement
+            | DecStatement
+            | AssignmentStatement
+            | ShortVarDeclaration
+            | VarDeclaration
+            | ConstDeclaration
+            | TypeDeclaration
+            | GoStatement
+            | DeferStatement
+            | ReturnStatement
+            | BreakStatement
+            | ContinueStatement
+            | GotoStatement
+            | FallthroughStatement
+            | IfStatement
+            | ExpressionSwitchStatement
+            | TypeSwitchStatement
+            | SelectStatement
+            | ForStatement => {
+                stats.lloc.logical_lines += 1;
+            }
+            _ => {
+                check_comment_ends_on_code_line(stats, start);
+                stats.ploc.lines.insert(start);
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn python_sloc() {
+        check_metrics::(
+            "
+
+            a = 42
+
+            ",
+            "foo.py",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 1.0,
+                      "ploc": 1.0,
+                      "lloc": 1.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 1.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 1.0,
+                      "sloc_max": 1.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_blank() {
+        check_metrics::(
+            "
+            a = 42
+
+            b = 43
+
+            ",
+            "foo.py",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 3.0,
+                      "ploc": 2.0,
+                      "lloc": 2.0,
+                      "cloc": 0.0,
+                      "blank": 1.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 2.0,
+                      "lloc_average": 2.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 1.0,
+                      "sloc_min": 3.0,
+                      "sloc_max": 3.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 2.0,
+                      "ploc_max": 2.0,
+                      "lloc_min": 2.0,
+                      "lloc_max": 2.0,
+                      "blank_min": 1.0,
+                      "blank_max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_blank() {
+        check_metrics::(
+            "
+
+            let a = 42;
+
+            let b = 43;
+
+            ",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 3.0,
+                      "ploc": 2.0,
+                      "lloc": 2.0,
+                      "cloc": 0.0,
+                      "blank": 1.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 2.0,
+                      "lloc_average": 2.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 1.0,
+                      "sloc_min": 3.0,
+                      "sloc_max": 3.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 2.0,
+                      "ploc_max": 2.0,
+                      "lloc_min": 2.0,
+                      "lloc_max": 2.0,
+                      "blank_min": 1.0,
+                      "blank_max": 1.0
+                    }"###
+                );
+            },
+        );
+
+        check_metrics::("fn func() { /* comment */ }", "foo.rs", |metric| {
+            // Spaces: 2
+            insta::assert_json_snapshot!(
+                metric.loc,
+                @r###"
+                    {
+                      "sloc": 1.0,
+                      "ploc": 1.0,
+                      "lloc": 0.0,
+                      "cloc": 1.0,
+                      "blank": 0.0,
+                      "sloc_average": 0.5,
+                      "ploc_average": 0.5,
+                      "lloc_average": 0.0,
+                      "cloc_average": 0.5,
+                      "blank_average": 0.0,
+                      "sloc_min": 1.0,
+                      "sloc_max": 1.0,
+                      "cloc_min": 1.0,
+                      "cloc_max": 1.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 0.0,
+                      "lloc_max": 0.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn python_no_zero_blank() {
+        // Checks that the blank metric is not equal to 0 when there are some
+        // comments next to code lines.
+        check_metrics::(
+            "def ConnectToUpdateServer():
+                 pool = 4
+
+                 updateServer = -42
+                 isConnected = False
+                 currTry = 0
+                 numRetries = 10 # Number of IPC connection retries before
+                                 # giving up.
+                 numTries = 20 # Number of IPC connection tries before
+                               # giving up.",
+            "foo.py",
+            |metric| {
+                // Spaces: 2
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 10.0,
+                      "ploc": 7.0,
+                      "lloc": 6.0,
+                      "cloc": 4.0,
+                      "blank": 1.0,
+                      "sloc_average": 5.0,
+                      "ploc_average": 3.5,
+                      "lloc_average": 3.0,
+                      "cloc_average": 2.0,
+                      "blank_average": 0.5,
+                      "sloc_min": 10.0,
+                      "sloc_max": 10.0,
+                      "cloc_min": 4.0,
+                      "cloc_max": 4.0,
+                      "ploc_min": 7.0,
+                      "ploc_max": 7.0,
+                      "lloc_min": 6.0,
+                      "lloc_max": 6.0,
+                      "blank_min": 1.0,
+                      "blank_max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_no_blank() {
+        // Checks that the blank metric is equal to 0 when there are no blank
+        // lines and there are comments next to code lines.
+        check_metrics::(
+            "def ConnectToUpdateServer():
+                 pool = 4
+                 updateServer = -42
+                 isConnected = False
+                 currTry = 0
+                 numRetries = 10 # Number of IPC connection retries before
+                                 # giving up.
+                 numTries = 20 # Number of IPC connection tries before
+                               # giving up.",
+            "foo.py",
+            |metric| {
+                // Spaces: 2
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 9.0,
+                      "ploc": 7.0,
+                      "lloc": 6.0,
+                      "cloc": 4.0,
+                      "blank": 0.0,
+                      "sloc_average": 4.5,
+                      "ploc_average": 3.5,
+                      "lloc_average": 3.0,
+                      "cloc_average": 2.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 9.0,
+                      "sloc_max": 9.0,
+                      "cloc_min": 4.0,
+                      "cloc_max": 4.0,
+                      "ploc_min": 7.0,
+                      "ploc_max": 7.0,
+                      "lloc_min": 6.0,
+                      "lloc_max": 6.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_no_zero_blank_more_comments() {
+        // Checks that the blank metric is not equal to 0 when there are more
+        // comments next to code lines compared to the previous tests.
+        check_metrics::(
+            "def ConnectToUpdateServer():
+                 pool = 4
+
+                 updateServer = -42
+                 isConnected = False
+                 currTry = 0 # Set this variable to 0
+                 numRetries = 10 # Number of IPC connection retries before
+                                 # giving up.
+                 numTries = 20 # Number of IPC connection tries before
+                               # giving up.",
+            "foo.py",
+            |metric| {
+                // Spaces: 2
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 10.0,
+                      "ploc": 7.0,
+                      "lloc": 6.0,
+                      "cloc": 5.0,
+                      "blank": 1.0,
+                      "sloc_average": 5.0,
+                      "ploc_average": 3.5,
+                      "lloc_average": 3.0,
+                      "cloc_average": 2.5,
+                      "blank_average": 0.5,
+                      "sloc_min": 10.0,
+                      "sloc_max": 10.0,
+                      "cloc_min": 5.0,
+                      "cloc_max": 5.0,
+                      "ploc_min": 7.0,
+                      "ploc_max": 7.0,
+                      "lloc_min": 6.0,
+                      "lloc_max": 6.0,
+                      "blank_min": 1.0,
+                      "blank_max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_no_zero_blank() {
+        // Checks that the blank metric is not equal to 0 when there are some
+        // comments next to code lines.
+        check_metrics::(
+            "fn ConnectToUpdateServer() {
+              let pool = 0;
+
+              let updateServer = -42;
+              let isConnected = false;
+              let currTry = 0;
+              let numRetries = 10;  // Number of IPC connection retries before
+                                    // giving up.
+              let numTries = 20;    // Number of IPC connection tries before
+                                    // giving up.
+            }",
+            "foo.rs",
+            |metric| {
+                // Spaces: 2
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 11.0,
+                      "ploc": 8.0,
+                      "lloc": 6.0,
+                      "cloc": 4.0,
+                      "blank": 1.0,
+                      "sloc_average": 5.5,
+                      "ploc_average": 4.0,
+                      "lloc_average": 3.0,
+                      "cloc_average": 2.0,
+                      "blank_average": 0.5,
+                      "sloc_min": 11.0,
+                      "sloc_max": 11.0,
+                      "cloc_min": 4.0,
+                      "cloc_max": 4.0,
+                      "ploc_min": 8.0,
+                      "ploc_max": 8.0,
+                      "lloc_min": 6.0,
+                      "lloc_max": 6.0,
+                      "blank_min": 1.0,
+                      "blank_max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_cloc() {
+        check_metrics::(
+            "\"\"\"Block comment
+            Block comment
+            \"\"\"
+            # Line Comment
+            a = 42 # Line Comment",
+            "foo.py",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 5.0,
+                      "ploc": 1.0,
+                      "lloc": 2.0,
+                      "cloc": 5.0,
+                      "blank": 0.0,
+                      "sloc_average": 5.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 2.0,
+                      "cloc_average": 5.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 5.0,
+                      "sloc_max": 5.0,
+                      "cloc_min": 5.0,
+                      "cloc_max": 5.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 2.0,
+                      "lloc_max": 2.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_cloc() {
+        check_metrics::(
+            "/*Block comment
+            Block Comment*/
+            //Line Comment
+            /*Block Comment*/ let a = 42; // Line Comment",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 4.0,
+                      "ploc": 1.0,
+                      "lloc": 1.0,
+                      "cloc": 5.0,
+                      "blank": 0.0,
+                      "sloc_average": 4.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 5.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 4.0,
+                      "sloc_max": 4.0,
+                      "cloc_min": 5.0,
+                      "cloc_max": 5.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_lloc() {
+        check_metrics::(
+            "for x in range(0,42):
+                if x % 2 == 0:
+                    print(x)",
+            "foo.py",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 3.0,
+                      "ploc": 3.0,
+                      "lloc": 3.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 3.0,
+                      "lloc_average": 3.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 3.0,
+                      "sloc_max": 3.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 3.0,
+                      "ploc_max": 3.0,
+                      "lloc_min": 3.0,
+                      "lloc_max": 3.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_lloc() {
+        check_metrics::(
+            "for x in 0..42 {
+                if x % 2 == 0 {
+                    println!(\"{}\", x);
+                }
+             }",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 5.0,
+                      "ploc": 5.0,
+                      "lloc": 3.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 5.0,
+                      "ploc_average": 5.0,
+                      "lloc_average": 3.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 5.0,
+                      "sloc_max": 5.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 5.0,
+                      "ploc_max": 5.0,
+                      "lloc_min": 3.0,
+                      "lloc_max": 3.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+
+        // LLOC returns three because there is an empty Rust statement
+        check_metrics::(
+            "let a = 42;
+             if true {
+                42
+             } else {
+                43
+             };",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 6.0,
+                      "ploc": 6.0,
+                      "lloc": 3.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 6.0,
+                      "ploc_average": 6.0,
+                      "lloc_average": 3.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 6.0,
+                      "sloc_max": 6.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 6.0,
+                      "ploc_max": 6.0,
+                      "lloc_min": 3.0,
+                      "lloc_max": 3.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_string_on_new_line() {
+        // More lines of the same instruction were counted as blank lines
+        check_metrics::(
+            "capabilities[\"goog:chromeOptions\"][\"androidPackage\"] = \\
+                \"org.chromium.weblayer.shell\"",
+            "foo.py",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 2.0,
+                      "ploc": 2.0,
+                      "lloc": 1.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 2.0,
+                      "ploc_average": 2.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 2.0,
+                      "sloc_max": 2.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 2.0,
+                      "ploc_max": 2.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_no_field_expression_lloc() {
+        check_metrics::(
+            "struct Foo {
+                field: usize,
+             }
+             let foo = Foo { 42 };
+             foo.field;",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 5.0,
+                      "ploc": 5.0,
+                      "lloc": 2.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 5.0,
+                      "ploc_average": 5.0,
+                      "lloc_average": 2.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 5.0,
+                      "sloc_max": 5.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 5.0,
+                      "ploc_max": 5.0,
+                      "lloc_min": 2.0,
+                      "lloc_max": 2.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_no_parenthesized_expression_lloc() {
+        check_metrics::("let a = (42 + 0);", "foo.rs", |metric| {
+            // Spaces: 1
+            insta::assert_json_snapshot!(
+                metric.loc,
+                @r###"
+                    {
+                      "sloc": 1.0,
+                      "ploc": 1.0,
+                      "lloc": 1.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 1.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 1.0,
+                      "sloc_max": 1.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_no_array_expression_lloc() {
+        check_metrics::("let a = [0; 42];", "foo.rs", |metric| {
+            // Spaces: 1
+            insta::assert_json_snapshot!(
+                metric.loc,
+                @r###"
+                    {
+                      "sloc": 1.0,
+                      "ploc": 1.0,
+                      "lloc": 1.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 1.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 1.0,
+                      "sloc_max": 1.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_no_tuple_expression_lloc() {
+        check_metrics::("let a = (0, 42);", "foo.rs", |metric| {
+            // Spaces: 1
+            insta::assert_json_snapshot!(
+                metric.loc,
+                @r###"
+                    {
+                      "sloc": 1.0,
+                      "ploc": 1.0,
+                      "lloc": 1.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 1.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 1.0,
+                      "sloc_max": 1.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_no_unit_expression_lloc() {
+        check_metrics::("let a = ();", "foo.rs", |metric| {
+            // Spaces: 1
+            insta::assert_json_snapshot!(
+                metric.loc,
+                @r###"
+                    {
+                      "sloc": 1.0,
+                      "ploc": 1.0,
+                      "lloc": 1.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 1.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 1.0,
+                      "sloc_max": 1.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_call_function_lloc() {
+        check_metrics::(
+            "let a = foo(); // +1
+             foo(); // +1
+             k!(foo()); // +1",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 3.0,
+                      "ploc": 3.0,
+                      "lloc": 3.0,
+                      "cloc": 3.0,
+                      "blank": 0.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 3.0,
+                      "lloc_average": 3.0,
+                      "cloc_average": 3.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 3.0,
+                      "sloc_max": 3.0,
+                      "cloc_min": 3.0,
+                      "cloc_max": 3.0,
+                      "ploc_min": 3.0,
+                      "ploc_max": 3.0,
+                      "lloc_min": 3.0,
+                      "lloc_max": 3.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_macro_invocation_lloc() {
+        check_metrics::(
+            "let a = foo!(); // +1
+             foo!(); // +1
+             k(foo!()); // +1",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 3.0,
+                      "ploc": 3.0,
+                      "lloc": 3.0,
+                      "cloc": 3.0,
+                      "blank": 0.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 3.0,
+                      "lloc_average": 3.0,
+                      "cloc_average": 3.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 3.0,
+                      "sloc_max": 3.0,
+                      "cloc_min": 3.0,
+                      "cloc_max": 3.0,
+                      "ploc_min": 3.0,
+                      "ploc_max": 3.0,
+                      "lloc_min": 3.0,
+                      "lloc_max": 3.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_function_in_loop_lloc() {
+        check_metrics::(
+            "for (a, b) in c.iter().enumerate() {} // +1
+             while (a, b) in c.iter().enumerate() {} // +1
+             while let Some(a) = c.strip_prefix(\"hi\") {} // +1",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 3.0,
+                      "ploc": 3.0,
+                      "lloc": 3.0,
+                      "cloc": 3.0,
+                      "blank": 0.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 3.0,
+                      "lloc_average": 3.0,
+                      "cloc_average": 3.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 3.0,
+                      "sloc_max": 3.0,
+                      "cloc_min": 3.0,
+                      "cloc_max": 3.0,
+                      "ploc_min": 3.0,
+                      "ploc_max": 3.0,
+                      "lloc_min": 3.0,
+                      "lloc_max": 3.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_function_in_if_lloc() {
+        check_metrics::(
+            "if foo() {} // +1
+             if let Some(a) = foo() {} // +1",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 2.0,
+                      "ploc": 2.0,
+                      "lloc": 2.0,
+                      "cloc": 2.0,
+                      "blank": 0.0,
+                      "sloc_average": 2.0,
+                      "ploc_average": 2.0,
+                      "lloc_average": 2.0,
+                      "cloc_average": 2.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 2.0,
+                      "sloc_max": 2.0,
+                      "cloc_min": 2.0,
+                      "cloc_max": 2.0,
+                      "ploc_min": 2.0,
+                      "ploc_max": 2.0,
+                      "lloc_min": 2.0,
+                      "lloc_max": 2.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_function_in_return_lloc() {
+        check_metrics::(
+            "return foo();
+             await foo();",
+            "foo.rs",
+            |metric| {
+                // Spaces: 1
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 2.0,
+                      "ploc": 2.0,
+                      "lloc": 2.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 2.0,
+                      "ploc_average": 2.0,
+                      "lloc_average": 2.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 2.0,
+                      "sloc_max": 2.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 2.0,
+                      "ploc_max": 2.0,
+                      "lloc_min": 2.0,
+                      "lloc_max": 2.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_closure_expression_lloc() {
+        check_metrics::(
+            "let a = |i: i32| -> i32 { i + 1 }; // +1
+             a(42); // +1
+             k(b.iter().map(|n| n.parse.ok().unwrap_or(42))); // +1",
+            "foo.rs",
+            |metric| {
+                // Spaces: 3
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 3.0,
+                      "ploc": 3.0,
+                      "lloc": 3.0,
+                      "cloc": 3.0,
+                      "blank": 0.0,
+                      "sloc_average": 1.0,
+                      "ploc_average": 1.0,
+                      "lloc_average": 1.0,
+                      "cloc_average": 1.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 1.0,
+                      "sloc_max": 1.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 1.0,
+                      "ploc_max": 1.0,
+                      "lloc_min": 0.0,
+                      "lloc_max": 0.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_general_loc() {
+        check_metrics::(
+            "def func(a,
+                      b,
+                      c):
+                 print(a)
+                 print(b)
+                 print(c)",
+            "foo.py",
+            |metric| {
+                // Spaces: 2
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 6.0,
+                      "ploc": 6.0,
+                      "lloc": 3.0,
+                      "cloc": 0.0,
+                      "blank": 0.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 3.0,
+                      "lloc_average": 1.5,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.0,
+                      "sloc_min": 6.0,
+                      "sloc_max": 6.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 6.0,
+                      "ploc_max": 6.0,
+                      "lloc_min": 3.0,
+                      "lloc_max": 3.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_real_loc() {
+        check_metrics::(
+            "def web_socket_transfer_data(request):
+                while True:
+                    line = request.ws_stream.receive_message()
+                    if line is None:
+                        return
+                    code, reason = line.split(' ', 1)
+                    if code is None or reason is None:
+                        return
+                    request.ws_stream.close_connection(int(code), reason)
+                    # close_connection() initiates closing handshake. It validates code
+                    # and reason. If you want to send a broken close frame for a test,
+                    # following code will be useful.
+                    # > data = struct.pack('!H', int(code)) + reason.encode('UTF-8')
+                    # > request.connection.write(stream.create_close_frame(data))
+                    # > # Suppress to re-respond client responding close frame.
+                    # > raise Exception(\"customized server initiated closing handshake\")",
+            "foo.py",
+            |metric| {
+                // Spaces: 2
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 16.0,
+                      "ploc": 9.0,
+                      "lloc": 8.0,
+                      "cloc": 7.0,
+                      "blank": 0.0,
+                      "sloc_average": 8.0,
+                      "ploc_average": 4.5,
+                      "lloc_average": 4.0,
+                      "cloc_average": 3.5,
+                      "blank_average": 0.0,
+                      "sloc_min": 16.0,
+                      "sloc_max": 16.0,
+                      "cloc_min": 7.0,
+                      "cloc_max": 7.0,
+                      "ploc_min": 9.0,
+                      "ploc_max": 9.0,
+                      "lloc_min": 8.0,
+                      "lloc_max": 8.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_sloc() {
+        check_metrics::(
+            "package main
+
+            // A comment
+            func main() {
+                x := 1
+            }
+            ",
+            "foo.go",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 6.0,
+                      "ploc": 4.0,
+                      "lloc": 1.0,
+                      "cloc": 1.0,
+                      "blank": 1.0,
+                      "sloc_average": 3.0,
+                      "ploc_average": 2.0,
+                      "lloc_average": 0.5,
+                      "cloc_average": 0.5,
+                      "blank_average": 0.5,
+                      "sloc_min": 3.0,
+                      "sloc_max": 3.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 3.0,
+                      "ploc_max": 3.0,
+                      "lloc_min": 1.0,
+                      "lloc_max": 1.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn go_lloc() {
+        check_metrics::(
+            "package main
+
+            func main() {
+                x := 1
+                y := 2
+                if x > y {
+                    return
+                }
+            }",
+            "foo.go",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.loc,
+                    @r###"
+                    {
+                      "sloc": 9.0,
+                      "ploc": 8.0,
+                      "lloc": 4.0,
+                      "cloc": 0.0,
+                      "blank": 1.0,
+                      "sloc_average": 4.5,
+                      "ploc_average": 4.0,
+                      "lloc_average": 2.0,
+                      "cloc_average": 0.0,
+                      "blank_average": 0.5,
+                      "sloc_min": 7.0,
+                      "sloc_max": 7.0,
+                      "cloc_min": 0.0,
+                      "cloc_max": 0.0,
+                      "ploc_min": 7.0,
+                      "ploc_max": 7.0,
+                      "lloc_min": 4.0,
+                      "lloc_max": 4.0,
+                      "blank_min": 0.0,
+                      "blank_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/mi.rs b/src/metrics/mi.rs
new file mode 100644
index 00000000..220f825b
--- /dev/null
+++ b/src/metrics/mi.rs
@@ -0,0 +1,134 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use super::cyclomatic;
+use super::halstead;
+use super::loc;
+
+use crate::checker::Checker;
+use crate::macros::implement_metric_trait;
+
+use crate::*;
+
+/// The `Mi` metric.
+#[derive(Default, Clone, Debug)]
+pub struct Stats {
+    halstead_length: f64,
+    halstead_vocabulary: f64,
+    halstead_volume: f64,
+    cyclomatic: f64,
+    sloc: f64,
+    comments_percentage: f64,
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("maintainability_index", 3)?;
+        st.serialize_field("mi_original", &self.mi_original())?;
+        st.serialize_field("mi_sei", &self.mi_sei())?;
+        st.serialize_field("mi_visual_studio", &self.mi_visual_studio())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "mi_original: {}, mi_sei: {}, mi_visual_studio: {}",
+            self.mi_original(),
+            self.mi_sei(),
+            self.mi_visual_studio()
+        )
+    }
+}
+
+impl Stats {
+    pub(crate) fn merge(&mut self, _other: &Stats) {}
+
+    /// Returns the `Mi` metric calculated using the original formula.
+    ///
+    /// Its value can be negative.
+    #[inline(always)]
+    pub fn mi_original(&self) -> f64 {
+        // http://www.projectcodemeter.com/cost_estimation/help/GL_maintainability.htm
+        171.0 - 5.2 * (self.halstead_volume).ln() - 0.23 * self.cyclomatic - 16.2 * self.sloc.ln()
+    }
+
+    /// Returns the `Mi` metric calculated using the derivative formula
+    /// employed by the Software Engineering Institute (SEI).
+    ///
+    /// Its value can be negative.
+    #[inline(always)]
+    pub fn mi_sei(&self) -> f64 {
+        // http://www.projectcodemeter.com/cost_estimation/help/GL_maintainability.htm
+        171.0 - 5.2 * self.halstead_volume.log2() - 0.23 * self.cyclomatic - 16.2 * self.sloc.log2()
+            + 50.0 * (self.comments_percentage * 2.4).sqrt().sin()
+    }
+
+    /// Returns the `Mi` metric calculated using the derivative formula
+    /// employed by Microsoft Visual Studio.
+    #[inline(always)]
+    pub fn mi_visual_studio(&self) -> f64 {
+        // http://www.projectcodemeter.com/cost_estimation/help/GL_maintainability.htm
+        let formula = 171.0
+            - 5.2 * self.halstead_volume.ln()
+            - 0.23 * self.cyclomatic
+            - 16.2 * self.sloc.ln();
+        (formula * 100.0 / 171.0).max(0.)
+    }
+}
+
+pub trait Mi
+where
+    Self: Checker,
+{
+    fn compute(
+        loc: &loc::Stats,
+        cyclomatic: &cyclomatic::Stats,
+        halstead: &halstead::Stats,
+        stats: &mut Stats,
+    ) {
+        stats.halstead_length = halstead.length();
+        stats.halstead_vocabulary = halstead.vocabulary();
+        stats.halstead_volume = halstead.volume();
+        stats.cyclomatic = cyclomatic.cyclomatic_sum();
+        stats.sloc = loc.sloc();
+        stats.comments_percentage = loc.cloc() / stats.sloc;
+    }
+}
+
+implement_metric_trait!([Mi], PythonCode, TypescriptCode, TsxCode, RustCode, GoCode);
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn check_mi_metrics() {
+        // This test checks that MI metric is computed correctly, so it verifies
+        // the calculations are correct, the adopted source code is irrelevant
+        check_metrics::(
+            "def f():
+                 pass",
+            "foo.py",
+            |metric| {
+                insta::assert_json_snapshot!(
+                    metric.mi,
+                    @r###"
+                    {
+                      "mi_original": 151.2033158832232,
+                      "mi_sei": 142.64306171748976,
+                      "mi_visual_studio": 88.42299174457497
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs
new file mode 100644
index 00000000..c6affda5
--- /dev/null
+++ b/src/metrics/mod.rs
@@ -0,0 +1,12 @@
+pub mod abc;
+pub mod cognitive;
+pub mod cyclomatic;
+pub mod exit;
+pub mod halstead;
+pub mod loc;
+pub mod mi;
+pub mod nargs;
+pub mod nom;
+pub mod npa;
+pub mod npm;
+pub mod wmc;
diff --git a/src/metrics/nargs.rs b/src/metrics/nargs.rs
new file mode 100644
index 00000000..a78e8fd1
--- /dev/null
+++ b/src/metrics/nargs.rs
@@ -0,0 +1,575 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::macros::implement_metric_trait;
+use crate::*;
+
+/// The `NArgs` metric.
+///
+/// This metric counts the number of arguments
+/// of functions/closures.
+#[derive(Debug, Clone)]
+pub struct Stats {
+    fn_nargs: usize,
+    closure_nargs: usize,
+    fn_nargs_sum: usize,
+    closure_nargs_sum: usize,
+    fn_nargs_min: usize,
+    closure_nargs_min: usize,
+    fn_nargs_max: usize,
+    closure_nargs_max: usize,
+    total_functions: usize,
+    total_closures: usize,
+}
+
+impl Default for Stats {
+    fn default() -> Self {
+        Self {
+            fn_nargs: 0,
+            closure_nargs: 0,
+            fn_nargs_sum: 0,
+            closure_nargs_sum: 0,
+            fn_nargs_min: usize::MAX,
+            closure_nargs_min: usize::MAX,
+            fn_nargs_max: 0,
+            closure_nargs_max: 0,
+            total_functions: 0,
+            total_closures: 0,
+        }
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("nargs", 10)?;
+        st.serialize_field("total_functions", &self.fn_args_sum())?;
+        st.serialize_field("total_closures", &self.closure_args_sum())?;
+        st.serialize_field("average_functions", &self.fn_args_average())?;
+        st.serialize_field("average_closures", &self.closure_args_average())?;
+        st.serialize_field("total", &self.nargs_total())?;
+        st.serialize_field("average", &self.nargs_average())?;
+        st.serialize_field("functions_min", &self.fn_args_min())?;
+        st.serialize_field("functions_max", &self.fn_args_max())?;
+        st.serialize_field("closures_min", &self.closure_args_min())?;
+        st.serialize_field("closures_max", &self.closure_args_max())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "total_functions: {}, total_closures: {}, average_functions: {}, average_closures: {}, total: {}, average: {}, functions_min: {}, functions_max: {}, closures_min: {}, closures_max: {}",
+            self.fn_args(),
+            self.closure_args(),
+            self.fn_args_average(),
+            self.closure_args_average(),
+            self.nargs_total(),
+            self.nargs_average(),
+            self.fn_args_min(),
+            self.fn_args_max(),
+            self.closure_args_min(),
+            self.closure_args_max()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `NArgs` metric into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        self.closure_nargs_min = self.closure_nargs_min.min(other.closure_nargs_min);
+        self.closure_nargs_max = self.closure_nargs_max.max(other.closure_nargs_max);
+        self.fn_nargs_min = self.fn_nargs_min.min(other.fn_nargs_min);
+        self.fn_nargs_max = self.fn_nargs_max.max(other.fn_nargs_max);
+        self.fn_nargs_sum += other.fn_nargs_sum;
+        self.closure_nargs_sum += other.closure_nargs_sum;
+    }
+
+    /// Returns the number of function arguments in a space.
+    #[inline(always)]
+    pub fn fn_args(&self) -> f64 {
+        self.fn_nargs as f64
+    }
+
+    /// Returns the number of closure arguments in a space.
+    #[inline(always)]
+    pub fn closure_args(&self) -> f64 {
+        self.closure_nargs as f64
+    }
+
+    /// Returns the number of function arguments sum in a space.
+    #[inline(always)]
+    pub fn fn_args_sum(&self) -> f64 {
+        self.fn_nargs_sum as f64
+    }
+
+    /// Returns the number of closure arguments sum in a space.
+    #[inline(always)]
+    pub fn closure_args_sum(&self) -> f64 {
+        self.closure_nargs_sum as f64
+    }
+
+    /// Returns the average number of functions arguments in a space.
+    #[inline(always)]
+    pub fn fn_args_average(&self) -> f64 {
+        self.fn_nargs_sum as f64 / self.total_functions.max(1) as f64
+    }
+
+    /// Returns the average number of closures arguments in a space.
+    #[inline(always)]
+    pub fn closure_args_average(&self) -> f64 {
+        self.closure_nargs_sum as f64 / self.total_closures.max(1) as f64
+    }
+
+    /// Returns the total number of arguments of each function and
+    /// closure in a space.
+    #[inline(always)]
+    pub fn nargs_total(&self) -> f64 {
+        self.fn_args_sum() + self.closure_args_sum()
+    }
+
+    /// Returns the `NArgs` metric average value
+    ///
+    /// This value is computed dividing the `NArgs` value
+    /// for the total number of functions/closures in a space.
+    #[inline(always)]
+    pub fn nargs_average(&self) -> f64 {
+        self.nargs_total() / (self.total_functions + self.total_closures).max(1) as f64
+    }
+    /// Returns the minimum number of function arguments in a space.
+    #[inline(always)]
+    pub fn fn_args_min(&self) -> f64 {
+        self.fn_nargs_min as f64
+    }
+    /// Returns the maximum number of function arguments in a space.
+    #[inline(always)]
+    pub fn fn_args_max(&self) -> f64 {
+        self.fn_nargs_max as f64
+    }
+    /// Returns the minimum number of closure arguments in a space.
+    #[inline(always)]
+    pub fn closure_args_min(&self) -> f64 {
+        self.closure_nargs_min as f64
+    }
+    /// Returns the maximum number of closure arguments in a space.
+    #[inline(always)]
+    pub fn closure_args_max(&self) -> f64 {
+        self.closure_nargs_max as f64
+    }
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.closure_nargs_sum += self.closure_nargs;
+        self.fn_nargs_sum += self.fn_nargs;
+    }
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        self.closure_nargs_min = self.closure_nargs_min.min(self.closure_nargs);
+        self.closure_nargs_max = self.closure_nargs_max.max(self.closure_nargs);
+        self.fn_nargs_min = self.fn_nargs_min.min(self.fn_nargs);
+        self.fn_nargs_max = self.fn_nargs_max.max(self.fn_nargs);
+        self.compute_sum();
+    }
+    pub(crate) fn finalize(&mut self, total_functions: usize, total_closures: usize) {
+        self.total_functions = total_functions;
+        self.total_closures = total_closures;
+    }
+}
+
+#[inline(always)]
+fn compute_args(node: &Node, nargs: &mut usize) {
+    if let Some(params) = node.child_by_field_name("parameters") {
+        let node_params = params;
+        node_params.act_on_child(&mut |n| {
+            if !T::is_non_arg(n) {
+                *nargs += 1;
+            }
+        });
+    }
+}
+
+pub trait NArgs
+where
+    Self: Checker,
+    Self: std::marker::Sized,
+{
+    fn compute(node: &Node, stats: &mut Stats) {
+        if Self::is_func(node) {
+            compute_args::(node, &mut stats.fn_nargs);
+            return;
+        }
+
+        if Self::is_closure(node) {
+            compute_args::(node, &mut stats.closure_nargs);
+        }
+    }
+}
+
+implement_metric_trait!(
+    [NArgs],
+    PythonCode,
+    TypescriptCode,
+    TsxCode,
+    RustCode,
+    GoCode
+);
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn python_no_functions_and_closures() {
+        check_metrics::("a = 42", "foo.py", |metric| {
+            // 0 functions + 0 closures
+            insta::assert_json_snapshot!(
+                metric.nargs,
+                @r###"
+                    {
+                      "total_functions": 0.0,
+                      "total_closures": 0.0,
+                      "average_functions": 0.0,
+                      "average_closures": 0.0,
+                      "total": 0.0,
+                      "average": 0.0,
+                      "functions_min": 0.0,
+                      "functions_max": 0.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_no_functions_and_closures() {
+        check_metrics::("let a = 42;", "foo.rs", |metric| {
+            // 0 functions + 0 closures
+            insta::assert_json_snapshot!(
+                metric.nargs,
+                @r###"
+                    {
+                      "total_functions": 0.0,
+                      "total_closures": 0.0,
+                      "average_functions": 0.0,
+                      "average_closures": 0.0,
+                      "total": 0.0,
+                      "average": 0.0,
+                      "functions_min": 0.0,
+                      "functions_max": 0.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn python_single_function() {
+        check_metrics::(
+            "def f(a, b):
+                 if a:
+                     return a",
+            "foo.py",
+            |metric| {
+                // 1 function
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 2.0,
+                      "total_closures": 0.0,
+                      "average_functions": 2.0,
+                      "average_closures": 0.0,
+                      "total": 2.0,
+                      "average": 2.0,
+                      "functions_min": 0.0,
+                      "functions_max": 2.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_single_function() {
+        check_metrics::(
+            "fn f(a: bool, b: usize) {
+                 if a {
+                     return a;
+                }
+             }",
+            "foo.rs",
+            |metric| {
+                // 1 function
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 2.0,
+                      "total_closures": 0.0,
+                      "average_functions": 2.0,
+                      "average_closures": 0.0,
+                      "total": 2.0,
+                      "average": 2.0,
+                      "functions_min": 0.0,
+                      "functions_max": 2.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_single_lambda() {
+        check_metrics::("bar = lambda a: True", "foo.py", |metric| {
+            // 1 lambda
+            insta::assert_json_snapshot!(
+                metric.nargs,
+                @r###"
+                    {
+                      "total_functions": 0.0,
+                      "total_closures": 1.0,
+                      "average_functions": 0.0,
+                      "average_closures": 1.0,
+                      "total": 1.0,
+                      "average": 1.0,
+                      "functions_min": 0.0,
+                      "functions_max": 0.0,
+                      "closures_min": 1.0,
+                      "closures_max": 1.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn rust_single_closure() {
+        check_metrics::("let bar = |i: i32| -> i32 { i + 1 };", "foo.rs", |metric| {
+            // 1 lambda
+            insta::assert_json_snapshot!(
+                metric.nargs,
+                @r###"
+                    {
+                      "total_functions": 0.0,
+                      "total_closures": 1.0,
+                      "average_functions": 0.0,
+                      "average_closures": 1.0,
+                      "total": 1.0,
+                      "average": 1.0,
+                      "functions_min": 0.0,
+                      "functions_max": 0.0,
+                      "closures_min": 0.0,
+                      "closures_max": 1.0
+                    }"###
+            );
+        });
+    }
+
+    #[test]
+    fn python_functions() {
+        check_metrics::(
+            "def f(a, b):
+                 if a:
+                     return a
+            def f(a, b):
+                 if b:
+                     return b",
+            "foo.py",
+            |metric| {
+                // 2 functions
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 4.0,
+                      "total_closures": 0.0,
+                      "average_functions": 2.0,
+                      "average_closures": 0.0,
+                      "total": 4.0,
+                      "average": 2.0,
+                      "functions_min": 0.0,
+                      "functions_max": 2.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+                );
+            },
+        );
+
+        check_metrics::(
+            "def f(a, b):
+                 if a:
+                     return a
+            def f(a, b, c):
+                 if b:
+                     return b",
+            "foo.py",
+            |metric| {
+                // 2 functions
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 5.0,
+                      "total_closures": 0.0,
+                      "average_functions": 2.5,
+                      "average_closures": 0.0,
+                      "total": 5.0,
+                      "average": 2.5,
+                      "functions_min": 0.0,
+                      "functions_max": 3.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_functions() {
+        check_metrics::(
+            "fn f(a: bool, b: usize) {
+                 if a {
+                     return a;
+                }
+             }
+             fn f1(a: bool, b: usize) {
+                 if a {
+                     return a;
+                }
+             }",
+            "foo.rs",
+            |metric| {
+                // 2 functions
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 4.0,
+                      "total_closures": 0.0,
+                      "average_functions": 2.0,
+                      "average_closures": 0.0,
+                      "total": 4.0,
+                      "average": 2.0,
+                      "functions_min": 0.0,
+                      "functions_max": 2.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+                );
+            },
+        );
+
+        check_metrics::(
+            "fn f(a: bool, b: usize) {
+                 if a {
+                     return a;
+                }
+             }
+             fn f1(a: bool, b: usize, c: usize) {
+                 if a {
+                     return a;
+                }
+             }",
+            "foo.rs",
+            |metric| {
+                // 2 functions
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 5.0,
+                      "total_closures": 0.0,
+                      "average_functions": 2.5,
+                      "average_closures": 0.0,
+                      "total": 5.0,
+                      "average": 2.5,
+                      "functions_min": 0.0,
+                      "functions_max": 3.0,
+                      "closures_min": 0.0,
+                      "closures_max": 0.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn python_nested_functions() {
+        check_metrics::(
+            "def f(a, b):
+                 def foo(a):
+                     if a:
+                         return 1
+                 bar = lambda a: lambda b: b or True or True
+                 return bar(foo(a))(a)",
+            "foo.py",
+            |metric| {
+                // 2 functions + 2 lambdas = 4
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 3.0,
+                      "total_closures": 2.0,
+                      "average_functions": 1.5,
+                      "average_closures": 1.0,
+                      "total": 5.0,
+                      "average": 1.25,
+                      "functions_min": 0.0,
+                      "functions_max": 2.0,
+                      "closures_min": 0.0,
+                      "closures_max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_nested_functions() {
+        check_metrics::(
+            "fn f(a: i32, b: i32) -> i32 {
+                 fn foo(a: i32) -> i32 {
+                     return a;
+                 }
+                 let bar = |a: i32, b: i32| -> i32 { a + 1 };
+                 let bar1 = |b: i32| -> i32 { b + 1 };
+                 return bar(foo(a), a);
+             }",
+            "foo.rs",
+            |metric| {
+                // 2 functions + 2 lambdas = 4
+                insta::assert_json_snapshot!(
+                    metric.nargs,
+                    @r###"
+                    {
+                      "total_functions": 3.0,
+                      "total_closures": 3.0,
+                      "average_functions": 1.5,
+                      "average_closures": 1.5,
+                      "total": 6.0,
+                      "average": 1.5,
+                      "functions_min": 0.0,
+                      "functions_max": 2.0,
+                      "closures_min": 0.0,
+                      "closures_max": 2.0
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/nom.rs b/src/metrics/nom.rs
new file mode 100644
index 00000000..414e9cf4
--- /dev/null
+++ b/src/metrics/nom.rs
@@ -0,0 +1,273 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::macros::implement_metric_trait;
+
+use crate::*;
+
+/// The `Nom` metric suite.
+#[derive(Clone, Debug)]
+pub struct Stats {
+    functions: usize,
+    closures: usize,
+    functions_sum: usize,
+    closures_sum: usize,
+    functions_min: usize,
+    functions_max: usize,
+    closures_min: usize,
+    closures_max: usize,
+    space_count: usize,
+}
+
+impl Default for Stats {
+    fn default() -> Self {
+        Self {
+            functions: 0,
+            closures: 0,
+            functions_sum: 0,
+            closures_sum: 0,
+            functions_min: usize::MAX,
+            functions_max: 0,
+            closures_min: usize::MAX,
+            closures_max: 0,
+            space_count: 1,
+        }
+    }
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("nom", 10)?;
+        st.serialize_field("functions", &self.functions_sum())?;
+        st.serialize_field("closures", &self.closures_sum())?;
+        st.serialize_field("functions_average", &self.functions_average())?;
+        st.serialize_field("closures_average", &self.closures_average())?;
+        st.serialize_field("total", &self.total())?;
+        st.serialize_field("average", &self.average())?;
+        st.serialize_field("functions_min", &self.functions_min())?;
+        st.serialize_field("functions_max", &self.functions_max())?;
+        st.serialize_field("closures_min", &self.closures_min())?;
+        st.serialize_field("closures_max", &self.closures_max())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "functions: {}, \
+             closures: {}, \
+             functions_average: {}, \
+             closures_average: {}, \
+             total: {} \
+             average: {} \
+             functions_min: {} \
+             functions_max: {} \
+             closures_min: {} \
+             closures_max: {}",
+            self.functions_sum(),
+            self.closures_sum(),
+            self.functions_average(),
+            self.closures_average(),
+            self.total(),
+            self.average(),
+            self.functions_min(),
+            self.functions_max(),
+            self.closures_min(),
+            self.closures_max(),
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Nom` metric suite into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        self.functions_min = self.functions_min.min(other.functions_min);
+        self.functions_max = self.functions_max.max(other.functions_max);
+        self.closures_min = self.closures_min.min(other.closures_min);
+        self.closures_max = self.closures_max.max(other.closures_max);
+        self.functions_sum += other.functions_sum;
+        self.closures_sum += other.closures_sum;
+        self.space_count += other.space_count;
+    }
+
+    /// Counts the number of function definitions in a scope
+    #[inline(always)]
+    pub fn functions(&self) -> f64 {
+        // Only function definitions are considered, not general declarations
+        self.functions as f64
+    }
+
+    /// Counts the number of closures in a scope
+    #[inline(always)]
+    pub fn closures(&self) -> f64 {
+        self.closures as f64
+    }
+
+    /// Return the sum metric for functions
+    #[inline(always)]
+    pub fn functions_sum(&self) -> f64 {
+        // Only function definitions are considered, not general declarations
+        self.functions_sum as f64
+    }
+
+    /// Return the sum metric for closures
+    #[inline(always)]
+    pub fn closures_sum(&self) -> f64 {
+        self.closures_sum as f64
+    }
+
+    /// Returns the average number of function definitions over all spaces
+    #[inline(always)]
+    pub fn functions_average(&self) -> f64 {
+        self.functions_sum() / self.space_count as f64
+    }
+
+    /// Returns the average number of closures over all spaces
+    #[inline(always)]
+    pub fn closures_average(&self) -> f64 {
+        self.closures_sum() / self.space_count as f64
+    }
+
+    /// Returns the average number of function definitions and closures over all spaces
+    #[inline(always)]
+    pub fn average(&self) -> f64 {
+        self.total() / self.space_count as f64
+    }
+
+    /// Counts the number of function definitions in a scope
+    #[inline(always)]
+    pub fn functions_min(&self) -> f64 {
+        // Only function definitions are considered, not general declarations
+        self.functions_min as f64
+    }
+
+    /// Counts the number of closures in a scope
+    #[inline(always)]
+    pub fn closures_min(&self) -> f64 {
+        self.closures_min as f64
+    }
+    /// Counts the number of function definitions in a scope
+    #[inline(always)]
+    pub fn functions_max(&self) -> f64 {
+        // Only function definitions are considered, not general declarations
+        self.functions_max as f64
+    }
+
+    /// Counts the number of closures in a scope
+    #[inline(always)]
+    pub fn closures_max(&self) -> f64 {
+        self.closures_max as f64
+    }
+    /// Returns the total number of function definitions and
+    /// closures in a scope
+    #[inline(always)]
+    pub fn total(&self) -> f64 {
+        self.functions_sum() + self.closures_sum()
+    }
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.functions_sum += self.functions;
+        self.closures_sum += self.closures;
+    }
+    #[inline(always)]
+    pub(crate) fn compute_minmax(&mut self) {
+        self.functions_min = self.functions_min.min(self.functions);
+        self.functions_max = self.functions_max.max(self.functions);
+        self.closures_min = self.closures_min.min(self.closures);
+        self.closures_max = self.closures_max.max(self.closures);
+        self.compute_sum();
+    }
+}
+
+pub trait Nom
+where
+    Self: Checker,
+{
+    fn compute(node: &Node, stats: &mut Stats) {
+        if Self::is_func(node) {
+            stats.functions += 1;
+            return;
+        }
+        if Self::is_closure(node) {
+            stats.closures += 1;
+        }
+    }
+}
+
+implement_metric_trait!([Nom], PythonCode, TypescriptCode, TsxCode, RustCode, GoCode);
+
+#[cfg(test)]
+mod tests {
+    use crate::tools::check_metrics;
+
+    use super::*;
+
+    #[test]
+    fn python_nom() {
+        check_metrics::(
+            "def a():
+                 pass
+             def b():
+                 pass
+             def c():
+                 pass
+             x = lambda a : a + 42",
+            "foo.py",
+            |metric| {
+                // Number of spaces = 4
+                insta::assert_json_snapshot!(
+                    metric.nom,
+                    @r###"
+                    {
+                      "functions": 3.0,
+                      "closures": 1.0,
+                      "functions_average": 0.75,
+                      "closures_average": 0.25,
+                      "total": 4.0,
+                      "average": 1.0,
+                      "functions_min": 0.0,
+                      "functions_max": 1.0,
+                      "closures_min": 0.0,
+                      "closures_max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+
+    #[test]
+    fn rust_nom() {
+        check_metrics::(
+            "mod A { fn foo() {}}
+             mod B { fn foo() {}}
+             let closure = |i: i32| -> i32 { i + 42 };",
+            "foo.rs",
+            |metric| {
+                // Number of spaces = 4
+                insta::assert_json_snapshot!(
+                    metric.nom,
+                    @r###"
+                    {
+                      "functions": 2.0,
+                      "closures": 1.0,
+                      "functions_average": 0.5,
+                      "closures_average": 0.25,
+                      "total": 3.0,
+                      "average": 0.75,
+                      "functions_min": 0.0,
+                      "functions_max": 1.0,
+                      "closures_min": 0.0,
+                      "closures_max": 1.0
+                    }"###
+                );
+            },
+        );
+    }
+}
diff --git a/src/metrics/npa.rs b/src/metrics/npa.rs
new file mode 100644
index 00000000..7fbb9cc2
--- /dev/null
+++ b/src/metrics/npa.rs
@@ -0,0 +1,205 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::langs::*;
+use crate::macros::implement_metric_trait;
+use crate::node::Node;
+
+/// The `Npa` metric.
+///
+/// This metric counts the number of public attributes
+/// of classes/interfaces.
+#[derive(Clone, Debug, Default)]
+pub struct Stats {
+    class_npa: usize,
+    interface_npa: usize,
+    class_na: usize,
+    interface_na: usize,
+    class_npa_sum: usize,
+    interface_npa_sum: usize,
+    class_na_sum: usize,
+    interface_na_sum: usize,
+    is_class_space: bool,
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("npa", 9)?;
+        st.serialize_field("classes", &self.class_npa_sum())?;
+        st.serialize_field("interfaces", &self.interface_npa_sum())?;
+        st.serialize_field("class_attributes", &self.class_na_sum())?;
+        st.serialize_field("interface_attributes", &self.interface_na_sum())?;
+        st.serialize_field("classes_average", &self.class_cda())?;
+        st.serialize_field("interfaces_average", &self.interface_cda())?;
+        st.serialize_field("total", &self.total_npa())?;
+        st.serialize_field("total_attributes", &self.total_na())?;
+        st.serialize_field("average", &self.total_cda())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "classes: {}, interfaces: {}, class_attributes: {}, interface_attributes: {}, classes_average: {}, interfaces_average: {}, total: {}, total_attributes: {}, average: {}",
+            self.class_npa_sum(),
+            self.interface_npa_sum(),
+            self.class_na_sum(),
+            self.interface_na_sum(),
+            self.class_cda(),
+            self.interface_cda(),
+            self.total_npa(),
+            self.total_na(),
+            self.total_cda()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Npa` metric into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        self.class_npa_sum += other.class_npa_sum;
+        self.interface_npa_sum += other.interface_npa_sum;
+        self.class_na_sum += other.class_na_sum;
+        self.interface_na_sum += other.interface_na_sum;
+    }
+
+    /// Returns the number of class public attributes in a space.
+    #[inline(always)]
+    pub fn class_npa(&self) -> f64 {
+        self.class_npa as f64
+    }
+
+    /// Returns the number of interface public attributes in a space.
+    #[inline(always)]
+    pub fn interface_npa(&self) -> f64 {
+        self.interface_npa as f64
+    }
+
+    /// Returns the number of class attributes in a space.
+    #[inline(always)]
+    pub fn class_na(&self) -> f64 {
+        self.class_na as f64
+    }
+
+    /// Returns the number of interface attributes in a space.
+    #[inline(always)]
+    pub fn interface_na(&self) -> f64 {
+        self.interface_na as f64
+    }
+
+    /// Returns the number of class public attributes sum in a space.
+    #[inline(always)]
+    pub fn class_npa_sum(&self) -> f64 {
+        self.class_npa_sum as f64
+    }
+
+    /// Returns the number of interface public attributes sum in a space.
+    #[inline(always)]
+    pub fn interface_npa_sum(&self) -> f64 {
+        self.interface_npa_sum as f64
+    }
+
+    /// Returns the number of class attributes sum in a space.
+    #[inline(always)]
+    pub fn class_na_sum(&self) -> f64 {
+        self.class_na_sum as f64
+    }
+
+    /// Returns the number of interface attributes sum in a space.
+    #[inline(always)]
+    pub fn interface_na_sum(&self) -> f64 {
+        self.interface_na_sum as f64
+    }
+
+    /// Returns the class `Cda` metric value
+    ///
+    /// The `Class Data Accessibility` metric value for a class
+    /// is computed by dividing the `Npa` value of the class
+    /// by the total number of attributes defined in the class.
+    ///
+    /// This metric is an adaptation of the `Classified Class Data Accessibility` (`CCDA`)
+    /// security metric for not classified attributes.
+    /// Paper: 
+    #[inline(always)]
+    pub fn class_cda(&self) -> f64 {
+        self.class_npa_sum() / self.class_na_sum as f64
+    }
+
+    /// Returns the interface `Cda` metric value
+    ///
+    /// The `Class Data Accessibility` metric value for an interface
+    /// is computed by dividing the `Npa` value of the interface
+    /// by the total number of attributes defined in the interface.
+    ///
+    /// This metric is an adaptation of the `Classified Class Data Accessibility` (`CCDA`)
+    /// security metric for not classified attributes.
+    /// Paper: 
+    #[inline(always)]
+    pub fn interface_cda(&self) -> f64 {
+        // For the Java language it's not necessary to compute the metric value
+        // The metric value in Java can only be 1.0 or f64:NAN
+        if self.interface_npa_sum == self.interface_na_sum && self.interface_npa_sum != 0 {
+            1.0
+        } else {
+            self.interface_npa_sum() / self.interface_na_sum()
+        }
+    }
+
+    /// Returns the total `Cda` metric value
+    ///
+    /// The total `Class Data Accessibility` metric value
+    /// is computed by dividing the total `Npa` value
+    /// by the total number of attributes.
+    ///
+    /// This metric is an adaptation of the `Classified Class Data Accessibility` (`CCDA`)
+    /// security metric for not classified attributes.
+    /// Paper: 
+    #[inline(always)]
+    pub fn total_cda(&self) -> f64 {
+        self.total_npa() / self.total_na()
+    }
+
+    /// Returns the total number of public attributes in a space.
+    #[inline(always)]
+    pub fn total_npa(&self) -> f64 {
+        self.class_npa_sum() + self.interface_npa_sum()
+    }
+
+    /// Returns the total number of attributes in a space.
+    #[inline(always)]
+    pub fn total_na(&self) -> f64 {
+        self.class_na_sum() + self.interface_na_sum()
+    }
+
+    // Accumulates the number of class and interface
+    // public and not public attributes into the sums
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.class_npa_sum += self.class_npa;
+        self.interface_npa_sum += self.interface_npa;
+        self.class_na_sum += self.class_na;
+        self.interface_na_sum += self.interface_na;
+    }
+
+    // Checks if the `Npa` metric is disabled
+    #[inline(always)]
+    pub(crate) fn is_disabled(&self) -> bool {
+        !self.is_class_space
+    }
+}
+
+pub trait Npa
+where
+    Self: Checker,
+{
+    fn compute(node: &Node, stats: &mut Stats);
+}
+
+implement_metric_trait!(Npa, PythonCode, TypescriptCode, TsxCode, RustCode, GoCode);
diff --git a/src/metrics/npm.rs b/src/metrics/npm.rs
new file mode 100644
index 00000000..96d1fae8
--- /dev/null
+++ b/src/metrics/npm.rs
@@ -0,0 +1,205 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::langs::*;
+use crate::macros::implement_metric_trait;
+use crate::node::Node;
+
+/// The `Npm` metric.
+///
+/// This metric counts the number of public methods
+/// of classes/interfaces.
+#[derive(Clone, Debug, Default)]
+pub struct Stats {
+    class_npm: usize,
+    interface_npm: usize,
+    class_nm: usize,
+    interface_nm: usize,
+    class_npm_sum: usize,
+    interface_npm_sum: usize,
+    class_nm_sum: usize,
+    interface_nm_sum: usize,
+    is_class_space: bool,
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("npm", 9)?;
+        st.serialize_field("classes", &self.class_npm_sum())?;
+        st.serialize_field("interfaces", &self.interface_npm_sum())?;
+        st.serialize_field("class_methods", &self.class_nm_sum())?;
+        st.serialize_field("interface_methods", &self.interface_nm_sum())?;
+        st.serialize_field("classes_average", &self.class_coa())?;
+        st.serialize_field("interfaces_average", &self.interface_coa())?;
+        st.serialize_field("total", &self.total_npm())?;
+        st.serialize_field("total_methods", &self.total_nm())?;
+        st.serialize_field("average", &self.total_coa())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "classes: {}, interfaces: {}, class_methods: {}, interface_methods: {}, classes_average: {}, interfaces_average: {}, total: {}, total_methods: {}, average: {}",
+            self.class_npm_sum(),
+            self.interface_npm_sum(),
+            self.class_nm_sum(),
+            self.interface_nm_sum(),
+            self.class_coa(),
+            self.interface_coa(),
+            self.total_npm(),
+            self.total_nm(),
+            self.total_coa()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Npm` metric into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        self.class_npm_sum += other.class_npm_sum;
+        self.interface_npm_sum += other.interface_npm_sum;
+        self.class_nm_sum += other.class_nm_sum;
+        self.interface_nm_sum += other.interface_nm_sum;
+    }
+
+    /// Returns the number of class public methods in a space.
+    #[inline(always)]
+    pub fn class_npm(&self) -> f64 {
+        self.class_npm as f64
+    }
+
+    /// Returns the number of interface public methods in a space.
+    #[inline(always)]
+    pub fn interface_npm(&self) -> f64 {
+        self.interface_npm as f64
+    }
+
+    /// Returns the number of class methods in a space.
+    #[inline(always)]
+    pub fn class_nm(&self) -> f64 {
+        self.class_nm as f64
+    }
+
+    /// Returns the number of interface methods in a space.
+    #[inline(always)]
+    pub fn interface_nm(&self) -> f64 {
+        self.interface_nm as f64
+    }
+
+    /// Returns the number of class public methods sum in a space.
+    #[inline(always)]
+    pub fn class_npm_sum(&self) -> f64 {
+        self.class_npm_sum as f64
+    }
+
+    /// Returns the number of interface public methods sum in a space.
+    #[inline(always)]
+    pub fn interface_npm_sum(&self) -> f64 {
+        self.interface_npm_sum as f64
+    }
+
+    /// Returns the number of class methods sum in a space.
+    #[inline(always)]
+    pub fn class_nm_sum(&self) -> f64 {
+        self.class_nm_sum as f64
+    }
+
+    /// Returns the number of interface methods sum in a space.
+    #[inline(always)]
+    pub fn interface_nm_sum(&self) -> f64 {
+        self.interface_nm_sum as f64
+    }
+
+    /// Returns the class `Coa` metric value
+    ///
+    /// The `Class Operation Accessibility` metric value for a class
+    /// is computed by dividing the `Npm` value of the class
+    /// by the total number of methods defined in the class.
+    ///
+    /// This metric is an adaptation of the `Classified Operation Accessibility` (`COA`)
+    /// security metric for not classified methods.
+    /// Paper: 
+    #[inline(always)]
+    pub fn class_coa(&self) -> f64 {
+        self.class_npm_sum() / self.class_nm_sum()
+    }
+
+    /// Returns the interface `Coa` metric value
+    ///
+    /// The `Class Operation Accessibility` metric value for an interface
+    /// is computed by dividing the `Npm` value of the interface
+    /// by the total number of methods defined in the interface.
+    ///
+    /// This metric is an adaptation of the `Classified Operation Accessibility` (`COA`)
+    /// security metric for not classified methods.
+    /// Paper: 
+    #[inline(always)]
+    pub fn interface_coa(&self) -> f64 {
+        // For the Java language it's not necessary to compute the metric value
+        // The metric value in Java can only be 1.0 or f64:NAN
+        if self.interface_npm_sum == self.interface_nm_sum && self.interface_npm_sum != 0 {
+            1.0
+        } else {
+            self.interface_npm_sum() / self.interface_nm_sum()
+        }
+    }
+
+    /// Returns the total `Coa` metric value
+    ///
+    /// The total `Class Operation Accessibility` metric value
+    /// is computed by dividing the total `Npm` value
+    /// by the total number of methods.
+    ///
+    /// This metric is an adaptation of the `Classified Operation Accessibility` (`COA`)
+    /// security metric for not classified methods.
+    /// Paper: 
+    #[inline(always)]
+    pub fn total_coa(&self) -> f64 {
+        self.total_npm() / self.total_nm()
+    }
+
+    /// Returns the total number of public methods in a space.
+    #[inline(always)]
+    pub fn total_npm(&self) -> f64 {
+        self.class_npm_sum() + self.interface_npm_sum()
+    }
+
+    /// Returns the total number of methods in a space.
+    #[inline(always)]
+    pub fn total_nm(&self) -> f64 {
+        self.class_nm_sum() + self.interface_nm_sum()
+    }
+
+    // Accumulates the number of class and interface
+    // public and not public methods into the sums
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.class_npm_sum += self.class_npm;
+        self.interface_npm_sum += self.interface_npm;
+        self.class_nm_sum += self.class_nm;
+        self.interface_nm_sum += self.interface_nm;
+    }
+
+    // Checks if the `Npm` metric is disabled
+    #[inline(always)]
+    pub(crate) fn is_disabled(&self) -> bool {
+        !self.is_class_space
+    }
+}
+
+pub trait Npm
+where
+    Self: Checker,
+{
+    fn compute(node: &Node, stats: &mut Stats);
+}
+
+implement_metric_trait!(Npm, PythonCode, TypescriptCode, TsxCode, RustCode, GoCode);
diff --git a/src/metrics/wmc.rs b/src/metrics/wmc.rs
new file mode 100644
index 00000000..f6296b39
--- /dev/null
+++ b/src/metrics/wmc.rs
@@ -0,0 +1,127 @@
+use serde::Serialize;
+use serde::ser::{SerializeStruct, Serializer};
+use std::fmt;
+
+use crate::checker::Checker;
+use crate::macros::implement_metric_trait;
+use crate::*;
+
+// FIX ME: New Java switches are not correctly recognised by tree-sitter-java version 0.19.0
+// However, the issue has already been addressed and resolved upstream on the tree-sitter-java GitHub repository
+// Upstream issue: https://github.com/tree-sitter/tree-sitter-java/issues/69
+// Upstream PR which resolves the issue: https://github.com/tree-sitter/tree-sitter-java/pull/78
+
+/// The `Wmc` metric.
+///
+/// This metric sums the cyclomatic complexities of all the methods defined in a class.
+/// The `Wmc` (Weighted Methods per Class) is an object-oriented metric for classes.
+///
+/// Original paper and definition:
+/// 
+#[derive(Debug, Clone, Default)]
+pub struct Stats {
+    cyclomatic: f64,
+    class_wmc: f64,
+    interface_wmc: f64,
+    class_wmc_sum: f64,
+    interface_wmc_sum: f64,
+    space_kind: SpaceKind,
+}
+
+impl Serialize for Stats {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let mut st = serializer.serialize_struct("wmc", 3)?;
+        st.serialize_field("classes", &self.class_wmc_sum())?;
+        st.serialize_field("interfaces", &self.interface_wmc_sum())?;
+        st.serialize_field("total", &self.total_wmc())?;
+        st.end()
+    }
+}
+
+impl fmt::Display for Stats {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "classes: {}, interfaces: {}, total: {}",
+            self.class_wmc_sum(),
+            self.interface_wmc_sum(),
+            self.total_wmc()
+        )
+    }
+}
+
+impl Stats {
+    /// Merges a second `Wmc` metric into the first one
+    pub fn merge(&mut self, other: &Stats) {
+        use SpaceKind::*;
+
+        // Merges the cyclomatic complexity of a method
+        // into the `Wmc` metric value of a class or interface
+        if let Function = other.space_kind {
+            match self.space_kind {
+                Class => self.class_wmc += other.cyclomatic,
+                Interface => self.interface_wmc += other.cyclomatic,
+                _ => {}
+            }
+        }
+
+        self.class_wmc_sum += other.class_wmc_sum;
+        self.interface_wmc_sum += other.interface_wmc_sum;
+    }
+
+    /// Returns the `Wmc` metric value of the classes in a space.
+    #[inline(always)]
+    pub fn class_wmc(&self) -> f64 {
+        self.class_wmc
+    }
+
+    /// Returns the `Wmc` metric value of the interfaces in a space.
+    #[inline(always)]
+    pub fn interface_wmc(&self) -> f64 {
+        self.interface_wmc
+    }
+
+    /// Returns the sum of the `Wmc` metric values of the classes in a space.
+    #[inline(always)]
+    pub fn class_wmc_sum(&self) -> f64 {
+        self.class_wmc_sum
+    }
+
+    /// Returns the sum of the `Wmc` metric values of the interfaces in a space.
+    #[inline(always)]
+    pub fn interface_wmc_sum(&self) -> f64 {
+        self.interface_wmc_sum
+    }
+
+    /// Returns the total `Wmc` metric value in a space.
+    #[inline(always)]
+    pub fn total_wmc(&self) -> f64 {
+        self.class_wmc_sum() + self.interface_wmc_sum()
+    }
+
+    // Accumulates the `Wmc` metric values
+    // of classes and interfaces into the sums
+    #[inline(always)]
+    pub(crate) fn compute_sum(&mut self) {
+        self.class_wmc_sum += self.class_wmc;
+        self.interface_wmc_sum += self.interface_wmc;
+    }
+
+    // Checks if the `Wmc` metric is disabled
+    #[inline(always)]
+    pub(crate) fn is_disabled(&self) -> bool {
+        matches!(self.space_kind, SpaceKind::Function | SpaceKind::Unknown)
+    }
+}
+
+pub trait Wmc
+where
+    Self: Checker,
+{
+    fn compute(space_kind: SpaceKind, cyclomatic: &cyclomatic::Stats, stats: &mut Stats);
+}
+
+implement_metric_trait!(Wmc, PythonCode, TypescriptCode, TsxCode, RustCode, GoCode);
diff --git a/src/node.rs b/src/node.rs
new file mode 100644
index 00000000..48c4698d
--- /dev/null
+++ b/src/node.rs
@@ -0,0 +1,232 @@
+use tree_sitter::Node as OtherNode;
+use tree_sitter::Tree as OtherTree;
+use tree_sitter::{Parser, TreeCursor};
+
+use crate::checker::Checker;
+use crate::traits::{LanguageInfo, Search};
+
+#[derive(Clone, Debug)]
+pub(crate) struct Tree(OtherTree);
+
+impl Tree {
+    pub(crate) fn new(code: &[u8]) -> Self {
+        let mut parser = Parser::new();
+        parser
+            .set_language(&T::get_lang().get_ts_language())
+            .unwrap();
+
+        Self(parser.parse(code, None).unwrap())
+    }
+
+    pub(crate) fn get_root(&self) -> Node<'_> {
+        Node(self.0.root_node())
+    }
+}
+
+/// An `AST` node.
+///
+/// The inner `tree_sitter::Node` is exposed for advanced use cases
+/// where direct access to the underlying tree-sitter API is needed.
+#[derive(Clone, Copy, Debug)]
+pub struct Node<'a>(pub OtherNode<'a>);
+
+impl<'a> Node<'a> {
+    /// Checks if a node represents a syntax error or contains any syntax errors
+    /// anywhere within it.
+    pub fn has_error(&self) -> bool {
+        self.0.has_error()
+    }
+
+    pub(crate) fn id(&self) -> usize {
+        self.0.id()
+    }
+
+    pub(crate) fn kind(&self) -> &'static str {
+        self.0.kind()
+    }
+
+    pub(crate) fn kind_id(&self) -> u16 {
+        self.0.kind_id()
+    }
+
+    pub(crate) fn start_byte(&self) -> usize {
+        self.0.start_byte()
+    }
+
+    pub(crate) fn end_byte(&self) -> usize {
+        self.0.end_byte()
+    }
+
+    pub(crate) fn start_position(&self) -> (usize, usize) {
+        let temp = self.0.start_position();
+        (temp.row, temp.column)
+    }
+
+    pub(crate) fn end_position(&self) -> (usize, usize) {
+        let temp = self.0.end_position();
+        (temp.row, temp.column)
+    }
+
+    pub(crate) fn start_row(&self) -> usize {
+        self.0.start_position().row
+    }
+
+    pub(crate) fn end_row(&self) -> usize {
+        self.0.end_position().row
+    }
+
+    pub(crate) fn parent(&self) -> Option> {
+        self.0.parent().map(Node)
+    }
+
+    #[inline(always)]
+    pub(crate) fn has_sibling(&self, id: u16) -> bool {
+        self.0.parent().is_some_and(|parent| {
+            self.0
+                .children(&mut parent.walk())
+                .any(|child| child.kind_id() == id)
+        })
+    }
+
+    pub(crate) fn next_sibling(&self) -> Option> {
+        self.0.next_sibling().map(Node)
+    }
+
+    #[inline(always)]
+    pub(crate) fn is_child(&self, id: u16) -> bool {
+        self.0
+            .children(&mut self.0.walk())
+            .any(|child| child.kind_id() == id)
+    }
+
+    pub(crate) fn child_count(&self) -> usize {
+        self.0.child_count()
+    }
+
+    pub(crate) fn child_by_field_name(&self, name: &str) -> Option> {
+        self.0.child_by_field_name(name).map(Node)
+    }
+
+    pub(crate) fn child(&self, pos: usize) -> Option> {
+        self.0.child(pos).map(Node)
+    }
+
+    pub(crate) fn children(&self) -> impl ExactSizeIterator> + use<'a> {
+        let mut cursor = self.cursor();
+        cursor.goto_first_child();
+        (0..self.child_count()).map(move |_| {
+            let result = cursor.node();
+            cursor.goto_next_sibling();
+            result
+        })
+    }
+
+    pub(crate) fn cursor(&self) -> Cursor<'a> {
+        Cursor(self.0.walk())
+    }
+
+    #[allow(dead_code)]
+    pub(crate) fn get_parent(&self, level: usize) -> Option> {
+        let mut level = level;
+        let mut node = *self;
+        while level != 0 {
+            if let Some(parent) = node.parent() {
+                node = parent;
+            } else {
+                return None;
+            }
+            level -= 1;
+        }
+
+        Some(node)
+    }
+
+    pub(crate) fn count_specific_ancestors(
+        &self,
+        check: fn(&Node) -> bool,
+        stop: fn(&Node) -> bool,
+    ) -> usize {
+        let mut count = 0;
+        let mut node = *self;
+        while let Some(parent) = node.parent() {
+            if stop(&parent) {
+                break;
+            }
+            if check(&parent) && !T::Checker::is_else_if(&parent) {
+                count += 1;
+            }
+            node = parent;
+        }
+        count
+    }
+
+    pub(crate) fn has_ancestors(&self, typ: fn(&Node) -> bool, typs: fn(&Node) -> bool) -> bool {
+        let mut res = false;
+        let mut node = *self;
+        if let Some(parent) = node.parent()
+            && typ(&parent)
+        {
+            node = parent;
+        }
+        if let Some(parent) = node.parent()
+            && typs(&parent)
+        {
+            res = true;
+        }
+        res
+    }
+}
+
+/// An `AST` cursor.
+#[derive(Clone)]
+pub struct Cursor<'a>(TreeCursor<'a>);
+
+impl<'a> Cursor<'a> {
+    pub(crate) fn reset(&mut self, node: &Node<'a>) {
+        self.0.reset(node.0);
+    }
+
+    pub(crate) fn goto_next_sibling(&mut self) -> bool {
+        self.0.goto_next_sibling()
+    }
+
+    pub(crate) fn goto_first_child(&mut self) -> bool {
+        self.0.goto_first_child()
+    }
+
+    pub(crate) fn node(&self) -> Node<'a> {
+        Node(self.0.node())
+    }
+}
+
+impl<'a> Search<'a> for Node<'a> {
+    fn act_on_node(&self, action: &mut dyn FnMut(&Node<'a>)) {
+        let mut cursor = self.cursor();
+        let mut stack = Vec::new();
+        let mut children = Vec::new();
+
+        stack.push(*self);
+
+        while let Some(node) = stack.pop() {
+            action(&node);
+            cursor.reset(&node);
+            if cursor.goto_first_child() {
+                loop {
+                    children.push(cursor.node());
+                    if !cursor.goto_next_sibling() {
+                        break;
+                    }
+                }
+                for child in children.drain(..).rev() {
+                    stack.push(child);
+                }
+            }
+        }
+    }
+
+    fn act_on_child(&self, action: &mut dyn FnMut(&Node<'a>)) {
+        for child in self.children() {
+            action(&child);
+        }
+    }
+}
diff --git a/src/ops.rs b/src/ops.rs
new file mode 100644
index 00000000..11eb42d7
--- /dev/null
+++ b/src/ops.rs
@@ -0,0 +1,485 @@
+use std::collections::HashSet;
+use std::path::{Path, PathBuf};
+
+use serde::Serialize;
+
+use crate::checker::Checker;
+use crate::getter::Getter;
+use crate::node::Node;
+use crate::spaces::SpaceKind;
+
+use crate::halstead::{Halstead, HalsteadMaps};
+
+use crate::dump_ops::*;
+use crate::traits::*;
+
+/// All operands and operators of a space.
+#[derive(Debug, Clone, Serialize)]
+pub struct Ops {
+    /// The name of a function space.
+    ///
+    /// If `None`, an error is occurred in parsing
+    /// the name of a function space.
+    pub name: Option,
+    /// The first line of a function space.
+    pub start_line: usize,
+    /// The last line of a function space.
+    pub end_line: usize,
+    /// The space kind.
+    pub kind: SpaceKind,
+    /// All subspaces contained in a function space.
+    pub spaces: Vec,
+    /// All operands of a space.
+    pub operands: Vec,
+    /// All operators of a space.
+    pub operators: Vec,
+}
+
+impl Ops {
+    fn new(node: &Node, code: &[u8], kind: SpaceKind) -> Self {
+        let (start_position, end_position) = match kind {
+            SpaceKind::Unit => {
+                if node.child_count() == 0 {
+                    (0, 0)
+                } else {
+                    (node.start_row() + 1, node.end_row())
+                }
+            }
+            _ => (node.start_row() + 1, node.end_row() + 1),
+        };
+        Self {
+            name: T::get_func_space_name(node, code).map(|name| name.to_string()),
+            spaces: Vec::new(),
+            kind,
+            start_line: start_position,
+            end_line: end_position,
+            operators: Vec::new(),
+            operands: Vec::new(),
+        }
+    }
+
+    pub(crate) fn merge_ops(&mut self, other: &Ops) {
+        self.operands.extend_from_slice(&other.operands);
+        self.operators.extend_from_slice(&other.operators);
+    }
+}
+
+#[derive(Debug, Clone)]
+struct State<'a> {
+    ops: Ops,
+    halstead_maps: HalsteadMaps<'a>,
+    primitive_types: HashSet,
+}
+
+fn compute_operators_and_operands(state: &mut State) {
+    state.ops.operators = state
+        .halstead_maps
+        .operators
+        .keys()
+        .filter(|k| !T::Checker::is_primitive(**k))
+        .map(|k| T::Getter::get_operator_id_as_str(*k).to_owned())
+        .collect();
+
+    // Add primitive types to operators
+    let v: Vec<_> = state.primitive_types.iter().cloned().collect();
+    state.ops.operators.extend_from_slice(&v);
+    println!("{:?}", state.ops.operators);
+    println!("{:?}", state.halstead_maps.operators);
+
+    state.ops.operands = state
+        .halstead_maps
+        .operands
+        .keys()
+        .map(|k| String::from_utf8(k.to_vec()).unwrap_or_else(|_| String::from("wrong_operands")))
+        .collect();
+}
+
+fn finalize(state_stack: &mut Vec, diff_level: usize) {
+    if state_stack.is_empty() {
+        return;
+    }
+
+    // If there is only the unit space
+    if state_stack.len() == 1 {
+        let last_state = state_stack.last_mut().unwrap();
+        // Compute last_state operators and operands
+        compute_operators_and_operands::(last_state);
+    }
+
+    for _ in 0..diff_level {
+        if state_stack.len() == 1 {
+            break;
+        } else {
+            let mut state = state_stack.pop().unwrap();
+            let last_state = state_stack.last_mut().unwrap();
+
+            // Compute state operators and operands
+            compute_operators_and_operands::(&mut state);
+
+            // Compute last_state operators and operands
+            compute_operators_and_operands::(last_state);
+
+            // Merge Halstead maps
+            last_state.halstead_maps.merge(&state.halstead_maps);
+
+            // Merge operands and operators between spaces
+            last_state.ops.merge_ops(&state.ops);
+            last_state.ops.spaces.push(state.ops);
+        }
+    }
+}
+
+/// Retrieves all the operators and operands of a code.
+///
+/// If `None`, it was not possible to retrieve the operators and operands
+/// of a code.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::PathBuf;
+///
+/// use mehen::{operands_and_operators, RustParser, ParserTrait};
+///
+/// # fn main() {
+/// let source_code = "fn main() { let a = 42; }";
+///
+/// let path = PathBuf::from("foo.rs");
+/// let source_as_vec = source_code.as_bytes().to_vec();
+///
+/// let parser = RustParser::new(source_as_vec, &path, None);
+///
+/// // Returns the operands and operators of each space in a code.
+/// operands_and_operators(&parser, &path).unwrap();
+/// # }
+/// ```
+pub fn operands_and_operators<'a, T: ParserTrait>(parser: &'a T, path: &'a Path) -> Option {
+    let code = parser.get_code();
+    let node = parser.get_root();
+    let mut cursor = node.cursor();
+    let mut stack = Vec::new();
+    let mut children = Vec::new();
+    let mut state_stack: Vec = Vec::new();
+    let mut last_level = 0;
+
+    stack.push((node, 0));
+
+    while let Some((node, level)) = stack.pop() {
+        if level < last_level {
+            finalize::(&mut state_stack, last_level - level);
+            last_level = level;
+        }
+
+        let kind = T::Getter::get_space_kind(&node);
+
+        let func_space = T::Checker::is_func(&node) || T::Checker::is_func_space(&node);
+
+        let new_level = if func_space {
+            let state = State {
+                ops: Ops::new::(&node, code, kind),
+                halstead_maps: HalsteadMaps::new(),
+                primitive_types: HashSet::new(),
+            };
+            state_stack.push(state);
+            last_level = level + 1;
+            last_level
+        } else {
+            level
+        };
+
+        if let Some(state) = state_stack.last_mut() {
+            T::Halstead::compute(&node, code, &mut state.halstead_maps);
+            if T::Checker::is_primitive(node.kind_id()) {
+                let code = &code[node.start_byte()..node.end_byte()];
+                let primitive_string = String::from_utf8(code.to_vec())
+                    .unwrap_or_else(|_| String::from("primitive_type"));
+                state.primitive_types.insert(primitive_string);
+            }
+        }
+
+        cursor.reset(&node);
+        if cursor.goto_first_child() {
+            loop {
+                children.push((cursor.node(), new_level));
+                if !cursor.goto_next_sibling() {
+                    break;
+                }
+            }
+            for child in children.drain(..).rev() {
+                stack.push(child);
+            }
+        }
+    }
+
+    finalize::(&mut state_stack, usize::MAX);
+
+    state_stack.pop().map(|mut state| {
+        state.ops.name = path.to_str().map(|name| name.to_string());
+        state.ops
+    })
+}
+
+/// Configuration options for retrieving
+/// all the operands and operators in a code.
+#[derive(Debug)]
+pub struct OpsCfg {
+    /// Path to the file containing the code.
+    pub path: PathBuf,
+}
+
+pub struct OpsCode {
+    _guard: (),
+}
+
+impl Callback for OpsCode {
+    type Res = std::io::Result<()>;
+    type Cfg = OpsCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        if let Some(ops) = operands_and_operators(parser, &cfg.path) {
+            dump_ops(&ops)
+        } else {
+            Ok(())
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::path::PathBuf;
+
+    use crate::{LANG, get_ops};
+
+    #[inline(always)]
+    fn check_ops(
+        lang: LANG,
+        source: &str,
+        file: &str,
+        correct_operators: &mut [&str],
+        correct_operands: &mut [&str],
+    ) {
+        let path = PathBuf::from(file);
+        let mut trimmed_bytes = source.trim_end().trim_matches('\n').as_bytes().to_vec();
+        trimmed_bytes.push(b'\n');
+        let ops = get_ops(&lang, trimmed_bytes, &path, None).unwrap();
+
+        let mut operators_str: Vec<&str> = ops.operators.iter().map(AsRef::as_ref).collect();
+        let mut operands_str: Vec<&str> = ops.operands.iter().map(AsRef::as_ref).collect();
+
+        // Sorting out operators because they are returned in arbitrary order
+        operators_str.sort_unstable();
+        correct_operators.sort_unstable();
+
+        assert_eq!(&operators_str[..], correct_operators);
+
+        // Sorting out operands because they are returned in arbitrary order
+        operands_str.sort_unstable();
+        correct_operands.sort_unstable();
+
+        assert_eq!(&operands_str[..], correct_operands);
+    }
+
+    #[test]
+    fn python_ops() {
+        check_ops(
+            LANG::Python,
+            "if True:
+                 a = 1 + 2",
+            "foo.py",
+            &mut ["if", "=", "+"],
+            &mut ["True", "a", "1", "2"],
+        );
+    }
+
+    #[test]
+    fn python_function_ops() {
+        check_ops(
+            LANG::Python,
+            "def foo():
+                 def bar():
+                     def toto():
+                        a = 1 + 1
+                     b = 2 + a
+                 c = 3 + 3",
+            "foo.py",
+            &mut ["def", "=", "+"],
+            &mut ["foo", "bar", "toto", "a", "b", "c", "1", "2", "3"],
+        );
+    }
+
+    #[test]
+    fn rust_ops() {
+        check_ops(
+            LANG::Rust,
+            "let: usize a = 5; let b: f32 = 7.0; let c: i32 = 3;",
+            "foo.rs",
+            &mut ["let", "usize", "=", ";", "f32", "i32"],
+            &mut ["a", "b", "c", "5", "7.0", "3"],
+        );
+    }
+
+    #[test]
+    fn rust_function_ops() {
+        check_ops(
+            LANG::Rust,
+            "fn main() {
+              let a = 5; let b = 5; let c = 5;
+              let avg = (a + b + c) / 3;
+              println!(\"{}\", avg);
+            }",
+            "foo.rs",
+            &mut ["fn", "()", "{}", "let", "=", "+", "/", ";", "!", ","],
+            &mut ["main", "a", "b", "c", "avg", "5", "3", "println", "\"{}\""],
+        );
+    }
+
+    #[test]
+    fn typescript_ops() {
+        check_ops(
+            LANG::Typescript,
+            "var a, b, c, avg;
+             let age: number = 32;
+             let name: string = \"John\"; let isUpdated: boolean = true;
+             a = 5; b = 5; c = 5;
+             avg = (a + b + c) / 3;
+             console.log(\"{}\", avg);",
+            "foo.ts",
+            &mut [
+                "()", "var", "let", "string", "number", "boolean", ":", "=", "+", "/", ",", ".",
+                ";",
+            ],
+            &mut [
+                "a",
+                "b",
+                "c",
+                "avg",
+                "age",
+                "name",
+                "isUpdated",
+                "32",
+                "\"John\"",
+                "true",
+                "3",
+                "5",
+                "console.log",
+                "console",
+                "log",
+                "\"{}\"",
+            ],
+        );
+    }
+
+    #[test]
+    fn typescript_function_ops() {
+        check_ops(
+            LANG::Typescript,
+            "function main() {
+              var a, b, c, avg;
+              let age: number = 32;
+              let name: string = \"John\"; let isUpdated: boolean = true;
+              a = 5; b = 5; c = 5;
+              avg = (a + b + c) / 3;
+              console.log(\"{}\", avg);
+            }",
+            "foo.ts",
+            &mut [
+                "function", "()", "{}", "var", "let", "string", "number", "boolean", ":", "=", "+",
+                "/", ",", ".", ";",
+            ],
+            &mut [
+                "main",
+                "a",
+                "b",
+                "c",
+                "avg",
+                "age",
+                "name",
+                "isUpdated",
+                "32",
+                "\"John\"",
+                "true",
+                "3",
+                "5",
+                "console.log",
+                "console",
+                "log",
+                "\"{}\"",
+            ],
+        );
+    }
+
+    #[test]
+    fn tsx_ops() {
+        check_ops(
+            LANG::Tsx,
+            "var a, b, c, avg;
+             let age: number = 32;
+             let name: string = \"John\"; let isUpdated: boolean = true;
+             a = 5; b = 5; c = 5;
+             avg = (a + b + c) / 3;
+             console.log(\"{}\", avg);",
+            "foo.ts",
+            &mut [
+                "()", "var", "let", "string", "number", "boolean", ":", "=", "+", "/", ",", ".",
+                ";",
+            ],
+            &mut [
+                "a",
+                "b",
+                "c",
+                "avg",
+                "age",
+                "name",
+                "isUpdated",
+                "32",
+                "\"John\"",
+                "true",
+                "3",
+                "5",
+                "console.log",
+                "console",
+                "log",
+                "\"{}\"",
+            ],
+        );
+    }
+
+    #[test]
+    fn tsx_function_ops() {
+        check_ops(
+            LANG::Tsx,
+            "function main() {
+              var a, b, c, avg;
+              let age: number = 32;
+              let name: string = \"John\"; let isUpdated: boolean = true;
+              a = 5; b = 5; c = 5;
+              avg = (a + b + c) / 3;
+              console.log(\"{}\", avg);
+            }",
+            "foo.ts",
+            &mut [
+                "function", "()", "{}", "var", "let", "string", "number", "boolean", ":", "=", "+",
+                "/", ",", ".", ";",
+            ],
+            &mut [
+                "main",
+                "a",
+                "b",
+                "c",
+                "avg",
+                "age",
+                "name",
+                "isUpdated",
+                "32",
+                "\"John\"",
+                "true",
+                "3",
+                "5",
+                "console.log",
+                "console",
+                "log",
+                "\"{}\"",
+            ],
+        );
+    }
+}
diff --git a/src/output/dump.rs b/src/output/dump.rs
new file mode 100644
index 00000000..40bacc53
--- /dev/null
+++ b/src/output/dump.rs
@@ -0,0 +1,188 @@
+use std::io::Write;
+
+use termcolor::{Color, ColorChoice, StandardStream, StandardStreamLock};
+
+use crate::node::Node;
+use crate::tools::{color, intense_color};
+
+use crate::traits::*;
+
+/// Dumps the `AST` of a code.
+///
+/// Returns a [`Result`] value, when an error occurs.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::PathBuf;
+///
+/// use mehen::{dump_node, RustParser, ParserTrait};
+///
+/// let source_code = "fn main() { let a = 42; }";
+///
+/// let path = PathBuf::from("foo.rs");
+/// let source_as_vec = source_code.as_bytes().to_vec();
+///
+/// let parser = RustParser::new(source_as_vec.clone(), &path, None);
+///
+/// let root = parser.get_root();
+///
+/// dump_node(&source_as_vec, &root, -1, None, None).unwrap();
+/// ```
+///
+/// [`Result`]: #variant.Result
+pub fn dump_node(
+    code: &[u8],
+    node: &Node,
+    depth: i32,
+    line_start: Option,
+    line_end: Option,
+) -> std::io::Result<()> {
+    let stdout = StandardStream::stdout(ColorChoice::Always);
+    let mut stdout = stdout.lock();
+    let ret = dump_tree_helper(
+        code,
+        node,
+        "",
+        true,
+        &mut stdout,
+        depth,
+        &line_start,
+        &line_end,
+    );
+
+    color(&mut stdout, Color::White)?;
+
+    ret
+}
+
+#[allow(clippy::too_many_arguments)]
+fn dump_tree_helper(
+    code: &[u8],
+    node: &Node,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+    depth: i32,
+    line_start: &Option,
+    line_end: &Option,
+) -> std::io::Result<()> {
+    if depth == 0 {
+        return Ok(());
+    }
+
+    let (pref_child, pref) = if node.parent().is_none() {
+        ("", "")
+    } else if last {
+        ("   ", "╰─ ")
+    } else {
+        ("│  ", "├─ ")
+    };
+
+    let node_row = node.start_row() + 1;
+    let mut display = true;
+    if let Some(line_start) = line_start {
+        display = node_row >= *line_start
+    }
+    if let Some(line_end) = line_end {
+        display = display && node_row <= *line_end
+    }
+
+    if display {
+        color(stdout, Color::Blue)?;
+        write!(stdout, "{prefix}{pref}")?;
+
+        intense_color(stdout, Color::Yellow)?;
+        write!(stdout, "{{{}:{}}} ", node.kind(), node.kind_id())?;
+
+        color(stdout, Color::White)?;
+        write!(stdout, "from ")?;
+
+        color(stdout, Color::Green)?;
+        let (pos_row, pos_column) = node.start_position();
+        write!(stdout, "({}, {}) ", pos_row + 1, pos_column + 1)?;
+
+        color(stdout, Color::White)?;
+        write!(stdout, "to ")?;
+
+        color(stdout, Color::Green)?;
+        let (pos_row, pos_column) = node.end_position();
+        write!(stdout, "({}, {}) ", pos_row + 1, pos_column + 1)?;
+
+        if node.start_row() == node.end_row() {
+            color(stdout, Color::White)?;
+            write!(stdout, ": ")?;
+
+            intense_color(stdout, Color::Red)?;
+            let code = &code[node.start_byte()..node.end_byte()];
+            if let Ok(code) = String::from_utf8(code.to_vec()) {
+                write!(stdout, "{code} ")?;
+            } else {
+                stdout.write_all(code).unwrap();
+            }
+        }
+
+        writeln!(stdout)?;
+    }
+
+    let count = node.child_count();
+    if count != 0 {
+        let prefix = format!("{prefix}{pref_child}");
+        let mut i = count;
+        let mut cursor = node.cursor();
+        cursor.goto_first_child();
+
+        loop {
+            i -= 1;
+            dump_tree_helper(
+                code,
+                &cursor.node(),
+                &prefix,
+                i == 0,
+                stdout,
+                depth - 1,
+                line_start,
+                line_end,
+            )?;
+            if !cursor.goto_next_sibling() {
+                break;
+            }
+        }
+    }
+
+    Ok(())
+}
+
+/// Configuration options for dumping the `AST` of a code.
+#[derive(Debug)]
+pub struct DumpCfg {
+    /// The first line of code to dump
+    ///
+    /// If `None`, the code is dumped from the first line of code
+    /// in a file
+    pub line_start: Option,
+    /// The last line of code to dump
+    ///
+    /// If `None`, the code is dumped until the last line of code
+    /// in a file
+    pub line_end: Option,
+}
+
+pub struct Dump {
+    _guard: (),
+}
+
+impl Callback for Dump {
+    type Res = std::io::Result<()>;
+    type Cfg = DumpCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        dump_node(
+            parser.get_code(),
+            &parser.get_root(),
+            -1,
+            cfg.line_start,
+            cfg.line_end,
+        )
+    }
+}
diff --git a/src/output/dump_metrics.rs b/src/output/dump_metrics.rs
new file mode 100644
index 00000000..e5e88ea9
--- /dev/null
+++ b/src/output/dump_metrics.rs
@@ -0,0 +1,439 @@
+use std::io::Write;
+use termcolor::{Color, ColorChoice, StandardStream, StandardStreamLock};
+
+use crate::abc;
+use crate::cognitive;
+use crate::cyclomatic;
+use crate::exit;
+use crate::halstead;
+use crate::loc;
+use crate::mi;
+use crate::nargs;
+use crate::nom;
+use crate::npa;
+use crate::npm;
+use crate::wmc;
+
+use crate::spaces::{CodeMetrics, FuncSpace};
+
+use crate::tools::{color, intense_color};
+
+/// Dumps the metrics of a code.
+///
+/// Returns a [`Result`] value, when an error occurs.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::PathBuf;
+///
+/// use mehen::{dump_root, metrics, RustParser, ParserTrait};
+///
+/// let source_code = "fn main() { let a = 42; }";
+///
+/// let path = PathBuf::from("foo.rs");
+/// let source_as_vec = source_code.as_bytes().to_vec();
+///
+/// let parser = RustParser::new(source_as_vec, &path, None);
+///
+/// let space = metrics(&parser, &path).unwrap();
+///
+/// dump_root(&space).unwrap();
+/// ```
+///
+/// [`Result`]: #variant.Result
+pub fn dump_root(space: &FuncSpace) -> std::io::Result<()> {
+    let stdout = StandardStream::stdout(ColorChoice::Always);
+    let mut stdout = stdout.lock();
+    dump_space(space, "", true, &mut stdout)?;
+    color(&mut stdout, Color::White)?;
+
+    Ok(())
+}
+
+fn dump_space(
+    space: &FuncSpace,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Yellow)?;
+    write!(stdout, "{}: ", space.kind)?;
+
+    intense_color(stdout, Color::Cyan)?;
+    write!(stdout, "{}", space.name.as_ref().map_or("", |name| name))?;
+
+    intense_color(stdout, Color::Red)?;
+    writeln!(stdout, " (@{})", space.start_line)?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_metrics(&space.metrics, &prefix, space.spaces.is_empty(), stdout)?;
+
+    if let Some((last, spaces)) = space.spaces.split_last() {
+        for space in spaces {
+            dump_space(space, &prefix, false, stdout)?;
+        }
+        dump_space(last, &prefix, true, stdout)?;
+    }
+
+    Ok(())
+}
+
+fn dump_metrics(
+    metrics: &CodeMetrics,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Yellow)?;
+    writeln!(stdout, "metrics")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_cognitive(&metrics.cognitive, &prefix, false, stdout)?;
+    dump_cyclomatic(&metrics.cyclomatic, &prefix, false, stdout)?;
+    dump_nargs(&metrics.nargs, &prefix, false, stdout)?;
+    dump_nexits(&metrics.nexits, &prefix, false, stdout)?;
+    dump_halstead(&metrics.halstead, &prefix, false, stdout)?;
+    dump_loc(&metrics.loc, &prefix, false, stdout)?;
+    dump_nom(&metrics.nom, &prefix, false, stdout)?;
+    dump_mi(&metrics.mi, &prefix, false, stdout)?;
+    dump_abc(&metrics.abc, &prefix, false, stdout)?;
+    dump_wmc(&metrics.wmc, &prefix, false, stdout)?;
+    dump_npm(&metrics.npm, &prefix, false, stdout)?;
+    dump_npa(&metrics.npa, &prefix, true, stdout)
+}
+
+fn dump_cognitive(
+    stats: &cognitive::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "cognitive")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+
+    dump_value("sum", stats.cognitive(), &prefix, false, stdout)?;
+    dump_value("average", stats.cognitive_average(), &prefix, true, stdout)
+}
+
+fn dump_cyclomatic(
+    stats: &cyclomatic::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "cyclomatic")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+
+    dump_value("sum", stats.cyclomatic(), &prefix, false, stdout)?;
+    dump_value("average", stats.cyclomatic_average(), &prefix, true, stdout)
+}
+
+fn dump_halstead(
+    stats: &halstead::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "halstead")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+
+    dump_value("n1", stats.u_operators(), &prefix, false, stdout)?;
+    dump_value("N1", stats.operators(), &prefix, false, stdout)?;
+    dump_value("n2", stats.u_operands(), &prefix, false, stdout)?;
+    dump_value("N2", stats.operands(), &prefix, false, stdout)?;
+
+    dump_value("length", stats.length(), &prefix, false, stdout)?;
+    dump_value(
+        "estimated program length",
+        stats.estimated_program_length(),
+        &prefix,
+        false,
+        stdout,
+    )?;
+    dump_value("purity ratio", stats.purity_ratio(), &prefix, false, stdout)?;
+    dump_value("vocabulary", stats.vocabulary(), &prefix, false, stdout)?;
+    dump_value("volume", stats.volume(), &prefix, false, stdout)?;
+    dump_value("difficulty", stats.difficulty(), &prefix, false, stdout)?;
+    dump_value("level", stats.level(), &prefix, false, stdout)?;
+    dump_value("effort", stats.effort(), &prefix, false, stdout)?;
+    dump_value("time", stats.time(), &prefix, false, stdout)?;
+    dump_value("bugs", stats.bugs(), &prefix, true, stdout)
+}
+
+fn dump_loc(
+    stats: &loc::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "loc")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_value("sloc", stats.sloc(), &prefix, false, stdout)?;
+    dump_value("ploc", stats.ploc(), &prefix, false, stdout)?;
+    dump_value("lloc", stats.lloc(), &prefix, false, stdout)?;
+    dump_value("cloc", stats.cloc(), &prefix, false, stdout)?;
+    dump_value("blank", stats.blank(), &prefix, true, stdout)
+}
+
+fn dump_nom(
+    stats: &nom::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "nom")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_value("functions", stats.functions(), &prefix, false, stdout)?;
+    dump_value("closures", stats.closures(), &prefix, false, stdout)?;
+    dump_value("total", stats.total(), &prefix, true, stdout)
+}
+
+fn dump_mi(
+    stats: &mi::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "mi")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_value("mi_original", stats.mi_original(), &prefix, false, stdout)?;
+    dump_value("mi_sei", stats.mi_sei(), &prefix, false, stdout)?;
+    dump_value(
+        "mi_visual_studio",
+        stats.mi_visual_studio(),
+        &prefix,
+        true,
+        stdout,
+    )
+}
+
+fn dump_nargs(
+    stats: &nargs::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "nargs")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_value("functions", stats.fn_args(), &prefix, false, stdout)?;
+    dump_value("closures", stats.closure_args(), &prefix, false, stdout)?;
+    dump_value("total", stats.nargs_total(), &prefix, false, stdout)?;
+    dump_value("average", stats.nargs_average(), &prefix, true, stdout)
+}
+
+fn dump_nexits(
+    stats: &exit::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let pref = if last { "`- " } else { "|- " };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    write!(stdout, "nexits: ")?;
+
+    color(stdout, Color::White)?;
+    writeln!(stdout, "{}", stats.exit())
+}
+
+fn dump_abc(
+    stats: &abc::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "abc")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+
+    dump_value(
+        "assignments",
+        stats.assignments_sum(),
+        &prefix,
+        false,
+        stdout,
+    )?;
+    dump_value("branches", stats.branches_sum(), &prefix, false, stdout)?;
+    dump_value("conditions", stats.conditions_sum(), &prefix, false, stdout)?;
+    dump_value("magnitude", stats.magnitude_sum(), &prefix, true, stdout)
+}
+
+fn dump_wmc(
+    stats: &wmc::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    if stats.is_disabled() {
+        return Ok(());
+    }
+
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "wmc")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_value("classes", stats.class_wmc_sum(), &prefix, false, stdout)?;
+    dump_value(
+        "interfaces",
+        stats.interface_wmc_sum(),
+        &prefix,
+        false,
+        stdout,
+    )?;
+    dump_value("total", stats.total_wmc(), &prefix, true, stdout)
+}
+
+fn dump_npm(
+    stats: &npm::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    if stats.is_disabled() {
+        return Ok(());
+    }
+
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "npm")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_value("classes", stats.class_npm_sum(), &prefix, false, stdout)?;
+    dump_value(
+        "interfaces",
+        stats.interface_npm_sum(),
+        &prefix,
+        false,
+        stdout,
+    )?;
+    dump_value("total", stats.total_npm(), &prefix, false, stdout)?;
+    dump_value("average", stats.total_coa(), &prefix, true, stdout)
+}
+
+fn dump_npa(
+    stats: &npa::Stats,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    if stats.is_disabled() {
+        return Ok(());
+    }
+
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "npa")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_value("classes", stats.class_npa_sum(), &prefix, false, stdout)?;
+    dump_value(
+        "interfaces",
+        stats.interface_npa_sum(),
+        &prefix,
+        false,
+        stdout,
+    )?;
+    dump_value("total", stats.total_npa(), &prefix, false, stdout)?;
+    dump_value("average", stats.total_cda(), &prefix, true, stdout)
+}
+
+fn dump_value(
+    name: &str,
+    val: f64,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let pref = if last { "`- " } else { "|- " };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Magenta)?;
+    write!(stdout, "{name}: ")?;
+
+    color(stdout, Color::White)?;
+    writeln!(stdout, "{val}")
+}
diff --git a/src/output/dump_ops.rs b/src/output/dump_ops.rs
new file mode 100644
index 00000000..5df68a46
--- /dev/null
+++ b/src/output/dump_ops.rs
@@ -0,0 +1,115 @@
+use std::io::Write;
+use termcolor::{Color, ColorChoice, StandardStream, StandardStreamLock};
+
+use crate::ops::Ops;
+
+use crate::tools::{color, intense_color};
+
+/// Dumps all operands and operators of a code.
+///
+/// Returns a [`Result`] value, when an error occurs.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::PathBuf;
+///
+/// use mehen::{dump_ops, operands_and_operators, RustParser, ParserTrait};
+///
+/// # fn main() {
+/// let source_code = "fn main() { let a = 42; }";
+///
+/// let path = PathBuf::from("foo.rs");
+/// let source_as_vec = source_code.as_bytes().to_vec();
+///
+/// let parser = RustParser::new(source_as_vec, &path, None);
+///
+/// let ops = operands_and_operators(&parser, &path).unwrap();
+///
+/// dump_ops(&ops).unwrap();
+/// # }
+/// ```
+///
+/// [`Result`]: #variant.Result
+pub fn dump_ops(ops: &Ops) -> std::io::Result<()> {
+    let stdout = StandardStream::stdout(ColorChoice::Always);
+    let mut stdout = stdout.lock();
+    dump_space(ops, "", true, &mut stdout)?;
+    color(&mut stdout, Color::White)?;
+
+    Ok(())
+}
+
+fn dump_space(
+    space: &Ops,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Yellow)?;
+    write!(stdout, "{}: ", space.kind)?;
+
+    intense_color(stdout, Color::Cyan)?;
+    write!(stdout, "{}", space.name.as_ref().map_or("", |name| name))?;
+
+    intense_color(stdout, Color::Red)?;
+    writeln!(stdout, " (@{})", space.start_line)?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    dump_space_ops(space, &prefix, space.spaces.is_empty(), stdout)?;
+
+    if let Some((last, spaces)) = space.spaces.split_last() {
+        for space in spaces {
+            dump_space(space, &prefix, false, stdout)?;
+        }
+        dump_space(last, &prefix, true, stdout)?;
+    }
+
+    Ok(())
+}
+
+fn dump_space_ops(
+    ops: &Ops,
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    dump_ops_values("operators", &ops.operators, prefix, last, stdout)?;
+    dump_ops_values("operands", &ops.operands, prefix, last, stdout)
+}
+
+fn dump_ops_values(
+    name: &str,
+    ops: &[String],
+    prefix: &str,
+    last: bool,
+    stdout: &mut StandardStreamLock,
+) -> std::io::Result<()> {
+    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}{pref}")?;
+
+    intense_color(stdout, Color::Green)?;
+    writeln!(stdout, "{name}")?;
+
+    let prefix = format!("{prefix}{pref_child}");
+    for op in ops.iter().take(ops.len() - 1) {
+        color(stdout, Color::Blue)?;
+        write!(stdout, "{prefix}|- ")?;
+
+        color(stdout, Color::White)?;
+        writeln!(stdout, "{op}")?;
+    }
+
+    color(stdout, Color::Blue)?;
+    write!(stdout, "{prefix}`- ")?;
+
+    color(stdout, Color::White)?;
+    writeln!(stdout, "{}", ops.last().unwrap())
+}
diff --git a/src/output/mod.rs b/src/output/mod.rs
new file mode 100644
index 00000000..974eda86
--- /dev/null
+++ b/src/output/mod.rs
@@ -0,0 +1,8 @@
+pub(crate) mod dump;
+pub use dump::*;
+
+pub(crate) mod dump_metrics;
+pub use dump_metrics::*;
+
+pub(crate) mod dump_ops;
+pub use dump_ops::*;
diff --git a/src/parser.rs b/src/parser.rs
new file mode 100644
index 00000000..424b98f7
--- /dev/null
+++ b/src/parser.rs
@@ -0,0 +1,178 @@
+use std::marker::PhantomData;
+use std::path::Path;
+use std::sync::Arc;
+
+use crate::abc::Abc;
+use crate::checker::Checker;
+use crate::cognitive::Cognitive;
+use crate::cyclomatic::Cyclomatic;
+use crate::exit::Exit;
+use crate::halstead::Halstead;
+use crate::loc::Loc;
+use crate::mi::Mi;
+use crate::nargs::NArgs;
+use crate::nom::Nom;
+use crate::npa::Npa;
+use crate::npm::Npm;
+use crate::wmc::Wmc;
+
+use crate::alterator::Alterator;
+use crate::getter::Getter;
+
+use crate::langs::*;
+use crate::node::{Node, Tree};
+use crate::preproc::PreprocResults;
+use crate::traits::*;
+
+#[derive(Debug)]
+pub struct Parser<
+    T: LanguageInfo
+        + Alterator
+        + Checker
+        + Getter
+        + Abc
+        + Cognitive
+        + Cyclomatic
+        + Exit
+        + Halstead
+        + Loc
+        + Mi
+        + NArgs
+        + Nom
+        + Npa
+        + Npm
+        + Wmc,
+> {
+    code: Vec,
+    tree: Tree,
+    phantom: PhantomData,
+}
+
+type FilterFn = dyn Fn(&Node) -> bool;
+
+pub struct Filter {
+    filters: Vec>,
+}
+
+impl Filter {
+    pub fn any(&self, node: &Node) -> bool {
+        for f in self.filters.iter() {
+            if f(node) {
+                return true;
+            }
+        }
+        false
+    }
+
+    pub fn all(&self, node: &Node) -> bool {
+        for f in self.filters.iter() {
+            if !f(node) {
+                return false;
+            }
+        }
+        true
+    }
+}
+
+#[inline(always)]
+fn get_fake_code(_code: &[u8], _path: &Path, _pr: Option>) -> Option> {
+    None
+}
+
+impl<
+    T: 'static
+        + LanguageInfo
+        + Alterator
+        + Checker
+        + Getter
+        + Abc
+        + Cognitive
+        + Cyclomatic
+        + Exit
+        + Halstead
+        + Loc
+        + Mi
+        + NArgs
+        + Nom
+        + Npa
+        + Npm
+        + Wmc,
+> ParserTrait for Parser
+{
+    type Checker = T;
+    type Getter = T;
+    type Cognitive = T;
+    type Cyclomatic = T;
+    type Halstead = T;
+    type Loc = T;
+    type Nom = T;
+    type Mi = T;
+    type NArgs = T;
+    type Exit = T;
+    type Wmc = T;
+    type Abc = T;
+    type Npm = T;
+    type Npa = T;
+
+    fn new(code: Vec, path: &Path, pr: Option>) -> Self {
+        let fake_code = get_fake_code(&code, path, pr);
+        let code = if let Some(fake) = fake_code {
+            fake
+        } else {
+            code
+        };
+
+        let tree = Tree::new::(&code);
+
+        Self {
+            code,
+            tree,
+            phantom: PhantomData,
+        }
+    }
+
+    #[inline(always)]
+    fn get_language(&self) -> LANG {
+        T::get_lang()
+    }
+
+    #[inline(always)]
+    fn get_root(&self) -> Node<'_> {
+        self.tree.get_root()
+    }
+
+    #[inline(always)]
+    fn get_code(&self) -> &[u8] {
+        &self.code
+    }
+
+    fn get_filters(&self, filters: &[String]) -> Filter {
+        let mut res: Vec> = Vec::new();
+        for f in filters.iter() {
+            let f = f.as_str();
+            match f {
+                "all" => res.push(Box::new(|_: &Node| -> bool { true })),
+                "call" => res.push(Box::new(T::is_call)),
+                "comment" => res.push(Box::new(T::is_comment)),
+                "error" => res.push(Box::new(T::is_error)),
+                "string" => res.push(Box::new(T::is_string)),
+                "function" => res.push(Box::new(T::is_func)),
+                _ => {
+                    if let Ok(n) = f.parse::() {
+                        res.push(Box::new(move |node: &Node| -> bool { node.kind_id() == n }));
+                    } else {
+                        let f = f.to_owned();
+                        res.push(Box::new(move |node: &Node| -> bool {
+                            node.kind().contains(&f)
+                        }));
+                    }
+                }
+            }
+        }
+        if res.is_empty() {
+            res.push(Box::new(|_: &Node| -> bool { true }))
+        }
+
+        Filter { filters: res }
+    }
+}
diff --git a/src/preproc.rs b/src/preproc.rs
new file mode 100644
index 00000000..907894b6
--- /dev/null
+++ b/src/preproc.rs
@@ -0,0 +1,187 @@
+use std::collections::{HashMap, HashSet, hash_map};
+use std::path::{Path, PathBuf};
+
+use petgraph::{
+    Direction, algo::kosaraju_scc, graph::NodeIndex, stable_graph::StableGraph, visit::Dfs,
+};
+use serde::{Deserialize, Serialize};
+
+use crate::tools::*;
+
+/// Preprocessor data of a `C/C++` file.
+#[derive(Debug, Default, Deserialize, Serialize)]
+pub struct PreprocFile {
+    /// The set of include directives explicitly written in a file
+    pub direct_includes: HashSet,
+    /// The set of include directives implicitly imported in a file
+    /// from other files
+    pub indirect_includes: HashSet,
+    /// The set of macros of a file
+    pub macros: HashSet,
+}
+
+/// Preprocessor data of a series of `C/C++` files.
+#[derive(Debug, Default, Deserialize, Serialize)]
+pub struct PreprocResults {
+    /// The preprocessor data of each `C/C++` file
+    pub files: HashMap,
+}
+
+impl PreprocFile {
+    /// Adds new macros to the set of macro of a file.
+    pub fn new_macros(macros: &[&str]) -> Self {
+        let mut pf = Self::default();
+        for m in macros {
+            pf.macros.insert((*m).to_string());
+        }
+        pf
+    }
+}
+
+/// Returns the macros contained in a `C/C++` file.
+pub fn get_macros(
+    file: &Path,
+    files: &HashMap,
+) -> HashSet {
+    let mut macros = HashSet::new();
+    if let Some(pf) = files.get(file) {
+        for m in pf.macros.iter() {
+            macros.insert(m.to_string());
+        }
+        for f in pf.indirect_includes.iter() {
+            if let Some(pf) = files.get(&PathBuf::from(f)) {
+                for m in pf.macros.iter() {
+                    macros.insert(m.to_string());
+                }
+            }
+        }
+    }
+    macros
+}
+
+/// Constructs a dependency graph of the include directives
+/// in a `C/C++` file.
+///
+/// The dependency graph is built using both preprocessor data and not
+/// extracted from the considered `C/C++` files.
+pub fn fix_includes(
+    files: &mut HashMap,
+    all_files: &HashMap, S>,
+) {
+    let mut nodes: HashMap = HashMap::new();
+    // Since we'll remove strong connected components we need to have a stable graph
+    // in order to use the nodes we've in the nodes HashMap.
+    let mut g = StableGraph::new();
+
+    // First we build a graph of include dependencies
+    for (file, pf) in files.iter() {
+        let node = match nodes.entry(file.clone()) {
+            hash_map::Entry::Occupied(l) => *l.get(),
+            hash_map::Entry::Vacant(p) => *p.insert(g.add_node(file.clone())),
+        };
+        let direct_includes = &pf.direct_includes;
+        for i in direct_includes {
+            let possibilities = guess_file(file, i, all_files);
+            for i in possibilities {
+                if &i != file {
+                    let i = match nodes.entry(i.clone()) {
+                        hash_map::Entry::Occupied(l) => *l.get(),
+                        hash_map::Entry::Vacant(p) => *p.insert(g.add_node(i)),
+                    };
+                    g.add_edge(node, i, 0);
+                } else {
+                    // TODO: add an option to display warning
+                    eprintln!("Warning: possible self inclusion {file:?}");
+                }
+            }
+        }
+    }
+
+    // In order to walk in the graph without issues due to cycles
+    // we replace strong connected components by a unique node
+    // All the paths in a scc finally represents a kind of unique file containing
+    // all the files in the scc.
+    let mut scc = kosaraju_scc(&g);
+    let mut scc_map: HashMap> = HashMap::new();
+    for component in scc.iter_mut() {
+        if component.len() > 1 {
+            // For Firefox, there are only few scc and all of them are pretty small
+            // So no need to take a hammer here (for 'contains' stuff).
+            // TODO: in some case a hammer can be useful: check perf Vec vs HashSet
+            let mut incoming = Vec::new();
+            let mut outgoing = Vec::new();
+            let mut paths = HashSet::new();
+
+            for c in component.iter() {
+                for i in g.neighbors_directed(*c, Direction::Incoming) {
+                    if !component.contains(&i) && !incoming.contains(&i) {
+                        incoming.push(i);
+                    }
+                }
+                for o in g.neighbors_directed(*c, Direction::Outgoing) {
+                    if !component.contains(&o) && !outgoing.contains(&o) {
+                        outgoing.push(o);
+                    }
+                }
+            }
+
+            let replacement = g.add_node(PathBuf::from(""));
+            for i in incoming.drain(..) {
+                g.add_edge(i, replacement, 0);
+            }
+            for o in outgoing.drain(..) {
+                g.add_edge(replacement, o, 0);
+            }
+            for c in component.drain(..) {
+                let path = g.remove_node(c).unwrap();
+                paths.insert(path.to_str().unwrap().to_string());
+                *nodes.get_mut(&path).unwrap() = replacement;
+            }
+
+            eprintln!("Warning: possible include cycle:");
+            for p in paths.iter() {
+                eprintln!("  - {p:?}");
+            }
+            eprintln!();
+
+            scc_map.insert(replacement, paths);
+        }
+    }
+
+    for (path, node) in nodes {
+        let mut dfs = Dfs::new(&g, node);
+        if let Some(pf) = files.get_mut(&path) {
+            let x_inc = &mut pf.indirect_includes;
+            while let Some(node) = dfs.next(&g) {
+                let w = g.node_weight(node).unwrap();
+                if w == &PathBuf::from("") {
+                    let paths = scc_map.get(&node);
+                    if let Some(paths) = paths {
+                        for p in paths {
+                            x_inc.insert(p.to_string());
+                        }
+                    } else {
+                        eprintln!("DEBUG: {path:?} {node:?}");
+                    }
+                } else {
+                    x_inc.insert(w.to_str().unwrap().to_string());
+                }
+            }
+        } else {
+            eprintln!(
+                "Warning: included file which has not been preprocessed: {:?}",
+                path
+            );
+        }
+    }
+}
+
+/// This function is deprecated and no longer functional as preprocessor support
+/// for C/C++ has been removed.
+///
+/// [`PreprocResults`]: struct.PreprocResults.html
+#[deprecated(note = "Preprocessor support removed with C/C++ language removal")]
+#[allow(dead_code)]
+pub fn preprocess(_path: &Path, _results: &mut PreprocResults) {
+    // No-op: Preprocessor support removed with C/C++ language removal
+}
diff --git a/src/spaces.rs b/src/spaces.rs
new file mode 100644
index 00000000..ea91ff93
--- /dev/null
+++ b/src/spaces.rs
@@ -0,0 +1,381 @@
+use std::collections::HashMap;
+
+use serde::Serialize;
+use std::fmt;
+use std::path::{Path, PathBuf};
+
+use crate::checker::Checker;
+use crate::node::Node;
+
+use crate::abc::{self, Abc};
+use crate::cognitive::{self, Cognitive};
+use crate::cyclomatic::{self, Cyclomatic};
+use crate::exit::{self, Exit};
+use crate::getter::Getter;
+use crate::halstead::{self, Halstead, HalsteadMaps};
+use crate::loc::{self, Loc};
+use crate::mi::{self, Mi};
+use crate::nargs::{self, NArgs};
+use crate::nom::{self, Nom};
+use crate::npa::{self, Npa};
+use crate::npm::{self, Npm};
+use crate::wmc::{self, Wmc};
+
+use crate::dump_metrics::*;
+use crate::traits::*;
+
+/// The list of supported space kinds.
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize)]
+#[serde(rename_all = "lowercase")]
+pub enum SpaceKind {
+    /// An unknown space
+    #[default]
+    Unknown,
+    /// A function space
+    Function,
+    /// A class space
+    Class,
+    /// A struct space
+    Struct,
+    /// A `Rust` trait space
+    Trait,
+    /// A `Rust` implementation space
+    Impl,
+    /// A general space
+    Unit,
+    /// A `C/C++` namespace
+    Namespace,
+    /// An interface
+    Interface,
+}
+
+impl fmt::Display for SpaceKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let s = match self {
+            SpaceKind::Unknown => "unknown",
+            SpaceKind::Function => "function",
+            SpaceKind::Class => "class",
+            SpaceKind::Struct => "struct",
+            SpaceKind::Trait => "trait",
+            SpaceKind::Impl => "impl",
+            SpaceKind::Unit => "unit",
+            SpaceKind::Namespace => "namespace",
+            SpaceKind::Interface => "interface",
+        };
+        write!(f, "{s}")
+    }
+}
+
+/// All metrics data.
+#[derive(Default, Debug, Clone, Serialize)]
+pub struct CodeMetrics {
+    /// `NArgs` data
+    pub nargs: nargs::Stats,
+    /// `NExits` data
+    pub nexits: exit::Stats,
+    pub cognitive: cognitive::Stats,
+    /// `Cyclomatic` data
+    pub cyclomatic: cyclomatic::Stats,
+    /// `Halstead` data
+    pub halstead: halstead::Stats,
+    /// `Loc` data
+    pub loc: loc::Stats,
+    /// `Nom` data
+    pub nom: nom::Stats,
+    /// `Mi` data
+    pub mi: mi::Stats,
+    /// `Abc` data
+    pub abc: abc::Stats,
+    /// `Wmc` data
+    #[serde(skip_serializing_if = "wmc::Stats::is_disabled")]
+    pub wmc: wmc::Stats,
+    /// `Npm` data
+    #[serde(skip_serializing_if = "npm::Stats::is_disabled")]
+    pub npm: npm::Stats,
+    /// `Npa` data
+    #[serde(skip_serializing_if = "npa::Stats::is_disabled")]
+    pub npa: npa::Stats,
+}
+
+impl fmt::Display for CodeMetrics {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "{}", self.nargs)?;
+        writeln!(f, "{}", self.nexits)?;
+        writeln!(f, "{}", self.cognitive)?;
+        writeln!(f, "{}", self.cyclomatic)?;
+        writeln!(f, "{}", self.halstead)?;
+        writeln!(f, "{}", self.loc)?;
+        writeln!(f, "{}", self.nom)?;
+        write!(f, "{}", self.mi)
+    }
+}
+
+impl CodeMetrics {
+    pub fn merge(&mut self, other: &CodeMetrics) {
+        self.cognitive.merge(&other.cognitive);
+        self.cyclomatic.merge(&other.cyclomatic);
+        self.halstead.merge(&other.halstead);
+        self.loc.merge(&other.loc);
+        self.nom.merge(&other.nom);
+        self.mi.merge(&other.mi);
+        self.nargs.merge(&other.nargs);
+        self.nexits.merge(&other.nexits);
+        self.abc.merge(&other.abc);
+        self.wmc.merge(&other.wmc);
+        self.npm.merge(&other.npm);
+        self.npa.merge(&other.npa);
+    }
+}
+
+/// Function space data.
+#[derive(Debug, Clone, Serialize)]
+pub struct FuncSpace {
+    /// The name of a function space
+    ///
+    /// If `None`, an error is occurred in parsing
+    /// the name of a function space
+    pub name: Option,
+    /// The first line of a function space
+    pub start_line: usize,
+    /// The last line of a function space
+    pub end_line: usize,
+    /// The space kind
+    pub kind: SpaceKind,
+    /// All subspaces contained in a function space
+    pub spaces: Vec,
+    /// All metrics of a function space
+    pub metrics: CodeMetrics,
+}
+
+impl FuncSpace {
+    fn new(node: &Node, code: &[u8], kind: SpaceKind) -> Self {
+        let (start_position, end_position) = match kind {
+            SpaceKind::Unit => {
+                if node.child_count() == 0 {
+                    (0, 0)
+                } else {
+                    (node.start_row() + 1, node.end_row())
+                }
+            }
+            _ => (node.start_row() + 1, node.end_row() + 1),
+        };
+
+        Self {
+            name: T::get_func_space_name(node, code)
+                .map(|name| name.split_whitespace().collect::>().join(" ")),
+            spaces: Vec::new(),
+            metrics: CodeMetrics::default(),
+            kind,
+            start_line: start_position,
+            end_line: end_position,
+        }
+    }
+}
+
+#[inline(always)]
+fn compute_halstead_mi_and_wmc(state: &mut State) {
+    state
+        .halstead_maps
+        .finalize(&mut state.space.metrics.halstead);
+    T::Mi::compute(
+        &state.space.metrics.loc,
+        &state.space.metrics.cyclomatic,
+        &state.space.metrics.halstead,
+        &mut state.space.metrics.mi,
+    );
+    T::Wmc::compute(
+        state.space.kind,
+        &state.space.metrics.cyclomatic,
+        &mut state.space.metrics.wmc,
+    );
+}
+
+#[inline(always)]
+fn compute_averages(state: &mut State) {
+    let nom_functions = state.space.metrics.nom.functions_sum() as usize;
+    let nom_closures = state.space.metrics.nom.closures_sum() as usize;
+    let nom_total = state.space.metrics.nom.total() as usize;
+    // Cognitive average
+    state.space.metrics.cognitive.finalize(nom_total);
+    // Nexit average
+    state.space.metrics.nexits.finalize(nom_total);
+    // Nargs average
+    state
+        .space
+        .metrics
+        .nargs
+        .finalize(nom_functions, nom_closures);
+}
+
+#[inline(always)]
+fn compute_minmax(state: &mut State) {
+    state.space.metrics.cyclomatic.compute_minmax();
+    state.space.metrics.nexits.compute_minmax();
+    state.space.metrics.cognitive.compute_minmax();
+    state.space.metrics.nargs.compute_minmax();
+    state.space.metrics.nom.compute_minmax();
+    state.space.metrics.loc.compute_minmax();
+    state.space.metrics.abc.compute_minmax();
+}
+
+#[inline(always)]
+fn compute_sum(state: &mut State) {
+    state.space.metrics.wmc.compute_sum();
+    state.space.metrics.npm.compute_sum();
+    state.space.metrics.npa.compute_sum();
+}
+
+fn finalize(state_stack: &mut Vec, diff_level: usize) {
+    if state_stack.is_empty() {
+        return;
+    }
+    for _ in 0..diff_level {
+        if state_stack.len() == 1 {
+            let last_state = state_stack.last_mut().unwrap();
+            compute_minmax(last_state);
+            compute_sum(last_state);
+            compute_halstead_mi_and_wmc::(last_state);
+            compute_averages(last_state);
+            break;
+        } else {
+            let mut state = state_stack.pop().unwrap();
+            compute_minmax(&mut state);
+            compute_sum(&mut state);
+            compute_halstead_mi_and_wmc::(&mut state);
+            compute_averages(&mut state);
+
+            let last_state = state_stack.last_mut().unwrap();
+            last_state.halstead_maps.merge(&state.halstead_maps);
+            compute_halstead_mi_and_wmc::(last_state);
+
+            // Merge function spaces
+            last_state.space.metrics.merge(&state.space.metrics);
+            last_state.space.spaces.push(state.space);
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+struct State<'a> {
+    space: FuncSpace,
+    halstead_maps: HalsteadMaps<'a>,
+}
+
+/// Returns all function spaces data of a code. This function needs a parser to
+/// be created a priori in order to work.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::Path;
+///
+/// use mehen::{RustParser, metrics, ParserTrait};
+///
+/// let source_code = "fn main() { let a = 42; }";
+///
+/// let path = Path::new("foo.rs");
+/// let source_as_vec = source_code.as_bytes().to_vec();
+///
+/// let parser = RustParser::new(source_as_vec, &path, None);
+///
+/// metrics(&parser, &path).unwrap();
+/// ```
+pub fn metrics<'a, T: ParserTrait>(parser: &'a T, path: &'a Path) -> Option {
+    let code = parser.get_code();
+    let node = parser.get_root();
+    let mut cursor = node.cursor();
+    let mut stack = Vec::new();
+    let mut children = Vec::new();
+    let mut state_stack: Vec = Vec::new();
+    let mut last_level = 0;
+    // Initialize nesting_map used for storing nesting information for cognitive
+    // Three type of nesting info: conditionals, functions and lambdas
+    let mut nesting_map = HashMap::::default();
+    nesting_map.insert(node.id(), (0, 0, 0));
+    stack.push((node, 0));
+
+    while let Some((node, level)) = stack.pop() {
+        if level < last_level {
+            finalize::(&mut state_stack, last_level - level);
+            last_level = level;
+        }
+
+        let kind = T::Getter::get_space_kind(&node);
+
+        let func_space = T::Checker::is_func(&node) || T::Checker::is_func_space(&node);
+        let unit = kind == SpaceKind::Unit;
+
+        let new_level = if func_space {
+            let state = State {
+                space: FuncSpace::new::(&node, code, kind),
+                halstead_maps: HalsteadMaps::new(),
+            };
+            state_stack.push(state);
+            last_level = level + 1;
+            last_level
+        } else {
+            level
+        };
+
+        if let Some(state) = state_stack.last_mut() {
+            let last = &mut state.space;
+            T::Cognitive::compute(&node, &mut last.metrics.cognitive, &mut nesting_map);
+            T::Cyclomatic::compute(&node, &mut last.metrics.cyclomatic);
+            T::Halstead::compute(&node, code, &mut state.halstead_maps);
+            T::Loc::compute(&node, &mut last.metrics.loc, func_space, unit);
+            T::Nom::compute(&node, &mut last.metrics.nom);
+            T::NArgs::compute(&node, &mut last.metrics.nargs);
+            T::Exit::compute(&node, &mut last.metrics.nexits);
+            T::Abc::compute(&node, &mut last.metrics.abc);
+            T::Npm::compute(&node, &mut last.metrics.npm);
+            T::Npa::compute(&node, &mut last.metrics.npa);
+        }
+
+        cursor.reset(&node);
+        if cursor.goto_first_child() {
+            loop {
+                children.push((cursor.node(), new_level));
+                if !cursor.goto_next_sibling() {
+                    break;
+                }
+            }
+            for child in children.drain(..).rev() {
+                stack.push(child);
+            }
+        }
+    }
+
+    finalize::(&mut state_stack, usize::MAX);
+
+    state_stack.pop().map(|mut state| {
+        state.space.name = path.to_str().map(|name| name.to_string());
+        state.space
+    })
+}
+
+/// Configuration options for computing
+/// the metrics of a code.
+#[derive(Debug)]
+pub struct MetricsCfg {
+    /// Path to the file containing the code
+    pub path: PathBuf,
+}
+
+pub struct Metrics {
+    _guard: (),
+}
+
+impl Callback for Metrics {
+    type Res = std::io::Result<()>;
+    type Cfg = MetricsCfg;
+
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res {
+        match metrics(parser, &cfg.path) {
+            Some(space) => dump_root(&space),
+            _ => Ok(()),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {}
diff --git a/src/tools.rs b/src/tools.rs
new file mode 100644
index 00000000..40d33582
--- /dev/null
+++ b/src/tools.rs
@@ -0,0 +1,442 @@
+use std::cmp::Ordering;
+use std::collections::HashMap;
+use std::fs::{self, File};
+use std::io::{Read, Write};
+use std::path::{Component, Path, PathBuf};
+use std::sync::OnceLock;
+
+use regex::bytes::Regex;
+use termcolor::{Color, ColorSpec, StandardStreamLock, WriteColor};
+
+use crate::langs::fake;
+use crate::langs::*;
+
+/// Reads a file.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::Path;
+///
+/// use mehen::read_file;
+///
+/// let path = Path::new("Cargo.toml");
+/// read_file(&path).unwrap();
+/// ```
+pub fn read_file(path: &Path) -> std::io::Result> {
+    let mut file = File::open(path)?;
+    let mut data = Vec::new();
+    file.read_to_end(&mut data)?;
+
+    remove_blank_lines(&mut data);
+
+    Ok(data)
+}
+
+/// Reads a file and adds an `EOL` at its end.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::Path;
+///
+/// use mehen::read_file_with_eol;
+///
+/// let path = Path::new("Cargo.toml");
+/// read_file_with_eol(&path).unwrap();
+/// ```
+pub fn read_file_with_eol(path: &Path) -> std::io::Result>> {
+    let file_size = fs::metadata(path).map_or(1024 * 1024, |m| m.len() as usize);
+    if file_size <= 3 {
+        // this file is very likely almost empty... so nothing to do on it
+        return Ok(None);
+    }
+
+    let mut file = File::open(path)?;
+
+    let mut start = vec![0; 64.min(file_size)];
+    let start = if file.read_exact(&mut start).is_ok() {
+        // Skip the bom if one
+        if start[..2] == [b'\xFE', b'\xFF'] || start[..2] == [b'\xFF', b'\xFE'] {
+            &start[2..]
+        } else if start[..3] == [b'\xEF', b'\xBB', b'\xBF'] {
+            &start[3..]
+        } else {
+            &start
+        }
+    } else {
+        return Ok(None);
+    };
+
+    // so start contains more or less 64 chars
+    let mut head = String::from_utf8_lossy(start).into_owned();
+    // The last char could be wrong because we were in the middle of an utf-8 sequence
+    head.pop();
+    // now check if there is an invalid char
+    if head.contains('\u{FFFD}') {
+        return Ok(None);
+    }
+
+    let mut data = Vec::with_capacity(file_size + 2);
+    data.extend_from_slice(start);
+
+    file.read_to_end(&mut data)?;
+
+    remove_blank_lines(&mut data);
+
+    Ok(Some(data))
+}
+
+/// Writes data to a file.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::path::Path;
+///
+/// use mehen::write_file;
+///
+/// let path = Path::new("foo.txt");
+/// let data: [u8; 4] = [0; 4];
+/// write_file(&path, &data).unwrap();
+/// ```
+pub fn write_file(path: &Path, data: &[u8]) -> std::io::Result<()> {
+    let mut file = File::create(path)?;
+    file.write_all(data)?;
+
+    Ok(())
+}
+
+/// Detects the language of a code using
+/// the extension of a file.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::Path;
+///
+/// use mehen::get_language_for_file;
+///
+/// let path = Path::new("build.rs");
+/// get_language_for_file(&path).unwrap();
+/// ```
+pub fn get_language_for_file(path: &Path) -> Option {
+    if let Some(ext) = path.extension() {
+        let ext = ext.to_str().unwrap().to_lowercase();
+        get_from_ext(&ext)
+    } else {
+        None
+    }
+}
+
+fn mode_to_str(mode: &[u8]) -> Option {
+    std::str::from_utf8(mode).ok().map(|m| m.to_lowercase())
+}
+
+// comment containing coding info are useful
+static RE1_EMACS: OnceLock = OnceLock::new();
+static RE2_EMACS: OnceLock = OnceLock::new();
+static RE1_VIM: OnceLock = OnceLock::new();
+
+// Regular expressions
+const FIRST_EMACS_EXPRESSION: &str = r"(?i)-\*-.*[^-\w]mode\s*:\s*([^:;\s]+)";
+const SECOND_EMACS_EXPRESSION: &str = r"-\*-\s*([^:;\s]+)\s*-\*-";
+const VIM_EXPRESSION: &str = r"(?i)vim\s*:.*[^\w]ft\s*=\s*([^:\s]+)";
+
+#[inline(always)]
+fn get_regex<'a>(
+    once_lock: &OnceLock,
+    line: &'a [u8],
+    regex: &'a str,
+) -> Option> {
+    once_lock
+        .get_or_init(|| Regex::new(regex).unwrap())
+        .captures_iter(line)
+        .next()
+}
+
+fn get_emacs_mode(buf: &[u8]) -> Option {
+    // we just try to use the emacs info (if there)
+    for (i, line) in buf.splitn(5, |c| *c == b'\n').enumerate() {
+        if let Some(cap) = get_regex(&RE1_EMACS, line, FIRST_EMACS_EXPRESSION) {
+            return mode_to_str(&cap[1]);
+        } else if let Some(cap) = get_regex(&RE2_EMACS, line, SECOND_EMACS_EXPRESSION) {
+            return mode_to_str(&cap[1]);
+        } else if let Some(cap) = get_regex(&RE1_VIM, line, VIM_EXPRESSION) {
+            return mode_to_str(&cap[1]);
+        }
+        if i == 3 {
+            break;
+        }
+    }
+
+    for (i, line) in buf.rsplitn(5, |c| *c == b'\n').enumerate() {
+        if let Some(cap) = get_regex(&RE1_VIM, line, VIM_EXPRESSION) {
+            return mode_to_str(&cap[1]);
+        }
+        if i == 3 {
+            break;
+        }
+    }
+
+    None
+}
+
+/// Guesses the language of a code.
+///
+/// Returns a tuple containing a [`LANG`] as first argument
+/// and the language name as a second one.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::PathBuf;
+///
+/// use mehen::guess_language;
+///
+/// let source_code = "int a = 42;";
+///
+/// // The path to a dummy file used to contain the source code
+/// let path = PathBuf::from("foo.c");
+/// let source_slice = source_code.as_bytes();
+///
+/// // Guess the language of a code
+/// guess_language(&source_slice, &path);
+/// ```
+///
+/// [`LANG`]: enum.LANG.html
+pub fn guess_language<'a, P: AsRef>(buf: &[u8], path: P) -> (Option, &'a str) {
+    let ext = path
+        .as_ref()
+        .extension()
+        .map(|e| e.to_str().unwrap())
+        .map(|e| e.to_lowercase())
+        .unwrap_or_else(|| "".to_string());
+    let from_ext = get_from_ext(&ext);
+
+    let mode = get_emacs_mode(buf).unwrap_or_default();
+
+    let from_mode = get_from_emacs_mode(&mode);
+
+    if let Some(lang_ext) = from_ext {
+        if let Some(lang_mode) = from_mode {
+            if lang_ext == lang_mode {
+                (
+                    Some(lang_mode),
+                    fake::get_true(&ext, &mode).unwrap_or_else(|| lang_mode.get_name()),
+                )
+            } else {
+                // we should probably rely on extension here
+                (Some(lang_ext), lang_ext.get_name())
+            }
+        } else {
+            (
+                Some(lang_ext),
+                fake::get_true(&ext, &mode).unwrap_or_else(|| lang_ext.get_name()),
+            )
+        }
+    } else if let Some(lang_mode) = from_mode {
+        (
+            Some(lang_mode),
+            fake::get_true(&ext, &mode).unwrap_or_else(|| lang_mode.get_name()),
+        )
+    } else {
+        (None, fake::get_true(&ext, &mode).unwrap_or_default())
+    }
+}
+
+/// Replaces \n and \r ending characters with a single generic \n
+pub(crate) fn remove_blank_lines(data: &mut Vec) {
+    let count_trailing = data
+        .iter()
+        .rev()
+        .take_while(|&c| *c == b'\n' || *c == b'\r')
+        .count();
+    if count_trailing > 0 {
+        data.truncate(data.len() - count_trailing);
+    }
+    data.push(b'\n');
+}
+
+pub(crate) fn normalize_path>(path: P) -> PathBuf {
+    // Copied from Cargo sources: https://github.com/rust-lang/cargo/blob/master/src/cargo/util/paths.rs#L65
+    let mut components = path.as_ref().components().peekable();
+    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
+        components.next();
+        PathBuf::from(c.as_os_str())
+    } else {
+        PathBuf::new()
+    };
+
+    for component in components {
+        match component {
+            Component::Prefix(..) => unreachable!(),
+            Component::RootDir => {
+                ret.push(component.as_os_str());
+            }
+            Component::CurDir => {}
+            Component::ParentDir => {
+                ret.pop();
+            }
+            Component::Normal(c) => {
+                ret.push(c);
+            }
+        }
+    }
+    ret
+}
+
+pub(crate) fn get_paths_dist(path1: &Path, path2: &Path) -> Option {
+    for ancestor in path1.ancestors() {
+        if path2.starts_with(ancestor) && !ancestor.as_os_str().is_empty() {
+            let path1 = path1.strip_prefix(ancestor).unwrap();
+            let path2 = path2.strip_prefix(ancestor).unwrap();
+            return Some(path1.components().count() + path2.components().count());
+        }
+    }
+    None
+}
+
+pub(crate) fn guess_file(
+    current_path: &Path,
+    include_path: &str,
+    all_files: &HashMap, S>,
+) -> Vec {
+    let include_path = if let Some(end) = include_path.strip_prefix("mozilla/") {
+        end
+    } else {
+        include_path
+    };
+    let include_path = normalize_path(include_path);
+    if let Some(possibilities) = all_files.get(include_path.file_name().unwrap().to_str().unwrap())
+    {
+        if possibilities.len() == 1 {
+            // Only one file with this name
+            return possibilities.clone();
+        }
+
+        let mut new_possibilities = Vec::new();
+        for p in possibilities.iter() {
+            if p.ends_with(&include_path) && current_path != p {
+                new_possibilities.push(p.clone());
+            }
+        }
+        if new_possibilities.len() == 1 {
+            // Only one path is finishing with "foo/Bar.h"
+            return new_possibilities;
+        }
+        new_possibilities.clear();
+
+        if let Some(parent) = current_path.parent() {
+            for p in possibilities.iter() {
+                if p.starts_with(parent) && current_path != p {
+                    new_possibilities.push(p.clone());
+                }
+            }
+            if new_possibilities.len() == 1 {
+                // Only one path in the current working directory (current_path)
+                return new_possibilities;
+            }
+            new_possibilities.clear();
+        }
+
+        let mut dist_min = usize::MAX;
+        let mut path_min = Vec::new();
+        for p in possibilities.iter() {
+            if current_path == p {
+                continue;
+            }
+            if let Some(dist) = get_paths_dist(current_path, p) {
+                match dist.cmp(&dist_min) {
+                    Ordering::Less => {
+                        dist_min = dist;
+                        path_min.clear();
+                        path_min.push(p);
+                    }
+                    Ordering::Equal => {
+                        path_min.push(p);
+                    }
+                    Ordering::Greater => {}
+                }
+            }
+        }
+
+        let path_min: Vec<_> = path_min.drain(..).map(|p| p.to_path_buf()).collect();
+        return path_min;
+    }
+
+    vec![]
+}
+
+#[inline(always)]
+pub(crate) fn color(stdout: &mut StandardStreamLock, color: Color) -> std::io::Result<()> {
+    stdout.set_color(ColorSpec::new().set_fg(Some(color)))
+}
+
+#[inline(always)]
+pub(crate) fn intense_color(stdout: &mut StandardStreamLock, color: Color) -> std::io::Result<()> {
+    stdout.set_color(ColorSpec::new().set_fg(Some(color)).set_intense(true))
+}
+
+#[cfg(test)]
+pub(crate) fn check_func_space(
+    source: &str,
+    filename: &str,
+    check: F,
+) {
+    let path = std::path::PathBuf::from(filename);
+    let mut trimmed_bytes = source.trim_end().trim_matches('\n').as_bytes().to_vec();
+    trimmed_bytes.push(b'\n');
+    let parser = T::new(trimmed_bytes, &path, None);
+    let func_space = crate::metrics(&parser, &path).unwrap();
+
+    check(func_space)
+}
+
+#[cfg(test)]
+pub(crate) fn check_metrics(
+    source: &str,
+    filename: &str,
+    check: fn(crate::CodeMetrics) -> (),
+) {
+    check_func_space::(source, filename, |func_space| check(func_space.metrics))
+}
+
+#[cfg(test)]
+mod tests {
+    use pretty_assertions::assert_eq;
+
+    use super::*;
+
+    #[test]
+    fn test_read() {
+        let tmp_dir = std::env::temp_dir();
+        let tmp_path = tmp_dir.join("test_read");
+        let data = vec![
+            (b"\xFF\xFEabc".to_vec(), Some(b"abc\n".to_vec())),
+            (b"\xFE\xFFabc".to_vec(), Some(b"abc\n".to_vec())),
+            (b"\xEF\xBB\xBFabc".to_vec(), Some(b"abc\n".to_vec())),
+            (b"\xEF\xBB\xBFabc\n".to_vec(), Some(b"abc\n".to_vec())),
+            (b"\xEF\xBBabc\n".to_vec(), None),
+            (b"abcdef\n".to_vec(), Some(b"abcdef\n".to_vec())),
+            (b"abcdef".to_vec(), Some(b"abcdef\n".to_vec())),
+        ];
+        for (d, expected) in data {
+            write_file(&tmp_path, &d).unwrap();
+            let res = read_file_with_eol(&tmp_path).unwrap();
+            assert_eq!(res, expected);
+        }
+    }
+
+    #[test]
+    fn test_guess_language() {
+        let buf = b"// -*- foo: bar; bar-mode: python; hello: world\n";
+        assert_eq!(
+            guess_language(buf, "foo.py"),
+            (Some(LANG::Python), "python")
+        );
+
+        let buf = b"\n\n\n\n\n\n\n\n\n\n\n\n";
+        assert_eq!(guess_language(buf, "foo.txt"), (None, ""));
+    }
+}
diff --git a/src/traits.rs b/src/traits.rs
new file mode 100644
index 00000000..12c4963c
--- /dev/null
+++ b/src/traits.rs
@@ -0,0 +1,72 @@
+use std::path::Path;
+use std::sync::Arc;
+
+use crate::abc::Abc;
+use crate::alterator::Alterator;
+use crate::checker::Checker;
+use crate::cognitive::Cognitive;
+use crate::cyclomatic::Cyclomatic;
+use crate::exit::Exit;
+use crate::getter::Getter;
+use crate::halstead::Halstead;
+use crate::langs::*;
+use crate::loc::Loc;
+use crate::mi::Mi;
+use crate::nargs::NArgs;
+use crate::node::Node;
+use crate::nom::Nom;
+use crate::npa::Npa;
+use crate::npm::Npm;
+use crate::parser::Filter;
+use crate::preproc::PreprocResults;
+use crate::wmc::Wmc;
+
+/// A trait for callback functions.
+///
+/// Allows to call a private library function, getting as result
+/// its output value.
+pub trait Callback {
+    /// The output type returned by the callee
+    type Res;
+    /// The input type used by the caller to pass the arguments to the callee
+    type Cfg;
+
+    /// Calls a function inside the library and returns its value
+    fn call(cfg: Self::Cfg, parser: &T) -> Self::Res;
+}
+
+pub trait LanguageInfo {
+    type BaseLang;
+
+    fn get_lang() -> LANG;
+    fn get_lang_name() -> &'static str;
+}
+
+#[doc(hidden)]
+pub trait ParserTrait {
+    type Checker: Alterator + Checker;
+    type Getter: Getter;
+    type Cognitive: Cognitive;
+    type Cyclomatic: Cyclomatic;
+    type Halstead: Halstead;
+    type Loc: Loc;
+    type Nom: Nom;
+    type Mi: Mi;
+    type NArgs: NArgs;
+    type Exit: Exit;
+    type Wmc: Wmc;
+    type Abc: Abc;
+    type Npm: Npm;
+    type Npa: Npa;
+
+    fn new(code: Vec, path: &Path, pr: Option>) -> Self;
+    fn get_language(&self) -> LANG;
+    fn get_root(&self) -> Node<'_>;
+    fn get_code(&self) -> &[u8];
+    fn get_filters(&self, filters: &[String]) -> Filter;
+}
+
+pub(crate) trait Search<'a> {
+    fn act_on_node(&self, pred: &mut dyn FnMut(&Node<'a>));
+    fn act_on_child(&self, action: &mut dyn FnMut(&Node<'a>));
+}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
new file mode 100644
index 00000000..0673aa2a
--- /dev/null
+++ b/tests/common/mod.rs
@@ -0,0 +1,93 @@
+use std::path::Path;
+use std::path::PathBuf;
+use std::process;
+
+use globset::{Glob, GlobSetBuilder};
+
+use mehen::LANG;
+use mehen::*;
+
+const REPO: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/", "repositories");
+const SNAPSHOT_PATH: &str = concat!(
+    env!("CARGO_MANIFEST_DIR"),
+    "/tests/",
+    "repositories/rca-output/snapshots"
+);
+
+#[derive(Debug)]
+struct Config {
+    language: Option,
+}
+
+fn act_on_file(path: PathBuf, cfg: &Config) -> std::io::Result<()> {
+    // Open file
+    let source = if let Some(source) = read_file_with_eol(&path)? {
+        source
+    } else {
+        return Ok(());
+    };
+
+    // Guess programming language
+    let language = if let Some(language) = cfg.language {
+        language
+    } else if let Some(language) = guess_language(&source, &path).0 {
+        language
+    } else {
+        return Ok(());
+    };
+
+    // Get FuncSpace struct
+    let funcspace_struct = get_function_spaces(&language, source, &path, None).unwrap();
+
+    insta::with_settings!({snapshot_path => Path::new(SNAPSHOT_PATH)
+                .join(path.strip_prefix(Path::new(REPO)).unwrap())
+                .parent()
+                .unwrap(),
+                prepend_module_to_snapshot => false,
+                sort_maps => true,
+    }, {
+        insta::assert_yaml_snapshot!(
+            path.file_name().unwrap().to_string_lossy().as_ref(),
+            funcspace_struct,
+            {
+                // Round floating point values to three decimal places since the can differ from
+                // system to system.
+                ".spaces[].**.metrics.*.*" => insta::rounded_redaction(3),
+                ".metrics.*.*" => insta::rounded_redaction(3),
+                // Redact away the name since paths are different on different systems.
+                ".name" => "[filepath]",
+            }
+        );
+
+    });
+
+    Ok(())
+}
+
+/// Produces metrics runtime and compares them with previously generated json files
+pub fn compare_rca_output_with_files(repo_name: &str, include: &[&str], exclude: &[&str]) {
+    let num_jobs = 4;
+
+    let cfg = Config { language: None };
+
+    let mut gsbi = GlobSetBuilder::new();
+    for file in include {
+        gsbi.add(Glob::new(file).unwrap());
+    }
+
+    let mut gsbe = GlobSetBuilder::new();
+    for file in exclude {
+        gsbe.add(Glob::new(file).unwrap());
+    }
+
+    let files_data = FilesData {
+        include: gsbi.build().unwrap(),
+        exclude: gsbe.build().unwrap(),
+        paths: vec![Path::new(REPO).join(repo_name)],
+    };
+
+    if let Err(e) = ConcurrentRunner::new(num_jobs, act_on_file).run(cfg, files_data) {
+        eprintln!("{e:?}");
+        process::exit(1);
+    }
+}
diff --git a/tests/repositories/rca-output b/tests/repositories/rca-output
new file mode 160000
index 00000000..f155a5e2
--- /dev/null
+++ b/tests/repositories/rca-output
@@ -0,0 +1 @@
+Subproject commit f155a5e26d152a3f4a83b4ba55cc5f81e3ed30c3
diff --git a/tests/repositories/serde b/tests/repositories/serde
new file mode 160000
index 00000000..d6de9118
--- /dev/null
+++ b/tests/repositories/serde
@@ -0,0 +1 @@
+Subproject commit d6de911855d1cc0ad13f87503a79d40dc4490442
diff --git a/tests/serde_test.rs b/tests/serde_test.rs
new file mode 100644
index 00000000..707faa8d
--- /dev/null
+++ b/tests/serde_test.rs
@@ -0,0 +1,8 @@
+mod common;
+
+use common::compare_rca_output_with_files;
+
+#[test]
+fn test_serde() {
+    compare_rca_output_with_files("serde", &["*.rs"], &[]);
+}
diff --git a/version.txt b/version.txt
index 81c871de..8acdd82b 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-1.10.0
+0.0.1
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
deleted file mode 100644
index 80e84019..00000000
--- a/xtask/Cargo.toml
+++ /dev/null
@@ -1,34 +0,0 @@
-[package]
-name = "xtask"
-version.workspace = true
-authors.workspace = true
-edition.workspace = true
-rust-version.workspace = true
-repository.workspace = true
-license.workspace = true
-description = "Mehen 1.0 — developer-only commands (snapshots, parity, tree-sitter generator) (internal)."
-publish = false
-
-[[bin]]
-name = "xtask"
-path = "src/main.rs"
-
-[dependencies]
-clap = { workspace = true }
-askama = "^0.16"
-serde_json = { workspace = true }
-tree-sitter = { workspace = true }
-antlr_rust_codegen = { workspace = true }
-# Kind-enum codegen reaches each grammar through the owning analyzer
-# crate's `__grammar_language()` accessor (see
-# `xtask/src/tree_sitter.rs::TARGETS`). The analyzer's grammar pin is
-# the single source of truth, so xtask deliberately does NOT depend on
-# `tree-sitter-c` or `tree-sitter-go` directly — that keeps the codegen
-# and the runtime parser locked to the same revision by construction.
-# ANTLR codegen consumes vendored `.g4` files through the workspace-pinned
-# `antlr_rust_codegen` library above, so no language grammar crate is linked.
-mehen-c = { workspace = true }
-mehen-go = { workspace = true }
-
-[lints]
-workspace = true
diff --git a/xtask/src/antlr.rs b/xtask/src/antlr.rs
deleted file mode 100644
index 4b0582ab..00000000
--- a/xtask/src/antlr.rs
+++ /dev/null
@@ -1,799 +0,0 @@
-//! ANTLR → Rust parser generator orchestration.
-//!
-//! The ANTLR analogue of `xtask/src/tree_sitter.rs`. Where the tree-sitter
-//! generator renders a kind-enum from a linked grammar crate, the ANTLR path
-//! calls the workspace-pinned `antlr-rust-codegen` library directly over a
-//! vendored `.g4` grammar.
-//!
-//! The generated modules are checked in verbatim under
-//! `crates/mehen--parser/src/generated/` (see that dir's README). The
-//! generator emits lint and `rustfmt::skip` attributes inside each file, so
-//! the owning parser crate includes them as plain modules.
-//!
-//! The generator is an xtask-only dependency. A normal `cargo build` targets
-//! the CLI default member and uses the checked-in modules, while
-//! `check-generated` is always available without a separately installed binary.
-
-use antlr_rust_codegen::{Builder, Error as CodegenError, Severity, UnknownSemanticPolicy};
-use askama::Template;
-use std::fmt::Write as _;
-use std::path::{Path, PathBuf};
-use std::process::Command;
-use std::{env, fs};
-
-/// The codegen package version recorded in generated parser-crate docs.
-///
-/// `Cargo.toml` pins the codegen and runtime packages in lockstep. Reading the
-/// linked package's version removes the second hand-maintained version string
-/// that the old external-binary integration required.
-const CODEGEN_VERSION: &str = antlr_rust_codegen::VERSION;
-
-/// Askama model for a parser crate's generated `README.md`.
-///
-/// Rendered from `xtask/templates/parser-readme.md` alongside the generated
-/// modules so every ANTLR parser crate ships consume-me docs (a git-dependency
-/// snippet and a parse example) without hand-maintenance. The doc code mirrors
-/// the compile-tested `//!` example in the crate's `lib.rs`; keeping the two in
-/// step is a review concern, not a build one (a plain README is not a
-/// doctest). Metadata fields (runtime version, entry rule, upstream) are
-/// drift-checked by `xtask antlr check-generated`.
-#[derive(Template)]
-#[template(path = "parser-readme.md", escape = "none")]
-struct ReadmeTemplate<'a> {
-    /// CLI slug (`kotlin`) — names the regenerate command in the header.
-    slug: &'a str,
-    /// Crate name as depended on (`mehen-kotlin-parser`).
-    crate_name: &'a str,
-    /// Crate identifier for `use` paths (`mehen_kotlin_parser`).
-    crate_ident: String,
-    /// Human-facing language name (`Kotlin`).
-    display_name: &'a str,
-    /// Workspace repository URL, used for the git-dependency snippet.
-    repo_url: &'a str,
-    /// Generated lexer module name (`kotlin_lexer`).
-    lexer_module: String,
-    /// Generated lexer type name (`KotlinLexer`).
-    lexer_type: String,
-    /// Generated parser module name (`kotlin_parser`).
-    parser_module: String,
-    /// Generated parser type name (`KotlinParser`).
-    parser_type: String,
-    /// Parser entry-rule method used in the example (`kotlin_file`).
-    entry_rule: &'a str,
-    /// One-line sample source parsed in the example (`fun main() {}`).
-    sample_source: &'a str,
-    /// Upstream grammar project name (`Kotlin/kotlin-spec`).
-    upstream_name: &'a str,
-    /// Upstream grammar project URL.
-    upstream_url: &'a str,
-    /// Pinned ANTLR Rust runtime + codegen version.
-    runtime_version: &'a str,
-    /// Hand-written lexer hooks (port of the upstream `LexerBase`),
-    /// when the grammar needs one. Switches the README examples to
-    /// `with_typed_hooks` lexer construction.
-    lexer_hooks: Option>,
-    /// Hand-written parser hooks (port of the upstream `ParserBase`),
-    /// when the grammar needs one. Switches the README examples to
-    /// `with_typed_hooks` parser construction.
-    parser_hooks: Option>,
-}
-
-/// A hooks type as the README template references it: `path` is the
-/// crate-relative module path for `use` lines (`hooks::JavaParserBase`),
-/// `type_name` the bare type for expression position (`JavaParserBase`).
-struct HooksReadme<'a> {
-    path: &'a str,
-    type_name: &'a str,
-}
-
-impl<'a> HooksReadme<'a> {
-    /// Split an `AntlrTarget` hooks path (`hooks::JavaParserBase`) into the
-    /// README's `use`-path and expression-position type name.
-    fn from_path(path: &'a str) -> Self {
-        let type_name = path.rsplit("::").next().expect("rsplit is non-empty");
-        Self { path, type_name }
-    }
-}
-
-/// One per-crate ANTLR target understood by `xtask antlr generate `.
-pub(crate) struct AntlrTarget {
-    /// CLI slug, e.g. `kotlin`.
-    pub slug: &'static str,
-    /// Owning crate directory, relative to the workspace root.
-    pub crate_dir: &'static str,
-    /// Vendored grammar directory (holds the `.g4` files), relative to the
-    /// workspace root. The lexer's `import`ed files (e.g. `UnicodeClasses`)
-    /// must live here too so the generator can resolve them relative to the
-    /// root grammar.
-    pub grammar_dir: &'static str,
-    /// Lexer grammar filename within `grammar_dir`.
-    pub lexer_g4: &'static str,
-    /// Parser grammar filename within `grammar_dir`.
-    pub parser_g4: &'static str,
-    /// Human-facing language name for the crate README (e.g. `Kotlin`).
-    pub display_name: &'static str,
-    /// Upstream grammar project name, as shown in the README (e.g.
-    /// `Kotlin/kotlin-spec`).
-    pub upstream_name: &'static str,
-    /// Upstream grammar project URL.
-    pub upstream_url: &'static str,
-    /// Parser entry-rule method used in the README usage example, in the
-    /// generated snake_case form (e.g. `kotlin_file`). Must be a real entry
-    /// rule on the generated `Parser` — it is compile-tested by the
-    /// mirrored `//!` doc example in the crate's `lib.rs`.
-    pub entry_rule: &'static str,
-    /// A minimal valid source snippet for the README usage example (e.g.
-    /// `fun main() {}`). Kept to one line — the template appends the newline.
-    pub sample_source: &'static str,
-    /// Semantic-pattern file within `grammar_dir` (passed as
-    /// `--sem-patterns`), lowering the grammar's named base-class helpers
-    /// (`this.Foo()` predicates/actions) to exact SemIR expressions or typed
-    /// hooks. `None` for grammars with no helper calls. Generation always
-    /// runs `--sem-unknown error --require-full-semantics`, so a helper the
-    /// pattern file misses fails codegen instead of silently assuming true.
-    pub sem_patterns: Option<&'static str>,
-    /// Grammar options implemented by caller-supplied hooks (passed as
-    /// `--option-hook KEY=VALUE`), e.g. `superClass=JavaParserBase` when the
-    /// parser crate ships a hand-written port of that base class. Options not
-    /// acknowledged here fail generation under `--require-full-semantics`.
-    pub option_hooks: &'static [&'static str],
-    /// Path (within the parser crate) of the hand-written hooks type the
-    /// lexer construction must install — the Rust port of the upstream
-    /// `LexerBase` (e.g. `hooks::CSharpLexerBase`). `None` when the
-    /// lexer needs no hooks. Referenced by the generated README so the usage
-    /// example is semantically exact.
-    pub lexer_hooks: Option<&'static str>,
-    /// Path (within the parser crate) of the hand-written hooks type the
-    /// parser construction must install — the Rust port of the upstream
-    /// `ParserBase` (e.g. `hooks::JavaParserBase`). `None` when every
-    /// parser helper lowers to a pure pattern (or there are none).
-    pub parser_hooks: Option<&'static str>,
-    /// Grammar-preparation script within `grammar_dir`, run before the
-    /// generator to derive [`Self::lexer_g4`] / [`Self::parser_g4`] (and any
-    /// `sem_patterns`) from a vendored upstream grammar that is not directly
-    /// generatable.
-    ///
-    /// `None` for grammars vendored in usable form (Kotlin, Java). C# vendors
-    /// Roslyn's `CSharp.Generated.g4`, a machine-generated *reference* grammar
-    /// that ANTLR rejects as-is, so its derived pair is a build artifact rather
-    /// than a checked-in source. The script is invoked as
-    ///
-    /// ```text
-    /// uv run --script